Merge remote-tracking branch 'upstream/master' into next-up-behavior-configuration

This commit is contained in:
Reynolds 2024-10-18 08:58:20 -04:00
commit 7cad83592d
57 changed files with 678 additions and 513 deletions

View File

@ -3,7 +3,7 @@
# If you want to get_images, you'll also need convert from ImageMagick
##########################################################################
VERSION := 2.1.7
VERSION := 2.2.0
## usage

View File

@ -42,10 +42,10 @@ end sub
sub itemContentChanged()
m.backdrop.blendColor = "#00a4db" ' set default in case global var is invalid
localGlobal = m.global
myGlobal = m.global
if isValid(localGlobal) and isValid(localGlobal.constants) and isValid(localGlobal.constants.poster_bg_pallet)
posterBackgrounds = localGlobal.constants.poster_bg_pallet
if isValid(myGlobal) and isValid(myGlobal.constants) and isValid(myGlobal.constants.poster_bg_pallet)
posterBackgrounds = myGlobal.constants.poster_bg_pallet
m.backdrop.blendColor = posterBackgrounds[rnd(posterBackgrounds.count()) - 1]
end if
@ -62,8 +62,8 @@ sub itemContentChanged()
m.itemIcon.uri = itemData.iconUrl
m.itemText.text = itemData.Title
else if itemData.type = "Series"
if isValid(localGlobal) and isValid(localGlobal.session) and isValid(localGlobal.session.user) and isValid(localGlobal.session.user.settings)
if localGlobal.session.user.settings["ui.tvshows.disableUnwatchedEpisodeCount"] = false
if isValid(myGlobal) and isValid(myGlobal.session) and isValid(myGlobal.session.user) and isValid(myGlobal.session.user.settings)
if myGlobal.session.user.settings["ui.tvshows.disableUnwatchedEpisodeCount"] = false
if isValid(itemData.json) and isValid(itemData.json.UserData) and isValid(itemData.json.UserData.UnplayedItemCount)
if itemData.json.UserData.UnplayedItemCount > 0
m.unplayedCount.visible = true

View File

@ -7,9 +7,11 @@ import "pkg:/source/roku_modules/log/LogMixin.brs"
sub init()
m.log = log.Logger("ItemGrid")
m.log.debug("start init()")
userSettings = m.global.session.user.settings
m.options = m.top.findNode("options")
m.showItemCount = m.global.session.user.settings["itemgrid.showItemCount"]
m.showItemCount = userSettings["itemgrid.showItemCount"]
m.tvGuide = invalid
m.channelFocused = invalid
@ -68,9 +70,9 @@ sub init()
m.alphaMenu = m.alpha.findNode("alphaMenu")
'Get reset folder setting
m.resetGrid = m.global.session.user.settings["itemgrid.reset"]
m.resetGrid = userSettings["itemgrid.reset"]
m.top.gridTitles = m.global.session.user.settings["itemgrid.gridTitles"]
m.top.gridTitles = userSettings["itemgrid.gridTitles"]
m.log.debug("end init()")
end sub
@ -84,6 +86,7 @@ sub loadInitialItems()
m.log.debug("start loadInitialItems()")
m.loadItemsTask.control = "stop"
startLoadingSpinner()
userSettings = m.global.session.user.settings
if m.top.parentItem.json.Type = "CollectionFolder" 'or m.top.parentItem.json.Type = "Folder"
m.top.HomeLibraryItem = m.top.parentItem.Id
@ -96,25 +99,25 @@ sub loadInitialItems()
' Read view/sort/filter settings
if m.top.parentItem.collectionType = "livetv"
' Translate between app and server nomenclature
viewSetting = m.global.session.user.settings["display.livetv.landing"]
viewSetting = userSettings["display.livetv.landing"]
if viewSetting = "guide"
m.view = "tvGuide"
else
m.view = "livetv"
end if
m.sortField = m.global.session.user.settings["display.livetv.sortField"]
sortAscendingStr = m.global.session.user.settings["display.livetv.sortAscending"]
m.filter = m.global.session.user.settings["display.livetv.filter"]
m.sortField = userSettings["display.livetv.sortField"]
sortAscendingStr = userSettings["display.livetv.sortAscending"]
m.filter = userSettings["display.livetv.filter"]
else if m.top.parentItem.collectionType = "music"
m.view = m.global.session.user.settings["display.music.view"]
m.sortField = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortField"]
sortAscendingStr = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortAscending"]
m.filter = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filter"]
m.view = userSettings["display.music.view"]
m.sortField = userSettings["display." + m.top.parentItem.Id + ".sortField"]
sortAscendingStr = userSettings["display." + m.top.parentItem.Id + ".sortAscending"]
m.filter = userSettings["display." + m.top.parentItem.Id + ".filter"]
else
m.sortField = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortField"]
sortAscendingStr = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortAscending"]
m.filter = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filter"]
m.view = m.global.session.user.settings["display." + m.top.parentItem.Id + ".landing"]
m.sortField = userSettings["display." + m.top.parentItem.Id + ".sortField"]
sortAscendingStr = userSettings["display." + m.top.parentItem.Id + ".sortAscending"]
m.filter = userSettings["display." + m.top.parentItem.Id + ".filter"]
m.view = userSettings["display." + m.top.parentItem.Id + ".landing"]
end if
if m.sortField = invalid
@ -180,7 +183,7 @@ sub loadInitialItems()
m.loadItemsTask.itemType = "MusicArtist"
m.loadItemsTask.itemId = m.top.parentItem.Id
m.view = m.global.session.user.settings["display.music.view"]
m.view = userSettings["display.music.view"]
if m.view = "music-album"
m.loadItemsTask.itemType = "MusicAlbum"
@ -191,7 +194,7 @@ sub loadInitialItems()
' For LiveTV, we want to "Fit" the item images, not zoom
m.top.imageDisplayMode = "scaleToFit"
if m.global.session.user.settings["display.livetv.landing"] = "guide" and m.options.view <> "livetv"
if userSettings["display.livetv.landing"] = "guide" and m.options.view <> "livetv"
showTvGuide()
end if
else if m.top.parentItem.collectionType = "CollectionFolder" or m.top.parentItem.type = "CollectionFolder" or m.top.parentItem.collectionType = "boxsets" or m.top.parentItem.Type = "Boxset" or m.top.parentItem.Type = "Boxsets" or m.top.parentItem.Type = "Folder" or m.top.parentItem.Type = "Channel"

View File

@ -18,21 +18,23 @@ sub init()
end sub
sub loadItems()
queueManager = m.global.queueManager
' Reset intro tracker in case task gets reused
m.top.isIntro = false
' Only show preroll once per queue
if m.global.queueManager.callFunc("isPrerollActive")
if queueManager.callFunc("isPrerollActive")
' Prerolls not allowed if we're resuming video
if m.global.queueManager.callFunc("getCurrentItem").startingPoint = 0
if queueManager.callFunc("getCurrentItem").startingPoint = 0
preRoll = GetIntroVideos(m.top.itemId)
if isValid(preRoll) and preRoll.TotalRecordCount > 0 and isValid(preRoll.items[0])
' If an error is thrown in the Intros plugin, instead of passing the error they pass the entire rick roll music video.
' Bypass the music video and treat it as an error message
if lcase(preRoll.items[0].name) <> "rick roll'd"
m.global.queueManager.callFunc("push", m.global.queueManager.callFunc("getCurrentItem"))
queueManager.callFunc("push", queueManager.callFunc("getCurrentItem"))
m.top.itemId = preRoll.items[0].id
m.global.queueManager.callFunc("setPrerollStatus", false)
queueManager.callFunc("setPrerollStatus", false)
m.top.isIntro = true
end if
end if
@ -40,7 +42,7 @@ sub loadItems()
end if
if m.top.selectedAudioStreamIndex = 0
currentItem = m.global.queueManager.callFunc("getCurrentItem")
currentItem = queueManager.callFunc("getCurrentItem")
if isValid(currentItem) and isValid(currentItem.json)
m.top.selectedAudioStreamIndex = FindPreferredAudioStream(currentItem.json.MediaStreams)
end if
@ -78,6 +80,10 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
return
end if
queueManager = m.global.queueManager
userSession = m.global.session.user
userSettings = userSession.settings
session.video.Update(meta)
if isValid(meta.json.MediaSources[0].RunTimeTicks)
@ -132,15 +138,14 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
end if
if LCase(m.top.itemType) = "episode"
userSession = m.global.session.user
if userSession.settings["playback.playnextepisode"] = "enabled" or userSession.settings["playback.playnextepisode"] = "webclient" and userSession.Configuration.EnableNextEpisodeAutoPlay
if userSettings["playback.playnextepisode"] = "enabled" or userSettings["playback.playnextepisode"] = "webclient" and userSession.Configuration.EnableNextEpisodeAutoPlay
addNextEpisodesToQueue(video.showID)
end if
end if
playbackPosition = 0!
currentItem = m.global.queueManager.callFunc("getCurrentItem")
currentItem = queueManager.callFunc("getCurrentItem")
if isValid(currentItem) and isValid(currentItem.startingPoint)
playbackPosition = currentItem.startingPoint
@ -220,8 +225,8 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
' transcode is that the Encoding Level is not supported, then try to direct play but silently
' fall back to the transcode if that fails.
if m.playbackInfo.MediaSources[0].MediaStreams.Count() > 0 and meta.live = false
tryDirectPlay = m.global.session.user.settings["playback.tryDirect.h264ProfileLevel"] and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
tryDirectPlay = tryDirectPlay or (m.global.session.user.settings["playback.tryDirect.hevcProfileLevel"] and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "hevc")
tryDirectPlay = userSettings["playback.tryDirect.h264ProfileLevel"] and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
tryDirectPlay = tryDirectPlay or (userSettings["playback.tryDirect.hevcProfileLevel"] and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "hevc")
if tryDirectPlay and isValid(m.playbackInfo.MediaSources[0].TranscodingUrl) and forceTranscoding = false
transcodingReasons = getTranscodeReasons(m.playbackInfo.MediaSources[0].TranscodingUrl)
if transcodingReasons.Count() = 1 and transcodingReasons[0] = "VideoLevelNotSupported"
@ -261,7 +266,8 @@ end sub
' @param {dynamic} videoID - id of video user is playing
' @return {integer} indicating the default track's server-side index. Defaults to {SubtitleSelection.none} is one is not found
function defaultSubtitleTrackFromVid(videoID) as integer
if m.global.session.user.configuration.SubtitleMode = "None"
userSession = m.global.session.user
if userSession.configuration.SubtitleMode = "None"
return SubtitleSelection.none ' No subtitles desired: return none
end if
@ -287,7 +293,7 @@ function defaultSubtitleTrackFromVid(videoID) as integer
return defaultTextSubs
end if
if not m.global.session.user.settings["playback.subs.onlytext"]
if not userSession.settings["playback.subs.onlytext"]
return defaultSubtitleTrack(subtitles["all"], selectedAudioLanguage) ' if no appropriate text subs exist, allow non-text
end if
@ -491,6 +497,8 @@ end function
' Add next episodes to the playback queue
sub addNextEpisodesToQueue(showID)
queueManager = m.global.queueManager
' Don't queue next episodes if we already have a playback queue
maxQueueCount = 1
@ -498,13 +506,13 @@ sub addNextEpisodesToQueue(showID)
maxQueueCount = 2
end if
if m.global.queueManager.callFunc("getCount") > maxQueueCount then return
if queueManager.callFunc("getCount") > maxQueueCount then return
videoID = m.top.itemId
' If first item is an intro video, use the next item in the queue
if m.top.isIntro
currentVideo = m.global.queueManager.callFunc("getItemByIndex", 1)
currentVideo = queueManager.callFunc("getItemByIndex", 1)
if isValid(currentVideo) and isValid(currentVideo.id)
videoID = currentVideo.id
@ -526,7 +534,7 @@ sub addNextEpisodesToQueue(showID)
if isValid(data) and data.Items.Count() > 1
for i = 1 to data.Items.Count() - 1
m.global.queueManager.callFunc("push", data.Items[i])
queueManager.callFunc("push", data.Items[i])
end for
end if
end sub
@ -585,8 +593,9 @@ function sortSubtitles(id as string, MediaStreams)
end function
function FindPreferredAudioStream(streams as dynamic) as integer
preferredLanguage = m.global.session.user.Configuration.AudioLanguagePreference
playDefault = m.global.session.user.Configuration.PlayDefaultAudioTrack
userConfig = m.global.session.user.configuration
preferredLanguage = userConfig.AudioLanguagePreference
playDefault = userConfig.PlayDefaultAudioTrack
if playDefault <> invalid and playDefault = true
return 1

View File

@ -30,6 +30,7 @@ end sub
sub init()
setupNodes()
userSettings = m.global.session.user.settings
m.overhang.isVisible = false
@ -39,7 +40,7 @@ sub init()
alphaMicText = m.alpha.findNode("alphaMicText")
alphaMicText.visible = false
m.showItemCount = m.global.session.user.settings["itemgrid.showItemCount"]
m.showItemCount = userSettings["itemgrid.showItemCount"]
m.swapAnimation.observeField("state", "swapDone")
@ -86,7 +87,7 @@ sub init()
m.loadItemsTask.totalRecordCount = 0
'Get reset folder setting
m.resetGrid = m.global.session.user.settings["itemgrid.reset"]
m.resetGrid = userSettings["itemgrid.reset"]
end sub
sub OnScreenHidden()
@ -112,6 +113,7 @@ end sub
sub loadInitialItems()
m.loadItemsTask.control = "stop"
startLoadingSpinner(false)
userSettings = m.global.session.user.settings
if m.top.parentItem.json.Type = "CollectionFolder"
m.top.HomeLibraryItem = m.top.parentItem.Id
@ -123,15 +125,15 @@ sub loadInitialItems()
SetBackground("")
end if
m.sortField = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortField"]
m.filter = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filter"]
m.filterOptions = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filterOptions"]
m.view = m.global.session.user.settings["display." + m.top.parentItem.Id + ".landing"]
m.sortAscending = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortAscending"]
m.sortField = userSettings["display." + m.top.parentItem.Id + ".sortField"]
m.filter = userSettings["display." + m.top.parentItem.Id + ".filter"]
m.filterOptions = userSettings["display." + m.top.parentItem.Id + ".filterOptions"]
m.view = userSettings["display." + m.top.parentItem.Id + ".landing"]
m.sortAscending = userSettings["display." + m.top.parentItem.Id + ".sortAscending"]
' If user has not set a preferred view for this folder, check if they've set a default view
if not isValid(m.view)
m.view = m.global.session.user.settings["itemgrid.movieDefaultView"]
m.view = userSettings["itemgrid.movieDefaultView"]
end if
if not isValid(m.sortField) then m.sortField = "SortName"
@ -200,7 +202,7 @@ sub loadInitialItems()
m.itemGrid.numRows = "3"
m.selectedMovieOverview.visible = false
m.infoGroup.visible = false
m.top.showItemTitles = m.global.session.user.settings["itemgrid.gridTitles"]
m.top.showItemTitles = userSettings["itemgrid.gridTitles"]
if LCase(m.top.showItemTitles) = "hidealways"
m.itemGrid.itemSize = "[230, 315]"
m.itemGrid.rowHeights = "[315]"

