From 05cbc5d6d5b3290fd0b98061c27760467dce17ec Mon Sep 17 00:00:00 2001 From: liam4 Date: Mon, 12 Jun 2017 08:18:53 -0300 Subject: Spooks and baddies with ffprobe --- src/loop-play.js | 59 +++++++++++++++++++++++++++++++++--------------- src/promisify-process.js | 8 ++++--- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/loop-play.js b/src/loop-play.js index ac666a3..d22d55d 100644 --- a/src/loop-play.js +++ b/src/loop-play.js @@ -62,27 +62,57 @@ class DownloadController extends EventEmitter { // It's up to the downloader to decide what to do with it. const [ title, downloaderArg ] = picked + // The "from" file is downloaded by the downloader (given in the + // DownloadController constructor) using the downloader argument we just + // got. + const fromFile = await this.downloader(downloaderArg) + + // Before we convert the file, we'll check if it's already an audio file. + // This goes on the assumption that if avprobe understands a file, play + // also does; which is probably true almost all the time. + let probeCode + + try { + // Well, lovely. avprobe ALWAYS outputs "# avprobe output" - even if + // its loglevel is set to silent! Blasphemy, but whatever. We're forced + // to not pipe to stdout (which we do by passing false to + // promisifyProcess). + await promisifyProcess(spawn('avprobe', [fromFile]), false) + } catch(errorCode) { + probeCode = errorCode + } + + // We'll use this wav file later, to actually play the track. + if (probeCode > 0) { + this.wavFile = await this.convert(picked, fromFile) + } else { + this.wavFile = fromFile + } + + // If this download was destroyed, we quit now; we don't want to emit that + // the download was finished if the finished download was the destroyed + // one! + if (wasDestroyed) { + return + } + + this.emit('downloadFinished') + } + + async convert(picked, fromFile) { // The "to" file is simply a WAV file. We give this WAV file a specific // name - the title of the track we got earlier, sanitized to be file-safe // - so that when `play` outputs the name of the song, it's obvious to the // user what's being played. const tempDir = tempy.directory() - const to = tempDir + `/.${sanitize(title)}.wav` - - // We'll use this wav file later, to actually play the track. - this.wavFile = to - - // The "from" file is downloaded by the downloader (given in the - // DownloadController constructor) using the downloader argument we just - // got. - const from = await this.downloader(downloaderArg) + const toFile = tempDir + `/.${sanitize(title)}.wav` // Now that we've got the `to` and `from` file names, we can actually do // the convertion. We don't want any output from `avconv` at all, since the // output of `play` will usually be displayed while `avconv` is running, // so we pass `-loglevel quiet` into `avconv`. const convertProcess = spawn('avconv', [ - '-loglevel', 'quiet', '-i', from, to + '-loglevel', 'quiet', '-i', fromFile, toFile ]) // We store the convert process so that we can kill it before it finishes, @@ -115,14 +145,7 @@ class DownloadController extends EventEmitter { } } - // If this download was destroyed, we quit now; we don't want to emit that - // the download was finished if the finished download was the destroyed - // one! - if (wasDestroyed) { - return - } - - this.emit('downloadFinished') + return to } skipUpNext() { diff --git a/src/promisify-process.js b/src/promisify-process.js index d330055..58a8597 100644 --- a/src/promisify-process.js +++ b/src/promisify-process.js @@ -2,14 +2,16 @@ const { Writable } = require('stream') -module.exports = function promisifyProcess(proc) { +module.exports = function promisifyProcess(proc, showLogging = true) { // Takes a process (from the child_process module) and returns a promise // that resolves when the process exits (or rejects, if the exit code is // non-zero). return new Promise((resolve, reject) => { - proc.stdout.pipe(process.stdout) - proc.stderr.pipe(process.stderr) + if (showLogging) { + proc.stdout.pipe(process.stdout) + proc.stderr.pipe(process.stderr) + } proc.on('exit', code => { if (code === 0) { -- cgit 1.3.0-6-gf8a5