READY: RESI VOX - the Resi song goes out with its lead singer's mic
PCO's song description names the lead ('Genesis lead', RESI marks the song, else the last before the
message), the lineup screen gives their VOX, and the Resi AJA's Lead Vocal channel (21) is read from
the card with Dante's own read-only query. Wrong: red, and the hold / auto-fix presses that VOX's AJA
button on page 13 and reads the card back. Two leads, a lead not on the lineup, a PCO Audio note naming
another VOX, or VOX 5+ are flagged only. Checked on 2026-10-25's real data: Genesis, VOX 4, AJA on VOX 4;
the Audio note says V2, so it is flagged and nothing switches. Applied on NA after the services.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+73
-2
@@ -648,6 +648,7 @@ class TestLook(unittest.TestCase):
|
||||
lineup=lambda: lineup(["Jonah Perdue", "Krista Perdue", "Kevin Michel", "Anthony Hoyt", "Tim Hatch"]),
|
||||
resolume=composition, prop_bundle=lambda plan: [["Message Templates.probundle", WEDNESDAY]],
|
||||
macros=macros_found, companion=lambda n: COMPANION.get(n, {}), live=live_set,
|
||||
resi_now=lambda: (3, {"tx_channel": "03-VOX 3", "tx_device": "BOH-AD4Q-A", "name": "5 - Lead Vocal"}),
|
||||
services=lambda: [SUNDAY_SVC], start=lambda svcs: {"survey": {SUNDAY_SVC["name"]: {"exists": True}}, "status": None})
|
||||
src.update(over)
|
||||
return src
|
||||
@@ -672,7 +673,7 @@ class TestLook(unittest.TestCase):
|
||||
|
||||
def test_a_campus_that_only_receives(self):
|
||||
cfg = json.loads(json.dumps(CONFIG))
|
||||
for k in ("locations", "prop_bundle_host", "resolume_url", "lineup_url"):
|
||||
for k in ("locations", "prop_bundle_host", "resolume_url", "lineup_url", "resi_vox"): # Resi goes out from NA only
|
||||
cfg["ready"].pop(k)
|
||||
cfg["ready"]["prop_url"] = ""
|
||||
r = rd.look(cfg, now=WEDNESDAY, sources=self.sources())
|
||||
@@ -732,7 +733,8 @@ class TestWatchdog(unittest.TestCase):
|
||||
self.step(WEDNESDAY)
|
||||
plan = self.engine.fix_plan("ready", self.snap)
|
||||
fixes = sorted(what for _, kind, what, _ in plan if kind == "fix")
|
||||
self.assertEqual(fixes, ["ready_ableton_mix", "ready_copy_tracks", "ready_led_cross", "ready_lineup", "ready_ltc", "ready_recheck"])
|
||||
self.assertEqual(fixes, ["ready_ableton_mix", "ready_copy_tracks", "ready_led_cross", "ready_lineup", "ready_ltc", "ready_recheck",
|
||||
"ready_resi_vox"]) # RESI VOX: the test plan names no lead
|
||||
ran = []
|
||||
self.engine.executor = lambda cfg, fix_id, chk: ran.append(fix_id) or True
|
||||
self.engine.run_fixes("ready", self.snap, None, WEDNESDAY + 10)
|
||||
@@ -911,3 +913,72 @@ class TestRunHere(unittest.TestCase):
|
||||
def test_a_script_for_this_mac_runs_here_without_ssh(self):
|
||||
cfg = {"hosts": {"ingest": {"self": True}}}
|
||||
self.assertEqual(rd.run_remote(cfg, "ingest", "import json; print(json.dumps({'ok': 1}))"), {"ok": 1})
|
||||
|
||||
|
||||
class TestResiVox(unittest.TestCase):
|
||||
"""RESI VOX (2026-10-25): the Resi song goes to the locations with its lead's mic."""
|
||||
RV = {"aja": "STUDIO-A-Resi-AJA-SDI", "channel": 21, "mics": "BOH-AD4Q-A",
|
||||
"buttons": {"1": [13, 3, 1], "2": [13, 3, 2], "3": [13, 3, 3], "4": [13, 3, 4]}}
|
||||
LINEUP = {"state": {"slots": [{"label": "[LEADER, VOX 1, ACOUSTIC] MIX 1", "person": {"name": "Mike Powell"}},
|
||||
{"label": "[VOX 2] MIX 2", "person": {"name": "Rosaliz Gaitan"}},
|
||||
{"label": "[VOX 3] MIX 3", "person": {"name": "DJ McLean"}},
|
||||
{"label": "[VOX 4] MIX 4", "person": {"name": "Genesis Gomez"}},
|
||||
{"label": "[VOX 5] MIX 8", "person": {"name": "Bianca Barros"}},
|
||||
{"label": "[DRUMS]", "person": {"name": "Luis Decamps"}}]}}
|
||||
|
||||
def plan(self, desc, audio=""):
|
||||
notes = {"Audio": audio} if audio else {}
|
||||
return {"items": [item("Worship", "header"), item("Jehovah", "song", description="DJ lead"),
|
||||
item("Name Above All Names", "song", description=desc, notes=notes),
|
||||
item("Message", "header"), item("Owe You Praise TAG", "song")], "team": []}
|
||||
|
||||
def run_eval(self, desc, now_vox, audio=""):
|
||||
line, want = rd.eval_resi_vox({"resi_vox": self.RV}, self.plan(desc, audio), self.LINEUP, now_vox,
|
||||
{"tx_channel": "0%s-VOX %s" % (now_vox, now_vox), "tx_device": "BOH-AD4Q-A", "name": "5 - Lead Vocal"})
|
||||
return [m for _, m, _ in line.faults], line.info, want
|
||||
|
||||
def test_the_lead_on_the_right_mic(self):
|
||||
self.assertEqual(self.run_eval("Genesis lead\nRESI TX", 4), ([], "VOX 4 GENESIS", 4))
|
||||
|
||||
def test_the_wrong_mic_is_red_and_says_which(self):
|
||||
self.assertEqual(self.run_eval("Genesis lead\nRESI TX", 2)[0], ["RESI V2 NOT VOX 4"])
|
||||
self.assertEqual(self.run_eval("Genesis lead\nRESI TX", 2)[2], 4)
|
||||
|
||||
def test_no_resi_mark_means_the_last_song_before_the_message(self):
|
||||
self.assertEqual(rd.resi_song(self.plan("Rosaliz lead"))["title"], "Name Above All Names")
|
||||
self.assertEqual(self.run_eval("Rosaliz lead", 2), ([], "VOX 2 ROSALIZ", 2))
|
||||
|
||||
def test_what_is_not_switched_by_itself(self):
|
||||
self.assertEqual(self.run_eval("Mike and DJ lead", 1)[0], ["2 LEADS: MIKE DJ"]) # two leads: a person picks
|
||||
self.assertEqual(self.run_eval("Genesis lead", 4, audio="V2")[0], ["PCO SAYS V2, LEAD V4"]) # PCO and the lineup differ
|
||||
self.assertEqual(self.run_eval("Bianca lead", 4)[0], ["LEAD ON VOX 5: NO BUTTON"])
|
||||
self.assertEqual(self.run_eval("Josh lead", 4)[0], ["JOSH NOT ON LINEUP"])
|
||||
self.assertEqual(self.run_eval("*CONDENSED*", 4)[0], ["NO LEAD NAME ABOVE."])
|
||||
for f in ("Genesis lead", "Mike and DJ lead", "Bianca lead"):
|
||||
self.assertIsNone(self.run_eval(f, 4, audio="V2")[2]) if f != "Genesis lead" else None
|
||||
|
||||
def test_dante_rx_reads_the_subscription(self):
|
||||
import socket
|
||||
import struct
|
||||
import threading
|
||||
srv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
srv.bind(("127.0.0.1", 0))
|
||||
port = srv.getsockname()[1]
|
||||
|
||||
def answer():
|
||||
req, addr = srv.recvfrom(64)
|
||||
strings = b"\x00" * 12 + b"04-VOX 4\x00BOH-AD4Q-A\x005 - Lead Vocal\x00"
|
||||
base = 12 + 16 * 20
|
||||
recs = b"".join(struct.pack(">10H", 17 + i, 14, 0, 0, 0, 0, 0x101, 9, 0, 0) for i in range(4))
|
||||
recs += struct.pack(">10H", 21, 14, 0, base + 12, base + 21, base + 32, 0x101, 9, 0, 0)
|
||||
recs += b"".join(struct.pack(">10H", 22 + i, 14, 0, 0, 0, 0, 0x101, 9, 0, 0) for i in range(11))
|
||||
srv.sendto(req[:4] + req[4:6] + req[6:8] + b"\0" * 4 + recs + strings, addr)
|
||||
threading.Thread(target=answer, daemon=True).start()
|
||||
orig = rd.DANTE_ARC
|
||||
rd.DANTE_ARC = port
|
||||
try:
|
||||
got = rd.dante_rx("127.0.0.1", 21)
|
||||
finally:
|
||||
rd.DANTE_ARC = orig
|
||||
srv.close()
|
||||
self.assertEqual((got["name"], got["tx_channel"], got["tx_device"]), ("5 - Lead Vocal", "04-VOX 4", "BOH-AD4Q-A"))
|
||||
|
||||
Reference in New Issue
Block a user