Remote-control bindings: build a Rocksky-controllable player or a remote UI.
Two roles over the remote-control WebSocket (remote-ws/PROTOCOL.md), both
wrapping the shared Rust core's C ABI (crates/rocksky-uniffi) via JVM Panama
FFM — the same opaque-handle style as rocksky.core's agent:
Both use a poll model: a blocking next-command/next-event you loop on a
background thread. listen does that for you — pass a handler map and it spawns
a thread that dispatches parsed commands/events to your fns.
(def player (remote/connect-player token "My Player")) (remote/listen player {:play #(engine-play) :pause #(engine-pause) :seek (fn [ms] (engine-seek ms))}) (remote/set-now-playing player {:title "…" :artist "…" :durationMs 200000 :elapsedMs 0 :isPlaying true}) (remote/set-status player :playing)
(def ctl (remote/connect-controller token "My Controller")) (remote/listen ctl {:devices (fn [e] (render (get e "devices"))) :now-playing (fn [e] (show (get e "track")))}) (remote/set-primary ctl device-id) (remote/pause ctl device-id) ; nil/omitted target ⇒ broadcast
Records/commands/events are Clojure maps with camelCase string keys — the same
convention as rocksky.core. Requires JDK 22+ (run with
--enable-native-access=ALL-UNNAMED) and the native lib built with the
remote-player feature (the crate default).
Remote-control bindings: build a Rocksky-controllable player or a remote UI.
Two roles over the remote-control WebSocket (remote-ws/PROTOCOL.md), both
wrapping the shared Rust core's C ABI (crates/rocksky-uniffi) via JVM Panama
FFM — the same opaque-handle style as `rocksky.core`'s agent:
- a RemotePlayer advertises now-playing/status/queue and receives commands;
- a RemoteController lists devices, picks the primary, and sends commands.
Both use a poll model: a blocking `next-command`/`next-event` you loop on a
background thread. `listen` does that for you — pass a handler map and it spawns
a thread that dispatches parsed commands/events to your fns.
(def player (remote/connect-player token "My Player"))
(remote/listen player {:play #(engine-play)
:pause #(engine-pause)
:seek (fn [ms] (engine-seek ms))})
(remote/set-now-playing player {:title "…" :artist "…" :durationMs 200000
:elapsedMs 0 :isPlaying true})
(remote/set-status player :playing)
(def ctl (remote/connect-controller token "My Controller"))
(remote/listen ctl {:devices (fn [e] (render (get e "devices")))
:now-playing (fn [e] (show (get e "track")))})
(remote/set-primary ctl device-id)
(remote/pause ctl device-id) ; nil/omitted target ⇒ broadcast
Records/commands/events are Clojure maps with camelCase string keys — the same
convention as `rocksky.core`. Requires JDK 22+ (run with
--enable-native-access=ALL-UNNAMED) and the native lib built with the
`remote-player` feature (the crate default).(connect-controller token name)(connect-controller token name url)Connect and register a controller (remote UI). Args as connect-player.
Returns a RemoteController.
Connect and register a controller (remote UI). Args as `connect-player`. Returns a `RemoteController`.
(connect-player token name)(connect-player token name url)Connect and register a controllable player. token is a Rocksky access token
(JWT); name is the device-picker label; url may be nil for the public
endpoint. Returns a RemotePlayer.
Connect and register a controllable player. `token` is a Rocksky access token (JWT); `name` is the device-picker label; `url` may be nil for the public endpoint. Returns a `RemotePlayer`.
(enqueue controller target tracks)(enqueue controller target tracks mode shuffle start-index)Enqueue tracks (a vector of queue-item maps) on target (nil ⇒ broadcast).
mode is :now | :next | :last (default :now); shuffle a bool (default false);
start-index an int (default 0).
Enqueue `tracks` (a vector of queue-item maps) on `target` (nil ⇒ broadcast). `mode` is :now | :next | :last (default :now); `shuffle` a bool (default false); `start-index` an int (default 0).
(next-command player)Block until the next controller command; returns a parsed command map (string
keys) or nil once disconnected. Prefer listen — this is the raw poll.
Block until the next controller command; returns a parsed command map (string keys) or nil once disconnected. Prefer `listen` — this is the raw poll.
(next-event controller)Block until the next update; returns a parsed event map (string keys) or nil
once disconnected. Prefer listen — this is the raw poll.
Block until the next update; returns a parsed event map (string keys) or nil once disconnected. Prefer `listen` — this is the raw poll.
(play controller)(play controller target)Play on target (a device id), or omit/nil to broadcast to all devices.
Play on `target` (a device id), or omit/nil to broadcast to all devices.
(queue-jump controller target index)Jump to index in target's queue (nil target ⇒ broadcast).
Jump to `index` in `target`'s queue (nil target ⇒ broadcast).
(queue-remove controller target index)Remove queue item index on target (nil target ⇒ broadcast).
Remove queue item `index` on `target` (nil target ⇒ broadcast).
(close this)Release the native handle. Call once, after disconnect.
Release the native handle. Call once, after `disconnect`.
(disconnect this)Disconnect and stop the background task. Unblocks the listen loop (its
next poll returns nil, ending the thread). The handle stays valid until
close.
Disconnect and stop the background task. Unblocks the `listen` loop (its next poll returns nil, ending the thread). The handle stays valid until `close`.
(listen this handlers)Spawn a background thread that loops the blocking poll and dispatches to
handlers (a map of keyword ⇒ fn). Returns the future; stop it with
disconnect. An optional :error handler receives any Throwable.
Spawn a background thread that loops the blocking poll and dispatches to `handlers` (a map of keyword ⇒ fn). Returns the `future`; stop it with `disconnect`. An optional `:error` handler receives any Throwable.
(seek controller target position-ms)Seek target to position-ms (nil target ⇒ broadcast).
Seek `target` to `position-ms` (nil target ⇒ broadcast).
(set-now-playing player track)Advertise the current track. track is a map with camelCase keys: :title,
:artist, :album, :albumArtist, :albumArt, :durationMs, :elapsedMs, :isPlaying,
plus optional audio info :codec (audio codec/container, e.g. "mp3", "flac")
and :sampleRate (sample rate in Hz, e.g. 44100), included in the track payload
when set and omitted otherwise.
Advertise the current track. `track` is a map with camelCase keys: :title, :artist, :album, :albumArtist, :albumArt, :durationMs, :elapsedMs, :isPlaying, plus optional audio info :codec (audio codec/container, e.g. "mp3", "flac") and :sampleRate (sample rate in Hz, e.g. 44100), included in the track payload when set and omitted otherwise.
(set-primary controller device-id)Choose the primary (scrobble/profile) device by id.
Choose the primary (scrobble/profile) device by id.
(set-queue player items index)Advertise the playback queue + active index. items is a vector of queue-item
maps (camelCase keys: :uploadId/:trackId, :title, :artist, :album,
:albumArtist, :albumArt, :durationMs, :songUri, :albumUri, :trackNumber).
Advertise the playback queue + active index. `items` is a vector of queue-item maps (camelCase keys: :uploadId/:trackId, :title, :artist, :album, :albumArtist, :albumArt, :durationMs, :songUri, :albumUri, :trackNumber).
(set-status player status)Advertise transport state — :playing, :paused, or :stopped (keyword or string).
Advertise transport state — :playing, :paused, or :stopped (keyword or string).
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |