Merge branch 'master' into video-fixes

This commit is contained in:
Neil Burrows 2021-09-06 07:23:38 +01:00 committed by GitHub
commit c23b64d46e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 111 additions and 91 deletions

View File

@ -1,11 +1,14 @@
sub init()
m.playbackTimer = m.top.findNode("playbackTimer")
m.bufferCheckTimer = m.top.findNode("bufferCheckTimer")
m.top.observeField("state", "onState")
m.playbackTimer.observeField("fire", "ReportPlayback")
m.bufferPercentage = 0 ' Track whether content is being loaded
m.playReported = false
m.top.transcodeReasons = []
end sub
'
' When Video Player state changes
sub onState(msg)
@ -14,11 +17,9 @@ sub onState(msg)
if m.top.state = "buffering" and m.bufferCheckTimer <> invalid
' start timer
m.bufferCheckTimer = m.top.findNode("bufferCheckTimer")
m.bufferCheckTimer.control = "start"
m.bufferCheckTimer.ObserveField("fire", "bufferCheck")
else if m.top.state = "error"
' If an error was encountered, Display dialog
dialog = createObject("roSGNode", "Dialog")
dialog.title = tr("Error During Playback")
@ -30,10 +31,50 @@ sub onState(msg)
' Stop playback and exit player
m.top.control = "stop"
m.top.backPressed = true
else if m.top.state = "playing"
if m.playReported = false
ReportPlayback("start")
m.playReported = true
else
m.playbackTimer.control = "start"
ReportPlayback()
end if
else if m.top.state = "paused"
m.playbackTimer.control = "stop"
ReportPlayback()
else if m.top.state = "stopped"
m.playbackTimer.control = "stop"
ReportPlayback("stop")
m.playReported = false
end if
end sub
'
' Report playback to server
sub ReportPlayback(state = "update" as string)
if m.top.position = invalid then return
params = {
"ItemId": m.top.id
"PlaySessionId": m.top.PlaySessionId,
"PositionTicks": int(m.top.position) * 10000000&, 'Ensure a LongInteger is used
"IsPaused": (m.top.state = "paused"),
}
if m.top.content.live
params.append({
"MediaSourceId": m.top.transcodeParams.MediaSourceId,
"LiveStreamId": m.top.transcodeParams.LiveStreamId
})
end if
' Report playstate via worker task
playstateTask = m.global.playstateTask
playstateTask.setFields({ status: state, params: params })
playstateTask.control = "RUN"
end sub
'
' Check the the buffering has not hung
sub bufferCheck(msg)

View File

@ -1,51 +1,48 @@
function PlaystateUpdate(id, state as string, params = {})
if state = "start"
url = "Sessions/Playing"
else if state = "stop"
url = "Sessions/Playing/Stopped"
else if state = "update"
url = "Sessions/Playing/Progress"
else
' Unknow State
return {}
end if
params = PlaystateDefaults(id, params)
resp = APIRequest(url)
return postJson(resp, params)
end function
function PlaystateDefaults(id = "" as string, params = {} as object)
new_params = {
'"CanSeek": false
'"Item": "{}", ' TODO!
'"NowPlayingQueue": "[]", ' TODO!
'"PlaylistItemId": "",
"ItemId": id,
'"SessionId": "", ' TODO!
'"MediaSourceId": id,
'"AudioStreamIndex": 1,
'"SubtitleStreamIndex": 0,
"IsPaused": false,
'"IsMuted": false,
"PositionTicks": 0,
'"PlaybackStartTimeTicks": 0,
'"VolumeLevel": 100,
'"Brightness": 100,
'"AspectRatio": "16x9",
'"PlayMethod": "DirectStream"
'"LiveStreamId": "",
'"PlaySessionId": "",
'"RepeatMode": "RepeatNone"
}
for each p in params.items()
new_params[p.key] = p.value
end for
return FormatJson(new_params)
end function
sub deleteTranscode(id)
devinfo = CreateObject("roDeviceInfo")
req = APIRequest("/Videos/ActiveEncodings", { "deviceID": devinfo.getChannelClientID(), "PlaySessionId": id })
req.setRequest("DELETE")
postVoid(req)
end sub
sub init()
m.top.functionName = "PlaystateUpdate"
end sub
sub PlaystateUpdate()
if m.top.status = "start"
url = "Sessions/Playing"
else if m.top.status = "stop"
url = "Sessions/Playing/Stopped"
else if m.top.status = "update"
url = "Sessions/Playing/Progress"
else
' Unknown State
return
end if
params = PlaystateDefaults(m.top.params)
resp = APIRequest(url)
postJson(resp, params)
end sub
function PlaystateDefaults(params = {} as object)
new_params = {
'"CanSeek": false
'"Item": "{}", ' TODO!
'"NowPlayingQueue": "[]", ' TODO!
'"PlaylistItemId": "",
'"ItemId": id,
'"SessionId": "", ' TODO!
'"MediaSourceId": id,
'"AudioStreamIndex": 1,
'"SubtitleStreamIndex": 0,
"IsPaused": false,
'"IsMuted": false,
"PositionTicks": 0,
'"PlaybackStartTimeTicks": 0,
'"VolumeLevel": 100,
'"Brightness": 100,
'"AspectRatio": "16x9",
'"PlayMethod": "DirectStream"
'"LiveStreamId": "",
'"PlaySessionId": "",
'"RepeatMode": "RepeatNone"
}
for each p in params.items()
new_params[p.key] = p.value
end for
return FormatJson(new_params)
end function

11
components/PlaystateTask.xml Executable file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="PlaystateTask" extends="Task">
<interface>
<field id="status" type="string" />
<field id="params" type="assocarray" />
</interface>
<script type="text/brightscript" uri="PlaystateTask.brs" />
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
</component>

