diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 603ed73b..23ea6ee1 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -1,6 +1,6 @@ /*----------------------------------------------------------------------- -TypeScript v4.6.2.1 zur Steuerung des SONOFF NSPanel mit dem ioBroker by @Armilar / @TT-Tom / @ticaki / @Britzelpuf / @Sternmiere / @ravenS0ne -- abgestimmt auf TFT 55 / v4.6.2 / BerryDriver 9 / Tasmota 14.5.0 +TypeScript v4.7.1.2 zur Steuerung des SONOFF NSPanel mit dem ioBroker by @Armilar / @TT-Tom / @ticaki / @Britzelpuf / @Sternmiere / @ravenS0ne +- abgestimmt auf TFT 56 / v4.7.1 / BerryDriver 9 / Tasmota 14.5.0 @joBr99 Projekt: https://github.com/joBr99/nspanel-lovelace-ui/tree/main/ioBroker NsPanelTs.ts (dieses TypeScript in ioBroker) Stable: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/NsPanelTs.ts icon_mapping.ts: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/icon_mapping.ts (TypeScript muss in global liegen) @@ -53,6 +53,13 @@ ReleaseNotes: - 01.04.2025 - v4.6.1 TFT 55 / 4.6.1 - Add Some Adapter Functions - 01.04.2025 - v4.6.2 TFT 55 / 4.6.2 - Add cardSchedule - 01.04.2025 - v4.6.2.1 Add startup TFT-Release directly from NSPanel-TFT, Comparison between version number and release removed + - 02.04.2025 - v4.7.0 TFT 56 / 4.7.0 - Fix cardSchedule + - 10.04.2025 - v4.7.0.2 Add cardMedia "Music Player Daemon (MPD)" (One-Instance-Player with Playlists, Tracklists, Shuffle, Repeat, Seek/Crossfade); mpd.X - Instance required + - 10.04.2025 - v4.7.0.3 Fix cardMedia "Music Player Daemon (MPD)" shuffle with repeat and repeat with repeat/single + - 10.04.2025 - v4.7.1 TFT 56 / 4.7.1 - Add Player Icon-Logos logo-alexa, logo-spotify, logo-dlna, logo-sonos, logo-mpd, logo-volumios, logo-bose + - 10.04.2025 - v4.7.1.1 Add parameter playerMediaIcon to cardMedia + - 12.04.2025 - v4.7.1.2 Fix Play/Pause in MediaPlayers + - 13.04.2025 - v4.7.1.2 TFT 56 / 4.7.1 (US-P and US-L) Todo: - XX.12.2024 - v5.0.0 ioBroker Adapter @@ -155,10 +162,10 @@ Install/Upgrades in Konsole: Tasmota BerryDriver Install: Backlog UrlFetch https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1 Tasmota BerryDriver Update: Backlog UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1 - TFT EU STABLE Version: FlashNextion http://nspanel.de/nspanel-v4.6.2.tft + TFT EU STABLE Version: FlashNextion http://nspanel.de/nspanel-v4.7.1.tft - TFT US-L STABLE Version: FlashNextion http://nspanel.de/nspanel-us-l-v4.6.0.tft - TFT US-P STABLE Version: FlashNextion http://nspanel.de/nspanel-us-p-v4.6.0.tft + TFT US-L STABLE Version: FlashNextion http://nspanel.de/nspanel-us-l-v4.7.1.tft + TFT US-P STABLE Version: FlashNextion http://nspanel.de/nspanel-us-p-v4.7.1.tft --------------------------------------------------------------------------------------- */ @@ -941,9 +948,9 @@ export const config: Config = { // _________________________________ DE: Ab hier keine Konfiguration mehr _____________________________________ // _________________________________ EN: No more configuration from here _____________________________________ -const scriptVersion: string = 'v4.6.2.1'; -const tft_version: string = 'v4.6.2'; -const desired_display_firmware_version = 55; +const scriptVersion: string = 'v4.7.1.2'; +const tft_version: string = 'v4.7.1'; +const desired_display_firmware_version = 56; const berry_driver_version = 9; const tasmotaOtaUrl: string = 'http://ota.tasmota.com/tasmota32/release/'; @@ -6896,6 +6903,46 @@ async function createAutoMediaAlias (id: string, mediaDevice: string, adapterPla } } } + break + case 'mpd.0.': + case 'mpd.1.': + case 'mpd.2.': + case 'mpd.3.': + case 'mpd.4.': + case 'mpd.5.': + case 'mpd.6.': + case 'mpd.7.': + case 'mpd.8.': + case 'mpd.9.': + { + if (existsObject(id) == false) { + log('MPD Alias ' + id + ' does not exist - will be created now', 'info'); + + const dpPath: string = adapterPlayerInstance; + + try { + setObject(id, {_id: id, type: 'channel', common: {role: 'media', name: 'media'}, native: {}}); + await createAliasAsync(id + '.ACTUAL', dpPath + 'setvol', true, {type: 'number', role: 'value.volume', name: 'ACTUAL'}); + await createAliasAsync(id + '.ALBUM', dpPath + 'album', true, {type: 'string', role: 'media.album', name: 'ALBUM'}); + await createAliasAsync(id + '.ARTIST', dpPath + 'artist', true, {type: 'string', role: 'media.artist', name: 'ARTIST'}); + await createAliasAsync(id + '.TITLE', dpPath + 'title', true, {type: 'string', role: 'media.title', name: 'TITLE'}); + await createAliasAsync(id + '.NEXT', dpPath + 'next', true, {type: 'boolean', role: 'button.next', name: 'NEXT'}); + await createAliasAsync(id + '.PREV', dpPath + 'previous', true, {type: 'boolean', role: 'button.prev', name: 'PREV'}); + await createAliasAsync(id + '.PLAY', dpPath + 'play', true, {type: 'boolean', role: 'button.play', name: 'PLAY'}); + await createAliasAsync(id + '.PAUSE', dpPath + 'pause', true, {type: 'boolean', role: 'button.pause', name: 'PAUSE'}); + await createAliasAsync(id + '.STOP', dpPath + 'stop', true, {type: 'boolean', role: 'button.stop', name: 'STOP'}); + await createAliasAsync(id + '.STATE', dpPath + 'state', true, {type: 'string', role: 'media.state', name: 'STATE'}); + await createAliasAsync(id + '.VOLUME', dpPath + 'volume', true, {type: 'number', role: 'level.volume', name: 'VOLUME'}); + await createAliasAsync(id + '.REPEAT', dpPath + 'repeat', true, {type: 'boolean', role: 'media.mode.repeat', name: 'REPEAT'}); + await createAliasAsync(id + '.SINGLE', dpPath + 'single', true, {type: 'number', role: 'media', name: 'SINGLE'}); + await createAliasAsync(id + '.SHUFFLE', dpPath + 'random', true, {type: 'boolean', role: 'media.mode.shuffle', name: 'SHUFFLE'}); + await createAliasAsync(id + '.DURATION', dpPath + 'current_duration', true, {type: 'string', role: 'media.duration.text', name: 'DURATION'}); + await createAliasAsync(id + '.ELAPSED', dpPath + 'current_elapsed', true, {type: 'string', role: 'media.elapsed.text', name: 'ELAPSED'}); + } catch (err: any) { + log('error at function createAutoMediaAlias Adapter mpd: ' + err.message, 'warn'); + } + } + } break; case 'bosesoundtouch.0.': case 'bosesoundtouch.1.': @@ -6937,6 +6984,7 @@ async function createAutoMediaAlias (id: string, mediaDevice: string, adapterPla } } break; + } default: { log(`Dont find adapterPlayerInstance: ${adapterPlayerInstance}!`, 'warn'); @@ -7069,6 +7117,13 @@ function GenerateMediaPage (page: NSPanel.PageMedia): NSPanel.Payload[] { let durationSeconds = parseInt(getState(id + '.DURATION').val) % 60 < 10 ? '0' : ''; let vDuration = Math.floor(getState(id + '.DURATION').val / 60) + ':' + durationSeconds + (getState(id + '.DURATION').val % 60); title = title + ' (' + vElapsed + '|' + vDuration + ')'; + } else if (v2Adapter == 'mpd') { + let vElapsed: string = getState(id + '.ELAPSED').val; + let vDuration: string = getState(id + '.DURATION').val; + title = title + ' (' + vElapsed + '|' + vDuration + ')'; + if (getState(id + '.STATE').val === 'stop') { + title = '(00:00|00:00)'; + } } } @@ -7124,6 +7179,13 @@ function GenerateMediaPage (page: NSPanel.PageMedia): NSPanel.Payload[] { //Spotify-Premium if (v2Adapter == 'spotify-premium') { media_icon = Icons.GetIcon('spotify'); + if (page.items[0].playerMediaIcon !== undefined) { + if (page.items[0].playerMediaIcon == 'logo-spotify') { + media_icon = page.items[0].playerMediaIcon; + } else { + media_icon = Icons.GetIcon(page.items[0].playerMediaIcon); + } + } name = getState(id + '.CONTEXT_DESCRIPTION').val; let nameLength = name.length; if (name.substring(0, 17) == 'Playlist: This Is') { @@ -7152,6 +7214,13 @@ function GenerateMediaPage (page: NSPanel.PageMedia): NSPanel.Payload[] { //Sonos if (v2Adapter == 'sonos') { media_icon = Icons.GetIcon('alpha-s-circle'); + if (page.items[0].playerMediaIcon !== undefined) { + if (page.items[0].playerMediaIcon == 'logo-sonos') { + media_icon = page.items[0].playerMediaIcon; + } else { + media_icon = Icons.GetIcon(page.items[0].playerMediaIcon); + } + } name = getState(id + '.CONTEXT_DESCRIPTION').val; let nameLenght = name.length; if (nameLenght == 0) { @@ -7175,6 +7244,13 @@ function GenerateMediaPage (page: NSPanel.PageMedia): NSPanel.Payload[] { //Bose Soundtouch if (v2Adapter == 'bosesoundtouch') { media_icon = Icons.GetIcon('alpha-b-circle'); + if (page.items[0].playerMediaIcon !== undefined) { + if (page.items[0].playerMediaIcon == 'logo-bose') { + media_icon = page.items[0].playerMediaIcon; + } else { + media_icon = Icons.GetIcon(page.items[0].playerMediaIcon); + } + } name = page.heading; if (getState(id + '.ALBUM').val.length > 0) { @@ -7193,6 +7269,13 @@ function GenerateMediaPage (page: NSPanel.PageMedia): NSPanel.Payload[] { //Logitech Squeezebox RPC if (v2Adapter == 'squeezeboxrpc') { media_icon = Icons.GetIcon('dlna'); + if (page.items[0].playerMediaIcon !== undefined) { + if (page.items[0].playerMediaIcon == 'logo-dnla') { + media_icon = page.items[0].playerMediaIcon; + } else { + media_icon = Icons.GetIcon(page.items[0].playerMediaIcon); + } + } if (name.length == 0) { name = page.heading; } else if (name.length > 16) { @@ -7203,6 +7286,13 @@ function GenerateMediaPage (page: NSPanel.PageMedia): NSPanel.Payload[] { //Alexa2 if (v2Adapter == 'alexa2') { media_icon = Icons.GetIcon('alpha-a-circle'); + if (page.items[0].playerMediaIcon !== undefined) { + if (page.items[0].playerMediaIcon == 'logo-alexa') { + media_icon = page.items[0].playerMediaIcon; + } else { + media_icon = Icons.GetIcon(page.items[0].playerMediaIcon); + } + } name = getState(id + '.ALBUM').val; let nameLength = name.length; if (name.substring(0, 9) == 'Playlist:') { @@ -7229,12 +7319,43 @@ function GenerateMediaPage (page: NSPanel.PageMedia): NSPanel.Payload[] { //Volumio if (v2Adapter == 'volumio') { media_icon = Icons.GetIcon('clock-time-twelve-outline'); + if (page.items[0].playerMediaIcon !== undefined) { + if (page.items[0].playerMediaIcon == 'logo-volumio') { + media_icon = page.items[0].playerMediaIcon; + } else { + media_icon = Icons.GetIcon(page.items[0].playerMediaIcon); + } + } if (name != undefined) { author = author + ' | ' + name; } name = page.heading; } + //MPD + if (v2Adapter == 'mpd') { + media_icon = Icons.GetIcon('alpha-m-circle'); + if (page.items[0].playerMediaIcon !== undefined) { + if (page.items[0].playerMediaIcon == 'logo-mpd') { + media_icon = page.items[0].playerMediaIcon; + } else { + media_icon = Icons.GetIcon(page.items[0].playerMediaIcon); + } + } + if (getState(id + '.ALBUM').val.length > 0) { + author = getState(id + '.ARTIST').val + ' | ' + getState(id + '.ALBUM').val; + if (author.length > 37) { + author = author.slice(0, 37) + '...'; + } + } else { + author = getState(id + '.ARTIST').val; + } + if (getState(id + '.ARTIST').val.length == 0) { + author = findLocale('media', 'no_music_to_control'); + } + name = page.heading; + } + let volume = scale(getState(id + '.VOLUME').val, activePage!.items[0]!.minValue ?? 0, activePage!.items[0]!.maxValue ?? 100, 100, 0); let iconplaypause = Icons.GetIcon('pause'); //pause let shuffle_icon = Icons.GetIcon('shuffle-variant'); //shuffle @@ -7265,6 +7386,20 @@ function GenerateMediaPage (page: NSPanel.PageMedia): NSPanel.Payload[] { } } + //Ausnahme für mpd, da State = play, pause,.... + if (v2Adapter == 'mpd') { + if (getState(id + '.STATE').val === 'play') { + onoffbutton = 65535; + iconplaypause = Icons.GetIcon('pause'); //pause + } else if (getState(id + '.STATE').val === 'pause') { + iconplaypause = Icons.GetIcon('play'); //play + } else if (getState(id + '.STATE').val === 'stop') { + onoffbutton = 1374; + iconplaypause = Icons.GetIcon('play'); //play + } + + } + //Ausnahme Volumio: status = string: play, pause, stop usw. if (v2Adapter == 'volumio') { if (getState(id + '.status').val == 'play') { @@ -7289,6 +7424,8 @@ function GenerateMediaPage (page: NSPanel.PageMedia): NSPanel.Payload[] { currentSpeaker = getState([page.items[0].adapterPlayerInstance, 'deviceInfo.name'].join('')).val; } else if (v2Adapter == 'volumio') { currentSpeaker = getState([page.items[0].adapterPlayerInstance, 'info.name'].join('')).val; + } else if (v2Adapter == 'mpd') { + currentSpeaker = v1Adapter[0] + '.' + v1Adapter[1]; } //------------------------------------------------------------------------------------------------------------- // All Alexa devices (the online / player and commands directory is available) are listed and linked below @@ -7310,6 +7447,9 @@ function GenerateMediaPage (page: NSPanel.PageMedia): NSPanel.Payload[] { if (Debug) log(getState(page.items[0].adapterPlayerInstance + 'devices.availableDeviceListString').val); speakerListArray = getState(page.items[0].adapterPlayerInstance + 'devices.availableDeviceListString').val.split(';'); page.items[0].speakerList = speakerListArray; + } else if (v2Adapter == 'mpd') { + // All possible Devices if page.items[0].speakerList empty + page.items[0].speakerList[0] = v1Adapter[0] + '.' + v1Adapter[1]; } else { let i_list = Array.prototype.slice.apply($('[state.id="' + page.items[0].adapterPlayerInstance + 'Echo-Devices.*.Info.name"]')); for (let i_index in i_list) { @@ -7368,6 +7508,12 @@ function GenerateMediaPage (page: NSPanel.PageMedia): NSPanel.Payload[] { /* Spotify: get all playlists if empty */ } else if (v2Adapter == 'spotify-premium') { page.items[0].playList = getState(page.items[0].adapterPlayerInstance + 'playlists.playlistListString').val.split(';'); + } else if (v2Adapter == 'mpd') { + let tempPL = getState(page.items[0].adapterPlayerInstance + 'listplaylists').val; + tempPL = tempPL.replace('[',''); + tempPL = tempPL.replace(']',''); + tempPL = tempPL.replaceAll('"',''); + page.items[0].playList = tempPL.split(','); } playListIconCol = rgb_dec565(HMIOn); playListString = @@ -7446,6 +7592,13 @@ function GenerateMediaPage (page: NSPanel.PageMedia): NSPanel.Payload[] { } catch { log('Hello Mr. Developer something went wrong in tracklist!', 'debug'); } + } else if (v2Adapter == 'mpd') { + try { + let tempTrackList = JSON.parse(getState(page.items[0].adapterPlayerInstance + 'playlist_list').val); + globalTracklist = tempTrackList; + } catch { + log('Hello Mr. Developer something went wrong in tracklist!', 'debug'); + } } if (globalTracklist != null && globalTracklist.length != 0) { @@ -7516,16 +7669,24 @@ function GenerateMediaPage (page: NSPanel.PageMedia): NSPanel.Payload[] { repeatIcon = Icons.GetIcon('repeat-variant'); repeatIconCol = rgb_dec565(HMIOn); } + } else if (v2Adapter == 'mpd') { + if (getState(id + '.REPEAT').val == true && getState(id + '.SINGLE').val == 0) { + repeatIcon = Icons.GetIcon('repeat'); + repeatIconCol = rgb_dec565(HMIOn); + } else if (getState(id + '.REPEAT').val == true && getState(id + '.SINGLE').val == 1) { + repeatIcon = Icons.GetIcon('repeat-once'); + repeatIconCol = rgb_dec565(HMIOn); + } } - if (v2Adapter == 'spotify-premium' || v2Adapter == 'alexa2' || v2Adapter == 'sonos' || v2Adapter == 'bosesoundtouch' || v2Adapter == 'volumio' || v2Adapter == 'squeezeboxrpc') { + if (v2Adapter == 'spotify-premium' || v2Adapter == 'alexa2' || v2Adapter == 'sonos' || v2Adapter == 'bosesoundtouch' || v2Adapter == 'volumio' || v2Adapter == 'squeezeboxrpc' || v2Adapter == 'mpd') { repeatButtonString = 'button' + '~' + tid + '?repeat' + '~' + repeatIcon + '~' + repeatIconCol + '~' + 'Repeat' + '~' + 'media4'; } //popUp Tools let toolsString: string = '~~~~~~'; let toolsIconCol = rgb_dec565(colMediaIcon); - if (v2Adapter == 'sonos') { + if (v2Adapter == 'sonos' || v2Adapter == 'mpd') { if (page.items[0].crossfade == undefined || page.items[0].crossfade == false) { toolsString = 'input_sel' + '~' + tid + '?seek' + '~' + media_icon + '~' + toolsIconCol + '~' + findLocale('media', 'seek') + '~' + 'media5~'; } else { @@ -8805,6 +8966,19 @@ function HandleButtonEvent (words: any): void { } GeneratePage(activePage!); break; + case 'mpd': + if (getState(id + '.REPEAT').val == false) { + setIfExists(id + '.REPEAT', true); + setIfExists(id + '.SINGLE', 0); + } else if (getState(id + '.REPEAT').val == true && getState(id + '.SINGLE').val == 0) { + setIfExists(id + '.REPEAT', true); + setIfExists(id + '.SINGLE', 1); + } else if (getState(id + '.REPEAT').val == true && getState(id + '.SINGLE').val == 1) { + setIfExists(id + '.REPEAT', false); + setIfExists(id + '.SINGLE', 0); + } + GeneratePage(activePage!); + break; case 'volumio': let urlString: string = `${getState(adapterInstanceRepeat + 'info.host').val}/api/commands/?cmd=repeat`; axios @@ -9036,6 +9210,12 @@ function HandleButtonEvent (words: any): void { } else if (stateVal == null) { setState(adapterPlayerInstanceStateSeceltor, 1); } + } else if (adaInstanceSplit[0] == 'mpd') { + if (getState(id + '.STATE').val === 'play') { + setIfExists(id + '.PAUSE', true); + } else { + setIfExists(id + '.PLAY', true); + } } else if (pageItemTemp.adapterPlayerInstance.startsWith('bosesoundtouch')) { setIfExists(pageItemTemp.adapterPlayerInstance + 'key', 'PLAY_PAUSE'); } else { @@ -9069,6 +9249,13 @@ function HandleButtonEvent (words: any): void { if (isPageMediaItem(item)) item.playList = []; break; } //Volumio: empty playlist $uha-20230103 + if (tempPage.adapterPlayerInstance.startsWith('mpd')) { + if (getState(id + '.SHUFFLE').val == false) { + setIfExists(id + '.SHUFFLE', true); + } else { + setIfExists(id + '.SHUFFLE', false); + } + } if (tempPage.adapterPlayerInstance.startsWith('spotify')) { if (getState(id + '.SHUFFLE').val == 'off') { setIfExists(id + '.SHUFFLE', 'on'); @@ -9226,6 +9413,13 @@ function HandleButtonEvent (words: any): void { setState(adapterInstancePL + 'key', 'AUX_INPUT'); } break; + case 'mpd': + if (Debug) log('mpd - playlist ' + pageItemPL.adapterPlayerInstance + ' - ' + words[4]); + if (Debug) log(pageItemPL.playList![words[4]]); + setState(adapterInstancePL + 'clear',true); // Clear current Queue + setState(adapterInstancePL + 'load', pageItemPL.playList![words[4]]); // Load stored Playlist + setState(adapterInstancePL + 'play',true); // Start new Queue with play + break; default: log('Hello Mr. Developer u miss in mode-playlist something!', 'warn'); } @@ -9249,6 +9443,9 @@ function HandleButtonEvent (words: any): void { //setState(adapterInstanceTL + 'player.trackId', getAttr(trackArray, words[4] + '.id')); setState(adapterInstanceTL + 'player.playlist.trackNo', parseInt(words[4]) + 1); break; + case 'mpd': + setState(adapterInstanceTL + 'playid', parseInt(words[4])); + break; case 'sonos': setState(adapterInstanceTL + 'root.' + pageItemTL.mediaDevice + '.current_track_number', parseInt(words[4]) + 1); case 'alexa2': @@ -9300,6 +9497,19 @@ function HandleButtonEvent (words: any): void { setIfExists(id + '.REPEAT', pageItemRP.repeatList![words[4]]); GeneratePage(activePage!); break; + case 'mpd': + if (getState(id + '.REPEAT').val == false) { + setIfExists(id + '.REPEAT', true); + setIfExists(id + '.SINGLE', 0); + } else if (getState(id + '.REPEAT').val == true && getState(id + '.SINGLE').val == 0) { + setIfExists(id + '.REPEAT', true); + setIfExists(id + '.SINGLE', 1); + } else if (getState(id + '.REPEAT').val == true && getState(id + '.SINGLE').val == 1) { + setIfExists(id + '.REPEAT', false); + setIfExists(id + '.SINGLE', 0); + } + GeneratePage(activePage!); + break; case 'alexa2': GeneratePage(activePage!); break; @@ -9328,6 +9538,9 @@ function HandleButtonEvent (words: any): void { case 'spotify-premium': setState(adapterInstanceSK + 'player.progressPercentage', parseInt(words[4]) * 10); break; + case 'mpd': + setState(adapterInstanceSK + 'seek', parseInt(words[4]) * 10); + break; case 'squeezeboxrpc': const vDuration: number = getState(adapterInstanceSK + 'Players.' + pageItemSeek.mediaDevice + '.Duration').val; const vSeekPercentage: number = words[4] * 10; @@ -9364,6 +9577,10 @@ function HandleButtonEvent (words: any): void { } setState(adapterInstanceCF + 'root.' + pageItemCrossfade.mediaDevice + '.crossfade', cfState); break; + case 'mpd': + if (Debug) log('HandleButtonEvent mode-crossfade -> id: ' + id, 'info'); + setState(adapterInstanceCF + 'crossfade', parseInt(words[4])); + break; } pageCounter = 0; GeneratePage(activePage!); @@ -10790,6 +11007,11 @@ function GenerateDetailPage (type: NSPanel.PopupType, optional: NSPanel.mediaOpt actualState = Math.round(actualStateTemp / 10) * 10 + '%'; optionalString = '0%?10%?20%?30%?40%?50%?60%?70%?80%?90%?100%'; } + if (vAdapter == 'mpd') { + const actualStateTemp: number = getState(pageItem.adapterPlayerInstance + 'seek').val; + actualState = Math.round(actualStateTemp / 10) * 10 + '%'; + optionalString = '0%?10%?20%?30%?40%?50%?60%?70%?80%?90%?100%'; + } if (vAdapter == 'spotify-premium') { const actualStateTemp: number = getState(pageItem.adapterPlayerInstance + 'player.progressPercentage').val; actualState = Math.round(actualStateTemp / 10) * 10 + '%'; @@ -10804,17 +11026,25 @@ function GenerateDetailPage (type: NSPanel.PopupType, optional: NSPanel.mediaOpt } mode = 'seek'; } else if (optional == 'crossfade') { - if (existsObject(pageItem.adapterPlayerInstance + 'root.' + pageItem.mediaDevice + '.crossfade')) { - let actualStateTemp: boolean = getState(pageItem.adapterPlayerInstance + 'root.' + pageItem.mediaDevice + '.crossfade').val; - if (actualStateTemp) { - actualState = findLocale('media', 'on'); - } else { - actualState = findLocale('media', 'off'); - } - } + //Sonos is using bool Auto-Crossfading 2 Songs if (vAdapter == 'sonos') { + if (existsObject(pageItem.adapterPlayerInstance + 'root.' + pageItem.mediaDevice + '.crossfade')) { + let actualStateTemp: boolean = getState(pageItem.adapterPlayerInstance + 'root.' + pageItem.mediaDevice + '.crossfade').val; + if (actualStateTemp) { + actualState = findLocale('media', 'on'); + } else { + actualState = findLocale('media', 'off'); + } + } optionalString = findLocale('media', 'on') + '?' + findLocale('media', 'off'); } + if (vAdapter == 'mpd') { + //MPD is using numeric X seconds for crossfading 2 Songs + if (existsObject(pageItem.adapterPlayerInstance + 'crossfade')) { + actualState = getState(pageItem.adapterPlayerInstance + 'crossfade').val + ' Sec'; + } + optionalString = '0 Sec?1 Sec?2 Sec?3 Sec?4 Sec?5 Sec?6 Sec?7 Sec?8 Sec?9 Sec?10 Sec'; + } mode = 'crossfade'; } else if (optional == 'speakerlist') { if (vAdapter == 'spotify-premium') { @@ -10849,6 +11079,15 @@ function GenerateDetailPage (type: NSPanel.PopupType, optional: NSPanel.mediaOpt tempPlayList[i] = formatInSelText(pageItem.playList![i]); } optionalString = pageItem.playList != undefined ? tempPlayList.join('?') : ''; + } else if (vAdapter == 'mpd') { + if (existsObject(pageItem.adapterPlayerInstance + 'listplaylist')) { + actualState = formatInSelText(getState(pageItem.adapterPlayerInstance + 'listplaylist').val); + } + let tempPlayList: string[] = []; + for (let i = 0; i < pageItem.playList!.length; i++) { + tempPlayList[i] = formatInSelText(pageItem.playList![i]); + } + optionalString = pageItem.playList != undefined ? tempPlayList.join('?') : ''; } else if (vAdapter == 'alexa2') { //Todo Richtiges Device finden actualState = formatInSelText(getState(pageItem.adapterPlayerInstance + 'Echo-Devices.' + pageItem.mediaDevice + '.Player.currentAlbum').val); @@ -10927,6 +11166,8 @@ function GenerateDetailPage (type: NSPanel.PopupType, optional: NSPanel.mediaOpt globalTracklist = pageItem.globalTracklist; } else if (vAdapter == 'squeezeboxrpc') { actualState = getState(pageItem.id + '.TITLE').val; + } else if (vAdapter == 'mpd') { + actualState = getState(pageItem.id + '.TITLE').val; } else if (vAdapter == 'sonos') { actualState = getState(pageItem.id + '.TITLE').val; } else { @@ -10939,9 +11180,14 @@ function GenerateDetailPage (type: NSPanel.PopupType, optional: NSPanel.mediaOpt if (Debug) log(globalTracklist, 'info'); //Limit 900 characters, then memory overflow --> Shorten as much as possible let temp_array: any[] = []; + let temp_cut_array: any; //let trackArray = (function () { try {return JSON.parse(getState(pageItem.adapterPlayerInstance + 'player.playlist.trackListArray').val);} catch(e) {return {};}})(); for (let track_index = 0; track_index < 48; track_index++) { - let temp_cut_array = getAttr(globalTracklist, track_index + '.title'); + if (vAdapter == 'mpd') { + temp_cut_array = getAttr(globalTracklist, track_index + '.Title'); + } else { + temp_cut_array = getAttr(globalTracklist, track_index + '.title'); + } /* Volumio: @local/NAS no title -> name */ if (temp_cut_array == undefined) { temp_cut_array = getAttr(globalTracklist, track_index + '.name'); @@ -12860,7 +13106,7 @@ function _clearSchedule (ref: number): null { return null; } const ArrayPlayerTypeWithMediaDevice = ['alexa2', 'sonos', 'squeezeboxrpc'] as const; -const ArrayPlayerTypeWithOutMediaDevice = ['spotify-premium', 'volumio', 'bosesoundtouch'] as const; +const ArrayPlayerTypeWithOutMediaDevice = ['spotify-premium', 'volumio', 'bosesoundtouch', 'mpd'] as const; /** * Checks if the given player type is a player with a media device. @@ -13195,6 +13441,7 @@ namespace NSPanel { export type PageMediaItem = { adapterPlayerInstance: adapterPlayerInstanceType; mediaDevice?: string; + playerMediaIcon?: string; colorMediaIcon?: RGB; colorMediaArtist?: RGB; colorMediaTitle?: RGB; @@ -13455,6 +13702,16 @@ namespace NSPanel { | 'squeezeboxrpc.7.' | 'squeezeboxrpc.8.' | 'squeezeboxrpc.9.' + | 'mpd.0.' + | 'mpd.1.' + | 'mpd.2.' + | 'mpd.3.' + | 'mpd.4.' + | 'mpd.5.' + | 'mpd.6.' + | 'mpd.7.' + | 'mpd.8.' + | 'mpd.9.' | 'bosesoundtouch.0.' | 'bosesoundtouch.1.' | 'bosesoundtouch.2.'