jf-roku/components/video/OSD.bs

342 lines
11 KiB
Plaintext
Raw Normal View History

2023-11-11 00:42:33 +00:00
import "pkg:/source/utils/misc.bs"
const LOGO_RIGHT_PADDING = 30
const OPTIONCONTROLS_TOP_PADDING = 50
sub init()
m.videoControls = m.top.findNode("videoControls")
m.optionControls = m.top.findNode("optionControls")
m.inactivityTimer = m.top.findNode("inactivityTimer")
m.videoInfo = m.top.findNode("videoInfo")
m.itemTitle = m.top.findNode("itemTitle")
m.videoPlayPause = m.top.findNode("videoPlayPause")
2023-11-11 22:30:06 +00:00
m.videoPositionTime = m.top.findNode("videoPositionTime")
m.videoRemainingTime = m.top.findNode("videoRemainingTime")
m.progressBar = m.top.findNode("progressBar")
m.progressBarBackground = m.top.findNode("progressBarBackground")
m.top.observeField("visible", "onVisibleChanged")
m.top.observeField("hasFocus", "onFocusChanged")
2023-11-11 22:30:06 +00:00
m.top.observeField("progressPercentage", "onProgressPercentageChanged")
m.top.observeField("playbackState", "onPlaybackStateChanged")
m.top.observeField("itemTitleText", "onItemTitleTextChanged")
m.top.observeField("seasonNumber", "onSeasonNumberChanged")
m.top.observeField("episodeNumber", "onEpisodeNumberChanged")
m.top.observeField("episodeNumberEnd", "onEpisodeNumberEndChanged")
m.top.observeField("logoImage", "onLogoImageChanged")
2023-12-02 17:45:42 +00:00
m.defaultButtonIndex = 2
m.focusedButtonIndex = 2
m.optionControlsMoved = false
m.videoControls.buttonFocused = m.defaultButtonIndex
m.optionControls.buttonFocused = m.optionControls.getChildCount() - 1
m.videoControls.getChild(m.defaultButtonIndex).focus = true
m.deviceInfo = CreateObject("roDeviceInfo")
end sub
2023-11-11 22:30:06 +00:00
' onProgressPercentageChanged: Handler for changes to m.top.progressPercentage param
'
sub onProgressPercentageChanged()
m.videoPositionTime.text = secondsToHuman(m.top.positionTime, true)
m.videoRemainingTime.text = secondsToHuman(m.top.remainingPositionTime, true)
2023-11-11 22:30:06 +00:00
m.progressBar.width = m.progressBarBackground.width * m.top.progressPercentage
end sub
' onPlaybackStateChanged: Handler for changes to m.top.playbackState param
'
sub onPlaybackStateChanged()
if LCase(m.top.playbackState) = "playing"
m.videoPlayPause.icon = "pkg:/images/icons/pause.png"
return
end if
m.videoPlayPause.icon = "pkg:/images/icons/play.png"
end sub
' onItemTitleTextChanged: Handler for changes to m.top.itemTitleText param.
'
sub onItemTitleTextChanged()
m.itemTitle.text = m.top.itemTitleText
end sub
' onSeasonNumberChanged: Handler for changes to m.top.seasonNumber param.
'
sub onSeasonNumberChanged()
m.top.unobserveField("seasonNumber")
itemSeason = m.top.findNode("itemSeason")
itemSeason.font.size = 32
itemSeason.text = `S${m.top.seasonNumber}`
' Move the option controls down to give room for season number
if not m.optionControlsMoved
moveOptionControls(0, OPTIONCONTROLS_TOP_PADDING)
m.optionControlsMoved = true
end if
end sub
' onEpisodeNumberChanged: Handler for changes to m.top.episodeNumber param.
'
sub onEpisodeNumberChanged()
m.top.unobserveField("episodeNumber")
itemEpisode = m.top.findNode("itemEpisode")
itemEpisode.font.size = 32
itemEpisode.text = `E${m.top.episodeNumber}`
' Move the option controls down to give room for episode number
if not m.optionControlsMoved
moveOptionControls(0, OPTIONCONTROLS_TOP_PADDING)
m.optionControlsMoved = true
end if
end sub
' onEpisodeNumberEndChanged: Handler for changes to m.top.episodeNumberEnd param.
'
sub onEpisodeNumberEndChanged()
m.top.unobserveField("episodeNumberEnd")
itemEpisodeEnd = m.top.findNode("itemEpisodeEnd")
itemEpisodeEnd.font.size = 32
itemEpisodeEnd.text = `-${m.top.episodeNumberEnd}`
' Move the option controls down to give room for episode number
if not m.optionControlsMoved
moveOptionControls(0, OPTIONCONTROLS_TOP_PADDING)
m.optionControlsMoved = true
end if
end sub
' moveOptionControls: Moves option controls node based on passed pixel values
'
' @param {integer} horizontalPixels - Number of horizontal pixels to move option controls
' @param {integer} verticalPixels - Number of vertical pixels to move option controls
sub moveOptionControls(horizontalPixels as integer, verticalPixels as integer)
m.optionControls.translation = `[${m.optionControls.translation[0] + horizontalPixels}, ${m.optionControls.translation[1] + verticalPixels}]`
end sub
' onLogoLoadStatusChanged: Handler for changes to logo image's status.
'
' @param {dynamic} event - field change event
sub onLogoLoadStatusChanged(event)
if LCase(event.GetData()) = "ready"
logoImage = event.getRoSGNode()
logoImage.unobserveField("loadStatus")
' Move video info to the right based on the logo width
m.videoInfo.translation = `[${m.videoInfo.translation[0] + logoImage.bitmapWidth + LOGO_RIGHT_PADDING}, ${m.videoInfo.translation[1]}]`
m.itemTitle.maxWidth = m.itemTitle.maxWidth - (logoImage.bitmapWidth + LOGO_RIGHT_PADDING)
' Move the option controls down based on the logo height
if not m.optionControlsMoved
moveOptionControls(0, OPTIONCONTROLS_TOP_PADDING)
m.optionControlsMoved = true
end if
end if
end sub
' onLogoImageChanged: Handler for changes to m.top.logoImage param.
'
sub onLogoImageChanged()
if isValidAndNotEmpty(m.top.logoImage)
logoImage = createObject("roSGNode", "Poster")
logoImage.Id = "logoImage"
logoImage.observeField("loadStatus", "onLogoLoadStatusChanged")
logoImage.uri = m.top.logoImage
logoImage.translation = [103, 61]
m.top.appendChild(logoImage)
end if
end sub
' resetFocusToDefaultButton: Reset focus back to the default button
'
sub resetFocusToDefaultButton()
' Remove focus from previously selected button
for each child in m.videoControls.getChildren(-1, 0)
if isValid(child.focus)
child.focus = false
end if
end for
for each child in m.optionControls.getChildren(-1, 0)
if isValid(child.focus)
child.focus = false
end if
end for
m.optionControls.setFocus(false)
' Set focus back to the default button
m.videoControls.setFocus(true)
m.focusedButtonIndex = m.defaultButtonIndex
m.videoControls.getChild(m.defaultButtonIndex).focus = true
2023-12-02 17:45:42 +00:00
m.videoControls.buttonFocused = m.defaultButtonIndex
m.optionControls.buttonFocused = m.optionControls.getChildCount() - 1
end sub
2023-11-16 14:26:20 +00:00
' onVisibleChanged: Handler for changes to the visibility of this menu.
'
sub onVisibleChanged()
if m.top.visible
resetFocusToDefaultButton()
m.inactivityTimer.observeField("fire", "inactiveCheck")
m.inactivityTimer.control = "start"
return
end if
m.inactivityTimer.unobserveField("fire")
m.inactivityTimer.control = "stop"
end sub
2023-11-16 14:26:20 +00:00
' onFocusChanged: Handler for changes to the focus of this menu.
'
sub onFocusChanged()
if m.top.hasfocus
focusedButton = m.optionControls.getChild(m.focusedButtonIndex)
if focusedButton.focus
m.optionControls.setFocus(true)
return
end if
m.videoControls.setFocus(true)
end if
end sub
2023-11-16 14:26:20 +00:00
' inactiveCheck: Checks if the time since last keypress is greater than or equal to the allowed inactive time of the menu.
'
sub inactiveCheck()
' If user is currently seeing a dialog box, ignore inactive check
if m.global.sceneManager.callFunc("isDialogOpen")
return
end if
if m.deviceInfo.timeSinceLastKeypress() >= m.top.inactiveTimeout
m.top.action = "hide"
end if
end sub
2023-11-16 14:26:20 +00:00
' onButtonSelected: Handler for selection of buttons from the menu.
'
sub onButtonSelected()
if m.optionControls.isInFocusChain()
buttonGroup = m.optionControls
else
buttonGroup = m.videoControls
end if
selectedButton = buttonGroup.getChild(m.focusedButtonIndex)
if LCase(selectedButton.id) = "chapterlist"
m.top.showChapterList = not m.top.showChapterList
end if
m.top.action = selectedButton.id
end sub
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
if key = "OK"
onButtonSelected()
return true
end if
if key = "play"
m.top.action = "videoplaypause"
return true
end if
if key = "right"
if m.optionControls.isInFocusChain()
buttonGroup = m.optionControls
else
buttonGroup = m.videoControls
end if
if m.focusedButtonIndex + 1 >= buttonGroup.getChildCount()
return true
end if
focusedButton = buttonGroup.getChild(m.focusedButtonIndex)
focusedButton.focus = false
' Skip spacer elements until next button is found
for i = m.focusedButtonIndex + 1 to buttonGroup.getChildCount()
m.focusedButtonIndex = i
focusedButton = buttonGroup.getChild(m.focusedButtonIndex)
if isValid(focusedButton.focus)
buttonGroup.buttonFocused = m.focusedButtonIndex
focusedButton.focus = true
exit for
end if
end for
return true
end if
if key = "left"
if m.focusedButtonIndex = 0
return true
end if
if m.optionControls.isInFocusChain()
buttonGroup = m.optionControls
else
buttonGroup = m.videoControls
end if
focusedButton = buttonGroup.getChild(m.focusedButtonIndex)
focusedButton.focus = false
' Skip spacer elements until next button is found
for i = m.focusedButtonIndex - 1 to 0 step -1
m.focusedButtonIndex = i
focusedButton = buttonGroup.getChild(m.focusedButtonIndex)
if isValid(focusedButton.focus)
buttonGroup.buttonFocused = m.focusedButtonIndex
focusedButton.focus = true
exit for
end if
end for
return true
end if
if key = "up"
if m.videoControls.isInFocusChain()
focusedButton = m.videoControls.getChild(m.focusedButtonIndex)
focusedButton.focus = false
m.videoControls.setFocus(false)
m.focusedButtonIndex = m.optionControls.buttonFocused
focusedButton = m.optionControls.getChild(m.focusedButtonIndex)
focusedButton.focus = true
m.optionControls.setFocus(true)
end if
return true
end if
if key = "down"
if m.optionControls.isInFocusChain()
focusedButton = m.optionControls.getChild(m.focusedButtonIndex)
focusedButton.focus = false
m.optionControls.setFocus(false)
m.focusedButtonIndex = m.videoControls.buttonFocused
focusedButton = m.videoControls.getChild(m.focusedButtonIndex)
focusedButton.focus = true
m.videoControls.setFocus(true)
end if
return true
end if
' All other keys hide the menu
m.top.action = "hide"
return true
end function