diff --git a/plugins/artnet/icon.png b/plugins/artnet/icon.png new file mode 100644 index 0000000..8ab4d7b Binary files /dev/null and b/plugins/artnet/icon.png differ diff --git a/plugins/artnet/icon.psd b/plugins/artnet/icon.psd new file mode 100644 index 0000000..7abee51 Binary files /dev/null and b/plugins/artnet/icon.psd differ diff --git a/plugins/artnet/info.html b/plugins/artnet/info.html new file mode 100644 index 0000000..4284f4e --- /dev/null +++ b/plugins/artnet/info.html @@ -0,0 +1,2 @@ +

Art-Net requires no configuration.

+

Art-Netâ„¢ Designed by and Copyright Artistic Licence Holdings Ltd

\ No newline at end of file diff --git a/plugins/artnet/main.js b/plugins/artnet/main.js new file mode 100644 index 0000000..519a5ef --- /dev/null +++ b/plugins/artnet/main.js @@ -0,0 +1,119 @@ +const _ = require('lodash'); + +exports.defaultName = "Art-Net"; +exports.connectionType = 'UDPsocket'; +exports.heartbeatInterval = 10000; +exports.searchOptions = { + type: 'UDPsocket', + searchBuffer: Buffer.from([65, 114, 116, 45, 78, 101, 116, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00]), + devicePort: 6454, + listenPort: 6454, + validateResponse (msg, info, devices) { + return msg.toString('utf8', 0, 7) === "Art-Net"; + } +}; +exports.defaultPort = 6454; + +exports.ready = function ready(device) { + const d = device; + d.data.universes = {}; + d.data.orderedUniverses = []; + +}; + +exports.data = function data(device, buf) { + if(buf.length < 18){ + return + } + const univ = buf.readUInt8(14); + const d = device; + let u = d.data.universes[univ]; + + if(!u){ + d.data.universes[univ] = {}; + u = d.data.universes[univ]; + } + + u.sequence = buf.readUInt8(12); + u.net = buf.readUInt8(15); + u.opCode = buf.readUInt8(9); + u.version = buf.readUInt16BE(10); + u.slots = Array.prototype.slice.call(buf, 18); + d.data.ip = d.addresses[0]; + + if(!_.includes(d.data.orderedUniverses, univ)){ + d.data.orderedUniverses.push(univ); + d.data.orderedUniverses.sort(); + u.slotElems = []; + u.slotElemsSet = false; + + d.draw(); + updateElementsCache(d, d.data.universes, d.data.orderedUniverses); + + } + + device.update("universeData", { + u: univ, + universe: u + }); + + +}; + + +exports.heartbeat = function heartbeat(device) { + +}; + + + +let lastUpdate = Date.now(); +exports.update = function update(device, document, updateType, updateData){ + + const data = updateData; + const doc = document; + + if(updateType === "universeData" && data.universe){ + + if(Date.now() - lastUpdate > 1000){ + lastUpdate = Date.now(); + updateElementsCache(device, device.data.universes, device.data.orderedUniverses); + } + + const $elem = doc.getElementById(`universe-${data.u}`); + + if($elem && data.universe.slotElemsSet){ + + for(let i = 0; i < 512; i++){ + data.universe.slotElems[i].innerText = data.universe.slots[i]; + } + + doc.getElementById(`universe-${data.u}-sequence`).innerText = data.universe.sequence; + + + }else{ + device.draw(); + updateElementsCache(device, device.data.universes, device.data.orderedUniverses); + } + + }else if(updateType === "elementCache"){ + + data.orderedUniverses.forEach(univ => { + for(let i = 0; i < 512; i++){ + data.universes[univ].slotElems[i] = doc.getElementById(`${univ}-${i}`); + } + data.universes[univ].slotElemsSet = true; + }); + + } + + +} + +function updateElementsCache(device, univ, ordered){ + device.update("elementCache", { + universes: univ, + orderedUniverses: ordered + }); +} + diff --git a/plugins/artnet/styles.css b/plugins/artnet/styles.css new file mode 100644 index 0000000..fbd5beb --- /dev/null +++ b/plugins/artnet/styles.css @@ -0,0 +1,29 @@ +table { + margin-bottom: 50px; + background-color: #333; +} +td, +th { + width: 35px; +} +td { + background-color: black; + text-align: center; + border-radius: 3px; + color: white; + font-size: 13px; +} +th { + background-color: #222; + color: #ccc; + font-size: 11px; +} +td.data { + padding: 7px; + font-size: 12px; + text-align: left; +} +td.data em { + font-size: 14px; + color: #008bd2; +} diff --git a/plugins/artnet/template.ejs b/plugins/artnet/template.ejs new file mode 100644 index 0000000..8373f98 --- /dev/null +++ b/plugins/artnet/template.ejs @@ -0,0 +1,64 @@ +
+

<%= data.source %> Art-Net

+
+ + +
+<% data.orderedUniverses.forEach(univ => { + let universe = data.universes[univ]; +%> + + + + + + + + + + + + + + + + <% for(col=1; col<=16; col++){ %> + + <% } %> + + + <% let slot = 0; %> + <% for(row=0; row<32; row++){ %> + + + <% for(col=0; col<16; col++){ %> + <% slot++%> + + <% } %> + + <% } %> + + +
+ Universe +
<%= univ %> +
+ Sub-Net +
<%= universe.net %> +
+ Sequence +
<%= universe.sequence %> +
+ OpCode +
<%= universe.opCode %> +
+ Version +
<%= universe.version %> +
+ IP +
<%= data.ip %> +
<%= col %>
<%= row*16+1 %><%= universe.slots[slot-1] %>
+ +<% }); %> + +
\ No newline at end of file diff --git a/plugins/eos/info.html b/plugins/eos/info.html new file mode 100644 index 0000000..bd6e1c1 --- /dev/null +++ b/plugins/eos/info.html @@ -0,0 +1,15 @@ +

Connection Requirements

+ +

Shell/ECU → Network

+ +If the "Third Party OSC" option is not available, Eos must be updated to 3.1 or newer. + +

System Settings → Show Control → OSC

+ \ No newline at end of file diff --git a/plugins/eos/main.js b/plugins/eos/main.js index 2160eac..08eed38 100644 --- a/plugins/eos/main.js +++ b/plugins/eos/main.js @@ -1,7 +1,6 @@ -let _ = require('lodash'); +const _ = require('lodash'); const fs = require('fs'); - exports.defaultName = 'ETC Eos'; exports.connectionType = 'osc'; exports.searchOptions = { @@ -11,71 +10,55 @@ exports.searchOptions = { 'ascii' ), testPort: 3032, - validateResponse: function (msg, info) { + validateResponse (msg, info) { return msg.toString().indexOf('/eos/out'); }, }; -exports.defaultPort = 3032; +exports.defaultPort = 3037; -// "\xc0/eos/ping\x00\x00\x2c\x00\x00\x00\xc0" -exports.ready = function (device) { +exports.ready = function ready(device) { device.send('/eos/get/cuelist/count'); device.send('/eos/get/version'); device.send('/eos/subscribe', [{ type: 'i', value: 1 }]); }; -exports.data = function (device, osc) { - const address = osc.address; +exports.data = function data(device, osc) { const p = osc.address.split('/'); + const d = device; p.shift(); - //console.log(address) + // console.log(osc.address) - if (p[1] == 'out' && p[2] == 'show' && p[3] == 'name') { - device.data.showName = osc.args[0]; - device.data.cuelists = {}; + if (match(p, ['eos','out','show','name'])) { + d.data.showName = osc.args[0]; + d.data.cuelists = {}; this.deviceInfoUpdate(device, 'defaultName', osc.args[0]); - } else if (osc.address == '/eos/out/get/cuelist/count') { + } else if (match(p, ['eos','out','get','cuelist','count'])) { for (let i = 0; i < osc.args[0]; i++) { - device.send(`/eos/get/cuelist/index/${i}`); + d.send(`/eos/get/cuelist/index/${i}`); } - } else if ( - p[1] == 'out' && - p[2] == 'get' && - p[3] == 'cuelist' && - p[5] == 'list' - ) { - device.data.cuelists[p[4]] = {}; - device.send(`/eos/get/cue/${p[4]}/count`); + } else if (match(p, ['eos','out','get','cuelist','*','list','*','*'])) { + d.data.cuelists[p[4]] = {}; + d.send(`/eos/get/cue/${p[4]}/count`); - } else if ( - p[1] == 'out' && - p[2] == 'get' && - p[3] == 'cue' && - p[5] == 'count' - ) { + } else if (match(p, ['eos','out','get','cue','*','count'])) { for (let i = 0; i < osc.args[0]; i++) { device.send(`/eos/get/cue/${p[4]}/index/${i}`); } - } else if ( - p[1] == 'out' && - p[2] == 'get' && - p[3] == 'cue' && - p[7] == 'list' - ) { + } else if (match(p, ['eos','out','get','cue','*','*','*','list','*','*'])) { this.deviceInfoUpdate(device, 'status', 'ok'); - if (device.data.cuelists[p[4]][p[5]] == undefined) { - device.data.cuelists[p[4]][p[5]] = {}; + if (d.data.cuelists[p[4]][p[5]] === undefined) { + d.data.cuelists[p[4]][p[5]] = {}; } - device.data.cuelists[p[4]][p[5]][p[6]] = { + d.data.cuelists[p[4]][p[5]][p[6]] = { uid: osc.args[1], label: osc.args[2], uptimeduration: osc.args[3], @@ -111,56 +94,34 @@ exports.data = function (device, osc) { }); - } else if (p[1] == 'out' && p[2] == 'get' && p[3] == 'cue' && p.length == 6) { - // console.log("cue "+p[4]+" "+p[5]+" deleted") - + } else if (match(p, ['eos','out','get','cue','*','*'])) { // There's no OSC notification of the deletion of a part. It just tells you to update the parent cue and remaining children. // So: we should fetch all the parts of a cue somehow every time there's an update to a cue. - - delete device.data.cuelists[p[4]][p[5]]; - device.draw(); + delete d.data.cuelists[p[4]][p[5]]; + d.draw(); - } else if ( - p[1] == 'out' && - p[2] == 'get' && - p[3] == 'cue' && - p[7] == 'actions' - ) { - if (osc.args.length == 3) { - device.data.cuelists[p[4]][p[5]][0].extlinks = osc.args[2]; + } else if (match(p, ['eos','out','get','cue','*','*','*','actions','list','*','*'])) { + if (osc.args.length === 3) { + d.data.cuelists[p[4]][p[5]][0].extlinks = osc.args[2]; } - } else if ( - p[1] == 'out' && - p[2] == 'event' && - p[3] == 'cue' && - p[6] == 'fire' - ) { - device.data.activeCue = p[5]; - - device.draw(); - device.update("activeCue", {uid: device.data.cuelists[p[4]][p[5]][0].uid}); + } else if (match(p, ['eos','out','event','cue','*','*','fire'])) { + d.data.activeCue = p[5]; + d.draw(); + d.update("activeCue", {uid: device.data.cuelists[p[4]][p[5]][0].uid}); - } else if (p[1] == 'out' && p[2] == 'notify' && p[3] == 'cue') { + } else if (match(p, ['eos','out','notify','cue','*','*','*','*'])) { const cueList = p[4]; - const listIndex = p[6]; - const listCount = p[7]; const cueNumber = osc.args[1]; - device.send(`/eos/get/cue/${cueList}/${cueNumber}`); + d.send(`/eos/get/cue/${cueList}/${cueNumber}`); - } else if ( - p[2] == 'cmd' || - p[2] == 'ping' || - p[2] == 'user' || - p[2] == 'softkey' - ) { - } else if (p[3] == 'version') { - device.data.version = osc.args[0]; + } else if (match(p, ['eos','out','get','version'])) { + d.data.version = osc.args[0]; } else { @@ -170,12 +131,13 @@ exports.data = function (device, osc) { // console.log(p) }; -let cueTemplate = _.template(fs.readFileSync(`./plugins/eos/cue.ejs`)); -exports.update = function(device, doc, updateType, data){ +const cueTemplate = _.template(fs.readFileSync(`./plugins/eos/cue.ejs`)); - if(updateType == "cueData"){ - $elem = doc.getElementById(data.uid); +exports.update = function update(device, doc, updateType, data){ + + if(updateType === "cueData"){ + const $elem = doc.getElementById(data.uid); if($elem){ $elem.outerHTML = cueTemplate({ @@ -189,8 +151,8 @@ exports.update = function(device, doc, updateType, data){ } - }else if(updateType == "activeCue"){ - $elem = doc.getElementById(data.uid); + }else if(updateType === "activeCue"){ + const $elem = doc.getElementById(data.uid); $elem.scrollIntoView({behavior: "smooth", block: "center"}); } @@ -199,6 +161,20 @@ exports.update = function(device, doc, updateType, data){ } -exports.heartbeat = function (device) { +exports.heartbeat = function heartbeat(device) { device.send('/eos/ping'); }; + + +function match(osc, array){ + let out = true; + if(osc.length !== array.length){ + return false; + } + array.forEach((m, i)=> { + if(osc[i] !== m && m !== "*"){ + out = false; + } + }); + return out; +} \ No newline at end of file diff --git a/plugins/eos/styles.css b/plugins/eos/styles.css index 8c14427..7f17bbd 100644 --- a/plugins/eos/styles.css +++ b/plugins/eos/styles.css @@ -25,7 +25,7 @@ td.num { font-weight: 600; font-size: 16px; } - + .scene { background-color: black; border-top: #141414 2px solid; @@ -51,13 +51,13 @@ td.num { tr.active-cue { color: #c78b07; } -tr.active-cue td.num div{ - margin: 0px; - padding: 1px 6px; - background-color: #c78b07; - border-radius: 4px; - color: black; - } +tr.active-cue td.num div { + margin: 0px; + padding: 1px 6px; + background-color: #c78b07; + border-radius: 4px; + color: black; +} tr.active-cue .time { border-color: #c78b07; } diff --git a/plugins/eos/template.ejs b/plugins/eos/template.ejs index daf77b8..b77c514 100644 --- a/plugins/eos/template.ejs +++ b/plugins/eos/template.ejs @@ -44,5 +44,3 @@ <% } %> - - diff --git a/plugins/pjlink/info.html b/plugins/pjlink/info.html new file mode 100644 index 0000000..edbdc3c --- /dev/null +++ b/plugins/pjlink/info.html @@ -0,0 +1,4 @@ +

Connection Requirements

+ \ No newline at end of file diff --git a/plugins/pjlink/main.js b/plugins/pjlink/main.js index a7cf3a5..80586cf 100644 --- a/plugins/pjlink/main.js +++ b/plugins/pjlink/main.js @@ -9,13 +9,13 @@ exports.searchOptions = { searchBuffer: Buffer.from([0x25, 0x32, 0x53, 0x52, 0x43, 0x48, 0x0d]), devicePort: 4352, listenPort: 4352, - validateResponse: function (msg, info) { + validateResponse (msg, info) { return msg.toString().indexOf('%2ACKN=') >= 0; }, }; exports.defaultPort = 4352; -exports.ready = function (device) { +exports.ready = function ready(device) { // Power status query // device.send("%1POWR ?\r"); }; @@ -23,96 +23,99 @@ let password = false; function processPJLink(device, str, that) { const arr = str.split('%'); - for (var key in arr) { - var split = arr[key].split('='); - var key = split[0]; - var value = split[1]; + const d = device; - switch (key) { - case '1POWR': - device.data.power = value; - break; - case '1INPT': - device.data.input = value; - break; - case '1AVMT': - device.data.avmute = value; - break; - case '1ERST': - device.data.fanError = value[0]; - device.data.lampError = value[1]; - device.data.tempError = value[2]; - device.data.coverError = value[3]; - device.data.filterError = value[4]; - device.data.otherError = value[5]; - break; - case '1LAMP': - device.data.lamp = value.split(' '); - break; - case '1NAME': - device.data.name = value; - that.deviceInfoUpdate(device, 'defaultName', device.data.name); - break; - case '1INF1': - device.data.info1 = value; - break; - case '1INF2': - device.data.info2 = value; - break; - case '2SNUM': - device.data.serial = value; - break; - case '2SVER': - device.data.version = value; - break; + arr.forEach((p) => { + const split = arr[p].split('='); + const key = split[0]; + const value = split[1]; + + if(key === '1POWR'){ + d.data.power = value; + + }else if(key === '1INPT'){ + d.data.input = value; + + }else if(key === '1AVMT'){ + d.data.avmute = value; + + }else if(key === '1ERST'){ + d.data.fanError = value[0]; + d.data.lampError = value[1]; + d.data.tempError = value[2]; + d.data.coverError = value[3]; + d.data.filterError = value[4]; + d.data.otherError = value[5]; + + }else if(key === '1LAMP'){ + d.data.lamp = value.split(' '); + + }else if(key === '1NAME'){ + d.data.name = value; + that.deviceInfoUpdate(d, 'defaultName', d.data.name); + + }else if(key === '1INF1'){ + d.data.info1 = value; + + }else if(key === '1INF2'){ + d.data.info2 = value; + + }else if(key === '2SNUM'){ + d.data.serial = value; + + }else if(key === '2SVER'){ + d.data.version = value; + } - } - device.draw(); + }); + + d.draw(); + } -exports.data = function (device, message) { +exports.data = function data(device, message) { this.deviceInfoUpdate(device, 'status', 'ok'); const msg = message.toString(); - if (msg.substring(0, 8) == 'PJLINK 1') { + if (msg.substring(0, 8) === 'PJLINK 1') { password = md5(`${msg.substring(9, 17)}JBMIAProjectorLink`); device.send( `${password}%1POWR ?\r%1INPT ?\r%1AVMT ?\r%1ERST ?\r%1LAMP ?\r%1NAME ?\r%1INF1 ?\r%1INF2 ?\r%2SNUM ?\r%2SVER ?\r` ); } - if (msg.substring(0, 7) == '%1POWR=') { + if (msg.substring(0, 7) === '%1POWR=') { processPJLink(device, msg, this); } - if (msg.substring(0, 7) == '%1INPT=') { + if (msg.substring(0, 7) === '%1INPT=') { processPJLink(device, msg, this); } - if (msg.substring(0, 7) == '%1AVMT=') { + if (msg.substring(0, 7) === '%1AVMT=') { processPJLink(device, msg, this); } - if (msg.substring(0, 7) == '%1ERST=') { + if (msg.substring(0, 7) === '%1ERST=') { processPJLink(device, msg, this); } - if (msg.substring(0, 7) == '%1LAMP=') { + if (msg.substring(0, 7) === '%1LAMP=') { processPJLink(device, msg, this); } - if (msg.substring(0, 7) == '%1NAME=') { + if (msg.substring(0, 7) === '%1NAME=') { processPJLink(device, msg, this); } - if (msg.substring(0, 7) == '%1INF1=') { + if (msg.substring(0, 7) === '%1INF1=') { processPJLink(device, msg, this); } - if (msg.substring(0, 7) == '%1INF2=') { + if (msg.substring(0, 7) === '%1INF2=') { processPJLink(device, msg, this); } - if (msg.substring(0, 7) == '%2SNUM=') { + if (msg.substring(0, 7) === '%2SNUM=') { processPJLink(device, msg, this); } - if (msg.substring(0, 7) == '%2SVER=') { + if (msg.substring(0, 7) === '%2SVER=') { processPJLink(device, msg, this); } }; -exports.heartbeat = function (device) { +exports.heartbeat = function heartbeat(device) { if (password) { device.send( `${password}%1POWR ?\r%1INPT ?\r%1AVMT ?\r%1ERST ?\r%1LAMP ?\r%1NAME ?\r%1INF1 ?\r%1INF2 ?\r%2SNUM ?\r%2SVER ?\r` diff --git a/plugins/qlab/cart.ejs b/plugins/qlab/cart.ejs index e5b263b..6b76b4f 100644 --- a/plugins/qlab/cart.ejs +++ b/plugins/qlab/cart.ejs @@ -10,12 +10,10 @@ <% for(let r=0; r <% for(let c=0; c -
+ <% let style = `style="left:${width*c}%; top:${height*r}px; width:${width }%; height:${height}px;"`; %> + +
>
+ <% } %> <% } %> diff --git a/plugins/qlab/cue.ejs b/plugins/qlab/cue.ejs index 30bb8f2..0198dd7 100644 --- a/plugins/qlab/cue.ejs +++ b/plugins/qlab/cue.ejs @@ -157,17 +157,18 @@ if(value>0){ let percent = value/def*100; - let bg = "background: black; background: linear-gradient(90deg, "+fill+" "+percent+"%, transparent "+percent+"%);"; + let bg = `style='background: black; background: linear-gradient(90deg, ${fill} ${percent}%, transparent ${percent}%);`; if(cue.paused){ bg+= "outline-color: "+border+";"; bg+= "color: white;"; } + bg+="'"; - return "
"+prettyFormatTime(Math.min(def, value))+""; + return `
"+prettyFormatTime(Math.min(def, value))+"`; }else if(type=="postWait" || type=="action"){ - return ""+prettyFormatTime(def)+""; + return `${prettyFormatTime(def)}`; }else{ return prettyFormatTime(def); diff --git a/plugins/qlab/info.html b/plugins/qlab/info.html new file mode 100644 index 0000000..5ca65d1 --- /dev/null +++ b/plugins/qlab/info.html @@ -0,0 +1,4 @@ +

Connection Requirements

+
    +
  • No Passcode
  • +
\ No newline at end of file diff --git a/plugins/qlab/main.js b/plugins/qlab/main.js index 8009d8b..c70f689 100644 --- a/plugins/qlab/main.js +++ b/plugins/qlab/main.js @@ -1,4 +1,4 @@ -let _ = require('lodash'); +const _ = require('lodash'); const fs = require('fs'); let lastElapsedUpdate = Date.now(); @@ -12,66 +12,62 @@ exports.searchOptions = { bonjourName: 'qlab', }; -exports.ready = function (device) { +exports.ready = function ready(device) { device.send(`/version`); device.send('/workspaces'); }; -exports.data = function (device, oscData) { - const address = oscData.address; - let osc = oscData.address.split('/'); +exports.data = function data(device, oscData) { + const osc = oscData.address.split('/'); osc.shift(); - - let data; + const d = device; - //console.log(address) + // console.log(oscData.address) if(match(osc, ["reply", "version"])){ - let json = JSON.parse(oscData.args[0]); - device.data.version = json.data; + const json = JSON.parse(oscData.args[0]); + d.data.version = json.data; - this.deviceInfoUpdate(device, 'status', 'ok'); + this.deviceInfoUpdate(d, 'status', 'ok'); }else if(match(osc, ["reply", "workspaces"])){ - let json = JSON.parse(oscData.args[0]); - device.data.workspaces = {}; + const json = JSON.parse(oscData.args[0]); + d.data.workspaces = {}; json.data.forEach(wksp => { - device.data.workspaces[wksp.uniqueID] = { + d.data.workspaces[wksp.uniqueID] = { uniqueID: wksp.uniqueID, displayName: wksp.displayName, cueLists: {}, cues: {} } - device.send(`/workspace/${wksp.uniqueID}/connect`); + d.send(`/workspace/${wksp.uniqueID}/connect`); }); - console.log(device.data.workspaces); - }else if(match(osc, ["reply", "workspace", "*", "connect"])){ - device.send(`/workspace/${osc[2]}/updates`, [ + d.send(`/workspace/${osc[2]}/updates`, [ { type: 'i', value: 1 }, ]); - device.send(`/workspace/${osc[2]}/cueLists`); + d.send(`/workspace/${osc[2]}/cueLists`); }else if(match(osc, ["reply", "workspace", "*", "cueLists"])){ - this.deviceInfoUpdate(device, 'status', 'ok'); + this.deviceInfoUpdate(d, 'status', 'ok'); - let workspace = device.data.workspaces[osc[2]]; - let json = JSON.parse(oscData.args[0]); + const workspace = d.data.workspaces[osc[2]]; + const json = JSON.parse(oscData.args[0]); workspace.cueLists = {}; workspace.cues = {}; @@ -82,13 +78,13 @@ exports.data = function (device, oscData) { addChildrenToWorkspace(workspace, ql); }); - device.draw(); + d.draw(); - setTimeout(function(){ + setTimeout(() => { json.data.forEach(ql => { workspace.cueLists[ql.uniqueID] = ql; - getValuesForKeys(device, json.workspace_id, ql); + getValuesForKeys(d, json.workspace_id, ql); }); }, 0); @@ -96,31 +92,32 @@ exports.data = function (device, oscData) { }else if(match(osc, ["reply", "cue_id", "*", "children"])){ - let json = JSON.parse(oscData.args[0]); - let workspace = device.data.workspaces[json.workspace_id]; - let cue_id = osc[2]; - let cue = workspace.cues[cue_id]; + const json = JSON.parse(oscData.args[0]); + const workspace = d.data.workspaces[json.workspace_id]; + const cueID = osc[2]; + const cue = workspace.cues[cueID]; if(!_.isEqual(cue.cues, json.data)){ - workspace.cueLists[cue_id].cues = json.data; - addChildrenToWorkspace(workspace, workspace.cueLists[cue_id]); + workspace.cueLists[cueID].cues = json.data; + addChildrenToWorkspace(workspace, workspace.cueLists[cueID]); - device.draw(); + d.draw(); - getValuesForKeys(device, json.workspace_id, cue); + getValuesForKeys(d, json.workspace_id, cue); } }else if(match(osc, ["reply", "cue_id", "*", "valuesForKeys"])){ - let json = JSON.parse(oscData.args[0]); - let cueValues = json.data; + const json = JSON.parse(oscData.args[0]); + const cueValues = json.data; - let workspace = device.data.workspaces[json.workspace_id]; + const workspace = d.data.workspaces[json.workspace_id]; let cue = workspace.cues[cueValues.uniqueID]; if(!cue){ - cue = workspace.cues[cueValues.uniqueID] = {}; + workspace.cues[cueValues.uniqueID] = {}; + cue = workspace.cues[cueValues.uniqueID]; } cue.uniqueID = cueValues.uniqueID; @@ -149,15 +146,15 @@ exports.data = function (device, oscData) { cue.actionElapsed = cueValues.actionElapsed; cue.postWaitElapsed = cueValues.postWaitElapsed; - let nestedGroupModes = []; - let nestedGroupPosition = [0]; - var obj = cue; + const nestedGroupModes = []; + const nestedGroupPosition = [0]; + let obj = cue; - while(obj.parent!="[root group of cue lists]"){ + while(obj.parent !== "[root group of cue lists]"){ nestedGroupModes.push(obj.groupMode); let pos = _.findIndex(workspace.cues[obj.parent].cues, {uniqueID: obj.uniqueID}); - pos= Math.abs(pos-workspace.cues[obj.parent].cues.length)-1; + pos = Math.abs(pos - workspace.cues[obj.parent].cues.length) - 1; nestedGroupPosition.push(pos) obj = workspace.cues[obj.parent]; @@ -165,61 +162,61 @@ exports.data = function (device, oscData) { cue.nestedGroupModes = nestedGroupModes; cue.nestedGroupPosition = nestedGroupPosition; - //console.log("draw "+cue.number) + // console.log("draw "+cue.number) - device.update("updateCueData", {cue: cue, allCues: workspace.cues, workspace: workspace}); + d.update("updateCueData", {'cue': cue, 'allCues': workspace.cues, 'workspace': workspace}); }else if(match(osc, ["reply", "cue_id", "*", "preWaitElapsed"])){ - let json = JSON.parse(oscData.args[0]); - let workspace = device.data.workspaces[json.workspace_id]; - let cue = workspace.cues[osc[2]]; + const json = JSON.parse(oscData.args[0]); + const workspace = d.data.workspaces[json.workspace_id]; + const cue = workspace.cues[osc[2]]; cue.preWaitElapsed = json.data; lastElapsedUpdate = Date.now(); - device.update("updateCueData", {cue: cue, allCues: workspace.cues, workspace: workspace}); + d.update("updateCueData", {'cue': cue, 'allCues': workspace.cues, 'workspace': workspace}); }else if(match(osc, ["reply", "cue_id", "*", "actionElapsed"])){ - let json = JSON.parse(oscData.args[0]); - let workspace = device.data.workspaces[json.workspace_id]; - let cue = workspace.cues[osc[2]]; + const json = JSON.parse(oscData.args[0]); + const workspace = d.data.workspaces[json.workspace_id]; + const cue = workspace.cues[osc[2]]; cue.actionElapsed = json.data; lastElapsedUpdate = Date.now(); - device.update("updateCueData", {cue: cue, allCues: workspace.cues, workspace: workspace}); + d.update("updateCueData", {'cue': cue, 'allCues': workspace.cues, 'workspace': workspace}); }else if(match(osc, ["reply", "cue_id", "*", "postWaitElapsed"])){ - let json = JSON.parse(oscData.args[0]); - let workspace = device.data.workspaces[json.workspace_id]; - let cue = workspace.cues[osc[2]]; + const json = JSON.parse(oscData.args[0]); + const workspace = device.data.workspaces[json.workspace_id]; + const cue = workspace.cues[osc[2]]; cue.postWaitElapsed = json.data; lastElapsedUpdate = Date.now(); - device.update("updateCueData", {cue: cue, allCues: workspace.cues, workspace: workspace}); + d.update("updateCueData", {'cue': cue, 'allCues': workspace.cues, 'workspace': workspace}); }else if(match(osc, ["update", "workspace", "*", "cue_id", "*"])){ - let workspace = device.data.workspaces[osc[2]]; + const workspace = d.data.workspaces[osc[2]]; if(workspace){ - let cueLists = Object.keys(workspace.cueLists); - let cue_id = osc[4]; + const cueLists = Object.keys(workspace.cueLists); + const cueID = osc[4]; - if(cue_id!="[root group of cue lists"){ - if(cueLists.includes(cue_id)){ - device.send(`/workspace/${workspace.uniqueID}/cue_id/${cue_id}/children`); + if(cueID !== "[root group of cue lists"){ + if(cueLists.includes(cueID)){ + d.send(`/workspace/${workspace.uniqueID}/cue_id/${cueID}/children`); } - device.send(`/workspace/${osc[2]}/cue_id/${cue_id}/valuesForKeys`, [ + d.send(`/workspace/${osc[2]}/cue_id/${cueID}/valuesForKeys`, [ {type: 's', value: valuesForKeysString} ]); @@ -229,40 +226,40 @@ exports.data = function (device, oscData) { }else if(match(osc, ["update", "workspace", "*"])){ // occurs when cue lists are reordered or a list is deleted - device.send(`/workspace/${osc[2]}/cueLists`); + d.send(`/workspace/${osc[2]}/cueLists`); }else if(match(osc, ["update", "workspace", "*", "dashboard"])){ - //this workspace might be new, let's check - - if(device.data.workspaces[osc[2]]){ + // this workspace might be new, let's check + if(d.data.workspaces[osc[2]]){ + // }else{ console.log("new workspace!"); - device.send('/workspaces'); + d.send('/workspaces'); } }else if(match(osc, ["update", "workspace", "*", "cueList", "*", "playbackPosition"])){ - let workspace = device.data.workspaces[osc[2]]; + const workspace = d.data.workspaces[osc[2]]; if(workspace){ - let cue = workspace.cues[oscData.args[0]]; + const cue = workspace.cues[oscData.args[0]]; if(cue){ workspace.playbackPosition = oscData.args[0] ? cue.uniqueID : ""; - device.update("updatePlaybackPosition", {cue: cue}); + d.update("updatePlaybackPosition", {'cue': cue}); } } }else if(match(osc, ["update", "workspace", "*", "disconnect"])){ - delete device.data.workspaces[osc[2]]; - device.draw(); + delete d.data.workspaces[osc[2]]; + d.draw(); }else{ - //console.log(address) + // console.log(address) } @@ -270,25 +267,24 @@ exports.data = function (device, oscData) { }; -let cueTemplate = _.template(fs.readFileSync(`./plugins/qlab/cue.ejs`)); -let tileTemplate = _.template(fs.readFileSync(`./plugins/qlab/tile.ejs`)); -let cartTemplate = _.template(fs.readFileSync(`./plugins/qlab/cart.ejs`)); -let listTemplate = _.template(fs.readFileSync(`./plugins/qlab/cuelist.ejs`)); +const cueTemplate = _.template(fs.readFileSync(`./plugins/qlab/cue.ejs`)); +const tileTemplate = _.template(fs.readFileSync(`./plugins/qlab/tile.ejs`)); +const cartTemplate = _.template(fs.readFileSync(`./plugins/qlab/cart.ejs`)); -exports.update = function(device, doc, updateType, data){ +exports.update = function update(device, doc, updateType, data){ - if(updateType=="updateCueData"){ - $elem = doc.getElementById(data.cue.uniqueID); + if(updateType === "updateCueData"){ + const $elem = doc.getElementById(data.cue.uniqueID); if($elem){ - if(data.cue.type=="Cue List"){ - $elem.outerHTML = '

'+data.workspace.displayName+' — '+data.cue.name+'

'; + if(data.cue.type === "Cue List"){ + $elem.outerHTML = `

${data.workspace.displayName} — ${data.cue.name}

`; - }else if(data.cue.type=="Cart"){ - $elem.outerHTML = cartTemplate({tileTemplate: tileTemplate, cueList: data.cue, allCues: data.workspace.cues}); + }else if(data.cue.type === "Cart"){ + $elem.outerHTML = cartTemplate({'tileTemplate': tileTemplate, 'cueList': data.cue, 'allCues': data.workspace.cues}); - }else if(data.cue.cartPosition && data.cue.cartPosition[0]!=0){ + }else if(data.cue.cartPosition && data.cue.cartPosition[0] !== 0){ $elem.outerHTML = tileTemplate(data); }else{ @@ -296,13 +292,13 @@ exports.update = function(device, doc, updateType, data){ } } - }else if(updateType=="updatePlaybackPosition"){ + }else if(updateType === "updatePlaybackPosition"){ Array.from(doc.getElementsByClassName("playback-position")).forEach( - function($elem, index, array) { + ($elem, index, array) => { $elem.classList.remove("playback-position"); }); - $elem = doc.getElementById(data.cue.uniqueID); + const $elem = doc.getElementById(data.cue.uniqueID); $elem.classList.add("playback-position"); $elem.scrollIntoView({behavior: "smooth", block: "center"}); @@ -319,30 +315,31 @@ exports.update = function(device, doc, updateType, data){ const valuesForKeysString = '["uniqueID","number","name","listName","isBroken","isRunning","isLoaded","isFlagged",' -+'"type","children","preWait","postWait","currentDuration","colorName","continueMode",' -+'"mode","parent","cartRows","cartColumns","cartPosition","displayName","preWaitElapsed",' -+'"actionElapsed","postWaitElapsed","isPaused"]'; ++ '"type","children","preWait","postWait","currentDuration","colorName","continueMode",' ++ '"mode","parent","cartRows","cartColumns","cartPosition","displayName","preWaitElapsed",' ++ '"actionElapsed","postWaitElapsed","isPaused"]'; function addChildrenToWorkspace(workspace, q){ - workspace.cues[q.uniqueID] = q; - workspace.cues[q.uniqueID].nestedGroupModes = []; - workspace.cues[q.uniqueID].nestedGroupPosition = []; + const w = workspace; + w.cues[q.uniqueID] = q; + w.cues[q.uniqueID].nestedGroupModes = []; + w.cues[q.uniqueID].nestedGroupPosition = []; if(q.cues){ - q.cues.forEach(q => { - addChildrenToWorkspace(workspace, q); + q.cues.forEach(cue => { + addChildrenToWorkspace(w, cue); }); } } -function getValuesForKeys(device, workspace_id, q){ - device.send(`/workspace/${workspace_id}/cue_id/${q.uniqueID}/valuesForKeys`, [ +function getValuesForKeys(device, workspaceID, q){ + device.send(`/workspace/${workspaceID}/cue_id/${q.uniqueID}/valuesForKeys`, [ {type: 's', value: valuesForKeysString} ]); if(q.cues){ - q.cues.forEach(q => { - getValuesForKeys(device, workspace_id, q); + q.cues.forEach(cue => { + getValuesForKeys(device, workspaceID, cue); }); } } @@ -350,11 +347,11 @@ function getValuesForKeys(device, workspace_id, q){ function match(osc, array){ let out = true; - if(osc.length!=array.length){ + if(osc.length !== array.length){ return false; } - array.forEach((match, i)=> { - if(osc[i]!=match && match!="*"){ + array.forEach((m, i)=> { + if(osc[i] !== m && m !== "*"){ out = false; } }); @@ -363,16 +360,16 @@ function match(osc, array){ let interval = 5; let heartbeatCount = 0; -exports.heartbeat = function (device) { +exports.heartbeat = function heartbeat(device) { heartbeatCount++; - if(Date.now()-lastElapsedUpdate>300){ + if(Date.now() - lastElapsedUpdate > 300){ interval = 5; }else{ interval = 1; } - if(heartbeatCount%interval==0){ + if(heartbeatCount % interval === 0){ device.send(`/cue/active/preWaitElapsed`); device.send(`/cue/active/actionElapsed`); device.send(`/cue/active/postWaitElapsed`); diff --git a/plugins/qlab/styles.css b/plugins/qlab/styles.css index f97bb37..9fc38f0 100644 --- a/plugins/qlab/styles.css +++ b/plugins/qlab/styles.css @@ -170,77 +170,73 @@ tr.playback-position .q-gray-text { color: #424242; } .q-time-elapsed { - margin: 0px 2px; - outline: #49c042 1px solid; + margin: 0px 2px; + outline: #49c042 1px solid; line-height: 18px; } - - - -.cart{ +.cart { position: relative; - height: 600px; - width: 100%; + height: 600px; + width: 100%; background-color: #2c2b2a; } -.cartCueWrapper{ - display: block; +.cartCueWrapper { + display: block; position: absolute; box-sizing: border-box; - padding: 3px; + padding: 3px; } -.cartCue{ - height: 100%; +.cartCue { + height: 100%; box-sizing: border-box; - border: 3px solid; - border-radius: 6px; - color: white; + border: 3px solid; + border-radius: 6px; + color: white; } -.cartCue p{ - margin: 10px; +.cartCue p { + margin: 10px; } -.cartCueIcon{ +.cartCueIcon { position: absolute; - right: 13px; - top: 13px; + right: 13px; + top: 13px; } -.cartColor-red{ - border-color: #ff4242; - background-color: #9b3726; +.cartColor-red { + border-color: #ff4242; + background-color: #9b3726; } -.cartColor-orange{ - border-color: #ffa500; +.cartColor-orange { + border-color: #ffa500; background-color: #ad6026; } -.cartColor-green{ - border-color: #01d52f; +.cartColor-green { + border-color: #01d52f; background-color: #397f27; } -.cartColor-blue{ - border-color: #536de0; +.cartColor-blue { + border-color: #536de0; background-color: #304893; } -.cartColor-purple{ - border-color: #a601c0; +.cartColor-purple { + border-color: #a601c0; background-color: #592d74; } -.cartColor-none{ - border-color: #95929f; - background-color: #3b3b3b +.cartColor-none { + border-color: #95929f; + background-color: #3b3b3b; } -.cartBlank{ - border-color: #1f1f1f; +.cartBlank { + border-color: #1f1f1f; background-color: #1f1f1f; } -.cartCueWrapper.playback-position .cartCue{ - border-color: #88b3db; - outline: #88b3db 1px solid; +.cartCueWrapper.playback-position .cartCue { + border-color: #88b3db; + outline: #88b3db 1px solid; box-shadow: 0px 0px 3px 3px #88b3db, inset 0px 0px 5px #88b3db; } - @media screen and (min-width: 0px) and (max-width: 750px) { .hide-medium { display: none; diff --git a/plugins/qlab/tile.ejs b/plugins/qlab/tile.ejs index 7d8a128..ca8e9e2 100644 --- a/plugins/qlab/tile.ejs +++ b/plugins/qlab/tile.ejs @@ -14,26 +14,24 @@ left = (cue.cartPosition[1]-1)*width; } + let style = `style="left:${left}%; top:${top}px; width:${width }%; height:${height}px;"`; + %> -
+
> -
- <% if(cue.broken){ %> - - <% }else if(cue.running){ %> - - <% }else{ %> - - <% } %> -
-
-

<%= cue.number %> • <%= cue.displayName %>

-
+
+ <% if(cue.broken){ %> + + <% }else if(cue.running){ %> + + <% }else{ %> + + <% } %> +
-
\ No newline at end of file +
+

<%= cue.number %> • <%= cue.displayName %>

+
+ +
\ No newline at end of file diff --git a/plugins/sacn/icon.png b/plugins/sacn/icon.png new file mode 100644 index 0000000..ef9783e Binary files /dev/null and b/plugins/sacn/icon.png differ diff --git a/plugins/sacn/icon.psd b/plugins/sacn/icon.psd new file mode 100644 index 0000000..9e2d797 Binary files /dev/null and b/plugins/sacn/icon.psd differ diff --git a/plugins/sacn/info.html b/plugins/sacn/info.html new file mode 100644 index 0000000..4e4c755 --- /dev/null +++ b/plugins/sacn/info.html @@ -0,0 +1 @@ +

sACN requires no configuration.

\ No newline at end of file diff --git a/plugins/sacn/main.js b/plugins/sacn/main.js new file mode 100644 index 0000000..bf9f3a0 --- /dev/null +++ b/plugins/sacn/main.js @@ -0,0 +1,158 @@ +const _ = require('lodash'); + +exports.defaultName = 'sACN Universe'; +exports.connectionType = 'multicast'; +exports.defaultPort = 5568; +exports.heartbeatInterval = 5000; +exports.searchOptions = { + type: "multicast", + address: getMulticastGroup(1), + port: 5568, + validateResponse (msg, info) { + return msg.toString('utf8', 4, 13) === "ASC-E1.17"; + }, +}; +exports.defaultPort = 5568; + +exports.ready = function ready(device) { + + const d = device; + d.data.universes = {}; + d.data.source = "Unknown Source"; + d.data.orderedUniverses = []; + + // device.draw(); + for(let i = 1; i <= 16; i++){ + d.connection.addMembership(getMulticastGroup(i)); + } + +}; + + +exports.data = function data(device, buf) { + + const univ = buf.readUInt16BE(113); + const d = device; + + let u = d.data.universes[univ]; + + if(!u){ + d.data.universes[univ] = {}; + u = d.data.universes[univ]; + } + + u.sequence = buf.readUInt8(111); + u.priority = buf.readUInt8(108); + u.cid = buf.toString('hex', 22, 38); + u.slots = Array.prototype.slice.call(buf, 126); + if(buf.readUInt8(125) !== 0){ + u.startCode = buf.readUInt8(125); + } + + + d.data.source = buf.toString('utf8', 44, 108); + d.displayName = `${d.data.source} sACN`; + d.data.ip = d.addresses[0]; + + if(!_.includes(d.data.orderedUniverses, univ)){ + d.data.orderedUniverses.push(univ); + d.data.orderedUniverses.sort(); + u.slotElems = []; + u.slotElemsSet = false; + + d.draw(); + updateElementsCache(d, d.data.universes, d.data.orderedUniverses); + + } + + d.update("universeData", { + u: univ, + universe: u, + startCode: u.startCode + }); + +}; + + +exports.heartbeat = function heartbeat(device) { + +}; + + + +let lastUpdate = Date.now(); +exports.update = function update(device, doc, updateType, updateData){ + + const d = device; + const data = updateData; + + if(updateType === "universeData" && data.universe){ + + if(Date.now() - lastUpdate > 1000){ + lastUpdate = Date.now(); + updateElementsCache(d, d.data.universes, d.data.orderedUniverses); + } + + const $elem = doc.getElementById(`universe-${data.u}`); + + if($elem && data.universe.slotElemsSet){ + + if(data.universe.priority > 0){ + for(let i = 0; i < 512; i++){ + data.universe.slotElems[i].innerText = data.universe.slots[i]; + } + + const $code = doc.getElementById(`universe-${data.u}-code`); + if(data.startCode === 0xDD){ + $code.innerText = "Net3" + }else if(data.startCode === 0x17){ + $code.innerText = "Text" + }else if(data.startCode === 0xCF){ + $code.innerText = "SIP" + }else if(data.startCode === 0xCC){ + $code.innerText = "RDM" + } + + } + + }else{ + d.draw(); + updateElementsCache(d, d.data.universes, d.data.orderedUniverses); + } + + }else if(updateType === "elementCache"){ + + data.orderedUniverses.forEach(univ => { + for(let i = 0; i < 512; i++){ + data.universes[univ].slotElems[i] = doc.getElementById(`${univ}-${i}`); + } + data.universes[univ].slotElemsSet = true; + }); + + } + + +} + + +function updateElementsCache(device, univ, ordered){ + device.update("elementCache", { + universes: univ, + orderedUniverses: ordered + }); +} + + + + + + + +// From https://github.com/hhromic/e131-node/blob/master/lib/e131.js +function getMulticastGroup(universe) { + if (universe < 1 || universe > 63999) { + throw new RangeError('universe should be in the range [1-63999]'); + } + return `239.255.${universe >> 8}.${universe & 0xff}`; + +} \ No newline at end of file diff --git a/plugins/sacn/styles.css b/plugins/sacn/styles.css new file mode 100644 index 0000000..47209a9 --- /dev/null +++ b/plugins/sacn/styles.css @@ -0,0 +1,29 @@ +table { + margin-bottom: 50px; + background-color: #333; +} +td, +th { + width: 35px; +} +td { + background-color: black; + text-align: center; + border-radius: 3px; + color: white; + font-size: 13px; +} +th { + background-color: #222; + color: #ccc; + font-size: 11px; +} +td.data { + padding: 7px; + font-size: 12px; + text-align: left; +} +td.data em { + font-size: 14px; + color: #ff0033; +} diff --git a/plugins/sacn/template.ejs b/plugins/sacn/template.ejs new file mode 100644 index 0000000..de4a90a --- /dev/null +++ b/plugins/sacn/template.ejs @@ -0,0 +1,58 @@ +
+

<%= data.source %> sACN (E1.31)

+
+ + +
+<% data.orderedUniverses.forEach(univ => { + let universe = data.universes[univ]; +%> + + + + + + + + + + + + + <% for(col=1; col<=16; col++){ %> + + <% } %> + + + <% let slot = 0; %> + <% for(row=0; row<32; row++){ %> + + + <% for(col=0; col<16; col++){ %> + <% slot++%> + + <% } %> + + <% } %> + + +
+ Universe +
<%= univ %> +
+ Priority +
<%= universe.priority %> +
+ CID +
<%= universe.cid %> +
+ IP +
<%= data.ip %> +
+ Flavor +
0 +
<%= col %>
<%= row*16+1 %><%= universe.slots[slot-1] %>
+ +<% }); %> + +
\ No newline at end of file diff --git a/plugins/watchout/info.html b/plugins/watchout/info.html new file mode 100644 index 0000000..e69de29 diff --git a/plugins/watchout/main.js b/plugins/watchout/main.js index 1c43cca..0f4c7dd 100644 --- a/plugins/watchout/main.js +++ b/plugins/watchout/main.js @@ -5,47 +5,49 @@ exports.searchOptions = { type: 'TCPport', searchBuffer: Buffer.from('authenticate 1\n', 'ascii'), testPort: 3040, - validateResponse: function (msg, info) { - return msg.toString().substring(0, 5) == 'Ready'; + validateResponse (msg, info) { + return msg.toString().substring(0, 5) === 'Ready'; }, }; exports.defaultPort = 3040; -exports.ready = function (device) { +exports.ready = function ready(device) { device.send('authenticate 1\n'); }; -exports.data = function (device, message) { +exports.data = function data(device, message) { const msg = message.toString(); - if (msg.substring(0, 5) == 'Ready') { - device.send('getStatus\n'); - } - if (msg.substring(0, 5) == 'Reply') { + const d = device; + + if (msg.substring(0, 5) === 'Ready') { + d.send('getStatus\n'); + + }else if (msg.substring(0, 5) === 'Reply') { const arr = msg.split(' '); - device.data.showName = ''; + d.data.showName = ''; let i = 0; - while (arr[i][arr[i].length - 1] != '"') { + while (arr[i][arr[i].length - 1] !== '"') { i++; - device.data.showName += `${arr[i]} `; + d.data.showName += `${arr[i]} `; } - device.data.showName = device.data.showName.substring( + d.data.showName = d.data.showName.substring( 1, - device.data.showName.length - 2 + d.data.showName.length - 2 ); i--; - device.data.busy = arr[i + 2]; - device.data.health = arr[i + 3]; - device.data.displayOpen = arr[i + 4]; - device.data.showActive = arr[i + 5]; - device.data.programmerOnline = arr[i + 6]; - device.data.position = Number(arr[i + 7]).toFixed(2); - device.data.rate = arr[i + 8]; - device.data.standby = arr[i + 9]; + d.data.busy = arr[i + 2]; + d.data.health = arr[i + 3]; + d.data.displayOpen = arr[i + 4]; + d.data.showActive = arr[i + 5]; + d.data.programmerOnline = arr[i + 6]; + d.data.position = Number(arr[i + 7]).toFixed(2); + d.data.rate = arr[i + 8]; + d.data.standby = arr[i + 9]; - this.deviceInfoUpdate(device, 'defaultName', device.data.showName); - device.draw(); + this.deviceInfoUpdate(d, 'defaultName', d.data.showName); + d.draw(); } // if(msg.substring(0, 5)=="Error"){ // device.data.error = msg.substring(6, 7); @@ -53,6 +55,6 @@ exports.data = function (device, message) { // console.log(msg) }; -exports.heartbeat = function (device) { +exports.heartbeat = function heartbeat(device) { device.send('getStatus\n'); }; diff --git a/plugins/x32/info.html b/plugins/x32/info.html new file mode 100644 index 0000000..e69de29 diff --git a/plugins/x32/main.js b/plugins/x32/main.js index 7e20e5b..4d41dda 100644 --- a/plugins/x32/main.js +++ b/plugins/x32/main.js @@ -6,24 +6,25 @@ exports.searchOptions = { searchBuffer: Buffer.from([0x2f, 0x78, 0x69, 0x6e, 0x66, 0x6f]), devicePort: 10023, listenPort: 0, - validateResponse: function (msg, info) { - return msg.toString().indexOf('/xinfo') == 0; + validateResponse (msg, info) { + return msg.toString().indexOf('/xinfo') === 0; }, }; exports.defaultPort = 10023; -exports.ready = function (device) { - device.data.channelFaders = new Array(32).fill(0); - device.data.channelFadersDB = new Array(32).fill(0); - device.data.channelMutes = new Array(32).fill(0); - device.data.channelNames = new Array(32).fill('end'); - device.data.channelColors = new Array(32); +exports.ready = function ready(device) { + const d = device; + d.data.channelFaders = new Array(32).fill(0); + d.data.channelFadersDB = new Array(32).fill(0); + d.data.channelMutes = new Array(32).fill(0); + d.data.channelNames = new Array(32).fill('end'); + d.data.channelColors = new Array(32); - device.data.stereoFader = 0; - device.data.stereoFaderDB = 0; - device.data.stereoMute = 0; + d.data.stereoFader = 0; + d.data.stereoFaderDB = 0; + d.data.stereoMute = 0; - device.send(Buffer.from('/xinfo')); + d.send(Buffer.from('/xinfo')); // device.send(Buffer.from("\x2f\x62\x61\x74\x63\x68\x73\x75\x62\x73\x63\x72\x69\x62\x65\x00\x2c\x73\x73\x69\x69\x69\x00\x00\x6d\x65\x74\x65\x72\x73\x2f\x30\x00\x00\x00\x00\x2f\x6d\x65\x74\x65\x72\x73\x2f\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")); // device.send(Buffer.from("/batchsubscribe\x00,ssiii\x00\x00meters/0\x00\x00\x00\x00/meters/0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")); @@ -40,31 +41,33 @@ function parseAddress(msg) { function convertToDBTheBehringerWay(f) { if (f >= 0.5) { return f * 40 - 30; - } else if (f >= 0.25) { - return f * 80 - 50; - } else if (f >= 0.0625) { - return f * 160 - 70; - } else { - return f * 480 - 90; } + if (f >= 0.25) { + return f * 80 - 50; + } + if (f >= 0.0625) { + return f * 160 - 70; + } + return f * 480 - 90; } -exports.data = function (device, buf) { +exports.data = function data(device, buf) { this.deviceInfoUpdate(device, 'status', 'ok'); const msg = buf.toString().split('\u0000\u0000'); + const d = device; - if (msg[0] == '/xinfo') { + if (msg[0] === '/xinfo') { this.deviceInfoUpdate(device, 'defaultName', msg[4]); - device.data.name = msg[4]; - device.data.ip = msg[2]; - device.data.firmware = msg[7]; - device.data.model = msg[5]; + d.data.name = msg[4]; + d.data.ip = msg[2]; + d.data.firmware = msg[7]; + d.data.model = msg[5]; - device.send(Buffer.from('/lr/mix/fader\u0000\u0000\u0000\u0000')); - device.send(Buffer.from('/lr/mix/on\u0000\u0000\u0000\u0000')); + d.send(Buffer.from('/lr/mix/fader\u0000\u0000\u0000\u0000')); + d.send(Buffer.from('/lr/mix/on\u0000\u0000\u0000\u0000')); for (let i = 0; i <= 32; i++) { - device.send( + d.send( Buffer.from( `/ch/${i .toString() @@ -72,59 +75,59 @@ exports.data = function (device, buf) { ) ); } - device.draw(); - } else if (msg[0] == '/meters/0') { + d.draw(); + } else if (msg[0] === '/meters/0') { // console.log(msg) } else if (msg[0].indexOf('/mix/fader') >= 0) { const addr = parseAddress(msg[0]); const channel = Number(addr[1]); - if (addr[0] == 'ch') { - device.data.channelFaders[channel - 1] = buf.readFloatBE(24); - device.data.channelFadersDB[channel - 1] = convertToDBTheBehringerWay( + if (addr[0] === 'ch') { + d.data.channelFaders[channel - 1] = buf.readFloatBE(24); + d.data.channelFadersDB[channel - 1] = convertToDBTheBehringerWay( buf.readFloatBE(24) ); - } else if (addr[0] == 'lr') { - device.data.stereoFader = buf.readFloatBE(20); - device.data.stereoFaderDB = convertToDBTheBehringerWay( + } else if (addr[0] === 'lr') { + d.data.stereoFader = buf.readFloatBE(20); + d.data.stereoFaderDB = convertToDBTheBehringerWay( buf.readFloatBE(20) ); } - device.draw(); + d.draw(); } else if (msg[0].indexOf('/mix/on') >= 0) { const addr = parseAddress(msg[0]); const channel = Number(addr[1]); - if (addr[0] == 'ch') { - device.data.channelMutes[channel - 1] = buf[23]; - } else if (addr[0] == 'lr') { - device.data.stereoMute = buf[19]; + if (addr[0] === 'ch') { + d.data.channelMutes[channel - 1] = buf[23]; + } else if (addr[0] === 'lr') { + d.data.stereoMute = buf[19]; } - device.draw(); - device.send( + d.draw(); + d.send( Buffer.from(`/ch/${addr[1]}/mix/fader\u0000\u0000\u0000\u0000`) ); } else if (msg[0].indexOf('/config/name') > 0) { const addr = parseAddress(msg[0]); const channel = Number(addr[1]); - device.data.channelNames[channel - 1] = msg[2]; - device.draw(); - device.send( + d.data.channelNames[channel - 1] = msg[2]; + d.draw(); + d.send( Buffer.from(`/ch/${addr[1]}/config/color\u0000\u0000\u0000\u0000`) ); } else if (msg[0].indexOf('/config/color') > 0) { const addr = parseAddress(msg[0]); const channel = Number(addr[1]); - device.data.channelColors[channel - 1] = buf.readInt8(27); - device.draw(); - device.send(Buffer.from(`/ch/${addr[1]}/mix/on\u0000\u0000\u0000\u0000`)); + d.data.channelColors[channel - 1] = buf.readInt8(27); + d.draw(); + d.send(Buffer.from(`/ch/${addr[1]}/mix/on\u0000\u0000\u0000\u0000`)); } else { // console.log(msg) } // console.log(msg) }; -exports.heartbeat = function (device) { +exports.heartbeat = function heartbeat(device) { device.send(Buffer.from('/xremote')); }; diff --git a/plugins/xair/info.html b/plugins/xair/info.html new file mode 100644 index 0000000..e69de29 diff --git a/plugins/xair/main.js b/plugins/xair/main.js index 377632b..3c759c7 100644 --- a/plugins/xair/main.js +++ b/plugins/xair/main.js @@ -6,24 +6,25 @@ exports.searchOptions = { searchBuffer: Buffer.from([0x2f, 0x78, 0x69, 0x6e, 0x66, 0x6f]), devicePort: 10024, listenPort: 0, - validateResponse: function (msg, info) { - return msg.toString().indexOf('/xinfo') == 0; + validateResponse (msg, info) { + return msg.toString().indexOf('/xinfo') === 0; }, }; exports.defaultPort = 10024; -exports.ready = function (device) { - device.data.channelFaders = new Array(32).fill(0); - device.data.channelFadersDB = new Array(32).fill(0); - device.data.channelMutes = new Array(32).fill(0); - device.data.channelNames = new Array(32).fill('end'); - device.data.channelColors = new Array(32); +exports.ready = function ready(device) { + const d = device; + d.data.channelFaders = new Array(32).fill(0); + d.data.channelFadersDB = new Array(32).fill(0); + d.data.channelMutes = new Array(32).fill(0); + d.data.channelNames = new Array(32).fill('end'); + d.data.channelColors = new Array(32); - device.data.stereoFader = 0; - device.data.stereoFaderDB = 0; - device.data.stereoMute = 0; + d.data.stereoFader = 0; + d.data.stereoFaderDB = 0; + d.data.stereoMute = 0; - device.send('/xinfo'); + d.send('/xinfo'); // device.send(Buffer.from("\x2f\x62\x61\x74\x63\x68\x73\x75\x62\x73\x63\x72\x69\x62\x65\x00\x2c\x73\x73\x69\x69\x69\x00\x00\x6d\x65\x74\x65\x72\x73\x2f\x30\x00\x00\x00\x00\x2f\x6d\x65\x74\x65\x72\x73\x2f\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")); // device.send(Buffer.from("/batchsubscribe\x00,ssiii\x00\x00meters/0\x00\x00\x00\x00/meters/0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")); @@ -40,36 +41,38 @@ function parseAddress(msg) { function convertToDBTheBehringerWay(f) { if (f >= 0.5) { return f * 40 - 30; - } else if (f >= 0.25) { - return f * 80 - 50; - } else if (f >= 0.0625) { - return f * 160 - 70; - } else { - return f * 480 - 90; } + if (f >= 0.25) { + return f * 80 - 50; + } + if (f >= 0.0625) { + return f * 160 - 70; + } + return f * 480 - 90; } -exports.data = function (device, buf) { +exports.data = function data(device, buf) { this.deviceInfoUpdate(device, 'status', 'ok'); const msg = buf.toString().split('\u0000'); + const d = device; - if (msg[0] == '/xinfo') { + if (msg[0] === '/xinfo') { if (msg[7].length > 0) { - device.data.name = msg[7]; + d.data.name = msg[7]; } else { - device.data.name = msg[6]; + d.data.name = msg[6]; } - device.data.ip = msg[5]; - device.data.firmware = msg[13]; - device.data.model = msg[9]; - this.deviceInfoUpdate(device, 'defaultName', device.data.name); + d.data.ip = msg[5]; + d.data.firmware = msg[13]; + d.data.model = msg[9]; + this.deviceInfoUpdate(d, 'defaultName', d.data.name); - device.send('/lr/mix/fader\u0000\u0000\u0000\u0000'); - device.send('/lr/mix/on\u0000\u0000\u0000\u0000'); + d.send('/lr/mix/fader\u0000\u0000\u0000\u0000'); + d.send('/lr/mix/on\u0000\u0000\u0000\u0000'); for (let i = 0; i <= 32; i++) { - device.send( + d.send( Buffer.from( `/ch/${i .toString() @@ -77,55 +80,60 @@ exports.data = function (device, buf) { ) ); } - device.draw(); - } else if (msg[0] == '/meters/0') { + d.draw(); + + } else if (msg[0] === '/meters/0') { // console.log(msg) } else if (msg[0].indexOf('/mix/fader') >= 0) { const addr = parseAddress(msg[0]); const channel = Number(addr[1]); - if (addr[0] == 'ch') { - device.data.channelFaders[channel - 1] = buf.readFloatBE(24); - device.data.channelFadersDB[channel - 1] = convertToDBTheBehringerWay( + if (addr[0] === 'ch') { + d.data.channelFaders[channel - 1] = buf.readFloatBE(24); + d.data.channelFadersDB[channel - 1] = convertToDBTheBehringerWay( buf.readFloatBE(24) ); - } else if (addr[0] == 'lr') { - device.data.stereoFader = buf.readFloatBE(20); - device.data.stereoFaderDB = convertToDBTheBehringerWay( + } else if (addr[0] === 'lr') { + d.data.stereoFader = buf.readFloatBE(20); + d.data.stereoFaderDB = convertToDBTheBehringerWay( buf.readFloatBE(20) ); } - device.draw(); + d.draw(); + } else if (msg[0].indexOf('/mix/on') >= 0) { const addr = parseAddress(msg[0]); const channel = Number(addr[1]); - if (addr[0] == 'ch') { - device.data.channelMutes[channel - 1] = buf[23]; - } else if (addr[0] == 'lr') { - device.data.stereoMute = buf[19]; + if (addr[0] === 'ch') { + d.data.channelMutes[channel - 1] = buf[23]; + } else if (addr[0] === 'lr') { + d.data.stereoMute = buf[19]; } device.draw(); device.send(`/ch/${addr[1]}/mix/fader\u0000\u0000\u0000\u0000`); + } else if (msg[0].indexOf('/config/name') > 0) { const addr = parseAddress(msg[0]); const channel = Number(addr[1]); - device.data.channelNames[channel - 1] = msg[4]; - device.draw(); - device.send(`/ch/${addr[1]}/config/color\u0000\u0000\u0000\u0000`); + d.data.channelNames[channel - 1] = msg[4]; + d.draw(); + d.send(`/ch/${addr[1]}/config/color\u0000\u0000\u0000\u0000`); + } else if (msg[0].indexOf('/config/color') > 0) { const addr = parseAddress(msg[0]); const channel = Number(addr[1]); - device.data.channelColors[channel - 1] = buf.readInt8(27); - device.draw(); - device.send(`/ch/${addr[1]}/mix/on\u0000\u0000\u0000\u0000`); + d.data.channelColors[channel - 1] = buf.readInt8(27); + d.draw(); + d.send(`/ch/${addr[1]}/mix/on\u0000\u0000\u0000\u0000`); + } else { // console.log(msg) } // console.log(msg) }; -exports.heartbeat = function (device) { +exports.heartbeat = function heartbeat(device) { device.send('/xremote'); };