' All of the Quick Play logic seperated by media type namespace quickplay ' Takes an array of items and adds to global queue. ' Stop loading items if memory level becomes low sub pushToQueue(queueArray as object, limitValue = 200 as integer) if isValidAndNotEmpty(queueArray) itemCount = queueArray.count() if limitValue >= itemCount ' load everything for each item in queueArray m.global.queueManager.callFunc("push", item) end for else newLimit = limitValue for i = 0 to itemCount - 1 m.global.queueManager.callFunc("push", queueArray[i]) if i = newLimit ' hit the item limit. check memory level newLimit = newLimit + limitValue print "m.global.session.memoryLevel=", m.global.session.memoryLevel if m.global.session.memoryLevel = "low" or m.global.session.memoryLevel = "critical" print "Memory is low. Stop loading items in the playlist..." exit for end if end if end for 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 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", "enableUserData": false, "EnableTotalRecordCount": false }) if isValid(albumSongs) and isValidAndNotEmpty(albumSongs.items) ' add every song to the queue for each song in albumSongs.items m.global.queueManager.callFunc("push", song) end for 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", "imageTypeLimit": 1, "Recursive": true, "enableUserData": false, "EnableTotalRecordCount": false }) print "artistSongs=", artistSongs if isValid(artistSongs) and isValidAndNotEmpty(artistSongs.items) pushToQueue(artistSongs.items) ' don't show shuffle icon for 1 song if artistSongs.items.count() > 1 m.global.queueManager.callFunc("toggleShuffle") end if end if end sub ' A boxset. ' Shuffle 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, "EnableTotalRecordCount": false }) if isValid(data) and isValidAndNotEmpty(data.Items) ' there are videos inside 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 for each item in data.Items m.global.queueManager.callFunc("push", item) end for 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 for each item in data.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 ' shuffle all episodes data = api.shows.GetEpisodes(itemNode.id, { "userid": m.global.session.user.id, "SortBy": "Random", "EnableTotalRecordCount": false }) if isValid(data) and isValidAndNotEmpty(data.Items) ' add all episodes found to a playlist pushToQueue(data.Items) end if 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, "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 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 }) if isValid(myPlaylist) and isValidAndNotEmpty(myPlaylist.Items) ' add each item to the queue pushToQueue(myPlaylist.Items) m.global.queueManager.callFunc("toggleShuffle") 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 print "itemNode.json=", itemNode.json paramArray = { "includeItemTypes": ["Episode", "Movie", "Video"], "videoTypes": "VideoFile", "sortBy": "Random", "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 else if folderType = "musicgenre" paramArray["genreIds"] = itemNode.id paramArray.delete("videoTypes") paramArray["includeItemTypes"] = "Audio" else paramArray["parentId"] = itemNode.id 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) pushToQueue(folderData.items) ' don't show shuffle icon for 1 item if folderData.items.count() > 1 m.global.queueManager.callFunc("toggleShuffle") 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 }) if isValid(data) and isValidAndNotEmpty(data.items) ' 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 m.global.queueManager.callFunc("push", item) end if end if end for m.global.queueManager.callFunc("toggleShuffle") end if else if collectionType = "music" ' get all audio files 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, "imageTypeLimit": 1, "enableUserData": false, "EnableTotalRecordCount": false }) print "songsData=", songsData if isValid(songsData) and isValidAndNotEmpty(songsData.items) pushToQueue(songsData.Items) if songsData.Items.count() > 1 m.global.queueManager.callFunc("toggleShuffle") end if end if else if collectionType = "boxsets" ' get list of all boxsets inside boxsetData = api.users.GetItemsByQuery(m.global.session.user.id, { "parentId": itemNode.id, "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 pushToQueue(boxsetData.Items) end if end if else if collectionType = "tvshows" ' get list of tv shows inside tvshowsData = api.users.GetItemsByQuery(m.global.session.user.id, { "parentId": itemNode.id, "imageTypeLimit": 0, "enableUserData": false, "EnableTotalRecordCount": false, "enableImages": false }) print "tvshowsData=", tvshowsData if isValid(tvshowsData) and isValidAndNotEmpty(tvshowsData.items) for each tvshow in tvshowsData.items ' grab all watched episodes for each series showData = api.shows.GetEpisodes(tvshow.id, { "userId": m.global.session.user.id, "imageTypeLimit": 0, "EnableTotalRecordCount": false, "enableImages": false }) if isValid(showData) and isValidAndNotEmpty(showData.items) ' 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 m.global.queueManager.callFunc("push", episode) end if end if end for end if end for m.global.queueManager.callFunc("toggleShuffle") 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 }) ' validate api results if isValid(playlistItems) and isValidAndNotEmpty(playlistItems.items) for each item in playlistItems.items m.global.queueManager.callFunc("push", item) end for ' don't show shuffle icon for 1 item if playlistItems.items.count() > 1 m.global.queueManager.callFunc("toggleShuffle") end if end if end if else print "Quick Play CollectionFolder WARNING: Unknown collection type" end if end sub end namespace