diff --git a/ext/src/cast/sdk/media/Media.ts b/ext/src/cast/sdk/media/Media.ts index 715a0e4..94a6bcf 100644 --- a/ext/src/cast/sdk/media/Media.ts +++ b/ext/src/cast/sdk/media/Media.ts @@ -32,6 +32,7 @@ import { ErrorCode } from "../enums"; import { ErrorCallback, SuccessCallback, UpdateListener } from "../../types"; import { SenderMediaMessage } from "../types"; +import { getEstimatedTime } from "../../utils"; export const NS_MEDIA = "urn:x-cast:com.google.cast.media"; @@ -92,45 +93,67 @@ export default class Media { .catch(errorCallback); } + /** + * Estimates the current break clip position based on the last + * information reported by the receiver. + */ getEstimatedBreakClipTime() { - logger.info("STUB :: Media#getEstimatedBreakClipTime"); + if (!this.breakStatus?.currentBreakClipTime) return; + + const currentBreakClip = this.media?.breakClips?.find( + breakClip => breakClip.id === this.breakStatus?.breakClipId + ); + if (!currentBreakClip) return; + + return getEstimatedTime({ + currentTime: this.breakStatus.currentBreakClipTime, + lastUpdateTime: this._lastUpdateTime, + duration: currentBreakClip.duration + }); } + + /** + * Estimates the current break position based on the last + * information reported by the receiver. + */ getEstimatedBreakTime() { - logger.info("STUB :: Media#getEstimatedBreakTime"); + if (!this.breakStatus?.currentBreakTime) return; + + const currentBreak = this.media?.breaks?.find( + break_ => break_.id === this.breakStatus?.breakId + ); + if (!currentBreak) return; + + return getEstimatedTime({ + currentTime: this.breakStatus.currentBreakTime, + lastUpdateTime: this._lastUpdateTime, + duration: currentBreak.duration + }); } + getEstimatedLiveSeekableRange() { logger.info("STUB :: Media#getEstimatedLiveSeekableRange"); } /** - * Estimate the current playback position based on the last - * time reported by the receiver and the current playback - * rate. + * Estimates the current playback position based on the last + * information reported by the receiver. */ getEstimatedTime(): number { if (this.playerState === PlayerState.PLAYING && this._lastUpdateTime) { - let estimatedTime = - this.currentTime + (Date.now() - this._lastUpdateTime) / 1000; - - // Enforce valid range - if (estimatedTime < 0) { - estimatedTime = 0; - } else if ( - this.media?.duration && - estimatedTime > this.media.duration - ) { - estimatedTime = this.media.duration; - } - - return estimatedTime; + return getEstimatedTime({ + currentTime: this.currentTime, + lastUpdateTime: this._lastUpdateTime, + duration: this.media?.duration + }); } return this.currentTime; } /** - * Request media status from the receiver application. This - * will also trigger any added media update listeners. + * Request media status from the receiver application. This will + * also trigger any added media update listeners. */ getStatus( getStatusRequest = new GetStatusRequest(), diff --git a/ext/src/cast/utils.ts b/ext/src/cast/utils.ts index c31ba01..37506da 100644 --- a/ext/src/cast/utils.ts +++ b/ext/src/cast/utils.ts @@ -27,3 +27,22 @@ export function hasRequiredCapabilities( } }); } + +interface GetEstimatedTimeOpts { + currentTime: number; + lastUpdateTime: number; + duration?: Nullable; +} +export function getEstimatedTime(opts: GetEstimatedTimeOpts) { + let estimatedTime = + opts.currentTime + (Date.now() - opts.lastUpdateTime) / 1000; + + // Enforce valid range + if (estimatedTime < 0) { + estimatedTime = 0; + } else if (opts.duration && estimatedTime > opts.duration) { + estimatedTime = opts.duration; + } + + return estimatedTime; +} diff --git a/ext/src/ui/popup/ReceiverMedia.svelte b/ext/src/ui/popup/ReceiverMedia.svelte index 7db7061..9549f67 100644 --- a/ext/src/ui/popup/ReceiverMedia.svelte +++ b/ext/src/ui/popup/ReceiverMedia.svelte @@ -14,6 +14,7 @@ const _ = browser.i18n.getMessage; import deviceStore from "./deviceStore"; + import { getEstimatedTime } from "../../cast/utils"; const dispatch = createEventDispatcher<{ togglePlayback: void; @@ -99,7 +100,7 @@ // Keep track of update times for currentTime estimations let lastUpdateTime = 0; - let currentTime = getEstimatedTime(); + let currentTime = getEstimatedMediaTime(); deviceStore.subscribe(devices => { const newDevice = devices.find(newDevice => newDevice.id === device.id); @@ -112,8 +113,8 @@ // Update estimated time every second onMount(() => { const intervalId = window.setInterval(() => { - if (currentTime !== getEstimatedTime()) { - currentTime = getEstimatedTime(); + if (currentTime !== getEstimatedMediaTime()) { + currentTime = getEstimatedMediaTime(); } }, 1000); @@ -126,23 +127,15 @@ * Estimates the current playback position based on the last status * update. */ - function getEstimatedTime() { - if (!status.currentTime) return 0; + function getEstimatedMediaTime() { + if (!status.currentTime || !lastUpdateTime) return 0; - if (status.playerState === PlayerState.PLAYING && lastUpdateTime) { - let estimatedTime = - status.currentTime + (Date.now() - lastUpdateTime) / 1000; - - if (estimatedTime < 0) { - estimatedTime = 0; - } else if ( - status.media?.duration && - estimatedTime > status.media.duration - ) { - estimatedTime = status.media.duration; - } - - return estimatedTime; + if (status.playerState === PlayerState.PLAYING) { + return getEstimatedTime({ + currentTime: status.currentTime, + lastUpdateTime, + duration: status.media?.duration + }); } return status.currentTime;