« get me outta code hell

mtui - Music Text User Interface - user-friendly command line music player
about summary refs log tree commit diff
path: root/backend.js
diff options
context:
space:
mode:
Diffstat (limited to 'backend.js')
-rw-r--r--backend.js101
1 files changed, 89 insertions, 12 deletions
diff --git a/backend.js b/backend.js
index ad13127..349d7f3 100644
--- a/backend.js
+++ b/backend.js
@@ -8,6 +8,7 @@ const { getMetadataReaderFor } = require('./metadata-readers')
 const { getPlayer } = require('./players')
 const RecordStore = require('./record-store')
 const os = require('os')
+const shortid = require('shortid')
 
 const {
   getTimeStringsFromSec,
@@ -62,6 +63,8 @@ class QueuePlayer extends EventEmitter {
   }) {
     super()
 
+    this.id = shortid.generate()
+
     this.player = null
     this.playingTrack = null
     this.queueGrouplike = {name: 'Queue', isTheQueue: true, items: []}
@@ -69,6 +72,10 @@ class QueuePlayer extends EventEmitter {
     this.loopQueueAtEnd = false
     this.playedTrackToEnd = false
     this.timeData = null
+    this.time = null
+
+    this.alwaysStartPaused = false
+    this.waitWhenDonePlaying = false
 
     this.getPlayer = getPlayer
     this.getRecordFor = getRecordFor
@@ -86,6 +93,7 @@ class QueuePlayer extends EventEmitter {
     this.player.on('printStatusLine', data => {
       if (this.playingTrack) {
         this.timeData = data
+        this.time = data.curSecTotal
         this.emit('received time data', data, this)
       }
     })
@@ -161,6 +169,7 @@ class QueuePlayer extends EventEmitter {
     }
 
     recursivelyAddTracks(topItem)
+    this.emit('queue', topItem, afterItem, {movePlayingTrack})
     this.emitQueueUpdated()
 
     // This is the first new track, if a group was queued.
@@ -169,9 +178,12 @@ class QueuePlayer extends EventEmitter {
     return newTrack
   }
 
-  distributeQueue(grouplike, {how = 'evenly', rangeEnd = 'end-of-queue'}) {
-    if (isTrack(grouplike)) {
-      grouplike = {items: [grouplike]}
+  distributeQueue(topItem, {how = 'evenly', rangeEnd = 'end-of-queue'} = {}) {
+    let grouplike
+    if (isTrack(topItem)) {
+      grouplike = {items: [topItem]}
+    } else {
+      grouplike = topItem
     }
 
     const { items } = this.queueGrouplike
@@ -237,6 +249,7 @@ class QueuePlayer extends EventEmitter {
       }
     }
 
+    this.emit('distribute-queue', topItem, {how, rangeEnd})
     this.emitQueueUpdated()
   }
 
@@ -281,11 +294,17 @@ class QueuePlayer extends EventEmitter {
     }
 
     recursivelyUnqueueTracks(topItem)
+    this.emit('unqueue', topItem)
     this.emitQueueUpdated()
 
     return focusItem
   }
 
+  replaceAllItems(newItems) {
+    this.queueGrouplike.items = newItems
+    this.emitQueueUpdated()
+  }
+
   clearQueuePast(track) {
     const { items } = this.queueGrouplike
     const index = items.indexOf(track) + 1
@@ -298,6 +317,7 @@ class QueuePlayer extends EventEmitter {
       items.splice(index)
     }
 
+    this.emit('clear-queue-past', track)
     this.emitQueueUpdated()
   }
 
@@ -314,6 +334,7 @@ class QueuePlayer extends EventEmitter {
       items.splice(startIndex, endIndex - startIndex)
     }
 
+    this.emit('clear-queue-up-to', track)
     this.emitQueueUpdated()
   }
 
@@ -344,6 +365,7 @@ class QueuePlayer extends EventEmitter {
     const remainingItems = queue.items.slice(index)
     const newItems = initialItems.concat(shuffleArray(remainingItems))
     queue.items = newItems
+    this.emit('shuffle-queue')
     this.emitQueueUpdated()
   }
 
@@ -352,6 +374,7 @@ class QueuePlayer extends EventEmitter {
     // the track that's currently playing).
     this.queueGrouplike.items = this.queueGrouplike.items
       .filter(item => item === this.playingTrack)
+    this.emit('clear-queue')
     this.emitQueueUpdated()
   }
 
@@ -368,7 +391,7 @@ class QueuePlayer extends EventEmitter {
   }
 
 
-  async play(item) {
+  async play(item, forceStartPaused) {
     if (this.player === null) {
       throw new Error('Attempted to play before a player was loaded')
     }
@@ -414,11 +437,15 @@ class QueuePlayer extends EventEmitter {
       }
 
       this.timeData = null
+      this.time = null
       this.playingTrack = item
+      this.emit('playing details', this.playingTrack, oldTrack, this)
       this.emit('playing', this.playingTrack, oldTrack, this)
 
       await this.player.kill()
-      if (this.playedTrackToEnd) {
+      if (this.alwaysStartPaused || forceStartPaused) {
+        this.player.setPause(true)
+      } else if (this.playedTrackToEnd) {
         this.player.setPause(this.pauseNextTrack)
         this.pauseNextTrack = false
         this.playedTrackToEnd = false
@@ -433,11 +460,14 @@ class QueuePlayer extends EventEmitter {
 
     if (playingThisTrack) {
       this.playedTrackToEnd = true
-      if (!this.playNext(item)) {
-        if (this.loopQueueAtEnd) {
-          this.playFirst()
-        } else {
-          this.clearPlayingTrack()
+      this.emit('done playing', this.playingTrack)
+      if (!this.waitWhenDonePlaying) {
+        if (!this.playNext(item)) {
+          if (this.loopQueueAtEnd) {
+            this.playFirst()
+          } else {
+            this.clearPlayingTrack()
+          }
         }
       }
     }
@@ -515,6 +545,8 @@ class QueuePlayer extends EventEmitter {
       const oldTrack = this.playingTrack
       this.playingTrack = null
       this.timeData = null
+      this.time = null
+      this.emit('playing details', null, oldTrack, this)
       this.emit('playing', null, oldTrack, this)
     }
   }
@@ -524,51 +556,73 @@ class QueuePlayer extends EventEmitter {
   }
 
   seekAhead(seconds) {
+    this.time += seconds
     this.player.seekAhead(seconds)
+    this.emit('seek-ahead', +seconds)
   }
 
   seekBack(seconds) {
+    if (this.time < seconds) {
+      this.time = 0
+    } else {
+      this.time -= seconds
+    }
     this.player.seekBack(seconds)
+    this.emit('seek-back', +seconds)
+  }
+
+  seekTo(timeInSecs) {
+    this.time = timeInSecs
+    this.player.seekTo(timeInSecs)
+    this.emit('seek-to', +timeInSecs)
   }
 
   togglePause() {
     this.player.togglePause()
+    this.emit('toggle-pause')
   }
 
   setPause(value) {
     this.player.setPause(value)
+    this.emit('set-pause', !!value)
   }
 
   toggleLoop() {
     this.player.toggleLoop()
+    this.emit('toggle-loop')
   }
 
   setLoop(value) {
     this.player.setLoop(value)
+    this.emit('set-loop', !!value)
   }
 
   volUp(amount = 10) {
     this.player.volUp(amount)
+    this.emit('vol-up', +amount)
   }
 
   volDown(amount = 10) {
     this.player.volDown(amount)
+    this.emit('vol-down', +amount)
   }
 
   setVolume(value) {
     this.player.setVolume(value)
+    this.emit('set-volume', +value)
   }
 
   setVolumeMultiplier(value) {
-    this.player.setVolumeMultiplier(value);
+    this.player.setVolumeMultiplier(value)
   }
 
   fadeIn() {
-    return this.player.fadeIn();
+    return this.player.fadeIn()
   }
 
   setPauseNextTrack(value) {
     this.pauseNextTrack = !!value
+    this.emit('set-pause-next-track', !!value)
   }
 
   setLoopQueueAtEnd(value) {
@@ -614,6 +668,8 @@ class Backend extends EventEmitter {
     }
 
     this.queuePlayers = []
+    this.alwaysStartPaused = false
+    this.waitWhenDonePlaying = false
 
     this.recordStore = new RecordStore()
     this.throttleMetadata = throttlePromise(10)
@@ -645,6 +701,9 @@ class Backend extends EventEmitter {
       return error
     }
 
+    queuePlayer.alwaysStartPaused = this.alwaysStartPaused
+    queuePlayer.waitWhenDonePlaying = this.waitWhenDonePlaying
+
     this.queuePlayers.push(queuePlayer)
     this.emit('added queue player', queuePlayer)
 
@@ -772,6 +831,20 @@ class Backend extends EventEmitter {
     return {seconds, string, noticedMissingMetadata, approxSymbol}
   }
 
+  setAlwaysStartPaused(value) {
+    this.alwaysStartPaused = !!value
+    for (const queuePlayer of this.queuePlayers) {
+      queuePlayer.alwaysStartPaused = !!value
+    }
+  }
+
+  setWaitWhenDonePlaying(value) {
+    this.waitWhenDonePlaying = !!value
+    for (const queuePlayer of this.queuePlayers) {
+      queuePlayer.waitWhenDonePlaying = !!value
+    }
+  }
+
   async stopPlayingAll() {
     for (const queuePlayer of this.queuePlayers) {
       await queuePlayer.stopPlaying()
@@ -781,6 +854,10 @@ class Backend extends EventEmitter {
   async download(item) {
     return download(item, this.getRecordFor(item))
   }
+
+  showLogMessage(messageInfo) {
+    this.emit('log message', messageInfo)
+  }
 }
 
 module.exports = Backend