From ead12c6875cdab9f5747e2e65d66e9115c4e0e71 Mon Sep 17 00:00:00 2001 From: Frank Maloschytzki Date: Mon, 30 Jul 2018 14:59:04 +0200 Subject: [PATCH] Add filter "Albums by Composer" --- app/i18n/strings_de.json | 2 + app/i18n/strings_en.json | 2 + app/musiclibrary.js | 8 +- app/plugins/music_service/mpd/index.js | 240 ++++++++++++++++++++++++- 4 files changed, 243 insertions(+), 9 deletions(-) diff --git a/app/i18n/strings_de.json b/app/i18n/strings_de.json index 87006ae9b..914e2a35e 100644 --- a/app/i18n/strings_de.json +++ b/app/i18n/strings_de.json @@ -166,6 +166,8 @@ "FAVOURITES":"Favoriten", "PLAYLISTS":"Wiedergabelisten", "MUSIC_LIBRARY":"Musikbibliothek", + "COMPOSERS":"Komponisten", + "COMPOSER":"Komponist", "ARTISTS":"Interpreten", "ARTIST":"Interpret", "ALBUMS":"Alben", diff --git a/app/i18n/strings_en.json b/app/i18n/strings_en.json index fcd677707..149c19b88 100644 --- a/app/i18n/strings_en.json +++ b/app/i18n/strings_en.json @@ -166,6 +166,8 @@ "FAVOURITES":"Favorites", "PLAYLISTS":"Playlists", "MUSIC_LIBRARY":"Music Library", + "COMPOSERS":"Composers", + "COMPOSER":"Composer", "ARTISTS":"Artists", "ARTIST":"Artist", "ALBUMS":"Albums", diff --git a/app/musiclibrary.js b/app/musiclibrary.js index 235fe795b..e10dc3fae 100755 --- a/app/musiclibrary.js +++ b/app/musiclibrary.js @@ -105,7 +105,8 @@ function CoreMusicLibrary (commandRouter) { } else { self.browseSources = [{albumart: '/albumart?sourceicon=music_service/mpd/favouritesicon.png', name: 'Favourites', uri: 'favourites',plugin_type:'',plugin_name:''}, {albumart: '/albumart?sourceicon=music_service/mpd/playlisticon.png', name: 'Playlists', uri: 'playlists',plugin_type:'music_service',plugin_name:'mpd'}, - {albumart: '/albumart?sourceicon=music_service/mpd/musiclibraryicon.png', name: 'Music Library', uri: 'music-library',plugin_type:'music_service',plugin_name:'mpd'}, + {albumart: '/albumart?sourceicon=music_service/mpd/musiclibraryicon.png', name: 'Music Library', uri: 'music-library',plugin_type:'music_service',plugin_name:'mpd'}, + {albumart: '/albumart?sourceicon=music_service/mpd/artisticon.png',name: 'Composers', uri: 'composers://',plugin_type:'music_service',plugin_name:'mpd'}, {albumart: '/albumart?sourceicon=music_service/mpd/artisticon.png',name: 'Artists', uri: 'artists://',plugin_type:'music_service',plugin_name:'mpd'}, {albumart: '/albumart?sourceicon=music_service/mpd/albumicon.png',name: 'Albums', uri: 'albums://',plugin_type:'music_service',plugin_name:'mpd'}, {albumart: '/albumart?sourceicon=music_service/mpd/genreicon.png',name: 'Genres', uri: 'genres://',plugin_type:'music_service',plugin_name:'mpd'} @@ -489,7 +490,10 @@ CoreMusicLibrary.prototype.updateBrowseSourcesLang = function() { break; case 'music-library': self.browseSources[i].name = self.commandRouter.getI18nString('COMMON.MUSIC_LIBRARY'); - break; + break; + case 'composers://': + self.browseSources[i].name = self.commandRouter.getI18nString('COMMON.COMPOSERS'); + break; case 'artists://': self.browseSources[i].name = self.commandRouter.getI18nString('COMMON.ARTISTS'); break; diff --git a/app/plugins/music_service/mpd/index.js b/app/plugins/music_service/mpd/index.js index ec32ab01c..3d7474da5 100644 --- a/app/plugins/music_service/mpd/index.js +++ b/app/plugins/music_service/mpd/index.js @@ -1,3 +1,5 @@ +/*jshint -W097 */ + 'use strict'; var cacheManager = require('cache-manager'); @@ -350,7 +352,7 @@ ControllerMpd.prototype.sendMpdCommand = function (sCommand, arrayParameters) { if ('error' in respobject) { self.commandRouter.broadcastToastMessage('error', 'Error', respobject.error) - self.sendMpdCommand('clearerror', []) + self.sendMpdCommand('clearerror', []); } return libQ.resolve(respobject); @@ -649,7 +651,7 @@ ControllerMpd.prototype.mpdEstablish = function () { self.checkUSBDrives(); self.listAlbums(); } - }) + }); // Catch and log errors self.clientMpd.on('error', function (err) { @@ -817,7 +819,7 @@ ControllerMpd.prototype.savePlaybackOptions = function (data) { payload:'' } ] - } + }; self.commandRouter.broadcastMessage("openModal", responseData); }, 1000); @@ -1094,7 +1096,7 @@ ControllerMpd.prototype.listPlaylists = function (uri) { } }; if (singleBrowse) { - response.navigation.prev ={'uri': 'music-library'} + response.navigation.prev ={'uri': 'music-library'}; } var promise = self.commandRouter.playListManager.listPlaylist(); promise.then(function (data) { @@ -1208,7 +1210,8 @@ ControllerMpd.prototype.lsInfo = function (uri) { if (singleBrowse && uri === 'music-library') { prev = '/'; var browseSources = [{albumart: '/albumart?sourceicon=music_service/mpd/favouritesicon.png', title: self.commandRouter.getI18nString('COMMON.FAVOURITES'), uri: 'favourites', type: 'title'}, - {albumart: '/albumart?sourceicon=music_service/mpd/playlisticon.png', title: self.commandRouter.getI18nString('COMMON.PLAYLISTS'), uri: 'playlists', type: 'title'}, + {albumart: '/albumart?sourceicon=music_service/mpd/playlisticon.png', title: self.commandRouter.getI18nString('COMMON.PLAYLISTS'), uri: 'playlists', type: 'title'}, + {albumart: '/albumart?sourceicon=music_service/mpd/artisticon.png',title: self.commandRouter.getI18nString('COMMON.COMPOSERS'), uri: 'composers://', type: 'title'}, {albumart: '/albumart?sourceicon=music_service/mpd/artisticon.png',title: self.commandRouter.getI18nString('COMMON.ARTISTS'), uri: 'artists://', type: 'title'}, {albumart: '/albumart?sourceicon=music_service/mpd/albumicon.png',title: self.commandRouter.getI18nString('COMMON.ALBUMS'), uri: 'albums://', type: 'title'}, {albumart: '/albumart?sourceicon=music_service/mpd/genreicon.png',title: self.commandRouter.getI18nString('COMMON.GENRES'), uri: 'genres://', type: 'title'}, @@ -2108,6 +2111,9 @@ ControllerMpd.prototype.explodeUri = function(uri) { defer.resolve(list); }); } + + // do I need an elseif for 'composers://'' here? + else if(uri.startsWith('artists://')) { /* artists://AC%2FDC/Rock%20or%20Bust in service mpd @@ -2904,6 +2910,32 @@ ControllerMpd.prototype.handleBrowseUri = function (curUri, previous) { } } + + +//composers (PW:this one picks up the click on the Composers button) + else if (curUri.startsWith('composers://')) { + console.log('PW: COMPOSERS'); + if (curUri == 'composers://') { + console.log('PW: COMPOSERS-IF - sends off to listComposers function'); + response = self.listComposers(curUri); + console.log('PW: curUri: ' + curUri); + } + else + { + if(splitted.length==3) { //No album name + console.log('PW: COMPOSERS-1st ELSE - sends to listComposer'); + response = self.listComposer(curUri,2,'composers://','composers://'); //Pass back to listComposer + console.log('PW: curUri: ' + curUri); + } + else { //Has album name + console.log('PW: goes into 2nd else'); + response = self.listAlbumSongs(curUri,3,'composers://'+ splitted[2]); //Pass to listAlbumSongs with artist and album name + } + } + } + + + //artists else if (curUri.startsWith('artists://')) { @@ -2943,6 +2975,7 @@ ControllerMpd.prototype.handleBrowseUri = function (curUri, previous) { } + } @@ -3200,6 +3233,192 @@ ControllerMpd.prototype.listAlbumSongs = function (uri,index,previous) { }; + + +/** + * + * list composers + */ +ControllerMpd.prototype.listComposers = function () { + + var self = this; + + var defer = libQ.defer(); + + var response = { + "navigation": { + "lists": [{ + "availableListViews": [ + "list", + "grid" + ], + "items": [ + + ] + }] + } + }; + if (singleBrowse) { + response.navigation.prev ={'uri': 'music-library'} + } + + var cmd = libMpd.cmd; + var artistlist = "composer"; + var artistbegin = "Composer: "; + + if (artistsort) { + artistlist = "albumartist"; + artistbegin = "AlbumArtist: "; + } + + self.clientMpd.sendCommand(cmd("list", [artistlist]), function (err, msg) { //List composers + + if(err) + defer.reject(new Error('Cannot list artist')); + else + { + var splitted=msg.split('\n'); + + for(var i in splitted) + { + + if(splitted[i].startsWith(artistbegin)) { + var artist=splitted[i].substring(artistbegin.length); + + + if(artist!=='') { + var codedArtists=encodeURIComponent(artist); + var albumart=self.getAlbumArt({artist:codedArtists},undefined,'users'); + var item={ + service: "mpd", + type: 'folder', + title: artist, + albumart: albumart, + uri: 'composers://' + codedArtists //PW: when this one is changed, the script hangs when click composer - goes back to throwing broswe error when 'goto function' is added to + } + + response.navigation.lists[0].items.push(item); + } + } + } + defer.resolve(response); + } + }); + return defer.promise; + +}; + +/** + * + * list composer + */ +ControllerMpd.prototype.listComposer = function (curUri,index,previous,uriBegin) { + console.log('PW: ARRIVING IN listComposer function'); + var self = this; + + var defer = libQ.defer(); + + var splitted=curUri.split('/'); + var albumart=self.getAlbumArt({artist:decodeURIComponent(splitted[index])},undefined,'users'); + + var response = { + "navigation": { + "lists": [{ + "title": self.commandRouter.getI18nString('COMMON.ALBUMS') + " (" + decodeURIComponent(splitted[index]) + ")", + "icon": "fa icon", + "availableListViews": [ + "list", + "grid" + ], + "items": [ + + ] + }, + { + "title": self.commandRouter.getI18nString('COMMON.TRACKS') + " (" + decodeURIComponent(splitted[index]) + ")", + "icon": "fa icon", + "availableListViews": [ + "list" + ], + "items": [ + + ] + }], + "prev": { + "uri": previous + }, + info: { + uri: curUri, + title: decodeURIComponent(splitted[index]), + service: 'mpd', + type: 'artist', + albumart: albumart + } + } + }; + + self.mpdReady + .then(function() { + var artist=decodeURIComponent(splitted[index]); + var VA = 0; + var cmd = libMpd.cmd; + var safeArtist = artist.replace(/"/g,'\\"'); + console.log('PW: artist:' + artist); + console.log('PW: safeArtist:' + safeArtist); + console.log('PW: MPD READY THEN FUNCTION BEGINS'); + if (uriBegin === 'genres://') { + console.log('PW: mpdReady IF'); + var genre = decodeURIComponent(splitted[2]); + var safeGenre = genre.replace(/"/g,'\\"'); + var findartist = "find artist \"" + safeArtist + "\" genre \"" + safeGenre + "\" "; + } + + else { + if (compilation.indexOf(artist)>-1) { //artist is in compilation array so use albumartist + console.log('PW: mpdReady first else'); + var findartist = "find albumartist \"" + safeArtist + "\""; + VA = 1; + } + else { + //artist is NOT in compilation array so use artist or albumartist + if (artistsort) { //Fix - now set by artistsort variable + console.log('PW: mpdReady 2nd else - artistsort'); + var findartist = "find albumartist \"" + safeArtist + "\""; + } + else { + console.log('PW: mpdReady 3rd else - findartist'); + var findartist = "find artist \"" + safeArtist + "\""; + } + } + } + + self.clientMpd.sendCommand(cmd(findartist, []), function (err, msg) { //get data (msg) + + if(msg=='') { //If there is no data (msg) get data first, else just parseListAlbum + + self.clientMpd.sendCommand(cmd(findartist, []), function (err, msg) { + console.log('PW: goto parseListAlbum IF'); + self.parseListAlbum(err,msg,defer,response,uriBegin,VA); // do I need to create a special parseListAlbum function for composers? + + }); + } + + else { + console.log('PW: goto parseListAlbum ELSE'); + self.parseListAlbum(err,msg,defer,response,uriBegin,VA); + } + }); + }); + + return defer.promise; + +}; + + + + + + /** * * list artists @@ -3373,10 +3592,12 @@ ControllerMpd.prototype.listArtist = function (curUri,index,previous,uriBegin) { ControllerMpd.prototype.parseListAlbum= function(err,msg,defer,response,uriBegin,VA) { + console.log('PW: ARRIVING @ parseListAlbum') var self=this; var list = []; var albums=[],albumarts=[]; if (msg) { + console.log('PW: parseListAlbum IF - inside msg'); var path; @@ -3423,6 +3644,7 @@ ControllerMpd.prototype.parseListAlbum= function(err,msg,defer,response,uriBegin uri: 'music-library/'+path }); +console.log('PW: arriving at blue block'); // The first expression in the following "if" statement prevents dummy-albums from being // created for orphaned tracks (tracks without an album). Such dummy-albums aren't required, // as orphaned tracks remain accessible from the tracks-list. @@ -3462,6 +3684,7 @@ ControllerMpd.prototype.parseListAlbum= function(err,msg,defer,response,uriBegin } else { + console.log('PW: parseListAlbum ELSE '); self.logger.info(err); defer.reject(new Error()); } @@ -3746,8 +3969,11 @@ ControllerMpd.prototype.prefetch = function (trackBlock) { }); } + ControllerMpd.prototype.goto=function(data){ - if (data.type=='artist') { + if (data.type=='composer') { + return this.listComposer('composers://'+encodeURIComponent(data.value),2,'', 'albums://'+encodeURIComponent(data.value)+'/') + } else if (data.type=='artist') { return this.listArtist('artists://'+encodeURIComponent(data.value),2,'', 'albums://'+encodeURIComponent(data.value)+'/') } else if (data.type=='album'){ return this.listAlbumSongs("albums://"+encodeURIComponent(data.artist)+'/'+encodeURIComponent(data.album),2,'albums://'+encodeURIComponent(data.artist)+'/'); @@ -3849,7 +4075,7 @@ ControllerMpd.prototype.saveMusicLibraryOptions=function(data){ ControllerMpd.prototype.dsdVolume=function(){ var self = this; - + if (dsd_autovolume) { self.logger.info('Setting Volume to 100 automatically for DSD') self.commandRouter.volumiosetvolume(100);