[Slim-Checkins] r10963 - in /trunk/server/Slim/Player: Client.pm Source.pm Squeezebox.pm

andy at svn.slimdevices.com andy at svn.slimdevices.com
Thu Dec 14 12:11:00 PST 2006


Author: andy
Date: Thu Dec 14 12:11:00 2006
New Revision: 10963

URL: http://svn.slimdevices.com?rev=10963&view=rev
Log:
Rebuffering code take 2... this uses a new event STMo which will be part of the next firmware

Modified:
    trunk/server/Slim/Player/Client.pm
    trunk/server/Slim/Player/Source.pm
    trunk/server/Slim/Player/Squeezebox.pm

Modified: trunk/server/Slim/Player/Client.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Player/Client.pm?rev=10963&r1=10962&r2=10963&view=diff
==============================================================================
--- trunk/server/Slim/Player/Client.pm (original)
+++ trunk/server/Slim/Player/Client.pm Thu Dec 14 12:11:00 2006
@@ -176,6 +176,7 @@
 	$client->[111] = {}; # pipe sockets used for parent/child communication
 	$client->[112] = 0; # knobSync
 	$client->[113] = {}; # pendingPrefChanges
+	$client->[114] = 0; # bufferStarted, tracks when players begin buffering/rebuffering
 
 	$clientHash{$id} = $client;
 
@@ -1704,4 +1705,9 @@
 	@_ ? ($r->[113] = shift) : $r->[113];
 }
 
+sub bufferStarted {
+	my $r = shift;
+	@_ ? ($r->[114] = shift) : $r->[114];
+}
+
 1;

Modified: trunk/server/Slim/Player/Source.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Player/Source.pm?rev=10963&r1=10962&r2=10963&view=diff
==============================================================================
--- trunk/server/Slim/Player/Source.pm (original)
+++ trunk/server/Slim/Player/Source.pm Thu Dec 14 12:11:00 2006
@@ -51,6 +51,7 @@
 	Slim::Networking::Slimproto::setEventCallback('STMd', \&decoderUnderrun);
 	Slim::Networking::Slimproto::setEventCallback('STMs', \&trackStartEvent);
 	Slim::Networking::Slimproto::setEventCallback('STMn', \&notSupported);
+	Slim::Networking::Slimproto::setEventCallback('STMo', \&outputUnderrun);
 }
 
 # rate can be negative for rew, zero for pause, 1 for playback and greater than one for ffwd
@@ -634,6 +635,96 @@
 	logError("Decoder does not support file format, skipping track");
 	
 	errorOpening($client);
