« 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/loop-play.js95
-rwxr-xr-xsrc/play.js2
-rw-r--r--todo.txt1
3 files changed, 58 insertions, 40 deletions
diff --git a/src/loop-play.js b/src/loop-play.js
index 4ea73c7..9d87423 100644
--- a/src/loop-play.js
+++ b/src/loop-play.js
@@ -1,5 +1,11 @@
 // This isn't actually the code for the `play` command! That's in `play.js`.
 
+// NOTE TO FUTURE SELF AND READERS:
+// Please be careful to discern the target of methods such as waitForDownload.
+// DownloadController and PlayController are messes and have lots of functions
+// of the same name but completely different purposes. (Also keep an eye out
+// for similarly/identically-named events between the two classes.)
+
 'use strict'
 
 const { spawn } = require('child_process')
@@ -83,15 +89,16 @@ class DownloadController extends EventEmitter {
   }
 }
 
-class PlayController {
+class PlayController extends EventEmitter {
   constructor(picker, downloadController) {
+    super()
+
     this.picker = picker
     this.downloadController = downloadController
     this.playOpts = []
     this.playerCommand = null
     this.currentTrack = null
     this.process = null
-    this.downloadProcess = null
   }
 
   async loopPlay() {
@@ -99,66 +106,76 @@ class PlayController {
     // set it yet.
     this.nextTrack = undefined
 
-    await (this.downloadProcess = this.downlold())
+    this.startNextDownload()
+
+    await this.waitForDownload()
 
     while (this.nextTrack) {
       this.currentTrack = this.nextTrack
 
-      this.downlold()
+      this.startNextDownload()
 
-      // Maybe Promise.all isn't good here? Rather, wait for play-file then
-      // downlold? Or - we should have some "downlolder" promise, set by
-      // downlold.
       if (this.nextFile) {
         await this.playFile(this.nextFile)
       }
 
-      await this.downloadProcess
+      await this.waitForDownload()
     }
   }
 
-  async downlold() {
-    this.nextTrack = this.startNextDownload()
-
-    try {
-      this.nextFile = await this.downloadController.waitForDownload()
-    } catch(err) {
-      console.warn(
-        "\x1b[31mFailed to download (or convert) track \x1b[1m" +
-        getItemPathString(this.nextTrack) + "\x1b[0m"
-      )
-
-      await (this.downloadProcess = this.downlold())
-    }
+  waitForDownload() {
+    return new Promise(resolve => {
+      if (this.isDownloading) {
+        this.once('downloaded', () => resolve())
+      } else {
+        resolve()
+      }
+    })
   }
 
   startNextDownload() {
-    // TODO: Handle/test null return from picker.
+    this.isDownloading = true
+
     const picked = this.picker()
+    this.nextTrack = picked
 
-    if (picked === null) {
+    if (!picked) {
       return null
-    } else {
-      let downloader
+    }
 
-      if (picked.downloader) {
-        downloader = downloadersByName[picked.downloader]()
+    let downloader
 
-        if (!downloader) {
-          console.error(
-            `Invalid downloader for track ${picked.name}:`, downloader
-          )
+    if (picked.downloader) {
+      downloader = downloadersByName[picked.downloader]()
 
-          return false
-        }
-      } else {
-        downloader = getDownloaderFor(picked.downloaderArg)
-      }
+      if (!downloader) {
+        console.error(
+          `Invalid downloader for track ${picked.name}:`, downloader
+        )
 
-      downloader = makeConverterDownloader(downloader, 'wav')
-      this.downloadController.download(downloader, picked.downloaderArg)
-      return picked
+        return false
+      }
+    } else {
+      downloader = getDownloaderFor(picked.downloaderArg)
     }
+
+    downloader = makeConverterDownloader(downloader, 'wav')
+    this.downloadController.download(downloader, picked.downloaderArg)
+
+    this.downloadController.waitForDownload()
+      .then(file => {
+        this.isDownloading = false
+        this.nextFile = file
+        this.emit('downloaded')
+      })
+      .catch(() => {
+        console.warn(
+          "\x1b[31mFailed to download (or convert) track \x1b[1m" +
+          getItemPathString(this.nextTrack) + "\x1b[0m"
+        )
+
+        this.startNextDownload()
+      })
   }
 
   playFile(file) {
diff --git a/src/play.js b/src/play.js
index 08a33cb..b2c04e9 100755
--- a/src/play.js
+++ b/src/play.js
@@ -409,7 +409,7 @@ async function main(args) {
         // TODO: It would be nice to have this as a method of
         // PlayController.
         // Double TODO: This doesn't actually work!!
-        play.downloadProcess = play.downlold()
+        play.startNextDownload()
       }
 
       if (
diff --git a/todo.txt b/todo.txt
index f4bd4fd..e59b512 100644
--- a/todo.txt
+++ b/todo.txt
@@ -220,6 +220,7 @@ TODO: Figure out how man pages work, and update the syntax in those files.
       more consistent, and figure out when to use '\-' or '-'.
 
 TODO: Fix skip up-next..!
+      (Done!)
 
 TODO: Make iTunes crawler prefer album artist over artist.
       (Done!)