Every MIDI link by wired address: flag links joined by name, hold MIDI moves them, refuse non-wired addresses
Tracks had joined NA Ingest, Lighting PC and Studio B by Bonjour name: macOS picks the network each time, so a reconnect could land on Wi-Fi or Dante. The wired check now also names a link joined by name; holding MIDI moves it to the wired address its own MIDI check names (a hold only: auto-fix never moves a working link). Reconnects prefer a wired address over a Wi-Fi or by-name one they last saw. The settings refuse a MIDI link whose address is a name or off the wired network, and the add-a-link screen fills in the wired address. Studio B's link now has its wired address, and Tracks' link to NA Ingest is watched (TRK INGEST). All links on the four Macs were moved and checked: wired IPv4, running. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+10
-2
@@ -1501,25 +1501,33 @@
|
||||
const macs = Object.entries(c.hosts).filter(([, h]) => h.self || (h.os || "mac") === "mac");
|
||||
const midiKey = c.tiles.find((t) => (t.checks || []).some((ch) => ch.type === "midi_peer"));
|
||||
const fixId = Object.keys(c.fixes).find((id) => c.fixes[id].kind === "midi_connect");
|
||||
// The wired network(s) MIDI must ride (the MIDI key's wired check): suggest and insist on an address on it.
|
||||
const nets = c.tiles.concat((c.ready_page || {}).keys || []).flatMap((t) => (t.checks || []).filter((ch) => ch.type === "midi_wired").flatMap((ch) => ch.nets || []));
|
||||
const ip4 = (a) => { const m = /^(\d+)\.(\d+)\.(\d+)\.(\d+)(?::\d+)?$/.exec(String(a || "").trim()); return m ? m.slice(1, 5).reduce((n, x) => n * 256 + Number(x), 0) : null; };
|
||||
const wired = (a) => { const v = ip4(a); return v !== null && nets.some((n) => { const [b, bits] = String(n).split("/"); const k = Number(bits || 32), base = ip4(b); if (base === null) return false; const mask = k ? (2 ** 32 - 2 ** (32 - k)) : 0; return Math.floor(v / 2 ** (32 - k)) === Math.floor(base / 2 ** (32 - k)) && (mask >= 0); }); };
|
||||
const wiredFor = (peer) => { for (const src of [live.local || {}].concat(Object.values(live.remote || {}))) for (const s of Object.values(src)) for (const p of s.peers || []) if (p.name === peer && wired(p.address)) return p.address;
|
||||
const h = Object.values(c.hosts).find((x) => x.name === peer || (x.midi_name || "") === peer); const ip = h && String(h.ssh || "").split("@").pop(); return ip && wired(ip) ? ip + ":5004" : ""; };
|
||||
const sessionsOf = (alias) => { const h = c.hosts[alias]; const src = h.self ? (live.local || {}) : ((live.remote || {})[alias] || {}); return Object.entries(src).map(([name, v]) => [name, (v.peers || []).map((p) => p.name)]); };
|
||||
dialog(`<h3>MIDI link${hint("A network MIDI session on one of the Macs, and the peer that must stay in it. Pick from what the Macs report now, or type the names if that Mac is off.")}</h3>
|
||||
<select id="jhost">${macs.map(([a, h]) => `<option value="${esc(a)}">${esc(h.name || a)}${h.self ? " (this Mac)" : ""}</option>`).join("")}</select>
|
||||
<input id="jsession" list="jsessions" placeholder="session, as Audio MIDI Setup names it"><datalist id="jsessions"></datalist>
|
||||
<input id="jpeer" list="jpeers" placeholder="peer (the other end)"><datalist id="jpeers"></datalist>
|
||||
<input id="jtag" placeholder="key text when lost (LIGHT PC)" maxlength="10">
|
||||
<input id="jaddr" placeholder="address, if it must be reconnected by address (optional)">
|
||||
<input id="jaddr" placeholder="${nets.length ? "wired address, like 10.1.10.206:5004" : "address, if it must be reconnected by address (optional)"}">
|
||||
<select id="jkey">${midiKey ? `<option value="${esc(midiKey.id)}">on the ${esc(midiKey.label)} key</option>` : ""}<option value="__new">on a new key</option></select>
|
||||
<div class="row"><button class="primary" id="dok">Add</button><button id="dcancel">Cancel</button></div>`, (b) => {
|
||||
b.querySelector("#dcancel").onclick = closeDialog;
|
||||
const fill = () => { const ss = sessionsOf(b.querySelector("#jhost").value); b.querySelector("#jsessions").innerHTML = ss.map(([n]) => `<option value="${esc(n)}">`).join(""); const cur = ss.find(([n]) => n === b.querySelector("#jsession").value) || ss[0]; if (cur && !b.querySelector("#jsession").value) b.querySelector("#jsession").value = cur[0]; b.querySelector("#jpeers").innerHTML = ((cur || [])[1] || []).map((n) => `<option value="${esc(n)}">`).join(""); };
|
||||
b.querySelector("#jhost").onchange = () => { b.querySelector("#jsession").value = ""; fill(); };
|
||||
b.querySelector("#jsession").oninput = fill;
|
||||
b.querySelector("#jpeer").oninput = () => { if (!b.querySelector("#jtag").value) b.querySelector("#jtag").placeholder = tagOf(b.querySelector("#jpeer").value) || "LIGHT PC"; };
|
||||
b.querySelector("#jpeer").oninput = () => { if (!b.querySelector("#jtag").value) b.querySelector("#jtag").placeholder = tagOf(b.querySelector("#jpeer").value) || "LIGHT PC"; const w = wiredFor(b.querySelector("#jpeer").value.trim()); if (w && !b.querySelector("#jaddr").dataset.typed) b.querySelector("#jaddr").value = w; };
|
||||
b.querySelector("#jaddr").oninput = (e) => { e.target.dataset.typed = "1"; };
|
||||
fill();
|
||||
b.querySelector("#dok").onclick = () => {
|
||||
const host = b.querySelector("#jhost").value, session = b.querySelector("#jsession").value.trim(), peer = b.querySelector("#jpeer").value.trim();
|
||||
const tag = b.querySelector("#jtag").value.trim() || tagOf(peer), addr = b.querySelector("#jaddr").value.trim(), keyId = b.querySelector("#jkey").value;
|
||||
if (!session || !peer) return alertBox("A session and a peer, please.");
|
||||
if (nets.length && !wired(addr)) return alertBox(`MIDI rides the wired network (${nets.join(", ")}). Give ${peer}'s wired address, like 10.1.10.206:5004: a name or a Wi-Fi address can drop mid-service.`);
|
||||
if (!ensureDraft()) return;
|
||||
const d = state.draft.config;
|
||||
const chk = Object.assign({ type: "midi_peer", session, peer, tag }, d.hosts[host].self ? {} : { host }, fixId ? { fix: fixId } : {}, addr ? { address: addr } : {});
|
||||
|
||||
Reference in New Issue
Block a user