From 7a8b4ef6f8894a51b6ee47fe8c96bcf37d77c124 Mon Sep 17 00:00:00 2001 From: AeRo Date: Fri, 4 Feb 2022 03:45:43 +0100 Subject: [PATCH 1/8] Fix queue when playing on remote device (partial) --- src/components/remotecontrol/remotecontrol.js | 4 + src/plugins/sessionPlayer/plugin.js | 139 +++++++++++++++++- 2 files changed, 141 insertions(+), 2 deletions(-) diff --git a/src/components/remotecontrol/remotecontrol.js b/src/components/remotecontrol/remotecontrol.js index 38eb27a2ba1..2e47a1f4eca 100644 --- a/src/components/remotecontrol/remotecontrol.js +++ b/src/components/remotecontrol/remotecontrol.js @@ -489,6 +489,10 @@ export default function () { function loadPlaylist(context, player) { getPlaylistItems(player).then(function (items) { + if (items.length === 0) { + return; + } + let html = ''; let favoritesEnabled = true; if (layoutManager.mobile) { diff --git a/src/plugins/sessionPlayer/plugin.js b/src/plugins/sessionPlayer/plugin.js index a165cd54c82..82b50063e99 100644 --- a/src/plugins/sessionPlayer/plugin.js +++ b/src/plugins/sessionPlayer/plugin.js @@ -83,6 +83,67 @@ function unsubscribeFromPlayerUpdates(instance) { } } +async function updatePlaylist(instance, queue) { + instance.playlist = []; + const max = 100; + const apiClient = getCurrentApiClient(instance); + + const fetch = async (queue) => { + const options = { + ids: queue.map(i => i.Id ), + serverId: apiClient.serverId() + }; + + const result = await playbackManager.getItemsForPlayback(options.serverId, { + Ids: options.ids.join(',') + }); + + const items = await playbackManager.translateItemsForPlayback(result.Items, options); + + for (let i = 0, length = items.length; i < length; i++) { + items[i].PlaylistItemId = queue[i].PlaylistItemId; + } + return items; + }; + + const n = Math.floor(queue.length / max) + 1; + + for (let i = 0; i < n; i++) { + instance.playlist.push(...await fetch(queue.slice(max * i, max * (i + 1)))); + } +} + +function compareQueues(q1, q2) { + if (q1.length !== q2.length) + return true; + + for (let i = 0, length = q1.length; i < length; i++) { + if (q1[i].Id !== q2[i].Id || q1[i].PlaylistItemId !== q2[i].PlaylistItemId) { + return true; + } + } + return false; +} + +function updateCurrentQueue(instance, session) { + const current = session.NowPlayingQueue; + if (instance.updating_playlist) + return; + + if (instance.lastPlayerData) + if (!compareQueues(current, instance.playlist)) + return; + + instance.updating_playlist = true; + + const finish = () => { + instance.updating_playlist = false; + instance.render_playlist = true; + }; + + updatePlaylist(instance, current).then(finish, finish); +} + function processUpdatedSessions(instance, sessions, apiClient) { const serverId = apiClient.serverId(); @@ -102,6 +163,8 @@ function processUpdatedSessions(instance, sessions, apiClient) { normalizeImages(session, apiClient); const eventNames = getChangedEvents(instance.lastPlayerData); + updateCurrentQueue(instance, session, apiClient); + instance.lastPlayerData = session; for (let i = 0, length = eventNames.length; i < length; i++) { @@ -187,6 +250,11 @@ class SessionPlayer { this.isLocalPlayer = false; this.id = 'remoteplayer'; + this.playlist = []; + this.render_playlist = true; + this.updating_playlist = false; + this.last_song_playlist_id = 0; + Events.on(serverNotifications, 'Sessions', function (e, apiClient, data) { processUpdatedSessions(self, data, apiClient); }); @@ -483,15 +551,82 @@ class SessionPlayer { return state.MediaType === 'Audio'; } + getTrackIndex(PlaylistItemId) { + for (let i = 0, length = this.playlist.length; i < length; i++) { + if (this.playlist[i].PlaylistItemId === PlaylistItemId) { + return i; + } + } + } + getPlaylist() { + let song_id = 0; + + if (this.lastPlayerData) { + song_id = this.lastPlayerData.PlaylistItemId; + } + + if (this.playlist.length > 0 && (this.render_playlist || song_id !== this.last_song_playlist_id)) { + this.render_playlist = false; + this.last_song_playlist_id = song_id; + return Promise.resolve(this.playlist); + } return Promise.resolve([]); } + movePlaylistItem(playlistItemId, newIndex) { + const index = this.getTrackIndex(playlistItemId); + if (index === newIndex) + return; + + const current = this.getCurrentPlaylistItemId(); + let current_pos = 0; + + if (current === playlistItemId) + current_pos = newIndex; + + const append = (newIndex + 1 >= this.playlist.length); + + if (newIndex > index) + newIndex++; + + const ids = []; + const item = this.playlist[index]; + + for (let i = 0, length = this.playlist.length; i < length; i++) { + if (i === index) + continue; + + if (i === newIndex) + ids.push(item.Id); + + if (this.playlist[i].PlaylistItemId === current) + current_pos = ids.length; + + ids.push(this.playlist[i].Id); + } + + if (append) + ids.push(item.Id); + + const options = { + ids: ids, + startIndex: current_pos + }; + + return sendPlayCommand(getCurrentApiClient(this), options, 'PlayNow'); + } + getCurrentPlaylistItemId() { + return this.lastPlayerData.PlaylistItemId; } - setCurrentPlaylistItem() { - return Promise.resolve(); + setCurrentPlaylistItem(PlaylistItemId) { + const options = { + ids: this.playlist.map(i => i.Id), + startIndex: this.getTrackIndex(PlaylistItemId) + }; + return sendPlayCommand(getCurrentApiClient(this), options, 'PlayNow'); } removeFromPlaylist() { From d81d26c1d663e39fc3100066ead64753dd2e6ec2 Mon Sep 17 00:00:00 2001 From: AeRo Date: Sat, 10 Dec 2022 18:18:31 +0100 Subject: [PATCH 2/8] fix sonarcloud bug (extra parameter) --- src/plugins/sessionPlayer/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/sessionPlayer/plugin.js b/src/plugins/sessionPlayer/plugin.js index d47559542a0..8a481061bb4 100644 --- a/src/plugins/sessionPlayer/plugin.js +++ b/src/plugins/sessionPlayer/plugin.js @@ -163,7 +163,7 @@ function processUpdatedSessions(instance, sessions, apiClient) { normalizeImages(session, apiClient); const eventNames = getChangedEvents(instance.lastPlayerData); - updateCurrentQueue(instance, session, apiClient); + updateCurrentQueue(instance, session); instance.lastPlayerData = session; From 5120070e28ad063a23b76a4dd727a7077b1c9d6f Mon Sep 17 00:00:00 2001 From: AeRo Date: Mon, 12 Dec 2022 09:59:59 +0100 Subject: [PATCH 3/8] fix eslint errors --- src/plugins/sessionPlayer/plugin.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/plugins/sessionPlayer/plugin.js b/src/plugins/sessionPlayer/plugin.js index 8a481061bb4..797c687c1d4 100644 --- a/src/plugins/sessionPlayer/plugin.js +++ b/src/plugins/sessionPlayer/plugin.js @@ -88,9 +88,9 @@ async function updatePlaylist(instance, queue) { const max = 100; const apiClient = getCurrentApiClient(instance); - const fetch = async (queue) => { + const fetch = async (newQueue) => { const options = { - ids: queue.map(i => i.Id ), + ids: newQueue.map(i => i.Id ), serverId: apiClient.serverId() }; @@ -101,7 +101,7 @@ async function updatePlaylist(instance, queue) { const items = await playbackManager.translateItemsForPlayback(result.Items, options); for (let i = 0, length = items.length; i < length; i++) { - items[i].PlaylistItemId = queue[i].PlaylistItemId; + items[i].PlaylistItemId = newQueue[i].PlaylistItemId; } return items; }; @@ -130,9 +130,8 @@ function updateCurrentQueue(instance, session) { if (instance.updating_playlist) return; - if (instance.lastPlayerData) - if (!compareQueues(current, instance.playlist)) - return; + if (instance.lastPlayerData && !compareQueues(current, instance.playlist)) + return; instance.updating_playlist = true; From e306286df33d8cfc5d682a55ab296d3db19884eb Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 16 Oct 2024 01:28:37 -0400 Subject: [PATCH 4/8] Fix lint issues --- src/plugins/sessionPlayer/plugin.js | 30 ++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/plugins/sessionPlayer/plugin.js b/src/plugins/sessionPlayer/plugin.js index d1c60331cfa..9a51ddb84ab 100644 --- a/src/plugins/sessionPlayer/plugin.js +++ b/src/plugins/sessionPlayer/plugin.js @@ -115,8 +115,9 @@ async function updatePlaylist(instance, queue) { } function compareQueues(q1, q2) { - if (q1.length !== q2.length) + if (q1.length !== q2.length) { return true; + } for (let i = 0, length = q1.length; i < length; i++) { if (q1[i].Id !== q2[i].Id || q1[i].PlaylistItemId !== q2[i].PlaylistItemId) { @@ -128,11 +129,13 @@ function compareQueues(q1, q2) { function updateCurrentQueue(instance, session) { const current = session.NowPlayingQueue; - if (instance.updating_playlist) + if (instance.updating_playlist) { return; + } - if (instance.lastPlayerData && !compareQueues(current, instance.playlist)) + if (instance.lastPlayerData && !compareQueues(current, instance.playlist)) { return; + } instance.updating_playlist = true; @@ -576,38 +579,39 @@ class SessionPlayer { movePlaylistItem(playlistItemId, newIndex) { const index = this.getTrackIndex(playlistItemId); - if (index === newIndex) - return; + if (index === newIndex) return; const current = this.getCurrentPlaylistItemId(); let current_pos = 0; - if (current === playlistItemId) + if (current === playlistItemId) { current_pos = newIndex; + } const append = (newIndex + 1 >= this.playlist.length); - if (newIndex > index) - newIndex++; + if (newIndex > index) newIndex++; const ids = []; const item = this.playlist[index]; for (let i = 0, length = this.playlist.length; i < length; i++) { - if (i === index) - continue; + if (i === index) continue; - if (i === newIndex) + if (i === newIndex) { ids.push(item.Id); + } - if (this.playlist[i].PlaylistItemId === current) + if (this.playlist[i].PlaylistItemId === current) { current_pos = ids.length; + } ids.push(this.playlist[i].Id); } - if (append) + if (append) { ids.push(item.Id); + } const options = { ids: ids, From 960b1eaef8f12863e5ca2114733421f4934ac4c9 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 16 Oct 2024 01:44:16 -0400 Subject: [PATCH 5/8] No snake case --- src/plugins/sessionPlayer/plugin.js | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/plugins/sessionPlayer/plugin.js b/src/plugins/sessionPlayer/plugin.js index 9a51ddb84ab..6d5bccac065 100644 --- a/src/plugins/sessionPlayer/plugin.js +++ b/src/plugins/sessionPlayer/plugin.js @@ -129,7 +129,7 @@ function compareQueues(q1, q2) { function updateCurrentQueue(instance, session) { const current = session.NowPlayingQueue; - if (instance.updating_playlist) { + if (instance.isUpdatingPlaylist) { return; } @@ -137,11 +137,11 @@ function updateCurrentQueue(instance, session) { return; } - instance.updating_playlist = true; + instance.isUpdatingPlaylist = true; const finish = () => { - instance.updating_playlist = false; - instance.render_playlist = true; + instance.isUpdatingPlaylist = false; + instance.isPlaylistRendered = true; }; updatePlaylist(instance, current).then(finish, finish); @@ -243,6 +243,8 @@ function normalizeImages(state, apiClient) { } class SessionPlayer { + lastPlaylistItemId; + constructor() { const self = this; @@ -252,9 +254,8 @@ class SessionPlayer { this.id = 'remoteplayer'; this.playlist = []; - this.render_playlist = true; - this.updating_playlist = false; - this.last_song_playlist_id = 0; + this.isPlaylistRendered = true; + this.isUpdatingPlaylist = false; Events.on(serverNotifications, 'Sessions', function (e, apiClient, data) { processUpdatedSessions(self, data, apiClient); @@ -563,15 +564,15 @@ class SessionPlayer { } getPlaylist() { - let song_id = 0; + let itemId; if (this.lastPlayerData) { - song_id = this.lastPlayerData.PlaylistItemId; + itemId = this.lastPlayerData.PlaylistItemId; } - if (this.playlist.length > 0 && (this.render_playlist || song_id !== this.last_song_playlist_id)) { - this.render_playlist = false; - this.last_song_playlist_id = song_id; + if (this.playlist.length > 0 && (this.isPlaylistRendered || itemId !== this.lastPlaylistItemId)) { + this.isPlaylistRendered = false; + this.lastPlaylistItemId = itemId; return Promise.resolve(this.playlist); } return Promise.resolve([]); @@ -582,10 +583,10 @@ class SessionPlayer { if (index === newIndex) return; const current = this.getCurrentPlaylistItemId(); - let current_pos = 0; + let currentIndex = 0; if (current === playlistItemId) { - current_pos = newIndex; + currentIndex = newIndex; } const append = (newIndex + 1 >= this.playlist.length); @@ -603,7 +604,7 @@ class SessionPlayer { } if (this.playlist[i].PlaylistItemId === current) { - current_pos = ids.length; + currentIndex = ids.length; } ids.push(this.playlist[i].Id); @@ -614,8 +615,8 @@ class SessionPlayer { } const options = { - ids: ids, - startIndex: current_pos + ids, + startIndex: currentIndex }; return sendPlayCommand(getCurrentApiClient(this), options, 'PlayNow'); @@ -623,7 +624,6 @@ class SessionPlayer { getCurrentPlaylistItemId() { return this.lastPlayerData.PlaylistItemId; - // not supported? } setCurrentPlaylistItem(PlaylistItemId) { From 31954baacb2b39b50ec06c487da2373c7dc87a4d Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 16 Oct 2024 11:08:01 -0400 Subject: [PATCH 6/8] Remove request chunking --- src/plugins/sessionPlayer/plugin.js | 35 ++++++++++------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/plugins/sessionPlayer/plugin.js b/src/plugins/sessionPlayer/plugin.js index 6d5bccac065..9093ae7dc3c 100644 --- a/src/plugins/sessionPlayer/plugin.js +++ b/src/plugins/sessionPlayer/plugin.js @@ -85,33 +85,22 @@ function unsubscribeFromPlayerUpdates(instance) { } async function updatePlaylist(instance, queue) { - instance.playlist = []; - const max = 100; - const apiClient = getCurrentApiClient(instance); - - const fetch = async (newQueue) => { - const options = { - ids: newQueue.map(i => i.Id ), - serverId: apiClient.serverId() - }; - - const result = await playbackManager.getItemsForPlayback(options.serverId, { - Ids: options.ids.join(',') - }); - - const items = await playbackManager.translateItemsForPlayback(result.Items, options); - - for (let i = 0, length = items.length; i < length; i++) { - items[i].PlaylistItemId = newQueue[i].PlaylistItemId; - } - return items; + const options = { + ids: queue.map(i => i.Id), + serverId: getCurrentApiClient(instance).serverId() }; - const n = Math.floor(queue.length / max) + 1; + const result = await playbackManager.getItemsForPlayback(options.serverId, { + Ids: options.ids.join(',') + }); + + const items = await playbackManager.translateItemsForPlayback(result.Items, options); - for (let i = 0; i < n; i++) { - instance.playlist.push(...await fetch(queue.slice(max * i, max * (i + 1)))); + for (let i = 0; i < items.length; i++) { + items[i].PlaylistItemId = queue[i].PlaylistItemId; } + + instance.playlist = items; } function compareQueues(q1, q2) { From 2089459df231513cd4bd7bca77db2fcb6cbc3101 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 16 Oct 2024 12:31:17 -0400 Subject: [PATCH 7/8] Simplify for loops --- src/plugins/sessionPlayer/plugin.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/sessionPlayer/plugin.js b/src/plugins/sessionPlayer/plugin.js index 9093ae7dc3c..3907d2c9052 100644 --- a/src/plugins/sessionPlayer/plugin.js +++ b/src/plugins/sessionPlayer/plugin.js @@ -108,7 +108,7 @@ function compareQueues(q1, q2) { return true; } - for (let i = 0, length = q1.length; i < length; i++) { + for (let i = 0; i < q1.length; i++) { if (q1[i].Id !== q2[i].Id || q1[i].PlaylistItemId !== q2[i].PlaylistItemId) { return true; } @@ -159,9 +159,9 @@ function processUpdatedSessions(instance, sessions, apiClient) { instance.lastPlayerData = session; - for (let i = 0, length = eventNames.length; i < length; i++) { - Events.trigger(instance, eventNames[i], [session]); - } + eventNames.forEach(eventName => { + Events.trigger(instance, eventName, [session]); + }); } else { instance.lastPlayerData = session; @@ -545,7 +545,7 @@ class SessionPlayer { } getTrackIndex(PlaylistItemId) { - for (let i = 0, length = this.playlist.length; i < length; i++) { + for (let i = 0; i < this.playlist.length; i++) { if (this.playlist[i].PlaylistItemId === PlaylistItemId) { return i; } @@ -585,7 +585,7 @@ class SessionPlayer { const ids = []; const item = this.playlist[index]; - for (let i = 0, length = this.playlist.length; i < length; i++) { + for (let i = 0; i < this.playlist.length; i++) { if (i === index) continue; if (i === newIndex) { From 2ab13647e9dbd242ba9ca5e98f73991340769137 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 16 Oct 2024 12:57:02 -0400 Subject: [PATCH 8/8] Fix variable casing --- src/plugins/sessionPlayer/plugin.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/sessionPlayer/plugin.js b/src/plugins/sessionPlayer/plugin.js index 3907d2c9052..510129d7f16 100644 --- a/src/plugins/sessionPlayer/plugin.js +++ b/src/plugins/sessionPlayer/plugin.js @@ -544,9 +544,9 @@ class SessionPlayer { return state.MediaType === 'Audio'; } - getTrackIndex(PlaylistItemId) { + getTrackIndex(playlistItemId) { for (let i = 0; i < this.playlist.length; i++) { - if (this.playlist[i].PlaylistItemId === PlaylistItemId) { + if (this.playlist[i].PlaylistItemId === playlistItemId) { return i; } } @@ -615,10 +615,10 @@ class SessionPlayer { return this.lastPlayerData.PlaylistItemId; } - setCurrentPlaylistItem(PlaylistItemId) { + setCurrentPlaylistItem(playlistItemId) { const options = { ids: this.playlist.map(i => i.Id), - startIndex: this.getTrackIndex(PlaylistItemId) + startIndex: this.getTrackIndex(playlistItemId) }; return sendPlayCommand(getCurrentApiClient(this), options, 'PlayNow'); }