Clean up AudioPlayer internals, remove the concept of multiple "temporary" streams

This commit is contained in:
Amish Shah
2017-04-12 20:12:51 +01:00
parent d0c2b84659
commit 9eaf1456b2

View File

@@ -36,6 +36,7 @@ class AudioPlayer extends EventEmitter {
*/
this.opusEncoder = OpusEncoders.fetch();
this.streams = new Collection();
this.currentStream = {};
this.streamingData = {
channels: 2,
count: 0,
@@ -47,7 +48,7 @@ class AudioPlayer extends EventEmitter {
}
get currentTranscoder() {
return (this.streams.last() || {}).transcoder;
return this.currentStream.transcoder;
}
/**
@@ -56,29 +57,19 @@ class AudioPlayer extends EventEmitter {
* @readonly
*/
get currentDispatcher() {
return this.streams.size > 0 ? this.streams.last().dispatcher || null : null;
return this.currentStream.dispatcher;
}
destroy() {
if (this.opusEncoder) this.opusEncoder.destroy();
}
destroyStream(stream) {
const data = this.streams.get(stream);
if (!data) return;
const transcoder = data.transcoder;
const dispatcher = data.dispatcher;
destroyCurrentStream() {
const transcoder = this.currentTranscoder;
const dispatcher = this.currentDispatcher;
if (transcoder) transcoder.kill();
if (dispatcher) dispatcher.destroy('end');
this.streams.delete(stream);
}
destroyAllStreams(except) {
for (const stream of this.streams.keys()) {
if (except === stream) continue;
if (except === true && this.streams.get(stream) === this.streams.last()) continue;
this.destroyStream(stream);
}
this.currentStream = {};
}
playUnknownStream(stream, { seek = 0, volume = 1, passes = 1 } = {}) {
@@ -89,30 +80,46 @@ class AudioPlayer extends EventEmitter {
media: stream,
ffmpegArguments: ffmpegArguments.concat(['-ss', String(seek)]),
});
this.streams.set(transcoder.output, { transcoder, input: stream });
this.destroyCurrentStream();
this.currentStream = {
transcoder: transcoder,
output: transcoder.output,
input: stream,
};
transcoder.on('error', e => {
this.destroyStream(stream);
this.destroyCurrentStream();
if (this.listenerCount('error') > 0) this.emit('error', e);
this.emit('warn', `prism transcoder error - ${e}`);
});
return this.playPCMStream(transcoder.output, options);
return this.playPCMStream(transcoder.output, options, true);
}
playPCMStream(stream, { seek = 0, volume = 1, passes = 1 } = {}) {
playPCMStream(stream, { seek = 0, volume = 1, passes = 1 } = {}, fromUnknown = false) {
OpusEncoders.guaranteeOpusEngine();
const options = { seek, volume, passes };
this.destroyAllStreams(stream);
const dispatcher = this.createDispatcher(stream, options);
if (!this.streams.has(stream)) this.streams.set(stream, { dispatcher, input: stream });
this.streams.get(stream).dispatcher = dispatcher;
if (fromUnknown) {
this.currentStream.dispatcher = dispatcher;
} else {
this.destroyCurrentStream();
this.currentStream = {
dispatcher,
input: stream,
output: stream,
};
}
return dispatcher;
}
playOpusStream(stream, { seek = 0, passes = 1 } = {}) {
const options = { seek, passes, opus: true };
this.destroyAllStreams(stream);
this.destroyCurrentStream();
const dispatcher = this.createDispatcher(stream, options);
this.streams.set(stream, { dispatcher, input: stream });
this.currentStream = {
dispatcher,
input: stream,
output: stream,
};
return dispatcher;
}
@@ -120,15 +127,20 @@ class AudioPlayer extends EventEmitter {
const options = { volume, passes };
this.destroyAllStreams();
const dispatcher = this.createDispatcher(broadcast, options);
this.streams.set(broadcast, { dispatcher, input: broadcast });
this.currentStream = {
dispatcher,
broadcast,
input: broadcast,
output: broadcast,
};
broadcast.registerDispatcher(dispatcher);
return dispatcher;
}
createDispatcher(stream, options) {
const dispatcher = new StreamDispatcher(this, stream, options);
dispatcher.on('end', () => this.destroyStream(stream));
dispatcher.on('error', () => this.destroyStream(stream));
dispatcher.on('end', () => this.destroyCurrentStream());
dispatcher.on('error', () => this.destroyCurrentStream());
dispatcher.on('speaking', value => this.voiceConnection.setSpeaking(value));
return dispatcher;
}