Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
When start listening to a broadcast, pause the others (#9489)
Browse files Browse the repository at this point in the history
  • Loading branch information
weeman1337 authored Oct 24, 2022
1 parent daf097e commit d702f4a
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 61 deletions.
17 changes: 13 additions & 4 deletions src/voice-broadcast/models/VoiceBroadcastPlayback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ export enum VoiceBroadcastPlaybackEvent {

interface EventMap {
[VoiceBroadcastPlaybackEvent.LengthChanged]: (length: number) => void;
[VoiceBroadcastPlaybackEvent.StateChanged]: (state: VoiceBroadcastPlaybackState) => void;
[VoiceBroadcastPlaybackEvent.StateChanged]: (
state: VoiceBroadcastPlaybackState,
playback: VoiceBroadcastPlayback
) => void;
[VoiceBroadcastPlaybackEvent.InfoStateChanged]: (state: VoiceBroadcastInfoState) => void;
}

Expand Down Expand Up @@ -217,14 +220,20 @@ export class VoiceBroadcastPlayback
}

public pause(): void {
if (!this.currentlyPlaying) return;
// stopped voice broadcasts cannot be paused
if (this.getState() === VoiceBroadcastPlaybackState.Stopped) return;

this.setState(VoiceBroadcastPlaybackState.Paused);
if (!this.currentlyPlaying) return;
this.currentlyPlaying.pause();
}

public resume(): void {
if (!this.currentlyPlaying) return;
if (!this.currentlyPlaying) {
// no playback to resume, start from the beginning
this.start();
return;
}

this.setState(VoiceBroadcastPlaybackState.Playing);
this.currentlyPlaying.play();
Expand Down Expand Up @@ -260,7 +269,7 @@ export class VoiceBroadcastPlayback
}

this.state = state;
this.emit(VoiceBroadcastPlaybackEvent.StateChanged, state);
this.emit(VoiceBroadcastPlaybackEvent.StateChanged, state, this);
}