View File

@ -25,6 +25,7 @@ end sub
sub init()
setupNodes()
userSettings = m.global.session.user.settings
m.overhang.isVisible = false
@ -34,7 +35,7 @@ sub init()
alphaMicText = m.alpha.findNode("alphaMicText")
alphaMicText.visible = false
m.showItemCount = m.global.session.user.settings["itemgrid.showItemCount"]
m.showItemCount = userSettings["itemgrid.showItemCount"]
m.swapAnimation.observeField("state", "swapDone")
@ -80,7 +81,7 @@ sub init()
m.loadItemsTask.totalRecordCount = 0
'Get reset folder setting
m.resetGrid = m.global.session.user.settings["itemgrid.reset"]
m.resetGrid = userSettings["itemgrid.reset"]
end sub
sub OnScreenHidden()
@ -106,6 +107,7 @@ end sub
sub loadInitialItems()
m.loadItemsTask.control = "stop"
startLoadingSpinner(false)
userSettings = m.global.session.user.settings
if LCase(m.top.parentItem.json.Type) = "collectionfolder"
m.top.HomeLibraryItem = m.top.parentItem.Id
@ -117,17 +119,17 @@ sub loadInitialItems()
SetBackground("")
end if
m.sortField = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortField"]
m.sortAscending = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortAscending"]
m.filter = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filter"]
m.view = m.global.session.user.settings["display." + m.top.parentItem.Id + ".landing"]
m.sortField = userSettings["display." + m.top.parentItem.Id + ".sortField"]
m.sortAscending = userSettings["display." + m.top.parentItem.Id + ".sortAscending"]
m.filter = userSettings["display." + m.top.parentItem.Id + ".filter"]
m.view = userSettings["display." + m.top.parentItem.Id + ".landing"]
if not isValid(m.sortField) then m.sortField = "SortName"
if not isValid(m.filter) then m.filter = "All"
if not isValid(m.view) then m.view = "ArtistsPresentation"
if not isValid(m.sortAscending) then m.sortAscending = true
m.top.showItemTitles = m.global.session.user.settings["itemgrid.gridTitles"]
m.top.showItemTitles = userSettings["itemgrid.gridTitles"]
if LCase(m.top.parentItem.json.type) = "musicgenre"
m.itemGrid.translation = "[96, 60]"

View File

@ -13,7 +13,8 @@ sub init()
m.top.transcodeReasons = []
m.bufferCheckTimer.duration = 30
if m.global.session.user.settings["ui.design.hideclock"] = true
userSettings = m.global.session.user.settings
if userSettings["ui.design.hideclock"]
clockNode = findNodeBySubtype(m.top, "clock")
if clockNode[0] <> invalid then clockNode[0].parent.removeChild(clockNode[0].node)
end if
@ -22,7 +23,7 @@ sub init()
m.nextEpisodeButton = m.top.findNode("nextEpisode")
m.nextEpisodeButton.text = tr("Next Episode")
m.nextEpisodeButton.setFocus(false)
m.nextupbuttonseconds = m.global.session.user.settings["playback.nextupbuttonseconds"].ToInt()
m.nextupbuttonseconds = userSettings["playback.nextupbuttonseconds"].ToInt()
m.showNextEpisodeButtonAnimation = m.top.findNode("showNextEpisodeButton")
m.hideNextEpisodeButtonAnimation = m.top.findNode("hideNextEpisodeButton")

View File

@ -17,10 +17,10 @@ sub init()
' Randomize the background colors
backdropColor = "#00a4db" ' set default in case global var is invalid
localGlobal = m.global
myGlobal = m.global
if isValid(localGlobal) and isValid(localGlobal.constants) and isValid(localGlobal.constants.poster_bg_pallet)
posterBackgrounds = localGlobal.constants.poster_bg_pallet
if isValid(myGlobal) and isValid(myGlobal.constants) and isValid(myGlobal.constants.poster_bg_pallet)
posterBackgrounds = myGlobal.constants.poster_bg_pallet
backdropColor = posterBackgrounds[rnd(posterBackgrounds.count()) - 1]
end if
@ -65,8 +65,9 @@ sub itemContentChanged() as void
m.poster = m.top.findNode("poster")
itemData = m.top.itemContent
m.title.text = itemData.title
userSettings = m.global.session.user.settings
if m.global.session.user.settings["ui.tvshows.disableUnwatchedEpisodeCount"] = false
if not userSettings["ui.tvshows.disableUnwatchedEpisodeCount"]
if isValid(itemData.json.UserData) and isValid(itemData.json.UserData.UnplayedItemCount)
if itemData.json.UserData.UnplayedItemCount > 0
m.unplayedCount.visible = true
@ -94,7 +95,7 @@ sub itemContentChanged() as void
imageUrl = itemData.posterURL
if m.global.session.user.settings["ui.tvshows.blurunwatched"] = true
if userSettings["ui.tvshows.blurunwatched"]
if itemData.json.lookup("Type") = "Episode" and isValid(itemData.json.userdata)
if not itemData.json.userdata.played
imageUrl = imageUrl + "&blur=15"
@ -116,7 +117,7 @@ sub focusChanged()
m.staticTitle.visible = false
m.title.visible = true
' text to speech for accessibility
if m.global.device.isAudioGuideEnabled = true
if m.global.device.isAudioGuideEnabled
txt2Speech = CreateObject("roTextToSpeech")
txt2Speech.Flush()
txt2Speech.Say(m.title.text)

View File

@ -1,11 +1,12 @@
sub init()
m.content = m.top.findNode("content")
appVersion = m.global.app.version
setPalette()
m.top.id = "OKDialog"
m.top.height = 900
m.top.title = tr("Welcome to version") + " " + m.global.app.version
m.top.title = tr("Welcome to version") + " " + appVersion
m.top.buttons = [tr("OK")]
dialogStyles = {
@ -27,7 +28,7 @@ sub init()
textLine = m.content.CreateChild("StdDlgMultiStyleTextItem")
textLine.drawingStyles = dialogStyles
textLine.text = tr("To view a complete list of changes visit") + " <url>https://github.com/jellyfin/jellyfin-roku/releases/tag/v" + m.global.app.version + "</url>"
textLine.text = tr("To view a complete list of changes visit") + " <url>https://github.com/jellyfin/jellyfin-roku/releases/tag/v" + appVersion + "</url>"
end sub
sub setPalette()

View File

@ -22,10 +22,10 @@ sub init()
' Randomize the background colors
backdropColor = "#00a4db" ' set default in case global var is invalid
localGlobal = m.global
myGlobal = m.global
if isValid(localGlobal) and isValid(localGlobal.constants) and isValid(localGlobal.constants.poster_bg_pallet)
posterBackgrounds = localGlobal.constants.poster_bg_pallet
if isValid(myGlobal) and isValid(myGlobal.constants) and isValid(myGlobal.constants.poster_bg_pallet)
posterBackgrounds = myGlobal.constants.poster_bg_pallet
backdropColor = posterBackgrounds[rnd(posterBackgrounds.count()) - 1]
end if
@ -62,7 +62,7 @@ sub itemContentChanged()
if isValid(m.unplayedCount) then m.unplayedCount.visible = false
itemData = m.top.itemContent
if itemData = invalid then return
localGlobal = m.global
userSettings = m.global.session.user.settings
itemData.Title = itemData.name ' Temporarily required while we move from "HomeItem" to "JFContentItem"
@ -79,9 +79,9 @@ sub itemContentChanged()
m.itemTextExtra.width = itemData.imageWidth
m.itemTextExtra.visible = true
m.itemTextExtra.text = ""
m.backdrop.width = itemData.imageWidth
if isValid(itemData.iconUrl)
m.itemIcon.uri = itemData.iconUrl
end if
@ -92,8 +92,8 @@ sub itemContentChanged()
m.playedIndicator.visible = false
if LCase(itemData.type) = "series"
if isValid(localGlobal) and isValid(localGlobal.session) and isValid(localGlobal.session.user) and isValid(localGlobal.session.user.settings)
unwatchedEpisodeCountSetting = localGlobal.session.user.settings["ui.tvshows.disableUnwatchedEpisodeCount"]
if isValid(userSettings)
unwatchedEpisodeCountSetting = userSettings["ui.tvshows.disableUnwatchedEpisodeCount"]
if isValid(unwatchedEpisodeCountSetting) and not unwatchedEpisodeCountSetting
if isValid(itemData.json.UserData) and isValid(itemData.json.UserData.UnplayedItemCount)
if itemData.json.UserData.UnplayedItemCount > 0
@ -164,16 +164,16 @@ sub itemContentChanged()
drawProgressBar(itemData)
end if
if localGlobal.session.user.settings["ui.general.episodeimagesnextup"] = "webclient"
tmpSetting = localGlobal.session.user.Configuration.useEpisodeImagesInNextUpAndResume
if userSettings["ui.general.episodeimagesnextup"] = "webclient"
tmpSetting = m.global.session.user.Configuration.useEpisodeImagesInNextUpAndResume
if isValid(tmpSetting) and tmpSetting
m.itemPoster.uri = itemData.thumbnailURL
else
m.itemPoster.uri = itemData.widePosterURL
end if
else if localGlobal.session.user.settings["ui.general.episodeimagesnextup"] = "show"
else if userSettings["ui.general.episodeimagesnextup"] = "show"
m.itemPoster.uri = itemData.widePosterURL
else if localGlobal.session.user.settings["ui.general.episodeimagesnextup"] = "episode"
else if userSettings["ui.general.episodeimagesnextup"] = "episode"
m.itemPoster.uri = itemData.thumbnailURL
end if

View File

@ -76,10 +76,11 @@ sub processUserSections()
m.processedRowCount = 0
sessionUser = m.global.session.user
userSettings = sessionUser.settings
' calculate expected row count by processing homesections
for i = 0 to 6
userSection = sessionUser.settings["homesection" + i.toStr()]
userSection = userSettings["homesection" + i.toStr()]
sectionName = userSection ?? "none"
sectionName = LCase(sectionName)
@ -99,7 +100,7 @@ sub processUserSections()
' Add home sections in order based on user settings
loadedSections = 0
for i = 0 to 6
userSection = sessionUser.settings["homesection" + i.toStr()]
userSection = userSettings["homesection" + i.toStr()]
sectionName = userSection ?? "none"
sectionName = LCase(sectionName)
@ -149,10 +150,10 @@ function getOriginalSectionIndex(sectionName as string) as integer
sectionIndex = 0
indexLatestMediaSection = 0
sessionUser = m.global.session.user
userSettings = m.global.session.user.settings
for i = 0 to 6
userSection = sessionUser.settings["homesection" + i.toStr()]
userSection = userSettings["homesection" + i.toStr()]
settingSectionName = userSection ?? "none"
settingSectionName = LCase(settingSectionName)

View File

@ -60,6 +60,7 @@ sub loadItems()
' Load Next Up
else if m.top.itemsToLoad = "nextUp"
userSettings = m.global.session.user.settings
url = "Shows/NextUp"
params = {}
@ -68,12 +69,12 @@ sub loadItems()
params["SortOrder"] = "Descending"
params["ImageTypeLimit"] = 1
params["UserId"] = m.global.session.user.id
params["EnableRewatching"] = m.global.session.user.settings["ui.details.enablerewatchingnextup"]
params["EnableRewatching"] = userSettings["ui.details.enablerewatchingnextup"]
params["DisableFirstEpisode"] = false
params["limit"] = 24
params["EnableTotalRecordCount"] = false
maxDaysInNextUp = m.global.session.user.settings["ui.details.maxdaysnextup"].ToInt()
maxDaysInNextUp = userSettings["ui.details.maxdaysnextup"].ToInt()
if isValid(maxDaysInNextUp)
if maxDaysInNextUp > 0
dateToday = CreateObject("roDateTime")

View File

@ -58,9 +58,9 @@ sub onSelectAudioPressed()
audioData.data.push(audioStreamItem)
end for
m.global.sceneManager.callFunc("radioDialog", tr("Select Audio"), audioData)
m.global.sceneManager.observeField("returnData", "onSelectionMade")
sceneManager = m.global.sceneManager
sceneManager.callFunc("radioDialog", tr("Select Audio"), audioData)
sceneManager.observeField("returnData", "onSelectionMade")
end sub
' User requested subtitle selection popup
@ -110,23 +110,25 @@ sub onSelectSubtitlePressed()
"Type": "subtitleselection"
})
m.global.sceneManager.callFunc("radioDialog", tr("Select Subtitles"), subtitleData)
m.global.sceneManager.observeField("returnData", "onSelectionMade")
sceneManager = m.global.sceneManager
sceneManager.callFunc("radioDialog", tr("Select Subtitles"), subtitleData)
sceneManager.observeField("returnData", "onSelectionMade")
end sub
' User has selected something from the radioDialog popup
sub onSelectionMade()
m.global.sceneManager.unobserveField("returnData")
sceneManager = m.global.sceneManager
sceneManager.unobserveField("returnData")
if not isValid(m.global.sceneManager.returnData) then return
if not isValid(m.global.sceneManager.returnData.type) then return
if not isValid(sceneManager.returnData) then return
if not isValid(sceneManager.returnData.type) then return
if LCase(m.global.sceneManager.returnData.type) = "subtitleselection"
if LCase(sceneManager.returnData.type) = "subtitleselection"
processSubtitleSelection()
return
end if
if LCase(m.global.sceneManager.returnData.type) = "audioselection"
if LCase(sceneManager.returnData.type) = "audioselection"
processAudioSelection()
return
end if
@ -216,21 +218,24 @@ end sub
' Playback state change event handlers
sub onStateChange()
if LCase(m.view.state) = "finished"
sceneManager = m.global.sceneManager
queueManager = m.global.queueManager
' Close any open dialogs
if m.global.sceneManager.callFunc("isDialogOpen")
m.global.sceneManager.callFunc("dismissDialog")
if sceneManager.callFunc("isDialogOpen")
sceneManager.callFunc("dismissDialog")
end if
' If there is something next in the queue, play it
if m.global.queueManager.callFunc("getPosition") < m.global.queueManager.callFunc("getCount") - 1
m.global.sceneManager.callFunc("clearPreviousScene")
m.global.queueManager.callFunc("moveForward")
m.global.queueManager.callFunc("playQueue")
if queueManager.callFunc("getPosition") < queueManager.callFunc("getCount") - 1
sceneManager.callFunc("clearPreviousScene")
queueManager.callFunc("moveForward")
queueManager.callFunc("playQueue")
return
end if
' Playback completed, return user to previous screen
m.global.sceneManager.callFunc("popScene")
sceneManager.callFunc("popScene")
m.global.audioPlayer.loopMode = ""
end if
end sub

View File

