Woonsocket's startup list covered: M32, SoundGrid link, MIDI on Macs without python

From the WS Production Startup checklist (check.watersmedia.org):
- M32 (the "X32" there is a Midas M32 at 10.2.1.146): Woonsocket's Companion got the X32/M32
  module (imported from NA's copy through Companion's own API) and an m32 connection; auto-setup
  names a single M32 connection's key M32.
- SuperRack's link to the Waves SoundGrid server: a soundgrid check builder (SuperRack's control
  connection on port 19000) inside every SUPERRACK key.
- MIDI ("Open Audio MIDI"): Macs without the Command Line Tools have their sessions read with
  JavaScript for Automation (coremidi.JXA_SESSIONS) - by the watchdog every 2 s and by discovery. A
  peer with no state (older macOS) counts as configured. A peer joined by name or IPv6 gets the
  wired address of the Mac whose session it is (matched by session name), at that session's port.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-20 16:48:28 -04:00
co-authored by Claude Opus 5.5
parent e1c9b2f974
commit 457335bc96
6 changed files with 98 additions and 4 deletions
+22
View File
@@ -207,6 +207,28 @@ def disconnect_peer(session_name, peer_name):
return "not connected" if result == "unchanged" else result
# The same read as sessions(), for a Mac without python (no Command Line Tools): macOS's own
# JavaScript for Automation calls CoreMIDI directly, nothing to install. Prints the sessions as JSON.
# Older macOS keeps no "state" for a peer; a peer without one is listed as configured, no verdict.
JXA_SESSIONS = r"""
ObjC.import('CoreMIDI'); ObjC.import('Foundation');
function str(o, k) { var r = Ref(); if ($.MIDIObjectGetStringProperty(o, k, r) !== 0) return null; return ObjC.unwrap(ObjC.castRefToObject(r[0])); }
function dict(o, k) { var r = Ref(); if ($.MIDIObjectGetDictionaryProperty(o, k, r) !== 0) return null; return ObjC.deepUnwrap(ObjC.castRefToObject(r[0])); }
var out = {}, n = $.MIDIGetNumberOfDevices();
for (var i = 0; i < n; i++) {
var dev = $.MIDIGetDevice(i), drv = str(dev, $('driver')) || '';
if (drv.indexOf('Network') < 0 && drv.toLowerCase().indexOf('rtp') < 0) continue;
for (var j = 0; j < $.MIDIDeviceGetNumberOfEntities(dev); j++) {
var ent = $.MIDIDeviceGetEntity(dev, j), s = dict(ent, $('apple.midirtp.session'));
if (!s) continue;
out[s['dns-sd-name'] || str(ent, $('name')) || '?'] = {port: s.port, peers: (s.peers || []).map(function (p) {
var q = {name: p.name, address: p.address}; if (p.state !== undefined) q.state = p.state; return q; })};
}
}
'SPMIDI' + JSON.stringify(out);
"""
def sessions():
"""{session name: {"port": int, "peers": [{"name", "address", "state"}]}}"""
found = {}