The bridge exposes two things to scripting panels: a mirror playlist called Up Next and a main-menu command. Panels written against this interface work with any version of the bridge.
This document describes the interface and explains how the mirror operates internally.
Examples use JScript Panel 3 (JSP3) and the standard plman and fb objects. A complete working example is available in example-panel/.
JSP3 exposes playlists but not the playback queue. The bridge fills that gap by keeping a normal playlist, Up Next, synchronised with the queue:
- Queue changes update
Up Next. - Changes to
Up Nextrebuild the queue.
Panels can treat Up Next as the queue and gain full queue control through the standard playlist API. Playing a specific queued track (and consuming all preceding queued tracks) is provided separately as a main-menu command.
The bridge maintains a playlist named Up Next that mirrors the playback queue. If the playlist does not exist when the component starts, it is created and populated from the current queue.
| Member | Type | Description |
|---|---|---|
| Name | string |
Always "Up Next". Resolve the playlist by name. |
Row N |
playlist item | Queue position N (0-based). Row 0 represents the next queued track. |
| Contents | FbMetadbHandleList |
Queued tracks in queue order, returned by plman.GetPlaylistItems. |
Resolve the playlist by name whenever you use it. Playlist indices are not stable and may change when other playlists are added or removed.
If Up Next cannot be found, assume the bridge is not loaded and fall back gracefully.
function resolvePlaylist() {
for (var i = 0, n = plman.PlaylistCount; i < n; i++) {
if (plman.GetPlaylistName(i) === "Up Next") return i;
}
return -1; // bridge not loaded
}- Resolve by name every time. Never cache the playlist index.
- Edit only
Up Next. Treat it as the queue. Do not start playback from the playlist directly (see Jump command). - Update from playlist callbacks. Bridge synchronisation appears as standard add, remove, and reorder callbacks on
Up Next(see Staying in sync).
All queue operations are performed through edits to the Up Next playlist. The bridge automatically synchronises those changes to the playback queue.
In the examples below, idx = resolvePlaylist() and is assumed to be valid.
Returns the queued tracks in queue order.
Call: plman.GetPlaylistItems(idx) → FbMetadbHandleList
var items = plman.GetPlaylistItems(idx);
for (var i = 0; i < items.Count; i++) {
var handle = items.GetItem(i); // queue position i
}Removes all queued tracks.
Call: plman.ClearPlaylist(idx)
plman.ClearPlaylist(idx);Removes a queued track.
| Parameter | Type | Description |
|---|---|---|
row |
number |
0-based queue position to remove. |
plman.ClearPlaylistSelection(idx);
plman.SetPlaylistSelectionSingle(idx, row, true);
plman.RemovePlaylistSelection(idx);Moves a queued track.
| Parameter | Type | Description |
|---|---|---|
from |
number |
0-based queue position to move. |
to |
number |
Destination gap index (0..count). |
plman.ClearPlaylistSelection(idx);
plman.SetPlaylistSelectionSingle(idx, from, true);
plman.MovePlaylistSelectionV2(idx, to);Playing a specific queued track cannot be represented as a playlist edit. Starting playback from Up Next directly makes it the active playlist, which interferes with queue synchronisation. The bridge therefore exposes this operation as a main-menu command.
Plays the focused row of Up Next and removes it, plus all preceding rows, from the queue.
| Field | Value |
|---|---|
| Menu path | Playback > Atelier: Play From Queue Point |
| Invoke as | fb.RunMainMenuCommand("Playback/Atelier: Play From Queue Point") |
| Parameters | None. The target row is taken from the playlist focus. |
- Set the focus to the target row in
Up Next. - Run the command.
plman.SetPlaylistFocusItem(idx, row);
fb.RunMainMenuCommand("Playback/Atelier: Play From Queue Point");- Reads the focused row.
- Removes that row and all preceding rows from the queue.
- Starts playback from the selected track.
- Removes the played track from
Up Next, along with all preceding rows.
If playback cannot advance (for example, when nothing is currently playing), the selected track remains at the head of the queue. The queue is never cleared.
Bridge updates to Up Next arrive through the normal playlist callbacks. Reload from those callbacks and use a low-frequency polling fallback.
function reload() { /* re-read Up Next, repaint if changed */ }
function on_playlists_changed() { reload(); }
function on_playlist_items_added() { reload(); }
function on_playlist_items_removed() { reload(); }
function on_playlist_items_reordered() { reload(); }
function on_playlist_switch() { reload(); }
window.SetInterval(reload, 1500); // fallback| Identifier | Value |
|---|---|
| Component DLL | foo_atelier_queuebridge.dll |
| Mirror playlist | Up Next |
| Menu command | Playback > Atelier: Play From Queue Point |
| Command GUID | {7A3C1E84-2B59-4D6F-9E11-5C8A2F0B4D63} |
The playlist name and menu command are the public contract. The GUID is an implementation detail; invoke the command by menu path.
The component is non-UI. It registers SDK services only: an initquit, two global callbacks, and a main-menu command. Its sole responsibility is synchronising Up Next with the core queue in both directions.
flowchart LR
subgraph QueueToPlaylist
Q[Queue changes]
P[playback_queue_callback]
S[sync_queue_to_playlist]
Q --> P --> S
end
subgraph PlaylistToQueue
E[Edits to Up Next]
C[Playlist callbacks]
R[rebuild_queue_from_playlist]
E --> C --> R
end
U[Up Next]
CQ[Core queue]
S --> U
R --> CQ
U <--> CQ
Queue > playlist: playback_queue_callback calls sync_queue_to_playlist(), which reads the queue and rebuilds Up Next (playlist_clear + playlist_add_items).
Playlist > queue: playlist callbacks trigger rebuild_queue_from_playlist(), which flushes the queue and rebuilds it from Up Next in order.
Each side triggers the other, so the bridge would otherwise enter a synchronisation loop. g_suppress_sync (managed via an RAII scope) prevents re-entry during internal updates. It preserves the previous state to support nesting.
Queue modification is not allowed inside playlist callbacks and will be dropped by the SDK. The write path therefore defers execution via fb2k::inMainThread(...), ensuring rebuild_queue_from_playlist() runs after the callback unwinds.