+}
+
+sub outputUnderrun {
+	my $client = shift;
+	
+	# STMo is called when the output buffer underruns but the decoder connection is still active.
+	# It signals that we need to pause and rebuffer the live audio stream.
+
+	return unless $client->playmode() =~ /play/;
+	
+	if ( $log->is_debug ) {
+		my $decoder = $client->bufferFullness();
+		my $output  = $client->outputBufferFullness();
+		$log->debug( "Output buffer underrun (decoder: $decoder / output: $output)" );
+	}
+	
+	playmode( $client, 'pause' );
+	
+	my ( $line1, $line2 ); 	 
+
+	my $string = 'REBUFFERING'; 	 
+	$line1 = $client->string('NOW_PLAYING') . ' (' . $client->string($string) . ' 0%)'; 	 
+	if ( $client->linesPerScreen() == 1 ) { 	 
+		$line2 = $client->string($string) . ' 0%'; 	 
+	} 	 
+	else { 	 
+		my $url = Slim::Player::Playlist::url($client); 	 
+		$line2  = Slim::Music::Info::title($url);
+	}
+	
+	$client->showBriefly( $line1, $line2, 2 ) unless $client->display->sbName();
+	
+	# Setup a timer to check the buffer and unpause
+	$client->bufferStarted( Time::HiRes::time() ); # track when we started rebuffering
+	Slim::Utils::Timers::setTimer( $client, Time::HiRes::time() + 1, \&rebuffer );
+}
+
+sub rebuffer {
+	my $client = shift;
+	
+	# If the user changes something, stop rebuffering
+	return unless $client->playmode() eq 'pause';
+	
+	$client->requestStatus();
+	
+	my $threshold = 80 * 1024; # 5 seconds of 128k
+	
+	my $url = Slim::Player::Playlist::url($client);
+	if ( my $bitrate = Slim::Music::Info::getBitrate($url) ) {
+		$threshold = 5 * ( int($bitrate / 8) );
+	}
+	
+	# We restart playback based on the decode buffer, 
+	# as the output buffer is not updated in pause mode.
+	my $fullness = $client->bufferFullness();
+	
+	$log->debug( "Rebuffering: $fullness / $threshold" );
+	
+	if ( $fullness >= $threshold ) {
+		playmode( $client, 'play' );
+		
+		$client->update();
+	}
+	else {
+		
+		# Only show rebuffering status if no user activity on player or we're on the Now Playing screen
+		my $nowPlaying = Slim::Buttons::Playlist::showingNowPlaying($client);
+		my $lastIR     = Slim::Hardware::IR::lastIRTime($client) || 0;
+
+		if ( $nowPlaying || $lastIR < $client->bufferStarted() ) {
+			my ( $line1, $line2 );
+		
+			# Bug 1827, display better buffering feedback while we wait for data
+			my $percent = sprintf "%d%%", ( $fullness / $threshold ) * 100;
+
+			my $string = 'REBUFFERING';
+			$line1 = $client->string('NOW_PLAYING') . ' (' . $client->string($string) . " $percent)"; 	 
+			if ( $client->linesPerScreen() == 1 ) { 	 
+				$line2 = $client->string($string) . " $percent"; 	 
+			} 	 
+			else { 	 
+				my $url = Slim::Player::Playlist::url($client); 	 
+				$line2  = Slim::Music::Info::title($url);
+			}
+		
+			$client->showBriefly( $line1, $line2, 2 ) unless $client->display->sbName();
+		}
+		
+		Slim::Utils::Timers::setTimer( $client, Time::HiRes::time() + 1, \&rebuffer );
+	}
 }
 
 sub skipahead {

Modified: trunk/server/Slim/Player/Squeezebox.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Player/Squeezebox.pm?rev=10963&r1=10962&r2=10963&view=diff
==============================================================================
--- trunk/server/Slim/Player/Squeezebox.pm (original)
+++ trunk/server/Slim/Player/Squeezebox.pm Thu Dec 14 12:11:00 2006
@@ -27,9 +27,6 @@
 use Slim::Utils::Misc;
 use Slim::Utils::Network;
 
-# Track when clients begin to buffer streams
-our $buffering = {};
-
 # We inherit new() completely from our parent class.
 
 sub init {
@@ -161,7 +158,7 @@
 		}
 		
 		# Set a timer for feedback during buffering
-		$buffering->{$client} = Time::HiRes::time(); # track when we started buffering
+		$client->bufferStarted( Time::HiRes::time() ); # track when we started buffering
 		Slim::Utils::Timers::killTimers( $client, \&buffering );
 		Slim::Utils::Timers::setTimer(
 			$client,
@@ -186,8 +183,6 @@
 #
 sub resume {
 	my $client = shift;
-
-	delete $buffering->{$client};
 	
 	Slim::Utils::Timers::killTimers($client, \&buffering);
 
@@ -202,8 +197,6 @@
 sub pause {
 	my $client = shift;
 
-	delete $buffering->{$client};
-
 	Slim::Utils::Timers::killTimers($client, \&buffering);
 
 	$client->stream('p');
@@ -213,8 +206,6 @@
 
 sub stop {
 	my $client = shift;
-	
-	delete $buffering->{$client};
 
 	Slim::Utils::Timers::killTimers($client, \&buffering);
 
@@ -227,8 +218,6 @@
 
 sub flush {
 	my $client = shift;
-	
-	delete $buffering->{$client};
 
 	Slim::Utils::Timers::killTimers($client, \&buffering);
 
@@ -244,8 +233,7 @@
 	
 	# If the track has started, stop displaying buffering status
 	# currentPlaylistChangeTime is set to time() after a track start event
-	if ( $client->currentPlaylistChangeTime() > $buffering->{$client} ) {
-		delete $buffering->{$client};
+	if ( $client->currentPlaylistChangeTime() > $client->bufferStarted() ) {
 		$client->update();
 		return;
 	}
@@ -306,7 +294,7 @@
 	my $nowPlaying = Slim::Buttons::Playlist::showingNowPlaying($client);
 	my $lastIR     = Slim::Hardware::IR::lastIRTime($client) || 0;
 	
-	if ( $nowPlaying || $lastIR < $buffering->{$client} ) {
+	if ( $nowPlaying || $lastIR < $client->bufferStarted() ) {
 		$client->showBriefly( $line1, $line2, 0.5 ) unless $client->display->sbName();
 		
 		# Call again unless we've reached the threshold



More information about the checkins mailing list