Repository navigation
Providing playlists from other plugins
This page explains how any other LMS plugin can supply its own dynamic playlists to Dynamic Playlists (DPL), so that they show up in the DPL menu and can be started and queued exactly like DPL's own built-in and custom playlists.
DPL does not require your plugin to "register" itself anywhere. Instead, every time DPL needs to (re)build its list of available dynamic playlists, it iterates over all currently enabled LMS plugins and checks, for each one, whether its Plugin.pm package implements both of the following subroutines:
getDynamicPlaylistsgetNextDynamicPlaylistTracks
If (and only if) both subs exist, DPL calls getDynamicPlaylists to obtain the playlist definitions and treats your plugin as a dynamic-playlist provider. So, to hook into DPL, you only need to implement these two subs at package level in your plugin's Plugin.pm - no explicit registration call, no dependency declaration, nothing else is required.
Your plugin does not need to use or depend on the DPL plugin at all — you can implement these two subs unconditionally. If the user does not have DPL installed or enabled, nothing goes wrong: DPL's plugin-scanning code simply never runs, your subs are never called, and no error or warning occurs. Your dynamic-playlist feature just won't appear anywhere, until (and unless) the user installs and enables DPL.
Called by DPL whenever it (re)builds its menu of available dynamic playlists (e.g. when the DPL menu is opened, or a client's power/sync state changes).
sub getDynamicPlaylists {
my ($client) = @_;
return \%myDynamicPlaylists;
}This sub takes a single argument, $client: the currently active Squeezebox client, or undef if no client context is available (e.g. web UI without a selected player).
A hashref, keyed by a unique, plugin-specific playlist ID (a plain string, e.g. 'dynamicmixartist'). Each value is itself a hashref describing one dynamic playlist. Prefix your IDs with something unique to your plugin to avoid collisions with other plugins' playlist IDs.
| Key | Type | Description |
|---|---|---|
id |
string | Must be identical to the hash key used above. |
name |
string | Display name shown in the DPL menu. Should normally come from string(...) so it is localized. |
| Key | Type | Description |
|---|---|---|
url |
string | Relative URL of a settings/info page for this playlist (used by the web UI, e.g. 'plugins/MyPlugin/settings/basic.html?'). |
groups |
arrayref of arrayrefs | Defines where the playlist appears in the DPL menu tree, e.g. [['My Plugin'], ['Songs']]. If omitted, DPL falls back to playlistcategory, or lists the playlist as "Not classified". |
playlistcategory |
string | Flat category name used for sorting/grouping when groups is not used. |
menulisttype |
string | Set to 'contextmenu' if this playlist should only be offered as a context-menu action on a track/album/artist/genre (see parameters below) rather than as a normal top-level menu entry. |
minlmsversion |
string | Minimum required LMS server version (e.g. '8.4.0'). DPL hides the playlist if the running server is older. |
parameters |
hashref | See "The parameters key" below. Omit entirely if the playlist needs no user input. |
If your dynamic playlist needs user input before it can produce tracks (e.g. "pick an artist first"), describe it via the parameters key. This is a hashref keyed by parameter position (1, 2, ...); each value is a hashref with:
| Key | Description |
|---|---|
id |
Same as the hash key (the parameter's position, 1, 2, ...). |
type |
Parameter type. Common built-in types: artist, album, genre, track, year, playlist, list (custom value list), multiplegenres, multipledecades, multipleyears. |
name |
Label shown to the user when asking for this parameter. |
| definition | Only for type => 'list': a hashref mapping each selectable value to its display label, e.g. { 'value1' => 'Label 1', 'value2' => 'Label 2' }. |
When menulisttype => 'contextmenu' is combined with a single artist/album/genre/track parameter, DPL automatically offers your playlist as a context-menu entry on matching items (artist/album/genre/track screens), and pre-fills that parameter's value with the item the user was browsing.
Called by DPL whenever it needs a (further) batch of tracks for one of your playlists.
sub getNextDynamicPlaylistTracks {
my ($client, $dynamicplaylist, $limit, $offset, $parameters) = @_;
my @trackIDs = ();
my %tracksCompleteInfo = ();
# ... build @trackIDs here ...
return \@trackIDs, \%tracksCompleteInfo;
}| Name | Description |
|---|---|
$client |
The (master, in case of sync groups) client this playlist is being played on. |
$dynamicplaylist |
The same hashref your plugin returned from getDynamicPlaylists for this playlist ID, with dynamicplaylistid and dynamicplaylistplugin added by DPL. Use $dynamicplaylist->{'id'} (or {'dynamicplaylistid'}) to tell which of your playlists is being requested if you registered more than one. |
$limit |
Number of tracks DPL would like returned in this batch. |
$offset |
0 on the very first call for a freshly-started playlist; incremented by DPL on subsequent calls (used, for instance, if you need to page through a result set). Many plugins can ignore this and just return one/a few tracks per call, reacting only to whether $offset is 0 (first call, pick a fresh seed) or non-zero (continue from previous seed/state). |
$parameters |
Hashref keyed by parameter position (matching the parameters you declared in getDynamicPlaylists), containing only the parameters the user actually set. Each entry is { 'id' => ..., 'value' => ... }. |
A two-element list ($trackIDs, $tracksCompleteInfo):
-
$trackIDs- an arrayref of numeric track IDs (seeSlim::Schema::Track->id), in the order they should be added to the playlist. Return an empty arrayref if no tracks could be found for this call (DPL will retry a limited number of times). Instead of an arrayref, you may return the plain scalar string'error'to tell DPL that the playlist definition itself is broken (DPL logs an error and stops requesting further tracks for this playlist for the current session). -
$tracksCompleteInfo- a hashref, keyed by the same track IDs, for optional extra per-track metadata DPL cannot derive by itself from the track ID alone. In practice this is mainly used to supplyprimary_artist(the contributor ID), which DPL uses for balanced/varied-artist shuffling. Return an empty hashref ({}) if you have nothing to add here.
The following is a simplified, self-contained pattern/example:
sub getDynamicPlaylists {
my ($client) = @_;
my %myDynamicPlaylists = (
'myplugin_byartist' => {
'id' => 'myplugin_byartist',
'name' => string('PLUGIN_MYPLUGIN_TRACKS_BASED_ON_SELECTED_ARTISTS'),
'menulisttype' => 'contextmenu',
'playlistcategory' => 'artists',
'parameters' => {
1 => {
'id' => 1,
'type' => 'artist',
'name' => 'Choose artist',
},
},
},
);
return \%myDynamicPlaylists;
}
sub getNextDynamicPlaylistTracks {
my ($client, $dynamicplaylist, $limit, $offset, $parameters) = @_;
my $dynamicplaylistId = $dynamicplaylist->{'id'};
my @trackIDs = ();
my %tracksCompleteInfo = ();
if (!$offset && $dynamicplaylistId eq 'myplugin_byartist') {
my $seedContributorId = $parameters->{1}->{'value'};
my $seedArtist = Slim::Schema->find('Contributor', $seedContributorId);
# ... use $seedArtist to get a track via your own logic ...
my $nextTrack = pickRelatedTrack($seedArtist);
if ($nextTrack) {
my $id = $nextTrack->id;
push @trackIDs, $id;
$tracksCompleteInfo{$id}{'primary_artist'} = $nextTrack->primary_artist if $nextTrack->primary_artist;
}
}
return \@trackIDs, \%tracksCompleteInfo;
}- Your plugin is enabled and implements
getDynamicPlaylistsandgetNextDynamicPlaylistTracksat package level. - Every playlist ID you return is unique and prefixed with something specific to your plugin.
-
getDynamicPlaylistsreturns a hashref of hashrefs with at leastidandname. -
getNextDynamicPlaylistTracksreturns(\@trackIDs, \%tracksCompleteInfo), where@trackIDsholds numericSlim::Schema::TrackIDs (or the scalar'error'on failure). - Any user-selectable input is declared via
parametersingetDynamicPlaylistsand read back via$parametersingetNextDynamicPlaylistTracks.