@ -97,6 +97,7 @@ sub itemContentChanged()
' Updates video metadata
item = m.top.itemContent
if isValid(item) and isValid(item.json)
userSettings = m.global.session.user.settings
itemData = item.json
m.top.id = itemData.id
m.top.findNode("moviePoster").uri = m.top.itemContent.posterURL
@ -120,7 +121,7 @@ sub itemContentChanged()
m.infoGroup.removeChild(m.top.findNode("officialRating"))
end if
if m.global.session.user.settings["ui.movies.showRatings"]
if userSettings["ui.movies.showRatings"]
if isValid(itemData.communityRating)
setFieldText("communityRating", int(itemData.communityRating * 10) / 10)
else
@ -145,7 +146,7 @@ sub itemContentChanged()
if type(itemData.RunTimeTicks) = "LongInteger"
setFieldText("runtime", stri(getRuntime()) + " mins")
if m.global.session.user.settings["ui.design.hideclock"] <> true
if userSettings["ui.design.hideclock"] <> true
setFieldText("ends-at", tr("Ends at %1").Replace("%1", getEndTime()))
end if
end if
@ -173,7 +174,7 @@ sub itemContentChanged()
m.top.findNode("details").removeChild(m.top.findNode("director"))
end if
if m.global.session.user.settings["ui.details.hidetagline"] = false
if userSettings["ui.details.hidetagline"] = false
if itemData.taglines.count() > 0
setFieldText("tagline", itemData.taglines[0])
end if

View File

@ -9,9 +9,14 @@ sub init()
m.lastRecordedPositionTimestamp = 0
m.scrubTimestamp = -1
m.playlistTypeCount = m.global.queueManager.callFunc("getQueueUniqueTypes").count()
m.queueManager = m.global.queueManager
m.playlistTypeCount = m.queueManager.callFunc("getQueueUniqueTypes").count()
m.audioPlayer = m.global.audioPlayer
m.audioPlayer.observeField("state", "audioStateChanged")
m.audioPlayer.observeField("position", "audioPositionChanged")
m.audioPlayer.observeField("bufferingStatus", "bufferPositionChanged")
setupAudioNode()
setupAnimationTasks()
setupButtons()
setupInfoNodes()
@ -91,13 +96,6 @@ sub setupDataTasks()
m.LoadScreenSaverTimeoutTask = CreateObject("roSGNode", "LoadScreenSaverTimeoutTask")
end sub
' Creates audio node used to play song(s)
sub setupAudioNode()
m.global.audioPlayer.observeField("state", "audioStateChanged")
m.global.audioPlayer.observeField("position", "audioPositionChanged")
m.global.audioPlayer.observeField("bufferingStatus", "bufferPositionChanged")
end sub
' Setup playback buttons, default to Play button selected
sub setupButtons()
m.buttons = m.top.findNode("buttons")
@ -149,10 +147,10 @@ end sub
sub bufferPositionChanged()
if m.inScrubMode then return
if not isValid(m.global.audioPlayer.bufferingStatus)
if not isValid(m.audioPlayer.bufferingStatus)
bufferPositionBarWidth = m.seekBar.width
else
bufferPositionBarWidth = m.seekBar.width * m.global.audioPlayer.bufferingStatus.percentage
bufferPositionBarWidth = m.seekBar.width * m.audioPlayer.bufferingStatus.percentage
end if
' Ensure position bar is never wider than the seek bar
@ -168,16 +166,16 @@ end sub
sub audioPositionChanged()
stopLoadingSpinner()
if m.global.audioPlayer.position = 0
if m.audioPlayer.position = 0
m.playPosition.width = 0
end if
if not isValid(m.global.audioPlayer.position)
if not isValid(m.audioPlayer.position)
playPositionBarWidth = 0
else if not isValid(m.songDuration)
playPositionBarWidth = 0
else
songPercentComplete = m.global.audioPlayer.position / m.songDuration
songPercentComplete = m.audioPlayer.position / m.songDuration
playPositionBarWidth = m.seekBar.width * songPercentComplete
end if
@ -189,7 +187,7 @@ sub audioPositionChanged()
if not m.inScrubMode
moveSeekbarThumb(playPositionBarWidth)
' Change the seek position timestamp
m.seekTimestamp.text = secondsToHuman(m.global.audioPlayer.position, false)
m.seekTimestamp.text = secondsToHuman(m.audioPlayer.position, false)
end if
' Use animation to make the display smooth
@ -197,9 +195,9 @@ sub audioPositionChanged()
m.playPositionAnimation.control = "start"
' Update displayed position timestamp
if isValid(m.global.audioPlayer.position)
m.lastRecordedPositionTimestamp = m.global.audioPlayer.position
m.positionTimestamp.text = secondsToHuman(m.global.audioPlayer.position, false)
if isValid(m.audioPlayer.position)
m.lastRecordedPositionTimestamp = m.audioPlayer.position
m.positionTimestamp.text = secondsToHuman(m.audioPlayer.position, false)
else
m.lastRecordedPositionTimestamp = 0
m.positionTimestamp.text = "0:00"
@ -247,25 +245,24 @@ sub endScreenSaver()
end sub
sub audioStateChanged()
' Song Finished, attempt to move to next song
if m.global.audioPlayer.state = "finished"
if m.audioPlayer.state = "finished"
' User has enabled single song loop, play current song again
if m.global.audioPlayer.loopMode = "one"
if m.audioPlayer.loopMode = "one"
m.scrubTimestamp = -1
playAction()
exitScrubMode()
return
end if
if m.global.queueManager.callFunc("getPosition") < m.global.queueManager.callFunc("getCount") - 1
if m.queueManager.callFunc("getPosition") < m.queueManager.callFunc("getCount") - 1
m.top.state = "finished"
else
' We are at the end of the song queue
' User has enabled loop for entire song queue, move back to first song
if m.global.audioPlayer.loopMode = "all"
m.global.queueManager.callFunc("setPosition", -1)
if m.audioPlayer.loopMode = "all"
m.queueManager.callFunc("setPosition", -1)
LoadNextSong()
return
end if
@ -277,18 +274,19 @@ sub audioStateChanged()
end sub
function playAction() as boolean
if m.global.audioPlayer.state = "playing"
m.global.audioPlayer.control = "pause"
if m.audioPlayer.state = "playing"
m.audioPlayer.control = "pause"
' Allow screen to go to real screensaver
WriteAsciiFile("tmp:/scene.temp", "nowplaying-paused")
MoveFile("tmp:/scene.temp", "tmp:/scene")
else if m.global.audioPlayer.state = "paused"
m.global.audioPlayer.control = "resume"
else if m.audioPlayer.state = "paused"
m.audioPlayer.control = "resume"
' Write screen tracker for screensaver
WriteAsciiFile("tmp:/scene.temp", "nowplaying")
MoveFile("tmp:/scene.temp", "tmp:/scene")
else if m.global.audioPlayer.state = "finished"
m.global.audioPlayer.control = "play"
else if m.audioPlayer.state = "finished"
m.audioPlayer.control = "play"
' Write screen tracker for screensaver
WriteAsciiFile("tmp:/scene.temp", "nowplaying")
MoveFile("tmp:/scene.temp", "tmp:/scene")
@ -298,20 +296,19 @@ function playAction() as boolean
end function
function previousClicked() as boolean
currentQueuePosition = m.global.queueManager.callFunc("getPosition")
currentQueuePosition = m.queueManager.callFunc("getPosition")
if currentQueuePosition = 0 then return false
if m.playlistTypeCount > 1
previousItem = m.global.queueManager.callFunc("getItemByIndex", currentQueuePosition - 1)
previousItemType = m.global.queueManager.callFunc("getItemType", previousItem)
previousItem = m.queueManager.callFunc("getItemByIndex", currentQueuePosition - 1)
previousItemType = m.queueManager.callFunc("getItemType", previousItem)
if previousItemType <> "audio"
m.global.audioPlayer.control = "stop"
m.audioPlayer.control = "stop"
m.global.sceneManager.callFunc("clearPreviousScene")
m.global.queueManager.callFunc("moveBack")
m.global.queueManager.callFunc("playQueue")
m.queueManager.callFunc("moveBack")
m.queueManager.callFunc("playQueue")
return true
end if
end if
@ -321,34 +318,33 @@ function previousClicked() as boolean
m.lastRecordedPositionTimestamp = 0
m.positionTimestamp.text = "0:00"
if m.global.audioPlayer.state = "playing"
m.global.audioPlayer.control = "stop"
if m.audioPlayer.state = "playing"
m.audioPlayer.control = "stop"
end if
' Reset loop mode due to manual user interaction
if m.global.audioPlayer.loopMode = "one"
if m.audioPlayer.loopMode = "one"
resetLoopModeToDefault()
end if
m.global.queueManager.callFunc("moveBack")
m.queueManager.callFunc("moveBack")
pageContentChanged()
return true
end function
sub resetLoopModeToDefault()
m.global.audioPlayer.loopMode = ""
m.audioPlayer.loopMode = ""
setLoopButtonImage()
end sub
function loopClicked() as boolean
if m.global.audioPlayer.loopMode = ""
m.global.audioPlayer.loopMode = "all"
else if m.global.audioPlayer.loopMode = "all"
m.global.audioPlayer.loopMode = "one"
if m.audioPlayer.loopMode = ""
m.audioPlayer.loopMode = "all"
else if m.audioPlayer.loopMode = "all"
m.audioPlayer.loopMode = "one"
else
m.global.audioPlayer.loopMode = ""
m.audioPlayer.loopMode = ""
end if
setLoopButtonImage()
@ -357,10 +353,10 @@ function loopClicked() as boolean
end function
sub setLoopButtonImage()
if m.global.audioPlayer.loopMode = "all"
if m.audioPlayer.loopMode = "all"
m.loopIndicator.opacity = "1"
m.loopIndicator.uri = m.loopIndicator.uri.Replace("-off", "-on")
else if m.global.audioPlayer.loopMode = "one"
else if m.audioPlayer.loopMode = "one"
m.loopIndicator.uri = m.loopIndicator.uri.Replace("-on", "1-on")
else
m.loopIndicator.uri = m.loopIndicator.uri.Replace("1-on", "-off")
@ -368,19 +364,20 @@ sub setLoopButtonImage()
end sub
function nextClicked() as boolean
if m.playlistTypeCount > 1
currentQueuePosition = m.global.queueManager.callFunc("getPosition")
if currentQueuePosition < m.global.queueManager.callFunc("getCount") - 1
nextItem = m.global.queueManager.callFunc("getItemByIndex", currentQueuePosition + 1)
nextItemType = m.global.queueManager.callFunc("getItemType", nextItem)
if m.playlistTypeCount > 1
currentQueuePosition = m.queueManager.callFunc("getPosition")
if currentQueuePosition < m.queueManager.callFunc("getCount") - 1
nextItem = m.queueManager.callFunc("getItemByIndex", currentQueuePosition + 1)
nextItemType = m.queueManager.callFunc("getItemType", nextItem)
if nextItemType <> "audio"
m.global.audioPlayer.control = "stop"
m.audioPlayer.control = "stop"
m.global.sceneManager.callFunc("clearPreviousScene")
m.global.queueManager.callFunc("moveForward")
m.global.queueManager.callFunc("playQueue")
m.queueManager.callFunc("moveForward")
m.queueManager.callFunc("playQueue")
return true
end if
end if
@ -392,11 +389,11 @@ function nextClicked() as boolean
m.positionTimestamp.text = "0:00"
' Reset loop mode due to manual user interaction
if m.global.audioPlayer.loopMode = "one"
if m.audioPlayer.loopMode = "one"
resetLoopModeToDefault()
end if
if m.global.queueManager.callFunc("getPosition") < m.global.queueManager.callFunc("getCount") - 1
if m.queueManager.callFunc("getPosition") < m.queueManager.callFunc("getCount") - 1
LoadNextSong()
end if
@ -404,14 +401,14 @@ function nextClicked() as boolean
end function
sub toggleShuffleEnabled()
m.global.queueManager.callFunc("toggleShuffle")
m.queueManager.callFunc("toggleShuffle")
end sub
function findCurrentSongIndex(songList) as integer
if not isValidAndNotEmpty(songList) then return 0
for i = 0 to songList.count() - 1
if songList[i].id = m.global.queueManager.callFunc("getCurrentItem").id
if songList[i].id = m.queueManager.callFunc("getCurrentItem").id
return i
end if
end for
@ -420,15 +417,14 @@ function findCurrentSongIndex(songList) as integer
end function
function shuffleClicked() as boolean
currentSongIndex = findCurrentSongIndex(m.global.queueManager.callFunc("getUnshuffledQueue"))
currentSongIndex = findCurrentSongIndex(m.queueManager.callFunc("getUnshuffledQueue"))
toggleShuffleEnabled()
if not m.global.queueManager.callFunc("getIsShuffled")
if not m.queueManager.callFunc("getIsShuffled")
m.shuffleIndicator.opacity = ".4"
m.shuffleIndicator.uri = m.shuffleIndicator.uri.Replace("-on", "-off")
m.global.queueManager.callFunc("setPosition", currentSongIndex)
m.queueManager.callFunc("setPosition", currentSongIndex)
setTrackNumberDisplay()
return true
end if
@ -441,26 +437,26 @@ function shuffleClicked() as boolean
end function
sub setShuffleIconState()
if m.global.queueManager.callFunc("getIsShuffled")
if m.queueManager.callFunc("getIsShuffled")
m.shuffleIndicator.opacity = "1"
m.shuffleIndicator.uri = m.shuffleIndicator.uri.Replace("-off", "-on")
end if
end sub
sub setTrackNumberDisplay()
setFieldTextValue("numberofsongs", "Track " + stri(m.global.queueManager.callFunc("getPosition") + 1) + "/" + stri(m.global.queueManager.callFunc("getCount")))
setFieldTextValue("numberofsongs", "Track " + stri(m.queueManager.callFunc("getPosition") + 1) + "/" + stri(m.queueManager.callFunc("getCount")))
end sub
sub LoadNextSong()
if m.global.audioPlayer.state = "playing"
m.global.audioPlayer.control = "stop"
if m.audioPlayer.state = "playing"
m.audioPlayer.control = "stop"
end if
exitScrubMode()
' Reset playPosition bar without animation
m.playPosition.width = 0
m.global.queueManager.callFunc("moveForward")
m.queueManager.callFunc("moveForward")
pageContentChanged()
end sub
@ -469,7 +465,7 @@ sub pageContentChanged()
m.LoadAudioStreamTask.control = "STOP"
currentItem = m.global.queueManager.callFunc("getCurrentItem")
currentItem = m.queueManager.callFunc("getCurrentItem")
m.LoadAudioStreamTask.itemId = currentItem.id
m.LoadAudioStreamTask.observeField("content", "onAudioStreamLoaded")
@ -478,7 +474,7 @@ end sub
' If we have more and 1 song to play, fade in the next and previous controls
sub loadButtons()
if m.global.queueManager.callFunc("getCount") > 1
if m.queueManager.callFunc("getCount") > 1
m.shuffleIndicator.opacity = ".4"
m.loopIndicator.opacity = ".4"
m.displayButtonsAnimation.control = "start"
@ -495,7 +491,7 @@ sub onAudioStreamLoaded()
m.bufferPosition.width = 0
useMetaTask = false
currentItem = m.global.queueManager.callFunc("getCurrentItem")
currentItem = m.queueManager.callFunc("getCurrentItem")
if not isValid(currentItem.RunTimeTicks)
useMetaTask = true
@ -531,9 +527,9 @@ sub onAudioStreamLoaded()
m.totalLengthTimestamp.text = ticksToHuman(currentItem.RunTimeTicks)
end if
m.global.audioPlayer.content = data
m.global.audioPlayer.control = "none"
m.global.audioPlayer.control = "play"
m.audioPlayer.content = data
m.audioPlayer.control = "none"
m.audioPlayer.control = "play"
end if
end sub
@ -739,7 +735,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
if m.inScrubMode
startLoadingSpinner()
m.inScrubMode = false
m.global.audioPlayer.seek = m.scrubTimestamp
m.audioPlayer.seek = m.scrubTimestamp
return true
end if
@ -773,15 +769,15 @@ function onKeyEvent(key as string, press as boolean) as boolean
end if
if key = "back"
m.global.audioPlayer.control = "stop"
m.global.audioPlayer.loopMode = ""
m.audioPlayer.control = "stop"
m.audioPlayer.loopMode = ""
else if key = "rewind"
return previousClicked()
else if key = "fastforward"
return nextClicked()
else if key = "left"
if m.buttons.hasFocus()
if m.global.queueManager.callFunc("getCount") = 1 then return false
if m.queueManager.callFunc("getCount") = 1 then return false
if m.top.selectedButtonIndex > 0
m.previouslySelectedButtonIndex = m.top.selectedButtonIndex
@ -791,7 +787,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
end if
else if key = "right"
if m.buttons.hasFocus()
if m.global.queueManager.callFunc("getCount") = 1 then return false
if m.queueManager.callFunc("getCount") = 1 then return false
m.previouslySelectedButtonIndex = m.top.selectedButtonIndex
if m.top.selectedButtonIndex < m.buttonCount - 1 then m.top.selectedButtonIndex = m.top.selectedButtonIndex + 1

