Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog9.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ <h2><a name="v9.2.0" id="v9.2.0"></a>Version 9.2.0</h2>
<li><a href="https://github.com/LMS-Community/slimserver/pull/1541">#1541</a> - Add per-player timezone support: players can now display date and time, and fire alarms, in their own timezone rather than the server's. (@boudekerk)</li>
<li><a href="https://github.com/LMS-Community/slimserver/pull/1546">#1546</a> - Add "Default Adjustment for Local Tracks" player option. (@SamInPgh)</li>
<li><a href="https://github.com/LMS-Community/slimserver/pull/1564">#1564</a> - Add Dismiss option to Jive alarm popup (@boudekerk)</li>
<li><a href="https://github.com/LMS-Community/slimserver/issues/1555">#1555</a> - Store display_artist from ALBUMARTIST/ARTIST tags separately from individual contributors. Optional use of ALBUMARTISTS/ARTISTS plural tags for contributor creation. (@Rouzax, @darrell-k)</li>
</ul>
<br />

Expand Down
9 changes: 9 additions & 0 deletions HTML/EN/settings/server/behavior.html
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,15 @@
</select>
[% END %]

[% WRAPPER setting title="SETUP_USEPLURALARTISTTAGS" desc="SETUP_USEPLURALARTISTTAGS_DESC"%]
<select class="stdedit" name="pref_usePluralArtistTags" id="usePluralArtistTags">

<option [% IF NOT prefs.pref_usePluralArtistTags %]selected [% END %]value="0">[% 'SETUP_USEPLURALARTISTTAGS_0' | string %]</option>
<option [% IF prefs.pref_usePluralArtistTags %]selected [% END %]value="1">[% 'SETUP_USEPLURALARTISTTAGS_1' | string %]</option>

</select>
[% END %]

[% WRAPPER setting title="SETUP_YEARMENU" desc="SETUP_YEARMENU_DESC"%]
<select class="stdedit" name="pref_onlyAlbumYears" id="onlyAlbumYears">

