3b1207dc2f
Update intro code comments Save msgNode to variable in main Selecting subtitle moves cursor to OK button Subtitle list moves with cursor instead of scrollbar
669 lines
32 KiB
Plaintext
669 lines
32 KiB
Plaintext
sub Main (args as dynamic) as void
|
|
' The main function that runs when the application is launched.
|
|
m.screen = CreateObject("roSGScreen")
|
|
' Set global constants
|
|
setConstants()
|
|
' Write screen tracker for screensaver
|
|
WriteAsciiFile("tmp:/scene.temp", "")
|
|
MoveFile("tmp:/scene.temp", "tmp:/scene")
|
|
|
|
m.port = CreateObject("roMessagePort")
|
|
m.screen.setMessagePort(m.port)
|
|
' Set any initial Global Variables
|
|
m.global = m.screen.getGlobalNode()
|
|
SaveAppToGlobal()
|
|
SaveDeviceToGlobal()
|
|
|
|
m.scene = m.screen.CreateScene("JFScene")
|
|
m.screen.show() ' vscode_rale_tracker_entry
|
|
|
|
playstateTask = CreateObject("roSGNode", "PlaystateTask")
|
|
playstateTask.id = "playstateTask"
|
|
|
|
sceneManager = CreateObject("roSGNode", "SceneManager")
|
|
sceneManager.observeField("dataReturned", m.port)
|
|
|
|
m.global.addFields({ app_loaded: false, playstateTask: playstateTask, sceneManager: sceneManager })
|
|
m.global.addFields({ queueManager: CreateObject("roSGNode", "QueueManager") })
|
|
m.global.addFields({ audioPlayer: CreateObject("roSGNode", "AudioPlayer") })
|
|
|
|
app_start:
|
|
' First thing to do is validate the ability to use the API
|
|
if not LoginFlow() then return
|
|
' remove previous scenes from the stack
|
|
sceneManager.callFunc("clearScenes")
|
|
' save user config
|
|
m.global.addFields({ userConfig: m.user.configuration })
|
|
' load home page
|
|
sceneManager.currentUser = m.user.Name
|
|
group = CreateHomeGroup()
|
|
group.callFunc("loadLibraries")
|
|
sceneManager.callFunc("pushScene", group)
|
|
|
|
m.scene.observeField("exit", m.port)
|
|
|
|
' Downloads and stores a fallback font to tmp:/
|
|
configEncoding = api_API().system.getconfigurationbyname("encoding")
|
|
|
|
if isValid(configEncoding) and isValid(configEncoding.EnableFallbackFont)
|
|
if configEncoding.EnableFallbackFont
|
|
re = CreateObject("roRegex", "Name.:.(.*?).,.Size", "s")
|
|
filename = APIRequest("FallbackFont/Fonts").GetToString()
|
|
if isValid(filename)
|
|
filename = re.match(filename)
|
|
if isValid(filename) and filename.count() > 0
|
|
filename = filename[1]
|
|
APIRequest("FallbackFont/Fonts/" + filename).gettofile("tmp:/font")
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
|
|
' Only show the Whats New popup the first time a user runs a new client version.
|
|
if m.global.app.version <> get_setting("LastRunVersion")
|
|
' Ensure the user hasn't disabled Whats New popups
|
|
if get_user_setting("load.allowwhatsnew") = "true"
|
|
set_setting("LastRunVersion", m.global.app.version)
|
|
dialog = createObject("roSGNode", "WhatsNewDialog")
|
|
m.scene.dialog = dialog
|
|
m.scene.dialog.observeField("buttonSelected", m.port)
|
|
end if
|
|
end if
|
|
|
|
' Handle input messages
|
|
input = CreateObject("roInput")
|
|
input.SetMessagePort(m.port)
|
|
|
|
device = CreateObject("roDeviceInfo")
|
|
device.setMessagePort(m.port)
|
|
device.EnableScreensaverExitedEvent(true)
|
|
device.EnableAppFocusEvent(false)
|
|
device.EnableAudioGuideChangedEvent(true)
|
|
|
|
' Check if we were sent content to play with the startup command (Deep Link)
|
|
if isValidAndNotEmpty(args.mediaType) and isValidAndNotEmpty(args.contentId)
|
|
video = CreateVideoPlayerGroup(args.contentId)
|
|
|
|
if isValid(video)
|
|
sceneManager.callFunc("pushScene", video)
|
|
else
|
|
dialog = createObject("roSGNode", "Dialog")
|
|
dialog.id = "OKDialog"
|
|
dialog.title = tr("Not found")
|
|
dialog.message = tr("The requested content does not exist on the server")
|
|
dialog.buttons = [tr("OK")]
|
|
m.scene.dialog = dialog
|
|
m.scene.dialog.observeField("buttonSelected", m.port)
|
|
end if
|
|
end if
|
|
|
|
' This is the core logic loop. Mostly for transitioning between scenes
|
|
' This now only references m. fields so could be placed anywhere, in theory
|
|
' "group" is always "whats on the screen"
|
|
' m.scene's children is the "previous view" stack
|
|
while true
|
|
msg = wait(0, m.port)
|
|
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed()
|
|
print "CLOSING SCREEN"
|
|
return
|
|
else if isNodeEvent(msg, "exit")
|
|
return
|
|
else if isNodeEvent(msg, "closeSidePanel")
|
|
group = sceneManager.callFunc("getActiveScene")
|
|
if group.lastFocus <> invalid
|
|
group.lastFocus.setFocus(true)
|
|
else
|
|
group.setFocus(true)
|
|
end if
|
|
else if isNodeEvent(msg, "quickPlayNode")
|
|
group = sceneManager.callFunc("getActiveScene")
|
|
reportingNode = msg.getRoSGNode()
|
|
itemNode = reportingNode.quickPlayNode
|
|
if isValid(itemNode) and isValid(itemNode.id) and itemNode.id <> ""
|
|
if itemNode.type = "Episode" or itemNode.type = "Movie" or itemNode.type = "Video"
|
|
audio_stream_idx = 0
|
|
if isValid(itemNode.selectedAudioStreamIndex)
|
|
audio_stream_idx = itemNode.selectedAudioStreamIndex
|
|
end if
|
|
|
|
itemNode.selectedAudioStreamIndex = audio_stream_idx
|
|
|
|
playbackPosition = 0
|
|
|
|
' Display playback options dialog
|
|
if isValid(itemNode.json) and isValid(itemNode.json.userdata) and isValid(itemNode.json.userdata.PlaybackPositionTicks)
|
|
playbackPosition = itemNode.json.userdata.PlaybackPositionTicks
|
|
end if
|
|
|
|
if playbackPosition > 0
|
|
m.global.queueManager.callFunc("hold", itemNode)
|
|
playbackOptionDialog(playbackPosition, itemNode.json)
|
|
else
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("push", itemNode)
|
|
m.global.queueManager.callFunc("playQueue")
|
|
end if
|
|
|
|
' Prevent quick play node from double firing
|
|
reportingNode.quickPlayNode = invalid
|
|
|
|
if LCase(group.subtype()) = "tvepisodes"
|
|
if isValid(group.lastFocus)
|
|
group.lastFocus.setFocus(true)
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
else if isNodeEvent(msg, "selectedItem")
|
|
' If you select a library from ANYWHERE, follow this flow
|
|
selectedItem = msg.getData()
|
|
if isValid(selectedItem)
|
|
selectedItemType = selectedItem.type
|
|
|
|
|
|
if selectedItemType = "CollectionFolder"
|
|
if selectedItem.collectionType = "movies"
|
|
group = CreateMovieLibraryView(selectedItem)
|
|
else if selectedItem.collectionType = "music"
|
|
group = CreateMusicLibraryView(selectedItem)
|
|
else
|
|
group = CreateItemGrid(selectedItem)
|
|
end if
|
|
sceneManager.callFunc("pushScene", group)
|
|
else if selectedItemType = "Folder" and selectedItem.json.type = "Genre"
|
|
' User clicked on a genre folder
|
|
if selectedItem.json.MovieCount > 0
|
|
group = CreateMovieLibraryView(selectedItem)
|
|
else
|
|
group = CreateItemGrid(selectedItem)
|
|
end if
|
|
sceneManager.callFunc("pushScene", group)
|
|
else if selectedItemType = "Folder" and selectedItem.json.type = "MusicGenre"
|
|
group = CreateMusicLibraryView(selectedItem)
|
|
sceneManager.callFunc("pushScene", group)
|
|
else if selectedItemType = "UserView" or selectedItemType = "Folder" or selectedItemType = "Channel" or selectedItemType = "Boxset"
|
|
group = CreateItemGrid(selectedItem)
|
|
sceneManager.callFunc("pushScene", group)
|
|
else if selectedItemType = "Episode"
|
|
' User has selected a TV episode they want us to play
|
|
audio_stream_idx = 0
|
|
if isValid(selectedItem.selectedAudioStreamIndex)
|
|
audio_stream_idx = selectedItem.selectedAudioStreamIndex
|
|
end if
|
|
|
|
selectedItem.selectedAudioStreamIndex = audio_stream_idx
|
|
|
|
' If we are playing a playlist, always start at the beginning
|
|
if m.global.queueManager.callFunc("getCount") > 1
|
|
selectedItem.startingPoint = 0
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("push", selectedItem)
|
|
m.global.queueManager.callFunc("playQueue")
|
|
else
|
|
' Display playback options dialog
|
|
if selectedItem.json.userdata.PlaybackPositionTicks > 0
|
|
m.global.queueManager.callFunc("hold", selectedItem)
|
|
playbackOptionDialog(selectedItem.json.userdata.PlaybackPositionTicks, selectedItem.json)
|
|
else
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("push", selectedItem)
|
|
m.global.queueManager.callFunc("playQueue")
|
|
end if
|
|
end if
|
|
|
|
|
|
else if selectedItemType = "Series"
|
|
group = CreateSeriesDetailsGroup(selectedItem.json.id)
|
|
else if selectedItemType = "Season"
|
|
group = CreateSeasonDetailsGroupByID(selectedItem.json.SeriesId, selectedItem.id)
|
|
else if selectedItemType = "Movie"
|
|
' open movie detail page
|
|
group = CreateMovieDetailsGroup(selectedItem)
|
|
else if selectedItemType = "Person"
|
|
CreatePersonView(selectedItem)
|
|
else if selectedItemType = "TvChannel" or selectedItemType = "Video" or selectedItemType = "Program"
|
|
' User selected a Live TV channel / program
|
|
|
|
' Show Channel Loading spinner
|
|
dialog = createObject("roSGNode", "ProgressDialog")
|
|
dialog.title = tr("Loading Channel Data")
|
|
m.scene.dialog = dialog
|
|
|
|
' User selected a program. Play the channel the program is on
|
|
if LCase(selectedItemType) = "program"
|
|
selectedItem.id = selectedItem.json.ChannelId
|
|
end if
|
|
|
|
' Display playback options dialog
|
|
if selectedItem.json.userdata.PlaybackPositionTicks > 0
|
|
dialog.close = true
|
|
m.global.queueManager.callFunc("hold", selectedItem)
|
|
playbackOptionDialog(selectedItem.json.userdata.PlaybackPositionTicks, selectedItem.json)
|
|
else
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("push", selectedItem)
|
|
m.global.queueManager.callFunc("playQueue")
|
|
dialog.close = true
|
|
end if
|
|
|
|
else if selectedItemType = "Photo"
|
|
' Nothing to do here, handled in ItemGrid
|
|
else if selectedItemType = "MusicArtist"
|
|
group = CreateArtistView(selectedItem.json)
|
|
if not isValid(group)
|
|
message_dialog(tr("Unable to find any albums or songs belonging to this artist"))
|
|
end if
|
|
else if selectedItemType = "MusicAlbum"
|
|
group = CreateAlbumView(selectedItem.json)
|
|
else if selectedItemType = "Playlist"
|
|
group = CreatePlaylistView(selectedItem.json)
|
|
else if selectedItemType = "Audio"
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("resetShuffle")
|
|
m.global.queueManager.callFunc("push", selectedItem.json)
|
|
m.global.queueManager.callFunc("playQueue")
|
|
else
|
|
' TODO - switch on more node types
|
|
message_dialog("This type is not yet supported: " + selectedItemType + ".")
|
|
end if
|
|
end if
|
|
else if isNodeEvent(msg, "movieSelected")
|
|
' If you select a movie from ANYWHERE, follow this flow
|
|
node = getMsgPicker(msg, "picker")
|
|
group = CreateMovieDetailsGroup(node)
|
|
else if isNodeEvent(msg, "seriesSelected")
|
|
' If you select a TV Series from ANYWHERE, follow this flow
|
|
node = getMsgPicker(msg, "picker")
|
|
group = CreateSeriesDetailsGroup(node.id)
|
|
else if isNodeEvent(msg, "seasonSelected")
|
|
' If you select a TV Season from ANYWHERE, follow this flow
|
|
ptr = msg.getData()
|
|
' ptr is for [row, col] of selected item... but we only have 1 row
|
|
series = msg.getRoSGNode()
|
|
if isValid(ptr) and ptr.count() >= 2 and isValid(ptr[1]) and isValid(series) and isValid(series.seasonData) and isValid(series.seasonData.items)
|
|
node = series.seasonData.items[ptr[1]]
|
|
group = CreateSeasonDetailsGroup(series.itemContent, node)
|
|
end if
|
|
else if isNodeEvent(msg, "musicAlbumSelected")
|
|
' If you select a Music Album from ANYWHERE, follow this flow
|
|
ptr = msg.getData()
|
|
albums = msg.getRoSGNode()
|
|
node = albums.musicArtistAlbumData.items[ptr]
|
|
group = CreateAlbumView(node)
|
|
else if isNodeEvent(msg, "appearsOnSelected")
|
|
' If you select a Music Album from ANYWHERE, follow this flow
|
|
ptr = msg.getData()
|
|
albums = msg.getRoSGNode()
|
|
node = albums.musicArtistAppearsOnData.items[ptr]
|
|
group = CreateAlbumView(node)
|
|
else if isNodeEvent(msg, "playSong")
|
|
' User has selected audio they want us to play
|
|
selectedIndex = msg.getData()
|
|
screenContent = msg.getRoSGNode()
|
|
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("resetShuffle")
|
|
m.global.queueManager.callFunc("push", screenContent.albumData.items[selectedIndex])
|
|
m.global.queueManager.callFunc("playQueue")
|
|
else if isNodeEvent(msg, "playItem")
|
|
' User has selected audio they want us to play
|
|
selectedIndex = msg.getData()
|
|
screenContent = msg.getRoSGNode()
|
|
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("resetShuffle")
|
|
m.global.queueManager.callFunc("push", screenContent.albumData.items[selectedIndex])
|
|
m.global.queueManager.callFunc("playQueue")
|
|
else if isNodeEvent(msg, "playAllSelected")
|
|
' User has selected playlist of of audio they want us to play
|
|
screenContent = msg.getRoSGNode()
|
|
m.spinner = screenContent.findNode("spinner")
|
|
m.spinner.visible = true
|
|
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("resetShuffle")
|
|
m.global.queueManager.callFunc("set", screenContent.albumData.items)
|
|
m.global.queueManager.callFunc("playQueue")
|
|
else if isNodeEvent(msg, "playArtistSelected")
|
|
' User has selected playlist of of audio they want us to play
|
|
screenContent = msg.getRoSGNode()
|
|
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("resetShuffle")
|
|
m.global.queueManager.callFunc("set", CreateArtistMix(screenContent.pageContent.id).Items)
|
|
m.global.queueManager.callFunc("playQueue")
|
|
|
|
else if isNodeEvent(msg, "instantMixSelected")
|
|
' User has selected instant mix
|
|
' User has selected playlist of of audio they want us to play
|
|
screenContent = msg.getRoSGNode()
|
|
m.spinner = screenContent.findNode("spinner")
|
|
if isValid(m.spinner)
|
|
m.spinner.visible = true
|
|
end if
|
|
|
|
viewHandled = false
|
|
|
|
' Create instant mix based on selected album
|
|
if isValid(screenContent.albumData)
|
|
if isValid(screenContent.albumData.items)
|
|
if screenContent.albumData.items.count() > 0
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("resetShuffle")
|
|
m.global.queueManager.callFunc("set", CreateInstantMix(screenContent.albumData.items[0].id).Items)
|
|
m.global.queueManager.callFunc("playQueue")
|
|
|
|
viewHandled = true
|
|
end if
|
|
end if
|
|
end if
|
|
|
|
if not viewHandled
|
|
' Create instant mix based on selected artist
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("resetShuffle")
|
|
m.global.queueManager.callFunc("set", CreateInstantMix(screenContent.pageContent.id).Items)
|
|
m.global.queueManager.callFunc("playQueue")
|
|
end if
|
|
|
|
else if isNodeEvent(msg, "search_value")
|
|
query = msg.getRoSGNode().search_value
|
|
group.findNode("SearchBox").visible = false
|
|
options = group.findNode("SearchSelect")
|
|
options.visible = true
|
|
options.setFocus(true)
|
|
|
|
dialog = createObject("roSGNode", "ProgressDialog")
|
|
dialog.title = tr("Loading Search Data")
|
|
m.scene.dialog = dialog
|
|
results = SearchMedia(query)
|
|
dialog.close = true
|
|
options.itemData = results
|
|
options.query = query
|
|
else if isNodeEvent(msg, "itemSelected")
|
|
' Search item selected
|
|
node = getMsgPicker(msg)
|
|
' TODO - swap this based on target.mediatype
|
|
' types: [ Series (Show), Episode, Movie, Audio, Person, Studio, MusicArtist ]
|
|
if node.type = "Series"
|
|
group = CreateSeriesDetailsGroup(node.id)
|
|
else if node.type = "Movie"
|
|
group = CreateMovieDetailsGroup(node)
|
|
else if node.type = "MusicArtist"
|
|
group = CreateArtistView(node.json)
|
|
else if node.type = "MusicAlbum"
|
|
group = CreateAlbumView(node.json)
|
|
else if node.type = "Audio"
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("resetShuffle")
|
|
m.global.queueManager.callFunc("push", node.json)
|
|
m.global.queueManager.callFunc("playQueue")
|
|
else if node.type = "Person"
|
|
group = CreatePersonView(node)
|
|
else if node.type = "TvChannel"
|
|
group = CreateVideoPlayerGroup(node.id)
|
|
sceneManager.callFunc("pushScene", group)
|
|
else if node.type = "Episode"
|
|
group = CreateVideoPlayerGroup(node.id)
|
|
sceneManager.callFunc("pushScene", group)
|
|
else if node.type = "Audio"
|
|
selectedIndex = msg.getData()
|
|
screenContent = msg.getRoSGNode()
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("resetShuffle")
|
|
m.global.queueManager.callFunc("push", screenContent.albumData.items[node.id])
|
|
m.global.queueManager.callFunc("playQueue")
|
|
else
|
|
' TODO - switch on more node types
|
|
message_dialog("This type is not yet supported: " + node.type + ".")
|
|
end if
|
|
else if isNodeEvent(msg, "buttonSelected")
|
|
' If a button is selected, we have some determining to do
|
|
btn = getButton(msg)
|
|
group = sceneManager.callFunc("getActiveScene")
|
|
if isValid(btn) and btn.id = "play-button"
|
|
' User chose Play button from movie detail view
|
|
|
|
' Check if a specific Audio Stream was selected
|
|
audio_stream_idx = 0
|
|
if isValid(group) and isValid(group.selectedAudioStreamIndex)
|
|
audio_stream_idx = group.selectedAudioStreamIndex
|
|
end if
|
|
|
|
group.itemContent.selectedAudioStreamIndex = audio_stream_idx
|
|
group.itemContent.id = group.selectedVideoStreamId
|
|
|
|
' Display playback options dialog
|
|
if group.itemContent.json.userdata.PlaybackPositionTicks > 0
|
|
m.global.queueManager.callFunc("hold", group.itemContent)
|
|
playbackOptionDialog(group.itemContent.json.userdata.PlaybackPositionTicks, group.itemContent.json)
|
|
else
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("push", group.itemContent)
|
|
m.global.queueManager.callFunc("playQueue")
|
|
end if
|
|
|
|
if isValid(group) and isValid(group.lastFocus) and isValid(group.lastFocus.id) and group.lastFocus.id = "main_group"
|
|
buttons = group.findNode("buttons")
|
|
if isValid(buttons)
|
|
group.lastFocus = group.findNode("buttons")
|
|
end if
|
|
end if
|
|
|
|
if isValid(group) and isValid(group.lastFocus)
|
|
group.lastFocus.setFocus(true)
|
|
end if
|
|
|
|
else if btn <> invalid and btn.id = "trailer-button"
|
|
' User chose to play a trailer from the movie detail view
|
|
dialog = createObject("roSGNode", "ProgressDialog")
|
|
dialog.title = tr("Loading trailer")
|
|
m.scene.dialog = dialog
|
|
|
|
trailerData = api_API().users.getlocaltrailers(get_setting("active_user"), group.id)
|
|
|
|
if isValid(trailerData) and isValid(trailerData[0]) and isValid(trailerData[0].id)
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("set", trailerData)
|
|
m.global.queueManager.callFunc("playQueue")
|
|
dialog.close = true
|
|
end if
|
|
|
|
if isValid(group) and isValid(group.lastFocus)
|
|
group.lastFocus.setFocus(true)
|
|
end if
|
|
else if btn <> invalid and btn.id = "watched-button"
|
|
movie = group.itemContent
|
|
if isValid(movie) and isValid(movie.watched) and isValid(movie.id)
|
|
if movie.watched
|
|
UnmarkItemWatched(movie.id)
|
|
else
|
|
MarkItemWatched(movie.id)
|
|
end if
|
|
movie.watched = not movie.watched
|
|
end if
|
|
else if btn <> invalid and btn.id = "favorite-button"
|
|
movie = group.itemContent
|
|
if movie.favorite
|
|
UnmarkItemFavorite(movie.id)
|
|
else
|
|
MarkItemFavorite(movie.id)
|
|
end if
|
|
movie.favorite = not movie.favorite
|
|
else
|
|
' If there are no other button matches, check if this is a simple "OK" Dialog & Close if so
|
|
dialog = msg.getRoSGNode()
|
|
if dialog.id = "OKDialog"
|
|
dialog.unobserveField("buttonSelected")
|
|
dialog.close = true
|
|
end if
|
|
end if
|
|
else if isNodeEvent(msg, "optionSelected")
|
|
button = msg.getRoSGNode()
|
|
group = sceneManager.callFunc("getActiveScene")
|
|
if button.id = "goto_search" and isValid(group)
|
|
' Exit out of the side panel
|
|
panel = group.findNode("options")
|
|
panel.visible = false
|
|
if isValid(group.lastFocus)
|
|
group.lastFocus.setFocus(true)
|
|
else
|
|
group.setFocus(true)
|
|
end if
|
|
group = CreateSearchPage()
|
|
sceneManager.callFunc("pushScene", group)
|
|
group.findNode("SearchBox").findNode("search_Key").setFocus(true)
|
|
group.findNode("SearchBox").findNode("search_Key").active = true
|
|
else if button.id = "change_server"
|
|
unset_setting("server")
|
|
unset_setting("port")
|
|
SignOut(false)
|
|
sceneManager.callFunc("clearScenes")
|
|
goto app_start
|
|
else if button.id = "sign_out"
|
|
SignOut()
|
|
sceneManager.callFunc("clearScenes")
|
|
goto app_start
|
|
else if button.id = "settings"
|
|
' Exit out of the side panel
|
|
panel = group.findNode("options")
|
|
panel.visible = false
|
|
if isValid(group) and isValid(group.lastFocus)
|
|
group.lastFocus.setFocus(true)
|
|
else
|
|
group.setFocus(true)
|
|
end if
|
|
sceneManager.callFunc("settings")
|
|
end if
|
|
else if isNodeEvent(msg, "selectSubtitlePressed")
|
|
node = m.scene.focusedChild
|
|
if node.focusedChild <> invalid and node.focusedChild.isSubType("JFVideo")
|
|
trackSelected = selectSubtitleTrack(node.Subtitles, node.SelectedSubtitle)
|
|
if trackSelected <> invalid and trackSelected <> -2
|
|
changeSubtitleDuringPlayback(trackSelected)
|
|
end if
|
|
end if
|
|
else if isNodeEvent(msg, "selectPlaybackInfoPressed")
|
|
node = m.scene.focusedChild
|
|
if node.focusedChild <> invalid and node.focusedChild.isSubType("JFVideo")
|
|
info = GetPlaybackInfo()
|
|
show_dialog(tr("Playback Information"), info)
|
|
end if
|
|
else if isNodeEvent(msg, "state")
|
|
node = msg.getRoSGNode()
|
|
if isValid(node) and isValid(node.state)
|
|
if node.selectedItemType = "TvChannel" and node.state = "finished"
|
|
video = CreateVideoPlayerGroup(node.id)
|
|
m.global.sceneManager.callFunc("pushScene", video)
|
|
m.global.sceneManager.callFunc("deleteSceneAtIndex", 2)
|
|
else if node.state = "finished"
|
|
node.control = "stop"
|
|
|
|
' If node allows retrying using Transcode Url, give that shot
|
|
if isValid(node.retryWithTranscoding) and node.retryWithTranscoding
|
|
retryVideo = CreateVideoPlayerGroup(node.Id, invalid, node.audioIndex, true, false)
|
|
m.global.sceneManager.callFunc("popScene")
|
|
if isValid(retryVideo)
|
|
m.global.sceneManager.callFunc("pushScene", retryVideo)
|
|
end if
|
|
else if not isValid(node.showID)
|
|
sceneManager.callFunc("popScene")
|
|
else
|
|
if video.errorMsg = ""
|
|
autoPlayNextEpisode(node.id, node.showID)
|
|
else
|
|
sceneManager.callFunc("popScene")
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
else if type(msg) = "roDeviceInfoEvent"
|
|
event = msg.GetInfo()
|
|
|
|
if event.exitedScreensaver = true
|
|
sceneManager.callFunc("resetTime")
|
|
group = sceneManager.callFunc("getActiveScene")
|
|
if isValid(group) and isValid(group.subtype())
|
|
' refresh the current view
|
|
if group.subtype() = "Home"
|
|
currentTime = CreateObject("roDateTime").AsSeconds()
|
|
group.timeLastRefresh = currentTime
|
|
group.callFunc("refresh")
|
|
end if
|
|
' todo: add other screens to be refreshed - movie detail, tv series, episode list etc.
|
|
end if
|
|
else if event.audioGuideEnabled <> invalid
|
|
tmpGlobalDevice = m.global.device
|
|
tmpGlobalDevice.AddReplace("isaudioguideenabled", event.audioGuideEnabled)
|
|
|
|
' update global device array
|
|
m.global.setFields({ device: tmpGlobalDevice })
|
|
else
|
|
print "Unhandled roDeviceInfoEvent:"
|
|
print msg.GetInfo()
|
|
end if
|
|
else if type(msg) = "roInputEvent"
|
|
if msg.IsInput()
|
|
info = msg.GetInfo()
|
|
if info.DoesExist("mediatype") and info.DoesExist("contentid")
|
|
video = CreateVideoPlayerGroup(info.contentId)
|
|
if video <> invalid
|
|
sceneManager.callFunc("pushScene", video)
|
|
else
|
|
dialog = createObject("roSGNode", "Dialog")
|
|
dialog.id = "OKDialog"
|
|
dialog.title = tr("Not found")
|
|
dialog.message = tr("The requested content does not exist on the server")
|
|
dialog.buttons = [tr("OK")]
|
|
m.scene.dialog = dialog
|
|
m.scene.dialog.observeField("buttonSelected", m.port)
|
|
end if
|
|
end if
|
|
end if
|
|
else if isNodeEvent(msg, "dataReturned")
|
|
popupNode = msg.getRoSGNode()
|
|
if isValid(popupNode) and isValid(popupNode.returnData)
|
|
selectedItem = m.global.queueManager.callFunc("getHold")
|
|
m.global.queueManager.callFunc("clearHold")
|
|
|
|
if isValid(selectedItem) and selectedItem.count() > 0 and isValid(selectedItem[0])
|
|
if popupNode.returnData.indexselected = 0
|
|
'Resume video from resume point
|
|
startingPoint = 0
|
|
|
|
if isValid(selectedItem[0].json) and isValid(selectedItem[0].json.UserData) and isValid(selectedItem[0].json.UserData.PlaybackPositionTicks)
|
|
if selectedItem[0].json.UserData.PlaybackPositionTicks > 0
|
|
startingPoint = selectedItem[0].json.UserData.PlaybackPositionTicks
|
|
end if
|
|
end if
|
|
|
|
selectedItem[0].startingPoint = startingPoint
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("push", selectedItem[0])
|
|
m.global.queueManager.callFunc("playQueue")
|
|
else if popupNode.returnData.indexselected = 1
|
|
'Start Over from beginning selected, set position to 0
|
|
selectedItem[0].startingPoint = 0
|
|
m.global.queueManager.callFunc("clear")
|
|
m.global.queueManager.callFunc("push", selectedItem[0])
|
|
m.global.queueManager.callFunc("playQueue")
|
|
else if popupNode.returnData.indexselected = 2
|
|
' User chose Go to series
|
|
CreateSeriesDetailsGroup(selectedItem[0].json.SeriesId)
|
|
else if popupNode.returnData.indexselected = 3
|
|
' User chose Go to season
|
|
CreateSeasonDetailsGroupByID(selectedItem[0].json.SeriesId, selectedItem[0].json.seasonID)
|
|
else if popupNode.returnData.indexselected = 4
|
|
' User chose Go to episode
|
|
CreateMovieDetailsGroup(selectedItem[0])
|
|
end if
|
|
end if
|
|
end if
|
|
else
|
|
print "Unhandled " type(msg)
|
|
print msg
|
|
end if
|
|
end while
|
|
|
|
end sub
|