diff --git a/components/video/OSD.bs b/components/video/OSD.bs index 7e61d0f58..101ac2796 100644 --- a/components/video/OSD.bs +++ b/components/video/OSD.bs @@ -16,8 +16,11 @@ sub init() m.videoInfo = m.top.findNode("videoInfo") m.itemTitle = m.top.findNode("itemTitle") m.videoPlayPause = m.top.findNode("videoPlayPause") - m.videoRemainingTime = m.top.findNode("videoRemainingTime") - m.videoEndingTime = m.top.findNode("videoEndingTime") + m.belowLeft = m.top.findNode("belowLeft") + m.aboveRight = m.top.findNode("aboveRight") + m.belowRight = m.top.findNode("belowRight") + m.aboveLeft = m.top.findNode("aboveLeft") + m.clock = m.top.findNode("clock") m.progressBar = m.top.findNode("progressBar") m.progressBarBackground = m.top.findNode("progressBarBackground") m.progressIndicator = m.top.findNode("progressIndicator") @@ -34,7 +37,8 @@ sub init() m.top.observeField("hasFocus", "onFocusChanged") m.top.observeField("progressPercentage", "onProgressPercentageChanged") m.top.observeField("playbackState", "onPlaybackStateChanged") - m.top.observeField("videoEndingTime", "setVideoEndingTime") + ' Ends-at is recalculated on a clock timer, so it moves while paused when position doesn't + m.top.observeField("videoEndingTime", "updateOSDTime") m.top.observeField("itemTitleText", "onItemTitleTextChanged") m.top.observeField("itemSubtitleText", "onItemSubtitleTextChanged") @@ -83,51 +87,54 @@ sub init() positionSecondaryControls() end sub -function formatOSDTimeSlot(slotKey as string) as string +' A previewPosition below zero means use the live playback position +function formatOSDTimeSlot(slotKey as string, previewPosition as float) as string slotMode = m.global.session.user.settings[slotKey] ?? "none" if slotMode = "none" or slotMode = "" then return "" - if slotMode = "elapsed" then return secondsToHuman(m.top.positionTime, true) - if slotMode = "remaining" then return "-" + secondsToHuman(m.top.remainingPositionTime, true) + + totalTime = m.top.positionTime + m.top.remainingPositionTime + position = previewPosition >= 0 ? previewPosition : m.top.positionTime + + if slotMode = "elapsed" then return secondsToHuman(position, true) if slotMode = "endsAt" then return "Ends at " + m.top.videoEndingTime - if slotMode = "time" then return m.top.videoEndingTime + if slotMode = "time" then return m.clock.callFunc("getFormattedTime", m.clock.callFunc("getCurrentTime"), true) + ' Both spellings are accepted because either can be the stored value + if slotMode = "timeRemaining" or slotMode = "remaining" then return "-" + secondsToHuman(totalTime - position, true) + if slotMode = "totalDuration" or slotMode = "totalTime" then return secondsToHuman(totalTime, true) return "" end function +' Every slot is assigned so that switching one to None clears whatever it was holding +sub renderOSDTimeSlots(previewPosition as float) + m.aboveLeft.text = formatOSDTimeSlot("playback.timeAboveLeft", previewPosition) + m.aboveRight.text = formatOSDTimeSlot("playback.timeAboveRight", previewPosition) + m.belowLeft.text = formatOSDTimeSlot("playback.timeBelowLeft", previewPosition) + m.belowRight.text = formatOSDTimeSlot("playback.timeBelowRight", previewPosition) +end sub + +' Observer callbacks receive an event argument when they declare a parameter, so this stays bare +sub updateOSDTime() + renderOSDTimeSlots(-1) +end sub + ' onProgressPercentageChanged: Handler for changes to m.top.progressPercentage param ' sub onProgressPercentageChanged() - totalTime = m.top.positionTime + m.top.remainingPositionTime m.progressBar.width = m.progressBarBackground.width * m.top.progressPercentage - - aboveLeft = formatOSDTimeSlot("playback.timeAboveLeft") - aboveRight = formatOSDTimeSlot("playback.timeAboveRight") - if aboveLeft <> "" or aboveRight <> "" - m.videoRemainingTime.text = (aboveLeft <> "" ? aboveLeft : "") + (aboveRight <> "" ? " / " + aboveRight : "") - else - m.videoRemainingTime.text = secondsToHuman(m.top.positionTime, true) + " / " + secondsToHuman(totalTime, true) - end if + updateOSDTime() ' Update circle indicator position (centered on progress, offset by circle radius) indicatorX = 103 + (m.progressBarBackground.width * m.top.progressPercentage) - 10 m.progressIndicator.translation = [indicatorX, 812] end sub -sub setVideoEndingTime() - belowRight = formatOSDTimeSlot("playback.timeBelowRight") - if belowRight <> "" - m.videoEndingTime.text = belowRight - else - m.videoEndingTime.text = "Ends at " + m.top.videoEndingTime - end if -end sub - sub updateSeekPreview(totalTime as float) newPosition = totalTime * m.seekPercentage m.progressBar.width = m.progressBarBackground.width * m.seekPercentage + renderOSDTimeSlots(newPosition) indicatorX = 103 + (m.progressBarBackground.width * m.seekPercentage) - 10 m.progressIndicator.translation = [indicatorX, 812] - m.videoRemainingTime.text = secondsToHuman(newPosition, true) + " / " + secondsToHuman(totalTime, true) m.top.action = "seek," + newPosition.ToStr() end sub diff --git a/components/video/OSD.xml b/components/video/OSD.xml index 7408ddf9c..3ded72da7 100644 --- a/components/video/OSD.xml +++ b/components/video/OSD.xml @@ -30,8 +30,10 @@ - - + + + + @@ -101,4 +103,4 @@ - \ No newline at end of file + diff --git a/settings/settings.json b/settings/settings.json index 83f73a6ba..8d2abc3a9 100644 --- a/settings/settings.json +++ b/settings/settings.json @@ -1975,87 +1975,63 @@ ] }, { - "title": "Media Bar Playback Time Above Left", + "title": "Progress Bar Time Above Left", "description": "Select information to display above the progress bar on the left side", "settingName": "playback.timeAboveLeft", "type": "radio", - "default": "elapsed", - "options": [ - { "title": "None", "id": "none" }, - { "title": "Current Time", "id": "time" }, - { "title": "Elapsed Time", "id": "elapsed" }, - { "title": "Remaining Time", "id": "remaining" }, - { "title": "Ends At Time", "id": "endsAt" } - ] - }, - { - "title": "Media Bar Playback Time Above Center", - "description": "Select information to display above the progress bar in the center", - "settingName": "playback.timeAboveCenter", - "type": "radio", "default": "none", "options": [ { "title": "None", "id": "none" }, { "title": "Current Time", "id": "time" }, { "title": "Elapsed Time", "id": "elapsed" }, - { "title": "Remaining Time", "id": "remaining" }, - { "title": "Ends At Time", "id": "endsAt" } - ] - }, - { - "title": "Media Bar Playback Time Above Right", - "description": "Select information to display above the progress bar on the right side", - "settingName": "playback.timeAboveRight", - "type": "radio", - "default": "remaining", - "options": [ - { "title": "None", "id": "none" }, - { "title": "Current Time", "id": "time" }, - { "title": "Elapsed Time", "id": "elapsed" }, - { "title": "Remaining Time", "id": "remaining" }, - { "title": "Ends At Time", "id": "endsAt" } + { "title": "Remaining Time", "id": "timeRemaining" }, + { "title": "Ends At Time", "id": "endsAt" }, + { "title": "Total Duration", "id": "totalDuration" } ] }, { - "title": "Media Bar Playback Time Below Left", + "title": "Progress Bar Time Below Left", "description": "Select information to display below the progress bar on the left side", "settingName": "playback.timeBelowLeft", "type": "radio", - "default": "none", + "default": "elapsed", "options": [ { "title": "None", "id": "none" }, { "title": "Current Time", "id": "time" }, { "title": "Elapsed Time", "id": "elapsed" }, - { "title": "Remaining Time", "id": "remaining" }, - { "title": "Ends At Time", "id": "endsAt" } + { "title": "Remaining Time", "id": "timeRemaining" }, + { "title": "Ends At Time", "id": "endsAt" }, + { "title": "Total Duration", "id": "totalDuration" } ] }, { - "title": "Media Bar Playback Time Below Center", - "description": "Select information to display below the progress bar in the center", - "settingName": "playback.timeBelowCenter", + "title": "Progress Bar Time Above Right", + "description": "Select information to display above the progress bar on the right side", + "settingName": "playback.timeAboveRight", "type": "radio", - "default": "none", + "default": "endsAt", "options": [ { "title": "None", "id": "none" }, { "title": "Current Time", "id": "time" }, { "title": "Elapsed Time", "id": "elapsed" }, - { "title": "Remaining Time", "id": "remaining" }, - { "title": "Ends At Time", "id": "endsAt" } + { "title": "Remaining Time", "id": "timeRemaining" }, + { "title": "Ends At Time", "id": "endsAt" }, + { "title": "Total Duration", "id": "totalDuration" } ] }, { - "title": "Media Bar Playback Time Below Right", + "title": "Progress Bar Time Below Right", "description": "Select information to display below the progress bar on the right side", "settingName": "playback.timeBelowRight", "type": "radio", - "default": "endsAt", + "default": "totalDuration", "options": [ { "title": "None", "id": "none" }, { "title": "Current Time", "id": "time" }, { "title": "Elapsed Time", "id": "elapsed" }, - { "title": "Remaining Time", "id": "remaining" }, - { "title": "Ends At Time", "id": "endsAt" } + { "title": "Remaining Time", "id": "timeRemaining" }, + { "title": "Ends At Time", "id": "endsAt" }, + { "title": "Total Duration", "id": "totalDuration" } ] } ] diff --git a/source/utils/settingsSync.bs b/source/utils/settingsSync.bs index 36b9541cb..19fe4693b 100644 --- a/source/utils/settingsSync.bs +++ b/source/utils/settingsSync.bs @@ -119,10 +119,8 @@ namespace settingsSync { pluginKey: "mergeRadarrSonarrCalendars", rokuKey: "calendar.merge", type: "bool" }, { pluginKey: "playbackTimeAboveLeft", rokuKey: "playback.timeAboveLeft", type: "direct" }, - { pluginKey: "playbackTimeAboveCenter", rokuKey: "playback.timeAboveCenter", type: "direct" }, { pluginKey: "playbackTimeAboveRight", rokuKey: "playback.timeAboveRight", type: "direct" }, { pluginKey: "playbackTimeBelowLeft", rokuKey: "playback.timeBelowLeft", type: "direct" }, - { pluginKey: "playbackTimeBelowCenter", rokuKey: "playback.timeBelowCenter", type: "direct" }, { pluginKey: "playbackTimeBelowRight", rokuKey: "playback.timeBelowRight", type: "direct" }, { pluginKey: "musicPlaybackTimeDisplay", rokuKey: "playback.musicTimeDisplay", type: "direct" },