Skip to content

Commit 2ab42df

Browse files
authored
Fix audio player seek bar position (#31127)
* fix(audio): stop clock when the source audio reaches the end * test(audio): add test for playback when audio source ended
1 parent a9993ae commit 2ab42df

2 files changed

Lines changed: 24 additions & 3 deletions

File tree

src/audio/Playback.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ export class Playback extends EventEmitter implements IDestroyable, PlaybackInte
202202
private onPlaybackEnd = async (): Promise<void> => {
203203
await this.context.suspend();
204204
this.emit(PlaybackState.Stopped);
205+
this.clock.flagStop();
205206
};
206207

207208
public async play(): Promise<void> {
@@ -248,9 +249,8 @@ export class Playback extends EventEmitter implements IDestroyable, PlaybackInte
248249
this.emit(PlaybackState.Paused);
249250
}
250251

251-
public async stop(): Promise<void> {
252-
await this.onPlaybackEnd();
253-
this.clock.flagStop();
252+
public stop(): Promise<void> {
253+
return this.onPlaybackEnd();
254254
}
255255

256256
public async toggle(): Promise<void> {

test/unit-tests/audio/Playback-test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ describe("Playback", () => {
4646

4747
beforeEach(() => {
4848
jest.spyOn(logger, "error").mockRestore();
49+
mockAudioBufferSourceNode.addEventListener.mockClear();
4950
mockAudioBuffer.getChannelData.mockClear().mockReturnValue(mockChannelData);
5051
mockAudioContext.decodeAudioData.mockReset().mockResolvedValue(mockAudioBuffer);
5152
mockAudioContext.resume.mockClear().mockResolvedValue(undefined);
@@ -105,6 +106,26 @@ describe("Playback", () => {
105106
expect(playback.currentState).toEqual(PlaybackState.Stopped);
106107
});
107108

109+
it("stop when audio source ended", async () => {
110+
const buffer = new ArrayBuffer(8);
111+
const playback = new Playback(buffer);
112+
await playback.prepare();
113+
await playback.play();
114+
115+
// Simulate the audio source ending by calling the 'ended' event listener
116+
const endedListener = mockAudioBufferSourceNode.addEventListener.mock.calls.find(
117+
(call) => call[0] === "ended",
118+
)[1];
119+
await endedListener();
120+
121+
// AudioContext should be suspended
122+
expect(mockAudioContext.suspend).toHaveBeenCalled();
123+
// Playback state should be Stopped
124+
expect(playback.currentState).toEqual(PlaybackState.Stopped);
125+
// Clock should be reset to 0
126+
expect(playback.timeSeconds).toEqual(0);
127+
});
128+
108129
describe("prepare()", () => {
109130
it("decodes audio data when not greater than 5mb", async () => {
110131
const buffer = new ArrayBuffer(8);

0 commit comments

Comments
 (0)