Skip to content

Commit

Permalink
Resume playback after schedule change (removes autoplay or external p…
Browse files Browse the repository at this point in the history
…layback state management)

(cherry picked from commit 3f25e0ffbb0e2b883875dfff5bd6d74669968800)
  • Loading branch information
robwalch committed Sep 10, 2024
1 parent ef72aa0 commit e1e515a
Showing 1 changed file with 29 additions and 7 deletions.
36 changes: 29 additions & 7 deletions src/controller/interstitials-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export default class InterstitialsController
private waitingItem: InterstitialScheduleEventItem | null = null;
private playingAsset: InterstitialAssetItem | null = null;
private bufferingAsset: InterstitialAssetItem | null = null;
private shouldPlay: boolean = false;

constructor(hls: Hls, HlsPlayerClass: typeof Hls) {
super('interstitials', hls.logger);
Expand Down Expand Up @@ -208,28 +209,33 @@ export default class InterstitialsController
// @ts-ignore
this.assetListLoader = null;
// @ts-ignore
this.onSeeking = this.onTimeupdate = null;
this.onPlay = this.onSeeking = this.onTimeupdate = null;
// @ts-ignore
this.onScheduleUpdate = null;
}

private onDestroying() {
const media = this.primaryMedia;
if (media) {
media.removeEventListener('seeking', this.onSeeking);
media.removeEventListener('timeupdate', this.onTimeupdate);
this.removeMediaListeners(media);
}
}

private removeMediaListeners(media: HTMLMediaElement) {
media.removeEventListener('play', this.onPlay);
media.removeEventListener('seeking', this.onSeeking);
media.removeEventListener('timeupdate', this.onTimeupdate);
}

private onMediaAttaching(
event: Events.MEDIA_ATTACHING,
data: MediaAttachingData,
) {
const media = (this.media = data.media);
media.removeEventListener('seeking', this.onSeeking);
media.removeEventListener('timeupdate', this.onTimeupdate);
this.removeMediaListeners(media);
media.addEventListener('seeking', this.onSeeking);
media.addEventListener('timeupdate', this.onTimeupdate);
media.addEventListener('play', this.onPlay);
}

private onMediaAttached(
Expand Down Expand Up @@ -269,8 +275,7 @@ export default class InterstitialsController
return;
}
if (media) {
media.removeEventListener('seeking', this.onSeeking);
media.removeEventListener('timeupdate', this.onTimeupdate);
this.removeMediaListeners(media);
}
// If detachMedia is called while in an Interstitial, detach the asset player as well and reset the schedule position
if (this.detachedData) {
Expand All @@ -283,6 +288,7 @@ export default class InterstitialsController
this.detachedData = null;
player.detachMedia();
}
this.shouldPlay = false;
}
}

Expand Down Expand Up @@ -661,6 +667,8 @@ export default class InterstitialsController
);
this.bufferingAsset = null;
this.detachedData = attachMediaSourceData;
} else if (toSegment && playerMedia) {
this.shouldPlay ||= !playerMedia.paused;
}
}

Expand Down Expand Up @@ -731,6 +739,10 @@ MediaSource ${JSON.stringify(attachMediaSourceData)} from ${logFromSource}`,
player.attachMedia(dataToAttach);
}

private onPlay = () => {
this.shouldPlay = true;
};

private onSeeking = () => {
const currentTime = this.currentTime;
if (currentTime === undefined || this.playbackDisabled) {
Expand All @@ -756,6 +768,9 @@ MediaSource ${JSON.stringify(attachMediaSourceData)} from ${logFromSource}`,
currentTime >= playingItem.end
) {
const scheduleIndex = this.schedule.findItemIndexAtTime(this.timelinePos);
if (!this.isInterstitial(playingItem) && this.media?.paused) {
this.shouldPlay = false;
}
if (!backwardSeek) {
// check if an Interstitial between the current item and target item has an X-RESTRICT JUMP restriction
const playingIndex = this.findItemIndex(playingItem);
Expand Down Expand Up @@ -1077,8 +1092,14 @@ MediaSource ${JSON.stringify(attachMediaSourceData)} from ${logFromSource}`,
index,
media,
);
if (this.shouldPlay) {
player.media?.play();
}
} else if (scheduledItem !== null) {
this.resumePrimary(scheduledItem, index);
if (this.shouldPlay) {
this.hls.media?.play();
}
} else if (playingLastItem && this.isInterstitial(currentItem)) {
// Maintain playingItem state at end of schedule (setSchedulePosition(-1) called to end program)
// this allows onSeeking handler to update schedule position
Expand Down Expand Up @@ -1958,6 +1979,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
if (!inQueuPlayer) {
return;
}
this.shouldPlay = true;
const scheduleIndex = this.schedule.findEventIndex(
interstitial.identifier,
);
Expand Down

0 comments on commit e1e515a

Please sign in to comment.