diff --git a/components/ItemGrid/ItemGrid.brs b/components/ItemGrid/ItemGrid.brs
index a1d57ab51..e740c7aac 100644
--- a/components/ItemGrid/ItemGrid.brs
+++ b/components/ItemGrid/ItemGrid.brs
@@ -725,6 +725,7 @@ sub showTVGuide()
m.tvGuide.filter = m.filter
m.tvGuide.searchTerm = m.voiceBox.text
m.top.appendChild(m.tvGuide)
+ m.scheduleGrid = m.top.findNode("scheduleGrid")
m.tvGuide.lastFocus.setFocus(true)
end sub
@@ -742,6 +743,18 @@ sub onChannelFocused(msg)
m.channelFocused = node.focusedChannel
end sub
+'Returns Focused Item
+function getItemFocused()
+ if m.itemGrid.isinFocusChain() and isValid(m.itemGrid.itemFocused)
+ return m.itemGrid.content.getChild(m.itemGrid.itemFocused)
+ else if m.genreList.isinFocusChain() and isValid(m.genreList.rowItemFocused)
+ return m.genreList.content.getChild(m.genreList.rowItemFocused[0]).getChild(m.genreList.rowItemFocused[1])
+ else if m.scheduleGrid.isinFocusChain() and isValid(m.scheduleGrid.itemFocused)
+ return m.scheduleGrid.content.getChild(m.scheduleGrid.itemFocused)
+ end if
+ return invalid
+end function
+
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
@@ -788,11 +801,11 @@ function onKeyEvent(key as string, press as boolean) as boolean
m.loadItemsTask.control = "stop"
return true
end if
- else if key = "play" or key = "OK"
+ else if key = "play"
markupGrid = m.top.findNode("itemGrid")
- itemToPlay = markupGrid.content.getChild(markupGrid.itemFocused)
+ itemToPlay = getItemFocused()
- if itemToPlay <> invalid and (itemToPlay.type = "Movie" or itemToPlay.type = "Episode")
+ if itemToPlay <> invalid
m.top.quickPlayNode = itemToPlay
return true
else if itemToPlay <> invalid and itemToPlay.type = "Photo"
diff --git a/components/ItemGrid/MovieLibraryView.brs b/components/ItemGrid/MovieLibraryView.brs
index e36ae141e..817573c62 100644
--- a/components/ItemGrid/MovieLibraryView.brs
+++ b/components/ItemGrid/MovieLibraryView.brs
@@ -708,7 +708,12 @@ end sub
'
'Returns Focused Item
function getItemFocused()
- return m.itemGrid.content.getChild(m.itemGrid.itemFocused)
+ if m.itemGrid.isinFocusChain() and isValid(m.itemGrid.itemFocused)
+ return m.itemGrid.content.getChild(m.itemGrid.itemFocused)
+ else if m.genreList.isinFocusChain() and isValid(m.genreList.rowItemFocused)
+ return m.genreList.content.getChild(m.genreList.rowItemFocused[0]).getChild(m.genreList.rowItemFocused[1])
+ end if
+ return invalid
end function
'
@@ -870,11 +875,10 @@ function onKeyEvent(key as string, press as boolean) as boolean
m.loadItemsTask.control = "stop"
return true
end if
- else if key = "play" or key = "OK"
-
+ else if key = "play"
itemToPlay = getItemFocused()
- if itemToPlay <> invalid and (itemToPlay.type = "Movie" or itemToPlay.type = "Episode")
+ if itemToPlay <> invalid
m.top.quickPlayNode = itemToPlay
return true
end if
diff --git a/components/ItemGrid/MusicLibraryView.brs b/components/ItemGrid/MusicLibraryView.brs
index b11b8dacc..1573a016e 100644
--- a/components/ItemGrid/MusicLibraryView.brs
+++ b/components/ItemGrid/MusicLibraryView.brs
@@ -573,7 +573,12 @@ end sub
'
'Returns Focused Item
function getItemFocused()
- return m.itemGrid.content.getChild(m.itemGrid.itemFocused)
+ if m.itemGrid.isinFocusChain() and isValid(m.itemGrid.itemFocused)
+ return m.itemGrid.content.getChild(m.itemGrid.itemFocused)
+ else if m.genreList.isinFocusChain() and isValid(m.genreList.itemFocused)
+ return m.genreList.content.getChild(m.genreList.itemFocused)
+ end if
+ return invalid
end function
'
@@ -751,7 +756,6 @@ function onKeyEvent(key as string, press as boolean) as boolean
alpha.setFocus(true)
return true
end if
-
else if key = "right" and m.Alpha.isinFocusChain()
m.top.alphaActive = false
m.Alpha.setFocus(false)
@@ -761,14 +765,12 @@ function onKeyEvent(key as string, press as boolean) as boolean
m.genreList.setFocus(m.genreList.opacity = 1)
return true
-
else if key = "replay" and m.itemGrid.isinFocusChain()
if m.resetGrid = true
m.itemGrid.animateToItem = 0
else
m.itemGrid.jumpToItem = 0
end if
-
else if key = "replay" and m.genreList.isinFocusChain()
if m.resetGrid = true
m.genreList.animateToItem = 0
@@ -776,6 +778,12 @@ function onKeyEvent(key as string, press as boolean) as boolean
m.genreList.jumpToItem = 0
end if
return true
+ else if key = "play"
+ itemToPlay = getItemFocused()
+ if itemToPlay <> invalid
+ m.top.quickPlayNode = itemToPlay
+ return true
+ end if
end if
if key = "replay"
diff --git a/components/data/HomeData.brs b/components/data/HomeData.brs
index 4266cc709..bba8aeca9 100644
--- a/components/data/HomeData.brs
+++ b/components/data/HomeData.brs
@@ -31,7 +31,7 @@ sub setData()
m.top.iconUrl = "pkg:/images/media_type_icons/folder_white.png"
end if
- else if datum.type = "Episode"
+ else if datum.type = "Episode" or datum.type = "MusicVideo"
m.top.isWatched = datum.UserData.Played
imgParams = {}
@@ -72,32 +72,7 @@ sub setData()
m.top.widePosterUrl = ImageURL(datum.Id, "Backdrop", imgParams)
end if
- else if datum.type = "Movie"
- m.top.isWatched = datum.UserData.Played
-
- imgParams = {}
- imgParams.Append({ "maxHeight": 261 })
- imgParams.Append({ "maxWidth": 175 })
-
- if datum.ImageTags.Primary <> invalid
- param = { "Tag": datum.ImageTags.Primary }
- imgParams.Append(param)
- end if
-
- m.top.posterURL = ImageURL(datum.id, "Primary", imgParams)
-
- ' For wide image, use backdrop
- imgParams["maxWidth"] = 464
-
- if datum.ImageTags <> invalid and datum.imageTags.Thumb <> invalid
- imgParams["Tag"] = datum.imageTags.Thumb
- m.top.thumbnailUrl = ImageURL(datum.Id, "Thumb", imgParams)
- else if datum.BackdropImageTags[0] <> invalid
- imgParams["Tag"] = datum.BackdropImageTags[0]
- m.top.thumbnailUrl = ImageURL(datum.id, "Backdrop", imgParams)
- end if
-
- else if datum.type = "Video"
+ else if datum.type = "Movie" or datum.type = "Video"
m.top.isWatched = datum.UserData.Played
imgParams = {}
@@ -126,12 +101,10 @@ sub setData()
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
m.top.widePosterUrl = m.top.thumbnailURL
m.top.posterUrl = m.top.thumbnailURL
-
else if datum.type = "TvChannel" or datum.type = "Channel"
params = { "Tag": datum.ImageTags.Primary, "maxHeight": 261, "maxWidth": 464 }
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
m.top.widePosterUrl = m.top.thumbnailURL
m.top.iconUrl = "pkg:/images/media_type_icons/live_tv_white.png"
end if
-
end sub
diff --git a/components/extras/ExtrasRowList.brs b/components/extras/ExtrasRowList.brs
index 230622cdd..c008795aa 100644
--- a/components/extras/ExtrasRowList.brs
+++ b/components/extras/ExtrasRowList.brs
@@ -3,6 +3,7 @@ sub init()
updateSize()
m.top.rowFocusAnimationStyle = "fixedFocus"
m.top.observeField("rowItemSelected", "onRowItemSelected")
+ m.top.observeField("rowItemFocused", "onRowItemFocused")
' Set up all Tasks
m.LoadPeopleTask = CreateObject("roSGNode", "LoadItemsTask")
@@ -207,3 +208,7 @@ end sub
sub onRowItemSelected()
m.top.selectedItem = m.top.content.getChild(m.top.rowItemSelected[0]).getChild(m.top.rowItemSelected[1])
end sub
+
+sub onRowItemFocused()
+ m.top.focusedItem = m.top.content.getChild(m.top.rowItemFocused[0]).getChild(m.top.rowItemFocused[1])
+end sub
diff --git a/components/extras/ExtrasRowList.xml b/components/extras/ExtrasRowList.xml
index 8245dd2d8..55f96a421 100644
--- a/components/extras/ExtrasRowList.xml
+++ b/components/extras/ExtrasRowList.xml
@@ -4,6 +4,7 @@
+
diff --git a/components/home/HomeItem.brs b/components/home/HomeItem.brs
index 8fb835290..29c2f1342 100644
--- a/components/home/HomeItem.brs
+++ b/components/home/HomeItem.brs
@@ -30,6 +30,7 @@ end sub
sub itemContentChanged()
itemData = m.top.itemContent
if itemData = invalid then return
+
itemData.Title = itemData.name ' Temporarily required while we move from "HomeItem" to "JFContentItem"
m.itemPoster.width = itemData.imageWidth
@@ -135,7 +136,7 @@ sub itemContentChanged()
return
end if
- if itemData.type = "Movie"
+ if itemData.type = "Movie" or itemData.type = "MusicVideo"
m.itemText.text = itemData.name
if itemData.PlayedPercentage > 0
diff --git a/components/home/HomeRows.brs b/components/home/HomeRows.brs
index 68a4a9ecd..609c42b89 100644
--- a/components/home/HomeRows.brs
+++ b/components/home/HomeRows.brs
@@ -522,21 +522,20 @@ sub itemSelected()
end sub
function onKeyEvent(key as string, press as boolean) as boolean
- handled = false
if press
if key = "play"
+ print "play was pressed from homerow"
itemToPlay = m.top.content.getChild(m.top.rowItemFocused[0]).getChild(m.top.rowItemFocused[1])
- if isValid(itemToPlay) and (itemToPlay.type = "Movie" or itemToPlay.type = "Episode")
+ if isValid(itemToPlay)
m.top.quickPlayNode = itemToPlay
end if
- handled = true
- end if
-
- if key = "replay"
+ return true
+ else if key = "replay"
m.top.jumpToRowItem = [m.top.rowItemFocused[0], 0]
+ return true
end if
end if
- return handled
+ return false
end function
function filterNodeArray(nodeArray as object, nodeKey as string, excludeArray as object) as object
diff --git a/components/home/HomeRows.xml b/components/home/HomeRows.xml
index 5c0dcfc03..77d91aeb6 100644
--- a/components/home/HomeRows.xml
+++ b/components/home/HomeRows.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/components/home/LoadItemsTask.brs b/components/home/LoadItemsTask.brs
index 79bb2d387..1ea788439 100644
--- a/components/home/LoadItemsTask.brs
+++ b/components/home/LoadItemsTask.brs
@@ -137,7 +137,8 @@ sub loadItems()
if isValid(data) and isValid(data.Items)
for each item in data.Items
' Skip Books for now as we don't support it (issue #558)
- if item.Type <> "Book"
+ ' also skip songs since there is limited space
+ if not (item.Type = "Book" or item.Type = "Audio")
tmp = CreateObject("roSGNode", "HomeData")
params = {}
diff --git a/components/manager/QueueManager.brs b/components/manager/QueueManager.brs
index ca9f30fa2..4a5b14b9e 100644
--- a/components/manager/QueueManager.brs
+++ b/components/manager/QueueManager.brs
@@ -11,6 +11,7 @@ sub init()
m.queue = []
m.originalQueue = []
m.queueTypes = []
+ m.isPlaying = false
' Preroll videos only play if user has cinema mode setting enabled
m.isPrerollActive = m.global.session.user.settings["playback.cinemamode"]
m.position = 0
@@ -19,6 +20,7 @@ end sub
' Clear all content from play queue
sub clear()
+ m.isPlaying = false
m.queue = []
m.queueTypes = []
m.isPrerollActive = m.global.session.user.settings["playback.cinemamode"]
@@ -111,6 +113,7 @@ end function
' Play items in queue
sub playQueue()
+ m.isPlaying = true
nextItem = getCurrentItem()
if not isValid(nextItem) then return
@@ -122,11 +125,21 @@ sub playQueue()
return
end if
+ if nextItemMediaType = "musicvideo"
+ CreateVideoPlayerView()
+ return
+ end if
+
if nextItemMediaType = "video"
CreateVideoPlayerView()
return
end if
+ if nextItemMediaType = "movie"
+ CreateVideoPlayerView()
+ return
+ end if
+
if nextItemMediaType = "episode"
CreateVideoPlayerView()
return
@@ -196,21 +209,25 @@ end function
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
+ itemIDArray = getQueue()
+ temp = invalid
+
+ if m.isPlaying
+ ' Save the currently playing item
+ temp = getCurrentItem()
+ ' remove currently playing item from itemIDArray
+ itemIDArray.Delete(m.position)
+ end if
+
+ ' shuffle all items
+ itemIDArray = shuffleArray(itemIDArray)
+
+ if m.isPlaying
+ ' Put currently playing item in front of itemIDArray
+ itemIDArray.Unshift(temp)
+ end if
- set(songIDArray)
+ set(itemIDArray)
end sub
' Return the fitst item in the play queue
diff --git a/components/movies/MovieDetails.brs b/components/movies/MovieDetails.brs
index 913ccd796..123a4a939 100644
--- a/components/movies/MovieDetails.brs
+++ b/components/movies/MovieDetails.brs
@@ -385,6 +385,12 @@ function onKeyEvent(key as string, press as boolean) as boolean
audioOptionsClosed()
return true
end if
+ else if key = "play" and m.extrasGrid.hasFocus()
+ print "Play was pressed from the movie details extras slider"
+ if m.extrasGrid.focusedItem <> invalid
+ m.top.quickPlayNode = m.extrasGrid.focusedItem
+ return true
+ end if
end if
return false
end function
diff --git a/components/movies/MovieDetails.xml b/components/movies/MovieDetails.xml
index cb850da0f..01222f140 100644
--- a/components/movies/MovieDetails.xml
+++ b/components/movies/MovieDetails.xml
@@ -50,5 +50,6 @@
+
\ No newline at end of file
diff --git a/components/music/ArtistView.brs b/components/music/ArtistView.brs
index 38336ecf2..4d9365690 100644
--- a/components/music/ArtistView.brs
+++ b/components/music/ArtistView.brs
@@ -313,5 +313,21 @@ function onKeyEvent(key as string, press as boolean) as boolean
end if
end if
+ if key = "play"
+ print "play button pressed from ArtistView"
+ itemToPlay = invalid
+
+ if isValid(m.albums) and m.albums.isInFocusChain()
+ itemToPlay = m.albums.MusicArtistAlbumData.items[m.albums.itemFocused]
+ else if isValid(m.appearsOn) and m.appearsOn.isInFocusChain()
+ itemToPlay = m.appearsOn.MusicArtistAlbumData.items[m.appearsOn.itemFocused]
+ end if
+
+ if isValid(itemToPlay)
+ m.top.quickPlayNode = itemToPlay
+ return true
+ end if
+ end if
+
return false
end function
diff --git a/components/music/ArtistView.xml b/components/music/ArtistView.xml
index c8b9be042..64f3d8ebc 100644
--- a/components/music/ArtistView.xml
+++ b/components/music/ArtistView.xml
@@ -54,5 +54,6 @@
+
\ No newline at end of file
diff --git a/components/tvshows/TVEpisodes.xml b/components/tvshows/TVEpisodes.xml
index c87d404d9..ec2dd9520 100644
--- a/components/tvshows/TVEpisodes.xml
+++ b/components/tvshows/TVEpisodes.xml
@@ -12,7 +12,7 @@
-
+
diff --git a/components/tvshows/TVShowDetails.brs b/components/tvshows/TVShowDetails.brs
index e5e1ead44..a8006df43 100644
--- a/components/tvshows/TVShowDetails.brs
+++ b/components/tvshows/TVShowDetails.brs
@@ -11,6 +11,7 @@ sub init()
m.getShuffleEpisodesTask = createObject("roSGNode", "getShuffleEpisodesTask")
m.Shuffle = m.top.findNode("Shuffle")
m.extrasSlider.visible = true
+ m.seasons = m.top.findNode("seasons")
end sub
sub itemContentChanged()
@@ -223,6 +224,20 @@ function onKeyEvent(key as string, press as boolean) as boolean
else if key = "up" and m.Shuffle.hasFocus()
overview.setFocus(true)
return true
+ else if key = "play" and m.seasons.hasFocus()
+ print "play was pressed from the seasons row"
+ if isValid(m.seasons.TVSeasonData) and isValid(m.seasons.TVSeasonData.Items)
+ itemFocused = m.seasons.rowItemFocused
+ m.top.quickPlayNode = m.seasons.TVSeasonData.Items[itemFocused[1]]
+ return true
+ end if
+ else if key = "play" and m.extrasSlider.isInFocusChain()
+ print "play was pressed from the extras grid"
+ extrasGrid = m.top.findNode("extrasGrid")
+ if extrasGrid.focusedItem <> invalid
+ m.top.quickPlayNode = extrasGrid.focusedItem
+ return true
+ end if
end if
return false
diff --git a/components/tvshows/TVShowDetails.xml b/components/tvshows/TVShowDetails.xml
index 4c42dfd52..197ee81cf 100644
--- a/components/tvshows/TVShowDetails.xml
+++ b/components/tvshows/TVShowDetails.xml
@@ -32,5 +32,6 @@
+
\ No newline at end of file
diff --git a/source/Main.brs b/source/Main.brs
index 347f4b632..f2d0ecf05 100644
--- a/source/Main.brs
+++ b/source/Main.brs
@@ -125,48 +125,89 @@ sub Main (args as dynamic) as void
group.setFocus(true)
end if
else if isNodeEvent(msg, "quickPlayNode")
+ ' measure processing time
+ timeSpan = CreateObject("roTimespan")
+
+ startMediaLoadingSpinner()
+
group = sceneManager.callFunc("getActiveScene")
reportingNode = msg.getRoSGNode()
- itemNode = reportingNode.quickPlayNode
+ itemNode = invalid
+ if isValid(reportingNode)
+ itemNode = reportingNode.quickPlayNode
+ reportingNodeType = reportingNode.subtype()
+ print "Quick Play reporting node type=", reportingNodeType
+ ' prevent double fire bug
+ if isValid(reportingNodeType) and (reportingNodeType = "Home" or reportingNodeType = "TVEpisodes")
+ reportingNode.quickPlayNode = invalid
+ end if
+ end if
+ print "Quick Play started. itemNode=", itemNode
+ ' if itemNode.json <> invalid
+ ' print "itemNode.json=", itemNode.json
+ ' end if
if isValid(itemNode) and isValid(itemNode.id) and itemNode.id <> ""
- if itemNode.type = "Episode" or itemNode.type = "Movie" or itemNode.type = "Video"
- if isValid(itemNode.selectedVideoStreamId)
- itemNode.id = itemNode.selectedVideoStreamId
- end if
-
- audio_stream_idx = 0
- if isValid(itemNode.selectedAudioStreamIndex) and itemNode.selectedAudioStreamIndex > 0
- audio_stream_idx = itemNode.selectedAudioStreamIndex
- end if
-
- itemNode.selectedAudioStreamIndex = audio_stream_idx
-
- playbackPosition = 0
-
- ' Display playback options dialog
- if isValid(itemNode.json) and isValid(itemNode.json.userdata) and isValid(itemNode.json.userdata.PlaybackPositionTicks)
- playbackPosition = itemNode.json.userdata.PlaybackPositionTicks
- end if
-
- if playbackPosition > 0
- m.global.queueManager.callFunc("hold", itemNode)
- playbackOptionDialog(playbackPosition, itemNode.json)
- else
- m.global.queueManager.callFunc("clear")
- m.global.queueManager.callFunc("push", itemNode)
- m.global.queueManager.callFunc("playQueue")
+ ' make sure there is a type and convert type to lowercase
+ itemType = invalid
+ if isValid(itemNode.type) and itemNode.type <> ""
+ itemType = Lcase(itemNode.type)
+ else
+ ' grab type from json and convert to lowercase
+ if isValid(itemNode.json) and isValid(itemNode.json.type)
+ itemType = Lcase(itemNode.json.type)
end if
-
- ' Prevent quick play node from double firing
- reportingNode.quickPlayNode = invalid
-
- if LCase(group.subtype()) = "tvepisodes"
- if isValid(group.lastFocus)
- group.lastFocus.setFocus(true)
+ end if
+ print "Quick Play itemNode type=", itemType
+
+ ' can't play the item without knowing what type it is
+ if isValid(itemType)
+ m.global.queueManager.callFunc("clear") ' empty queue/playlist
+ m.global.queueManager.callFunc("resetShuffle") ' turn shuffle off
+
+ if itemType = "episode" or itemType = "movie" or itemType = "video"
+ quickplay.video(itemNode)
+ ' restore focus
+ if LCase(group.subtype()) = "tvepisodes"
+ if isValid(group.lastFocus)
+ group.lastFocus.setFocus(true)
+ end if
end if
+ else if itemType = "audio"
+ quickplay.audio(itemNode)
+ else if itemType = "musicalbum"
+ quickplay.album(itemNode)
+ else if itemType = "musicartist"
+ quickplay.artist(itemNode)
+ else if itemType = "series"
+ quickplay.series(itemNode)
+ else if itemType = "season"
+ quickplay.season(itemNode)
+ else if itemType = "boxset"
+ quickplay.boxset(itemNode)
+ else if itemType = "collectionfolder"
+ quickplay.collectionFolder(itemNode)
+ else if itemType = "playlist"
+ quickplay.playlist(itemNode)
+ else if itemType = "userview"
+ quickplay.userView(itemNode)
+ else if itemType = "folder"
+ quickplay.folder(itemNode)
+ else if itemType = "musicvideo"
+ quickplay.musicVideo(itemNode)
+ else if itemType = "person"
+ quickplay.person(itemNode)
+ else if itemType = "tvchannel"
+ quickplay.tvChannel(itemNode)
+ else if itemType = "program"
+ quickplay.program(itemNode)
end if
+
+ m.global.queueManager.callFunc("playQueue")
end if
end if
+ stopLoadingSpinner()
+ elapsed = timeSpan.TotalMilliseconds() / 1000
+ print "Quick Play finished loading in " + elapsed.toStr() + " seconds."
else if isNodeEvent(msg, "selectedItem")
' If you select a library from ANYWHERE, follow this flow
selectedItem = msg.getData()
@@ -259,6 +300,8 @@ sub Main (args as dynamic) as void
end if
else if selectedItemType = "MusicAlbum"
group = CreateAlbumView(selectedItem.json)
+ else if selectedItemType = "MusicVideo"
+ group = CreateMovieDetailsGroup(selectedItem)
else if selectedItemType = "Playlist"
group = CreatePlaylistView(selectedItem.json)
else if selectedItemType = "Audio"
@@ -397,6 +440,8 @@ sub Main (args as dynamic) as void
group = CreateArtistView(node.json)
else if node.type = "MusicAlbum"
group = CreateAlbumView(node.json)
+ else if node.type = "MusicVideo"
+ group = CreateMovieDetailsGroup(node)
else if node.type = "Audio"
m.global.queueManager.callFunc("clear")
m.global.queueManager.callFunc("resetShuffle")
@@ -621,6 +666,7 @@ sub Main (args as dynamic) as void
' - "low" means that the general memory is below acceptable levels but not critical
' - "critical" means that general memory are at dangerously low level and that the OS may force terminate the application
print "event.generalMemoryLevel = ", event.generalMemoryLevel
+ session.Update("memoreyLevel", event.generalMemoryLevel)
else if isValid(event.audioCodecCapabilityChanged)
' The audio codec capability has changed if true.
print "event.audioCodecCapabilityChanged = ", event.audioCodecCapabilityChanged
diff --git a/source/ShowScenes.brs b/source/ShowScenes.brs
index 28d38b845..ebac0c585 100644
--- a/source/ShowScenes.brs
+++ b/source/ShowScenes.brs
@@ -598,6 +598,7 @@ function CreateMovieDetailsGroup(movie as object) as dynamic
end if
' start building MovieDetails view
group = CreateObject("roSGNode", "MovieDetails")
+ group.observeField("quickPlayNode", m.port)
group.overhangTitle = movie.title
group.optionsAvailable = false
group.trailerAvailable = false
@@ -651,6 +652,7 @@ function CreateSeriesDetailsGroup(seriesID as string) as dynamic
group.seasonData = seasonData
' watch for button presses
group.observeField("seasonSelected", m.port)
+ group.observeField("quickPlayNode", m.port)
' setup and load series extras
extras = group.findNode("extrasGrid")
extras.observeField("selectedItem", m.port)
@@ -703,6 +705,7 @@ function CreateArtistView(artist as object) as dynamic
group.observeField("appearsOnSelected", m.port)
end if
+ group.observeField("quickPlayNode", m.port)
m.global.sceneManager.callFunc("pushScene", group)
return group
@@ -821,6 +824,7 @@ function CreateItemGrid(libraryItem as object) as dynamic
group.parentItem = libraryItem
group.optionsAvailable = true
group.observeField("selectedItem", m.port)
+ group.observeField("quickPlayNode", m.port)
return group
end function
@@ -832,6 +836,7 @@ function CreateMovieLibraryView(libraryItem as object) as dynamic
group.parentItem = libraryItem
group.optionsAvailable = true
group.observeField("selectedItem", m.port)
+ group.observeField("quickPlayNode", m.port)
return group
end function
@@ -843,6 +848,7 @@ function CreateMusicLibraryView(libraryItem as object) as dynamic
group.parentItem = libraryItem
group.optionsAvailable = true
group.observeField("selectedItem", m.port)
+ group.observeField("quickPlayNode", m.port)
return group
end function
diff --git a/source/api/Items.brs b/source/api/Items.brs
index 699c8de6d..90f77458d 100644
--- a/source/api/Items.brs
+++ b/source/api/Items.brs
@@ -225,15 +225,20 @@ function AppearsOnList(id as string)
end function
' Get list of songs belonging to an artist
-function GetSongsByArtist(id as string)
+function GetSongsByArtist(id as string, params = {} as object)
url = Substitute("Users/{0}/Items", m.global.session.user.id)
- resp = APIRequest(url, {
+ paramArray = {
"AlbumArtistIds": id,
"includeitemtypes": "Audio",
"sortBy": "SortName",
"Recursive": true
- })
+ }
+ ' overwrite defaults with the params provided
+ for each param in params
+ paramArray.AddReplace(param, params[param])
+ end for
+ resp = APIRequest(url, paramArray)
data = getJson(resp)
results = []
@@ -410,7 +415,7 @@ function TVSeasons(id as string) as dynamic
results = []
for each item in data.Items
imgParams = { "AddPlayedIndicator": item.UserData.Played }
- tmp = CreateObject("roSGNode", "TVEpisodeData")
+ tmp = CreateObject("roSGNode", "TVSeasonData")
tmp.image = PosterImage(item.id, imgParams)
tmp.json = item
results.push(tmp)
diff --git a/source/api/sdk.bs b/source/api/sdk.bs
index 38ef4929a..9cd713f91 100644
--- a/source/api/sdk.bs
+++ b/source/api/sdk.bs
@@ -1200,8 +1200,8 @@ namespace api
end function
' Gets the original items of a playlist.
- function GetItems(id as string, params = {} as object)
- req = APIRequest(Substitute("/playlists/{0}/items", id), params)
+ function GetItems(playlistID as string, params = {} as object)
+ req = APIRequest(Substitute("/playlists/{0}/items", playlistID), params)
return getJson(req)
end function
diff --git a/source/utils/misc.brs b/source/utils/misc.brs
index f91b8b16c..4138a0c9a 100644
--- a/source/utils/misc.brs
+++ b/source/utils/misc.brs
@@ -392,3 +392,13 @@ function arrayHasValue(arr as object, value as dynamic) as boolean
end for
return false
end function
+
+' Takes an array of data, shuffles the order, then returns the array
+' uses the Fisher-Yates shuffling algorithm
+function shuffleArray(array as object) as object
+ for i = array.count() - 1 to 1 step -1
+ j = Rnd(i + 1) - 1
+ t = array[i] : array[i] = array[j] : array[j] = t
+ end for
+ return array
+end function
diff --git a/source/utils/quickplay.bs b/source/utils/quickplay.bs
new file mode 100644
index 000000000..794d8ef67
--- /dev/null
+++ b/source/utils/quickplay.bs
@@ -0,0 +1,585 @@
+' All of the Quick Play logic seperated by media type
+namespace quickplay
+
+ ' Takes an array of items and adds to global queue.
+ ' Also shuffles the playlist if asked
+ sub pushToQueue(queueArray as object, shufflePlay = false as boolean)
+ if isValidAndNotEmpty(queueArray)
+ ' load everything
+ for each item in queueArray
+ m.global.queueManager.callFunc("push", item)
+ end for
+ ' shuffle the playlist if asked
+ if shufflePlay and m.global.queueManager.callFunc("getCount") > 1
+ m.global.queueManager.callFunc("toggleShuffle")
+ end if
+ end if
+ end sub
+
+ ' A single video file.
+ sub video(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.id) or not isValid(itemNode.json) then return
+
+ ' attempt to play video file. resume if possible
+ if isValid(itemNode.selectedVideoStreamId)
+ itemNode.id = itemNode.selectedVideoStreamId
+ end if
+
+ audio_stream_idx = 0
+ if isValid(itemNode.selectedAudioStreamIndex) and itemNode.selectedAudioStreamIndex > 0
+ audio_stream_idx = itemNode.selectedAudioStreamIndex
+ end if
+ itemNode.selectedAudioStreamIndex = audio_stream_idx
+
+ playbackPosition = 0
+ if isValid(itemNode.json.userdata) and isValid(itemNode.json.userdata.PlaybackPositionTicks)
+ playbackPosition = itemNode.json.userdata.PlaybackPositionTicks
+ end if
+ itemNode.startingPoint = playbackPosition
+
+ m.global.queueManager.callFunc("push", itemNode)
+ end sub
+
+ ' A single audio file.
+ sub audio(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.id) then return
+
+ m.global.queueManager.callFunc("push", itemNode)
+ end sub
+
+ ' A single music video file.
+ sub musicVideo(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.id) or not isValid(itemNode.json) then return
+
+ m.global.queueManager.callFunc("push", itemNode)
+ end sub
+
+ ' A music album.
+ ' Play the entire album starting with track 1.
+ sub album(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.id) then return
+
+ ' grab list of songs in the album
+ albumSongs = api.users.GetItemsByQuery(m.global.session.user.id, {
+ "parentId": itemNode.id,
+ "imageTypeLimit": 1,
+ "sortBy": "SortName",
+ "limit": 2000,
+ "enableUserData": false,
+ "EnableTotalRecordCount": false
+ })
+ if isValid(albumSongs) and isValidAndNotEmpty(albumSongs.items)
+ quickplay.pushToQueue(albumSongs.items)
+ end if
+ end sub
+
+ ' A music artist.
+ ' Shuffle play all songs by artist.
+ sub artist(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.id) then return
+
+ ' get all songs by artist
+ artistSongs = api.users.GetItemsByQuery(m.global.session.user.id, {
+ "artistIds": itemNode.id,
+ "includeItemTypes": "Audio",
+ "sortBy": "Album",
+ "limit": 2000,
+ "imageTypeLimit": 1,
+ "Recursive": true,
+ "enableUserData": false,
+ "EnableTotalRecordCount": false
+ })
+ print "artistSongs=", artistSongs
+
+ if isValid(artistSongs) and isValidAndNotEmpty(artistSongs.items)
+ quickplay.pushToQueue(artistSongs.items, true)
+ end if
+ end sub
+
+ ' A boxset.
+ ' Play all items inside.
+ sub boxset(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.id) then return
+
+ data = api.items.GetByQuery({
+ "userid": m.global.session.user.id,
+ "parentid": itemNode.id,
+ "limit": 2000,
+ "EnableTotalRecordCount": false
+ })
+ if isValid(data) and isValidAndNotEmpty(data.Items)
+ quickplay.pushToQueue(data.items)
+ end if
+ end sub
+
+ ' A TV Show Series.
+ ' Play the first unwatched episode.
+ ' If none, shuffle play the whole series.
+ sub series(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.id) then return
+
+ data = api.shows.GetNextUp({
+ "seriesId": itemNode.id,
+ "recursive": true,
+ "SortBy": "DatePlayed",
+ "SortOrder": "Descending",
+ "ImageTypeLimit": 1,
+ "UserId": m.global.session.user.id,
+ "EnableRewatching": false,
+ "DisableFirstEpisode": false,
+ "EnableTotalRecordCount": false
+ })
+
+ if isValid(data) and isValidAndNotEmpty(data.Items)
+ ' there are unwatched episodes
+ m.global.queueManager.callFunc("push", data.Items[0])
+ else
+ ' next up check was empty
+ ' check for a resumable episode
+ data = api.users.GetResumeItemsByQuery(m.global.session.user.id, {
+ "parentId": itemNode.id,
+ "userid": m.global.session.user.id,
+ "SortBy": "DatePlayed",
+ "recursive": true,
+ "SortOrder": "Descending",
+ "Filters": "IsResumable",
+ "EnableTotalRecordCount": false
+ })
+ print "resumeitems data=", data
+ if isValid(data) and isValidAndNotEmpty(data.Items)
+ ' play the resumable episode
+ if isValid(data.Items[0].UserData) and isValid(data.Items[0].UserData.PlaybackPositionTicks)
+ data.Items[0].startingPoint = data.Items[0].userdata.PlaybackPositionTicks
+ end if
+ m.global.queueManager.callFunc("push", data.Items[0])
+ else
+ ' shuffle all episodes
+ data = api.shows.GetEpisodes(itemNode.id, {
+ "userid": m.global.session.user.id,
+ "SortBy": "Random",
+ "limit": 2000,
+ "EnableTotalRecordCount": false
+ })
+
+ if isValid(data) and isValidAndNotEmpty(data.Items)
+ ' add all episodes found to a playlist
+ quickplay.pushToQueue(data.Items)
+ end if
+ end if
+ end if
+ end sub
+
+ ' More than one TV Show Series.
+ ' Shuffle play all watched episodes
+ sub multipleSeries(itemNodes as object)
+ if isValidAndNotEmpty(itemNodes)
+ numTotal = 0
+ numLimit = 2000
+ for each tvshow in itemNodes
+ ' grab all watched episodes for each series
+ showData = api.shows.GetEpisodes(tvshow.id, {
+ "userId": m.global.session.user.id,
+ "SortBy": "Random",
+ "imageTypeLimit": 0,
+ "EnableTotalRecordCount": false,
+ "enableImages": false
+ })
+
+ if isValid(showData) and isValidAndNotEmpty(showData.items)
+ playedEpisodes = []
+ ' add all played episodes to queue
+ for each episode in showData.items
+ if isValid(episode.userdata) and isValid(episode.userdata.Played)
+ if episode.userdata.Played
+ playedEpisodes.push(episode)
+ end if
+ end if
+ end for
+ quickplay.pushToQueue(playedEpisodes)
+
+ ' keep track of how many items we've seen
+ numTotal = numTotal + showData.items.count()
+ if numTotal >= numLimit
+ ' stop grabbing more items if we hit our limit
+ exit for
+ end if
+ end if
+ end for
+ if m.global.queueManager.callFunc("getCount") > 1
+ m.global.queueManager.callFunc("toggleShuffle")
+ end if
+ end if
+ end sub
+
+ ' A TV Show Season.
+ ' Play the first unwatched episode.
+ ' If none, play the whole season starting with episode 1.
+ sub season(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.id) then return
+
+ unwatchedData = api.shows.GetEpisodes(itemNode.json.SeriesId, {
+ "seasonId": itemNode.id,
+ "userid": m.global.session.user.id,
+ "limit": 2000,
+ "EnableTotalRecordCount": false
+ })
+
+ if isValid(unwatchedData) and isValidAndNotEmpty(unwatchedData.Items)
+ ' find the first unwatched episode
+ firstUnwatchedEpisodeIndex = invalid
+ for each item in unwatchedData.Items
+ if isValid(item.UserData)
+ if isValid(item.UserData.Played) and item.UserData.Played = false
+ firstUnwatchedEpisodeIndex = item.IndexNumber - 1
+ if isValid(item.UserData.PlaybackPositionTicks)
+ item.startingPoint = item.UserData.PlaybackPositionTicks
+ end if
+ exit for
+ end if
+ end if
+ end for
+
+ if isValid(firstUnwatchedEpisodeIndex)
+ ' add the first unwatched episode and the rest of the season to a playlist
+ for i = firstUnwatchedEpisodeIndex to unwatchedData.Items.count() - 1
+ m.global.queueManager.callFunc("push", unwatchedData.Items[i])
+ end for
+ else
+ ' try to find a "continue watching" episode
+ continueData = api.users.GetResumeItemsByQuery(m.global.session.user.id, {
+ "parentId": itemNode.id,
+ "userid": m.global.session.user.id,
+ "SortBy": "DatePlayed",
+ "recursive": true,
+ "SortOrder": "Descending",
+ "Filters": "IsResumable",
+ "EnableTotalRecordCount": false
+ })
+
+ if isValid(continueData) and isValidAndNotEmpty(continueData.Items)
+ ' play the resumable episode
+ for each item in continueData.Items
+ if isValid(item.UserData) and isValid(item.UserData.PlaybackPositionTicks)
+ item.startingPoint = item.userdata.PlaybackPositionTicks
+ end if
+ m.global.queueManager.callFunc("push", item)
+ end for
+ else
+ ' play the whole season in order
+ if isValid(unwatchedData) and isValidAndNotEmpty(unwatchedData.Items)
+ ' add all episodes found to a playlist
+ pushToQueue(unwatchedData.Items)
+ end if
+ end if
+ end if
+ end if
+ end sub
+
+ ' Quick Play A Person.
+ ' Shuffle play all videos found
+ sub person(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.id) then return
+ ' get movies and videos by the person
+ personMovies = api.users.GetItemsByQuery(m.global.session.user.id, {
+ "personIds": itemNode.id,
+ "includeItemTypes": "Movie,Video",
+ "excludeItemTypes": "Season,Series",
+ "recursive": true,
+ "limit": 2000
+ })
+ print "personMovies=", personMovies
+
+ if isValid(personMovies) and isValidAndNotEmpty(personMovies.Items)
+ ' add each item to the queue
+ quickplay.pushToQueue(personMovies.Items)
+ end if
+
+ ' get watched episodes by the person
+ personEpisodes = api.users.GetItemsByQuery(m.global.session.user.id, {
+ "personIds": itemNode.id,
+ "includeItemTypes": "Episode",
+ "isPlayed": true,
+ "excludeItemTypes": "Season,Series",
+ "recursive": true,
+ "limit": 2000
+ })
+ print "personEpisodes=", personEpisodes
+
+ if isValid(personEpisodes) and isValidAndNotEmpty(personEpisodes.Items)
+ ' add each item to the queue
+ quickplay.pushToQueue(personEpisodes.Items)
+ end if
+
+ if m.global.queueManager.callFunc("getCount") > 1
+ m.global.queueManager.callFunc("toggleShuffle")
+ end if
+ end sub
+
+ ' Quick Play A TVChannel
+ sub tvChannel(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.id) then return
+
+ stopLoadingSpinner()
+ group = CreateVideoPlayerGroup(itemNode.id)
+ m.global.sceneManager.callFunc("pushScene", group)
+ end sub
+
+ ' Quick Play A Live Program
+ sub program(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.json) or not isValid(itemNode.json.ChannelId) then return
+
+ stopLoadingSpinner()
+ group = CreateVideoPlayerGroup(itemNode.json.ChannelId)
+ m.global.sceneManager.callFunc("pushScene", group)
+ end sub
+
+ ' Quick Play A Playlist.
+ ' Play the first unwatched episode.
+ ' If none, play the whole season starting with episode 1.
+ sub playlist(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.id) then return
+ ' get playlist items
+ myPlaylist = api.playlists.GetItems(itemNode.id, {
+ "userId": m.global.session.user.id,
+ "limit": 2000
+ })
+
+ if isValid(myPlaylist) and isValidAndNotEmpty(myPlaylist.Items)
+ ' add each item to the queue
+ quickplay.pushToQueue(myPlaylist.Items)
+ if m.global.queueManager.callFunc("getCount") > 1
+ m.global.queueManager.callFunc("toggleShuffle")
+ end if
+ end if
+ end sub
+
+ ' Quick Play A folder.
+ ' Shuffle play all items found
+ sub folder(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.id) then return
+
+ paramArray = {
+ "includeItemTypes": ["Episode", "Movie", "Video"],
+ "videoTypes": "VideoFile",
+ "sortBy": "Random",
+ "limit": 2000,
+ "imageTypeLimit": 1,
+ "Recursive": true,
+ "enableUserData": false,
+ "EnableTotalRecordCount": false
+ }
+ ' modify api query based on folder type
+ folderType = Lcase(itemNode.json.type)
+ if folderType = "studio"
+ paramArray["studioIds"] = itemNode.id
+ else if folderType = "genre"
+ paramArray["genreIds"] = itemNode.id
+ if isValid(itemNode.json.MovieCount) and itemNode.json.MovieCount > 0
+ paramArray["includeItemTypes"] = "Movie"
+ end if
+ else if folderType = "musicgenre"
+ paramArray["genreIds"] = itemNode.id
+ paramArray.delete("videoTypes")
+ paramArray["includeItemTypes"] = "Audio"
+ else
+ paramArray["parentId"] = itemNode.id
+ end if
+ ' look for tv series instead of video files
+ if isValid(itemNode.json.SeriesCount) and itemNode.json.SeriesCount > 0
+ paramArray["includeItemTypes"] = "Series"
+ paramArray.Delete("videoTypes")
+ end if
+ ' get folder items
+ folderData = api.users.GetItemsByQuery(m.global.session.user.id, paramArray)
+ print "folderData=", folderData
+
+ if isValid(folderData) and isValidAndNotEmpty(folderData.items)
+ if isValid(itemNode.json.SeriesCount) and itemNode.json.SeriesCount > 0
+ if itemNode.json.SeriesCount = 1
+ quickplay.series(folderData.items[0])
+ else
+ quickplay.multipleSeries(folderData.items)
+ end if
+ else
+ quickplay.pushToQueue(folderData.items, true)
+ end if
+ end if
+ end sub
+
+ ' Quick Play A CollectionFolder.
+ ' Shuffle play the items inside
+ ' with some differences based on collectionType.
+ sub collectionFolder(itemNode as object)
+ if not isValid(itemNode) or not isValid(itemNode.id) then return
+ ' play depends on the kind of files inside the collectionfolder
+ print "attempting to quickplay a collection folder"
+ collectionType = LCase(itemNode.collectionType)
+ print "collectionType=", collectionType
+
+ if collectionType = "movies"
+ ' get randomized list of movies inside
+ data = api.users.GetItemsByQuery(m.global.session.user.id, {
+ "parentId": itemNode.id,
+ "sortBy": "Random",
+ "limit": 2000
+ })
+
+ if isValid(data) and isValidAndNotEmpty(data.items)
+ movieList = []
+ ' add each item to the queue
+ for each item in data.Items
+ ' only add movies we're not currently watching
+ if isValid(item.userdata) and isValid(item.userdata.PlaybackPositionTicks)
+ if item.userdata.PlaybackPositionTicks = 0
+ movieList.push(item)
+ end if
+ end if
+ end for
+ quickplay.pushToQueue(movieList)
+ end if
+ else if collectionType = "music"
+ ' get audio files from under this collection
+ ' sort songs by album then artist
+ songsData = api.users.GetItemsByQuery(m.global.session.user.id, {
+ "parentId": itemNode.id,
+ "includeItemTypes": "Audio",
+ "sortBy": "Album",
+ "Recursive": true,
+ "limit": 2000,
+ "imageTypeLimit": 1,
+ "enableUserData": false,
+ "EnableTotalRecordCount": false
+ })
+ print "songsData=", songsData
+ if isValid(songsData) and isValidAndNotEmpty(songsData.items)
+ quickplay.pushToQueue(songsData.Items, true)
+ end if
+ else if collectionType = "boxsets"
+ ' get list of all boxsets inside
+ boxsetData = api.users.GetItemsByQuery(m.global.session.user.id, {
+ "parentId": itemNode.id,
+ "limit": 2000,
+ "imageTypeLimit": 0,
+ "enableUserData": false,
+ "EnableTotalRecordCount": false,
+ "enableImages": false
+ })
+
+ print "boxsetData=", boxsetData
+
+ if isValid(boxsetData) and isValidAndNotEmpty(boxsetData.items)
+ ' pick a random boxset
+ arrayIndex = Rnd(boxsetData.items.count()) - 1
+ myBoxset = boxsetData.items[arrayIndex]
+ ' grab list of items from boxset
+ print "myBoxset=", myBoxset
+ boxsetData = api.users.GetItemsByQuery(m.global.session.user.id, {
+ "parentId": myBoxset.id,
+ "EnableTotalRecordCount": false
+ })
+
+ if isValid(boxsetData) and isValidAndNotEmpty(boxsetData.items)
+ ' add all boxset items to queue
+ quickplay.pushToQueue(boxsetData.Items)
+ end if
+ end if
+ else if collectionType = "tvshows" or collectionType = "collectionfolder"
+ ' get list of tv shows inside
+ tvshowsData = api.users.GetItemsByQuery(m.global.session.user.id, {
+ "parentId": itemNode.id,
+ "sortBy": "Random",
+ "imageTypeLimit": 0,
+ "enableUserData": false,
+ "EnableTotalRecordCount": false,
+ "enableImages": false
+ })
+
+ print "tvshowsData=", tvshowsData
+
+ if isValid(tvshowsData) and isValidAndNotEmpty(tvshowsData.items)
+ quickplay.multipleSeries(tvshowsData.items)
+ end if
+ else if collectionType = "musicvideos"
+ ' get randomized list of videos inside
+ data = api.users.GetItemsByQuery(m.global.session.user.id, {
+ "parentId": itemNode.id,
+ "includeItemTypes": "MusicVideo",
+ "sortBy": "Random",
+ "Recursive": true,
+ "limit": 2000,
+ "imageTypeLimit": 1,
+ "enableUserData": false,
+ "EnableTotalRecordCount": false
+ })
+ print "data=", data
+ if isValid(data) and isValidAndNotEmpty(data.items)
+ quickplay.pushToQueue(data.Items)
+ end if
+ ' else if collectionType = "homevideos" ' also used for a "Photo" library
+ else
+ print "Quick Play WARNING: Unknown collection type"
+ end if
+ end sub
+
+ ' Quick Play A UserView.
+ ' Play logic depends on "collectionType".
+ sub userView(itemNode as object)
+ ' play depends on the kind of files inside the collectionfolder
+ collectionType = LCase(itemNode.collectionType)
+ print "collectionType=", collectionType
+
+ if collectionType = "playlists"
+ ' get list of all playlists inside
+ playlistData = api.users.GetItemsByQuery(m.global.session.user.id, {
+ "parentId": itemNode.id,
+ "imageTypeLimit": 0,
+ "enableUserData": false,
+ "EnableTotalRecordCount": false,
+ "enableImages": false
+ })
+
+ print "playlistData=", playlistData
+
+ if isValid(playlistData) and isValidAndNotEmpty(playlistData.items)
+ ' pick a random playlist
+ arrayIndex = Rnd(playlistData.items.count()) - 1
+ myPlaylist = playlistData.items[arrayIndex]
+ ' grab list of items from playlist
+ print "myPlaylist=", myPlaylist
+ playlistItems = api.playlists.GetItems(myPlaylist.id, {
+ "userId": m.global.session.user.id,
+ "EnableTotalRecordCount": false,
+ "limit": 2000
+ })
+ ' validate api results
+ if isValid(playlistItems) and isValidAndNotEmpty(playlistItems.items)
+ quickplay.pushToQueue(playlistItems.items, true)
+ end if
+ end if
+ else if collectionType = "livetv"
+ ' get list of all tv channels
+ channelData = api.users.GetItemsByQuery(m.global.session.user.id, {
+ "includeItemTypes": "TVChannel",
+ "sortBy": "Random",
+ "Recursive": true,
+ "imageTypeLimit": 0,
+ "enableUserData": false,
+ "EnableTotalRecordCount": false,
+ "enableImages": false
+ })
+ print "channelData=", channelData
+
+ if isValid(channelData) and isValidAndNotEmpty(channelData.items)
+ ' pick a random channel
+ arrayIndex = Rnd(channelData.items.count()) - 1
+ myChannel = channelData.items[arrayIndex]
+ print "myChannel=", myChannel
+ ' play channel
+ quickplay.tvChannel(myChannel)
+ end if
+ else
+ print "Quick Play CollectionFolder WARNING: Unknown collection type"
+ end if
+ end sub
+
+end namespace
diff --git a/source/utils/session.bs b/source/utils/session.bs
index 56548aa56..43d950b82 100644
--- a/source/utils/session.bs
+++ b/source/utils/session.bs
@@ -8,6 +8,7 @@ namespace session
sub Init()
m.global.addFields({
session: {
+ "memoryLevel": "normal",
server: {},
user: {
Configuration: {},