jf-roku/docs/api/source_utils_quickplay.bs.html

724 lines
65 KiB
HTML
Raw Normal View History

2023-11-11 13:41:20 +00:00
<!DOCTYPE html><html lang="en" style="font-size:16px"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Source: source/utils/quickplay.bs</title><!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
2023-12-05 16:56:00 +00:00
<![endif]--><script src="scripts/third-party/hljs.js" defer="defer"></script><script src="scripts/third-party/hljs-line-num.js" defer="defer"></script><script src="scripts/third-party/popper.js" defer="defer"></script><script src="scripts/third-party/tippy.js" defer="defer"></script><script src="scripts/third-party/tocbot.min.js"></script><script>var baseURL="/",locationPathname="";baseURL=(baseURL=(baseURL="https://jellyfin.github.io/jellyfin-roku/").replace(/https?:\/\//i,"")).substr(baseURL.indexOf("/"))</script><link rel="stylesheet" href="styles/clean-jsdoc-theme.min.css"><svg aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none"><defs><symbol id="copy-icon" viewbox="0 0 488.3 488.3"><g><path d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z"/><path d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z"/></g></symbol><symbol id="search-icon" viewBox="0 0 512 512"><g><g><path d="M225.474,0C101.151,0,0,101.151,0,225.474c0,124.33,101.151,225.474,225.474,225.474 c124.33,0,225.474-101.144,225.474-225.474C450.948,101.151,349.804,0,225.474,0z M225.474,409.323 c-101.373,0-183.848-82.475-183.848-183.848S124.101,41.626,225.474,41.626s183.848,82.475,183.848,183.848 S326.847,409.323,225.474,409.323z"/></g></g><g><g><path d="M505.902,476.472L386.574,357.144c-8.131-8.131-21.299-8.131-29.43,0c-8.131,8.124-8.131,21.306,0,29.43l119.328,119.328 c4.065,4.065,9.387,6.098,14.715,6.098c5.321,0,10.649-2.033,14.715-6.098C514.033,497.778,514.033,484.596,505.902,476.472z"/></g></g></symbol><symbol id="font-size-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.246 15H4.754l-2 5H.6L7 4h2l6.4 16h-2.154l-2-5zm-.8-2L8 6.885 5.554 13h4.892zM21 12.535V12h2v8h-2v-.535a4 4 0 1 1 0-6.93zM19 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol><symbol id="add-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z"/></symbol><symbol id="minus-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 11h14v2H5z"/></symbol><symbol id="dark-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol><symbol id="light-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol><symbol id="reset-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10c0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 1 0-2.46 5.772l.997 1.795z"/></symbol><symbol id="down-icon" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.7803 6.21967C13.0732 6.51256 13.0732 6.98744 12.7803 7.28033L8.53033 11.5303C8.23744 11.8232 7.76256 11.8232 7.46967 11.5303L3.21967 7.28033C2.92678 6.98744 2.92678 6.51256 3.21967 6.21967C3.51256 5.92678 3.98744 5.92678 4.28033 6.21967L8 9.93934L11.7197 6.21967C12.0126 5.92678 12.4874 5.92678 12.7803 6.21967Z"></path></symbol><symbol id="codepen-icon" viewBox="0 0 24 24"><path fill="none" d=
2023-10-28 21:26:12 +00:00
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
2023-11-15 00:22:33 +00:00
' 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)
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-11-15 00:22:33 +00:00
end if
end sub
2023-10-28 21:26:12 +00:00
' 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)
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
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)
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
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)
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
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)
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
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")
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
end if
end if
end sub
2023-11-30 03:26:14 +00:00
' A container with some kind of videos inside of it
sub videoContainer(itemNode as object)
print "itemNode=", itemNode
collectionType = Lcase(itemNode.collectionType)
if collectionType = "movies"
' get randomized list of videos inside
data = api.users.GetItemsByQuery(m.global.session.user.id, {
"parentId": itemNode.id,
"sortBy": "Random",
"recursive": true,
"includeItemTypes": "Movie,Video",
"limit": 2000
})
print "data=", data
if isValid(data) and isValidAndNotEmpty(data.items)
videoList = []
' add each item to the queue
for each item in data.Items
print "data.Item=", item
' only add videos we're not currently watching
if isValid(item.userdata) and isValid(item.userdata.PlaybackPositionTicks)
if item.userdata.PlaybackPositionTicks = 0
videoList.push(item)
end if
end if
end for
quickplay.pushToQueue(videoList)
else
stopLoadingSpinner()
end if
return
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",
"recursive": true,
"excludeItemTypes": "Season",
"imageTypeLimit": 0,
"enableUserData": false,
"EnableTotalRecordCount": false,
"enableImages": false
})
print "tvshowsData=", tvshowsData
if isValid(tvshowsData) and isValidAndNotEmpty(tvshowsData.items)
' the type of media returned from api may change.
if tvshowsData.items[0].Type = "Series"
quickplay.multipleSeries(tvshowsData.items)
else
' if first item is not a series, then assume they are all videos and/or episodes
quickplay.pushToQueue(tvshowsData.items)
end if
else
stopLoadingSpinner()
end if
else
stopLoadingSpinner()
print "Quick Play videoContainer WARNING: Unknown collection type"
end if
end sub
2023-10-28 21:26:12 +00:00
' 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
2023-11-30 03:26:14 +00:00
firstUnwatchedEpisodeIndex = isValid(item.IndexNumber) ? item.IndexNumber - 1 : 0
2023-10-28 21:26:12 +00:00
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
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
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")
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
end if
end sub
' Quick Play A TVChannel
sub tvChannel(itemNode as object)
if not isValid(itemNode) or not isValid(itemNode.id) then return
group = CreateVideoPlayerGroup(itemNode.id)
2023-11-30 01:22:26 +00:00
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
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
group = CreateVideoPlayerGroup(itemNode.json.ChannelId)
2023-11-30 01:22:26 +00:00
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
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
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
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)
2023-11-15 00:22:33 +00:00
print "folderType=", folderType
2023-10-28 21:26:12 +00:00
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"
2023-11-15 00:22:33 +00:00
else if folderType = "photoalbum"
paramArray["parentId"] = itemNode.id
paramArray["includeItemTypes"] = "Photo"
paramArray.delete("videoTypes")
paramArray.delete("Recursive")
2023-10-28 21:26:12 +00:00
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
2023-11-15 00:22:33 +00:00
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
2023-10-28 21:26:12 +00:00
end if
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
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"
2023-11-30 03:26:14 +00:00
quickplay.videoContainer(itemNode)
2023-10-28 21:26:12 +00:00
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)
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
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)
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
end if
end if
else if collectionType = "tvshows" or collectionType = "collectionfolder"
2023-11-30 03:26:14 +00:00
quickplay.videoContainer(itemNode)
2023-10-28 21:26:12 +00:00
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)
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
end if
2023-11-15 00:22:33 +00:00
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)
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-11-15 00:22:33 +00:00
end if
2023-10-28 21:26:12 +00:00
else
2023-11-30 01:22:26 +00:00
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
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)
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
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)
2023-11-30 01:22:26 +00:00
else
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
end if
2023-11-30 03:26:14 +00:00
else if collectionType = "movies"
quickplay.videoContainer(itemNode)
else if collectionType = "tvshows"
quickplay.videoContainer(itemNode)
2023-10-28 21:26:12 +00:00
else
2023-11-30 01:22:26 +00:00
stopLoadingSpinner()
2023-10-28 21:26:12 +00:00
print "Quick Play CollectionFolder WARNING: Unknown collection type"
end if
end sub
end namespace
2023-12-05 16:56:00 +00:00
</code></pre></article></section><footer class="footer" id="PeOAagUepe"><div class="wrapper"><span class="jsdoc-message">Automatically generated using <a href="https://github.com/jsdoc/jsdoc" target="_blank">JSDoc</a> and the <a href="https://github.com/ankitskvmdam/clean-jsdoc-theme" target="_blank">clean-jsdoc-theme</a>.</span></div></footer></div></div></div><div class="search-container" id="PkfLWpAbet" style="display:none"><div class="wrapper" id="iCxFxjkHbP"><button class="icon-button search-close-button" id="VjLlGakifb" aria-label="close search"><svg><use xlink:href="#close-icon"></use></svg></button><div class="search-box-c"><svg><use xlink:href="#search-icon"></use></svg> <input type="text" id="vpcKVYIppa" class="search-input" placeholder="Search..." autofocus></div><div class="search-result-c" id="fWwVHRuDuN"><span class="search-result-c-text">Type anything to view search result</span></div></div></div><div class="mobile-menu-icon-container"><button class="icon-button" id="mobile-menu" data-isopen="false" aria-label="menu"><svg><use xlink:href="#menu-icon"></use></svg></button></div><div id="mobile-sidebar" class="mobile-sidebar-container"><div class="mobile-sidebar-wrapper"><a href="/" class="sidebar-title sidebar-title-anchor">jellyfin-roku Code Documentation</a><div class="mobile-nav-links"><div class="external-link navbar-item"><a id="jellyfin-link-mobile" href="https://jellyfin.org/" target="_blank">Jellyfin</a></div><div class="external-link navbar-item"><a id="github-link-mobile" href="https://github.com/jellyfin/jellyfin-roku" target="_blank">GitHub</a></div><div class="external-link navbar-item"><a id="forum-link-mobile" href="https://forum.jellyfin.org/f-roku-development" target="_blank">Forum</a></div><div class="external-link navbar-item"><a id="matrix-link-mobile" href="https://matrix.to/#/#jellyfin-dev-roku:matrix.org" target="_blank">Matrix</a></div></div><div class="mobile-sidebar-items-c"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-AlbumData.html">AlbumData</a></div><div class="sidebar-section-children"><a href="module-AlbumGrid.html">AlbumGrid</a></div><div class="sidebar-section-children"><a href="module-AlbumTrackList.html">AlbumTrackList</a></div><div class="sidebar-section-children"><a href="module-AlbumView.html">AlbumView</a></div><div class="sidebar-section-children"><a href="module-Alpha.html">Alpha</a></div><div class="sidebar-section-children"><a href="module-ArtistView.html">ArtistView</a></div><div class="sidebar-section-children"><a href="module-AudioPlayer.html">AudioPlayer</a></div><div class="sidebar-section-children"><a href="module-AudioPlayerView.html">AudioPlayerView</a></div><div class="sidebar-section-children"><a href="module-AudioTrackListItem.html">AudioTrackListItem</a></div><div class="sidebar-section-children"><a href="module-ButtonGroupHoriz.html">ButtonGroupHoriz</a></div><div class="sidebar-section-children"><a href="module-ButtonGroupVert.html">ButtonGroupVert</a></div><div class="sidebar-section-children"><a href="module-ChannelData.html">ChannelData</a></div><div class="sidebar-section-children"><a href="module-Clock.html">Clock</a></div><div class="sidebar-section-children"><a href="module-CollectionData.html">CollectionData</a></div><div class="sidebar-section-children"><a href="module-ConfigData.html">ConfigData</a></div><div class="sidebar-section-children"><a href="module-ConfigItem.html">ConfigItem</a></div><div class="sidebar-section-children"><a href="module-ConfigList.html">ConfigList</a></div><div class="sidebar-section-children"><a href="module-ExtrasItem.html">ExtrasItem</a></div><div class="sidebar-section-children"><a href="module-ExtrasRowList.html">ExtrasRowList</a></div><div class="sidebar-section-children"><a href="module-FavoriteItemsTask.html">FavoriteItemsTask</a></div><div class="sidebar-section-children"><a href="module-Folder