logo blechtrottel.net blechtrottel.net
English

websockets und Soundcraft

3. Teil

Javascript websockets für Soundcraft UI-mixer

einleitung

Im zweiten teil dieser anleitung ging es um das ansteuern des mixers via Javascript. Das funktioniert gut, allerdings kann nicht mit sicherheit gesagt werden, ob auch alle befehle vom mixer umgesetzt wurden. Die änderungen der anzeige im infofeld stammen ja aus dem javascript auf der seite. Neue informationen schickt der Soundcraft UI nur, wenn die seite neu geladen wird und damit eine neue websocket-verbindung aufgebaut.

Um die aktuellen einstellungen ohne neuladen zu erhalten, muss man auf die datei http://10.10.1.1/js/initparams.js zugreifen. (10.10.1.1 ist dabei die ip-adresse des mixers in dessen eigenen wlan und muss ggf. angepasst werden.)

Wir schreiben dafür eine funktion.

function getParams() { dataValue = {}; activeChs = ''; fetch("http://10.10.1.1/js/initparams.js", { cache: 'no-cache', }) .then(initparams => { return(initparams.text()); })

Der erste abschnitt der funktion holt die datei vom server; die anweisung cache: 'no-cache' stellt sicher, dass die datei immer neu heruntergeladen wird. Danach holen wir den inhalt von initparams.js als text.

Daraus nehmen wir den ganzen abschnitt zwischen dataValue= und der abschließenden geschwungenen klammer. Den beginn und ein etwaiges , vor dieser klammer am ende entfernen wir. Aus dem ergebnis erstellen wir eine eigeness JSON-objekt namens dataValue.

.then(txt => { dV = txt.match(/dataValue.*\}/)[0]; dV = dV.replace('dataValue=', ''); dV = dV.replace(',}', '}'); dataValue = JSON.parse(dV); })

Eine forEach-schleife holt für jedes instrument den mutestatus aus dataValue, speichert ihn in die textvariable activeChs und gibt ihn in das info-feld aus.

.then(() => { instruments.forEach((instrument, iid) => { mute = dataValue["i." + iid + ".mute"]; activeChs += mute; mutestatus = (mute == '0') ? "ein" : "aus"; info.innerHTML += "Kanal " + (iid*1+1) + ": " + instrument + " " + mutestatus + "<br>"; }) })

Im letzen schritt wird überprüft, ob die abfolge der mute-einstellungen in der variable activeChs einer der tasten entspricht und ggf. deren farbe gesetzt.

.then(() => { if (activeChs == '0011' || activeChs == '1100') { buttons[activeChs.substr(0,1)].classList.add('active'); } });

Die funktion changeInstruments() aus dem zweiten teil dieser anleitung kann jetzt noch angepasst werden, damit sie nach dem druck auf eine der tasten das ergebnis über die neue funktion getParams() prüft und anzeigt.

function changeInstruments(chls) { info.innerHTML = ''; buttons.forEach(button => { button.classList.remove('active'); }); if (socket.readyState == 1) { chls = chls.match(/\d+/g); instruments.forEach((instrument, iid) => { mute = ((iid == chls[0]-1) || (iid == chls[1]-1)) ? 0 : 1; socket.send('3:::SETD^i.' + iid + '.mute^' + mute); }); getParams(); } else { console.log("Keine Verbindung zum Server."); } }

CORS

Die datei initparams liegt aber auf einem anderen server als unser javascript. Deshalb kommt es meist zu zugriffsproblemen, die das abrufen und auslesen behindern. Es gibt aber für praktisch jeden browser eine erweiterung, die dem browser sagen kann, er möge den html-header ignorieren. Nicht alle erweiterungen erlauben dabei eine eigene seite im format file://websocketsui.html.

In test hat unter Firefox CORS Everywhere gut funktioniert. Unter Android gibt es eine bearbeitete version namens CORS for ME.

download

Wer dieses beispiel gerne selbst ausprobieren möchte, aber keine lust zum abtippen hat, kann diese datei herunterladen.

1. teil - 2. teil - 3. teil

weiterführendes

Wer über diese einfachen funktionen hinaus doch eine umfangreiche javascript-bibliothek für die kommunikation mit seinem mixer nutzen möchte, sei auf das projekt von Ferdinand Malcher verwiesen.