diff --git a/config.json b/config.json index 9932158..4be8606 100644 --- a/config.json +++ b/config.json @@ -171,7 +171,10 @@ ] }, { "id": "service", "label": "ALARMS", "pos": [3, 0], "kind": "service" }, - { "id": "atem", "label": "ATEM", "pos": [3, 1], "checks": [{ "type": "conn", "conn": "ATEM" }] }, + { "id": "atem", "label": "ATEM", "pos": [3, 1], "checks": [ + { "type": "conn", "conn": "ATEM" }, + { "type": "pref", "domain": "com.blackmagic-design.ATEM Software Control", "key": "midiEnabled", "want": "0", "msg": "ATEM SW MIDI ON" } + ] }, { "id": "obs", "label": "OBS", "pos": [3, 2], "checks": [{ "type": "conn", "conn": "OBS-Youtube", "service_only": true, "fix": "obs" }] }, { "id": "resi", "label": "RESI", "pos": [3, 3], "checks": [ { "type": "conn", "conn": "RESI_Decoder", "tag": "DECODER" }, diff --git a/status_panel.py b/status_panel.py index 57fe06b..de170d4 100644 --- a/status_panel.py +++ b/status_panel.py @@ -149,6 +149,7 @@ class Snapshot: self.remote_midi_time = {} # host -> when it last reported self.peer_addr = {} # (host or "", session, peer) -> address it was last seen at self.conn_hosts = {} # Companion connection label -> its "host" setting + self.prefs = {} # (preferences domain, key) -> value as "defaults read" prints it self.midi_time = 0.0 self.mdns = set() # Bonjour _apple-midi._udp instance names self.mdns_time = 0.0 @@ -415,6 +416,14 @@ def check_http(chk, snap, ctx): return [("http", Result(OK))] +def check_pref(chk, snap, ctx): + """An app setting on NA Ingest, e.g. ATEM Software Control's "Enable MIDI control" must stay off.""" + value = snap.prefs.get((chk["domain"], chk["key"])) + if value is None or value == str(chk["want"]): + return [("pref", Result(OK))] # not read yet, or as it should be + return [("pref", Result(ERR, chk["msg"], named=True))] + + def check_disk(chk, snap, ctx): free = snap.disk.get(chk["path"]) if free is None: @@ -496,7 +505,7 @@ def check_remote(chk, snap, ctx): CHECKS = { "conn": check_conn, "hyperdeck": check_hyperdeck, "dante": check_dante, "shure": check_shure, "psm": check_psm, "tascam": check_tascam, "ping": check_ping, "launchd": check_launchd, - "process": check_process, "http": check_http, "disk": check_disk, "midi_peer": check_midi_peer, + "process": check_process, "http": check_http, "disk": check_disk, "midi_peer": check_midi_peer, "pref": check_pref, "mdns": check_mdns, "midi_rx": check_midi_rx, "remote": check_remote, "artnet": check_artnet, } @@ -1451,6 +1460,10 @@ def poll_system(snap, cfg): elif c["type"] == "disk": usage = shutil.disk_usage(c["path"]) snap.disk = dict(snap.disk, **{c["path"]: int(usage.free / 1e9)}) + elif c["type"] == "pref": + r = subprocess.run(["/usr/bin/defaults", "read", c["domain"], c["key"]], capture_output=True, + text=True, timeout=5) + snap.prefs[(c["domain"], c["key"])] = r.stdout.strip() if r.returncode == 0 else None snap.procs = procs diff --git a/tests/test_status_panel.py b/tests/test_status_panel.py index e455083..425ff85 100644 --- a/tests/test_status_panel.py +++ b/tests/test_status_panel.py @@ -275,6 +275,14 @@ class TestChecks(unittest.TestCase): self.assertIn("solo_afl", CONFIG["auto_fix"]["fixes"]) self.assertIn('"bad":true', chk["cmd"]) + def test_atem_software_midi_control_must_stay_off(self): + key = ("com.blackmagic-design.ATEM Software Control", "midiEnabled") + engine = sp.Engine(CONFIG) + self.snap.prefs[key] = "0" + self.assertEqual(run_steps(engine, self.snap, self.now, 4)[0]["atem"]["x"], "ATEM\nOK") + self.snap.prefs[key] = "1" + self.assertEqual(run_steps(engine, self.snap, self.now + 5, 4)[0]["atem"]["x"], "ATEM\nATEM SW MIDI ON") + def test_propresenter_yellow_warning_is_ignored(self): engine = sp.Engine(CONFIG) self.snap.conns["Propresenter-API"].update(category="warning", message="Socket closed")