A native macOS menu-bar app written in Swift, zero dependencies, that talks directly to specific home AV hardware on the local network. No cloud, no IFTTT, no HomeKit bridge — just WebSocket, HTTP, ADB, SSDP, Wake-on-LAN, and mDNS aimed at five named devices.
It’s deliberately scoped as a personal project exploring what local-network device control feels like when you skip the smart-home middleware. It works for the specific stack listed below; the ROADMAP sketches the path to a configurable, distributable version.
Supported devices
| Device | Protocol | On | Off | Status |
|---|---|---|---|---|
| Cambridge Audio CXN v2 | StreamMagic WebSocket (SMOIP) | power cycle | WebSocket | live polling |
| LG webOS TV | SSAP WebSocket + WoL | Wake-on-LAN | SSAP turnOff | WebSocket registration |
| NVIDIA Shield | ADB over network | wake keyevent | sleep keyevent | dumpsys power |
| Xbox | SSDP | — | — | unicast probe |
| Plex Media Server | HTTP API | — | — | active session count |
The protocol mix is the interesting part. Each device speaks something different, none of them speak HomeKit, and most are not designed to be controlled from a Mac at all. The app shims them into a single menu-bar surface where toggles and status rows behave consistently.
Features
- Toggle rows for CXN, TV, and Shield with live state indicators
- Status rows for Xbox (SSDP) and Plex server (active stream count)
- Roon session toggle — power-cycles the CXN, launches and quits Roon in a single click
- Plex session toggle — wakes the Shield and launches Plex on the TV
- Shield app launcher — a Services submenu with brand icons for 16 streaming/media apps (Netflix, Disney+, Apple TV, Stremio, BBC iPlayer, etc.), launched via ADB intents
- Plex library scans — Movies / TV / Music scans triggered from the menu
- Configurable services list — settings sheet to show or hide apps in the Shield submenu
- mDNS discovery — finds the CXN via Bonjour and resolves the TV’s IP from MAC via ARP, so device addresses survive DHCP changes
- Launch at Login via the native
SMAppServiceAPI - No dock icon (menu-bar only via
LSUIElement)
Build and configuration
swiftc against AppKit and Foundation produces the binary; that gets dropped into a hand-rolled .app bundle. Requires macOS 13+, Swift 5, and adb (for the Shield).
brew install android-platform-tools
cd MenuBarApp
swiftc -o HiFiControl HiFiControl.swift \
-framework AppKit -framework Foundation -swift-version 5
cp HiFiControl "HiFi Control.app/Contents/MacOS/HiFi Control"
Device IPs, the TV MAC, and the Plex token live in a gitignored config.local file at the project root — never committed, read at launch:
TV_MAC=AA:BB:CC:DD:EE:FF
CXN_IP=192.168.1.x
TV_IP=192.168.1.x
SHIELD_IP=192.168.1.x
XBOX_IP=192.168.1.x
PLEX_IP=192.168.1.x
PLEX_TOKEN=your_plex_token_here
Pairing notes
- CXN v2 — no pairing; the StreamMagic API is open on the LAN
- LG webOS TV — accept the prompt on the TV the first time. The app uses the same pairing key
lgtv2writes (~/Library/Preferences/lgtv2/), so a one-time Node helper handles the handshake - NVIDIA Shield — enable Network Debugging in Developer Options, accept the ADB authorisation prompt on first connection. After that the app talks to the Shield over TCP 5555
Why a single Swift file
The whole app is one HiFiControl.swift. No package manifest, no Xcode project, no SwiftUI — just NSStatusItem, NSMenu, URLSession, and the relevant network primitives. That decision pays off on a project like this: protocol exploration moves much faster when there’s nothing between you and the wire. Once the surface stabilises, the ROADMAP calls for a proper Swift Package Manager layout, an SwiftUI settings UI, and a configurable device registry — but the single-file shape was the right starting point.
Status
Experimental. It runs reliably for this hardware mix and has been on a daily-driver Mac for some months without rewrites — but device IDs are hard-coded, error handling is “log and shrug” in places, and the configuration model assumes you know your network. The scope question for the next phase is whether to make it a configurable end-user app, a library other people can build their own menus on top of, or a public reference for “how to talk to home AV devices on a local network without the cloud.”