[Slim-Checkins] r11445 - in /trunk/server/Slim: Player/Playlist.pm Plugin/RandomPlay/Plugin.pm

adrian at svn.slimdevices.com adrian at svn.slimdevices.com
Thu Feb 15 09:45:08 PST 2007


Author: adrian
Date: Thu Feb 15 09:45:08 2007
New Revision: 11445

URL: http://svn.slimdevices.com?rev=11445&view=rev
Log:
Bug: 4724 (related)
Description: ensure random play adds each group of tracks in a random
order.  Reduce cpu hit by caching list of ids and useing for next call.

Modified:
    trunk/server/Slim/Player/Playlist.pm
    trunk/server/Slim/Plugin/RandomPlay/Plugin.pm

Modified: trunk/server/Slim/Player/Playlist.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Player/Playlist.pm?rev=11445&r1=11444&r2=11445&view=diff
==============================================================================
--- trunk/server/Slim/Player/Playlist.pm (original)
+++ trunk/server/Slim/Player/Playlist.pm Thu Feb 15 09:45:08 2007
@@ -730,7 +730,8 @@
 
 	$log->info("Checking if persistPlaylists is set..");
 
-	if (!$client || !Slim::Utils::Prefs::get('persistPlaylists')) {
+	if (!$client || !Slim::Utils::Prefs::get('persistPlaylists') ||
+		exists &Slim::Plugin::RandomPlay::Plugin::active && Slim::Plugin::RandomPlay::Plugin::active($client) ) {
 
 		return;
 	}

Modified: trunk/server/Slim/Plugin/RandomPlay/Plugin.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/RandomPlay/Plugin.pm?rev=11445&r1=11444&r2=11445&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/RandomPlay/Plugin.pm (original)
+++ trunk/server/Slim/Plugin/RandomPlay/Plugin.pm Thu Feb 15 09:45:08 2007
@@ -89,71 +89,95 @@
 
 # Find tracks matching parameters and add them to the playlist
 sub findAndAdd {
-	my ($client, $type, $find, $limit, $addOnly) = @_;
+	my ($client, $type, $find, $limit, $idList, $addOnly) = @_;
 
 	$log->info(sprintf("Starting random selection of %s items for type: $type", defined($limit) ? $limit : 'unlimited'));
 
-	my @joins  = ();
-
-	# Pull in the right tables to do our searches
-	if ($type eq 'track' || $type eq 'year') {
-
-		if ($find->{'genreTracks.genre'}) {
-
-			push @joins, 'genreTracks';
-		}
-
-	} elsif ($type eq 'album') {
-
-		if ($find->{'genreTracks.genre'}) {
-
-			push @joins, { 'tracks' => 'genreTracks' };
+	my @results;
+
+	if ($limit && scalar @$idList) {
+
+		# use previous id list as same find criteria as last call, select a random set of them
+		my @randomIds;
+
+		for (my $i = 0; $i < $limit && scalar @$idList; ++$i) {
+
+			push @randomIds, (splice @$idList, rand @$idList, 1);
+		}
+
+		# Turn ids into tracks, note this will reorder ids so needs use of RAND() in SQL statement to maintain randomness
+		@results = Slim::Schema->rs($type)->search({ 'id' => { 'in' => \@randomIds } }, { 'order_by' => \'RAND()' })->all;
+
+	} else {
+
+		# Search the database for all items of $type which match find criteria
+
+		my @joins  = ();
+
+		# Pull in the right tables to do our searches
+		if ($type eq 'track' || $type eq 'year') {
+
+			if ($find->{'genreTracks.genre'}) {
+
+				push @joins, 'genreTracks';
+			}
+
+		} elsif ($type eq 'album') {
+
+			if ($find->{'genreTracks.genre'}) {
+
+				push @joins, { 'tracks' => 'genreTracks' };
+
+			} else {
+
+				push @joins, 'tracks';
+			}
+
+		} elsif ($type eq 'contributor') {
+
+			if ($find->{'genreTracks.genre'}) {
+
+				push @joins, { 'contributorTracks' => { 'track' => 'genreTracks' } };
+
+			} else {
+
+				push @joins, { 'contributorTracks' => 'track' };
+			}
+		}
+
+		my $rs = Slim::Schema->rs($type)->search($find, { 'join' => \@joins });
+
+		if ($limit) {
+
+			# Get ids for all results from find and store in @$idList so they can be used in repeat calls
+			@$idList = $rs->distinct->get_column('me.id')->all;
+
+			# Get a random selection for this call
+			my @randomIds;
+
+			for (my $i = 0; $i < $limit && scalar @$idList; ++$i) {
+
+				push @randomIds, (splice @$idList, rand @$idList, 1);
+			}
+
+			# Turn ids into tracks, note this will reorder ids so needs use of RAND() in SQL statement to maintain randomness
+			@results = Slim::Schema->rs($type)->search({ 'id' => { 'in' => \@randomIds } }, { 'order_by' => \'RAND()' })->all;
 
 		} else {
 
-			push @joins, 'tracks';
-		}
-
-	} elsif ($type eq 'contributor') {
-
-		if ($find->{'genreTracks.genre'}) {
-
-			push @joins, { 'contributorTracks' => { 'track' => 'genreTracks' } };
-
-		} else {
-
-			push @joins, { 'contributorTracks' => 'track' };
-		}
-	}
-
-	# Search the database for the number of track we need. 
-	# Restrict by the genre's we've selected.
-	my $rs     = Slim::Schema->rs($type)->search($find, { 'join' => \@joins });
-
-	my @idList;
-
-	if ($limit) {
-
-		# Get a fixed selection of random keys, make sure they don't duplicate.
-		my @allIds = $rs->distinct->get_column('me.id')->all;
-
-		for (my $i = 0; $i < $limit && @allIds; ++$i) {
-
-			push @idList, (splice @allIds, rand @allIds, 1);
-		}
-
-	} else {
-
-		@idList = $rs->distinct->get_column('me.id')->all;
-
-		Slim::Player::Playlist::fischer_yates_shuffle(\@idList);
-	}
-
-	$log->info(sprintf("Find returned %i items", scalar @idList));
+			# We want all results from the result set, but need to randomise them
+			my @all = $rs->all;
+
+			while (@all) {
+
+				push @results, (splice @all, rand @all, 1);
+			}
+		}
+	}
+
+	$log->info(sprintf("Find returned %i items", scalar @results));
 
 	# Pull the first track off to add / play it if needed.
-	my @results = Slim::Schema->rs($type)->search({ 'id' => { 'in' => \@idList } })->all;
-
 	my $obj = shift @results;
 
 	if (!$obj || !ref($obj)) {
@@ -278,11 +302,7 @@
 
 	$log->debug("Called with type $type");
 
-	if (!$mixInfo{$client->masterOrSelf->id} || !$mixInfo{$client->masterOrSelf->id}->{'type'}) {
-
-		# init hash for each new client
-		$mixInfo{$client->masterOrSelf->id}->{'type'} = '';
-	}
+	$mixInfo{$client->masterOrSelf->id}->{'type'} ||= '';
 	
 	$type ||= 'track';
 	$type = lc($type);
@@ -293,9 +313,11 @@
 	# If this is a new mix, store the start time
 	my $startTime = undef;
 
-	if ($continuousMode && $type && (!$mixInfo{$client->masterOrSelf->id}->{'type'} || $mixInfo{$client->masterOrSelf->id}->{'type'} ne $type)) {
-
-		$startTime = time();
+	if ($type ne $mixInfo{$client->masterOrSelf->id}->{'type'}) {
+
+		$mixInfo{$client->masterOrSelf->id}->{'idList'} = undef;
+
+		$startTime = time() if $continuousMode;
 	}
 
 	my $songIndex = Slim::Player::Source::streamingSongIndex($client);
@@ -407,6 +429,7 @@
 				    $type eq 'year' ? 'track' : $type,
 				    $find,
 				    $type eq 'year' ? undef : $numItems,
+					$mixInfo{$client->masterOrSelf->id}->{'idList'} ||= [],
 					# 2nd time round just add tracks to end
 					$i == 0 ? $addOnly : 1
 				);
@@ -466,6 +489,8 @@
 			$continuousMode ? 'continuous' : 'static', $type, Slim::Player::Playlist::count($client)
 		));
 
+		$mixInfo{$client->masterOrSelf->id}->{'type'} = $type;
+
 		# $startTime will only be defined if this is a new (or restarted) mix
 		if (defined $startTime) {
 
@@ -473,7 +498,6 @@
 			# Do this last to prevent menu items changing too soon
 			$log->info("New mix started at $startTime");
 
-			$mixInfo{$client->masterOrSelf->id}->{'type'} = $type;
 			$mixInfo{$client->masterOrSelf->id}->{'startTime'} = $startTime;
 		}
 	}
@@ -920,6 +944,12 @@
 	}
 }
 
+sub active {
+	my $client = shift;
+
+	return $mixInfo{$client->masterOrSelf->id} ? 1 : 0;
+}
+
 1;
 
 __END__



More information about the checkins mailing list