View File

@ -10,8 +10,9 @@ sub init()
m.textBackground = m.top.findNode("background")
m.statusTimer = m.top.findNode("statusTimer")
m.statusTimer.observeField("fire", "statusUpdate")
m.slideshow = m.global.session.user.settings["photos.slideshow"]
m.random = m.global.session.user.settings["photos.random"]
userSettings = m.global.session.user.settings
m.slideshow = userSettings["photos.slideshow"]
m.random = userSettings["photos.random"]
m.showStatusAnimation = m.top.findNode("showStatusAnimation")
m.hideStatusAnimation = m.top.findNode("hideStatusAnimation")

View File

@ -91,26 +91,28 @@ sub settingFocused()
m.integerSetting.visible = false
m.radioSetting.visible = false
userSettings = m.global.session.user.settings
if selectedSetting.type = invalid
return
else if selectedSetting.type = "bool"
m.boolSetting.visible = true
if m.global.session.user.settings[selectedSetting.settingName] = true
if userSettings[selectedSetting.settingName] = true
m.boolSetting.checkedItem = 1
else
m.boolSetting.checkedItem = 0
end if
else if selectedSetting.type = "integer"
integerValue = m.global.session.user.settings[selectedSetting.settingName].ToStr()
integerValue = userSettings[selectedSetting.settingName].ToStr()
if isValid(integerValue)
m.integerSetting.text = integerValue
end if
m.integerSetting.visible = true
else if LCase(selectedSetting.type) = "radio"
selectedValue = m.global.session.user.settings[selectedSetting.settingName]
selectedValue = userSettings[selectedSetting.settingName]
radioContent = CreateObject("roSGNode", "ContentNode")
@ -173,7 +175,6 @@ sub boolSettingChanged()
set_setting(selectedSetting.settingName, "true")
' setting specific triggers
if selectedSetting.settingName = "global.rememberme"
print "m.global.session.user.id=", m.global.session.user.id
set_setting("active_user", m.global.session.user.id)
end if
else

View File

@ -21,13 +21,16 @@ end sub
sub itemContentChanged()
item = m.top.itemContent
itemData = item.json
userSettings = m.global.session.user.settings
' Set default video source if user hasn't selected one yet
if item.selectedVideoStreamId = "" and isValid(itemData.MediaSources)
item.selectedVideoStreamId = itemData.MediaSources[0].id
end if
if isValid(itemData.indexNumber)
if isValid(itemData.parentIndexNumber) and itemData.parentIndexNumber = 0
indexNumber = `${tr("Special")} - `
else if isValid(itemData.indexNumber)
indexNumber = `${itemData.indexNumber}. `
if isValid(itemData.indexNumberEnd)
indexNumber = `${itemData.indexNumber}-${itemData.indexNumberEnd}. `
@ -46,7 +49,7 @@ sub itemContentChanged()
imageUrl = item.posterURL
if m.global.session.user.settings["ui.tvshows.blurunwatched"] = true
if userSettings["ui.tvshows.blurunwatched"] = true
if itemData.lookup("Type") = "Episode"
if not itemData.userdata.played
imageUrl = imageUrl + "&blur=15"
@ -64,12 +67,12 @@ sub itemContentChanged()
m.top.findNode("runtime").text = stri(runTime).trim() + " mins"
end if
if m.global.session.user.settings["ui.design.hideclock"] <> true
if userSettings["ui.design.hideclock"] <> true
m.top.findNode("endtime").text = tr("Ends at %1").Replace("%1", getEndTime())
end if
end if
if m.global.session.user.settings["ui.tvshows.disableCommunityRating"] = false
if userSettings["ui.tvshows.disableCommunityRating"] = false
if isValid(itemData.communityRating)
m.top.findNode("star").visible = true
m.top.findNode("communityRating").text = str(int(itemData.communityRating * 10) / 10)

View File

@ -181,9 +181,11 @@ end function
sub onShuffleEpisodeDataLoaded()
m.getShuffleEpisodesTask.unobserveField("data")
if isValid(m.getShuffleEpisodesTask.data)
m.global.queueManager.callFunc("set", m.getShuffleEpisodesTask.data.items)
m.global.queueManager.callFunc("playQueue")
queueManager = m.global.queueManager
queueManager.callFunc("set", m.getShuffleEpisodesTask.data.items)
queueManager.callFunc("playQueue")
end if
end sub

View File

@ -35,7 +35,6 @@ sub init()
m.optionControls.buttonFocused = m.optionControls.getChildCount() - 1
m.videoControls.getChild(m.defaultButtonIndex).focus = true
m.deviceInfo = CreateObject("roDeviceInfo")
end sub
' onProgressPercentageChanged: Handler for changes to m.top.progressPercentage param
@ -221,7 +220,8 @@ sub inactiveCheck()
return
end if
if m.deviceInfo.timeSinceLastKeypress() >= m.top.inactiveTimeout
deviceInfo = CreateObject("roDeviceInfo")
if deviceInfo.timeSinceLastKeypress() >= m.top.inactiveTimeout
m.top.action = "hide"
end if
end sub

View File

@ -7,6 +7,7 @@ sub init()
m.log = log.Logger("VideoPlayerView")
' Hide the overhang on init to prevent showing 2 clocks
m.top.getScene().findNode("overhang").visible = false
userSettings = m.global.session.user.settings
m.currentItem = m.global.queueManager.callFunc("getCurrentItem")
m.top.id = m.currentItem.id
@ -46,7 +47,7 @@ sub init()
m.top.transcodeReasons = []
m.bufferCheckTimer.duration = 30
if m.global.session.user.settings["ui.design.hideclock"] = true
if userSettings["ui.design.hideclock"] = true
clockNode = findNodeBySubtype(m.top, "clock")
if clockNode[0] <> invalid then clockNode[0].parent.removeChild(clockNode[0].node)
end if
@ -55,7 +56,7 @@ sub init()
m.nextEpisodeButton = m.top.findNode("nextEpisode")
m.nextEpisodeButton.text = tr("Next Episode")
m.nextEpisodeButton.setFocus(false)
m.nextupbuttonseconds = m.global.session.user.settings["playback.nextupbuttonseconds"].ToInt()
m.nextupbuttonseconds = userSettings["playback.nextupbuttonseconds"].ToInt()
m.showNextEpisodeButtonAnimation = m.top.findNode("showNextEpisodeButton")
m.hideNextEpisodeButtonAnimation = m.top.findNode("hideNextEpisodeButton")
@ -100,26 +101,30 @@ end sub
' @param {string} action - skip action to take
sub handleItemSkipAction(action as string)
if action = "itemnext"
queueManager = m.global.queueManager
' If there is something next in the queue, play it
if m.global.queueManager.callFunc("getPosition") < m.global.queueManager.callFunc("getCount") - 1
if queueManager.callFunc("getPosition") < queueManager.callFunc("getCount") - 1
m.top.control = "stop"
session.video.Delete()
m.global.sceneManager.callFunc("clearPreviousScene")
m.global.queueManager.callFunc("moveForward")
m.global.queueManager.callFunc("playQueue")
queueManager.callFunc("moveForward")
queueManager.callFunc("playQueue")
end if
return
end if
if action = "itemback"
queueManager = m.global.queueManager
' If there is something previous in the queue, play it
if m.global.queueManager.callFunc("getPosition") > 0
if queueManager.callFunc("getPosition") > 0
m.top.control = "stop"
session.video.Delete()
m.global.sceneManager.callFunc("clearPreviousScene")
m.global.queueManager.callFunc("moveBack")
m.global.queueManager.callFunc("playQueue")
queueManager.callFunc("moveBack")
queueManager.callFunc("playQueue")
end if
return
@ -523,9 +528,9 @@ sub showNextEpisodeButton()
if m.top.content.contenttype <> 4 then return ' only display when content is type "Episode"
if m.nextupbuttonseconds = 0 then return ' is the button disabled?
if m.nextEpisodeButton.opacity <> 0 then return
userSession = m.global.session.user
if userSession.settings["playback.playnextepisode"] = "disabled" then return
if userSession.settings["playback.playnextepisode"] = "webclient" and not userSession.Configuration.EnableNextEpisodeAutoPlay then return
userSettings = m.global.session.user.settings
if userSettings["playback.playnextepisode"] = "disabled" then return
if userSettings["playback.playnextepisode"] = "webclient" and not m.global.session.user.Configuration.EnableNextEpisodeAutoPlay then return
m.nextEpisodeButton.visible = true
m.showNextEpisodeButtonAnimation.control = "start"

View File

@ -44,10 +44,10 @@ end sub
sub itemContentChanged()
m.backdrop.blendColor = "#00a4db" ' set default in case global var is invalid
localGlobal = m.global
myGlobal = m.global
if isValid(localGlobal) and isValid(localGlobal.constants) and isValid(localGlobal.constants.poster_bg_pallet)
posterBackgrounds = localGlobal.constants.poster_bg_pallet
if isValid(myGlobal) and isValid(myGlobal.constants) and isValid(myGlobal.constants.poster_bg_pallet)
posterBackgrounds = myGlobal.constants.poster_bg_pallet
m.backdrop.blendColor = posterBackgrounds[rnd(posterBackgrounds.count()) - 1]
end if
@ -64,8 +64,8 @@ sub itemContentChanged()
m.itemIcon.uri = itemData.iconUrl
m.itemText.text = itemData.Title
else if itemData.type = "Series"
if isValid(localGlobal) and isValid(localGlobal.session) and isValid(localGlobal.session.user) and isValid(localGlobal.session.user.settings)
if localGlobal.session.user.settings["ui.tvshows.disableUnwatchedEpisodeCount"] = false
if isValid(myGlobal) and isValid(myGlobal.session) and isValid(myGlobal.session.user) and isValid(myGlobal.session.user.settings)
if myGlobal.session.user.settings["ui.tvshows.disableUnwatchedEpisodeCount"] = false
if isValid(itemData.json) and isValid(itemData.json.UserData) and isValid(itemData.json.UserData.UnplayedItemCount)
if itemData.json.UserData.UnplayedItemCount > 0
m.unplayedCount.visible = true

View File

@ -9,9 +9,11 @@ import "pkg:/source/roku_modules/log/LogMixin.brs"
sub init()
m.log = log.Logger("ItemGrid")
m.log.debug("start init()")
userSettings = m.global.session.user.settings
m.options = m.top.findNode("options")
m.showItemCount = m.global.session.user.settings["itemgrid.showItemCount"]
m.showItemCount = userSettings["itemgrid.showItemCount"]
m.tvGuide = invalid
m.channelFocused = invalid
@ -70,9 +72,9 @@ sub init()
m.alphaMenu = m.alpha.findNode("alphaMenu")
'Get reset folder setting
m.resetGrid = m.global.session.user.settings["itemgrid.reset"]
m.resetGrid = userSettings["itemgrid.reset"]
m.top.gridTitles = m.global.session.user.settings["itemgrid.gridTitles"]
m.top.gridTitles = userSettings["itemgrid.gridTitles"]
m.log.debug("end init()")
end sub
@ -86,6 +88,7 @@ sub loadInitialItems()
m.log.debug("start loadInitialItems()")
m.loadItemsTask.control = "stop"
startLoadingSpinner()
userSettings = m.global.session.user.settings
if m.top.parentItem.json.Type = "CollectionFolder" 'or m.top.parentItem.json.Type = "Folder"
m.top.HomeLibraryItem = m.top.parentItem.Id
@ -98,25 +101,25 @@ sub loadInitialItems()
' Read view/sort/filter settings
if m.top.parentItem.collectionType = "livetv"
' Translate between app and server nomenclature
viewSetting = m.global.session.user.settings["display.livetv.landing"]
viewSetting = userSettings["display.livetv.landing"]
if viewSetting = "guide"
m.view = "tvGuide"
else
m.view = "livetv"
end if
m.sortField = m.global.session.user.settings["display.livetv.sortField"]
sortAscendingStr = m.global.session.user.settings["display.livetv.sortAscending"]
m.filter = m.global.session.user.settings["display.livetv.filter"]
m.sortField = userSettings["display.livetv.sortField"]
sortAscendingStr = userSettings["display.livetv.sortAscending"]
m.filter = userSettings["display.livetv.filter"]
else if m.top.parentItem.collectionType = "music"
m.view = m.global.session.user.settings["display.music.view"]
m.sortField = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortField"]
sortAscendingStr = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortAscending"]
m.filter = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filter"]
m.view = userSettings["display.music.view"]
m.sortField = userSettings["display." + m.top.parentItem.Id + ".sortField"]
sortAscendingStr = userSettings["display." + m.top.parentItem.Id + ".sortAscending"]
m.filter = userSettings["display." + m.top.parentItem.Id + ".filter"]
else
m.sortField = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortField"]
sortAscendingStr = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortAscending"]
m.filter = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filter"]
m.view = m.global.session.user.settings["display." + m.top.parentItem.Id + ".landing"]
m.sortField = userSettings["display." + m.top.parentItem.Id + ".sortField"]
sortAscendingStr = userSettings["display." + m.top.parentItem.Id + ".sortAscending"]
m.filter = userSettings["display." + m.top.parentItem.Id + ".filter"]
m.view = userSettings["display." + m.top.parentItem.Id + ".landing"]
end if
if m.sortField = invalid
@ -182,7 +185,7 @@ sub loadInitialItems()
m.loadItemsTask.itemType = "MusicArtist"
m.loadItemsTask.itemId = m.top.parentItem.Id
m.view = m.global.session.user.settings["display.music.view"]
m.view = userSettings["display.music.view"]
if m.view = "music-album"
m.loadItemsTask.itemType = "MusicAlbum"
@ -193,7 +196,7 @@ sub loadInitialItems()
' For LiveTV, we want to "Fit" the item images, not zoom
m.top.imageDisplayMode = "scaleToFit"
if m.global.session.user.settings["display.livetv.landing"] = "guide" and m.options.view &lt;> "livetv"
if userSettings["display.livetv.landing"] = "guide" and m.options.view &lt;> "livetv"
showTvGuide()
end if
else if m.top.parentItem.collectionType = "CollectionFolder" or m.top.parentItem.type = "CollectionFolder" or m.top.parentItem.collectionType = "boxsets" or m.top.parentItem.Type = "Boxset" or m.top.parentItem.Type = "Boxsets" or m.top.parentItem.Type = "Folder" or m.top.parentItem.Type = "Channel"

