IntercomServer binds web server (8080) and media port (50000) to the clinic
interface only. Phones post an SDP offer and receive talkback (Opus) and the
PGM preview (H.264 constrained baseline, 960x540, 25 fps).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Single cipher suite (ECDHE-ECDSA-AES128-GCM-SHA256), client certificate
checked against the SDP fingerprint, extended master secret.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Building blocks for a minimal WebRTC stack on CryptoKit/CommonCrypto,
verified against RFC 5769, RFC 3711 and OpenSSL vectors.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As a login item macOS launched Musubi without its window, so the SwiftUI
.task never ran: no outputs, no remote control after a reboot. An app
delegate now starts discovery and the coordinator in applicationDidFinishLaunching.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Right after launch macOS briefly reports 'Local network prohibited'; the
connection then stayed in waiting and was never retried. Connect attempts now
time out after 6 s and start over; the waiting reason is logged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The mode switch posts didChangeScreenParameters synchronously; reconcile ran
nested before the output was registered and opened a second window/receiver,
which stayed visible after stopping. Register first, never nest reconcile,
handle the notification asynchronously. Switching sources keeps the 50 Hz mode.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Coordinator: restores live state on launch, role-based Bonjour server/browser,
node adopts commands, control keeps desired config per node and re-sends on reconnect
- Scene menu (load, save, save as, export, import), settings (role, interface, login item)
- Remote screens with status on the control; node banner
- Developer ID signing with hardened runtime and audio-input entitlement
- Retry and clear message when macOS blocks Bonjour
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Scene = control config + config per node; screens matched by name, then position
- Remote module: length-prefixed JSON messages, NodeServer (Bonjour on the
technical interface), NodeBrowser with auto-reconnect
- ChannelSelection moves to MusubiCore
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- NDIReceiver captures audio (audio-only bandwidth for sound routes)
- AUHAL output per device, mic input via AUHAL, fan-out to routes
- Drift-compensated, allocation-free render path; backlog trimmed on start
- Global talk key (Ctrl-Option-Space, hold or toggle) gates mic routes
- Sound tab with channel strips, meters, gain, mute, L/R/L+R
- --audio-route launch argument, per-minute audio CSV, 10 s diagnostics log
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Senders like NDI Test Patterns send a still image once; a held NDI connection
now counts as alive so the receiver does not reconnect in a loop.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- NDIReceiver: per-source receive thread, IOSurface pixel buffers, watchdog reconnect
- VideoOutput: borderless output window above menu bar, AVSampleBufferVideoRenderer,
50 Hz display mode for app lifetime, display sleep assertion
- Screen cards with drag and drop, live fps and frame loss
- Per-minute stats CSV in ~/Library/Logs/Musubi for long-run tests
- --route launch argument for scripted tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- XcodeGen project: macOS 14, universal (arm64 + x86_64), studio.zielke.musubi
- MusubiKit package: MusubiCore, NDIKit (+ CNDI module map), VideoOutput,
AudioMatrix, DesignSystem (symlink to design/Theme.swift)
- Main window with NDI source list, NDI version logged at launch
- Swift Testing suite for MusubiCore models
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>