From b8748be6554e79dfe1f103a718646b97e138c4cb Mon Sep 17 00:00:00 2001 From: christian Date: Thu, 8 Oct 2026 12:19:26 -0400 Subject: [PATCH] Fix NA Ingest's own DVS from the DANTE button, and stop saying NOTHING TO FIX when something is failing. STUDIO-A-Ingest now maps to a local dvs_ingest fix (same helper as the other Macs, which NA Ingest also needs). A hold on a failing button that has no automatic fix now shows NO AUTO FIX instead of NOTHING TO FIX. Co-Authored-By: Claude Opus 5.5 --- config.json | 4 +++- remote-access/mac-dvs-helper.sh | 2 +- status_panel.py | 16 ++++++++++++++-- tests/test_status_panel.py | 13 +++++++++++++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/config.json b/config.json index 17aefb2..be7d822 100644 --- a/config.json +++ b/config.json @@ -42,6 +42,7 @@ "dvs_prop": { "host": "prop", "short": "DVS", "label": "start Dante Virtual Soundcard on the ProPresenter Mac", "run": "sudo -n /usr/local/sbin/status-panel-dvs-start && open -a 'Dante Virtual Soundcard'" }, "dvs_tracks": { "host": "tracks", "short": "DVS", "label": "start Dante Virtual Soundcard on the Tracks Mac", "run": "sudo -n /usr/local/sbin/status-panel-dvs-start && open -a 'Dante Virtual Soundcard'" }, "dvs_translation": { "host": "translation", "short": "DVS", "label": "start Dante Virtual Soundcard on NA Translation", "run": "sudo -n /usr/local/sbin/status-panel-dvs-start && open -a 'Dante Virtual Soundcard'" }, + "dvs_ingest": { "kind": "local", "short": "DVS", "label": "start Dante Virtual Soundcard on NA Ingest", "run": "sudo -n /usr/local/sbin/status-panel-dvs-start && open -a 'Dante Virtual Soundcard'" }, "bridge": { "kind": "local", "short": "BRIDGE", "label": "restart the Resi bridge", "run": "launchctl kickstart -k gui/$(id -u)/org.waterschurch.resi-propresenter || launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/org.waterschurch.resi-propresenter.plist" }, "captions": { "kind": "local", "short": "CAPTIONS", "label": "restart lobby captions", @@ -70,7 +71,8 @@ { "id": "x32", "label": "X32", "pos": [2, 1], "checks": [{ "type": "conn", "conn": "x32" }] }, { "id": "dante", "label": "DANTE", "pos": [2, 2], "checks": [ { "type": "dante", "conn": "audinate-dantecontroller", - "fix": { "NA-ProPresenter-Mac": "dvs_prop", "NA-Tracks": "dvs_tracks", "NA-Translation": "dvs_translation" }, + "fix": { "NA-ProPresenter-Mac": "dvs_prop", "NA-Tracks": "dvs_tracks", "NA-Translation": "dvs_translation", + "STUDIO-A-Ingest": "dvs_ingest" }, "devices": { "FOH-DiGiCo-DMI-1": "DMI-1", "FOH-DiGiCo-DMI-2": "DMI-2", "BOH-WING": "WING", "BOH-DQ-Rack": "DQ RACK", "BOH-AD4Q-A": "AD4Q-A", "BOH-AD4Q-B": "AD4Q-B", "STUDIO-A-X32": "STA X32", diff --git a/remote-access/mac-dvs-helper.sh b/remote-access/mac-dvs-helper.sh index 465a9f3..902534d 100644 --- a/remote-access/mac-dvs-helper.sh +++ b/remote-access/mac-dvs-helper.sh @@ -1,4 +1,4 @@ -# Paste into Apple Remote Desktop: select NA ProPresenter Mac, NA Tracks, NA Translation -> +# Paste into Apple Remote Desktop: select NA ProPresenter Mac, NA Tracks, NA Translation, NA Ingest -> # Manage -> Send UNIX Command -> "Run command as: User: root" -> Send. # # Lets the status panel start Dante Virtual Soundcard's audio engine, which needs admin rights: diff --git a/status_panel.py b/status_panel.py index b32a775..16e3e85 100644 --- a/status_panel.py +++ b/status_panel.py @@ -754,6 +754,14 @@ class Engine: plan.append((ident, "restart", chk["conn"], chk)) return plan + def failing(self, tile_id): + """Is anything on this button (or its members) in a confirmed fault right now?""" + for key in self.keys_for(tile_id): + tr = self.trackers[key] + if tr.confirmed and tr.result.level in (WARN, ERR): + return True + return False + def note(self, tile_id, text, level, now, seconds): """Show `text` on the button for a while (hold feedback), instead of its usual text.""" self.notes[tile_id] = {"text": text, "level": level, "until": now + seconds} @@ -761,8 +769,12 @@ class Engine: def run_fixes(self, tile_id, snap, comp, now, cooldown=60): plan = self.fix_plan(tile_id, snap) if not plan: - log.info("HOLD %s: nothing failing, nothing to fix", tile_id) - self.note(tile_id, "NOTHING\nTO FIX", "idle", now, 4) + if self.failing(tile_id): + log.info("HOLD %s: failing, but there is no automatic fix for it", tile_id) + self.note(tile_id, "NO AUTO\nFIX", "idle", now, 4) + else: + log.info("HOLD %s: nothing failing, nothing to fix", tile_id) + self.note(tile_id, "NOTHING\nTO FIX", "idle", now, 4) return plan started, names, waited = [], [], False for ident, kind, what, chk in plan: diff --git a/tests/test_status_panel.py b/tests/test_status_panel.py index 79e44ff..601d139 100644 --- a/tests/test_status_panel.py +++ b/tests/test_status_panel.py @@ -530,6 +530,19 @@ class TestFixes(unittest.TestCase): tiles = self.engine.step(self.snap, time.time()) self.assertEqual((tiles["dante"]["x"], level(tiles["dante"])), ("DANTE\nFIX FAILED\nDVS", "failed")) + def test_ingest_dvs_and_no_auto_fix(self): + devices = json.loads(self.snap.vars[("audinate-dantecontroller", "devices")]) + devices.remove("STUDIO-A-Ingest") + self.snap.vars[("audinate-dantecontroller", "devices")] = json.dumps(devices) + self.assertEqual(self.plan("dante"), [("fix", "dvs_ingest")]) + # A failure with no fix (a console) must not claim there is nothing wrong. + devices.append("STUDIO-A-Ingest") + devices.remove("BOH-WING") + self.snap.vars[("audinate-dantecontroller", "devices")] = json.dumps(devices) + _, t = run_steps(self.engine, self.snap, SUNDAY, 4) + self.engine.run_fixes("dante", self.snap, None, t) + self.assertEqual(self.engine.notes["dante"]["text"], "NO AUTO\nFIX") + def test_hold_on_a_green_button_says_so(self): _, t = run_steps(self.engine, self.snap, SUNDAY, 2) self.engine.run_fixes("x32", self.snap, None, t)