Expand Down
21 changes: 15 additions & 6 deletions Slim/Control/Queries.pm
Original file line number Diff line number Diff line change
Expand Up @@ -5797,8 +5797,8 @@ sub _songDataFromHash {
$returnHash{$role} = $res->{$role};
}
}
# also return contributor_display.name
$returnHash{'display_artist'} = $res->{'contributor_display.name'} if $res->{'contributor_display.name'};
my $da = $res->{'tcd.name'} || $res->{'acd.name'};
$returnHash{display_artist} = $da if $da;
}
elsif ( $tag eq 'S' ) {
for my $role ( @contributorRoles ) {
Expand Down Expand Up @@ -6400,9 +6400,15 @@ sub _getTagDataForTracks {
};

my $join_contributor_display = sub {
if ( $sql !~ /JOIN contributor_display/ ) {
if ( $sql !~ /JOIN contributor_display AS acd/ ) {
$join_albums->();
$sql .= 'LEFT JOIN contributor_display ON albums.display_contributor = contributor_display.id ';
$sql .= 'LEFT JOIN contributor_display AS acd ON albums.display_contributor = acd.id ';
}
};

my $join_track_contributor_display = sub {
if ( $sql !~ /JOIN contributor_display AS tcd/ ) {
$sql .= 'LEFT JOIN contributor_display AS tcd ON tracks.display_contributor = tcd.id ';
}
};

Expand Down Expand Up @@ -6512,7 +6518,9 @@ sub _getTagDataForTracks {
$join_contributors->();
$c->{'contributors.name'} = 1 if $tags =~ /a/;
$join_contributor_display->();
$c->{'contributor_display.name'} = 1;
$join_track_contributor_display->();
$c->{'acd.name'} = 1;
$c->{'tcd.name'} = 1;

# only albums on which the contributor has a specific role?
my @roles;
Expand Down Expand Up @@ -6672,7 +6680,8 @@ sub _getTagDataForTracks {
utf8::decode( $c->{'tracks.lyrics'} ) if exists $c->{'tracks.lyrics'};
utf8::decode( $c->{'albums.title'} ) if exists $c->{'albums.title'};
utf8::decode( $c->{'contributors.name'} ) if exists $c->{'contributors.name'};
utf8::decode( $c->{'contributor_display.name'} ) if exists $c->{'contributor_display.name'};
utf8::decode( $c->{'acd.name'} ) if exists $c->{'acd.name'};
utf8::decode( $c->{'tcd.name'} ) if exists $c->{'tcd.name'};
utf8::decode( $c->{'genres.name'} ) if exists $c->{'genres.name'};
utf8::decode( $c->{'comments.value'} ) if exists $c->{'comments.value'};
utf8::decode( $c->{'tracks.discsubtitle'}) if exists $c->{'tracks.discsubtitle'};
Expand Down
8 changes: 6 additions & 2 deletions Slim/Plugin/FullTextSearch/Plugin.pm
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ use constant SQL_CREATE_TRACK_ITEM => q{
UNIQUE_TOKENS(LOWER(IFNULL(tracks.title, '')) || ' ' || IFNULL(tracks.titlesearch, '') || ' ' || IFNULL(tracks.customsearch, '')),
-- weight 5
UNIQUE_TOKENS(IFNULL(tracks.year, '') || ' ' || GROUP_CONCAT(albums.title, ' ') || ' ' || GROUP_CONCAT(albums.titlesearch, ' ') || ' '
|| GROUP_CONCAT(genres.name, ' ') || ' ' || GROUP_CONCAT(genres.namesearch, ' ')),
|| GROUP_CONCAT(genres.name, ' ') || ' ' || GROUP_CONCAT(genres.namesearch, ' ') || ' '
|| IFNULL(tcd.name, '') || ' ' || IFNULL(acd.name, '')),
-- weight 3 - contributors create multiple hits, therefore only w3
UNIQUE_TOKENS(CONCAT_CONTRIBUTOR_ROLE(tracks.id, GROUP_CONCAT(contributor_track.contributor, ','), 'contributor_track') || ' '
|| IGNORE_CASE(comments.value) || ' ' || IGNORE_CASE(tracks.lyrics) || ' ' || IFNULL(tracks.content_type, '') || ' '
Expand All @@ -52,6 +53,8 @@ use constant SQL_CREATE_TRACK_ITEM => q{
LEFT JOIN genre_track ON genre_track.track = tracks.id
LEFT JOIN genres ON genres.id = genre_track.genre
LEFT JOIN comments ON comments.track = tracks.id
LEFT JOIN contributor_display AS acd ON albums.display_contributor = acd.id
LEFT JOIN contributor_display AS tcd ON tracks.display_contributor = tcd.id

%s

Expand Down Expand Up @@ -112,7 +115,7 @@ use constant SQL_CREATE_ALBUM_ITEM => qq{
UNIQUE_TOKENS(LOWER(IFNULL(albums.title, '')) || ' ' || IFNULL(albums.titlesearch, '') || ' ' || IFNULL(albums.customsearch, '') || ' '
|| IFNULL((SELECT GROUP_CONCAT(wt,' ') FROM (SELECT DISTINCT works.titlesearch wt FROM tracks JOIN works ON tracks.work = works.id WHERE tracks.album = albums.id) ), ' ') ),
-- weight 5
IFNULL(albums.year, ''),
UNIQUE_TOKENS(IFNULL(albums.year, '') || ' ' || IFNULL(contributor_display.name, '')),
-- weight 3
UNIQUE_TOKENS(CONCAT_CONTRIBUTOR_ROLE(albums.id, GROUP_CONCAT(contributor_album.contributor, ','), 'contributor_album')),
-- weight 1
Expand All @@ -122,6 +125,7 @@ use constant SQL_CREATE_ALBUM_ITEM => qq{
FROM albums
LEFT JOIN contributor_album ON contributor_album.album = albums.id
LEFT JOIN contributors ON contributors.id = contributor_album.contributor
LEFT JOIN contributor_display ON albums.display_contributor = contributor_display.id

%s

Expand Down
139 changes: 111 additions & 28 deletions Slim/Schema.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1708,15 +1708,26 @@ sub _newTrack {
$LAST_ERROR = 'Track is DRM-protected';
return;
}
if ( $attributeHash->{ALBUMARTIST} && $attributeHash->{ALBUMARTISTS} ) {
my $temp = $attributeHash->{ALBUMARTISTS};
$attributeHash->{ALBUMARTISTS} = $attributeHash->{ALBUMARTIST};
$attributeHash->{ALBUMARTIST} = $temp;
}
if ( $attributeHash->{ARTIST} && $attributeHash->{ARTISTS} ) {
my $temp = $attributeHash->{ARTISTS};
$attributeHash->{ARTISTS} = $attributeHash->{ARTIST};
$attributeHash->{ARTIST} = $temp;
my $albumDisplayArtist;
if ( $attributeHash->{ALBUMARTIST} ) {
$albumDisplayArtist = ref $attributeHash->{ALBUMARTIST} eq 'ARRAY'
? $attributeHash->{ALBUMARTIST}->[0]
: $attributeHash->{ALBUMARTIST};
} elsif ( $attributeHash->{ALBUMARTISTS} ) {
$albumDisplayArtist = ref $attributeHash->{ALBUMARTISTS} eq 'ARRAY'
? join(', ', grep { defined $_ && $_ ne '' } @{$attributeHash->{ALBUMARTISTS}})
: $attributeHash->{ALBUMARTISTS};
}

my $trackDisplayArtist;
if ( $attributeHash->{ARTIST} ) {
$trackDisplayArtist = ref $attributeHash->{ARTIST} eq 'ARRAY'
? $attributeHash->{ARTIST}->[0]
: $attributeHash->{ARTIST};
} elsif ( $attributeHash->{ARTISTS} ) {
$trackDisplayArtist = ref $attributeHash->{ARTISTS} eq 'ARRAY'
? join(', ', grep { defined $_ && $_ ne '' } @{$attributeHash->{ARTISTS}})
: $attributeHash->{ARTISTS};
}
($attributeHash, $deferredAttributes) = $self->_preCheckAttributes({
'url' => $url,
Expand Down Expand Up @@ -1804,23 +1815,14 @@ sub _newTrack {
# Walk through the valid contributor roles, adding them to the database.
my $contributors = $self->_mergeAndCreateContributors($deferredAttributes, $isCompilation, 1);

my $aaDisplayID;
if ( $deferredAttributes->{ALBUMARTISTS} ) {
my $contributor_display_sth = $self->dbh->prepare_cached('SELECT id FROM contributor_display WHERE name = ?');
$contributor_display_sth->execute($deferredAttributes->{ALBUMARTISTS});
($aaDisplayID) = $contributor_display_sth->fetchrow_array;
$contributor_display_sth->finish;
if ( !$aaDisplayID ) {
my $sth_insert = $self->dbh->prepare_cached("INSERT INTO contributor_display (name) VALUES (?)");
$sth_insert->execute( $deferredAttributes->{ALBUMARTISTS} );
$aaDisplayID = $self->dbh->last_insert_id(undef, undef, undef, undef);
}
}
my $aaDisplayID = $self->_getOrCreateDisplayContributor($albumDisplayArtist);
my $taDisplayID = $self->_getOrCreateDisplayContributor($trackDisplayArtist);

# Set primary_artist for the track
if ( my $artist = $contributors->{ARTIST} || $contributors->{TRACKARTIST} ) {
$columnValueHash{primary_artist} = $artist->[0];
}
$columnValueHash{display_contributor} = $taDisplayID if $taDisplayID;

### Create Work rows
my $workID;
Expand Down Expand Up @@ -1866,7 +1868,7 @@ sub _newTrack {
$trackId = $self->_createTrack(\%columnValueHash, \%persistentColumnValueHash, $source);

### Create ContributorTrack & ContributorAlbum rows
$self->_createContributorRoleRelationships($contributors, $trackId, $albumId, $aaDisplayID);
$self->_createContributorRoleRelationships($contributors, $trackId, $albumId, $aaDisplayID, $taDisplayID);

### Create Genre rows
$self->_createGenre($deferredAttributes->{'GENRE'}, $trackId, 1);
Expand Down Expand Up @@ -2022,6 +2024,28 @@ sub updateOrCreateBase {
$attributeHash = { %{Slim::Formats->readTags($url)}, %$attributeHash };
}

my $albumDisplayArtist;
if ( $attributeHash->{ALBUMARTIST} ) {
$albumDisplayArtist = ref $attributeHash->{ALBUMARTIST} eq 'ARRAY'
? $attributeHash->{ALBUMARTIST}->[0]
: $attributeHash->{ALBUMARTIST};
} elsif ( $attributeHash->{ALBUMARTISTS} ) {
$albumDisplayArtist = ref $attributeHash->{ALBUMARTISTS} eq 'ARRAY'
? join(', ', grep { defined $_ && $_ ne '' } @{$attributeHash->{ALBUMARTISTS}})
: $attributeHash->{ALBUMARTISTS};
}

my $trackDisplayArtist;
if ( $attributeHash->{ARTIST} ) {
$trackDisplayArtist = ref $attributeHash->{ARTIST} eq 'ARRAY'
? $attributeHash->{ARTIST}->[0]
: $attributeHash->{ARTIST};
} elsif ( $attributeHash->{ARTISTS} ) {
$trackDisplayArtist = ref $attributeHash->{ARTISTS} eq 'ARRAY'
? join(', ', grep { defined $_ && $_ ne '' } @{$attributeHash->{ARTISTS}})
: $attributeHash->{ARTISTS};
}

my $deferredAttributes;
($attributeHash, $deferredAttributes) = $self->_preCheckAttributes({
'url' => $url,
Expand Down Expand Up @@ -2072,9 +2096,11 @@ sub updateOrCreateBase {
if (!$playlist) {

$self->_postCheckAttributes({
'track' => $track,
'attributes' => $deferredAttributes,
'integrateRemote' => $integrateRemote
'track' => $track,
'attributes' => $deferredAttributes,
'integrateRemote' => $integrateRemote,
'albumDisplayArtist' => $albumDisplayArtist,
'trackDisplayArtist' => $trackDisplayArtist,
});
}

Expand Down Expand Up @@ -3051,6 +3077,9 @@ sub _postCheckAttributes {
my $attributes = $args->{'attributes'};
my $create = $args->{'create'} || 0;

my $albumDisplayArtist = $args->{'albumDisplayArtist'};
my $trackDisplayArtist = $args->{'trackDisplayArtist'};

# Don't bother with directories / lnks. This makes sure "No Artist",
# etc don't show up if you don't have any.
my %cols = $track->get_columns;
Expand Down Expand Up @@ -3092,6 +3121,13 @@ sub _postCheckAttributes {
$cols{primary_artist} = $artist->[0];
}

my $aaDisplayID = $self->_getOrCreateDisplayContributor($albumDisplayArtist);
my $taDisplayID = $self->_getOrCreateDisplayContributor($trackDisplayArtist);

if ($taDisplayID) {
$track->set_column('display_contributor', $taDisplayID);
}

#Work
if (defined $attributes->{'WORK'}) {
if ( _workRequired($attributes->{'GENRE'}) ) {
Expand All @@ -3111,18 +3147,20 @@ sub _postCheckAttributes {
my $albumId = $self->_createOrUpdateAlbum($attributes,
\%cols, # trackColumns
$isCompilation,
$artist->[0], # primary contributor-id
$artist->[0], # primary contributor-id
defined $contributors->{'ALBUMARTIST'}->[0] ? 1 : 0, # hasAlbumArtist
$create, # create
$track, # Track
undef, # basename
$aaDisplayID,
);

# Don't add an album to container tracks - See bug 2337
if (!Slim::Music::Info::isContainer($track, $trackType)) {
$track->album($albumId);
}

$self->_createContributorRoleRelationships($contributors, $trackId, $albumId);
$self->_createContributorRoleRelationships($contributors, $trackId, $albumId, $aaDisplayID, $taDisplayID);

# Save any changes - such as album.
$track->update;
Expand Down Expand Up @@ -3160,6 +3198,19 @@ sub _mergeAndCreateContributors {
}
}

if ( $prefs->get('usePluralArtistTags') ) {
for my $pair ( ['ALBUMARTISTS', 'ALBUMARTIST'], ['ARTISTS', $attributes->{TRACKARTIST} ? 'TRACKARTIST' : 'ARTIST'] ) {
my ($plural, $singular) = @$pair;
next unless defined $attributes->{$plural};

my @individuals = grep { defined $_ && $_ ne '' }
Slim::Music::Info::splitTag($attributes->{$plural});
next unless @individuals;

$attributes->{$singular} = \@individuals;
}
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not working. example tags:

ALBUMARTIST: Bill Evans Trio with Scott LaFaro & Paul Motian
ALBUMARTISTS: Bill Evans; Bill Evans Trio; Scott LaFaro; Paul Motian

Results in only a single contributor being created "Bill Evans Trio with Scott LaFaro & Paul Motian" (I forced the new pref to "1").

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably because $attributes->{ALBUMARTISTS} is not an array?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. The code assumed an arrayref but ALBUMARTISTS arrives as a scalar when written as a single semicolon-joined field (e.g. "Bill Evans; Scott LaFaro"). Fixed by routing through splitTag which handles both arrayrefs (pass-through) and scalars (splits on the configured splitList separator). Added a test fixture (fixture 23) that writes scalar plural tags to catch this going forward.

my %contributors = ();

for my $tag (Slim::Schema::Contributor->contributorRoles) {
Expand Down Expand Up @@ -3217,9 +3268,31 @@ sub _mergeAndCreateContributors {
return \%contributors;
}

sub _getOrCreateDisplayContributor {
my ($self, $displayName) = @_;
return unless defined $displayName && $displayName ne '';

my $sth = $self->dbh->prepare_cached(
'SELECT id FROM contributor_display WHERE name = ?'
);
$sth->execute($displayName);
my ($id) = $sth->fetchrow_array;
$sth->finish;

if (!$id) {
my $insert = $self->dbh->prepare_cached(
'INSERT INTO contributor_display (name) VALUES (?)'
);
$insert->execute($displayName);
$id = $self->dbh->last_insert_id(undef, undef, undef, undef);
}

return $id;
}

sub _createContributorRoleRelationships {

my ($self, $contributors, $trackId, $albumId, $aaDisplayID) = @_;
my ($self, $contributors, $trackId, $albumId, $aaDisplayID, $taDisplayID) = @_;

if (!keys %$contributors) {
main::DEBUGLOG && $log->debug('Attempt to set empty contributor set for trackid=', $trackId);
Expand Down Expand Up @@ -3266,6 +3339,13 @@ sub _createContributorRoleRelationships {
(?, ?, ?)
} ) if $aaDisplayID;

my $sth_track_display = $self->dbh->prepare_cached( qq{
REPLACE INTO contributor_track_display
(contributor_display, contributor, track)
VALUES
(?, ?, ?)
} ) if $taDisplayID;

while (my ($role, $contributorList) = each %{$contributors}) {
my $roleId = Slim::Schema::Contributor->typeToRole($role);
for my $contributor (@{$contributorList}) {
Expand All @@ -3279,6 +3359,9 @@ sub _createContributorRoleRelationships {
if ( $aaDisplayID && $role eq 'ALBUMARTIST' ) {
$sth_album_display->execute( $aaDisplayID, $contributor, $albumId );
}
if ( $taDisplayID && ($role eq 'ARTIST' || $role eq 'TRACKARTIST') ) {
$sth_track_display->execute( $taDisplayID, $contributor, $trackId );
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion Slim/Utils/Prefs.pm
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ sub init {
'autoDownloadUpdate' => sub { $os->canAutoUpdate() },
'noGenreFilter' => 0,
'noRoleFilter' => 0,
'usePluralArtistTags' => 0,
'searchSubString' => 0,
'ignoredarticles' => "The El La Los Las Le Les",
'splitList' => ';',
Expand Down Expand Up @@ -410,7 +411,7 @@ sub init {

$prefs->setChange(
sub { Slim::Control::Request::executeRequest(undef, ['wipecache', $prefs->get('dontTriggerScanOnPrefChange') ? 'queue' : undef]) },
qw(splitList groupdiscs useTPE2AsAlbumArtist useTIT1AsWork cleanupReleaseTypes worksScan)
qw(splitList groupdiscs useTPE2AsAlbumArtist useTIT1AsWork cleanupReleaseTypes worksScan usePluralArtistTags)
);

$prefs->setChange( sub {
Expand Down
2 changes: 1 addition & 1 deletion Slim/Web/Settings/Server/Behavior.pm
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ sub prefs {
ignoreReleaseTypes cleanupReleaseTypes groupArtistAlbumsByReleaseType
useTPE2AsAlbumArtist variousArtistsString ratingImplementation useUnifiedArtistsList
skipsentinel showComposerReleasesbyAlbum myClassicalGenres onlyAlbumYears
worksScan useTIT1AsWork)
worksScan useTIT1AsWork usePluralArtistTags)
);
}

Expand Down
12 changes: 12 additions & 0 deletions strings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8703,6 +8703,18 @@ SETUP_NOROLEFILTER_DESC
SV När du bläddrar genom "Artister" kan du filtrera så att bara album och låtar som matchar den valda rollen ("ALBUMARTIST", "COMPOSER", etc.) visas.
ZH_CN 在浏览艺术家时,可以过滤并只显示和所选角色匹配的专辑和音轨(例如,ALBUMARTIST,COMPOSER等)。

SETUP_USEPLURALARTISTTAGS
EN Use Plural Artist Tags

SETUP_USEPLURALARTISTTAGS_DESC
EN When your music files contain both a display name (e.g. ALBUMARTIST = "John Lennon & Yoko Ono") and a list of individual artists (ALBUMARTISTS/ARTISTS tags), LMS normally creates a single artist entry from the display name. Enable this setting to use the individual artist list instead, so each artist gets their own entry in the library. The display name is still shown in the UI. Requires a rescan after changing. Most taggers (Picard, SongKong, Mp3tag) can write these tags.

SETUP_USEPLURALARTISTTAGS_0
EN Disabled

SETUP_USEPLURALARTISTTAGS_1
EN Enabled

SETUP_ROLESINARTISTS
CS Interpret skladby, Skladatel, Skupina a Orchestr v Interpretech
DA Nummerets kunstner, Komponist, band og orkester i Kunstnere
Expand Down