Index: Networking/SqueezeNetwork/Players.pm =================================================================== --- Networking/SqueezeNetwork/Players.pm (revision 32441) +++ Networking/SqueezeNetwork/Players.pm (working copy) @@ -121,6 +121,15 @@ # Make a list of all apps for the web UI my $allApps = {}; + # Add 3rd party plugins which have requested to be on the apps menu + if (my $nonSNApps = Slim::Plugin::Base->nonSNApps) { + for my $plugin (@$nonSNApps) { + if ($plugin->can('tag')) { + $allApps->{ $plugin->tag } = { plugin => $plugin }; + } + } + } + # SN can provide string translations for new menu items if ( $res->{strings} ) { main::DEBUGLOG && $log->is_debug && $log->debug( 'Adding SN-supplied strings: ' . Data::Dump::dump( $res->{strings} ) ); @@ -382,4 +391,4 @@ $request->setStatusDone(); } -1; \ No newline at end of file +1; Index: Player/Client.pm =================================================================== --- Player/Client.pm (revision 32441) +++ Player/Client.pm (working copy) @@ -1459,7 +1459,17 @@ sub apps { my $client = shift; - return $prefs->client($client)->get('apps') || {}; + my %clientApps = %{$prefs->client($client)->get('apps') || {}}; + + if (my $nonSNApps = Slim::Plugin::Base->nonSNApps) { + for my $plugin (@$nonSNApps) { + if ($plugin->can('tag')) { + $clientApps{ $plugin->tag } = { plugin => $plugin }; + } + } + } + + return \%clientApps; } sub isAppEnabled { Index: Plugin/Base.pm =================================================================== --- Plugin/Base.pm (revision 32441) +++ Plugin/Base.pm (working copy) @@ -15,6 +15,8 @@ my $WEIGHTS = {}; +my $nonSNApps; + sub initPlugin { my $class = shift; my $args = shift; @@ -74,6 +76,12 @@ if ($class->_pluginDataFor('icon')) { Slim::Web::Pages->addPageLinks("icons", { $name => $class->_pluginDataFor('icon') }); } + + # add 3rd party plugins which wish to be in the apps menu to nonSNApps list + if ($class->can('menu') && $class->menu eq 'apps' && $class =~ /^Plugins::/) { + $nonSNApps ||= []; + push @$nonSNApps, $class; + } } if ($class->can('defaultMap') && !main::SCANNER) { @@ -132,6 +140,10 @@ sub getWeights { $WEIGHTS } +sub nonSNApps { + return main::SLIM_SERVICE && $nonSNApps +} + 1; __END__ Index: Plugin/MyApps/Plugin.pm =================================================================== --- Plugin/MyApps/Plugin.pm (revision 32441) +++ Plugin/MyApps/Plugin.pm (working copy) @@ -9,13 +9,57 @@ my $class = shift; $class->SUPER::initPlugin( - feed => Slim::Networking::SqueezeNetwork->url( '/api/myapps/v1/opml' ), tag => 'myapps', node => 'home', weight => 80, ); } +# return SN based feed, or fetch it and add on nonSN apps +sub feed { + my $client = shift; + + my $feedUrl = Slim::Networking::SqueezeNetwork->url('/api/myapps/v1/opml'); + + if (my $nonSNApps = Slim::Plugin::Base->nonSNApps) { + + return sub { + my ($client, $callback, $args) = @_; + + Slim::Formats::XML->getFeedAsync( + + sub { + my $feed = shift; + + for my $app (@$nonSNApps) { + + push @{$feed->{'items'}}, { + name => Slim::Utils::Strings::getString($app->getDisplayName), + type => 'redirect', + player => { + mode => $app, + modeParams => {}, + }, + }; + } + + $callback->($feed); + }, + + sub { + $callback->(); + }, + + { client => $client, url => $feedUrl, timeout => 35 }, + ); + } + + } else { + + return $feedUrl; + } +} + # Don't add this item to any menu sub playerMenu { }