Skip to main content

songbird-collab

Real-time collaboration infrastructure for multi-user DAW sessions.

What it owns

  • Peer management and operation logs.
  • WebSocket transport to the Node.js collab server (server/server.js).
  • Throttled mixer broadcasting.
  • State, session, and transport synchronization across peers.

Public API

Modules:
  • collab — top-level session lifecycle, peer management, room join/leave.
  • collab_transport — WebSocket connection to server/server.js.
  • collab_mixer_sync — debounced/throttled mixer-parameter broadcast and apply.
  • collab_state_sync — full project state push/pull and merge integration.

How it fits

Sits between songbird-state (source of truth being synced) and the network. Consumed by songbird-state, songbird-app, songbird-engine.
React UI                                     Other Peer
  ├─ services/collabSocket.ts                  ↑
  ├─ services/collabMixerSync.ts               │
  └─ data/slices/collab.ts                     │
       │ sync engine (collab.* commands)       │
       ▼                                       │
  songbird-sync::channels::collab               │
       │                                       │
       ▼                                       │
  songbird-collab    ───WebSocket───►   server/server.js
  (this crate)                          (Node.js)


                                        merge/{bird-merge.js,json-merge.js}
All UI ↔ Rust traffic goes through the sync engine — see AGENTS.md §3 and the collab channel at rust/crates/data/songbird-sync/src/channels/collab/. There is no direct Tauri command path for collab; everything is a collab.* command or collab:* event.

Sync Protocol

Wire messages between the Rust client and server/server.js:
DirectionTypeDescription
Client → ServercreateCreate room, returns invite code
Client → ServerjoinJoin room with invite code
Client → ServerpushPush file changes after a local commit
Client → ServerpullRequest current file state
Client → ServerpresenceCursor / tool position
Server → ClientcreatedRoom created + invite code
Server → ClientjoinedJoined + files + peer list
Server → ClientupdateRemote changes (post-merge)
Server → ClientpushAckPush acknowledged
Server → ClientpresenceRemote cursor update
Server → ClientpeerJoinedPeer connectivity
Server → ClientpeerLeftPeer disconnect
The collab sync-engine channel translates these into typed events consumed by React (see defs.rs for the full enum).

Merge Strategy

Performed by the Node.js server, not by this crate — but consumers should understand the contract:
  • .bird files: parsed into a structured tree (sig → tracks → arr → sections → tracks). Merged at track-per-section granularity. Two users editing different tracks in the same section auto-merge.
  • .mixer.json, .plugins.json: recursive deep merge at the per-track-property level. Different controls auto-merge.
  • Conflicts: last-write-wins (the incoming push takes precedence).
Server-side merge code lives in server/merge/{bird-merge.js,json-merge.js}.

Echo Prevention (critical)

When applying remote files, the client must set the undoRedoInProgress guard so the local commit loop does not echo the changes back to the server. This reuses the same guard mechanism as undo/redo. Skipping this causes infinite sync loops between two peers. Full guard semantics: rust/crates/data/songbird-state/SPEC.md.

Running the collab server locally

./utils/collab-server.sh           # default port 8765
PORT=9000 ./utils/collab-server.sh # custom port

Tests

cargo test -p songbird-collab            # Rust client tests
node server/test-merge.js                # 7 server-side merge tests
For multi-peer browser testing, follow the e2e-headless skill — open two browser sessions and exercise create/join/push/pull through the UI. See AGENTS.md §6 for the mandatory browser-testing rule that applies here.