From ff0986a4e1f6af5134b3585af8bc035428dd3604 Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Sat, 8 Apr 2023 13:48:57 -0400
Subject: [PATCH] Fix music shuffle function
---
components/manager/QueueManager.brs | 57 +++++++++++++++++++++++++++-
components/manager/QueueManager.xml | 4 ++
components/music/AudioPlayerView.brs | 43 +++++++++------------
source/Main.brs | 9 +++++
4 files changed, 86 insertions(+), 27 deletions(-)
diff --git a/components/manager/QueueManager.brs b/components/manager/QueueManager.brs
index 657f2da2..374e0130 100644
--- a/components/manager/QueueManager.brs
+++ b/components/manager/QueueManager.brs
@@ -1,7 +1,9 @@
sub init()
m.queue = []
+ m.originalQueue = []
m.queueTypes = []
m.position = 0
+ m.shuffleEnabled = false
end sub
' Clear all content from play queue
@@ -27,6 +29,11 @@ function getCurrentItem()
return getItemByIndex(m.position)
end function
+' Return whether or not shuffle is enabled
+function getIsShuffled()
+ return m.shuffleEnabled
+end function
+
' Return the item in the passed index from the play queue
function getItemByIndex(index)
return m.queue[index]
@@ -108,6 +115,54 @@ sub setPosition(newPosition)
m.position = newPosition
end sub
+' Reset shuffle to off state
+sub resetShuffle()
+ m.shuffleEnabled = false
+end sub
+
+' Toggle shuffleEnabled state
+sub toggleShuffle()
+ m.shuffleEnabled = not m.shuffleEnabled
+
+ if m.shuffleEnabled
+ shuffleQueueItems()
+ return
+ end if
+
+ resetQueueItemOrder()
+end sub
+
+' Reset queue items back to original, unshuffled order
+sub resetQueueItemOrder()
+ set(m.originalQueue)
+end sub
+
+' Return original, unshuffled queue
+function getUnshuffledQueue()
+ return m.originalQueue
+end function
+
+' Save a copy of the original queue and randomize order of queue items
+sub shuffleQueueItems()
+ ' By calling getQueue 2 different ways, Roku avoids needing to do a deep copy
+ m.originalQueue = m.global.queueManager.callFunc("getQueue")
+ songIDArray = getQueue()
+
+ ' Move the currently playing song to the front of the queue
+ temp = top()
+ songIDArray[0] = getCurrentItem()
+ songIDArray[getPosition()] = temp
+
+ for i = 1 to songIDArray.count() - 1
+ j = Rnd(songIDArray.count() - 1)
+ temp = songIDArray[i]
+ songIDArray[i] = songIDArray[j]
+ songIDArray[j] = temp
+ end for
+
+ set(songIDArray)
+end sub
+
' Return the fitst item in the play queue
function top()
return getItemByIndex(0)
@@ -115,7 +170,7 @@ end function
' Replace play queue with passed array
sub set(items)
- setPosition(0)
+ clear()
m.queue = items
for each item in items
m.queueTypes.push(getItemType(item))
diff --git a/components/manager/QueueManager.xml b/components/manager/QueueManager.xml
index 05cb4d54..79ea899f 100644
--- a/components/manager/QueueManager.xml
+++ b/components/manager/QueueManager.xml
@@ -5,19 +5,23 @@
+
+
+
+
diff --git a/components/music/AudioPlayerView.brs b/components/music/AudioPlayerView.brs
index 555d85d8..84792112 100644
--- a/components/music/AudioPlayerView.brs
+++ b/components/music/AudioPlayerView.brs
@@ -10,7 +10,6 @@ sub init()
m.playlistTypeCount = m.global.queueManager.callFunc("getQueueUniqueTypes").count()
- m.shuffleEnabled = false
m.buttonCount = m.buttons.getChildCount()
m.screenSaverTimeout = 300
@@ -26,6 +25,8 @@ sub init()
loadButtons()
pageContentChanged()
+ setShuffleIconState()
+ setLoopButtonImage()
end sub
sub onScreensaverTimeoutLoaded()
@@ -313,10 +314,12 @@ function nextClicked() as boolean
end function
sub toggleShuffleEnabled()
- m.shuffleEnabled = not m.shuffleEnabled
+ m.global.queueManager.callFunc("toggleShuffle")
end sub
function findCurrentSongIndex(songList) as integer
+ if not isValidAndNotEmpty(songList) then return 0
+
for i = 0 to songList.count() - 1
if songList[i].id = m.global.queueManager.callFunc("getCurrentItem").id
return i
@@ -328,14 +331,13 @@ end function
function shuffleClicked() as boolean
+ currentSongIndex = findCurrentSongIndex(m.global.queueManager.callFunc("getUnshuffledQueue"))
+
toggleShuffleEnabled()
- if not m.shuffleEnabled
+ if not m.global.queueManager.callFunc("getIsShuffled")
m.shuffleIndicator.opacity = ".4"
m.shuffleIndicator.uri = m.shuffleIndicator.uri.Replace("-on", "-off")
-
- currentSongIndex = findCurrentSongIndex(m.originalSongList)
- m.global.queueManager.callFunc("set", m.originalSongList)
m.global.queueManager.callFunc("setPosition", currentSongIndex)
setFieldTextValue("numberofsongs", "Track " + stri(m.global.queueManager.callFunc("getPosition") + 1) + "/" + stri(m.global.queueManager.callFunc("getCount")))
@@ -345,27 +347,16 @@ function shuffleClicked() as boolean
m.shuffleIndicator.opacity = "1"
m.shuffleIndicator.uri = m.shuffleIndicator.uri.Replace("-off", "-on")
- m.originalSongList = m.global.queueManager.callFunc("getQueue")
-
- songIDArray = m.global.queueManager.callFunc("getQueue")
-
- ' Move the currently playing song to the front of the queue
- temp = m.global.queueManager.callFunc("top")
- songIDArray[0] = m.global.queueManager.callFunc("getCurrentItem")
- songIDArray[m.global.queueManager.callFunc("getPosition")] = temp
-
- for i = 1 to songIDArray.count() - 1
- j = Rnd(songIDArray.count() - 1)
- temp = songIDArray[i]
- songIDArray[i] = songIDArray[j]
- songIDArray[j] = temp
- end for
-
- m.global.queueManager.callFunc("set", songIDArray)
-
return true
end function
+sub setShuffleIconState()
+ if m.global.queueManager.callFunc("getIsShuffled")
+ m.shuffleIndicator.opacity = "1"
+ m.shuffleIndicator.uri = m.shuffleIndicator.uri.Replace("-off", "-on")
+ end if
+end sub
+
sub LoadNextSong()
if m.global.audioPlayer.state = "playing"
m.global.audioPlayer.control = "stop"
@@ -509,8 +500,8 @@ sub setOnScreenTextValues(json)
if isValid(json)
currentSongIndex = m.global.queueManager.callFunc("getPosition")
- if m.shuffleEnabled
- currentSongIndex = findCurrentSongIndex(m.originalSongList)
+ if m.global.queueManager.callFunc("getIsShuffled")
+ currentSongIndex = findCurrentSongIndex(m.global.queueManager.callFunc("getUnshuffledQueue"))
end if
if m.playlistTypeCount = 1
diff --git a/source/Main.brs b/source/Main.brs
index 95c154a0..563129f8 100644
--- a/source/Main.brs
+++ b/source/Main.brs
@@ -239,6 +239,7 @@ sub Main (args as dynamic) as void
group = CreatePlaylistView(selectedItem.json)
else if selectedItem.type = "Audio"
m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("resetShuffle")
m.global.queueManager.callFunc("push", selectedItem.json)
m.global.queueManager.callFunc("playQueue")
else
@@ -280,6 +281,7 @@ sub Main (args as dynamic) as void
screenContent = msg.getRoSGNode()
m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("resetShuffle")
m.global.queueManager.callFunc("push", screenContent.albumData.items[selectedIndex])
m.global.queueManager.callFunc("playQueue")
else if isNodeEvent(msg, "playItem")
@@ -288,6 +290,7 @@ sub Main (args as dynamic) as void
screenContent = msg.getRoSGNode()
m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("resetShuffle")
m.global.queueManager.callFunc("push", screenContent.albumData.items[selectedIndex])
m.global.queueManager.callFunc("playQueue")
else if isNodeEvent(msg, "playAllSelected")
@@ -297,6 +300,7 @@ sub Main (args as dynamic) as void
m.spinner.visible = true
m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("resetShuffle")
m.global.queueManager.callFunc("set", screenContent.albumData.items)
m.global.queueManager.callFunc("playQueue")
else if isNodeEvent(msg, "playArtistSelected")
@@ -304,6 +308,7 @@ sub Main (args as dynamic) as void
screenContent = msg.getRoSGNode()
m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("resetShuffle")
m.global.queueManager.callFunc("set", CreateArtistMix(screenContent.pageContent.id).Items)
m.global.queueManager.callFunc("playQueue")
@@ -323,6 +328,7 @@ sub Main (args as dynamic) as void
if isValid(screenContent.albumData.items)
if screenContent.albumData.items.count() > 0
m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("resetShuffle")
m.global.queueManager.callFunc("set", CreateInstantMix(screenContent.albumData.items[0].id).Items)
m.global.queueManager.callFunc("playQueue")
@@ -334,6 +340,7 @@ sub Main (args as dynamic) as void
if not viewHandled
' Create instant mix based on selected artist
m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("resetShuffle")
m.global.queueManager.callFunc("set", CreateInstantMix(screenContent.pageContent.id).Items)
m.global.queueManager.callFunc("playQueue")
end if
@@ -381,6 +388,7 @@ sub Main (args as dynamic) as void
group = CreateAlbumView(node.json)
else if node.type = "Audio"
m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("resetShuffle")
m.global.queueManager.callFunc("push", node.json)
m.global.queueManager.callFunc("playQueue")
else if node.type = "Person"
@@ -395,6 +403,7 @@ sub Main (args as dynamic) as void
selectedIndex = msg.getData()
screenContent = msg.getRoSGNode()
m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("resetShuffle")
m.global.queueManager.callFunc("push", screenContent.albumData.items[node.id])
m.global.queueManager.callFunc("playQueue")
else