' 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 single photo. sub photo(itemNode as object) if not isValid(itemNode) or not isValid(itemNode.id) then return photoPlayer = CreateObject("roSgNode", "PhotoDetails") photoPlayer.itemsNode = itemNode photoPlayer.itemIndex = 0 m.global.sceneManager.callfunc("pushScene", photoPlayer) end sub ' A photo album. sub photoAlbum(itemNode as object) if not isValid(itemNode) or not isValid(itemNode.id) then return ' grab all photos inside photo album photoAlbumData = api.users.GetItemsByQuery(m.global.session.user.id, { "parentId": itemNode.id, "includeItemTypes": "Photo", "sortBy": "Random", "Recursive": true }) print "photoAlbumData=", photoAlbumData if isValid(photoAlbumData) and isValidAndNotEmpty(photoAlbumData.items) photoPlayer = CreateObject("roSgNode", "PhotoDetails") photoPlayer.isSlideshow = true photoPlayer.isRandom = false photoPlayer.itemsArray = photoAlbumData.items photoPlayer.itemIndex = 0 m.global.sceneManager.callfunc("pushScene", photoPlayer) end if 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) print "folderType=", folderType 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 if folderType = "photoalbum" paramArray["parentId"] = itemNode.id paramArray["includeItemTypes"] = "Photo" paramArray.delete("videoTypes") paramArray.delete("Recursive") 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 if folderType = "photoalbum" photoPlayer = CreateObject("roSgNode", "PhotoDetails") photoPlayer.isSlideshow = true photoPlayer.isRandom = false photoPlayer.itemsArray = folderData.items photoPlayer.itemIndex = 0 m.global.sceneManager.callfunc("pushScene", photoPlayer) else quickplay.pushToQueue(folderData.items, true) end if 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" ' Photo library - items can be type video, photo, or photoAlbum ' grab all photos inside library folderData = api.users.GetItemsByQuery(m.global.session.user.id, { "parentId": itemNode.id, "includeItemTypes": "Photo", "sortBy": "Random", "Recursive": true }) print "folderData=", folderData if isValid(folderData) and isValidAndNotEmpty(folderData.items) photoPlayer = CreateObject("roSgNode", "PhotoDetails") photoPlayer.isSlideshow = true photoPlayer.isRandom = false photoPlayer.itemsArray = folderData.items photoPlayer.itemIndex = 0 m.global.sceneManager.callfunc("pushScene", photoPlayer) end if 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