/****************** * Offline player is for special screens, like the error * screen or the Flex Fallback screen. * * This module has to follow the program-player contract. * Asynchronous call to return a stream. Then the stream * can be used to play the program. **/ const EventEmitter = require('events'); const FFMPEG = require('./ffmpeg') class OfflinePlayer { constructor(error, context) { this.context = context; this.error = error; if (context.isLoading === true) { context.channel = JSON.parse( JSON.stringify(context.channel) ); context.channel.offlinePicture = `http://localhost:${process.env.PORT}/images/loading-screen.png`; context.channel.offlineSoundtrack = undefined; } if (context.isInterlude === true) { context.channel = JSON.parse( JSON.stringify(context.channel) ); context.channel.offlinePicture = `http://localhost:${process.env.PORT}/images/black.png`; context.channel.offlineSoundtrack = undefined; } this.ffmpeg = new FFMPEG(context.ffmpegSettings, context.channel); this.ffmpeg.setAudioOnly(this.context.audioOnly); } cleanUp() { this.ffmpeg.kill(); } async play(outStream) { try { let emitter = new EventEmitter(); let ffmpeg = this.ffmpeg; let lineupItem = this.context.lineupItem; let duration = lineupItem.streamDuration - lineupItem.start; let ff; if (this.error) { ff = await ffmpeg.spawnError(duration); } else { ff = await ffmpeg.spawnOffline(duration); } ff.pipe(outStream, {'end':false} ); ffmpeg.on('end', () => { emitter.emit('end'); }); ffmpeg.on('close', () => { emitter.emit('close'); }); ffmpeg.on('error', async (err) => { //wish this code wasn't repeated. if (! this.error ) { console.log("Replacing failed stream with error stream"); ff.unpipe(outStream); ffmpeg.removeAllListeners('data'); ffmpeg.removeAllListeners('end'); ffmpeg.removeAllListeners('error'); ffmpeg.removeAllListeners('close'); ffmpeg = new FFMPEG(this.context.ffmpegSettings, this.context.channel); // Set the transcoder options ffmpeg.setAudioOnly(this.context.audioOnly); ffmpeg.on('close', () => { emitter.emit('close'); }); ffmpeg.on('end', () => { emitter.emit('end'); }); ffmpeg.on('error', (err) => { emitter.emit('error', err ); }); ff = await ffmpeg.spawnError('oops', 'oops', Math.min(duration, 60000) ); ff.pipe(outStream); } else { emitter.emit('error', err); } }); return emitter; } catch(err) { if (err instanceof Error) { throw err; } else { throw Error("Error when attempting to play offline screen: " + JSON.stringify(err) ); } } } } module.exports = OfflinePlayer;