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

Album sorting by role #1323

Open
wants to merge 1 commit into
base: public/9.1
Choose a base branch
from
Open
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
53 changes: 44 additions & 9 deletions Slim/Control/Queries.pm
Original file line number Diff line number Diff line change
Expand Up @@ -292,16 +292,16 @@ sub albumsQuery {
my $releaseType = $request->getParam('release_type');
my $libraryID = Slim::Music::VirtualLibraries->getRealId($request->getParam('library_id'));
my $year = $request->getParam('year');
my $sort = $request->getParam('sort') || ($roleID ? 'artistalbum' : 'album');
# a work_id of -1 would mean "all works"
my $work = $request->getParam('work_id');
my $work = $request->getParam('work_id');
my $composerID = $request->getParam('composer_id');
my $fromSearch = $request->getParam('from_search');
my $sort = $request->getParam('sort') || ($roleID && !$work ? 'artistalbum' : 'album');

my $ignoreNewAlbumsCache = $search || $compilation || $contributorID || $genreID || $trackID || $albumID || $year || Slim::Music::Import->stillScanning();

# FIXME: missing genrealbum, genreartistalbum
if ($request->paramNotOneOfIfDefined($sort, ['new', 'changed', 'album', 'artflow', 'artistalbum', 'yearalbum', 'yearartistalbum', 'random' ])) {
if ($request->paramNotOneOfIfDefined($sort, ['new', 'changed', 'album', 'artflow', 'artistalbum', 'yearalbum', 'yearartistalbum', 'random', Slim::Schema::Contributor->contributorRoleIds() ])) {
$request->setStatusBadParams();
return;
}
Expand Down Expand Up @@ -579,6 +579,22 @@ sub albumsQuery {
}
}

if ( Slim::Schema::Contributor->roleToType($sort) ) {
$sql .= 'JOIN tracks ON tracks.album = albums.id ' unless $sql =~ /JOIN tracks/;
$sql .= "LEFT JOIN contributor_track AS rolesort_track ON rolesort_track.track = tracks.id AND rolesort_track.role = $sort ";
$sql .= 'LEFT JOIN contributors AS rolesort ON rolesort.id = rolesort_track.contributor ';
my $col = 'GROUP_CONCAT(DISTINCT rolesort.name)';
$c->{$col} = 1;
$as->{$col} = 'rolesort.name';
$col = 'GROUP_CONCAT(DISTINCT rolesort.id)';
$c->{$col} = 1;
$as->{$col} = 'rolesort.id';
$col = 'GROUP_CONCAT(DISTINCT rolesort.namesort)';
$c->{$col} = 1;
$as->{$col} = 'rolesort.namesort';
$order_by = "CASE WHEN GROUP_CONCAT(DISTINCT rolesort.namesort) IS NULL THEN 1 ELSE 0 END, GROUP_CONCAT(DISTINCT rolesort.namesort) $collate, " . $order_by;
$page_key = "COALESCE(SUBSTR(rolesort.namesort,1,1), '-')";
}

if ( $tags =~ /l/ ) {
# title/disc/discc is needed to construct (N of M) title
Expand Down Expand Up @@ -805,11 +821,13 @@ sub albumsQuery {
utf8::decode( $c->{'composer.name'} ) if exists $c->{'composer.name'};
utf8::decode( $c->{'tracks.performance'} ) if exists $c->{'tracks.performance'};
utf8::decode( $c->{'contributors.name'} ) if exists $c->{'contributors.name'};
utf8::decode( $c->{'rolesort.name'} ) if exists $c->{'rolesort.name'};
$request->addResultLoop($loopname, $chunkCount, 'id', $c->{'albums.id'});
$request->addResultLoopIfValueDefined($loopname, $chunkCount, 'work_id', $c->{'tracks.work'});
$request->addResultLoopIfValueDefined($loopname, $chunkCount, 'work_name', $c->{'works.title'});
$request->addResultLoopIfValueDefined($loopname, $chunkCount, 'composer', $c->{'composer.name'});
$request->addResultLoop($loopname, $chunkCount, 'performance', $c->{'tracks.performance'}||"");
$request->addResultLoopIfValueDefined($loopname, $chunkCount, 'rolesort_name', $c->{'rolesort.name'});

my $favoritesUrl = $work
? sprintf('db:album.title=%s&contributor.name=%s&work.title=%s&composer.name=%s&track.performance=%s',
Expand Down Expand Up @@ -872,7 +890,10 @@ sub albumsQuery {
if ($tags =~ /s/) {
#FIXME: see if multiple char textkey is doable for year/genre sort
my $textKey;
if ($sort eq 'artflow' || $sort eq 'artistalbum') {
if (Slim::Schema::Contributor->roleToType($sort)) {
utf8::decode( $c->{'rolesort.namesort'} ) if exists $c->{'rolesort.namesort'};
$textKey = $c->{'rolesort.namesort'} ? substr $c->{'rolesort.namesort'}, 0, 1 : '-';
} elsif ($sort eq 'artflow' || $sort eq 'artistalbum') {
utf8::decode( $c->{'contributors.namesort'} ) if exists $c->{'contributors.namesort'};
$textKey = substr $c->{'contributors.namesort'}, 0, 1;
} elsif ( $sort eq 'album' ) {
Expand Down Expand Up @@ -911,6 +932,12 @@ sub albumsQuery {
unshift @artists, $c->{'contributors.name'} if $c->{'contributors.name'};
unshift @artistIds, $c->{'albums.contributor'} if $c->{'albums.contributor'};
}
# if role_sort specified, put the role artist at the top of the list
if ($c->{'rolesort.name'}) {
unshift @artists, $c->{'rolesort.name'} if $c->{'rolesort.name'};
unshift @artistIds, $c->{'rolesort.id'} if $c->{'rolesort.id'};
}

@artists = Slim::Utils::Misc::uniq(@artists);
@artistIds = Slim::Utils::Misc::uniq(@artistIds);

Expand Down Expand Up @@ -3172,6 +3199,7 @@ sub rolesQuery {
my $albumID = $request->getParam('album_id');
my $trackID = $request->getParam('track_id');
my $workID = $request->getParam('work_id');
my $genreID = $request->getParam('genre_id');
my $libraryID = Slim::Music::VirtualLibraries->getRealId($request->getParam('library_id'));
my $tags = $request->getParam('tags') || '';

Expand Down Expand Up @@ -3209,12 +3237,13 @@ sub rolesQuery {
push @{$p}, $libraryID;
}

if (defined $albumID) {
push @{$w}, 'contributor_album.album = ?';
push @{$p}, $albumID;
if ( defined $albumID ) {
# remove anything nasty that might have crept into the parameter
$albumID = join(',', grep /^\d+$/, split(',', $albumID));
push @{$w}, "contributor_album.album IN ($albumID)";
}

if (defined $year || defined $workID) {
if (defined $year || defined $workID || defined $genreID) {
$sql .= 'JOIN contributor_track ON contributors.id = contributor_track.contributor ';
$sql .= 'JOIN tracks ON tracks.id = contributor_track.track ';

Expand All @@ -3230,6 +3259,12 @@ sub rolesQuery {
push @{$p}, $workID;
}
}
if (defined $genreID) {
my @genreIDs = split(/,/, $genreID);
$sql .= 'JOIN genre_track ON genre_track.track = tracks.id ';
push @{$w}, 'genre_track.genre IN (' . join(', ', map {'?'} @genreIDs) . ')';
push @{$p}, @genreIDs;
}
}
}

Expand All @@ -3242,7 +3277,7 @@ sub rolesQuery {

my $dbh = Slim::Schema->dbh;

if (defined $trackID) {
if (defined $trackID || defined $workID || defined $genreID) {
$sql = sprintf($sql, 'DISTINCT contributor_track.role');
} else {
$sql = sprintf($sql, 'DISTINCT contributor_album.role');
Expand Down
26 changes: 17 additions & 9 deletions Slim/Menu/BrowseLibrary.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1389,14 +1389,6 @@ sub _years {
);
}

my %orderByList = (
ALBUM => 'album',
SORT_YEARALBUM => 'yearalbum',
SORT_YEARARTISTALBUM => 'yearartistalbum',
SORT_ARTISTALBUM => 'artistalbum',
SORT_ARTISTYEARALBUM => 'artflow',
);

my %mapArtistOrders = (
album => 'album',
yearalbum => 'yearalbum',
Expand Down Expand Up @@ -1473,13 +1465,21 @@ sub _albums {

$tags .= 'y' unless grep {/^year:/} @searchTags;

my %orderByList = (
ALBUM => 'album',
SORT_YEARALBUM => 'yearalbum',
SORT_YEARARTISTALBUM => 'yearartistalbum',
SORT_ARTISTALBUM => 'artistalbum',
SORT_ARTISTYEARALBUM => 'artflow',
);

# Remove artist from sort order if selection includes artist
if ($sort && $sort =~ /sort:(.*)/) {
my $mapped;
if ($artistId && ($mapped = $mapArtistOrders{$1})) {
$sort = 'sort:' . $mapped;
}
$sort = undef unless grep {$_ eq $1} ('new', 'changed', 'random', values %orderByList);
$sort = undef unless grep {$_ eq $1} ('new', 'changed', 'random', values %orderByList, Slim::Schema::Contributor::contributorRoleIds());
}

# Under certain circumstances (random albums in web UI or with remote streams) we are only
Expand All @@ -1504,6 +1504,7 @@ sub _albums {
my $results = shift;
my $items = $results->{'albums_loop'};
$remote_library ||= $args->{'remote_library'};
my @albumList;

foreach (@$items) {
$_->{'name'} = $_->{'composer'} ? $_->{'composer'} . cstring($client, 'COLON') . ' ' : '';
Expand Down Expand Up @@ -1547,6 +1548,7 @@ sub _albums {
$_->{'image'} = _proxiedImageUrl($_, $remote_library);
delete $_->{'artwork_track_id'};
}
push @albumList, $_->{'id'};
}

my $extra;
Expand Down Expand Up @@ -1749,6 +1751,12 @@ sub _albums {
$actions{'playall'} = $actions{'play'};
$actions{'addall'} = $actions{'add'};

my $rolesRequest = Slim::Control::Request->new( undef, [ 'roles', 0, 1000, "tags:t", "album_id:" . join(',', @albumList) ] );
$rolesRequest->execute();
foreach my $role (@{ $rolesRequest->getResult('roles_loop') || [] }) {
$orderByList{$role->{'role_name'}} = $role->{'role_id'} unless $role->{'role_name'} =~ /^ARTIST$|^ALBUMARTIST$/;
}

my $result = {
items => $items,
actions => \%actions,
Expand Down