diff --git a/classes/AudioBuffer.js b/classes/AudioBuffer.js index 42da365..ff2d321 100644 --- a/classes/AudioBuffer.js +++ b/classes/AudioBuffer.js @@ -6,24 +6,27 @@ class StreamBuffer extends EventEmitter { constructor(stream, settings) { super(); + this.size = settings.size; this.times = { start: Date.now() }; this.playback = { paused: false, - progress: 0, hiccups: 0 }; this.#setupBuffer(settings?.threshold); this.#setupStreams(stream, settings?.audio); } - resume() { + play() { this.#writeBufferedChunk(4096, true); } pause() { this.playback.paused = true; + this.threshold.announced = false; + this.streams.buffer._readableState.buffer.clear(); + this.streams.buffer._readableState.length = 0; } stop() { @@ -31,7 +34,7 @@ class StreamBuffer extends EventEmitter { } getProgress() { - return this.playback.progress; + return this.streams.output?.bytesWritten || 0; } getHiccups() { @@ -189,12 +192,15 @@ class StreamBuffer extends EventEmitter { }); this.streams.output.on('drain', () => { this.times.drained = Date.now(); - logger.debug('output stream is drained, file should be completely written to the speaker after ' + (this.times.drained - this.times.start) + 'ms'); + logger.debug('output stream is drained, wrote ' + this.streams.output.bytesWritten + '/' + this.size + ' bytes to the speaker after ' + (this.times.drained - this.times.start) + 'ms'); + if (this.streams.output.bytesWritten < this.size) { + return; + } this.#destroy(); }); - this.streams.output.on('progress', (progress) => { - this.playback.progress = progress; - }); + // this.streams.output.on('progress', (progress) => { + // this.playback.progress = progress; + // }); this.streams.output.on('hiccup', () => { this.playback.hiccups++; logger.warn('hiccup ' + this.playback.hiccups + ' detected...'); diff --git a/classes/Audiostream.js b/classes/Audiostream.js index 7a1f2fd..37ddef6 100644 --- a/classes/Audiostream.js +++ b/classes/Audiostream.js @@ -37,11 +37,15 @@ class Audiostream { logger.debug('handling event \'audio:initialize\'...'); this.#initialize(data); }); - this.eventParser.on(constants.AUDIO_PLAY, (data) => { + this.eventParser.on(constants.AUDIO_PLAY, () => { logger.debug('handling event \'' + constants.AUDIO_PLAY + '\'...'); global.player.play(); }); - this.eventParser.on(constants.AUDIO_PAUSE, (data) => { + this.eventParser.on(constants.AUDIO_RESUME, () => { + logger.debug('handling event \'' + constants.AUDIO_RESUME + '\'...'); + global.player.resume(); + }); + this.eventParser.on(constants.AUDIO_PAUSE, () => { logger.debug('handling event \'' + constants.AUDIO_PAUSE + '\'...'); global.player.pause(); }); diff --git a/classes/Player.js b/classes/Player.js index 30d7fc7..055bed4 100644 --- a/classes/Player.js +++ b/classes/Player.js @@ -11,24 +11,24 @@ class Player extends EventEmitter { async prepare(stream, settings) { logger.debug('preparing audio player...'); - this.#reset(); - this.audiobuffer = new AudioBuffer(stream, settings); + this.settings = settings; + this.audiobuffer = new AudioBuffer(stream, this.settings); this.audiobuffer.on(constants.THRESHOLD, () => { this.#setState(constants.READY); }); - this.audiobuffer.on('close', () => { - this.#setState(constants.STOPPED); - }); this.audiobuffer.on('play', () => { this.#setState(constants.PLAYING); }); this.audiobuffer.on('pause', () => { this.#setState(constants.PAUSED); - }) + }); + this.audiobuffer.on('close', () => { + this.#setState(constants.STOPPED); + }); } play() { - this.audiobuffer.resume(); + this.audiobuffer.play(); } pause() { @@ -37,8 +37,6 @@ class Player extends EventEmitter { async stop() { this.audiobuffer.stop(); - this.#reset(); - this.#setState(constants.STOPPED); } isReady() { @@ -62,28 +60,21 @@ class Player extends EventEmitter { } getProgress() { - return this.audiobuffer?.getProgress(); + return this.audiobuffer?.getProgress() || 0; } #setState(state, data) { - if (this.state === state) { - return; - } this.state = state; logger.debug('setting state of audio player to \'' + state + '\'...'); - if (this.events.includes(state)) { - return; - } + // if (this.events.includes(state)) { + // return; + // } logger.debug('emitting state \'' + state + '\' of audio player...'); this.emit(this.state, { data: data }); this.emit(constants.STATECHANGE, { state: this.state, progress: this.getProgress() }); this.events.push(state); } - #reset() { - this.events = []; - } - } module.exports = Player; \ No newline at end of file diff --git a/libs/constants.js b/libs/constants.js index ef66372..96ad9ff 100644 --- a/libs/constants.js +++ b/libs/constants.js @@ -15,6 +15,7 @@ module.exports = { PROGRESS: 'progress', AUDIO_PLAY: 'audio:play', + AUDIO_RESUME: 'audio:resume', AUDIO_PAUSE: 'audio:pause', AUDIO_STOP: 'audio:stop', AUDIO_STATE: 'audio:state', diff --git a/libs/speaker/index.js b/libs/speaker/index.js index 857a316..350d0af 100644 --- a/libs/speaker/index.js +++ b/libs/speaker/index.js @@ -51,7 +51,7 @@ class Speaker extends Writable { this.on('unpipe', this._unpipe) // total bytes written - this.bytesWritten = 0; + this.bytesWritten = 0 } /** @@ -206,9 +206,8 @@ class Speaker extends Writable { } const onwrite = (r) => { - this.bytesWritten += r; - this.emit('written', r); - this.emit('progress', this.bytesWritten); + this.bytesWritten += r + this.emit('written', r) debug('wrote %o bytes', r) if (r === 0) { this.emit('hiccup');