diff --git a/HTML/Default/status_list.html b/HTML/Default/status_list.html index bd06841c14..66531cf347 100644 --- a/HTML/Default/status_list.html +++ b/HTML/Default/status_list.html @@ -50,7 +50,12 @@ [% IF item.includeAlbum && item.album.defined && item.album != noAlbum %]
[% IF item.album_id %] - [% item.album | html %] + [% IF item.version; + album_and_version = item.album _ ' [' _ item.version _ ']' ; + ELSE; + album_and_version = item.album; + END %] + [% album_and_version | html %] [% ELSE %][% item.album | html %][% END %]
[% END %] diff --git a/HTML/EN/html/SqueezeJS/Base.js b/HTML/EN/html/SqueezeJS/Base.js index 67e2ed21f6..a75b821b88 100644 --- a/HTML/EN/html/SqueezeJS/Base.js +++ b/HTML/EN/html/SqueezeJS/Base.js @@ -726,6 +726,16 @@ SqueezeJS.SonginfoParser = { }); }, + version : function(result, noLink){ + var version; + + if (result.playlist_tracks > 0 && result.playlist_loop[0].version) { + version = result.playlist_loop[0].version; + } + + return version; + }, + bitrate : function(result){ var bitrate = ''; diff --git a/HTML/EN/html/SqueezeJS/UI.js b/HTML/EN/html/SqueezeJS/UI.js index 51772638fa..dd4c723490 100644 --- a/HTML/EN/html/SqueezeJS/UI.js +++ b/HTML/EN/html/SqueezeJS/UI.js @@ -1559,14 +1559,16 @@ SqueezeJS.UI.CompoundTitle = Ext.extend(SqueezeJS.UI.Component, { SqueezeJS.UI.Album = Ext.extend(SqueezeJS.UI.Component, { onPlayerStateChange : function(result){ var year = SqueezeJS.SonginfoParser.year(result, this.noLink); + var version = SqueezeJS.SonginfoParser.version(result, this.noLink); this.el.update(SqueezeJS.SonginfoParser.album(result, this.noLink) - + (year ? ' (' + year + ')' : '')); + + (year ? ' (' + year + ')' : '') + (version ? ' [' + version + ']' : '') ); } }); SqueezeJS.UI.AlbumTitle = Ext.extend(SqueezeJS.UI.Component, { onPlayerStateChange : function(result){ - this.el.update(SqueezeJS.SonginfoParser.album(result, this.noLink)); + var version = SqueezeJS.SonginfoParser.version(result, this.noLink); + this.el.update(SqueezeJS.SonginfoParser.album(result, this.noLink) + (version ? ' [' + version + ']' : '')); } }); diff --git a/SQL/SQLite/schema_27_down.sql b/SQL/SQLite/schema_27_down.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/SQL/SQLite/schema_27_up.sql b/SQL/SQLite/schema_27_up.sql new file mode 100644 index 0000000000..3e3cd9d3d2 --- /dev/null +++ b/SQL/SQLite/schema_27_up.sql @@ -0,0 +1,23 @@ +ALTER TABLE albums ADD version blob; +DROP INDEX IF EXISTS albumsLabelIndex; +CREATE INDEX albumsLabelIndex ON albums (label); +DROP TABLE IF EXISTS labels; +CREATE TABLE labels ( + id integer PRIMARY KEY AUTOINCREMENT, + name blob, + namesort text, + namesearch text +); +DROP TABLE IF EXISTS label_album; +CREATE TABLE label_album ( + label int(10), + album int(10), + PRIMARY KEY (label,album), + FOREIGN KEY (`album`) REFERENCES `albums` (`id`) ON DELETE CASCADE, + FOREIGN KEY (`label`) REFERENCES `labels` (`id`) ON DELETE CASCADE +); +DROP INDEX IF EXISTS label_albumAlbumIndex; +CREATE INDEX label_albumAlbumIndex ON label_album (album); +DROP INDEX IF EXISTS label_albumLabelIndex; +CREATE INDEX label_albumLabelIndex ON label_album (label); + diff --git a/SQL/mysql/schema_27_down.sql b/SQL/mysql/schema_27_down.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/SQL/mysql/schema_27_up.sql b/SQL/mysql/schema_27_up.sql new file mode 100644 index 0000000000..3e3cd9d3d2 --- /dev/null +++ b/SQL/mysql/schema_27_up.sql @@ -0,0 +1,23 @@ +ALTER TABLE albums ADD version blob; +DROP INDEX IF EXISTS albumsLabelIndex; +CREATE INDEX albumsLabelIndex ON albums (label); +DROP TABLE IF EXISTS labels; +CREATE TABLE labels ( + id integer PRIMARY KEY AUTOINCREMENT, + name blob, + namesort text, + namesearch text +); +DROP TABLE IF EXISTS label_album; +CREATE TABLE label_album ( + label int(10), + album int(10), + PRIMARY KEY (label,album), + FOREIGN KEY (`album`) REFERENCES `albums` (`id`) ON DELETE CASCADE, + FOREIGN KEY (`label`) REFERENCES `labels` (`id`) ON DELETE CASCADE +); +DROP INDEX IF EXISTS label_albumAlbumIndex; +CREATE INDEX label_albumAlbumIndex ON label_album (album); +DROP INDEX IF EXISTS label_albumLabelIndex; +CREATE INDEX label_albumLabelIndex ON label_album (label); + diff --git a/Slim/Control/Commands.pm b/Slim/Control/Commands.pm index a3fbb74837..42efac8ccf 100644 --- a/Slim/Control/Commands.pm +++ b/Slim/Control/Commands.pm @@ -3598,6 +3598,7 @@ sub _playlistXtracksCommand_parseDbItem { my $lcClass = lc($class); $classes{Album} = Slim::Schema->search('Album', { titlesearch => $albumObj->titlesearch, + version => $albumObj->version, "$lcClass.$key" => $value, },{ prefetch => $lcClass diff --git a/Slim/Control/Queries.pm b/Slim/Control/Queries.pm index 6ce452bf1a..64c9dfd6b9 100644 --- a/Slim/Control/Queries.pm +++ b/Slim/Control/Queries.pm @@ -582,7 +582,7 @@ sub albumsQuery { if ( $tags =~ /l/ ) { # title/disc/discc is needed to construct (N of M) title - map { $c->{$_} = 1 } qw(albums.title albums.disc albums.discc); + map { $c->{$_} = 1 } qw(albums.title albums.version albums.disc albums.discc); } if ( $tags =~ /y/ ) { @@ -806,6 +806,7 @@ sub albumsQuery { while ( $sth->fetch ) { utf8::decode( $c->{'albums.title'} ) if exists $c->{'albums.title'}; + utf8::decode( $c->{'albums.version'} ) if exists $c->{'albums.version'}; utf8::decode( $c->{'works.title'} ) if exists $c->{'works.title'}; utf8::decode( $c->{'composer.name'} ) if exists $c->{'composer.name'}; utf8::decode( $c->{'tracks.performance'} ) if exists $c->{'tracks.performance'}; @@ -816,23 +817,31 @@ sub albumsQuery { $request->addResultLoopIfValueDefined($loopname, $chunkCount, 'composer', $c->{'composer.name'}); $request->addResultLoop($loopname, $chunkCount, 'performance', $c->{'tracks.performance'}||""); - my $favoritesUrl = $work - ? sprintf('db:album.title=%s&contributor.name=%s&work.title=%s&composer.name=%s&track.performance=%s', - URI::Escape::uri_escape_utf8($c->{'albums.title'}), URI::Escape::uri_escape_utf8($c->{'contributors.name'}), - URI::Escape::uri_escape_utf8($c->{'works.title'}), URI::Escape::uri_escape_utf8($c->{'composer.name'}), URI::Escape::uri_escape_utf8($c->{'tracks.performance'})) - : sprintf('db:album.title=%s&contributor.name=%s', URI::Escape::uri_escape_utf8($c->{'albums.title'}), URI::Escape::uri_escape_utf8($c->{'contributors.name'})); + my $favoritesUrl = sprintf('db:album.title=%s', URI::Escape::uri_escape_utf8($c->{'albums.title'})); + if ( $c->{'albums.version'} ) { + $favoritesUrl .= sprintf('&album.version=%s', URI::Escape::uri_escape_utf8($c->{'albums.version'})); + } + $favoritesUrl .= $work + ? sprintf('&contributor.name=%s&work.title=%s&composer.name=%s&track.performance=%s', + URI::Escape::uri_escape_utf8($c->{'contributors.name'}), URI::Escape::uri_escape_utf8($c->{'works.title'}), + URI::Escape::uri_escape_utf8($c->{'composer.name'}), URI::Escape::uri_escape_utf8($c->{'tracks.performance'})) + : sprintf('&contributor.name=%s', URI::Escape::uri_escape_utf8($c->{'contributors.name'})); # even if we have an extid, it cannot be used when we're dealing here with a work, which is a subset of the album. $request->addResultLoop($loopname, $chunkCount, 'favorites_url', $c->{'albums.extid'} && !$c->{'tracks.work'} ? $c->{'albums.extid'} : $favoritesUrl); my $favoritesTitle = $c->{'albums.title'}; + $favoritesTitle .= ' [' . $c->{'albums.version'} . ']' if $c->{'albums.version'}; if ( $work ) { $favoritesTitle = $c->{'composer.name'} ? $c->{'composer.name'} . cstring($client, 'COLON') . ' ' : ''; $favoritesTitle .= $c->{'works.title'} . ' ('; $favoritesTitle .= "$c->{'tracks.performance'} " if $c->{'tracks.performance'}; - $favoritesTitle .= cstring($client,'FROM') . ' ' . $c->{'albums.title'} . ')'; + $favoritesTitle .= cstring($client,'FROM') . ' ' . $c->{'albums.title'}; + $favoritesTitle .= ' [' . $c->{'albums.version'} . ']' if $c->{'albums.version'}; + $favoritesTitle .= ')'; } $request->addResultLoop($loopname, $chunkCount, 'favorites_title', $favoritesTitle); $tags =~ /l/ && $request->addResultLoop($loopname, $chunkCount, 'album', $construct_title->()); + $tags =~ /l/ && $request->addResultLoop($loopname, $chunkCount, 'version', $c->{'albums.version'}); $tags =~ /y/ && $request->addResultLoopIfValueDefined($loopname, $chunkCount, 'year', $c->{'albums.year'}); if ($tags =~ /j/) { my $albumCover = $c->{'tracks.coverid'} ? $c->{'tracks.coverid'} : $c->{'albums.artwork'}; @@ -5723,6 +5732,12 @@ sub _songDataFromHash { } } + # Special case for l (albums.title), return albums.version as well + elsif ( $tag eq 'l' ) { + $returnHash{'album'} = $res->{'albums.title'} if $res->{'albums.title'}; + $returnHash{'version'} = $res->{'albums.version'} if $res->{'albums.version'}; + } + # Special case for b (work), return work_id as well elsif ( $tag eq 'b' ) { $returnHash{'work'} = $res->{'works.title'} if $res->{'works.title'}; @@ -6454,6 +6469,7 @@ sub _getTagDataForTracks { $tags =~ /l/ && do { $join_albums->(); $c->{'albums.title'} = 1; + $c->{'albums.version'} = 1; }; $tags =~ /q/ && do { @@ -6580,6 +6596,7 @@ sub _getTagDataForTracks { utf8::decode( $c->{'works.title'} ) if exists $c->{'works.title'}; utf8::decode( $c->{'tracks.lyrics'} ) if exists $c->{'tracks.lyrics'}; utf8::decode( $c->{'albums.title'} ) if exists $c->{'albums.title'}; + utf8::decode( $c->{'albums.version'} ) if exists $c->{'albums.version'}; utf8::decode( $c->{'contributors.name'} ) if exists $c->{'contributors.name'}; utf8::decode( $c->{'genres.name'} ) if exists $c->{'genres.name'}; utf8::decode( $c->{'comments.value'} ) if exists $c->{'comments.value'}; diff --git a/Slim/Menu/AlbumInfo.pm b/Slim/Menu/AlbumInfo.pm index 38a5776a50..b0469f7b60 100644 --- a/Slim/Menu/AlbumInfo.pm +++ b/Slim/Menu/AlbumInfo.pm @@ -367,6 +367,7 @@ sub infoAlbum { my $item; my $library_id = $filter->{library_id} || Slim::Music::VirtualLibraries->getLibraryIdForClient($client); my $albumName = $album->title; + $albumName .= ' [' . $album->version . ']' if $album->version; my $totalAlbumTracks = $album->tracks->count; if ( $albumName && $totalAlbumTracks > $filter->{track_count} ) { diff --git a/Slim/Menu/BrowseLibrary.pm b/Slim/Menu/BrowseLibrary.pm index 95286a0e94..97a138a2e1 100644 --- a/Slim/Menu/BrowseLibrary.pm +++ b/Slim/Menu/BrowseLibrary.pm @@ -1534,8 +1534,9 @@ sub _albums { $_->{'name'} .= "$_->{'performance'} " if $_->{'performance'}; $_->{'name'} .= cstring($client,'FROM') . ' '; } - $_->{'name'} .= $_->{'album'}; - $_->{'name'} .= ')' if $_->{'work_id'}; + $_->{'name'} .= $_->{'album'}; + $_->{'name'} .= ' [' . $_->{'version'} . ']' if $_->{'version'}; + $_->{'name'} .= ')' if $_->{'work_id'}; $_->{'image'} = 'music/' . $_->{'artwork_track_id'} . '/cover' if $_->{'artwork_track_id'}; $_->{'image'} ||= $_->{'artwork_url'} if $_->{'artwork_url'}; $_->{'type'} = 'playlist'; diff --git a/Slim/Schema.pm b/Slim/Schema.pm index 9b7774b544..a5c4b87d48 100644 --- a/Slim/Schema.pm +++ b/Slim/Schema.pm @@ -901,6 +901,7 @@ sub _objForDbUrl { if ($term =~ /(.*)=(.*)/) { my $key = $1; my $value = Slim::Utils::Misc::unescape($2); + $key = 'me.version' if $key eq 'album.version'; if (utf8::is_utf8($value)) { utf8::decode($value); @@ -937,6 +938,7 @@ sub _createOrUpdateAlbum { # Now handle Album creation my $title = $attributes->{ALBUM}; + my $version = $attributes->{VERSION}; my $disc = $attributes->{DISC}; my $discc = $attributes->{DISCC}; # Bug 10583 - Also check for MusicBrainz Album Id @@ -1079,6 +1081,7 @@ sub _createOrUpdateAlbum { ( $lastAlbum->{_dirname} && $lastAlbum->{_dirname} eq $basename && $lastAlbum->{title} eq $title + && $lastAlbum->{version} eq $version && (!$checkDisc || (($disc || '') eq ($lastAlbum->{disc} || 0))) ) ) { @@ -1103,6 +1106,13 @@ sub _createOrUpdateAlbum { push @{$search}, 'albums.title = ?'; push @{$values}, $title; + if ($version) { + push @{$search}, 'albums.version = ?'; + push @{$values}, $version; + } else { + push @{$search}, 'albums.version IS NULL'; + } + if (defined $brainzId) { push @{$search}, 'albums.musicbrainz_id = ?'; push @{$values}, $brainzId; @@ -1281,6 +1291,8 @@ sub _createOrUpdateAlbum { $albumHash->{release_type} = Slim::Utils::Text::ignoreCase( $releaseType || 'album' ); Slim::Schema::Album->addReleaseTypeMap($releaseType, $albumHash->{release_type}); + $albumHash->{version} = $attributes->{VERSION}; + # Bug 3255 - add album contributor which is either VA or the primary artist, used for sort by artist $vaObjId ||= $self->variousArtistsObject->id; @@ -1547,7 +1559,6 @@ sub _createWork { sub _createTrack { my ($self, $columnValueHash, $persistentColumnValueHash, $source) = @_; - # Create the track # Using native DBI here to improve performance during scanning my $dbh = $self->dbh; @@ -2847,6 +2858,8 @@ sub _preCheckAttributes { # We also need these in _postCheckAttributes, but they should be set during create() $deferredAttributes->{'DISC'} = $attributes->{'DISC'} if $attributes->{'DISC'}; + $deferredAttributes->{'VERSION'} = $attributes->{'VERSION'} || undef; + # thumb has gone away, since we have GD resizing. delete $attributes->{'THUMB'}; diff --git a/Slim/Schema/Album.pm b/Slim/Schema/Album.pm index 2ee7f52ba5..68600c3de4 100644 --- a/Slim/Schema/Album.pm +++ b/Slim/Schema/Album.pm @@ -36,6 +36,9 @@ my $log = logger('database.info'); musicbrainz_id release_type extid + subtitle + label + version ), title => { accessor => undef() }); $class->set_primary_key('id');