diff --git a/receivers/electron/src/player/Player.ts b/receivers/electron/src/player/Player.ts index d7cf776..550f3b9 100644 --- a/receivers/electron/src/player/Player.ts +++ b/receivers/electron/src/player/Player.ts @@ -203,6 +203,16 @@ export class Player { } } + isCaptionsSupported(): boolean { + if (this.playerType === PlayerType.Dash) { + return (this.player as dashjs.MediaPlayerClass).getTracksFor('text').length > 0; + } else if (this.playerType === PlayerType.Hls) { + return this.hlsPlayer.allSubtitleTracks.length > 0; + } else { + return false; // HTML captions not currently supported + } + } + isCaptionsEnabled(): boolean { if (this.playerType === PlayerType.Dash) { return (this.player as dashjs.MediaPlayerClass).isTextEnabled(); @@ -212,6 +222,7 @@ export class Player { return false; // HTML captions not currently supported } } + enableCaptions(enable: boolean) { if (this.playerType === PlayerType.Dash) { (this.player as dashjs.MediaPlayerClass).enableText(enable); diff --git a/receivers/electron/src/player/Renderer.ts b/receivers/electron/src/player/Renderer.ts index a5ce4a4..88cd32e 100644 --- a/receivers/electron/src/player/Renderer.ts +++ b/receivers/electron/src/player/Renderer.ts @@ -309,7 +309,7 @@ enum PlayerControlEvent { ExitFullscreen, } -// UI update handler +// UI update handlers function playerCtrlStateUpdate(event: PlayerControlEvent) { switch (event) { case PlayerControlEvent.Load: { @@ -332,6 +332,15 @@ function playerCtrlStateUpdate(event: PlayerControlEvent) { playerCtrlDuration.innerHTML = `/  ${formatDuration(player.getDuration())}`; } + if (player.isCaptionsSupported()) { + playerCtrlCaptions.setAttribute("style", "display: block"); + videoCaptions.setAttribute("style", "display: block"); + } + else { + playerCtrlCaptions.setAttribute("style", "display: none"); + videoCaptions.setAttribute("style", "display: none"); + player.enableCaptions(false); + } playerCtrlStateUpdate(PlayerControlEvent.SetCaptions); break; } @@ -481,6 +490,25 @@ function playerCtrlStateUpdate(event: PlayerControlEvent) { } } +function scrubbingMouseUIHandler(e: MouseEvent) { + const progressBarOffset = e.offsetX - 8; + const progressBarWidth = PlayerCtrlProgressBarInteractiveArea.offsetWidth - 16; + let time = isLive ? Math.round((1 - (progressBarOffset / progressBarWidth)) * player.getDuration()) : Math.round((progressBarOffset / progressBarWidth) * player.getDuration()); + time = Math.min(player.getDuration(), Math.max(0.0, time)); + + if (scrubbing && isLive && e.buttons === 1) { + isLivePosition = false; + playerCtrlLiveBadge.setAttribute("style", `background-color: #595959`); + } + + const livePrefix = isLive && Math.floor(time) !== 0 ? "-" : ""; + playerCtrlProgressBarPosition.textContent = isLive ? `${livePrefix}${formatDuration(time)}` : formatDuration(time); + + let offset = e.offsetX - (playerCtrlProgressBarPosition.offsetWidth / 2); + offset = Math.min(PlayerCtrlProgressBarInteractiveArea.offsetWidth - (playerCtrlProgressBarPosition.offsetWidth / 1), Math.max(8, offset)); + playerCtrlProgressBarPosition.setAttribute("style", `display: block; left: ${offset}px`); +} + // Receiver generated event handlers playerCtrlAction.onclick = () => { if (player.isPaused()) {