fix coalescing logic of multiple seekFwdBackN commands

This commit is contained in:
Drew Weymouth
2024-09-11 08:20:15 -07:00
parent 00ffb8b3a1
commit 1fff7f6488
+40 -9
View File
@@ -35,6 +35,10 @@ type playbackCommand struct {
Arg3 any Arg3 any
} }
// playbackCommandQueue is a queue to accumulate player commands from the UI
// commands are processed by the playback engine as fast as they can, but if
// more commands arrive before the player can respond to them, they will queue up
// and some commands may coalesce together (e.g. multiple volume commands into just one)
type playbackCommandQueue struct { type playbackCommandQueue struct {
mutex sync.Mutex mutex sync.Mutex
queue []playbackCommand queue []playbackCommand
@@ -157,21 +161,48 @@ func (c *playbackCommandQueue) filterCommandsAndAdd(excludeTypes []playbackComma
} }
func (c *playbackCommandQueue) seekBackOrFwd(direction int) { func (c *playbackCommandQueue) seekBackOrFwd(direction int) {
// find the index of the last seekBackOrFwd command
// in the queue that can be coalesced with this one
lastIdx := -1
c.mutex.Lock() c.mutex.Lock()
j := 0 done := false
n := 0 for i := len(c.queue) - 1; i >= 0 && !done; i-- {
for _, cmd := range c.queue { cmd := c.queue[i]
if cmd.Type == cmdSeekFwdBackN { switch cmd.Type {
case cmdSeekFwdBackN:
lastIdx = i
case cmdRemoveTracksFromQueue, cmdLoadItems, cmdPlayTrackAt,
cmdLoadRadioStation, cmdUpdatePlayQueue, cmdStopAndClearPlayQueue:
// any queue-modifying command means we can't coalesce any
// more seekFwdBackN commands before here
done = true
}
}
if lastIdx == -1 {
// no coalescable seekFwdBackN commands, just append new one
c.queue = append(c.queue, playbackCommand{Type: cmdSeekFwdBackN, Arg: direction})
} else {
newQueue := make([]playbackCommand, 0, len(c.queue))
// copy over all cmds past the first coalescable idx
newQueue = append(newQueue, c.queue[0:lastIdx]...)
n := direction
for i := lastIdx; i < len(c.queue); i++ {
if cmd := c.queue[i]; cmd.Type == cmdSeekFwdBackN {
// coalesce this cmd with the new one
n += cmd.Arg.(int) n += cmd.Arg.(int)
} else { } else {
c.queue[j] = cmd // copy over other non-seekFwdBackN command
j++ newQueue = append(newQueue, cmd)
} }
} }
c.queue = c.queue[:j] newQueue = append(newQueue, playbackCommand{
c.queue = append(c.queue, playbackCommand{
Type: cmdSeekFwdBackN, Type: cmdSeekFwdBackN,
Arg: n + direction}) Arg: n,
})
c.queue = newQueue
}
c.mutex.Unlock() c.mutex.Unlock()
c.cmdAvailable.Signal() c.cmdAvailable.Signal()
} }