public getInfoState(): VoiceBroadcastInfoState {
Expand Down
56 changes: 51 additions & 5 deletions src/voice-broadcast/stores/VoiceBroadcastPlaybacksStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ limitations under the License.
import { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { TypedEventEmitter } from "matrix-js-sdk/src/models/typed-event-emitter";

import { VoiceBroadcastPlayback } from "..";
import { VoiceBroadcastPlayback, VoiceBroadcastPlaybackEvent, VoiceBroadcastPlaybackState } from "..";
import { IDestroyable } from "../../utils/IDestroyable";

export enum VoiceBroadcastPlaybacksStoreEvent {
CurrentChanged = "current_changed",
Expand All @@ -28,10 +29,16 @@ interface EventMap {
}

/**
* This store provides access to the current and specific Voice Broadcast playbacks.
* This store manages VoiceBroadcastPlaybacks:
* - access the currently playing voice broadcast
* - ensures that only once broadcast is playing at a time
*/
export class VoiceBroadcastPlaybacksStore extends TypedEventEmitter<VoiceBroadcastPlaybacksStoreEvent, EventMap> {
export class VoiceBroadcastPlaybacksStore
extends TypedEventEmitter<VoiceBroadcastPlaybacksStoreEvent, EventMap>
implements IDestroyable {
private current: VoiceBroadcastPlayback | null;

/** Playbacks indexed by their info event id. */
private playbacks = new Map<string, VoiceBroadcastPlayback>();

public constructor() {
Expand All @@ -42,7 +49,7 @@ export class VoiceBroadcastPlaybacksStore extends TypedEventEmitter<VoiceBroadca
if (this.current === current) return;

this.current = current;
this.playbacks.set(current.infoEvent.getId(), current);
this.addPlayback(current);
this.emit(VoiceBroadcastPlaybacksStoreEvent.CurrentChanged, current);
}

Expand All @@ -54,12 +61,51 @@ export class VoiceBroadcastPlaybacksStore extends TypedEventEmitter<VoiceBroadca
const infoEventId = infoEvent.getId();

if (!this.playbacks.has(infoEventId)) {
this.playbacks.set(infoEventId, new VoiceBroadcastPlayback(infoEvent, client));
this.addPlayback(new VoiceBroadcastPlayback(infoEvent, client));
}

return this.playbacks.get(infoEventId);
}

private addPlayback(playback: VoiceBroadcastPlayback): void {
const infoEventId = playback.infoEvent.getId();

if (this.playbacks.has(infoEventId)) return;

this.playbacks.set(infoEventId, playback);
playback.on(VoiceBroadcastPlaybackEvent.StateChanged, this.onPlaybackStateChanged);
}

private onPlaybackStateChanged = (
state: VoiceBroadcastPlaybackState,
playback: VoiceBroadcastPlayback,
): void => {
if ([
VoiceBroadcastPlaybackState.Buffering,
VoiceBroadcastPlaybackState.Playing,
].includes(state)) {
this.pauseExcept(playback);
}
};

private pauseExcept(playbackNotToPause: VoiceBroadcastPlayback): void {
for (const playback of this.playbacks.values()) {
if (playback !== playbackNotToPause) {
playback.pause();
}
}
}

public destroy(): void {
this.removeAllListeners();

for (const playback of this.playbacks.values()) {
playback.off(VoiceBroadcastPlaybackEvent.StateChanged, this.onPlaybackStateChanged);
}

this.playbacks = new Map();
}

public static readonly _instance = new VoiceBroadcastPlaybacksStore();

/**
Expand Down
67 changes: 46 additions & 21 deletions test/voice-broadcast/models/VoiceBroadcastPlayback-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,25 @@ describe("VoiceBroadcastPlayback", () => {

const itShouldEmitAStateChangedEvent = (state: VoiceBroadcastPlaybackState) => {
it(`should emit a ${state} state changed event`, () => {
expect(mocked(onStateChanged)).toHaveBeenCalledWith(state);
expect(mocked(onStateChanged)).toHaveBeenCalledWith(state, playback);
});
};

const startPlayback = () => {
beforeEach(async () => {
await playback.start();
});
};

const pausePlayback = () => {
beforeEach(() => {
playback.pause();
});
};

const stopPlayback = () => {
beforeEach(() => {
playback.stop();
});
};

Expand Down Expand Up @@ -180,14 +198,28 @@ describe("VoiceBroadcastPlayback", () => {
});

describe("and calling start", () => {
beforeEach(async () => {
await playback.start();
});
startPlayback();

it("should be in buffering state", () => {
expect(playback.getState()).toBe(VoiceBroadcastPlaybackState.Buffering);
});

describe("and calling stop", () => {
stopPlayback();
itShouldSetTheStateTo(VoiceBroadcastPlaybackState.Stopped);

describe("and calling pause", () => {
pausePlayback();
// stopped voice broadcasts cannot be paused
itShouldSetTheStateTo(VoiceBroadcastPlaybackState.Stopped);
});
});

describe("and calling pause", () => {
pausePlayback();
itShouldSetTheStateTo(VoiceBroadcastPlaybackState.Paused);
});

describe("and receiving the first chunk", () => {
beforeEach(() => {
// TODO Michael W: Use RelationsHelper
Expand All @@ -212,9 +244,7 @@ describe("VoiceBroadcastPlayback", () => {
});

describe("and calling start", () => {
beforeEach(async () => {
await playback.start();
});
startPlayback();

it("should play the last chunk", () => {
// assert that the last chunk is played first
Expand Down Expand Up @@ -258,10 +288,7 @@ describe("VoiceBroadcastPlayback", () => {
});

describe("and calling start", () => {
beforeEach(async () => {
await playback.start();
});

startPlayback();
itShouldSetTheStateTo(VoiceBroadcastPlaybackState.Buffering);
});
});
Expand All @@ -278,9 +305,7 @@ describe("VoiceBroadcastPlayback", () => {
itShouldSetTheStateTo(VoiceBroadcastPlaybackState.Stopped);

describe("and calling start", () => {
beforeEach(async () => {
await playback.start();
});
startPlayback();

itShouldSetTheStateTo(VoiceBroadcastPlaybackState.Playing);

Expand All @@ -303,13 +328,15 @@ describe("VoiceBroadcastPlayback", () => {
});

describe("and calling pause", () => {
beforeEach(() => {
playback.pause();
});

pausePlayback();
itShouldSetTheStateTo(VoiceBroadcastPlaybackState.Paused);
itShouldEmitAStateChangedEvent(VoiceBroadcastPlaybackState.Paused);
});

describe("and calling stop", () => {
stopPlayback();
itShouldSetTheStateTo(VoiceBroadcastPlaybackState.Stopped);
});
});

describe("and calling toggle for the first time", () => {
Expand Down Expand Up @@ -337,9 +364,7 @@ describe("VoiceBroadcastPlayback", () => {
});

describe("and calling stop", () => {
beforeEach(() => {
playback.stop();
});
stopPlayback();

itShouldSetTheStateTo(VoiceBroadcastPlaybackState.Stopped);

Expand Down
Loading

0 comments on commit d702f4a

Please sign in to comment.