From 78176cb4b61e24e41a3fdb6e55909d9d21035f65 Mon Sep 17 00:00:00 2001 From: Michael Herger Date: Wed, 30 Jun 2021 17:57:00 +0200 Subject: [PATCH] Bring the "More" menu item to subscribed podcast feeds. This required a change in `Slim::Control::XMLBrowser`: if an item has a variable (eg. URL) pointing at a code ref, we must ignore it. These items can't be dealt with by Squeezeplay. In the Podcasts plugin this would eg. be the Search menu item. There's no "More" info menu for such items, which is ok. --- Slim/Control/XMLBrowser.pm | 8 +++- Slim/Formats/XML.pm | 14 +++++-- Slim/Plugin/Podcast/Plugin.pm | 76 ++++++++++++++++++++++------------- 3 files changed, 67 insertions(+), 31 deletions(-) diff --git a/Slim/Control/XMLBrowser.pm b/Slim/Control/XMLBrowser.pm index b7ac4b17d60..6d338a67013 100644 --- a/Slim/Control/XMLBrowser.pm +++ b/Slim/Control/XMLBrowser.pm @@ -1309,9 +1309,15 @@ sub _cliQuery_done { my %params; my @vars = @{$actionParamsNeeded{$key}}; for (my $i = 0; $i < scalar @vars; $i += 2) { + # ignore items whose URL points to a code ref - Squeezeplay can't handle them + if (ref $item->{$vars[$i+1]}) { + %params = (); + last; + } + $params{$vars[$i]} = $item->{$vars[$i+1]}; } - $hash{$key} = \%params; + $hash{$key} = \%params if keys %params; } } diff --git a/Slim/Formats/XML.pm b/Slim/Formats/XML.pm index 037cfee878b..000a44ae933 100644 --- a/Slim/Formats/XML.pm +++ b/Slim/Formats/XML.pm @@ -93,7 +93,7 @@ sub getFeedAsync { $handler->explodePlaylist($params->{client}, $url, sub { my ($tracks) = @_; - # explode playlist might return a full opml list + # explode playlist might return a full opml list return $cb->($tracks, $params) if ref $tracks eq 'HASH'; # if not, this is just an array of url @@ -147,8 +147,8 @@ sub getFeedAsync { if ( $url =~ IS_TUNEIN_RE ) { # Add the TuneIn username - if ( $url !~ /username/ && $url =~ /(?:presets|title)/ - && Slim::Utils::PluginManager->isEnabled('Slim::Plugin::InternetRadio::Plugin') + if ( $url !~ /username/ && $url =~ /(?:presets|title)/ + && Slim::Utils::PluginManager->isEnabled('Slim::Plugin::InternetRadio::Plugin') && ( my $username = Slim::Plugin::InternetRadio::TuneIn->getUsername($params->{client}) ) ) { $url .= '&username=' . uri_escape_utf8($username); @@ -439,6 +439,14 @@ sub parseRSS { $feed{'image'} = $href unless ref $href; } + if (my $language = $xml->{'channel'}->{'language'}) { + $feed{language} = unescapeAndTrim($language); + } + + if (my $author = $xml->{'channel'}->{'author'} || $xml->{'channel'}->{'itunes:author'}) { + $feed{author} = unescapeAndTrim($author); + } + # some feeds (slashdot) have items at same level as channel my $items; diff --git a/Slim/Plugin/Podcast/Plugin.pm b/Slim/Plugin/Podcast/Plugin.pm index a1f43db391c..c0393d046cf 100644 --- a/Slim/Plugin/Podcast/Plugin.pm +++ b/Slim/Plugin/Podcast/Plugin.pm @@ -177,38 +177,37 @@ sub handleFeed { name => $_->{name}, url => $url, favorites_url => $url, + favorites_type => 'link', parser => 'Slim::Plugin::Podcast::Parser', image => $image || __PACKAGE__->_pluginDataFor('icon'), playlist => $url, }; - unless ($image) { - # always cache image avoid sending a flood of requests - $cache->set('podcast-rss-' . $url, __PACKAGE__->_pluginDataFor('icon'), '1days'); - - Slim::Networking::SimpleAsyncHTTP->new( + unless ($image && $cache->get('podcast_moreInfo_' . $url)) { + Slim::Formats::XML->getFeedAsync( sub { - eval { - my $xml = XMLin(shift->content); - my $image = $xml->{channel}->{image}->{url} || $xml->{channel}->{'itunes:image'}->{href}; - $cache->set('podcast-rss-' . $url, $image, '90days') if $image; - }; - - $log->warn("can't parse $url RSS for feed icon: ", $@) if $@; + _precacheShowDetails($url, $_[0]); }, sub { - $log->warn("can't get $url RSS feed icon: ", shift->error); + $log->warn("can't get $url RSS feed information: ", $_[0]); }, { - cache => 1, - expires => 86400, - }, - )->get($_->{value}); + parser => 'Slim::Plugin::Podcast::Parser', + url => $_->{value}, + expires => 86400 + } + ); } } $cb->({ items => $items, + actions => { + info => { + command => ['podcastinfo', 'items'], + variables => [ 'url', 'url', 'name', 'name', 'image', 'image' ], + }, + } }); } @@ -284,16 +283,7 @@ sub searchHandler { $feed->{parser} ||= 'Slim::Plugin::Podcast::Parser'; push @$items, $feed; - # pre-cache some additional information to be shown in feed info menu - my %moreInfo; - - foreach (qw(language author description)) { - if (my $value = $feed->{$_}) { - $moreInfo{$_} = $value; - } - } - - $cache->set('podcast_moreInfo_' . $feed->{url}, \%moreInfo); + _precacheShowDetails($feed->{url}, $feed); } push @$items, { name => cstring($client, 'EMPTY') } if !scalar @$items; @@ -322,6 +312,29 @@ sub searchHandler { )->get($url, @$headers); } +sub _precacheShowDetails { + my ($url, $feed) = @_; + + if (my $image = $feed->{image}) { + $cache->set('podcast-rss-' . $url, $image, '90days'); + } + else { + # always cache image to avoid sending a flood of requests + $cache->set('podcast-rss-' . $url, __PACKAGE__->_pluginDataFor('icon'), '1days'); + } + + # pre-cache some additional information to be shown in feed info menu + my %moreInfo; + + foreach (qw(language author description)) { + if (my $value = $feed->{$_}) { + $moreInfo{$_} = $value; + } + } + + $cache->set('podcast_moreInfo_' . $url, \%moreInfo); +} + sub registerProvider { my ($class, $force) = @_; @@ -417,6 +430,15 @@ sub showInfo { $name = $client->pluginData('showName'); } + if (ref $url || $url !~ /^http/) { + return Slim::Control::XMLBrowser::cliQuery('podcastinfo', { + name => $name, + items => [{ + name => $name + }] + }, $request); + } + my $menuTitle = cstring($client, 'PLUGIN_PODCAST_SUBSCRIBE', Slim::Utils::Unicode::utf8decode($name)); my $menuAction = 'addshow';