Add support for the jukebox endpoint
This supports most of jukeboxControl.view as far as i can tell. Things seem to be playing ok without freaking out I've also only tested it a little bit with ultrasonic but it does appear to be working pretty well
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"path"
|
||||
|
||||
"go.senan.xyz/gonic/db"
|
||||
"go.senan.xyz/gonic/jukebox"
|
||||
"go.senan.xyz/gonic/scanner"
|
||||
)
|
||||
|
||||
@@ -49,6 +50,7 @@ type Controller struct {
|
||||
MusicPath string
|
||||
Scanner *scanner.Scanner
|
||||
ProxyPrefix string
|
||||
Jukebox *jukebox.Jukebox
|
||||
}
|
||||
|
||||
// Path returns a URL path with the proxy prefix included
|
||||
|
||||
@@ -112,6 +112,7 @@ func (c *Controller) ServeGetUser(r *http.Request) *spec.Response {
|
||||
sub.User = &spec.User{
|
||||
Username: user.Name,
|
||||
AdminRole: user.IsAdmin,
|
||||
JukeboxRole: true,
|
||||
ScrobblingEnabled: user.LastFMSession != "",
|
||||
Folder: []int{1},
|
||||
}
|
||||
@@ -313,3 +314,51 @@ func (c *Controller) ServeGetRandomSongs(r *http.Request) *spec.Response {
|
||||
}
|
||||
return sub
|
||||
}
|
||||
|
||||
func (c *Controller) ServeJukebox(r *http.Request) *spec.Response {
|
||||
params := r.Context().Value(CtxParams).(params.Params)
|
||||
switch params.Get("action") {
|
||||
case "set":
|
||||
var tracks []*db.Track
|
||||
ids := params.GetFirstListInt("id")
|
||||
if len(ids) == 0 {
|
||||
c.Jukebox.ClearTracks()
|
||||
}
|
||||
for _, id := range ids {
|
||||
track := &db.Track{}
|
||||
err := c.DB.Preload("Album").First(track, id).Error
|
||||
if err != nil {
|
||||
return spec.NewError(10, "couldn't find tracks with provided ids")
|
||||
}
|
||||
tracks = append(tracks, track)
|
||||
}
|
||||
c.Jukebox.SetTracks(tracks)
|
||||
case "clear":
|
||||
c.Jukebox.ClearTracks()
|
||||
case "remove":
|
||||
index, err := params.GetInt("index")
|
||||
if err != nil {
|
||||
return spec.NewError(10, "please provide an id for remove actions")
|
||||
}
|
||||
c.Jukebox.RemoveTrack(index)
|
||||
case "stop":
|
||||
c.Jukebox.Stop()
|
||||
case "start":
|
||||
c.Jukebox.Start()
|
||||
case "skip":
|
||||
index, err := params.GetInt("index")
|
||||
var skipCurrent bool
|
||||
if err != nil {
|
||||
skipCurrent = true
|
||||
}
|
||||
c.Jukebox.Skip(index, skipCurrent)
|
||||
case "get":
|
||||
sub := spec.NewResponse()
|
||||
sub.JukeboxPlaylist = c.Jukebox.GetTracks()
|
||||
return sub
|
||||
}
|
||||
// All actions except get are expected to return a status
|
||||
sub := spec.NewResponse()
|
||||
sub.JukeboxStatus = c.Jukebox.Status()
|
||||
return sub
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ type Response struct {
|
||||
ArtistInfoTwo *ArtistInfo `xml:"artistInfo2" json:"artistInfo2,omitempty"`
|
||||
Genres *Genres `xml:"genres" json:"genres,omitempty"`
|
||||
PlayQueue *PlayQueue `xml:"playQueue" json:"playQueue,omitempty"`
|
||||
JukeboxStatus *JukeboxStatus `xml:"jukeboxStatus" json:"jukeboxStatus,omitempty"`
|
||||
JukeboxPlaylist *JukeboxPlaylist `xml:"jukeboxPlaylist" json:"jukeboxPlaylist,omitempty"`
|
||||
}
|
||||
|
||||
func NewResponse() *Response {
|
||||
@@ -269,3 +271,15 @@ type PlayQueue struct {
|
||||
ChangedBy string `xml:"changedBy,attr" json:"changedBy"`
|
||||
List []*TrackChild `xml:"entry,omitempty" json:"entry,omitempty"`
|
||||
}
|
||||
|
||||
type JukeboxStatus struct {
|
||||
CurrentIndex int `xml:"currentIndex,attr" json:"currentIndex"`
|
||||
Playing bool `xml:"playing,attr" json:"playing"`
|
||||
Gain float64 `xml:"gain,attr" json:"gain"`
|
||||
Position int `xml:"position,attr" json:"position"`
|
||||
}
|
||||
|
||||
type JukeboxPlaylist struct {
|
||||
List []*TrackChild `xml:"entry,omitempty" json:"entry,omitempty"`
|
||||
JukeboxStatus
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"go.senan.xyz/gonic/db"
|
||||
"go.senan.xyz/gonic/jukebox"
|
||||
"go.senan.xyz/gonic/scanner"
|
||||
"go.senan.xyz/gonic/server/assets"
|
||||
"go.senan.xyz/gonic/server/ctrladmin"
|
||||
@@ -46,7 +47,9 @@ func New(opts Options) *Server {
|
||||
MusicPath: opts.MusicPath,
|
||||
ProxyPrefix: opts.ProxyPrefix,
|
||||
Scanner: scanner,
|
||||
Jukebox: &jukebox.Jukebox{},
|
||||
}
|
||||
base.Jukebox.Init(opts.MusicPath)
|
||||
// router with common wares for admin / subsonic
|
||||
r := mux.NewRouter()
|
||||
r.Use(base.WithLogging)
|
||||
@@ -154,6 +157,7 @@ func setupSubsonic(r *mux.Router, ctrl *ctrlsubsonic.Controller) {
|
||||
r.Handle("/getSong{_:(?:\\.view)?}", ctrl.H(ctrl.ServeGetSong))
|
||||
r.Handle("/getRandomSongs{_:(?:\\.view)?}", ctrl.H(ctrl.ServeGetRandomSongs))
|
||||
r.Handle("/getSongsByGenre{_:(?:\\.view)?}", ctrl.H(ctrl.ServeGetSongsByGenre))
|
||||
r.Handle("/jukeboxControl{_:(?:\\.view)?}", ctrl.H(ctrl.ServeJukebox))
|
||||
// ** begin raw
|
||||
r.Handle("/download{_:(?:\\.view)?}", ctrl.HR(ctrl.ServeDownload))
|
||||
r.Handle("/getCoverArt{_:(?:\\.view)?}", ctrl.HR(ctrl.ServeGetCoverArt))
|
||||
|
||||
Reference in New Issue
Block a user