View File

@ -20,21 +20,23 @@ sub init()
end sub
sub loadItems()
queueManager = m.global.queueManager
' Reset intro tracker in case task gets reused
m.top.isIntro = false
' Only show preroll once per queue
if m.global.queueManager.callFunc("isPrerollActive")
if queueManager.callFunc("isPrerollActive")
' Prerolls not allowed if we're resuming video
if m.global.queueManager.callFunc("getCurrentItem").startingPoint = 0
if queueManager.callFunc("getCurrentItem").startingPoint = 0
preRoll = GetIntroVideos(m.top.itemId)
if isValid(preRoll) and preRoll.TotalRecordCount > 0 and isValid(preRoll.items[0])
' If an error is thrown in the Intros plugin, instead of passing the error they pass the entire rick roll music video.
' Bypass the music video and treat it as an error message
if lcase(preRoll.items[0].name) &lt;> "rick roll'd"
m.global.queueManager.callFunc("push", m.global.queueManager.callFunc("getCurrentItem"))
queueManager.callFunc("push", queueManager.callFunc("getCurrentItem"))
m.top.itemId = preRoll.items[0].id
m.global.queueManager.callFunc("setPrerollStatus", false)
queueManager.callFunc("setPrerollStatus", false)
m.top.isIntro = true
end if
end if
@ -42,7 +44,7 @@ sub loadItems()
end if
if m.top.selectedAudioStreamIndex = 0
currentItem = m.global.queueManager.callFunc("getCurrentItem")
currentItem = queueManager.callFunc("getCurrentItem")
if isValid(currentItem) and isValid(currentItem.json)
m.top.selectedAudioStreamIndex = FindPreferredAudioStream(currentItem.json.MediaStreams)
end if
@ -80,6 +82,10 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
return
end if
queueManager = m.global.queueManager
userSession = m.global.session.user
userSettings = userSession.settings
session.video.Update(meta)
if isValid(meta.json.MediaSources[0].RunTimeTicks)
@ -134,15 +140,14 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
end if
if LCase(m.top.itemType) = "episode"
userSession = m.global.session.user
if userSession.settings["playback.playnextepisode"] = "enabled" or userSession.settings["playback.playnextepisode"] = "webclient" and userSession.Configuration.EnableNextEpisodeAutoPlay
if userSettings["playback.playnextepisode"] = "enabled" or userSettings["playback.playnextepisode"] = "webclient" and userSession.Configuration.EnableNextEpisodeAutoPlay
addNextEpisodesToQueue(video.showID)
end if
end if
playbackPosition = 0!
currentItem = m.global.queueManager.callFunc("getCurrentItem")
currentItem = queueManager.callFunc("getCurrentItem")
if isValid(currentItem) and isValid(currentItem.startingPoint)
playbackPosition = currentItem.startingPoint
@ -222,8 +227,8 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
' transcode is that the Encoding Level is not supported, then try to direct play but silently
' fall back to the transcode if that fails.
if m.playbackInfo.MediaSources[0].MediaStreams.Count() > 0 and meta.live = false
tryDirectPlay = m.global.session.user.settings["playback.tryDirect.h264ProfileLevel"] and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
tryDirectPlay = tryDirectPlay or (m.global.session.user.settings["playback.tryDirect.hevcProfileLevel"] and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "hevc")
tryDirectPlay = userSettings["playback.tryDirect.h264ProfileLevel"] and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
tryDirectPlay = tryDirectPlay or (userSettings["playback.tryDirect.hevcProfileLevel"] and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "hevc")
if tryDirectPlay and isValid(m.playbackInfo.MediaSources[0].TranscodingUrl) and forceTranscoding = false
transcodingReasons = getTranscodeReasons(m.playbackInfo.MediaSources[0].TranscodingUrl)
if transcodingReasons.Count() = 1 and transcodingReasons[0] = "VideoLevelNotSupported"
@ -263,7 +268,8 @@ end sub
' @param {dynamic} videoID - id of video user is playing
' @return {integer} indicating the default track's server-side index. Defaults to {SubtitleSelection.none} is one is not found
function defaultSubtitleTrackFromVid(videoID) as integer
if m.global.session.user.configuration.SubtitleMode = "None"
userSession = m.global.session.user
if userSession.configuration.SubtitleMode = "None"
return SubtitleSelection.none ' No subtitles desired: return none
end if
@ -289,7 +295,7 @@ function defaultSubtitleTrackFromVid(videoID) as integer
return defaultTextSubs
end if
if not m.global.session.user.settings["playback.subs.onlytext"]
if not userSession.settings["playback.subs.onlytext"]
return defaultSubtitleTrack(subtitles["all"], selectedAudioLanguage) ' if no appropriate text subs exist, allow non-text
end if
@ -493,6 +499,8 @@ end function
' Add next episodes to the playback queue
sub addNextEpisodesToQueue(showID)
queueManager = m.global.queueManager
' Don't queue next episodes if we already have a playback queue
maxQueueCount = 1
@ -500,13 +508,13 @@ sub addNextEpisodesToQueue(showID)
maxQueueCount = 2
end if
if m.global.queueManager.callFunc("getCount") > maxQueueCount then return
if queueManager.callFunc("getCount") > maxQueueCount then return
videoID = m.top.itemId
' If first item is an intro video, use the next item in the queue
if m.top.isIntro
currentVideo = m.global.queueManager.callFunc("getItemByIndex", 1)
currentVideo = queueManager.callFunc("getItemByIndex", 1)
if isValid(currentVideo) and isValid(currentVideo.id)
videoID = currentVideo.id
@ -528,7 +536,7 @@ sub addNextEpisodesToQueue(showID)
if isValid(data) and data.Items.Count() > 1
for i = 1 to data.Items.Count() - 1
m.global.queueManager.callFunc("push", data.Items[i])
queueManager.callFunc("push", data.Items[i])
end for
end if
end sub
@ -587,8 +595,9 @@ function sortSubtitles(id as string, MediaStreams)
end function
function FindPreferredAudioStream(streams as dynamic) as integer
preferredLanguage = m.global.session.user.Configuration.AudioLanguagePreference
playDefault = m.global.session.user.Configuration.PlayDefaultAudioTrack
userConfig = m.global.session.user.configuration
preferredLanguage = userConfig.AudioLanguagePreference
playDefault = userConfig.PlayDefaultAudioTrack
if playDefault &lt;> invalid and playDefault = true
return 1

View File

@ -32,6 +32,7 @@ end sub
sub init()
setupNodes()
userSettings = m.global.session.user.settings
m.overhang.isVisible = false
@ -41,7 +42,7 @@ sub init()
alphaMicText = m.alpha.findNode("alphaMicText")
alphaMicText.visible = false
m.showItemCount = m.global.session.user.settings["itemgrid.showItemCount"]
m.showItemCount = userSettings["itemgrid.showItemCount"]
m.swapAnimation.observeField("state", "swapDone")
@ -88,7 +89,7 @@ sub init()
m.loadItemsTask.totalRecordCount = 0
'Get reset folder setting
m.resetGrid = m.global.session.user.settings["itemgrid.reset"]
m.resetGrid = userSettings["itemgrid.reset"]
end sub
sub OnScreenHidden()
@ -114,6 +115,7 @@ end sub
sub loadInitialItems()
m.loadItemsTask.control = "stop"
startLoadingSpinner(false)
userSettings = m.global.session.user.settings
if m.top.parentItem.json.Type = "CollectionFolder"
m.top.HomeLibraryItem = m.top.parentItem.Id
@ -125,15 +127,15 @@ sub loadInitialItems()
SetBackground("")
end if
m.sortField = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortField"]
m.filter = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filter"]
m.filterOptions = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filterOptions"]
m.view = m.global.session.user.settings["display." + m.top.parentItem.Id + ".landing"]
m.sortAscending = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortAscending"]
m.sortField = userSettings["display." + m.top.parentItem.Id + ".sortField"]
m.filter = userSettings["display." + m.top.parentItem.Id + ".filter"]
m.filterOptions = userSettings["display." + m.top.parentItem.Id + ".filterOptions"]
m.view = userSettings["display." + m.top.parentItem.Id + ".landing"]
m.sortAscending = userSettings["display." + m.top.parentItem.Id + ".sortAscending"]
' If user has not set a preferred view for this folder, check if they've set a default view
if not isValid(m.view)
m.view = m.global.session.user.settings["itemgrid.movieDefaultView"]
m.view = userSettings["itemgrid.movieDefaultView"]
end if
if not isValid(m.sortField) then m.sortField = "SortName"
@ -202,7 +204,7 @@ sub loadInitialItems()
m.itemGrid.numRows = "3"
m.selectedMovieOverview.visible = false
m.infoGroup.visible = false
m.top.showItemTitles = m.global.session.user.settings["itemgrid.gridTitles"]
m.top.showItemTitles = userSettings["itemgrid.gridTitles"]
if LCase(m.top.showItemTitles) = "hidealways"
m.itemGrid.itemSize = "[230, 315]"
m.itemGrid.rowHeights = "[315]"

View File

@ -27,6 +27,7 @@ end sub
sub init()
setupNodes()
userSettings = m.global.session.user.settings
m.overhang.isVisible = false
@ -36,7 +37,7 @@ sub init()
alphaMicText = m.alpha.findNode("alphaMicText")
alphaMicText.visible = false
m.showItemCount = m.global.session.user.settings["itemgrid.showItemCount"]
m.showItemCount = userSettings["itemgrid.showItemCount"]
m.swapAnimation.observeField("state", "swapDone")
@ -82,7 +83,7 @@ sub init()
m.loadItemsTask.totalRecordCount = 0
'Get reset folder setting
m.resetGrid = m.global.session.user.settings["itemgrid.reset"]
m.resetGrid = userSettings["itemgrid.reset"]
end sub
sub OnScreenHidden()
@ -108,6 +109,7 @@ end sub
sub loadInitialItems()
m.loadItemsTask.control = "stop"
startLoadingSpinner(false)
userSettings = m.global.session.user.settings
if LCase(m.top.parentItem.json.Type) = "collectionfolder"
m.top.HomeLibraryItem = m.top.parentItem.Id
@ -119,17 +121,17 @@ sub loadInitialItems()
SetBackground("")
end if
m.sortField = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortField"]
m.sortAscending = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortAscending"]
m.filter = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filter"]
m.view = m.global.session.user.settings["display." + m.top.parentItem.Id + ".landing"]
m.sortField = userSettings["display." + m.top.parentItem.Id + ".sortField"]
m.sortAscending = userSettings["display." + m.top.parentItem.Id + ".sortAscending"]
m.filter = userSettings["display." + m.top.parentItem.Id + ".filter"]
m.view = userSettings["display." + m.top.parentItem.Id + ".landing"]
if not isValid(m.sortField) then m.sortField = "SortName"
if not isValid(m.filter) then m.filter = "All"
if not isValid(m.view) then m.view = "ArtistsPresentation"
if not isValid(m.sortAscending) then m.sortAscending = true
m.top.showItemTitles = m.global.session.user.settings["itemgrid.gridTitles"]
m.top.showItemTitles = userSettings["itemgrid.gridTitles"]
if LCase(m.top.parentItem.json.type) = "musicgenre"
m.itemGrid.translation = "[96, 60]"

View File

@ -15,7 +15,8 @@ sub init()
m.top.transcodeReasons = []
m.bufferCheckTimer.duration = 30
if m.global.session.user.settings["ui.design.hideclock"] = true
userSettings = m.global.session.user.settings
if userSettings["ui.design.hideclock"]
clockNode = findNodeBySubtype(m.top, "clock")
if clockNode[0] &lt;> invalid then clockNode[0].parent.removeChild(clockNode[0].node)
end if
@ -24,7 +25,7 @@ sub init()
m.nextEpisodeButton = m.top.findNode("nextEpisode")
m.nextEpisodeButton.text = tr("Next Episode")
m.nextEpisodeButton.setFocus(false)
m.nextupbuttonseconds = m.global.session.user.settings["playback.nextupbuttonseconds"].ToInt()
m.nextupbuttonseconds = userSettings["playback.nextupbuttonseconds"].ToInt()
m.showNextEpisodeButtonAnimation = m.top.findNode("showNextEpisodeButton")
m.hideNextEpisodeButtonAnimation = m.top.findNode("hideNextEpisodeButton")

View File

@ -19,10 +19,10 @@ sub init()
' Randomize the background colors
backdropColor = "#00a4db" ' set default in case global var is invalid
localGlobal = m.global
myGlobal = m.global
if isValid(localGlobal) and isValid(localGlobal.constants) and isValid(localGlobal.constants.poster_bg_pallet)
posterBackgrounds = localGlobal.constants.poster_bg_pallet
if isValid(myGlobal) and isValid(myGlobal.constants) and isValid(myGlobal.constants.poster_bg_pallet)
posterBackgrounds = myGlobal.constants.poster_bg_pallet
backdropColor = posterBackgrounds[rnd(posterBackgrounds.count()) - 1]
end if
@ -67,8 +67,9 @@ sub itemContentChanged() as void
m.poster = m.top.findNode("poster")
itemData = m.top.itemContent
m.title.text = itemData.title
userSettings = m.global.session.user.settings
if m.global.session.user.settings["ui.tvshows.disableUnwatchedEpisodeCount"] = false
if not userSettings["ui.tvshows.disableUnwatchedEpisodeCount"]
if isValid(itemData.json.UserData) and isValid(itemData.json.UserData.UnplayedItemCount)
if itemData.json.UserData.UnplayedItemCount > 0
m.unplayedCount.visible = true
@ -96,7 +97,7 @@ sub itemContentChanged() as void
imageUrl = itemData.posterURL
if m.global.session.user.settings["ui.tvshows.blurunwatched"] = true
if userSettings["ui.tvshows.blurunwatched"]
if itemData.json.lookup("Type") = "Episode" and isValid(itemData.json.userdata)
if not itemData.json.userdata.played
imageUrl = imageUrl + "&amp;blur=15"
@ -118,7 +119,7 @@ sub focusChanged()
m.staticTitle.visible = false
m.title.visible = true
' text to speech for accessibility
if m.global.device.isAudioGuideEnabled = true
if m.global.device.isAudioGuideEnabled
txt2Speech = CreateObject("roTextToSpeech")
txt2Speech.Flush()
txt2Speech.Say(m.title.text)

