start of JukeboxPlayer backend

This commit is contained in:
Drew Weymouth
2023-12-19 17:31:10 -08:00
parent f8f8a3a5cb
commit 1e466e4cdf
7 changed files with 227 additions and 9 deletions
+19
View File
@@ -148,6 +148,25 @@ type SupportsRating interface {
SetRating(params RatingFavoriteParameters, rating int) error
}
type JukeboxProvider interface {
JukeboxStart() error
JukeboxStop() error
JukeboxSeek(idx, seconds int) error
JukeboxClear() error
JukeboxSet(trackID string) error
JukeboxAdd(trackID string) error
JukeboxRemove(idx int) error
JukeboxSetVolume(vol int) error
JukeboxGetStatus() (*JukeboxStatus, error)
}
type JukeboxStatus struct {
Volume int
CurrentTrack int
Playing bool
PositionSeconds float64
}
func genresMatch(filterGenres, albumGenres []string) bool {
for _, g1 := range filterGenres {
for _, g2 := range albumGenres {
+67
View File
@@ -0,0 +1,67 @@
package subsonic
import (
"strconv"
"github.com/dweymouth/supersonic/backend/mediaprovider"
)
var _ mediaprovider.JukeboxProvider = (*subsonicMediaProvider)(nil)
func (s *subsonicMediaProvider) JukeboxStart() error {
_, err := s.client.JukeboxControl("start", nil)
return err
}
func (s *subsonicMediaProvider) JukeboxStop() error {
_, err := s.client.JukeboxControl("stop", nil)
return err
}
func (s *subsonicMediaProvider) JukeboxClear() error {
_, err := s.client.JukeboxControl("clear", nil)
return err
}
func (s *subsonicMediaProvider) JukeboxSetVolume(vol int) error {
_, err := s.client.JukeboxControl("setGain",
map[string]string{"gain": strconv.Itoa(vol)})
return err
}
func (s *subsonicMediaProvider) JukeboxSeek(idx, seconds int) error {
_, err := s.client.JukeboxControl("skip",
map[string]string{"index": strconv.Itoa(idx), "offset": strconv.Itoa(seconds)})
return err
}
func (s *subsonicMediaProvider) JukeboxRemove(idx int) error {
_, err := s.client.JukeboxControl("remove",
map[string]string{"index": strconv.Itoa(idx)})
return err
}
func (s *subsonicMediaProvider) JukeboxSet(trackID string) error {
_, err := s.client.JukeboxControl("set",
map[string]string{"id": trackID})
return err
}
func (s *subsonicMediaProvider) JukeboxAdd(trackID string) error {
_, err := s.client.JukeboxControl("add",
map[string]string{"id": trackID})
return err
}
func (s *subsonicMediaProvider) JukeboxGetStatus() (*mediaprovider.JukeboxStatus, error) {
stat, err := s.client.JukeboxControl("status", nil)
if err != nil {
return nil, err
}
return &mediaprovider.JukeboxStatus{
Volume: int(stat.Gain * 100),
CurrentTrack: stat.CurrentIndex,
Playing: stat.Playing,
PositionSeconds: float64(stat.Position),
}, nil
}
+2 -2
View File
@@ -229,8 +229,8 @@ func (p *PlaybackManager) LoadTracks(tracks []*mediaprovider.Track, appendToQueu
return err
}
urlP.AppendFile(url)
} else if trP, ok := p.player.(player.TrackIDPlayer); ok {
trP.AppendTrack(tracks[i].ID)
} else if trP, ok := p.player.(player.TrackPlayer); ok {
trP.AppendTrack(tracks[i])
} else {
panic("unsupported player type")
}
+1 -1
View File
@@ -8,7 +8,7 @@ require (
github.com/deluan/sanitize v0.0.0-20230310221930-6e18967d9fc1
github.com/dweymouth/go-jellyfin v0.0.0-20231116161116-e800860bdacc
github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee
github.com/dweymouth/go-subsonic v0.0.0-20231216234924-3f62122dc53a
github.com/dweymouth/go-subsonic v0.0.0-20231217175944-9b48c9ffc002
github.com/fsnotify/fsnotify v1.6.0
github.com/godbus/dbus/v5 v5.1.0
github.com/google/uuid v1.3.0
+2 -2
View File
@@ -75,8 +75,8 @@ github.com/dweymouth/go-jellyfin v0.0.0-20231116161116-e800860bdacc h1:wJy4U12Ys
github.com/dweymouth/go-jellyfin v0.0.0-20231116161116-e800860bdacc/go.mod h1:BMwS4vdjEYf1gmjPGSKCzWP/I6YlI6fkefJ9nsjBjaU=
github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee h1:ZGyJ6wp7CAfT31BugypcF/TPKEy2RrGR9JFq1JOjOpY=
github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee/go.mod h1:Ov0ieN90M7i+0k3OxhA/g1dozGs+UcPHDsMKqPgRDk0=
github.com/dweymouth/go-subsonic v0.0.0-20231216234924-3f62122dc53a h1:UJcwloSIzRpUOIwRE207JF2SHoTmOg7vJWzfQWpztSk=
github.com/dweymouth/go-subsonic v0.0.0-20231216234924-3f62122dc53a/go.mod h1:OWtcumdQsan8uM6wmx6PqKhldaCthH10CQ+vb+94kzo=
github.com/dweymouth/go-subsonic v0.0.0-20231217175944-9b48c9ffc002 h1:DhWQZJObkCUSFmHu/eEzHRqy0R33DcR266nPAvZJE34=
github.com/dweymouth/go-subsonic v0.0.0-20231217175944-9b48c9ffc002/go.mod h1:OWtcumdQsan8uM6wmx6PqKhldaCthH10CQ+vb+94kzo=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+132
View File
@@ -0,0 +1,132 @@
package jukebox
import (
"github.com/dweymouth/supersonic/backend/mediaprovider"
"github.com/dweymouth/supersonic/player"
)
const (
stopped = 0
playing = 1
paused = 2
)
type JukeboxPlayer struct {
provider mediaprovider.JukeboxProvider
state int // stopped, playing, paused
volume int
seeking bool
numTracks int
curTrack int
curTrackDuration float64
startTrackTime float64
startedAtUnixSecs float64
}
func (j *JukeboxPlayer) SetVolume(vol int) error {
go func() {
if err := j.provider.JukeboxSetVolume(vol); err == nil {
j.volume = vol
}
}()
return nil
}
func (j *JukeboxPlayer) GetVolume() int {
return j.volume
}
func (j *JukeboxPlayer) PlayTrackAt(idx int) error {
go func() {
if err := j.provider.JukeboxSeek(idx, 0); err == nil {
j.curTrack = idx
j.Continue()
}
}()
return nil
}
func (j *JukeboxPlayer) Continue() error {
if j.state == playing {
return nil
}
go func() {
if err := j.provider.JukeboxStart(); err != nil {
return
}
j.state = playing
}()
return nil
}
func (j *JukeboxPlayer) Pause() error {
if j.state != playing {
return nil
}
go func() {
if err := j.provider.JukeboxStop(); err != nil {
return
}
j.state = paused
}()
return nil
}
func (j *JukeboxPlayer) Stop() error {
if j.state == stopped {
return nil
}
go func() {
if err := j.provider.JukeboxStop(); err != nil {
return
}
j.state = stopped
}()
return nil
}
func (j *JukeboxPlayer) SeekPrevious() error {
track := j.curTrack
if track > 0 {
track = j.curTrack - 1
}
return j.PlayTrackAt(track)
}
func (j *JukeboxPlayer) SeekNext() error {
track := j.curTrack
if track >= j.numTracks {
return nil
}
return j.PlayTrackAt(track + 1)
}
func (j *JukeboxPlayer) SeekSeconds(secs float64) error {
j.seeking = true
go func() {
j.provider.JukeboxSeek(j.curTrack, int(secs))
j.seeking = false
}()
return nil
}
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,
}
}
+4 -4
View File
@@ -1,15 +1,15 @@
package player
import "github.com/dweymouth/supersonic/backend/mediaprovider"
type URLPlayer interface {
BasePlayer
AppendFile(url string) error
PlayFile(url string) error
}
type TrackIDPlayer interface {
type TrackPlayer interface {
BasePlayer
AppendTrack(trackID string) error
PlayTrack(trackID string) error
AppendTrack(track *mediaprovider.Track) error
}
type BasePlayer interface {