Repository navigation
Description
I am opening this first, as CONTRIBUTING.md suggests for a new feature, before I send a PR.
Problem
An API client can add a track to the queue with add_to_queue, but it cannot see the queue or change it. /status shows only the next track. To remove, reorder or clear queued tracks, a client has only one way: the Spotify app sends the set_queue dealer command. Then handlePlayerCommand calls p.setQueue.
Motivation
I am building spotui, a terminal Spotify player. It embeds the daemon in-process and sends ApiRequests over the channel. I want a queue view where the user sees the upcoming tracks, plays a track next, removes one, reorders them, or clears the queue. The same requests also help HTTP clients of the daemon.
Proposal
Two new API request types, with HTTP endpoints and api-spec.yml entries:
queue,GET /player/queue. It returnsprev_tracksandnext_tracksas last published, so at most 32 on each side (tracks.MaxTracksInContext). Each entry hasuri,uidandprovider(queue,contextorautoplay). It also has the track metadata in the same shape that/statususes, if the metadata is in the cache. If no session is active, it returns 204.set_queue,POST /player/queuewith{"tracks": [{"uri": "...", "uid": "..."}]}. It replaces the queued tracks, in order. An empty list clears the queue. It goes through the existingsetQueue/tracks.List.SetQueuepath, so the state publish,invalidateUpcomingand the prefetch reset happen as they do for the dealer command. The track that plays now and the context do not change.
Input checks for set_queue:
- Track and episode URIs only.
- 0 to 32 entries.
- No uid twice.
- A missing or null
tracksfield returns 400. - If no context is loaded, it returns 409.
- A uid stays only if it names a queued entry with the same URI. Other entries get a new queue uid, the same way
add_to_queuemakes one.
The change is about 660 lines with tests and the regenerated api_gen.go. It has no new config, no new dependencies, and no change to add_to_queue. It has two commits:
feat: let a list job answer a waiting caller. A loader job can carry a reply, so a request that the loader drops or never runs still gets an answer and does not hang.feat: read and set the play queue through the API.
Questions before I send the PR
- The queue has no size limit, but the published state holds at most 32 upcoming tracks. So
set_queuetakes at most 32, and if more tracks are in the queue, it drops the ones that are not in the list. The dealer command works the same way today, becausetracks.List.SetQueuekeeps only the queued tracks in the list that it gets. Is that acceptable, or do you want a different rule? For example,set_queuecould keep the queued tracks after entry 32. - Do you want a websocket event when the queue changes? I left it out to keep the PR small, but it is easy to add in this PR or a later one.
- Are
GETandPOST /player/queuegood names, or do you prefer/player/set_queuenext to/player/add_to_queue?
How I tested
Unit tests (test_unit) cover these cases:
- The read lists queued tracks before context tracks, in order.
set_queuereorders, removes, adds and clears, also with 32 queued tracks.- If the user skips to another track before the job runs, the publish shows the skip.
- A dropped job and a closed lane still answer.
- A request with no context gets 409.
- The HTTP handler rejects bad input.
gofmt, go vet, go build ./cmd/daemon and go test -tags "test_unit test_integration" ./... pass. I did not test it against a live account yet.
If this fits the project, I can send the PR. I can also change any of the choices above first.
Activity