« get me outta code hell

http-music - Command-line music player + utils (not a server!)
about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/downloaders.js4
-rwxr-xr-xsrc/http-music.js18
-rw-r--r--src/loop-play.js48
-rw-r--r--todo.txt9
4 files changed, 59 insertions, 20 deletions
diff --git a/src/downloaders.js b/src/downloaders.js
index 1de6730..bc9cf15 100644
--- a/src/downloaders.js
+++ b/src/downloaders.js
@@ -33,13 +33,13 @@ function makeYouTubeDownloader() {
     const opts = [
       '--quiet',
       '--extract-audio',
-      '--audio-format', 'wav',
+      '--audio-format', 'mp3',
       '--output', tempDir + '/dl.%(ext)s',
       arg
     ]
 
     return promisifyProcess(spawn('youtube-dl', opts))
-      .then(() => tempDir + '/dl.wav')
+      .then(() => tempDir + '/dl.mp3')
   }
 }
 
diff --git a/src/http-music.js b/src/http-music.js
index bcd4672..a6c9479 100755
--- a/src/http-music.js
+++ b/src/http-music.js
@@ -284,7 +284,8 @@ Promise.resolve()
 
       const {
         promise: playPromise,
-        controller: play
+        playController: play,
+        downloadController
       } = loopPlay(picker, playOpts)
 
       // We're looking to gather standard input one keystroke at a time.
@@ -335,7 +336,20 @@ Promise.resolve()
             "(Press I for track info!)"
           )
 
-          play.skipCurrent()
+          play.skip()
+        }
+
+        if (Buffer.from([0x7f]).equals(data)) {
+          clearConsoleLine()
+          console.log(
+            "Skipping the track that's up next. " +
+            "(Press I for track info!)"
+          )
+
+          // TODO: It would be nice to have this as a method of
+          // PlayController.
+          downloadController.cancel()
+          play.startNextDownload()
         }
 
         if (
diff --git a/src/loop-play.js b/src/loop-play.js
index aca518a..8ca4ae4 100644
--- a/src/loop-play.js
+++ b/src/loop-play.js
@@ -27,7 +27,7 @@ class DownloadController extends EventEmitter {
     // which would void the result of the old download.)
 
     let canceled = false
-    this.once('skipped', () => {
+    this.once('canceled', () => {
       canceled = true
     })
 
@@ -43,7 +43,7 @@ class DownloadController extends EventEmitter {
     // waitForDownload promises, though -- you'll need to start
     // a new download to resolve those.
 
-    this.emit('skipped')
+    this.emit('canceled')
   }
 }
 
@@ -57,39 +57,47 @@ class PlayController {
   }
 
   async loopPlay() {
-    let next
+    let nextFile
+
+    // Null would imply there's NO up-next track, but really
+    // we just haven't set it yet.
+    this.nextTrack = undefined
 
     let downloadNext = () => {
-      if (this.startNextDownload() !== null) {
-        return this.downloadController.waitForDownload().then(_next => {
-          next = _next
+      this.nextTrack = this.startNextDownload()
+      if (this.nextTrack !== null) {
+        return this.downloadController.waitForDownload().then(file => {
+          nextFile = file
         })
       } else {
-        next = null
+        nextFile = null
         return Promise.resolve()
       }
     }
 
     await downloadNext()
 
-    while (next) {
+    while (this.nextTrack) {
+      this.currentTrack = this.nextTrack
       await Promise.all([
-        this.playFile(next),
+        this.playFile(nextFile),
         downloadNext()
       ])
     }
   }
 
   startNextDownload() {
-    // TODO: Is there a method for this?
     // TODO: Handle/test null return from picker.
-    const arg = this.picker()[1]
+    const picked = this.picker()
 
-    if (arg === null) {
+    if (picked === null) {
       return null
     } else {
+      // TODO: Is there a function for this?
+      const arg = picked[1]
       const downloader = getDownloaderFor(arg)
       this.downloadController.download(downloader, arg)
+      return picked
     }
   }
 
@@ -170,7 +178,7 @@ class PlayController {
     })
   }
 
-  skipCurrent() {
+  skip() {
     this.kill()
   }
 
@@ -215,11 +223,18 @@ class PlayController {
 
   logTrackInfo() {
     if (this.currentTrack) {
-      const [ curTitle, curArg ] = this.currentTrack
-      console.log(`Playing: \x1b[1m${curTitle} \x1b[2m${curArg}\x1b[0m`)
+      const [ title, arg ] = this.currentTrack
+      console.log(`Playing: \x1b[1m${title} \x1b[2m${arg}\x1b[0m`)
     } else {
       console.log("No song currently playing.")
     }
+
+    if (this.nextTrack) {
+      const [ title, arg ] = this.nextTrack
+      console.log(`Up next: \x1b[1m${title} \x1b[2m${arg}\x1b[0m`)
+    } else {
+      console.log("No song up next.")
+    }
   }
 }
 
@@ -237,6 +252,7 @@ module.exports = function loopPlay(picker, playArgs = []) {
 
   return {
     promise,
-    controller: playController
+    playController,
+    downloadController
   }
 }
diff --git a/todo.txt b/todo.txt
index ba57347..39f1517 100644
--- a/todo.txt
+++ b/todo.txt
@@ -174,3 +174,12 @@ TODO: Figure out the horrible, evil cause of the max listeners warning
       Skipping tracks still leads to issue. Wait for them to start playing
       before skipping, though.
 
+TODO: Something's requesting avprobe, and I'm not sure why.
+      (While playing flora.json/YouTube videos.) Perhaps
+      it's youtube-dl..?
+
+TODO: Re-implement skip.
+      (Done!)
+
+TODO: Re-implement skip and view up-next track.
+      (Done!)