Build a Rocksky-controllable player over the remote-control WebSocket
(see remote-ws/PROTOCOL.md).
connect/2,3 registers as a device in the background; you advertise what
you're playing (set_now_playing/2, set_status/2, set_queue/3) and react
to commands a miniplayer sends (play/pause/next/previous/seek/enqueue/queue
actions). Heartbeat, reconnect, and the device-id handshake are handled by the
native core.
Poll next_command/1 in a loop, or let listen/2 do it for you and dispatch
each command to a handler map:
player = Rocksky.RemotePlayer.connect(token, "My Player")
Rocksky.RemotePlayer.listen(player, %{
play: fn -> engine_play() end,
pause: fn -> engine_pause() end,
next: fn -> engine_next() end,
seek: fn ms -> engine_seek(ms) end,
enqueue: fn cmd -> engine_enqueue(cmd["tracks"], cmd["mode"]) end
})
Rocksky.RemotePlayer.set_now_playing(player, %{
"title" => "Chaser", "artist" => "Calibro 35",
"durationMs" => 182_320, "elapsedMs" => 0, "isPlaying" => true
})
Rocksky.RemotePlayer.set_status(player, "playing")The handle is an opaque NIF resource (freed by GC); disconnect/1 just stops
the background task. Setters return {:ok, value} | {:error, message}.
Records/queue items are maps with camelCase string keys.
Summary
Functions
Connect and register a controllable player. name is the miniplayer
device-picker label; url overrides the WebSocket endpoint (nil = public).
Returns the opaque player handle.
Disconnect and stop the background task (the handle stays valid until GC'd).
Spawn a process that loops next_command/1 and dispatches each command to the
matching function in handlers. Returns {:ok, pid}. The loop ends when the
player disconnects.
Block until the next controller command, returned as a decoded command map
(e.g. %{"action" => "play"} or %{"action" => "seek", "position" => ms}).
Returns nil once the player is disconnected.
Advertise the currently-playing track. track is a map with camelCase string
keys: "title", "artist", and optional "album", "albumArtist",
"albumArt", "durationMs", "elapsedMs", "isPlaying". Call it whenever
the track changes, and periodically with a fresh "elapsedMs" so controllers
show smooth progress.
Advertise the playback queue + active index. items is a list of queue-item
maps (camelCase string keys); index is 0-based.
Advertise transport status: "playing", "paused", or "stopped".
Functions
Connect and register a controllable player. name is the miniplayer
device-picker label; url overrides the WebSocket endpoint (nil = public).
Returns the opaque player handle.
Disconnect and stop the background task (the handle stays valid until GC'd).
Spawn a process that loops next_command/1 and dispatches each command to the
matching function in handlers. Returns {:ok, pid}. The loop ends when the
player disconnects.
handlers is a map keyed by command:
:play,:pause,:next,:previous— 0-arity functions:seek— receives the position in ms:queue_jump,:queue_remove— receive the queue index:enqueue— receives the full command map ("tracks","mode","shuffle","startIndex")
Unhandled commands are ignored.
Block until the next controller command, returned as a decoded command map
(e.g. %{"action" => "play"} or %{"action" => "seek", "position" => ms}).
Returns nil once the player is disconnected.
Advertise the currently-playing track. track is a map with camelCase string
keys: "title", "artist", and optional "album", "albumArtist",
"albumArt", "durationMs", "elapsedMs", "isPlaying". Call it whenever
the track changes, and periodically with a fresh "elapsedMs" so controllers
show smooth progress.
Advertise the playback queue + active index. items is a list of queue-item
maps (camelCase string keys); index is 0-based.
Advertise transport status: "playing", "paused", or "stopped".