Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More releases rework #1303

Merged
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
12 changes: 9 additions & 3 deletions Slim/Control/Queries.pm
Original file line number Diff line number Diff line change
Expand Up @@ -929,9 +929,15 @@ sub albumsQuery {
}

if ( $tags =~ /R/ ) {
$contributorRoleSth ||= $dbh->prepare_cached("SELECT role FROM contributor_album WHERE album = ? AND contributor = ?");
my $rolesRef = $dbh->selectall_arrayref($contributorRoleSth, , undef, $c->{'albums.id'}, $contributorID || $c->{'albums.contributor'});

my $rolesRef;
my $contributorRoleSql = "SELECT role FROM contributor_album WHERE album = ?";
$contributorRoleSql .= " AND contributor = ?" if $contributorID;
$contributorRoleSth ||= $dbh->prepare_cached($contributorRoleSql);
if ( $contributorID ) {
$rolesRef = $dbh->selectall_arrayref( $contributorRoleSth, undef, ($c->{'albums.id'}, $contributorID) );
} else {
$rolesRef = $dbh->selectall_arrayref( $contributorRoleSth, undef, ($c->{'albums.id'}) );
}
if ($rolesRef) {
my $roles = join(',', map { $_->[0] } @$rolesRef);
$request->addResultLoopIfValueDefined($loopname, $chunkCount, 'role_ids', $roles);
Expand Down
89 changes: 55 additions & 34 deletions Slim/Menu/BrowseLibrary/Releases.pm
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use Slim::Utils::Strings qw(cstring);

# Should we page through results instead of doing one huge bulk request?
use constant MAX_ALBUMS => 1500;
use constant LIST_LIMIT => 980; # SQL parameter limit is 999. This is used to limit the number of album_ids passed in. Leave some room for other searchTags.

my $log = logger('database.info');
my $prefs = preferences('server');
Expand All @@ -16,15 +17,18 @@ my $prefs = preferences('server');
sub _releases {
my ($client, $callback, $args, $pt) = @_;
my @searchTags = $pt->{'searchTags'} ? @{$pt->{'searchTags'}} : ();
my @originalSearchTags = @searchTags;
my $tags = 'lWRSw';
my $library_id = $args->{'library_id'} || $pt->{'library_id'};
my $orderBy = $args->{'orderBy'} || $pt->{'orderBy'};
my $menuMode = $args->{'params'}->{'menu_mode'};
my $menuRoles = $args->{'params'}->{'menu_roles'};
my $search = $args->{'search'};

push @searchTags, "search:$search" if $search && !grep /search:/, @searchTags;
my @originalSearchTags = @searchTags;

# map menuRoles to name for readability
$menuRoles = join(',', map { Slim::Schema::Contributor->roleToType($_) } split(',', $menuRoles || ''));
$menuRoles = join(',', map { Slim::Schema::Contributor->roleToType($_) || $_ } split(',', $menuRoles || ''));

Slim::Schema::Album->addReleaseTypeStrings();

Expand All @@ -34,7 +38,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;
push @searchTags, "role_id:$menuRoles" if $menuRoles && $menuMode ne 'artists';
michaelherger marked this conversation as resolved.
Show resolved Hide resolved

my @artistIds = grep /artist_id:/, @searchTags;
my $artistId;
Expand All @@ -52,10 +56,10 @@ 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, 'role_id:'. ($menuRoles ? $menuRoles : join(',',Slim::Schema::Contributor->contributorRoles)) ] );
$request->execute();
my $releasesRequest = Slim::Control::Request->new( undef, [ $query, 0, MAX_ALBUMS, @searchTags ] );
$releasesRequest->execute();

$log->error($request->getStatusText()) if $request->isStatusError();
$log->error($releasesRequest->getStatusText()) if $releasesRequest->isStatusError();

# compile list of release types and contributions
my %releaseTypes;
Expand All @@ -66,43 +70,43 @@ sub _releases {
my $checkComposerGenres = !( $menuMode && $menuMode ne 'artists' && $menuRoles ) && $prefs->get('showComposerReleasesbyAlbum') == 2;
my $allComposers = ( $menuMode && $menuMode ne 'artists' && $menuRoles ) || $prefs->get('showComposerReleasesbyAlbum') == 1;

foreach (@{ $request->getResult('albums_loop') || [] }) {
foreach my $release (@{ $releasesRequest->getResult('albums_loop') || [] }) {

# map to role's name for readability
$_->{role_ids} = join(',', map { Slim::Schema::Contributor->roleToType($_) } split(',', $_->{role_ids} || ''));
my ($defaultRoles, $userDefinedRoles) = Slim::Schema::Contributor->splitDefaultAndCustomRoles($_->{role_ids});
$release->{role_ids} = join(',', map { Slim::Schema::Contributor->roleToType($_) } split(',', $release->{role_ids} || ''));
my ($defaultRoles, $userDefinedRoles) = Slim::Schema::Contributor->splitDefaultAndCustomRoles($release->{role_ids});

my $genreMatch = undef;
if ( $checkComposerGenres ) {
my $request = Slim::Control::Request->new( undef, [ 'genres', 0, MAX_ALBUMS, 'album_id:' . $_->{id} ] );
$request->execute();
my $genresRequest = Slim::Control::Request->new( undef, [ 'genres', 0, MAX_ALBUMS, 'album_id:' . $release->{id} ] );
$genresRequest->execute();

if ($request->isStatusError()) {
$log->error($request->getStatusText());
if ($genresRequest->isStatusError()) {
$log->error($genresRequest->getStatusText());
}
else {
foreach my $genre (@{$request->getResult('genres_loop')}) {
foreach my $genre (@{$genresRequest->getResult('genres_loop')}) {
last if $genreMatch = Slim::Schema::Genre->isMyClassicalGenre($genre->{genre});
}
}
}

my $addToMainReleases = sub {
$isPrimaryArtist{$_->{id}}++;
$releaseTypes{$_->{release_type}}++;
$albumList{$_->{release_type}} ||= [];
push @{$albumList{$_->{release_type}}}, $_->{id};
$isPrimaryArtist{$release->{id}}++;
$releaseTypes{$release->{release_type}}++;
$albumList{$release->{release_type}} ||= [];
push @{$albumList{$release->{release_type}}}, $release->{id};
};

my $addUserDefinedRoles = sub {
foreach my $role ( split(',', $userDefinedRoles || '') ) {
$contributions{$role} ||= [];
push @{$contributions{$role}}, $_->{id};
push @{$contributions{$role}}, $release->{id};
}
};

if ($_->{compilation}) {
$_->{release_type} = 'COMPILATION';
if ($release->{compilation}) {
$release->{release_type} = 'COMPILATION';
$addToMainReleases->();
# only list default roles outside the compilations if Composer/Conductor
if ( $defaultRoles !~ /COMPOSER|CONDUCTOR/ || $defaultRoles =~ /ARTIST|BAND/ ) {
Expand All @@ -119,7 +123,7 @@ sub _releases {
# Consider this artist the main (album) artist if there's no other, defined album artist
elsif ( $defaultRoles =~ /ARTIST/ ) {
my $albumArtist = Slim::Schema->first('ContributorAlbum', {
album => $_->{id},
album => $release->{id},
role => Slim::Schema::Contributor->typeToRole('ALBUMARTIST'),
contributor => { '!=' => $artistId }
});
Expand All @@ -134,14 +138,14 @@ sub _releases {
# Default roles on other releases
foreach my $role ( grep { $_ ne 'ALBUMARTIST' } split(',', $defaultRoles || '') ) {
# don't list as trackartist, if the artist is albumartist, too
next if $role eq 'TRACKARTIST' && $isPrimaryArtist{$_->{id}};
next if $role eq 'TRACKARTIST' && $isPrimaryArtist{$release->{id}};

if ( $role eq 'COMPOSER' && ( $genreMatch || $allComposers ) ) {
$role = 'COMPOSERALBUM';
}

$contributions{$role} ||= [];
push @{$contributions{$role}}, $_->{id};
push @{$contributions{$role}}, $release->{id};
}

# User-defined roles
Expand All @@ -163,9 +167,10 @@ sub _releases {
} keys %releaseTypes);

foreach my $releaseType (@sortedReleaseTypes) {
my $name = Slim::Schema::Album->releaseTypeName($releaseType, $client);

if ($releaseTypes{uc($releaseType)}) {
my $name = Slim::Schema::Album->releaseTypeName($releaseType, $client);
$name = _limitList($client, $albumList{$releaseType}, $name);
$pt->{'searchTags'} = $releaseType eq 'COMPILATION'
? [@searchTags, 'compilation:1', "album_id:" . join(',', @{$albumList{$releaseType}})]
: [@searchTags, "compilation:0", "release_type:$releaseType", "album_id:" . join(',', @{$albumList{$releaseType}})];
Expand All @@ -174,13 +179,17 @@ sub _releases {
}

if (my $albumIds = delete $contributions{COMPOSERALBUM}) {
my $name = cstring($client, 'COMPOSERALBUMS');
$name = _limitList($client, $albumIds, $name);
$pt->{'searchTags'} = [@searchTags, "role_id:COMPOSER", "album_id:" . join(',', @$albumIds)];
push @items, _createItem(cstring($client, 'COMPOSERALBUMS'), [{%$pt}]);
push @items, _createItem($name, [{%$pt}]);
}

if (my $albumIds = delete $contributions{COMPOSER}) {
my $name = cstring($client, 'COMPOSITIONS');
$name = _limitList($client, $albumIds, $name);
push @items, {
name => cstring($client, 'COMPOSITIONS'),
name => $name,
image => 'html/images/playlists.png',
type => 'playlist',
playlist => \&_tracks,
Expand All @@ -191,24 +200,26 @@ sub _releases {
}

if (my $albumIds = delete $contributions{TRACKARTIST}) {
my $name = cstring($client, 'APPEARANCES');
$name = _limitList($client, $albumIds, $name);
$pt->{'searchTags'} = [@searchTags, "role_id:TRACKARTIST", "album_id:" . join(',', @$albumIds)];
push @items, _createItem(cstring($client, 'APPEARANCES'), [{%$pt}]);
push @items, _createItem($name, [{%$pt}]);
}

foreach my $role (sort keys %contributions) {
my $name = cstring($client, $role) if Slim::Utils::Strings::stringExists($role);
$name = _limitList($client, $contributions{$role}, $name || ucfirst($role));
$pt->{'searchTags'} = [@searchTags, "role_id:$role", "album_id:" . join(',', @{$contributions{$role}})];
push @items, _createItem($name || ucfirst($role), [{%$pt}]);
push @items, _createItem($name, [{%$pt}]);
}

# Add item for Classical Works if the artist has any.
push @searchTags, "role_id:$menuRoles" if $menuRoles && $menuMode && $menuMode ne 'artists';
push @searchTags, "genre_id:" . Slim::Schema::Genre->myClassicalGenreIds() if $checkComposerGenres;
main::INFOLOG && $log->is_info && $log->info("works ($index, $quantity): tags ->", join(', ', @searchTags));
my $requestRef = [ 'works', 0, MAX_ALBUMS, @searchTags ];
my $request = Slim::Control::Request->new( $client ? $client->id() : undef, $requestRef );
$request->execute();
$log->error($request->getStatusText()) if $request->isStatusError();
my $worksRequest = Slim::Control::Request->new( undef, [ 'works', 0, MAX_ALBUMS, @searchTags ] );
$worksRequest->execute();
$log->error($worksRequest->getStatusText()) if $worksRequest->isStatusError();

push @items, {
name => cstring($client, 'WORKS_CLASSICAL'),
Expand All @@ -217,7 +228,7 @@ sub _releases {
playlist => \&_tracks,
url => \&_works,
passthrough => [ { searchTags => [@searchTags, "work_id:-1", "wantMetadata:1", "wantIndex:1"] } ],
} if ( $request->getResult('count') > 1 || ( scalar @items && $request->getResult('count') ) );
} if ( $worksRequest->getResult('count') > 1 || ( scalar @items && $worksRequest->getResult('count') ) );

# restore original search tags
$pt->{'searchTags'} = [@originalSearchTags];
Expand Down Expand Up @@ -277,4 +288,14 @@ sub _createItem {
};
}

sub _limitList {
my ($client, $listRef, $name) = @_;
my $albumCount = scalar @$listRef;
if ( $albumCount > LIST_LIMIT ) {
splice @$listRef, LIST_LIMIT;
$name .= ' ' . cstring($client, 'FIRST_N_ALBUMS', LIST_LIMIT);
}
return $name;
}

1;
7 changes: 7 additions & 0 deletions strings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26924,3 +26924,10 @@ SETUP_MYCLASSICALGENRES_DESC
FR Précisez les genres concernés par les œuvres et les compositeurs. Séparez-les par des virgules.
NL Gebruik deze genres voor werken en albums van componisten. Scheid met komma's.

FIRST_N_ALBUMS
DE (erste %s Alben)
EN (first %s albums)
ES (primeros %s álbumes)
FR (premiers %s albums)
NL (eerste %s albums)