File diff suppressed because one or more lines are too long

View File

@ -24,10 +24,10 @@ sub init()
' Randomize the background colors
backdropColor = "#00a4db" ' set default in case global var is invalid
localGlobal = m.global
myGlobal = m.global
if isValid(localGlobal) and isValid(localGlobal.constants) and isValid(localGlobal.constants.poster_bg_pallet)
posterBackgrounds = localGlobal.constants.poster_bg_pallet
if isValid(myGlobal) and isValid(myGlobal.constants) and isValid(myGlobal.constants.poster_bg_pallet)
posterBackgrounds = myGlobal.constants.poster_bg_pallet
backdropColor = posterBackgrounds[rnd(posterBackgrounds.count()) - 1]
end if
@ -64,7 +64,7 @@ sub itemContentChanged()
if isValid(m.unplayedCount) then m.unplayedCount.visible = false
itemData = m.top.itemContent
if itemData = invalid then return
localGlobal = m.global
userSettings = m.global.session.user.settings
itemData.Title = itemData.name ' Temporarily required while we move from "HomeItem" to "JFContentItem"
@ -81,9 +81,9 @@ sub itemContentChanged()
m.itemTextExtra.width = itemData.imageWidth
m.itemTextExtra.visible = true
m.itemTextExtra.text = ""
m.backdrop.width = itemData.imageWidth
if isValid(itemData.iconUrl)
m.itemIcon.uri = itemData.iconUrl
end if
@ -94,8 +94,8 @@ sub itemContentChanged()
m.playedIndicator.visible = false
if LCase(itemData.type) = "series"
if isValid(localGlobal) and isValid(localGlobal.session) and isValid(localGlobal.session.user) and isValid(localGlobal.session.user.settings)
unwatchedEpisodeCountSetting = localGlobal.session.user.settings["ui.tvshows.disableUnwatchedEpisodeCount"]
if isValid(userSettings)
unwatchedEpisodeCountSetting = userSettings["ui.tvshows.disableUnwatchedEpisodeCount"]
if isValid(unwatchedEpisodeCountSetting) and not unwatchedEpisodeCountSetting
if isValid(itemData.json.UserData) and isValid(itemData.json.UserData.UnplayedItemCount)
if itemData.json.UserData.UnplayedItemCount > 0
@ -166,16 +166,16 @@ sub itemContentChanged()
drawProgressBar(itemData)
end if
if localGlobal.session.user.settings["ui.general.episodeimagesnextup"] = "webclient"
tmpSetting = localGlobal.session.user.Configuration.useEpisodeImagesInNextUpAndResume
if userSettings["ui.general.episodeimagesnextup"] = "webclient"
tmpSetting = m.global.session.user.Configuration.useEpisodeImagesInNextUpAndResume
if isValid(tmpSetting) and tmpSetting
m.itemPoster.uri = itemData.thumbnailURL
else
m.itemPoster.uri = itemData.widePosterURL
end if
else if localGlobal.session.user.settings["ui.general.episodeimagesnextup"] = "show"
else if userSettings["ui.general.episodeimagesnextup"] = "show"
m.itemPoster.uri = itemData.widePosterURL
else if localGlobal.session.user.settings["ui.general.episodeimagesnextup"] = "episode"
else if userSettings["ui.general.episodeimagesnextup"] = "episode"
m.itemPoster.uri = itemData.thumbnailURL
end if

View File

@ -78,10 +78,11 @@ sub processUserSections()
m.processedRowCount = 0
sessionUser = m.global.session.user
userSettings = sessionUser.settings
' calculate expected row count by processing homesections
for i = 0 to 6
userSection = sessionUser.settings["homesection" + i.toStr()]
userSection = userSettings["homesection" + i.toStr()]
sectionName = userSection ?? "none"
sectionName = LCase(sectionName)
@ -101,7 +102,7 @@ sub processUserSections()
' Add home sections in order based on user settings
loadedSections = 0
for i = 0 to 6
userSection = sessionUser.settings["homesection" + i.toStr()]
userSection = userSettings["homesection" + i.toStr()]
sectionName = userSection ?? "none"
sectionName = LCase(sectionName)
@ -151,10 +152,10 @@ function getOriginalSectionIndex(sectionName as string) as integer
sectionIndex = 0
indexLatestMediaSection = 0
sessionUser = m.global.session.user
userSettings = m.global.session.user.settings
for i = 0 to 6
userSection = sessionUser.settings["homesection" + i.toStr()]
userSection = userSettings["homesection" + i.toStr()]
settingSectionName = userSection ?? "none"
settingSectionName = LCase(settingSectionName)

View File

@ -62,6 +62,7 @@ sub loadItems()
' Load Next Up
else if m.top.itemsToLoad = "nextUp"
userSettings = m.global.session.user.settings
url = "Shows/NextUp"
params = {}
@ -70,12 +71,12 @@ sub loadItems()
params["SortOrder"] = "Descending"
params["ImageTypeLimit"] = 1
params["UserId"] = m.global.session.user.id
params["EnableRewatching"] = m.global.session.user.settings["ui.details.enablerewatchingnextup"]
params["EnableRewatching"] = userSettings["ui.details.enablerewatchingnextup"]
params["DisableFirstEpisode"] = false
params["limit"] = 24
params["EnableTotalRecordCount"] = false
maxDaysInNextUp = m.global.session.user.settings["ui.details.maxdaysnextup"].ToInt()
maxDaysInNextUp = userSettings["ui.details.maxdaysnextup"].ToInt()
if isValid(maxDaysInNextUp)
if maxDaysInNextUp > 0
dateToday = CreateObject("roDateTime")

View File

@ -60,9 +60,9 @@ sub onSelectAudioPressed()
audioData.data.push(audioStreamItem)
end for
m.global.sceneManager.callFunc("radioDialog", tr("Select Audio"), audioData)
m.global.sceneManager.observeField("returnData", "onSelectionMade")
sceneManager = m.global.sceneManager
sceneManager.callFunc("radioDialog", tr("Select Audio"), audioData)
sceneManager.observeField("returnData", "onSelectionMade")
end sub
' User requested subtitle selection popup
@ -112,23 +112,25 @@ sub onSelectSubtitlePressed()
"Type": "subtitleselection"
})
m.global.sceneManager.callFunc("radioDialog", tr("Select Subtitles"), subtitleData)
m.global.sceneManager.observeField("returnData", "onSelectionMade")
sceneManager = m.global.sceneManager
sceneManager.callFunc("radioDialog", tr("Select Subtitles"), subtitleData)
sceneManager.observeField("returnData", "onSelectionMade")
end sub
' User has selected something from the radioDialog popup
sub onSelectionMade()
m.global.sceneManager.unobserveField("returnData")
sceneManager = m.global.sceneManager
sceneManager.unobserveField("returnData")
if not isValid(m.global.sceneManager.returnData) then return
if not isValid(m.global.sceneManager.returnData.type) then return
if not isValid(sceneManager.returnData) then return
if not isValid(sceneManager.returnData.type) then return
if LCase(m.global.sceneManager.returnData.type) = "subtitleselection"
if LCase(sceneManager.returnData.type) = "subtitleselection"
processSubtitleSelection()
return
end if
if LCase(m.global.sceneManager.returnData.type) = "audioselection"
if LCase(sceneManager.returnData.type) = "audioselection"
processAudioSelection()
return
end if
@ -218,21 +220,24 @@ end sub
' Playback state change event handlers
sub onStateChange()
if LCase(m.view.state) = "finished"
sceneManager = m.global.sceneManager
queueManager = m.global.queueManager
' Close any open dialogs
if m.global.sceneManager.callFunc("isDialogOpen")
m.global.sceneManager.callFunc("dismissDialog")
if sceneManager.callFunc("isDialogOpen")
sceneManager.callFunc("dismissDialog")
end if
' If there is something next in the queue, play it
if m.global.queueManager.callFunc("getPosition") &lt; m.global.queueManager.callFunc("getCount") - 1
m.global.sceneManager.callFunc("clearPreviousScene")
m.global.queueManager.callFunc("moveForward")
m.global.queueManager.callFunc("playQueue")
if queueManager.callFunc("getPosition") &lt; queueManager.callFunc("getCount") - 1
sceneManager.callFunc("clearPreviousScene")
queueManager.callFunc("moveForward")
queueManager.callFunc("playQueue")
return
end if
' Playback completed, return user to previous screen
m.global.sceneManager.callFunc("popScene")
sceneManager.callFunc("popScene")
m.global.audioPlayer.loopMode = ""
end if
end sub

View File

@ -99,6 +99,7 @@ sub itemContentChanged()
' Updates video metadata
item = m.top.itemContent
if isValid(item) and isValid(item.json)
userSettings = m.global.session.user.settings
itemData = item.json
m.top.id = itemData.id
m.top.findNode("moviePoster").uri = m.top.itemContent.posterURL
@ -122,7 +123,7 @@ sub itemContentChanged()
m.infoGroup.removeChild(m.top.findNode("officialRating"))
end if
if m.global.session.user.settings["ui.movies.showRatings"]
if userSettings["ui.movies.showRatings"]
if isValid(itemData.communityRating)
setFieldText("communityRating", int(itemData.communityRating * 10) / 10)
else
@ -147,7 +148,7 @@ sub itemContentChanged()
if type(itemData.RunTimeTicks) = "LongInteger"
setFieldText("runtime", stri(getRuntime()) + " mins")
if m.global.session.user.settings["ui.design.hideclock"] &lt;> true
if userSettings["ui.design.hideclock"] &lt;> true
setFieldText("ends-at", tr("Ends at %1").Replace("%1", getEndTime()))
end if
end if
@ -175,7 +176,7 @@ sub itemContentChanged()
m.top.findNode("details").removeChild(m.top.findNode("director"))
end if
if m.global.session.user.settings["ui.details.hidetagline"] = false
if userSettings["ui.details.hidetagline"] = false
if itemData.taglines.count() > 0
setFieldText("tagline", itemData.taglines[0])
end if

View File

