103 lines
2.1 KiB
Go
103 lines
2.1 KiB
Go
package backend
|
|
|
|
import (
|
|
"slices"
|
|
"sync"
|
|
)
|
|
|
|
type PlaybackCommandType int
|
|
|
|
const (
|
|
CmdStop PlaybackCommandType = iota
|
|
CmdContinue
|
|
CmdPause
|
|
CmdPlayTrackAt
|
|
CmdSeekSeconds
|
|
CmdSeekFwdBackN
|
|
CmdVolume
|
|
CmdLoopMode
|
|
)
|
|
|
|
type PlaybackCommand struct {
|
|
Type PlaybackCommandType
|
|
Arg any
|
|
}
|
|
|
|
type CommandQueue struct {
|
|
mutex sync.Mutex
|
|
queue []PlaybackCommand
|
|
cmdAvailable *sync.Cond
|
|
nextChan chan (PlaybackCommand)
|
|
}
|
|
|
|
func NewCommandQueue() *CommandQueue {
|
|
c := &CommandQueue{}
|
|
c.cmdAvailable = sync.NewCond(&c.mutex)
|
|
go c.chanWriter()
|
|
return c
|
|
}
|
|
|
|
func (c *CommandQueue) C() <-chan PlaybackCommand {
|
|
return c.nextChan
|
|
}
|
|
|
|
func (c *CommandQueue) Stop() {
|
|
c.filterCommandsAndAdd([]PlaybackCommandType{CmdContinue, CmdPause, CmdStop},
|
|
PlaybackCommand{Type: CmdStop})
|
|
}
|
|
|
|
func (c *CommandQueue) Continue() {
|
|
c.filterCommandsAndAdd([]PlaybackCommandType{CmdContinue, CmdPause, CmdStop},
|
|
PlaybackCommand{Type: CmdContinue})
|
|
}
|
|
|
|
func (c *CommandQueue) Pause() {
|
|
c.filterCommandsAndAdd([]PlaybackCommandType{CmdContinue, CmdPause, CmdStop},
|
|
PlaybackCommand{Type: CmdPause})
|
|
}
|
|
|
|
func (c *CommandQueue) Volume(vol int) {
|
|
c.filterCommandsAndAdd([]PlaybackCommandType{CmdVolume},
|
|
PlaybackCommand{Type: CmdVolume, Arg: vol})
|
|
}
|
|
|
|
func (c *CommandQueue) LoopMode(mode LoopMode) {
|
|
c.filterCommandsAndAdd([]PlaybackCommandType{CmdLoopMode},
|
|
PlaybackCommand{Type: CmdLoopMode, Arg: mode})
|
|
}
|
|
|
|
func (c *CommandQueue) SeekSeconds(s float64) {
|
|
c.filterCommandsAndAdd([]PlaybackCommandType{CmdVolume},
|
|
PlaybackCommand{Type: CmdSeekSeconds, Arg: s})
|
|
}
|
|
|
|
func (c *CommandQueue) filterCommandsAndAdd(excludeTypes []PlaybackCommandType, command PlaybackCommand) {
|
|
c.mutex.Lock()
|
|
defer c.mutex.Unlock()
|
|
|
|
j := 0
|
|
for _, cmd := range c.queue {
|
|
if slices.Contains(excludeTypes, cmd.Type) {
|
|
continue
|
|
}
|
|
c.queue[j] = cmd
|
|
j++
|
|
}
|
|
c.queue = c.queue[:j]
|
|
c.queue = append(c.queue, command)
|
|
}
|
|
|
|
func (c *CommandQueue) chanWriter() {
|
|
for {
|
|
c.mutex.Lock()
|
|
for len(c.queue) == 0 {
|
|
c.cmdAvailable.Wait()
|
|
}
|
|
cmd := c.queue[0]
|
|
copy(c.queue, c.queue[1:])
|
|
c.queue = c.queue[:len(c.queue)-1]
|
|
c.mutex.Unlock()
|
|
c.nextChan <- cmd
|
|
}
|
|
}
|