From ddcae2d5f8feaa734adf8c4e57ef39d688f5c5e4 Mon Sep 17 00:00:00 2001 From: darrell-k Date: Wed, 10 Jul 2024 20:48:33 +0100 Subject: [PATCH 1/4] Additional Browse Modes - user defined roles --- Slim/Menu/AlbumInfo.pm | 1 - Slim/Menu/BrowseLibrary/Releases.pm | 3 +- .../settings/browsemodes.html | 19 ++++++++ Slim/Plugin/ExtendedBrowseModes/Settings.pm | 37 ++++++++++++++ Slim/Plugin/ExtendedBrowseModes/strings.txt | 22 +++++++++ Slim/Schema/Contributor.pm | 48 ++++++++++++++----- Slim/Utils/Prefs.pm | 8 ++++ 7 files changed, 123 insertions(+), 15 deletions(-) diff --git a/Slim/Menu/AlbumInfo.pm b/Slim/Menu/AlbumInfo.pm index a5c1246b37d..ac740232caf 100644 --- a/Slim/Menu/AlbumInfo.pm +++ b/Slim/Menu/AlbumInfo.pm @@ -273,7 +273,6 @@ sub infoContributors { $linkRoles{'TRACKARTIST'} = 1; $linkRoles{'ALBUMARTIST'} = 1; - # Loop through the contributor types and append for my $role (@roles) { for my $contributor ( $album->artistsForRoles($role) ) { diff --git a/Slim/Menu/BrowseLibrary/Releases.pm b/Slim/Menu/BrowseLibrary/Releases.pm index 5ce30d06233..73e2a0a9992 100644 --- a/Slim/Menu/BrowseLibrary/Releases.pm +++ b/Slim/Menu/BrowseLibrary/Releases.pm @@ -34,6 +34,7 @@ sub _releases { # library_id:-1 is supposed to clear/override the global library_id $_ && $_ !~ /(?:library_id\s*:\s*-1|remote_library)/ } @searchTags; + push @searchTags, "role_id:$menuRoles" if $menuRoles; my @artistIds = grep /artist_id:/, @searchTags; my $artistId; @@ -51,7 +52,7 @@ sub _releases { main::INFOLOG && $log->is_info && $log->info("$query ($index, $quantity): tags ->", join(', ', @searchTags)); # get the artist's albums list to create releases sub-items etc. - my $request = Slim::Control::Request->new( undef, [ $query, 0, MAX_ALBUMS, @searchTags ] ); + my $request = Slim::Control::Request->new( undef, [ $query, 0, MAX_ALBUMS, @searchTags, 'role_id:'. $menuRoles ? $menuRoles : join(',',Slim::Schema::Contributor->contributorRoles) ] ); $request->execute(); $log->error($request->getStatusText()) if $request->isStatusError(); diff --git a/Slim/Plugin/ExtendedBrowseModes/HTML/EN/plugins/ExtendedBrowseModes/settings/browsemodes.html b/Slim/Plugin/ExtendedBrowseModes/HTML/EN/plugins/ExtendedBrowseModes/settings/browsemodes.html index 72f225544b9..1bfeddc11e4 100644 --- a/Slim/Plugin/ExtendedBrowseModes/HTML/EN/plugins/ExtendedBrowseModes/settings/browsemodes.html +++ b/Slim/Plugin/ExtendedBrowseModes/HTML/EN/plugins/ExtendedBrowseModes/settings/browsemodes.html @@ -67,6 +67,25 @@ [% END %] + [% WRAPPER setting title="PLUGIN_EXTENDED_BROWSEMODES_TAGS" %] + + + + + + [% FOREACH tag = customTags.keys.sort %] + + + + + [% END %] + + + + +
[% "PLUGIN_EXTENDED_BROWSEMODES_ROLE" | string %][% "PLUGIN_EXTENDED_BROWSEMODES_ROLE_TEXT" | string %]
+ [% END %] + [% IF needsClient %] diff --git a/Slim/Plugin/ExtendedBrowseModes/Settings.pm b/Slim/Plugin/ExtendedBrowseModes/Settings.pm index 1b80c764fc2..df59070ff2b 100644 --- a/Slim/Plugin/ExtendedBrowseModes/Settings.pm +++ b/Slim/Plugin/ExtendedBrowseModes/Settings.pm @@ -53,6 +53,41 @@ sub handler { my $serverPrefs = $class->getServerPrefs($client); if ($params->{'saveSettings'}) { + + my $currentRoles = $prefs->get('userDefinedRoles'); + my $customTags = {}; + my $id = 21; + my $changed = 0; + foreach my $pref (keys %{$params}) { + if ($pref =~ /(.*)_tag$/) { + my $key = $1; + my $tag = $params->{$pref}; + + if ( $tag ) { + $customTags->{$tag} = { + name => $params->{$key . '_name'} || $tag, + id => $id, + }; + if ( !$currentRoles->{$tag} || $currentRoles->{$tag}->{name} ne $customTags->{$tag}->{name} ) { + Slim::Utils::Strings::storeExtraStrings([{ + strings => { EN => $customTags->{$tag}->{name}}, + token => $tag, + }]) if !Slim::Utils::Strings::stringExists($tag); + $changed = 1; + } + $id++; + } + } + } + foreach my $old (keys %{$currentRoles}) { + $changed = 1 if !$customTags->{$old}; + } + + if ( $changed ) { + $prefs->set('userDefinedRoles', $customTags); + Slim::Schema::Contributor->initializeRoles(); + } + my $menus = $prefs->get('additionalMenuItems'); for (my $i = 1; defined $params->{"id$i"}; $i++) { @@ -192,6 +227,8 @@ sub getServerPrefs {} sub beforeRender { my ($class, $params, $client) = @_; + $params->{customTags} = $prefs->get('userDefinedRoles'); + $params->{libraries} = {}; if ($params->{'needsAudioBookUpdate'}) { diff --git a/Slim/Plugin/ExtendedBrowseModes/strings.txt b/Slim/Plugin/ExtendedBrowseModes/strings.txt index 11f823d9e26..ee30395e89a 100644 --- a/Slim/Plugin/ExtendedBrowseModes/strings.txt +++ b/Slim/Plugin/ExtendedBrowseModes/strings.txt @@ -279,3 +279,25 @@ PLUGIN_EXTENDED_BROWSEMODES_AUTHORS FR Auteurs NL Schrijvers SV Författare + +PLUGIN_EXTENDED_BROWSEMODES_TAGS + EN User Defined Roles + DE Benutzerdefinierte Rollen + FR Rôles définis par l'utilisateur + ES Roles definidos por el usuario + NL Door de gebruiker gedefinieerde rollen + +PLUGIN_EXTENDED_BROWSEMODES_ROLE + EN Role + DE Rolle + FR Rôle + ES Role + NL Rol + +PLUGIN_EXTENDED_BROWSEMODES_ROLE_TEXT + EN Display Text + DE Text anzeigen + FR Afficher le texte + ES Mostrar texto + NL Tekst weergeven + diff --git a/Slim/Schema/Contributor.pm b/Slim/Schema/Contributor.pm index c48e2b065e1..f0b76204854 100644 --- a/Slim/Schema/Contributor.pm +++ b/Slim/Schema/Contributor.pm @@ -10,21 +10,16 @@ use Slim::Schema::ResultSet::Contributor; use Slim::Utils::Log; use Slim::Utils::Misc; +use Slim::Utils::Prefs; -my %contributorToRoleMap = ( - 'ARTIST' => 1, - 'COMPOSER' => 2, - 'CONDUCTOR' => 3, - 'BAND' => 4, - 'ALBUMARTIST' => 5, - 'TRACKARTIST' => 6, -); +my %contributorToRoleMap; +my @contributorRoles; +my @contributorRoleIds; +my $totalContributorRoles; +my %roleToContributorMap; +my %contributorToRoleTextMap; -my @contributorRoles = sort keys %contributorToRoleMap; -my @contributorRoleIds = values %contributorToRoleMap; -my $totalContributorRoles = scalar @contributorRoles; - -my %roleToContributorMap = reverse %contributorToRoleMap; +initializeRoles(); { my $class = __PACKAGE__; @@ -63,6 +58,29 @@ my %roleToContributorMap = reverse %contributorToRoleMap; $class->resultset_class('Slim::Schema::ResultSet::Contributor'); } +sub initializeRoles { + %contributorToRoleMap = ( + 'ARTIST' => 1, + 'COMPOSER' => 2, + 'CONDUCTOR' => 3, + 'BAND' => 4, + 'ALBUMARTIST' => 5, + 'TRACKARTIST' => 6, + ); + if ( my $prefs = preferences('plugin.extendedbrowsemodes') ) { + my $userDefinedRoles = $prefs->get('userDefinedRoles'); + while ( my($k, $v) = each (%$userDefinedRoles) ) { + $contributorToRoleMap{$k} = $v->{id}; + $contributorToRoleTextMap{$k} = $v->{name}; + } + } + + @contributorRoles = sort keys %contributorToRoleMap; + @contributorRoleIds = values %contributorToRoleMap; + $totalContributorRoles = scalar @contributorRoles; + %roleToContributorMap = reverse %contributorToRoleMap; +} + sub contributorRoles { return @contributorRoles; } @@ -83,6 +101,10 @@ sub typeToRole { return $contributorToRoleMap{$_[1]} || $_[1]; } +sub typeToRoleText { + return $contributorToRoleTextMap{$_[1]} || $_[1]; +} + sub roleToType { return $roleToContributorMap{$_[1]}; } diff --git a/Slim/Utils/Prefs.pm b/Slim/Utils/Prefs.pm index 17dbdc9b5f2..20fe41e80e7 100644 --- a/Slim/Utils/Prefs.pm +++ b/Slim/Utils/Prefs.pm @@ -96,6 +96,7 @@ my $os = Slim::Utils::OSDetect->getOS(); $os->migratePrefsFolder($path); my $prefs = preferences('server'); +my $ebmPrefs = preferences('plugin.extendedbrowsemodes'); # File paths need to be prepared in order to correctly read the file system $prefs->setFilepaths(qw(mediadirs ignoreInAudioScan playlistdir cachedir librarycachedir coverArt)); @@ -397,6 +398,13 @@ sub init { qw(splitList groupdiscs useTPE2AsAlbumArtist) ); + $ebmPrefs->setChange( + sub { + Slim::Control::Request::executeRequest(undef, ['wipecache', $prefs->get('dontTriggerScanOnPrefChange') ? 'queue' : undef]); + }, + 'userDefinedRoles' + ); + $prefs->setChange( sub { Slim::Utils::Misc::setPriority($_[1]) }, 'serverPriority'); $prefs->setChange( sub { From 6bdb14f9d09a7d34308ec21a81b458bb761ca8e0 Mon Sep 17 00:00:00 2001 From: darrell-k Date: Wed, 10 Jul 2024 21:07:42 +0100 Subject: [PATCH 2/4] tidy up --- Slim/Schema/Contributor.pm | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Slim/Schema/Contributor.pm b/Slim/Schema/Contributor.pm index f0b76204854..de352b0ee1f 100644 --- a/Slim/Schema/Contributor.pm +++ b/Slim/Schema/Contributor.pm @@ -17,7 +17,6 @@ my @contributorRoles; my @contributorRoleIds; my $totalContributorRoles; my %roleToContributorMap; -my %contributorToRoleTextMap; initializeRoles(); @@ -71,7 +70,6 @@ sub initializeRoles { my $userDefinedRoles = $prefs->get('userDefinedRoles'); while ( my($k, $v) = each (%$userDefinedRoles) ) { $contributorToRoleMap{$k} = $v->{id}; - $contributorToRoleTextMap{$k} = $v->{name}; } } @@ -101,10 +99,6 @@ sub typeToRole { return $contributorToRoleMap{$_[1]} || $_[1]; } -sub typeToRoleText { - return $contributorToRoleTextMap{$_[1]} || $_[1]; -} - sub roleToType { return $roleToContributorMap{$_[1]}; } From bd906752d404c79712f4ada454b44d84b8c78646 Mon Sep 17 00:00:00 2001 From: darrell-k Date: Fri, 12 Jul 2024 15:07:47 +0100 Subject: [PATCH 3/4] Use server prefs, not plugin prefs --- Slim/Menu/AlbumInfo.pm | 1 + .../ExtendedBrowseModes/settings/browsemodes.html | 2 +- Slim/Plugin/ExtendedBrowseModes/Settings.pm | 10 ++++++---- Slim/Plugin/ExtendedBrowseModes/strings.txt | 13 ++++++++----- Slim/Schema/Contributor.pm | 4 ++-- Slim/Utils/Prefs.pm | 10 +--------- 6 files changed, 19 insertions(+), 21 deletions(-) diff --git a/Slim/Menu/AlbumInfo.pm b/Slim/Menu/AlbumInfo.pm index ac740232caf..a5c1246b37d 100644 --- a/Slim/Menu/AlbumInfo.pm +++ b/Slim/Menu/AlbumInfo.pm @@ -273,6 +273,7 @@ sub infoContributors { $linkRoles{'TRACKARTIST'} = 1; $linkRoles{'ALBUMARTIST'} = 1; + # Loop through the contributor types and append for my $role (@roles) { for my $contributor ( $album->artistsForRoles($role) ) { diff --git a/Slim/Plugin/ExtendedBrowseModes/HTML/EN/plugins/ExtendedBrowseModes/settings/browsemodes.html b/Slim/Plugin/ExtendedBrowseModes/HTML/EN/plugins/ExtendedBrowseModes/settings/browsemodes.html index 1bfeddc11e4..f462dc2c2a4 100644 --- a/Slim/Plugin/ExtendedBrowseModes/HTML/EN/plugins/ExtendedBrowseModes/settings/browsemodes.html +++ b/Slim/Plugin/ExtendedBrowseModes/HTML/EN/plugins/ExtendedBrowseModes/settings/browsemodes.html @@ -67,7 +67,7 @@ [% END %] - [% WRAPPER setting title="PLUGIN_EXTENDED_BROWSEMODES_TAGS" %] + [% WRAPPER setting title="PLUGIN_EXTENDED_BROWSEMODES_TAGS" desc="PLUGIN_EXTENDED_BROWSEMODES_TAGS_DESC" %] diff --git a/Slim/Plugin/ExtendedBrowseModes/Settings.pm b/Slim/Plugin/ExtendedBrowseModes/Settings.pm index df59070ff2b..e1b1cdc224e 100644 --- a/Slim/Plugin/ExtendedBrowseModes/Settings.pm +++ b/Slim/Plugin/ExtendedBrowseModes/Settings.pm @@ -54,14 +54,15 @@ sub handler { if ($params->{'saveSettings'}) { - my $currentRoles = $prefs->get('userDefinedRoles'); + my $serverPrefs = preferences('server'); + my $currentRoles = $serverPrefs->get('userDefinedRoles'); my $customTags = {}; my $id = 21; my $changed = 0; foreach my $pref (keys %{$params}) { if ($pref =~ /(.*)_tag$/) { my $key = $1; - my $tag = $params->{$pref}; + my $tag = uc($params->{$pref}); if ( $tag ) { $customTags->{$tag} = { @@ -84,7 +85,7 @@ sub handler { } if ( $changed ) { - $prefs->set('userDefinedRoles', $customTags); + $serverPrefs->set('userDefinedRoles', $customTags); Slim::Schema::Contributor->initializeRoles(); } @@ -227,7 +228,8 @@ sub getServerPrefs {} sub beforeRender { my ($class, $params, $client) = @_; - $params->{customTags} = $prefs->get('userDefinedRoles'); + my $serverPrefs = preferences('server'); + $params->{customTags} = $serverPrefs->get('userDefinedRoles'); $params->{libraries} = {}; diff --git a/Slim/Plugin/ExtendedBrowseModes/strings.txt b/Slim/Plugin/ExtendedBrowseModes/strings.txt index ee30395e89a..a489857af85 100644 --- a/Slim/Plugin/ExtendedBrowseModes/strings.txt +++ b/Slim/Plugin/ExtendedBrowseModes/strings.txt @@ -287,12 +287,15 @@ PLUGIN_EXTENDED_BROWSEMODES_TAGS ES Roles definidos por el usuario NL Door de gebruiker gedefinieerde rollen +PLUGIN_EXTENDED_BROWSEMODES_TAGS_DESC + EN Tell LMS about any custom contributor role tags used in the music library. For example, SOLOIST, DRUMMER, PRODUCER, etc. These can then be used as Contributor Roles in the Additional Browse Modes above. They will also appear as categories when browsing albums or artists with Release Type grouping enabled. Changes here will trigger a rescan of the music library. + PLUGIN_EXTENDED_BROWSEMODES_ROLE - EN Role - DE Rolle - FR Rôle - ES Role - NL Rol + EN Role tag + DE Rolle tag + FR Rôle tag + ES Role tag + NL Rol tag PLUGIN_EXTENDED_BROWSEMODES_ROLE_TEXT EN Display Text diff --git a/Slim/Schema/Contributor.pm b/Slim/Schema/Contributor.pm index de352b0ee1f..4ed0694e93c 100644 --- a/Slim/Schema/Contributor.pm +++ b/Slim/Schema/Contributor.pm @@ -66,8 +66,8 @@ sub initializeRoles { 'ALBUMARTIST' => 5, 'TRACKARTIST' => 6, ); - if ( my $prefs = preferences('plugin.extendedbrowsemodes') ) { - my $userDefinedRoles = $prefs->get('userDefinedRoles'); + my $prefs = preferences('server'); + if ( my $userDefinedRoles = $prefs->get('userDefinedRoles') ) { while ( my($k, $v) = each (%$userDefinedRoles) ) { $contributorToRoleMap{$k} = $v->{id}; } diff --git a/Slim/Utils/Prefs.pm b/Slim/Utils/Prefs.pm index 20fe41e80e7..48367bc6722 100644 --- a/Slim/Utils/Prefs.pm +++ b/Slim/Utils/Prefs.pm @@ -96,7 +96,6 @@ my $os = Slim::Utils::OSDetect->getOS(); $os->migratePrefsFolder($path); my $prefs = preferences('server'); -my $ebmPrefs = preferences('plugin.extendedbrowsemodes'); # File paths need to be prepared in order to correctly read the file system $prefs->setFilepaths(qw(mediadirs ignoreInAudioScan playlistdir cachedir librarycachedir coverArt)); @@ -395,14 +394,7 @@ sub init { $prefs->setChange( sub { Slim::Control::Request::executeRequest(undef, ['wipecache', $prefs->get('dontTriggerScanOnPrefChange') ? 'queue' : undef]) }, - qw(splitList groupdiscs useTPE2AsAlbumArtist) - ); - - $ebmPrefs->setChange( - sub { - Slim::Control::Request::executeRequest(undef, ['wipecache', $prefs->get('dontTriggerScanOnPrefChange') ? 'queue' : undef]); - }, - 'userDefinedRoles' + qw(splitList groupdiscs useTPE2AsAlbumArtist userDefinedRoles) ); $prefs->setChange( sub { Slim::Utils::Misc::setPriority($_[1]) }, 'serverPriority'); From e35c8a5abd7ac269149edd7793e0074acb19e91d Mon Sep 17 00:00:00 2001 From: darrell-k Date: Wed, 17 Jul 2024 22:20:37 +0100 Subject: [PATCH 4/4] refinements --- Changelog9.html | 1 + .../EN/plugins/ExtendedBrowseModes/settings/browsemodes.html | 4 ++-- Slim/Plugin/ExtendedBrowseModes/Settings.pm | 1 - Slim/Plugin/ExtendedBrowseModes/strings.txt | 4 ++++ Slim/Utils/Prefs.pm | 2 ++ 5 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Changelog9.html b/Changelog9.html index b6363dd67ff..7eab70073a2 100644 --- a/Changelog9.html +++ b/Changelog9.html @@ -13,6 +13,7 @@

Introducing... Lyrion Music Server Version
  • Massive upgrade for Classical music lovers: add support for Works, Performances, Disc Subtitles. Thanks a ton @darrel-k!
  • #1095 - Link from online tracks and albums to local library (if possible).
  • #1115 - Add option to show tracks from a given year, even if their album would be listed in a different year.
  • +
  • #1115 - Allow user defined contributor roles.

  • diff --git a/Slim/Plugin/ExtendedBrowseModes/HTML/EN/plugins/ExtendedBrowseModes/settings/browsemodes.html b/Slim/Plugin/ExtendedBrowseModes/HTML/EN/plugins/ExtendedBrowseModes/settings/browsemodes.html index f462dc2c2a4..30dfd49ffe2 100644 --- a/Slim/Plugin/ExtendedBrowseModes/HTML/EN/plugins/ExtendedBrowseModes/settings/browsemodes.html +++ b/Slim/Plugin/ExtendedBrowseModes/HTML/EN/plugins/ExtendedBrowseModes/settings/browsemodes.html @@ -75,8 +75,8 @@

    [% FOREACH tag = customTags.keys.sort %] - - + + [% END %] diff --git a/Slim/Plugin/ExtendedBrowseModes/Settings.pm b/Slim/Plugin/ExtendedBrowseModes/Settings.pm index e1b1cdc224e..b1455b2e237 100644 --- a/Slim/Plugin/ExtendedBrowseModes/Settings.pm +++ b/Slim/Plugin/ExtendedBrowseModes/Settings.pm @@ -86,7 +86,6 @@ sub handler { if ( $changed ) { $serverPrefs->set('userDefinedRoles', $customTags); - Slim::Schema::Contributor->initializeRoles(); } my $menus = $prefs->get('additionalMenuItems'); diff --git a/Slim/Plugin/ExtendedBrowseModes/strings.txt b/Slim/Plugin/ExtendedBrowseModes/strings.txt index a489857af85..7eae33ade19 100644 --- a/Slim/Plugin/ExtendedBrowseModes/strings.txt +++ b/Slim/Plugin/ExtendedBrowseModes/strings.txt @@ -289,6 +289,10 @@ PLUGIN_EXTENDED_BROWSEMODES_TAGS PLUGIN_EXTENDED_BROWSEMODES_TAGS_DESC EN Tell LMS about any custom contributor role tags used in the music library. For example, SOLOIST, DRUMMER, PRODUCER, etc. These can then be used as Contributor Roles in the Additional Browse Modes above. They will also appear as categories when browsing albums or artists with Release Type grouping enabled. Changes here will trigger a rescan of the music library. + DE Informieren Sie LMS über alle benutzerdefinierten Rollen-Tags, die in der Musikbibliothek verwendet werden. Zum Beispiel SOLOIST, DRUMMER, PRODUCER, usw. Diese können dann als Mitwirkende Rollen in den zusätzlichen Suchmodi oben verwendet werden. Sie werden auch als Kategorien angezeigt, wenn Sie Alben oder Künstler mit aktivierter Gruppierung nach Veröffentlichungstyp durchsuchen. Änderungen hier lösen einen erneuten Scan der Musikbibliothek aus. + FR Indiquez à LMS toute étiquette de rôle de contributeur personnalisée utilisée dans la bibliothèque musicale. Par exemple, SOLOIST, DRUMMER, PRODUCER, etc. Ceux-ci peuvent ensuite être utilisés comme rôles de contributeur dans les modes de navigation supplémentaires ci-dessus. Ils apparaîtront également en tant que catégories lorsque vous parcourez des albums ou des artistes en activant le regroupement par type de publication. Les modifications apportées à ces catégories déclencheront une nouvelle analyse de la bibliothèque musicale. + ES Informe a LMS sobre cualquier etiqueta de rol de colaborador personalizada utilizada en la biblioteca musical. Por ejemplo, SOLISTA, BATERISTA, PRODUCTOR, etc. Estas etiquetas se pueden utilizar como roles de colaborador en los modos de exploración adicionales anteriores. También aparecerán como categorías al explorar álbumes o artistas con la agrupación Tipo de publicación activada. Los cambios que se realicen aquí provocarán una nueva exploración de la biblioteca musical. + NL Vertel LMS over alle aangepaste rollabels voor medewerkers die worden gebruikt in de muziekbibliotheek. Bijvoorbeeld SOLOIST, DRUMMER, PRODUCER, enz. Deze kunnen dan worden gebruikt als rollen voor medewerkers in de extra bladermodi hierboven. Ze verschijnen ook als categorieën wanneer u door albums of artiesten bladert met de Release Type groepering ingeschakeld. Als u hier wijzigingen aanbrengt, wordt de muziekbibliotheek opnieuw gescand. PLUGIN_EXTENDED_BROWSEMODES_ROLE EN Role tag diff --git a/Slim/Utils/Prefs.pm b/Slim/Utils/Prefs.pm index 48367bc6722..bcac8bbf672 100644 --- a/Slim/Utils/Prefs.pm +++ b/Slim/Utils/Prefs.pm @@ -397,6 +397,8 @@ sub init { qw(splitList groupdiscs useTPE2AsAlbumArtist userDefinedRoles) ); + $prefs->setChange( sub { Slim::Schema::Contributor->initializeRoles() }, 'userDefinedRoles'); + $prefs->setChange( sub { Slim::Utils::Misc::setPriority($_[1]) }, 'serverPriority'); $prefs->setChange( sub {
    [% "PLUGIN_EXTENDED_BROWSEMODES_ROLE" | string %]