91 lines
2.6 KiB
Go
91 lines
2.6 KiB
Go
package subsonic
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"git.noroutes.net/NoRoutes/vibetunes/internal/database"
|
|
)
|
|
|
|
func init() {
|
|
registerExtension("indexBasedQueue", 1)
|
|
register("getPlayQueueByIndex", handleGetPlayQueueByIndex)
|
|
register("savePlayQueueByIndex", handleSavePlayQueueByIndex)
|
|
}
|
|
|
|
// The indexBasedQueue extension shares the same play_queues storage as
|
|
// the classic getPlayQueue/savePlayQueue (internal/subsonic/playqueue.go)
|
|
// — the table has always tracked the current *index*, not a song ID; the
|
|
// classic endpoints are the ones that lossily resolve index -> song ID
|
|
// for their "current" attribute. Duplicate song IDs in the queue are
|
|
// therefore already handled correctly by construction: saving stores a
|
|
// plain ordered ID list, and both current-track values (index here,
|
|
// looked-up ID for the classic endpoint) are derived from the same
|
|
// unambiguous index.
|
|
func handleGetPlayQueueByIndex(rc *Context) *apiError {
|
|
db := rc.Server.DB
|
|
q, err := database.GetPlayQueue(db, rc.User.ID)
|
|
if err == database.ErrNotFound {
|
|
rc.Response = newResponse()
|
|
return nil
|
|
}
|
|
if err != nil {
|
|
return newError(ErrGeneric, err.Error())
|
|
}
|
|
|
|
var ids []string
|
|
if uerr := json.Unmarshal([]byte(q.SongIDsJSON), &ids); uerr != nil {
|
|
return newError(ErrGeneric, "corrupt saved play queue")
|
|
}
|
|
|
|
out := &PlayQueueByIndex{
|
|
CurrentIndex: q.CurrentIndex,
|
|
Position: int64(q.PositionMs),
|
|
Username: rc.User.Username,
|
|
Changed: isoTime(q.UpdatedAt),
|
|
ChangedBy: q.Client,
|
|
}
|
|
for _, id := range ids {
|
|
song, serr := database.GetSong(db, id)
|
|
if serr != nil {
|
|
continue
|
|
}
|
|
mf, merr := database.GetMediaFile(db, song.MediaFileID)
|
|
if merr != nil {
|
|
continue
|
|
}
|
|
out.Entry = append(out.Entry, childFromSong(db, song, mf, albumOfSong(db, song), rc.User.ID))
|
|
}
|
|
|
|
rc.Response = newResponse()
|
|
rc.Response.PlayQueueByIndex = out
|
|
return nil
|
|
}
|
|
|
|
func handleSavePlayQueueByIndex(rc *Context) *apiError {
|
|
ids := rc.Params.GetAll("id")
|
|
position := rc.Params.Int("position", 0)
|
|
client := rc.Params.Get("c")
|
|
|
|
currentIndex := 0
|
|
if len(ids) > 0 {
|
|
var aerr *apiError
|
|
currentIndex, aerr = rc.Params.RequiredInt("currentIndex")
|
|
if aerr != nil {
|
|
return aerr
|
|
}
|
|
if currentIndex < 0 || currentIndex >= len(ids) {
|
|
return newError(ErrGeneric, "currentIndex out of range")
|
|
}
|
|
}
|
|
|
|
encoded, err := json.Marshal(ids)
|
|
if err != nil {
|
|
return newError(ErrGeneric, err.Error())
|
|
}
|
|
if err := database.SavePlayQueue(rc.Server.DB, rc.User.ID, string(encoded), currentIndex, position, client); err != nil {
|
|
return newError(ErrGeneric, err.Error())
|
|
}
|
|
rc.Response = newResponse()
|
|
return nil
|
|
}
|