MIDI: STUDIO B KEY - the Waves Tune key the tracks send really arrives in Studio B
User 2026-10-26: make sure the key Ableton sends changes Waves Tune at FOH and in Studio B. Studio B's Pro Tools can't report the plugin's key, so midi_witness.py (LaunchAgent there) logs every program change on 'Network Tracks Midi' and the watchdog checks it against the song ProPresenter shows (the program that song's Waves Tune clip sends, from the READY look): wrong program, or none after 45 s of a running song, is red. FOH's LiveBox has no network interface: a witness on NA Ingest logs whether it sends anything back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
"""midi_witness.py (2026-10-26, NA): the key changes Studio B really receives, through real CoreMIDI."""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import unittest
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
import coremidi # noqa: E402
|
||||
import midi_witness as mw # noqa: E402
|
||||
|
||||
|
||||
class TestWitness(unittest.TestCase):
|
||||
def test_parses_a_packet(self):
|
||||
self.assertEqual(mw.messages(bytes([0xC0, 7, 0xF8, 0x90, 60, 100, 0xF0, 1, 2, 0xF7, 0xC1, 4])),
|
||||
[(0xC0, b"\x07"), (0x90, b"<d"), (0xC1, b"\x04")])
|
||||
|
||||
def test_writes_down_program_changes_it_really_receives(self):
|
||||
src = coremidi.VirtualSource("witness-test")
|
||||
out = os.path.join(tempfile.mkdtemp(), "w.json")
|
||||
try:
|
||||
w = mw.Witness(["witness-test"], out=out)
|
||||
w.poll()
|
||||
time.sleep(0.3)
|
||||
src.send(bytes([0xC0, 7])) # Ebmaj
|
||||
src.send(bytes([0x90, 60, 100]))
|
||||
src.send(bytes([0xC2, 11]))
|
||||
time.sleep(0.5)
|
||||
w.save()
|
||||
d = json.load(open(out))
|
||||
self.assertTrue(d["sources"]["witness-test"]["connected"])
|
||||
self.assertEqual([p[2:] for p in d["pcs"]], [[1, 7], [3, 11]])
|
||||
self.assertEqual(d["sources"]["witness-test"]["count"], 3)
|
||||
finally:
|
||||
src.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -377,6 +377,30 @@ class TestChecks(unittest.TestCase):
|
||||
tiles, _ = run_steps(sp.Engine(CONFIG), self.snap, sunday + 38 * 60, 4)
|
||||
self.assertEqual(tiles["resi"]["x"], "RESI\nEVENT CHANGE")
|
||||
|
||||
def test_studio_b_got_the_key_the_tracks_sent(self):
|
||||
"""2026-10-26: the key Ableton sends must really change Waves Tune in Studio B (midi_witness.py there)."""
|
||||
import readiness
|
||||
readiness.LAST["tune_sent"] = {"OWE YOU PRAISE": {"clip": "Emaj", "program": 4, "title": "Owe You Praise"}}
|
||||
sunday = datetime(2026, 10, 25, 9, 40).timestamp() # in the auto-fix hours
|
||||
chk = {"type": "tune_rx", "host": "studiob", "name": "STUDIO B"}
|
||||
ctx = {"now": sunday, "any_recording": False, "autofix_windows": CONFIG["auto_fix"]["windows"]}
|
||||
try:
|
||||
self.snap.prop_song = {"name": "Owe You Praise - [ Full ]", "since": sunday - 20, "changes": 3}
|
||||
self.snap.witness = {"studiob": {"read": sunday, "pcs": [[sunday - 18, "Network Tracks Midi", 1, 4]]}}
|
||||
self.assertEqual(sp.check_tune_rx(chk, self.snap, ctx)[0][1].info, "STUDIO B KEY EMAJ")
|
||||
self.snap.witness["studiob"]["pcs"] = [[sunday - 18, "Network Tracks Midi", 1, 7]] # Ebmaj arrived
|
||||
self.assertEqual(sp.check_tune_rx(chk, self.snap, ctx)[0][1].msg, "STUDIO B KEY WRONG")
|
||||
self.snap.witness["studiob"]["pcs"] = [[sunday - 600, "Network Tracks Midi", 1, 4]] # nothing this song
|
||||
self.assertEqual(sp.check_tune_rx(chk, self.snap, ctx)[0][1].level, sp.OK) # only 20 s in
|
||||
self.snap.prop_song["since"] = sunday - 60
|
||||
self.assertEqual(sp.check_tune_rx(chk, self.snap, ctx)[0][1].msg, "STUDIO B GOT NO KEY")
|
||||
self.snap.prop_song["changes"] = 0 # slides still: tracks off
|
||||
self.assertEqual(sp.check_tune_rx(chk, self.snap, ctx)[0][1].level, sp.OK)
|
||||
monday = datetime(2026, 10, 26, 12, 0).timestamp() # outside the hours
|
||||
self.assertEqual(sp.check_tune_rx(chk, self.snap, dict(ctx, now=monday))[0][1].level, sp.OK)
|
||||
finally:
|
||||
readiness.LAST.pop("tune_sent", None)
|
||||
|
||||
def test_resi_audio_silent(self):
|
||||
"""An input stuck at the meter floor (2026-10-25: the Resi AJA passed no Dante audio and nothing said so):
|
||||
red while a deck records (a service is on); between services the Resi send is quiet on purpose."""
|
||||
|
||||
Reference in New Issue
Block a user