586 lines
23 KiB
Plaintext
586 lines
23 KiB
Plaintext
' 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"
|
|
' 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
|