Files
supersonic/backend/player/jukebox/jukeboxplayer.go
T

161 lines
3.0 KiB
Go

package jukebox
import (
"time"
"github.com/dweymouth/supersonic/backend/mediaprovider"
"github.com/dweymouth/supersonic/backend/player"
)
const (
stopped = 0
playing = 1
paused = 2
)
type JukeboxPlayer struct {
player.BasePlayerCallbackImpl
provider mediaprovider.JukeboxProvider
state int // stopped, playing, paused
volume int
seeking bool
curTrack int
queueLength int
curTrackDuration float64
startTrackTime float64
startedAtUnixMilli int64
nextTrackTimer *time.Timer
}
func (j *JukeboxPlayer) SetVolume(vol int) error {
if err := j.provider.JukeboxSetVolume(vol); err != nil {
return err
}
j.volume = vol
return nil
}
func (j *JukeboxPlayer) GetVolume() int {
return j.volume
}
func (j *JukeboxPlayer) Continue() error {
if j.state == playing {
return nil
}
if err := j.startAndUpdateTime(); err != nil {
return err
}
j.state = playing
j.InvokeOnPlaying()
return nil
}
func (j *JukeboxPlayer) Pause() error {
if j.state != playing {
return nil
}
if err := j.provider.JukeboxStop(); err != nil {
return err
}
// TODO: calculate paused at time
j.state = paused
j.InvokeOnPaused()
return nil
}
func (j *JukeboxPlayer) Stop() error {
if j.state == stopped {
return nil
}
if err := j.provider.JukeboxStop(); err != nil {
return err
}
j.state = stopped
j.InvokeOnStopped()
return nil
}
func (j *JukeboxPlayer) PlayTrack(track *mediaprovider.Track) error {
if err := j.provider.JukeboxSet(track.ID); err != nil {
return err
}
j.startTrackTime = 0
if err := j.startAndUpdateTime(); err != nil {
return err
}
j.curTrack = 0
j.queueLength = 1
j.curTrackDuration = float64(track.Duration)
return nil
}
func (j *JukeboxPlayer) SetNextTrack(track *mediaprovider.Track) error {
// we need to replace the last track in the queue, remove it first
if j.curTrack < j.queueLength-1 {
if err := j.provider.JukeboxRemove(j.curTrack + 1); err != nil {
return err
}
j.queueLength -= 1
}
// append the new track to the queue
if err := j.provider.JukeboxAdd(track.ID); err != nil {
return err
}
j.queueLength += 1
return nil
}
func (j *JukeboxPlayer) SeekSeconds(secs float64) error {
j.seeking = true
err := j.provider.JukeboxSeek(j.curTrack, int(secs))
j.seeking = false
j.InvokeOnSeek()
return err
}
func (j *JukeboxPlayer) IsSeeking() bool {
return j.seeking
}
func (j *JukeboxPlayer) GetStatus() player.Status {
state := player.Stopped
if j.state == playing {
state = player.Playing
} else if j.state == paused {
state = player.Paused
}
// TODO - the rest
return player.Status{
State: state,
}
}
func (j *JukeboxPlayer) Destroy() {}
func (j *JukeboxPlayer) startAndUpdateTime() error {
beforeStart := time.Now()
if err := j.provider.JukeboxStart(); err != nil {
return err
}
afterStart := time.Now()
// assume track started playing at (ie has been playing for)
// half the round-trip latency
j.startedAtUnixMilli = time.Now().Add(-afterStart.Sub(beforeStart)).UnixMilli()
return nil
}
func (j *JukeboxPlayer) handleNextTrack() {
}