View File

@ -17,7 +17,11 @@ sub Main (args as dynamic) as void
' Set any initial Global Variables
m.global = m.screen.getGlobalNode()
m.global.addFields({ app_loaded: false })
playstateTask = CreateObject("roSGNode", "PlaystateTask")
playstateTask.id = "playstateTask"
m.global.addFields({ app_loaded: false, playstateTask: playstateTask })
m.overhang = CreateObject("roSGNode", "JFOverhang")
m.scene.insertChild(m.overhang, 0)
@ -62,7 +66,6 @@ sub Main (args as dynamic) as void
m.scene.appendChild(group)
group.setFocus(true)
group.control = "play"
ReportPlayback(group, "start")
m.overhang.visible = false
else
dialog = createObject("roSGNode", "Dialog")
@ -120,7 +123,6 @@ sub Main (args as dynamic) as void
m.scene.appendChild(group)
group.setFocus(true)
group.control = "play"
ReportPlayback(group, "start")
m.overhang.visible = false
end if
end if
@ -139,6 +141,7 @@ sub Main (args as dynamic) as void
' play episode
' todo: create an episode page to link here
video_id = selectedItem.id
m.scene.unobserveField("optionsPressed")
video = CreateVideoPlayerGroup(video_id)
if video <> invalid
group.lastFocus = group.focusedChild
@ -148,7 +151,6 @@ sub Main (args as dynamic) as void
m.scene.appendChild(group)
group.setFocus(true)
group.control = "play"
ReportPlayback(group, "start")
m.overhang.visible = false
end if
else if selectedItem.type = "Series"
@ -184,6 +186,7 @@ sub Main (args as dynamic) as void
dialog.title = tr("Loading Channel Data")
m.scene.dialog = dialog
m.scene.unobserveField("optionsPressed")
video = CreateVideoPlayerGroup(video_id)
dialog.close = true
@ -195,7 +198,6 @@ sub Main (args as dynamic) as void
m.scene.appendChild(group)
group.setFocus(true)
group.control = "play"
ReportPlayback(group, "start")
m.overhang.visible = false
else
dialog = createObject("roSGNode", "Dialog")
@ -258,6 +260,7 @@ sub Main (args as dynamic) as void
' If you select a TV Episode from ANYWHERE, follow this flow
node = getMsgPicker(msg, "picker")
video_id = node.id
m.scene.unobserveField("optionsPressed")
video = CreateVideoPlayerGroup(video_id)
if video <> invalid
group.lastFocus = group.focusedChild
@ -267,7 +270,6 @@ sub Main (args as dynamic) as void
m.scene.appendChild(group)
group.setFocus(true)
group.control = "play"
ReportPlayback(group, "start")
m.overhang.visible = false
end if
else if isNodeEvent(msg, "search_value")
@ -323,7 +325,6 @@ sub Main (args as dynamic) as void
m.scene.appendChild(group)
group.setFocus(true)
group.control = "play"
ReportPlayback(group, "start")
m.overhang.visible = false
end if
else if btn <> invalid and btn.id = "watched-button"
@ -399,8 +400,6 @@ sub Main (args as dynamic) as void
changeSubtitleDuringPlayback(trackSelected)
end if
end if
else if isNodeEvent(msg, "fire")
ReportPlayback(group, "update")
else if isNodeEvent(msg, "state")
node = msg.getRoSGNode()
if node.state = "finished"
@ -411,8 +410,6 @@ sub Main (args as dynamic) as void
nextEpisode = autoPlayNextEpisode(node.id, node.showID)
if nextEpisode <> invalid then group = nextEpisode
end if
else if node.state = "playing" or node.state = "paused"
ReportPlayback(group, "update")
end if
else if type(msg) = "roDeviceInfoEvent"
event = msg.GetInfo()
@ -441,7 +438,6 @@ sub Main (args as dynamic) as void
m.scene.appendChild(group)
group.setFocus(true)
group.control = "play"
ReportPlayback(group, "start")
m.overhang.visible = false
else
dialog = createObject("roSGNode", "Dialog")

View File

@ -295,13 +295,9 @@ function CreateVideoPlayerGroup(video_id, audio_stream_idx = 1)
' Video is Playing
video = VideoPlayer(video_id, audio_stream_idx)
if video = invalid then return invalid
timer = video.findNode("playbackTimer")
video.observeField("backPressed", m.port)
video.observeField("selectSubtitlePressed", m.port)
video.observeField("state", m.port)
timer.control = "start"
timer.observeField("fire", m.port)
return video
end function

View File

@ -208,30 +208,10 @@ function getAudioInfo(meta as object) as object
return results
end function
sub ReportPlayback(video, state = "update" as string)
if video = invalid or video.position = invalid then return
params = {
"PlaySessionId": video.PlaySessionId,
"PositionTicks": int(video.position) * 10000000&, 'Ensure a LongInteger is used
"IsPaused": (video.state = "paused"),
}
if video.content.live
params.append({
"MediaSourceId": video.transcodeParams.MediaSourceId,
"LiveStreamId": video.transcodeParams.LiveStreamId
})
end if
PlaystateUpdate(video.id, state, params)
end sub
sub StopPlayback()
video = m.scene.focusedchild
video.control = "stop"
m.device.EnableAppFocusEvent(False)
video.findNode("playbackTimer").control = "stop"
ReportPlayback(video, "stop")
end sub
function autoPlayNextEpisode(videoID as string, showID as string)
@ -254,7 +234,6 @@ function autoPlayNextEpisode(videoID as string, showID as string)
m.scene.appendChild(nextVideo)
nextVideo.setFocus(true)
nextVideo.control = "play"
ReportPlayback(nextVideo, "start")
return nextVideo
else
' can't play next episode