mirror of
https://github.com/stagehacks/Cue-View.git
synced 2026-08-06 14:23:40 +00:00
initial commit for show cue systems
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 563 B |
@@ -0,0 +1,4 @@
|
||||
<h3>Connection Requirements</h3>
|
||||
<ul>
|
||||
<li>Network Protocol must be set to TCP under Remote App Interface settings</li>
|
||||
</ul>
|
||||
@@ -0,0 +1,187 @@
|
||||
exports.config = {
|
||||
defaultName: 'Show Cue Systems',
|
||||
connectionType: 'TCPsocket',
|
||||
defaultPort: 58000,
|
||||
mayChangePort: true,
|
||||
heartbeatInterval: 5000,
|
||||
searchOptions: {
|
||||
type: 'TCPport',
|
||||
searchBuffer: Buffer.from('/_status', 'ascii'),
|
||||
testPort: 58000,
|
||||
validateResponse(msg, info) {
|
||||
return msg.toString().includes('/_status');
|
||||
},
|
||||
},
|
||||
fields: [],
|
||||
};
|
||||
|
||||
const typeMap = {
|
||||
A: 'Video/Image',
|
||||
E: 'Memo',
|
||||
F: 'Audio File',
|
||||
G: 'GoTo Cue',
|
||||
H: 'Multi-File Cue',
|
||||
I: 'Live Input',
|
||||
J: 'Enable/Disable',
|
||||
K: 'Lighting',
|
||||
L: 'Level Change',
|
||||
M: 'Control Send',
|
||||
N: 'Note',
|
||||
P: 'Playlist',
|
||||
Q: 'Call Cue',
|
||||
R: 'Run Program',
|
||||
S: 'SFR',
|
||||
T: 'Set Position',
|
||||
U: 'MIDI Time Code',
|
||||
};
|
||||
|
||||
const versionMap = {
|
||||
10: 'LITE',
|
||||
20: 'STD',
|
||||
30: 'PRO',
|
||||
40: 'PLUS',
|
||||
45: 'DEMO',
|
||||
50: 'PLAT',
|
||||
};
|
||||
|
||||
exports.ready = function ready(_device) {
|
||||
const device = _device;
|
||||
console.log('Show Cue Systems ready');
|
||||
device.data.cues = [];
|
||||
device.send(Buffer.from('/_prod/gettitle'));
|
||||
};
|
||||
|
||||
exports.data = function data(_device, message) {
|
||||
const device = _device;
|
||||
this.deviceInfoUpdate(device, 'status', 'ok');
|
||||
const msg = message.toString();
|
||||
const messagePath = msg.substring(0, msg.indexOf(' '));
|
||||
if (messagePath === '/_prod/gettitle') {
|
||||
const title = msg.replace(messagePath, '').replaceAll('"', '').trim();
|
||||
this.deviceInfoUpdate(device, 'defaultName', title);
|
||||
device.send(Buffer.from('/_info/scsversion'));
|
||||
} else if (messagePath === '/_info/scsversion') {
|
||||
const versionInfo = msg.replace(messagePath, '').trim().split(' ');
|
||||
const versionNumber = versionInfo[0];
|
||||
const versionMajor = versionNumber.substring(0, 2).replace('0', '');
|
||||
const versionMinor = versionNumber.substring(2, 4).replace('0', '');
|
||||
const versionPatch = versionNumber.substring(4, 6).replace('0', '');
|
||||
const versionString = `${versionMajor}.${versionMinor}.${versionPatch}`;
|
||||
|
||||
const versionType = versionMap[versionInfo[1]];
|
||||
device.data.version = {
|
||||
number: versionString,
|
||||
type: versionType,
|
||||
};
|
||||
device.send(Buffer.from('/_info/finalcue', 'ascii'));
|
||||
} else if (messagePath === '/_info/finalcue') {
|
||||
const cueCount = parseInt(msg.replace(messagePath, '').trim(), 10);
|
||||
device.data.cues = new Array(cueCount).fill(0).map(() => ({
|
||||
label: '',
|
||||
page: '',
|
||||
description: '',
|
||||
type: { code: '', display: '' },
|
||||
state: '',
|
||||
activation: '',
|
||||
file_info: '',
|
||||
length: '',
|
||||
colors: ['', ''],
|
||||
}));
|
||||
device.send(Buffer.from(`/_cue/getitemsn 1 QNTCLSPARZ`));
|
||||
} else if (messagePath === '/_info/getcue') {
|
||||
const cueLabelInfo = msg.replace(messagePath, '').trim().split(' ');
|
||||
const cueNumber = parseInt(cueLabelInfo[0], 10);
|
||||
const cueLabel = cueLabelInfo[1].replaceAll('"', '');
|
||||
|
||||
device.data.cues[cueNumber - 1].label = cueLabel;
|
||||
device.draw();
|
||||
} else if (messagePath === '/_cue/getpage') {
|
||||
const pageInfo = msg.replace(messagePath, '').trim().match(/".*?"/g);
|
||||
const cueLabel = pageInfo[0].replaceAll('"', '');
|
||||
const cueIndex = device.data.cues.map((cue) => cue.label).indexOf(cueLabel);
|
||||
device.data.cues[cueIndex].page = pageInfo[1].replaceAll('"', '');
|
||||
if (cueIndex < device.data.cues.length - 1) {
|
||||
device.send(Buffer.from(`/_cue/getpage ${device.data.cues[cueIndex + 1].label}`));
|
||||
} else {
|
||||
// console.log('done loading cue pages');
|
||||
device.draw();
|
||||
device.send(Buffer.from('/_status'));
|
||||
}
|
||||
} else if (messagePath === '/_cue/getname') {
|
||||
const nameInfo = msg.replace(messagePath, '').trim().match(/".*?"/g);
|
||||
const cueLabel = nameInfo[0].replaceAll('"', '');
|
||||
const cueIndex = device.data.cues.map((cue) => cue.label).indexOf(cueLabel);
|
||||
|
||||
device.data.cues[cueIndex].description = nameInfo[1].replaceAll('"', '');
|
||||
device.draw();
|
||||
} else if (messagePath === '/_cue/gettype') {
|
||||
const typeInfo = msg.replace(messagePath, '').trim().match(/".*?"/g);
|
||||
const cueLabel = typeInfo[0].replaceAll('"', '');
|
||||
const cueIndex = device.data.cues.map((cue) => cue.label).indexOf(cueLabel);
|
||||
|
||||
device.data.cues[cueIndex].type = {
|
||||
code: typeInfo[1].replaceAll('"', ''),
|
||||
display: typeMap[typeInfo[1].replaceAll('"', '')],
|
||||
};
|
||||
device.draw();
|
||||
} else if (messagePath === '/_cue/getitemsn') {
|
||||
const itemParts = msg
|
||||
.replace(messagePath, '')
|
||||
.trim('')
|
||||
.match(/".*?"|\d+/g);
|
||||
if (itemParts.length === 12) {
|
||||
const cueIndex = itemParts[0] - 1;
|
||||
device.data.cues[cueIndex].label = sanitizeSCSString(itemParts[2]);
|
||||
device.data.cues[cueIndex].description = sanitizeSCSString(itemParts[3]);
|
||||
device.data.cues[cueIndex].type = {
|
||||
code: sanitizeSCSString(itemParts[4]),
|
||||
display: typeMap[sanitizeSCSString(itemParts[4])],
|
||||
};
|
||||
device.data.cues[cueIndex].colors = sanitizeSCSString(itemParts[5]).split(', ');
|
||||
device.data.cues[cueIndex].length = millisToString(itemParts[6]);
|
||||
device.data.cues[cueIndex].state = itemParts[7];
|
||||
device.data.cues[cueIndex].position = itemParts[8];
|
||||
device.data.cues[cueIndex].activation = sanitizeSCSString(itemParts[9]);
|
||||
device.data.cues[cueIndex].repeat = itemParts[10];
|
||||
device.data.cues[cueIndex].loop = itemParts[11];
|
||||
device.draw();
|
||||
|
||||
if (cueIndex < device.data.cues.length - 1) {
|
||||
device.send(Buffer.from(`/_cue/getitemsn ${cueIndex + 2} QNTCLSPARZ`));
|
||||
} else {
|
||||
// console.log('done loading cue items');
|
||||
device.send(Buffer.from(`/_cue/getpage ${device.data.cues[0].label}`));
|
||||
}
|
||||
} else {
|
||||
console.error('bad response from getitems');
|
||||
}
|
||||
} else if (messagePath === '/_status') {
|
||||
const status = parseInt(msg.split(' ')[1].trim(), 10);
|
||||
console.log(`status: ${status}`);
|
||||
} else {
|
||||
console.error(`unhandled message path: ${messagePath}`);
|
||||
}
|
||||
};
|
||||
|
||||
function sanitizeSCSString(string) {
|
||||
return string.substring(1, string.length - 1);
|
||||
}
|
||||
|
||||
function millisToString(duration) {
|
||||
const milliseconds = parseInt(duration % 1000, 10);
|
||||
let seconds = parseInt((duration / 1000) % 60, 10);
|
||||
const minutes = parseInt((duration / (1000 * 60)) % 60, 10);
|
||||
|
||||
if (minutes === 0) {
|
||||
return `${seconds}.${milliseconds}`;
|
||||
}
|
||||
if (seconds === 0) {
|
||||
return `0.${milliseconds}`;
|
||||
}
|
||||
if (seconds < 10) {
|
||||
seconds = `0${seconds}`;
|
||||
}
|
||||
return `${minutes}:${seconds}.${milliseconds}`;
|
||||
}
|
||||
|
||||
exports.heartbeat = function heartbeat(device) {};
|
||||
@@ -0,0 +1,12 @@
|
||||
table {
|
||||
background: white;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.header-row {
|
||||
background: white;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<header>
|
||||
<h1><%= listName %></h1>
|
||||
</header>
|
||||
<table>
|
||||
<tr class="header-row">
|
||||
<th>Label</th>
|
||||
<th>Page</th>
|
||||
<th>Description</th>
|
||||
<th>Cue Type</th>
|
||||
<th>State</th>
|
||||
<th>Activation</th>
|
||||
<th>Length</th>
|
||||
</tr>
|
||||
<% data.cues.forEach((cue)=>{ %>
|
||||
<tr style="background-color: <%=cue.colors[0]%>; color: <%=cue.colors[1]%>;">
|
||||
<td><%=cue.label%></td>
|
||||
<td><%=cue.page%></td>
|
||||
<td><%=cue.description%></td>
|
||||
<td><%=cue.type.display%></td>
|
||||
<td><%=cue.state%></td>
|
||||
<td><%=cue.activation%></td>
|
||||
<td><%=cue.length%></td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</table>
|
||||
Reference in New Issue
Block a user