Implement voice broadcast playback buffering (#9435)
Co-authored-by: Kerry <kerrya@element.io>
This commit is contained in:
parent
877c95df8f
commit
788dd904b7
5 changed files with 201 additions and 22 deletions
|
@ -36,6 +36,7 @@ export enum VoiceBroadcastPlaybackState {
|
|||
Paused,
|
||||
Playing,
|
||||
Stopped,
|
||||
Buffering,
|
||||
}
|
||||
|
||||
export enum VoiceBroadcastPlaybackEvent {
|
||||
|
@ -91,7 +92,7 @@ export class VoiceBroadcastPlayback
|
|||
this.chunkRelationHelper.emitCurrent();
|
||||
}
|
||||
|
||||
private addChunkEvent(event: MatrixEvent): boolean {
|
||||
private addChunkEvent = async (event: MatrixEvent): Promise<boolean> => {
|
||||
const eventId = event.getId();
|
||||
|
||||
if (!eventId
|
||||
|
@ -102,8 +103,17 @@ export class VoiceBroadcastPlayback
|
|||
}
|
||||
|
||||
this.chunkEvents.set(eventId, event);
|
||||
|
||||
if (this.getState() !== VoiceBroadcastPlaybackState.Stopped) {
|
||||
await this.enqueueChunk(event);
|
||||
}
|
||||
|
||||
if (this.getState() === VoiceBroadcastPlaybackState.Buffering) {
|
||||
await this.start();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private addInfoEvent = (event: MatrixEvent): void => {
|
||||
if (this.lastInfoEvent && this.lastInfoEvent.getTs() >= event.getTs()) {
|
||||
|
@ -149,20 +159,30 @@ export class VoiceBroadcastPlayback
|
|||
playback.on(UPDATE_EVENT, (state) => this.onPlaybackStateChange(playback, state));
|
||||
}
|
||||
|
||||
private onPlaybackStateChange(playback: Playback, newState: PlaybackState) {
|
||||
private async onPlaybackStateChange(playback: Playback, newState: PlaybackState) {
|
||||
if (newState !== PlaybackState.Stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
const next = this.queue[this.queue.indexOf(playback) + 1];
|
||||
await this.playNext(playback);
|
||||
}
|
||||
|
||||
private async playNext(current: Playback): Promise<void> {
|
||||
const next = this.queue[this.queue.indexOf(current) + 1];
|
||||
|
||||
if (next) {
|
||||
this.setState(VoiceBroadcastPlaybackState.Playing);
|
||||
this.currentlyPlaying = next;
|
||||
next.play();
|
||||
await next.play();
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState(VoiceBroadcastPlaybackState.Stopped);
|
||||
if (this.getInfoState() === VoiceBroadcastInfoState.Stopped) {
|
||||
this.setState(VoiceBroadcastPlaybackState.Stopped);
|
||||
} else {
|
||||
// No more chunks available, although the broadcast is not finished → enter buffering state.
|
||||
this.setState(VoiceBroadcastPlaybackState.Buffering);
|
||||
}
|
||||
}
|
||||
|
||||
public async start(): Promise<void> {
|
||||
|
@ -174,14 +194,14 @@ export class VoiceBroadcastPlayback
|
|||
? 0 // start at the beginning for an ended voice broadcast
|
||||
: this.queue.length - 1; // start at the current chunk for an ongoing voice broadcast
|
||||
|
||||
if (this.queue.length === 0 || !this.queue[toPlayIndex]) {
|
||||
this.setState(VoiceBroadcastPlaybackState.Stopped);
|
||||
if (this.queue[toPlayIndex]) {
|
||||
this.setState(VoiceBroadcastPlaybackState.Playing);
|
||||
this.currentlyPlaying = this.queue[toPlayIndex];
|
||||
await this.currentlyPlaying.play();
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState(VoiceBroadcastPlaybackState.Playing);
|
||||
this.currentlyPlaying = this.queue[toPlayIndex];
|
||||
await this.currentlyPlaying.play();
|
||||
this.setState(VoiceBroadcastPlaybackState.Buffering);
|
||||
}
|
||||
|
||||
public get length(): number {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue