diff --git a/Slim/Player/Protocols/HTTP.pm b/Slim/Player/Protocols/HTTP.pm index 0218635ccde..0648ca8c0ee 100644 --- a/Slim/Player/Protocols/HTTP.pm +++ b/Slim/Player/Protocols/HTTP.pm @@ -1105,7 +1105,8 @@ sub getMetadataFor { } } else { - my $handler = $song ? $song->currentHandler : Slim::Player::ProtocolHandlers->handlerForURL($url); + # make sure that protocol handler is what the $song wanted, not just the $url-based one + my $handler = $song ? $song->currentTrackHandler : Slim::Player::ProtocolHandlers->handlerForURL($url); if ( $handler && $handler !~ /^(?:$class|Slim::Player::Protocols::MMS|Slim::Player::Protocols::HTTPS?)$/ && $handler->can('getMetadataFor') ) { return $handler->getMetadataFor( $client, $url ); } diff --git a/Slim/Player/SongStreamController.pm b/Slim/Player/SongStreamController.pm index 2835a963109..d71503ea730 100644 --- a/Slim/Player/SongStreamController.pm +++ b/Slim/Player/SongStreamController.pm @@ -1,6 +1,5 @@ package Slim::Player::SongStreamController; - # Logitech Media Server Copyright 2001-2020 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, @@ -9,22 +8,30 @@ package Slim::Player::SongStreamController; use bytes; use strict; +use base qw(Slim::Utils::Accessor); + use Slim::Utils::Log; my $log = logger('player.source'); my $_liveCount = 0; +{ + __PACKAGE__->mk_accessor('ro', qw(song streamHandler urlHandler)); + __PACKAGE__->mk_accessor('rw', qw(playerProxyStreaming)); +} + sub new { my ($class, $song, $streamHandler) = @_; + + my $self = $class->SUPER::new; - my $self = { + $self->init_accessor( song => $song, streamHandler => $streamHandler, - }; + urlHandler => Slim::Player::ProtocolHandlers->handlerForURL($song->streamUrl()), + ); - bless $self, $class; - $_liveCount++; if (main::DEBUGLOG && $log->is_debug) { $log->debug("live=$_liveCount"); @@ -44,39 +51,32 @@ sub DESTROY { } } -sub song {return shift->{'song'};} -sub streamHandler {return shift->{'streamHandler'};} -sub protocolHandler {return shift->song()->currentTrackHandler();} - sub close { my $self = shift; - my $fd = $self->{'streamHandler'}; + my $fd = $self->streamHandler; if (defined $fd) { Slim::Networking::Select::removeError($fd); Slim::Networking::Select::removeRead($fd); $fd->close; - delete $self->{'streamHandler'}; } } +sub songHandler { + return shift->song->currentTrackHandler(); +} + sub isDirect { - return shift->{'song'}->directstream() || 0; + return shift->song->directstream() || 0; } sub streamUrl { - return shift->{'song'}->streamUrl(); + return shift->song->streamUrl(); } sub track { - return shift->{'song'}->currentTrack(); -} - -sub playerProxyStreaming { - my $self = shift; - $self->{'playerProxyStreaming'} = shift if @_; - return $self->{'playerProxyStreaming'}; + return shift->song->currentTrack(); } 1; diff --git a/Slim/Player/Squeezebox.pm b/Slim/Player/Squeezebox.pm index 60b0b7449fd..2c3acf5abba 100644 --- a/Slim/Player/Squeezebox.pm +++ b/Slim/Player/Squeezebox.pm @@ -136,7 +136,7 @@ sub play { my $params = shift; my $controller = $params->{'controller'}; - my $handler = $controller->protocolHandler(); + my $handler = $controller->songHandler(); # Calculate the correct buffer threshold for remote URLs if ( $handler->isRemote() ) { @@ -534,7 +534,8 @@ sub stream_s { my $controller = $params->{'controller'}; my $url = $controller->streamUrl(); my $track = $controller->track(); - my $handler = $controller->protocolHandler(); + my $handler = $controller->urlHandler(); + my $songHandler = $controller->songHandler(); my $isDirect = $controller->isDirect(); my $master = $client->master(); @@ -562,9 +563,8 @@ sub stream_s { # use getFormatForURL only if the format is not already given # This method is bad because it only looks at the URL suffix and can cause # (for example) Ogg HTTP streams to be played using the mp3 decoder! - if ( !$format && $handler->can("getFormatForURL") ) { - $format = $handler->getFormatForURL($url); - } + my $methodHandler = $songHandler->can('getFormatForURL') ? $songHandler : $handler; + $format = $methodHandler->getFormatForURL($url) if !$format && $methodHandler; } if ( !$format ) { @@ -750,8 +750,8 @@ sub stream_s { $outputThreshold = 1; # Handler may override pcmsamplesize (Rhapsody) - if ( $handler && $handler->can('pcmsamplesize') ) { - $pcmsamplesize = $handler->pcmsamplesize( $client, $params ); + if ( $songHandler && $songHandler->can('pcmsamplesize') ) { + $pcmsamplesize = $songHandler->pcmsamplesize( $client, $params ); } # XXX: The use of mp3 as default has been known to cause the mp3 decoder to be used for @@ -772,7 +772,8 @@ sub stream_s { main::INFOLOG && logger('player.streaming.direct')->info("SqueezePlay direct stream: $url"); - $request_string = $handler->requestString($client, $url, undef, $params->{'seekdata'}); + my $methodHandler = $songHandler->can('requestString') ? $songHandler : $handler; + $request_string = $methodHandler->getRequestString($client, $url, undef, $params->{'seekdata'}); $autostart += 2; # will be 2 for direct streaming with no autostart, or 3 for direct with autostart } elsif (my $proxy = $params->{'proxyStream'}) { @@ -815,7 +816,9 @@ sub stream_s { } $server_port = $port; - $request_string = $handler->requestString($client, $url, undef, $params->{'seekdata'}); + # prioritize song's protocol handler at even in direct mode it might change requestString + my $methodHandler = $songHandler->can('requestString') ? $songHandler : $handler; + $request_string = $methodHandler->requestString($client, $url, undef, $params->{'seekdata'}); $autostart += 2; # will be 2 for direct streaming with no autostart, or 3 for direct with autostart if (!$server_port || !$server_ip) { @@ -934,10 +937,10 @@ sub stream_s { } # Bug 10567, allow plugins to override transition setting - if ( $handler && $handler->can('transitionType') ) { - my $override = $handler->transitionType( $master, $controller->song(), $transitionType ); + if ( $songHandler && $songHandler->can('transitionType') ) { + my $override = $songHandler->transitionType( $master, $controller->song(), $transitionType ); if ( defined $override ) { - main::INFOLOG && $log->is_info && $log->info("$handler changed transition type to $override"); + main::INFOLOG && $log->is_info && $log->info("$songHandler changed transition type to $override"); $transitionType = $override; } } diff --git a/Slim/Player/Squeezebox2.pm b/Slim/Player/Squeezebox2.pm index df3a1b6c6f5..66ca8589f57 100644 --- a/Slim/Player/Squeezebox2.pm +++ b/Slim/Player/Squeezebox2.pm @@ -460,7 +460,7 @@ sub songElapsedSeconds { sub canDirectStream { my ($client, $url, $song) = @_; - # this is client's canDirectStream, not protocol handler's + # this is client's canDirectStream, not protocol handler's so there is a $song my $handler = $song->currentTrackHandler; return unless $handler; @@ -478,7 +478,7 @@ sub directHeaders { main::INFOLOG && $directlog->is_info && $directlog->info("Processing headers for direct streaming:\n$headers"); my $controller = $client->controller()->songStreamController(); - my $handler = $controller->protocolHandler() if $controller; + my $handler = $controller->urlHandler() if $controller; if ($handler && $handler->can('handlesStreamHeaders')) { @@ -491,6 +491,7 @@ sub directHeaders { return unless $controller && $controller->isDirect(); my $url = $controller->streamUrl(); + my $songHandler = $controller->songHandler(); # We involve the protocol handler in the header parsing process. # The current iteration of the firmware only knows about HTTP @@ -527,12 +528,12 @@ sub directHeaders { $directlog->warn("Invalid response code ($response) from remote stream $url"); - if ($handler && $handler->can("handleDirectError")) { + if ($songHandler && $songHandler->can("handleDirectError")) { # bug 10407 - make sure ready to stream again $client->readyToStream(1); - $handler->handleDirectError($client, $url, $response, $status_line); + $songHandler->handleDirectError($client, $url, $response, $status_line); } else { $client->failedDirectStream($status_line); @@ -552,12 +553,15 @@ sub directHeaders { $directlog->info("Processing " . scalar(@headers) . " headers"); } - if ($handler && $handler->can("parseDirectHeaders")) { - # Could use a hash ref for header parameters - main::INFOLOG && $directlog->info("Calling $handler ::parseDirectHeaders"); - ($title, $bitrate, $metaint, $redir, $contentType, $length, $body) = $handler->parseDirectHeaders($client, $url, @headers); - } - + # prioritize song's protocol handler over url handler + my $methodHandler = $songHandler && $songHandler->can('parseDirectHeaders') ? $songHandler : $handler; + + main::INFOLOG && $directlog->info("Calling $methodHandler :: parseDirectHeader"); + $directlog->error("Calling $methodHandler::parseDirectHeader"); + # Could use a hash ref for header parameters + ($title, $bitrate, $metaint, $redir, $contentType, $length, $body) = + $methodHandler->parseDirectHeaders($client, $methodHandler == $songHandler ? $controller->song()->currentTrack() : $url, @headers); + $controller->song()->isLive($length ? 0 : 1) if !$redir; # XXX maybe should (also) check $song->scanData()->{$url}->{metadata}->{info}->{broadcast} # for WMA streams here. @@ -709,7 +713,7 @@ sub directBodyFrame { my $controller = $client->controller()->songStreamController(); - unless ($controller && $controller->isDirect()) {return;} + return unless $controller && $controller->isDirect(); my $url = $controller->streamUrl(); my $handler = $controller->protocolHandler(); diff --git a/Slim/Plugin/xPL/Plugin.pm b/Slim/Plugin/xPL/Plugin.pm index 82fb45700f7..40d3538ff4c 100644 --- a/Slim/Plugin/xPL/Plugin.pm +++ b/Slim/Plugin/xPL/Plugin.pm @@ -348,7 +348,7 @@ sub sendXplHBeatMsg { $title = $track->title if $track->can('title'); my $remoteMeta = {}; my $url = $track->url; - my $handler = $client->playingSong->currentTrackHandler; + my $handler = $client->playingSong->currentTrackHandler || Slim::Player::ProtocolHandlers->handlerForURL($url); if ( $handler && $handler->can('getMetadataFor') ) { $remoteMeta = $handler->getMetadataFor($client, $url); # Override data from track object (this is same or better)