@ -11,9 +11,14 @@ sub init()
m.lastRecordedPositionTimestamp = 0
m.scrubTimestamp = -1
m.playlistTypeCount = m.global.queueManager.callFunc("getQueueUniqueTypes").count()
m.queueManager = m.global.queueManager
m.playlistTypeCount = m.queueManager.callFunc("getQueueUniqueTypes").count()
m.audioPlayer = m.global.audioPlayer
m.audioPlayer.observeField("state", "audioStateChanged")
m.audioPlayer.observeField("position", "audioPositionChanged")
m.audioPlayer.observeField("bufferingStatus", "bufferPositionChanged")
setupAudioNode()
setupAnimationTasks()
setupButtons()
setupInfoNodes()
@ -93,13 +98,6 @@ sub setupDataTasks()
m.LoadScreenSaverTimeoutTask = CreateObject("roSGNode", "LoadScreenSaverTimeoutTask")
end sub
' Creates audio node used to play song(s)
sub setupAudioNode()
m.global.audioPlayer.observeField("state", "audioStateChanged")
m.global.audioPlayer.observeField("position", "audioPositionChanged")
m.global.audioPlayer.observeField("bufferingStatus", "bufferPositionChanged")
end sub
' Setup playback buttons, default to Play button selected
sub setupButtons()
m.buttons = m.top.findNode("buttons")
@ -151,10 +149,10 @@ end sub
sub bufferPositionChanged()
if m.inScrubMode then return
if not isValid(m.global.audioPlayer.bufferingStatus)
if not isValid(m.audioPlayer.bufferingStatus)
bufferPositionBarWidth = m.seekBar.width
else
bufferPositionBarWidth = m.seekBar.width * m.global.audioPlayer.bufferingStatus.percentage
bufferPositionBarWidth = m.seekBar.width * m.audioPlayer.bufferingStatus.percentage
end if
' Ensure position bar is never wider than the seek bar
@ -170,16 +168,16 @@ end sub
sub audioPositionChanged()
stopLoadingSpinner()
if m.global.audioPlayer.position = 0
if m.audioPlayer.position = 0
m.playPosition.width = 0
end if
if not isValid(m.global.audioPlayer.position)
if not isValid(m.audioPlayer.position)
playPositionBarWidth = 0
else if not isValid(m.songDuration)
playPositionBarWidth = 0
else
songPercentComplete = m.global.audioPlayer.position / m.songDuration
songPercentComplete = m.audioPlayer.position / m.songDuration
playPositionBarWidth = m.seekBar.width * songPercentComplete
end if
@ -191,7 +189,7 @@ sub audioPositionChanged()
if not m.inScrubMode
moveSeekbarThumb(playPositionBarWidth)
' Change the seek position timestamp
m.seekTimestamp.text = secondsToHuman(m.global.audioPlayer.position, false)
m.seekTimestamp.text = secondsToHuman(m.audioPlayer.position, false)
end if
' Use animation to make the display smooth
@ -199,9 +197,9 @@ sub audioPositionChanged()
m.playPositionAnimation.control = "start"
' Update displayed position timestamp
if isValid(m.global.audioPlayer.position)
m.lastRecordedPositionTimestamp = m.global.audioPlayer.position
m.positionTimestamp.text = secondsToHuman(m.global.audioPlayer.position, false)
if isValid(m.audioPlayer.position)
m.lastRecordedPositionTimestamp = m.audioPlayer.position
m.positionTimestamp.text = secondsToHuman(m.audioPlayer.position, false)
else
m.lastRecordedPositionTimestamp = 0
m.positionTimestamp.text = "0:00"
@ -249,25 +247,24 @@ sub endScreenSaver()
end sub
sub audioStateChanged()
' Song Finished, attempt to move to next song
if m.global.audioPlayer.state = "finished"
if m.audioPlayer.state = "finished"
' User has enabled single song loop, play current song again
if m.global.audioPlayer.loopMode = "one"
if m.audioPlayer.loopMode = "one"
m.scrubTimestamp = -1
playAction()
exitScrubMode()
return
end if
if m.global.queueManager.callFunc("getPosition") &lt; m.global.queueManager.callFunc("getCount") - 1
if m.queueManager.callFunc("getPosition") &lt; m.queueManager.callFunc("getCount") - 1
m.top.state = "finished"
else
' We are at the end of the song queue
' User has enabled loop for entire song queue, move back to first song
if m.global.audioPlayer.loopMode = "all"
m.global.queueManager.callFunc("setPosition", -1)
if m.audioPlayer.loopMode = "all"
m.queueManager.callFunc("setPosition", -1)
LoadNextSong()
return
end if
@ -279,18 +276,19 @@ sub audioStateChanged()
end sub
function playAction() as boolean
if m.global.audioPlayer.state = "playing"
m.global.audioPlayer.control = "pause"
if m.audioPlayer.state = "playing"
m.audioPlayer.control = "pause"
' Allow screen to go to real screensaver
WriteAsciiFile("tmp:/scene.temp", "nowplaying-paused")
MoveFile("tmp:/scene.temp", "tmp:/scene")
else if m.global.audioPlayer.state = "paused"
m.global.audioPlayer.control = "resume"
else if m.audioPlayer.state = "paused"
m.audioPlayer.control = "resume"
' Write screen tracker for screensaver
WriteAsciiFile("tmp:/scene.temp", "nowplaying")
MoveFile("tmp:/scene.temp", "tmp:/scene")
else if m.global.audioPlayer.state = "finished"
m.global.audioPlayer.control = "play"
else if m.audioPlayer.state = "finished"
m.audioPlayer.control = "play"
' Write screen tracker for screensaver
WriteAsciiFile("tmp:/scene.temp", "nowplaying")
MoveFile("tmp:/scene.temp", "tmp:/scene")
@ -300,20 +298,19 @@ function playAction() as boolean
end function
function previousClicked() as boolean
currentQueuePosition = m.global.queueManager.callFunc("getPosition")
currentQueuePosition = m.queueManager.callFunc("getPosition")
if currentQueuePosition = 0 then return false
if m.playlistTypeCount > 1
previousItem = m.global.queueManager.callFunc("getItemByIndex", currentQueuePosition - 1)
previousItemType = m.global.queueManager.callFunc("getItemType", previousItem)
previousItem = m.queueManager.callFunc("getItemByIndex", currentQueuePosition - 1)
previousItemType = m.queueManager.callFunc("getItemType", previousItem)
if previousItemType &lt;> "audio"
m.global.audioPlayer.control = "stop"
m.audioPlayer.control = "stop"
m.global.sceneManager.callFunc("clearPreviousScene")
m.global.queueManager.callFunc("moveBack")
m.global.queueManager.callFunc("playQueue")
m.queueManager.callFunc("moveBack")
m.queueManager.callFunc("playQueue")
return true
end if
end if
@ -323,34 +320,33 @@ function previousClicked() as boolean
m.lastRecordedPositionTimestamp = 0
m.positionTimestamp.text = "0:00"
if m.global.audioPlayer.state = "playing"
m.global.audioPlayer.control = "stop"
if m.audioPlayer.state = "playing"
m.audioPlayer.control = "stop"
end if
' Reset loop mode due to manual user interaction
if m.global.audioPlayer.loopMode = "one"
if m.audioPlayer.loopMode = "one"
resetLoopModeToDefault()
end if
m.global.queueManager.callFunc("moveBack")
m.queueManager.callFunc("moveBack")
pageContentChanged()
return true
end function
sub resetLoopModeToDefault()
m.global.audioPlayer.loopMode = ""
m.audioPlayer.loopMode = ""
setLoopButtonImage()
end sub
function loopClicked() as boolean
if m.global.audioPlayer.loopMode = ""
m.global.audioPlayer.loopMode = "all"
else if m.global.audioPlayer.loopMode = "all"
m.global.audioPlayer.loopMode = "one"
if m.audioPlayer.loopMode = ""
m.audioPlayer.loopMode = "all"
else if m.audioPlayer.loopMode = "all"
m.audioPlayer.loopMode = "one"
else
m.global.audioPlayer.loopMode = ""
m.audioPlayer.loopMode = ""
end if
setLoopButtonImage()
@ -359,10 +355,10 @@ function loopClicked() as boolean
end function
sub setLoopButtonImage()
if m.global.audioPlayer.loopMode = "all"
if m.audioPlayer.loopMode = "all"
m.loopIndicator.opacity = "1"
m.loopIndicator.uri = m.loopIndicator.uri.Replace("-off", "-on")
else if m.global.audioPlayer.loopMode = "one"
else if m.audioPlayer.loopMode = "one"
m.loopIndicator.uri = m.loopIndicator.uri.Replace("-on", "1-on")
else
m.loopIndicator.uri = m.loopIndicator.uri.Replace("1-on", "-off")
@ -370,19 +366,20 @@ sub setLoopButtonImage()
end sub
function nextClicked() as boolean
if m.playlistTypeCount > 1
currentQueuePosition = m.global.queueManager.callFunc("getPosition")
if currentQueuePosition &lt; m.global.queueManager.callFunc("getCount") - 1
nextItem = m.global.queueManager.callFunc("getItemByIndex", currentQueuePosition + 1)
nextItemType = m.global.queueManager.callFunc("getItemType", nextItem)
if m.playlistTypeCount > 1
currentQueuePosition = m.queueManager.callFunc("getPosition")
if currentQueuePosition &lt; m.queueManager.callFunc("getCount") - 1
nextItem = m.queueManager.callFunc("getItemByIndex", currentQueuePosition + 1)
nextItemType = m.queueManager.callFunc("getItemType", nextItem)
if nextItemType &lt;> "audio"
m.global.audioPlayer.control = "stop"
m.audioPlayer.control = "stop"
m.global.sceneManager.callFunc("clearPreviousScene")
m.global.queueManager.callFunc("moveForward")
m.global.queueManager.callFunc("playQueue")
m.queueManager.callFunc("moveForward")
m.queueManager.callFunc("playQueue")
return true
end if
end if
@ -394,11 +391,11 @@ function nextClicked() as boolean
m.positionTimestamp.text = "0:00"
' Reset loop mode due to manual user interaction
if m.global.audioPlayer.loopMode = "one"
if m.audioPlayer.loopMode = "one"
resetLoopModeToDefault()
end if
if m.global.queueManager.callFunc("getPosition") &lt; m.global.queueManager.callFunc("getCount") - 1
if m.queueManager.callFunc("getPosition") &lt; m.queueManager.callFunc("getCount") - 1
LoadNextSong()
end if
@ -406,14 +403,14 @@ function nextClicked() as boolean
end function
sub toggleShuffleEnabled()
m.global.queueManager.callFunc("toggleShuffle")
m.queueManager.callFunc("toggleShuffle")
end sub
function findCurrentSongIndex(songList) as integer
if not isValidAndNotEmpty(songList) then return 0
for i = 0 to songList.count() - 1
if songList[i].id = m.global.queueManager.callFunc("getCurrentItem").id
if songList[i].id = m.queueManager.callFunc("getCurrentItem").id
return i
end if
end for
@ -422,15 +419,14 @@ function findCurrentSongIndex(songList) as integer
end function
function shuffleClicked() as boolean
currentSongIndex = findCurrentSongIndex(m.global.queueManager.callFunc("getUnshuffledQueue"))
currentSongIndex = findCurrentSongIndex(m.queueManager.callFunc("getUnshuffledQueue"))
toggleShuffleEnabled()
if not m.global.queueManager.callFunc("getIsShuffled")
if not m.queueManager.callFunc("getIsShuffled")
m.shuffleIndicator.opacity = ".4"
m.shuffleIndicator.uri = m.shuffleIndicator.uri.Replace("-on", "-off")
m.global.queueManager.callFunc("setPosition", currentSongIndex)
m.queueManager.callFunc("setPosition", currentSongIndex)
setTrackNumberDisplay()
return true
end if
@ -443,26 +439,26 @@ function shuffleClicked() as boolean
end function
sub setShuffleIconState()
if m.global.queueManager.callFunc("getIsShuffled")
if m.queueManager.callFunc("getIsShuffled")
m.shuffleIndicator.opacity = "1"
m.shuffleIndicator.uri = m.shuffleIndicator.uri.Replace("-off", "-on")
end if
end sub
sub setTrackNumberDisplay()
setFieldTextValue("numberofsongs", "Track " + stri(m.global.queueManager.callFunc("getPosition") + 1) + "/" + stri(m.global.queueManager.callFunc("getCount")))
setFieldTextValue("numberofsongs", "Track " + stri(m.queueManager.callFunc("getPosition") + 1) + "/" + stri(m.queueManager.callFunc("getCount")))
end sub
sub LoadNextSong()
if m.global.audioPlayer.state = "playing"
m.global.audioPlayer.control = "stop"
if m.audioPlayer.state = "playing"
m.audioPlayer.control = "stop"
end if
exitScrubMode()
' Reset playPosition bar without animation
m.playPosition.width = 0
m.global.queueManager.callFunc("moveForward")
m.queueManager.callFunc("moveForward")
pageContentChanged()
end sub
@ -471,7 +467,7 @@ sub pageContentChanged()
m.LoadAudioStreamTask.control = "STOP"
currentItem = m.global.queueManager.callFunc("getCurrentItem")
currentItem = m.queueManager.callFunc("getCurrentItem")
m.LoadAudioStreamTask.itemId = currentItem.id
m.LoadAudioStreamTask.observeField("content", "onAudioStreamLoaded")
@ -480,7 +476,7 @@ end sub
' If we have more and 1 song to play, fade in the next and previous controls
sub loadButtons()
if m.global.queueManager.callFunc("getCount") > 1
if m.queueManager.callFunc("getCount") > 1
m.shuffleIndicator.opacity = ".4"
m.loopIndicator.opacity = ".4"
m.displayButtonsAnimation.control = "start"
@ -497,7 +493,7 @@ sub onAudioStreamLoaded()
m.bufferPosition.width = 0
useMetaTask = false
currentItem = m.global.queueManager.callFunc("getCurrentItem")
currentItem = m.queueManager.callFunc("getCurrentItem")
if not isValid(currentItem.RunTimeTicks)
useMetaTask = true
@ -533,9 +529,9 @@ sub onAudioStreamLoaded()
m.totalLengthTimestamp.text = ticksToHuman(currentItem.RunTimeTicks)
end if
m.global.audioPlayer.content = data
m.global.audioPlayer.control = "none"
m.global.audioPlayer.control = "play"
m.audioPlayer.content = data
m.audioPlayer.control = "none"
m.audioPlayer.control = "play"
end if
end sub
@ -741,7 +737,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
if m.inScrubMode
startLoadingSpinner()
m.inScrubMode = false
m.global.audioPlayer.seek = m.scrubTimestamp
m.audioPlayer.seek = m.scrubTimestamp
return true
end if
@ -775,15 +771,15 @@ function onKeyEvent(key as string, press as boolean) as boolean
end if
if key = "back"
m.global.audioPlayer.control = "stop"
m.global.audioPlayer.loopMode = ""
m.audioPlayer.control = "stop"
m.audioPlayer.loopMode = ""
else if key = "rewind"
return previousClicked()
else if key = "fastforward"
return nextClicked()
else if key = "left"
if m.buttons.hasFocus()
if m.global.queueManager.callFunc("getCount") = 1 then return false
if m.queueManager.callFunc("getCount") = 1 then return false
if m.top.selectedButtonIndex > 0
m.previouslySelectedButtonIndex = m.top.selectedButtonIndex
@ -793,7 +789,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
end if
else if key = "right"
if m.buttons.hasFocus()
if m.global.queueManager.callFunc("getCount") = 1 then return false
if m.queueManager.callFunc("getCount") = 1 then return false
m.previouslySelectedButtonIndex = m.top.selectedButtonIndex
if m.top.selectedButtonIndex &lt; m.buttonCount - 1 then m.top.selectedButtonIndex = m.top.selectedButtonIndex + 1

View File

@ -12,8 +12,9 @@ sub init()
m.textBackground = m.top.findNode("background")
m.statusTimer = m.top.findNode("statusTimer")
m.statusTimer.observeField("fire", "statusUpdate")
m.slideshow = m.global.session.user.settings["photos.slideshow"]
m.random = m.global.session.user.settings["photos.random"]
userSettings = m.global.session.user.settings
m.slideshow = userSettings["photos.slideshow"]
m.random = userSettings["photos.random"]
m.showStatusAnimation = m.top.findNode("showStatusAnimation")
m.hideStatusAnimation = m.top.findNode("hideStatusAnimation")

View File

@ -93,26 +93,28 @@ sub settingFocused()
m.integerSetting.visible = false
m.radioSetting.visible = false
userSettings = m.global.session.user.settings
if selectedSetting.type = invalid
return
else if selectedSetting.type = "bool"
m.boolSetting.visible = true
if m.global.session.user.settings[selectedSetting.settingName] = true
if userSettings[selectedSetting.settingName] = true
m.boolSetting.checkedItem = 1
else
m.boolSetting.checkedItem = 0
end if
else if selectedSetting.type = "integer"
integerValue = m.global.session.user.settings[selectedSetting.settingName].ToStr()
integerValue = userSettings[selectedSetting.settingName].ToStr()
if isValid(integerValue)
m.integerSetting.text = integerValue
end if
m.integerSetting.visible = true
else if LCase(selectedSetting.type) = "radio"
selectedValue = m.global.session.user.settings[selectedSetting.settingName]
selectedValue = userSettings[selectedSetting.settingName]
radioContent = CreateObject("roSGNode", "ContentNode")
@ -175,7 +177,6 @@ sub boolSettingChanged()
set_setting(selectedSetting.settingName, "true")
' setting specific triggers
if selectedSetting.settingName = "global.rememberme"
print "m.global.session.user.id=", m.global.session.user.id
set_setting("active_user", m.global.session.user.id)
end if
else

View File

@ -23,13 +23,16 @@ end sub
sub itemContentChanged()
item = m.top.itemContent
itemData = item.json
userSettings = m.global.session.user.settings
' Set default video source if user hasn't selected one yet
if item.selectedVideoStreamId = "" and isValid(itemData.MediaSources)
item.selectedVideoStreamId = itemData.MediaSources[0].id
end if
if isValid(itemData.indexNumber)
if isValid(itemData.parentIndexNumber) and itemData.parentIndexNumber = 0
indexNumber = `${tr("Special")} - `
else if isValid(itemData.indexNumber)
indexNumber = `${itemData.indexNumber}. `
if isValid(itemData.indexNumberEnd)
indexNumber = `${itemData.indexNumber}-${itemData.indexNumberEnd}. `
@ -48,7 +51,7 @@ sub itemContentChanged()
imageUrl = item.posterURL
if m.global.session.user.settings["ui.tvshows.blurunwatched"] = true
if userSettings["ui.tvshows.blurunwatched"] = true
if itemData.lookup("Type") = "Episode"
if not itemData.userdata.played
imageUrl = imageUrl + "&amp;blur=15"
@ -66,12 +69,12 @@ sub itemContentChanged()
m.top.findNode("runtime").text = stri(runTime).trim() + " mins"
end if
if m.global.session.user.settings["ui.design.hideclock"] &lt;> true
if userSettings["ui.design.hideclock"] &lt;> true
m.top.findNode("endtime").text = tr("Ends at %1").Replace("%1", getEndTime())
end if
end if
if m.global.session.user.settings["ui.tvshows.disableCommunityRating"] = false
if userSettings["ui.tvshows.disableCommunityRating"] = false
if isValid(itemData.communityRating)
m.top.findNode("star").visible = true
m.top.findNode("communityRating").text = str(int(itemData.communityRating * 10) / 10)

View File

@ -183,9 +183,11 @@ end function
sub onShuffleEpisodeDataLoaded()
m.getShuffleEpisodesTask.unobserveField("data")
if isValid(m.getShuffleEpisodesTask.data)
m.global.queueManager.callFunc("set", m.getShuffleEpisodesTask.data.items)
m.global.queueManager.callFunc("playQueue")
queueManager = m.global.queueManager
queueManager.callFunc("set", m.getShuffleEpisodesTask.data.items)
queueManager.callFunc("playQueue")
end if
end sub

