more jukebox work
This commit is contained in:
@@ -298,11 +298,16 @@ type JukeboxProvider interface {
|
|||||||
JukeboxStop() error
|
JukeboxStop() error
|
||||||
JukeboxSeek(idx, seconds int) error
|
JukeboxSeek(idx, seconds int) error
|
||||||
JukeboxClear() error
|
JukeboxClear() error
|
||||||
JukeboxSet(trackID string) error
|
|
||||||
JukeboxAdd(trackID string) error
|
JukeboxAdd(trackID string) error
|
||||||
JukeboxRemove(idx int) error
|
JukeboxRemove(idx int) error
|
||||||
JukeboxSetVolume(vol int) error
|
|
||||||
JukeboxGetStatus() (*JukeboxStatus, error)
|
JukeboxGetStatus() (*JukeboxStatus, error)
|
||||||
|
|
||||||
|
// Performs a Clear followed by an Add to set the queue
|
||||||
|
// to contain a single track
|
||||||
|
JukeboxSet(trackID string) error
|
||||||
|
|
||||||
|
// Sets the volume of the jukebox player (0-100)
|
||||||
|
JukeboxSetVolume(vol int) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type JukeboxStatus struct {
|
type JukeboxStatus struct {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package subsonic
|
package subsonic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||||
@@ -24,8 +25,9 @@ func (s *subsonicMediaProvider) JukeboxClear() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *subsonicMediaProvider) JukeboxSetVolume(vol int) error {
|
func (s *subsonicMediaProvider) JukeboxSetVolume(vol int) error {
|
||||||
|
v := float64(vol) / 100
|
||||||
_, err := s.client.JukeboxControl("setGain",
|
_, err := s.client.JukeboxControl("setGain",
|
||||||
map[string]string{"gain": strconv.Itoa(vol)})
|
map[string]string{"gain": fmt.Sprintf("%0.2f", v)})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package jukebox
|
package jukebox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||||
"github.com/dweymouth/supersonic/backend/player"
|
"github.com/dweymouth/supersonic/backend/player"
|
||||||
)
|
)
|
||||||
@@ -14,15 +16,16 @@ const (
|
|||||||
type JukeboxPlayer struct {
|
type JukeboxPlayer struct {
|
||||||
provider mediaprovider.JukeboxProvider
|
provider mediaprovider.JukeboxProvider
|
||||||
|
|
||||||
state int // stopped, playing, paused
|
state int // stopped, playing, paused
|
||||||
volume int
|
volume int
|
||||||
seeking bool
|
seeking bool
|
||||||
numTracks int
|
|
||||||
|
|
||||||
curTrack int
|
curTrack int
|
||||||
curTrackDuration float64
|
queueLength int
|
||||||
startTrackTime float64
|
curTrackDuration float64
|
||||||
startedAtUnixSecs float64
|
startTrackTime float64
|
||||||
|
startedAtUnixMilli int64
|
||||||
|
nextTrackTimer *time.Timer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *JukeboxPlayer) SetVolume(vol int) error {
|
func (j *JukeboxPlayer) SetVolume(vol int) error {
|
||||||
@@ -37,21 +40,14 @@ func (j *JukeboxPlayer) GetVolume() int {
|
|||||||
return j.volume
|
return j.volume
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *JukeboxPlayer) PlayTrackAt(idx int) error {
|
|
||||||
if err := j.provider.JukeboxSeek(idx, 0); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
j.curTrack = idx
|
|
||||||
return j.Continue()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *JukeboxPlayer) Continue() error {
|
func (j *JukeboxPlayer) Continue() error {
|
||||||
if j.state == playing {
|
if j.state == playing {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := j.provider.JukeboxStart(); err != nil {
|
if err := j.startAndUpdateTime(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
j.state = playing
|
j.state = playing
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -63,6 +59,7 @@ func (j *JukeboxPlayer) Pause() error {
|
|||||||
if err := j.provider.JukeboxStop(); err != nil {
|
if err := j.provider.JukeboxStop(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// TODO: calculate paused at time
|
||||||
j.state = paused
|
j.state = paused
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -78,20 +75,37 @@ func (j *JukeboxPlayer) Stop() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *JukeboxPlayer) SeekPrevious() error {
|
func (j *JukeboxPlayer) PlayTrack(track *mediaprovider.Track) error {
|
||||||
track := j.curTrack
|
if err := j.provider.JukeboxSet(track.ID); err != nil {
|
||||||
if track > 0 {
|
return err
|
||||||
track = j.curTrack - 1
|
|
||||||
}
|
}
|
||||||
return j.PlayTrackAt(track)
|
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) SeekNext() error {
|
func (j *JukeboxPlayer) SetNextTrack(track *mediaprovider.Track) error {
|
||||||
track := j.curTrack
|
// we need to replace the last track in the queue, remove it first
|
||||||
if track >= j.numTracks {
|
if j.curTrack < j.queueLength-1 {
|
||||||
return nil
|
if err := j.provider.JukeboxRemove(j.curTrack + 1); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
j.queueLength -= 1
|
||||||
}
|
}
|
||||||
return j.PlayTrackAt(track + 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 {
|
func (j *JukeboxPlayer) SeekSeconds(secs float64) error {
|
||||||
@@ -119,3 +133,20 @@ func (j *JukeboxPlayer) GetStatus() player.Status {
|
|||||||
State: state,
|
State: state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user