Skip to content

Commit

Permalink
fix coalescing logic of multiple seekFwdBackN commands
Browse files Browse the repository at this point in the history
  • Loading branch information
dweymouth committed Sep 11, 2024
1 parent 00ffb8b commit 1fff7f6
Showing 1 changed file with 43 additions and 12 deletions.
55 changes: 43 additions & 12 deletions backend/playbackcommands.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ type playbackCommand struct {
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 {
mutex sync.Mutex
queue []playbackCommand
Expand Down Expand Up @@ -157,21 +161,48 @@ func (c *playbackCommandQueue) filterCommandsAndAdd(excludeTypes []playbackComma
}

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()
j := 0
n := 0
for _, cmd := range c.queue {
if cmd.Type == cmdSeekFwdBackN {
n += cmd.Arg.(int)
} else {
c.queue[j] = cmd
j++
done := false
for i := len(c.queue) - 1; i >= 0 && !done; i-- {
cmd := c.queue[i]
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
}
}
c.queue = c.queue[:j]
c.queue = append(c.queue, playbackCommand{
Type: cmdSeekFwdBackN,
Arg: n + direction})

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)
} else {
// copy over other non-seekFwdBackN command
newQueue = append(newQueue, cmd)
}
}
newQueue = append(newQueue, playbackCommand{
Type: cmdSeekFwdBackN,
Arg: n,
})
c.queue = newQueue
}

c.mutex.Unlock()
c.cmdAvailable.Signal()
}
Expand Down

0 comments on commit 1fff7f6

Please sign in to comment.