basic atem connection/display working

This commit is contained in:
2023-01-26 00:48:06 -06:00
parent 61e6d24e0f
commit 6f0e528164
8 changed files with 2263 additions and 2428 deletions
+2055 -2427
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -30,6 +30,7 @@
"prettier": "^2.8.3"
},
"dependencies": {
"atem": "^0.1.8",
"bonjour": "^3.5.0",
"electron-updater": "^5.3.0",
"lodash": "^4.17.21",
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File
+85
View File
@@ -0,0 +1,85 @@
const { infoUpdate } = require('../../src/device');
exports.config = {
defaultName: 'ATEM',
connectionType: 'atem',
defaultPort: 9910,
mayChangePort: false,
heartbeatInterval: 5000,
heartbeatTimeout: 6000,
searchOptions: {
type: 'UDPsocket',
searchBuffer: Buffer.from('', 'ascii'),
testPort: 9910,
validateResponse(msg, info) {
return true;
},
},
};
exports.ready = function ready(_device) {
console.log('atem ready');
};
exports.data = function data(_device, msg) {
const device = _device;
switch (msg.event) {
case 'sourceConfiguration':
if (device.data.source === undefined) {
device.data.source = {};
}
if (device.data.source[msg.sourceID] === undefined) {
device.data.source[msg.sourceID] = {
tally: {
preview: false,
program: false,
},
};
}
device.data.source[msg.sourceID] = {
...msg.sourceConfiguration,
};
break;
case 'sourceTally':
if (device.data.source === undefined) {
device.data.source = {};
}
if (device.data.source[msg.sourceID] === undefined) {
device.data.source[msg.sourceID] = {};
}
device.data.source[msg.sourceID].tally = msg.state;
device.draw();
break;
case 'connectionStateChange':
device.draw();
break;
case 'rawCommand':
if (msg.cmd.name === '_ver') {
console.log(msg);
} else if (msg.cmd.name === '_pin') {
if (msg.cmd.data !== undefined) {
infoUpdate(device, 'defaultName', msg.cmd.data.toString().trim());
}
} else if (msg.cmd.name === '_top') {
device.data.topology = {
MEs: msg.cmd.data[0],
sources: msg.cmd.data[1],
colorGens: msg.cmd.data[2],
AUXs: msg.cmd.data[3],
DSKs: msg.cmd.data[4],
stingers: msg.cmd.data[5],
DVEs: msg.cmd.data[6],
superSources: msg.cmd.data[7],
};
console.log(device);
}
break;
default:
break;
}
};
exports.heartbeat = function heartbeat(device) {};
+39
View File
@@ -0,0 +1,39 @@
h3 {
color: #6d6d6d;
}
.atem-input {
width: 50px;
height: 50px;
background: white;
border: 4px solid;
border-color: #8c8c8c;
border-radius: 3px;
margin: 6px;
}
.source-wrapper {
display: flex;
flex-wrap: wrap;
background-color: #1f1f1f;
border: 1px solid;
border-color: #1a1a1a;
border-radius: 5px;
}
.program-active {
background: rgb(255, 130, 131);
background: radial-gradient(circle, rgba(255, 130, 131, 1) 0%, rgba(255, 41, 40, 1) 100%);
}
.preview-active {
background: rgb(14, 238, 7);
background: radial-gradient(circle, rgba(14, 238, 7, 1) 0%, rgba(29, 204, 14, 1) 100%);
}
.source-label {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
+45
View File
@@ -0,0 +1,45 @@
<header>
<h1><%= listName %></h1>
</header>
<div class="program">
<h3>Program</h3>
<div class="source-wrapper">
<% Object.entries(data.source).forEach(([sourceID, state])=>{ %>
<% if (state.tally.program) { %>
<div id="atem-program-source-<%= sourceID %>" class="atem-input program-active">
<div class="source-label">
<%= state.abbreviation %>
</div>
</div>
<% } else { %>
<div id="atem-program-source-<%= sourceID %>" class="atem-input">
<div class="source-label">
<%= state.abbreviation %>
</div>
</div>
<% } %>
<% }) %>
</div>
</div>
<div class="preview">
<h3>Preview</h3>
<div class="source-wrapper">
<% Object.entries(data.source).forEach(([sourceID, state])=>{ %>
<% if (state.tally.preview) { %>
<div id="atem-preview-source-<%= sourceID %>" class="atem-input preview-active">
<div class="source-label">
<div><%= state.abbreviation %></div>
</div>
</div>
<% } else { %>
<div id="atem-preview-source-<%= sourceID %>" class="atem-input">
<div class="source-label">
<div><%= state.abbreviation %></div>
</div>
</div>
<% } %>
<% }) %>
</div>
</div>
+38 -1
View File
@@ -2,7 +2,7 @@ const { v4: uuid } = require('uuid');
const osc = require('osc');
const net = require('net');
const udp = require('dgram');
const Atem = require('atem');
const PLUGINS = require('./plugins.js');
const VIEW = require('./view.js');
const SAVESLOTS = require('./saveSlots.js');
@@ -193,6 +193,43 @@ function initDeviceConnection(id) {
});
device.send = (data) => {};
} else if (plugins[type].config.connectionType === 'atem') {
device.connection = new Atem(device.addresses[0]);
device.connection.on('connectionStateChange', (state) => {
plugins[type].ready(device);
infoUpdate(device, 'status', 'ok');
const msg = {
event: 'connectionStateChange',
state,
};
plugins[type].data(device, msg);
});
device.connection.on('sourceTally', (sourceID, state) => {
const msg = {
event: 'sourceTally',
sourceID,
state,
};
plugins[type].data(device, msg);
});
device.connection.on('sourceConfiguration', (sourceID, sourceConfiguration) => {
const msg = {
event: 'sourceConfiguration',
sourceID,
sourceConfiguration,
};
plugins[type].data(device, msg);
});
device.connection.on('rawCommand', (cmd) => {
const msg = {
event: 'rawCommand',
cmd,
};
plugins[type].data(device, msg);
});
}
return true;