View File

@ -37,7 +37,6 @@ sub init()
m.optionControls.buttonFocused = m.optionControls.getChildCount() - 1
m.videoControls.getChild(m.defaultButtonIndex).focus = true
m.deviceInfo = CreateObject("roDeviceInfo")
end sub
' onProgressPercentageChanged: Handler for changes to m.top.progressPercentage param
@ -213,7 +212,8 @@ sub inactiveCheck()
return
end if
if m.deviceInfo.timeSinceLastKeypress() >= m.top.inactiveTimeout
deviceInfo = CreateObject("roDeviceInfo")
if deviceInfo.timeSinceLastKeypress() >= m.top.inactiveTimeout
m.top.action = "hide"
end if
end sub

View File

@ -9,6 +9,7 @@ sub init()
m.log = log.Logger("VideoPlayerView")
' Hide the overhang on init to prevent showing 2 clocks
m.top.getScene().findNode("overhang").visible = false
userSettings = m.global.session.user.settings
m.currentItem = m.global.queueManager.callFunc("getCurrentItem")
m.top.id = m.currentItem.id
@ -48,7 +49,7 @@ sub init()
m.top.transcodeReasons = []
m.bufferCheckTimer.duration = 30
if m.global.session.user.settings["ui.design.hideclock"] = true
if userSettings["ui.design.hideclock"] = true
clockNode = findNodeBySubtype(m.top, "clock")
if clockNode[0] &lt;> invalid then clockNode[0].parent.removeChild(clockNode[0].node)
end if
@ -57,7 +58,7 @@ sub init()
m.nextEpisodeButton = m.top.findNode("nextEpisode")
m.nextEpisodeButton.text = tr("Next Episode")
m.nextEpisodeButton.setFocus(false)
m.nextupbuttonseconds = m.global.session.user.settings["playback.nextupbuttonseconds"].ToInt()
m.nextupbuttonseconds = userSettings["playback.nextupbuttonseconds"].ToInt()
m.showNextEpisodeButtonAnimation = m.top.findNode("showNextEpisodeButton")
m.hideNextEpisodeButtonAnimation = m.top.findNode("hideNextEpisodeButton")
@ -102,26 +103,30 @@ end sub
' @param {string} action - skip action to take
sub handleItemSkipAction(action as string)
if action = "itemnext"
queueManager = m.global.queueManager
' If there is something next in the queue, play it
if m.global.queueManager.callFunc("getPosition") &lt; m.global.queueManager.callFunc("getCount") - 1
if queueManager.callFunc("getPosition") &lt; queueManager.callFunc("getCount") - 1
m.top.control = "stop"
session.video.Delete()
m.global.sceneManager.callFunc("clearPreviousScene")
m.global.queueManager.callFunc("moveForward")
m.global.queueManager.callFunc("playQueue")
queueManager.callFunc("moveForward")
queueManager.callFunc("playQueue")
end if
return
end if
if action = "itemback"
queueManager = m.global.queueManager
' If there is something previous in the queue, play it
if m.global.queueManager.callFunc("getPosition") > 0
if queueManager.callFunc("getPosition") > 0
m.top.control = "stop"
session.video.Delete()
m.global.sceneManager.callFunc("clearPreviousScene")
m.global.queueManager.callFunc("moveBack")
m.global.queueManager.callFunc("playQueue")
queueManager.callFunc("moveBack")
queueManager.callFunc("playQueue")
end if
return
@ -525,9 +530,9 @@ sub showNextEpisodeButton()
if m.top.content.contenttype &lt;> 4 then return ' only display when content is type "Episode"
if m.nextupbuttonseconds = 0 then return ' is the button disabled?
if m.nextEpisodeButton.opacity &lt;> 0 then return
userSession = m.global.session.user
if userSession.settings["playback.playnextepisode"] = "disabled" then return
if userSession.settings["playback.playnextepisode"] = "webclient" and not userSession.Configuration.EnableNextEpisodeAutoPlay then return
userSettings = m.global.session.user.settings
if userSettings["playback.playnextepisode"] = "disabled" then return
if userSettings["playback.playnextepisode"] = "webclient" and not m.global.session.user.Configuration.EnableNextEpisodeAutoPlay then return
m.nextEpisodeButton.visible = true
m.showNextEpisodeButtonAnimation.control = "start"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -74,15 +74,18 @@
end if
end if
' has the current user ran this version before?
usersLastRunVersion = m.global.session.user.settings.lastRunVersion
if not isValid(usersLastRunVersion) or not versionChecker(m.global.session.user.settings.lastRunVersion, m.global.app.version)
set_user_setting("LastRunVersion", m.global.app.version)
' show what's new popup
if m.global.session.user.settings["load.allowwhatsnew"]
dialog = createObject("roSGNode", "WhatsNewDialog")
m.scene.dialog = dialog
m.scene.dialog.observeField("buttonSelected", m.port)
' only show whats new popup and update lastRunVersion on prod
if not m.global.app.isDev
' has the current user ran this version before?
usersLastRunVersion = m.global.session.user.settings.lastRunVersion
if not isValid(usersLastRunVersion) or not versionChecker(usersLastRunVersion, m.global.app.version)
set_user_setting("LastRunVersion", m.global.app.version)
' show what's new popup
if m.global.session.user.settings["load.allowwhatsnew"]
dialog = createObject("roSGNode", "WhatsNewDialog")
m.scene.dialog = dialog
m.scene.dialog.observeField("buttonSelected", m.port)
end if
end if
end if

View File

@ -39,8 +39,10 @@ function ItemPostPlaybackInfo(id as string, mediaSourceId = "" as string, audioT
params.EnableDirectPlay = false
end if
if audioTrackIndex > -1
selectedAudioStream = m.global.session.video.json.MediaStreams[audioTrackIndex]
myGLobal = m.global
if audioTrackIndex > -1 and myGLobal.session.video.json.MediaStreams &lt;> invalid
selectedAudioStream = myGLobal.session.video.json.MediaStreams[audioTrackIndex]
if selectedAudioStream &lt;> invalid
params.AudioStreamIndex = audioTrackIndex
@ -64,7 +66,6 @@ function ItemPostPlaybackInfo(id as string, mediaSourceId = "" as string, audioT
end for
end if
end if
end if
end if

File diff suppressed because one or more lines are too long

View File

@ -99,11 +99,8 @@ sub SaveDeviceToGlobal()
print "ERROR parsing deviceInfo.GetVideoMode()"
end if
videoWidth = heightToWidth[videoHeight]
if videoHeight = "2160" and extraData = "b10"
bitDepth = 10
else if videoHeight = "4320"
bitDepth = 12
end if
if extraData &lt;> invalid and extraData = "b10" then bitDepth = 10
if videoHeight = "4320" then bitDepth = 12
m.global.addFields({
device: {

View File

@ -1314,6 +1314,14 @@
<translation>Use Show Image</translation>
<extracomment>User Setting - Setting option title</extracomment>
</message>
<message>
<source>Play Next Episode Automatically</source>
<translation>Play Next Episode Automatically</translation>
</message>
<message>
<source>When finished playing a single episode, play the next one automatically.</source>
<translation>When finished playing a single episode, play the next one automatically.</translation>
</message>
</context>
<context>
<name></name>

View File

@ -1366,5 +1366,10 @@
<translation>Both</translation>
<extracomment>User Setting - Setting option title</extracomment>
</message>
<message>
<source>Special</source>
<translation>Special</translation>
<extracomment>Special episode of a TV Show</extracomment>
</message>
</context>
</TS>

View File

@ -2,8 +2,8 @@
title=Jellyfin
major_version=2
minor_version=1
build_version=7
minor_version=2
build_version=0
### Main Menu Icons / Channel Poster Artwork

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "jellyfin-roku",
"version": "2.1.7",
"version": "2.2.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "jellyfin-roku",
"version": "2.1.7",
"version": "2.2.0",
"hasInstallScript": true,
"license": "GPL-2.0",
"dependencies": {

View File

@ -1,7 +1,7 @@
{
"name": "jellyfin-roku",
"type": "module",
"version": "2.1.7",
"version": "2.2.0",
"description": "Roku app for Jellyfin media server",
"dependencies": {
"@rokucommunity/bslib": "0.1.1",

View File

@ -72,15 +72,18 @@ sub Main (args as dynamic) as void
end if
end if
' has the current user ran this version before?
usersLastRunVersion = m.global.session.user.settings.lastRunVersion
if not isValid(usersLastRunVersion) or not versionChecker(m.global.session.user.settings.lastRunVersion, m.global.app.version)
set_user_setting("LastRunVersion", m.global.app.version)
' show what's new popup
if m.global.session.user.settings["load.allowwhatsnew"]
dialog = createObject("roSGNode", "WhatsNewDialog")
m.scene.dialog = dialog
m.scene.dialog.observeField("buttonSelected", m.port)
' only show whats new popup and update lastRunVersion on prod
if not m.global.app.isDev
' has the current user ran this version before?
usersLastRunVersion = m.global.session.user.settings.lastRunVersion
if not isValid(usersLastRunVersion) or not versionChecker(usersLastRunVersion, m.global.app.version)
set_user_setting("LastRunVersion", m.global.app.version)
' show what's new popup
if m.global.session.user.settings["load.allowwhatsnew"]
dialog = createObject("roSGNode", "WhatsNewDialog")
m.scene.dialog = dialog
m.scene.dialog.observeField("buttonSelected", m.port)
end if
end if
end if

View File

@ -37,8 +37,10 @@ function ItemPostPlaybackInfo(id as string, mediaSourceId = "" as string, audioT
params.EnableDirectPlay = false
end if
if audioTrackIndex > -1
selectedAudioStream = m.global.session.video.json.MediaStreams[audioTrackIndex]
myGLobal = m.global
if audioTrackIndex > -1 and myGLobal.session.video.json.MediaStreams <> invalid
selectedAudioStream = myGLobal.session.video.json.MediaStreams[audioTrackIndex]
if selectedAudioStream <> invalid
params.AudioStreamIndex = audioTrackIndex
@ -62,7 +64,6 @@ function ItemPostPlaybackInfo(id as string, mediaSourceId = "" as string, audioT
end for
end if
end if
end if
end if

View File

@ -414,7 +414,9 @@ function getContainerProfiles() as object
end function
function getCodecProfiles() as object
globalUserSettings = m.global.session.user.settings
myGlobal = m.global
globalUserSettings = myGlobal.session.user.settings
codecProfiles = []
profileSupport = {
"h264": {},
@ -555,26 +557,45 @@ function getCodecProfiles() as object
hevcVideoRangeTypes = "SDR"
vp9VideoRangeTypes = "SDR"
av1VideoRangeTypes = "SDR"
canPlayDovi = false
dp = di.GetDisplayProperties()
if dp.Hdr10
hevcVideoRangeTypes = hevcVideoRangeTypes + "|HDR10"
vp9VideoRangeTypes = vp9VideoRangeTypes + "|HDR10"
av1VideoRangeTypes = av1VideoRangeTypes + "|HDR10"
end if
if dp.Hdr10Plus
av1VideoRangeTypes = av1VideoRangeTypes + "|HDR10+"
end if
if dp.HLG
hevcVideoRangeTypes = hevcVideoRangeTypes + "|HLG"
vp9VideoRangeTypes = vp9VideoRangeTypes + "|HLG"
av1VideoRangeTypes = av1VideoRangeTypes + "|HLG"
end if
if dp.DolbyVision
h264VideoRangeTypes = h264VideoRangeTypes + "|DOVI"
hevcVideoRangeTypes = hevcVideoRangeTypes + "|DOVI"
'vp9VideoRangeTypes = vp9VideoRangeTypes + ",DOVI" no evidence that vp9 can hold DOVI
av1VideoRangeTypes = av1VideoRangeTypes + "|DOVI"
if canPlay4k()
dp = di.GetDisplayProperties()
if dp.DolbyVision
canPlayDovi = true
h264VideoRangeTypes = h264VideoRangeTypes + "|DOVI|DOVIWithSDR"
hevcVideoRangeTypes = hevcVideoRangeTypes + "|DOVI|DOVIWithSDR"
av1VideoRangeTypes = av1VideoRangeTypes + "|DOVI|DOVIWithSDR"
end if
if dp.Hdr10
hevcVideoRangeTypes = hevcVideoRangeTypes + "|HDR10"
vp9VideoRangeTypes = vp9VideoRangeTypes + "|HDR10"
av1VideoRangeTypes = av1VideoRangeTypes + "|HDR10"
if canPlayDovi
hevcVideoRangeTypes = hevcVideoRangeTypes + "|DOVIWithHDR10"
av1VideoRangeTypes = av1VideoRangeTypes + "|DOVIWithHDR10"
end if
end if
if dp.Hdr10Plus
av1VideoRangeTypes = av1VideoRangeTypes + "|HDR10+"
end if
if dp.HLG
hevcVideoRangeTypes = hevcVideoRangeTypes + "|HLG"
vp9VideoRangeTypes = vp9VideoRangeTypes + "|HLG"
av1VideoRangeTypes = av1VideoRangeTypes + "|HLG"
if canPlayDovi
hevcVideoRangeTypes = hevcVideoRangeTypes + "|DOVIWithHLG"
vp9VideoRangeTypes = vp9VideoRangeTypes + "|DOVIWithHLG"
av1VideoRangeTypes = av1VideoRangeTypes + "|DOVIWithHLG"
end if
end if
end if
' H264
@ -605,12 +626,6 @@ function getCodecProfiles() as object
"Value": "true",
"IsRequired": false
},
{
"Condition": "LessThanEqual",
"Property": "VideoBitDepth",
"Value": "8",
"IsRequired": false
},
{
"Condition": "EqualsAny",
"Property": "VideoProfile",
@ -1094,3 +1109,28 @@ function setPreferredCodec(codecString as string, preferredCodec as string) as s
return newCodecString
end if
end function
' does the connected display support playing 4k video?
function canPlay4k() as boolean
deviceInfo = CreateObject("roDeviceInfo")
hdmiStatus = CreateObject("roHdmiStatus")
' Check if the output mode is 2160p or higher
maxVideoHeight = m.global.device.videoHeight
if maxVideoHeight = invalid then return false
if maxVideoHeight.ToInt() < 2160
return false
end if
' Check if HDCP 2.2 is enabled, skip check for TVs
if deviceInfo.GetModelType() = "STB" and hdmiStatus.IsHdcpActive("2.2") <> true
return false
end if
' Check if the Roku player can decode 4K 60fps HEVC streams
if deviceInfo.CanDecodeVideo({ Codec: "hevc", Profile: "main", Level: "5.1" }).result <> true
return false
end if
return true
end function

View File

@ -97,11 +97,8 @@ sub SaveDeviceToGlobal()
print "ERROR parsing deviceInfo.GetVideoMode()"
end if
videoWidth = heightToWidth[videoHeight]
if videoHeight = "2160" and extraData = "b10"
bitDepth = 10
else if videoHeight = "4320"
bitDepth = 12
end if
if extraData <> invalid and extraData = "b10" then bitDepth = 10
if videoHeight = "4320" then bitDepth = 12
m.global.addFields({
device: {