2022-11-29 22:05:46 +00:00
|
|
|
' Play Audio
|
|
|
|
sub CreateAudioPlayerView()
|
2023-02-25 16:43:36 +00:00
|
|
|
m.view = CreateObject("roSGNode", "AudioPlayerView")
|
|
|
|
m.view.observeField("state", "onStateChange")
|
|
|
|
m.global.sceneManager.callFunc("pushScene", m.view)
|
|
|
|
end sub
|
|
|
|
|
|
|
|
' Play Video
|
|
|
|
sub CreateVideoPlayerView()
|
|
|
|
m.playbackData = {}
|
|
|
|
m.selectedSubtitle = {}
|
|
|
|
|
|
|
|
m.view = CreateObject("roSGNode", "VideoPlayerView")
|
|
|
|
m.view.observeField("state", "onStateChange")
|
|
|
|
m.view.observeField("selectPlaybackInfoPressed", "onSelectPlaybackInfoPressed")
|
|
|
|
m.view.observeField("selectSubtitlePressed", "onSelectSubtitlePressed")
|
|
|
|
|
2023-05-07 01:26:02 +00:00
|
|
|
mediaSourceId = m.global.queueManager.callFunc("getCurrentItem").mediaSourceId
|
|
|
|
|
|
|
|
if not isValid(mediaSourceId) or mediaSourceId = ""
|
|
|
|
mediaSourceId = m.global.queueManager.callFunc("getCurrentItem").id
|
|
|
|
end if
|
|
|
|
|
2023-02-25 16:43:36 +00:00
|
|
|
m.getPlaybackInfoTask = createObject("roSGNode", "GetPlaybackInfoTask")
|
2023-05-07 01:26:02 +00:00
|
|
|
m.getPlaybackInfoTask.videoID = mediaSourceId
|
2023-02-25 16:43:36 +00:00
|
|
|
m.getPlaybackInfoTask.observeField("data", "onPlaybackInfoLoaded")
|
|
|
|
|
|
|
|
m.global.sceneManager.callFunc("pushScene", m.view)
|
|
|
|
end sub
|
|
|
|
|
2023-03-09 19:35:29 +00:00
|
|
|
' -----------------
|
2023-02-25 16:43:36 +00:00
|
|
|
' Event Handlers
|
|
|
|
' -----------------
|
|
|
|
|
|
|
|
' User requested subtitle selection popup
|
|
|
|
sub onSelectSubtitlePressed()
|
|
|
|
' None is always first in the subtitle list
|
|
|
|
subtitleData = {
|
2023-05-07 01:26:02 +00:00
|
|
|
data: [{
|
|
|
|
"Index": -1,
|
|
|
|
"IsExternal": false,
|
|
|
|
"Track": {
|
|
|
|
"description": "None"
|
|
|
|
},
|
|
|
|
"Type": "subtitleselection"
|
|
|
|
}]
|
2023-02-25 16:43:36 +00:00
|
|
|
}
|
|
|
|
|
2023-05-07 01:26:02 +00:00
|
|
|
for each item in m.view.fullSubtitleData
|
2023-02-25 16:43:36 +00:00
|
|
|
item.type = "subtitleselection"
|
|
|
|
|
2023-05-07 01:26:02 +00:00
|
|
|
if m.view.selectedSubtitle <> -1
|
|
|
|
' Subtitle is a track within the file
|
|
|
|
if item.index = m.view.selectedSubtitle
|
|
|
|
item.selected = true
|
|
|
|
end if
|
|
|
|
else
|
|
|
|
' Subtitle is from an external source
|
2023-05-09 18:09:27 +00:00
|
|
|
availableSubtitleTrackIndex = availSubtitleTrackIdx(item.track.TrackName)
|
|
|
|
if availableSubtitleTrackIndex <> -1
|
|
|
|
|
|
|
|
' Convert Jellyfin subtitle track name to Roku track name
|
|
|
|
subtitleFullTrackName = m.view.availableSubtitleTracks[availableSubtitleTrackIndex].TrackName
|
|
|
|
|
|
|
|
if subtitleFullTrackName = m.view.subtitleTrack
|
|
|
|
item.selected = true
|
|
|
|
end if
|
|
|
|
|
2023-05-07 01:26:02 +00:00
|
|
|
end if
|
2023-02-25 16:43:36 +00:00
|
|
|
end if
|
|
|
|
|
|
|
|
subtitleData.data.push(item)
|
|
|
|
end for
|
|
|
|
|
|
|
|
m.global.sceneManager.callFunc("radioDialog", tr("Select Subtitles"), subtitleData)
|
|
|
|
m.global.sceneManager.observeField("returnData", "onSelectionMade")
|
|
|
|
end sub
|
|
|
|
|
|
|
|
' User has selected something from the radioDialog popup
|
|
|
|
sub onSelectionMade()
|
|
|
|
m.global.sceneManager.unobserveField("returnData")
|
|
|
|
|
|
|
|
if not isValid(m.global.sceneManager.returnData) then return
|
|
|
|
if not isValid(m.global.sceneManager.returnData.type) then return
|
|
|
|
|
|
|
|
if LCase(m.global.sceneManager.returnData.type) = "subtitleselection"
|
|
|
|
processSubtitleSelection()
|
|
|
|
end if
|
|
|
|
end sub
|
|
|
|
|
|
|
|
sub processSubtitleSelection()
|
|
|
|
m.selectedSubtitle = m.global.sceneManager.returnData
|
|
|
|
|
2023-05-07 01:26:02 +00:00
|
|
|
' The selected encoded subtitle did not change.
|
|
|
|
if m.view.selectedSubtitle <> -1 or m.selectedSubtitle.index <> -1
|
|
|
|
if m.view.selectedSubtitle = m.selectedSubtitle.index then return
|
|
|
|
end if
|
|
|
|
|
|
|
|
' The playbackData is now outdated and must be refreshed
|
|
|
|
m.playbackData = invalid
|
|
|
|
|
|
|
|
if LCase(m.selectedSubtitle.track.description) = "none"
|
2023-02-25 16:43:36 +00:00
|
|
|
m.view.globalCaptionMode = "Off"
|
|
|
|
m.view.subtitleTrack = ""
|
2023-05-07 01:26:02 +00:00
|
|
|
|
|
|
|
if m.view.selectedSubtitle <> -1
|
|
|
|
m.view.selectedSubtitle = -1
|
|
|
|
end if
|
|
|
|
|
2023-02-25 16:43:36 +00:00
|
|
|
return
|
|
|
|
end if
|
|
|
|
|
2023-05-07 01:26:02 +00:00
|
|
|
if m.selectedSubtitle.IsEncoded
|
|
|
|
m.view.globalCaptionMode = "Off"
|
|
|
|
else
|
|
|
|
m.view.globalCaptionMode = "On"
|
|
|
|
end if
|
|
|
|
|
|
|
|
if m.selectedSubtitle.IsExternal
|
2023-05-09 18:09:27 +00:00
|
|
|
availableSubtitleTrackIndex = availSubtitleTrackIdx(m.selectedSubtitle.Track.TrackName)
|
|
|
|
if availableSubtitleTrackIndex = -1 then return
|
|
|
|
|
|
|
|
m.view.subtitleTrack = m.view.availableSubtitleTracks[availableSubtitleTrackIndex].TrackName
|
2023-05-07 01:26:02 +00:00
|
|
|
else
|
|
|
|
m.view.selectedSubtitle = m.selectedSubtitle.Index
|
|
|
|
end if
|
2023-02-25 16:43:36 +00:00
|
|
|
end sub
|
|
|
|
|
|
|
|
' User requested playback info
|
|
|
|
sub onSelectPlaybackInfoPressed()
|
|
|
|
' Check if we already have playback info and show it in a popup
|
2023-03-09 19:35:29 +00:00
|
|
|
if isValid(m.playbackData) and isValid(m.playbackData.playbackinfo)
|
2023-02-25 16:43:36 +00:00
|
|
|
m.global.sceneManager.callFunc("standardDialog", tr("Playback Info"), m.playbackData.playbackinfo)
|
|
|
|
return
|
|
|
|
end if
|
|
|
|
|
|
|
|
m.getPlaybackInfoTask.control = "RUN"
|
|
|
|
end sub
|
|
|
|
|
|
|
|
' The playback info task has returned data
|
|
|
|
sub onPlaybackInfoLoaded()
|
|
|
|
m.playbackData = m.getPlaybackInfoTask.data
|
|
|
|
|
|
|
|
' Check if we have playback info and show it in a popup
|
2023-03-09 19:35:29 +00:00
|
|
|
if isValid(m.playbackData) and isValid(m.playbackData.playbackinfo)
|
2023-02-25 16:43:36 +00:00
|
|
|
m.global.sceneManager.callFunc("standardDialog", tr("Playback Info"), m.playbackData.playbackinfo)
|
|
|
|
end if
|
|
|
|
end sub
|
|
|
|
|
|
|
|
' Playback state change event handlers
|
|
|
|
sub onStateChange()
|
|
|
|
if LCase(m.view.state) = "finished"
|
2023-05-11 01:47:54 +00:00
|
|
|
' Close any open dialogs
|
|
|
|
if m.global.sceneManager.callFunc("isDialogOpen")
|
|
|
|
m.global.sceneManager.callFunc("dismissDialog")
|
|
|
|
end if
|
|
|
|
|
2023-02-25 16:43:36 +00:00
|
|
|
' 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")
|
|
|
|
return
|
|
|
|
end if
|
|
|
|
|
|
|
|
' Playback completed, return user to previous screen
|
|
|
|
m.global.sceneManager.callFunc("popScene")
|
2023-03-21 00:21:47 +00:00
|
|
|
m.global.audioPlayer.loopMode = ""
|
2023-02-25 16:43:36 +00:00
|
|
|
end if
|
2022-11-29 22:05:46 +00:00
|
|
|
end sub
|
2023-05-09 18:09:27 +00:00
|
|
|
|
|
|
|
' Roku translates the info provided in subtitleTracks into availableSubtitleTracks
|
|
|
|
' Including ignoring tracks, if they are not understood, thus making indexing unpredictable.
|
|
|
|
' This function translates between our internel selected subtitle index
|
|
|
|
' and the corresponding index in availableSubtitleTracks.
|
|
|
|
function availSubtitleTrackIdx(tracknameToFind as string) as integer
|
|
|
|
idx = 0
|
|
|
|
for each availTrack in m.view.availableSubtitleTracks
|
|
|
|
' The TrackName must contain the URL we supplied originally, though
|
|
|
|
' Roku mangles the name a bit, so we check if the URL is a substring, rather
|
|
|
|
' than strict equality
|
|
|
|
if Instr(1, availTrack.TrackName, tracknameToFind)
|
|
|
|
return idx
|
|
|
|
end if
|
|
|
|
idx = idx + 1
|
|
|
|
end for
|
|
|
|
return -1
|
|
|
|
end function
|