« get me outta code hell

past 3 second threshold, (P) to seek to start - mtui - Music Text User Interface - user-friendly command line music player
about summary refs log tree commit diff
path: root/players.js
diff options
context:
space:
mode:
author(quasar) nebula <towerofnix@gmail.com>2021-07-17 20:09:09 -0300
committer(quasar) nebula <towerofnix@gmail.com>2021-07-17 20:09:09 -0300
commit7af31d6ccb2d1b0c47c0bbb60a7e51c64bb01bf1 (patch)
tree57f10337ee6a22155862e65086feaf9f51b69fe9 /players.js
parent382d5afc7e2ac24f67b7c891328b8b9bb7e91058 (diff)
past 3 second threshold, (P) to seek to start
Diffstat (limited to 'players.js')
-rw-r--r--players.js38
1 files changed, 38 insertions, 0 deletions
diff --git a/players.js b/players.js
index b41ce0c..c707494 100644
--- a/players.js
+++ b/players.js
@@ -41,6 +41,7 @@ class Player extends EventEmitter {
   seekAhead(secs) {}
   seekBack(secs) {}
   seekTo(timeInSecs) {}
+  seekToStart() {}
   volUp(amount) {}
   volDown(amount) {}
   setVolume(value) {}
@@ -197,6 +198,10 @@ module.exports.ControllableMPVPlayer = class extends module.exports.MPVPlayer {
     this.sendCommand('seek', timeInSecs, 'absolute')
   }
 
+  seekToStart() {
+    this.seekTo(0)
+  }
+
   volUp(amount) {
     this.setVolume(this.volume + amount)
   }
@@ -261,6 +266,8 @@ module.exports.SoXPlayer = class extends Player {
     // You don't get keyboard controls such as seeking or volume adjusting
     // with SoX, though.
 
+    this._file = file
+
     this.process = spawn('play', [file].concat(
       this.processOptions,
       startTime ? ['trim', startTime] : []
@@ -313,8 +320,39 @@ module.exports.SoXPlayer = class extends Player {
 
     return new Promise(resolve => {
       this.process.on('close', () => resolve())
+    }).then(() => {
+      if (this._restartPromise) {
+        const p = this._restartPromise
+        this._restartPromise = null
+        return p
+      }
     })
   }
+
+  async seekToStart() {
+    // SoX doesn't support a command interface to interact while playback is
+    // ongoing. However, we can simulate seeking to the start by restarting
+    // playback altogether. We just need to be careful not to resolve the
+    // original playback promise before the new one is complete!
+
+    if (!this._file) {
+      return
+    }
+
+    let resolve = null
+    let reject = null
+
+    // The original call of playFile() will yield control to this promise, which
+    // we bind to the resolve/reject of a new call to playFile().
+    this._restartPromise = new Promise((res, rej) => {
+      resolve = res
+      reject = rej
+    })
+
+    await this.kill()
+
+    this.playFile(this._file).then(resolve, reject)
+  }
 }
 
 module.exports.getPlayer = async function(name = null, options = []) {