first commit
This commit is contained in:
commit
050032f726
|
|
@ -0,0 +1,7 @@
|
|||
node_modules/
|
||||
.pnp.*
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.DS_Store
|
||||
|
|
@ -0,0 +1 @@
|
|||
nodeLinker: node-modules
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 Bitfocus AS - Open Source
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
## companion-module-purelink-pt-ma-hd44m
|
||||
|
||||
See [HELP.md](./companion/HELP.md) and [LICENSE](./LICENSE)
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
const { Regex } = require('@companion-module/base');
|
||||
|
||||
module.exports = {
|
||||
getActions() {
|
||||
const actions = {};
|
||||
|
||||
actions.setCrosspoint = {
|
||||
name: 'Set crosspoint',
|
||||
options: [
|
||||
{
|
||||
id: 'out',
|
||||
type: 'dropdown',
|
||||
label: 'OUTPUT',
|
||||
choices: this.getOutputsList(true),
|
||||
default: this.getFirstOutID()
|
||||
},
|
||||
{
|
||||
id: 'ipt',
|
||||
type: 'dropdown',
|
||||
label: 'INPUT',
|
||||
choices: this.getInputsList(),
|
||||
default: this.getFirstIptID()
|
||||
}
|
||||
],
|
||||
callback: async (event) => {
|
||||
let out = this.getOutByID(event.options.out);
|
||||
let ipt = this.getIptByID(event.options.ipt);
|
||||
this.log('info', `PT-MA-HD44M MATRIX | SET CROSSPOINT >>> ${out.label} > ${ipt.label}`);
|
||||
this.sendPriorityCommand(`#video_d out${event.options.out} matrix=${event.options.ipt}`);
|
||||
}
|
||||
};
|
||||
|
||||
actions.recallPreset = {
|
||||
name: 'Preset - Recall',
|
||||
options: [
|
||||
{
|
||||
id: 'pst',
|
||||
type: 'dropdown',
|
||||
label: 'PRESET',
|
||||
choices: this.getPresetsList(),
|
||||
default: this.getFirstPstID()
|
||||
}
|
||||
],
|
||||
callback: async (event) => {
|
||||
let pst = this.getPstByID(event.options.pst);
|
||||
this.log('info', `PT-MA-HD44M MATRIX | RECALL PRESET >>> ${pst.label}`);
|
||||
this.sendPriorityCommand(`#preset:${event.options.pst} exe=0`);
|
||||
}
|
||||
};
|
||||
|
||||
actions.savePreset = {
|
||||
name: 'Preset - Save',
|
||||
options: [
|
||||
{
|
||||
id: 'pst',
|
||||
type: 'dropdown',
|
||||
label: 'PRESET',
|
||||
choices: this.getPresetsList(),
|
||||
default: this.getFirstPstID()
|
||||
}
|
||||
],
|
||||
callback: async (event) => {
|
||||
let pst = this.getPstByID(event.options.pst);
|
||||
this.log('info', `PT-MA-HD44M MATRIX | SAVE PRESET >>> ${pst.label}`);
|
||||
this.sendPriorityCommand(`#preset:${event.options.pst} exe=1`);
|
||||
}
|
||||
};
|
||||
|
||||
actions.clearPreset = {
|
||||
name: 'Preset - Clear',
|
||||
options: [
|
||||
{
|
||||
id: 'pst',
|
||||
type: 'dropdown',
|
||||
label: 'PRESET',
|
||||
choices: this.getPresetsList(),
|
||||
default: this.getFirstPstID()
|
||||
}
|
||||
],
|
||||
callback: async (event) => {
|
||||
let pst = this.getPstByID(event.options.pst);
|
||||
this.log('info', `PT-MA-HD44M MATRIX | CLEAR PRESET >>> ${pst.label}`);
|
||||
this.sendPriorityCommand(`#preset:${event.options.pst} exe=2`);
|
||||
}
|
||||
};
|
||||
|
||||
actions.refreshInfo = {
|
||||
name: 'Refresh Info',
|
||||
options: [],
|
||||
callback: async () => {
|
||||
this.log('info', `PT-MA-HD44M MATRIX | REFRESH INFO`);
|
||||
this.sendPriorityCommand(`#get info`);
|
||||
}
|
||||
};
|
||||
|
||||
actions.sendCommand = {
|
||||
name: 'Send Command',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
id: 'cmd',
|
||||
label: 'Command:',
|
||||
tooltip: 'Use %hh to insert Hex codes\nObsolete, use Send HEX command instead',
|
||||
default: '',
|
||||
useVariables: true,
|
||||
}
|
||||
],
|
||||
callback: async (event) => {
|
||||
this.log('info', `PT-MA-HD44M MATRIX | SEND COMMAND >>> ${event.options.cmd}`);
|
||||
await this.sendPriorityCommand(event.options.cmd, false);
|
||||
}
|
||||
};
|
||||
|
||||
return actions;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# PureLink - PT-MA-HD44M
|
||||
|
||||
Companion module to control PureLink PureTools PT-MA-HD44M video matrix
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"id": "purelink-pt-ma-hd44m",
|
||||
"name": "purelink-pt-ma-hd44m",
|
||||
"shortname": "PT-MA-HD44M Matrix",
|
||||
"description": "PureLink PT-MA-HD44M Matrix module for Companion",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"repository": "git+https://github.com/bitfocus/companion-module-purelink-pt-ma-hd44m.git",
|
||||
"bugs": "https://github.com/bitfocus/companion-module-purelink-pt-ma-hd44m/issues",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Adrien RENARD",
|
||||
"email": "arenard@pixap.fr"
|
||||
}
|
||||
],
|
||||
"runtime": {
|
||||
"type": "node18",
|
||||
"api": "nodejs-ipc",
|
||||
"apiVersion": "1.3.0",
|
||||
"entrypoint": "../main.js"
|
||||
},
|
||||
"legacyIds": [],
|
||||
"manufacturer": "purelink",
|
||||
"products": [
|
||||
"PT-MA-HD44M"
|
||||
],
|
||||
"keywords": [
|
||||
"Video Matrix"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
const { Regex } = require('@companion-module/base');
|
||||
module.exports = {
|
||||
getConfigFields() {
|
||||
return [
|
||||
{
|
||||
id: 'info',
|
||||
type: 'static-text',
|
||||
width: 12,
|
||||
label: 'Information',
|
||||
value: "This module allow to controls a PureLink PureTools PT-MA-HD44M video matrix crosspoints.<br/>It's based on this native <a target='_blank' href='https://cloud.purelink.de/index.php/s/cMPB4FsRSCNb5fk/download'>protocol</a><br/>",
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
id: 'host',
|
||||
label: 'Matrix IP',
|
||||
width: 8,
|
||||
regex: Regex.IP,
|
||||
default: '192.168.1.168'
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
id: 'port',
|
||||
label: 'Matrix Port',
|
||||
width: 4,
|
||||
regex: Regex.PORT,
|
||||
min: 1,
|
||||
max: 65535,
|
||||
default: '5000'
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
id: 'timeout',
|
||||
label: 'Send Command Timeout (in ms)',
|
||||
width: 12,
|
||||
regex: Regex.PORT,
|
||||
min: 5,
|
||||
max: 500,
|
||||
default: 100
|
||||
}
|
||||
];
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
const { InstanceBase, combineRgb } = require('@companion-module/base');
|
||||
|
||||
module.exports = {
|
||||
getFeedbacks() {
|
||||
const feedbacks = {};
|
||||
|
||||
feedbacks.crosspoint_status = {
|
||||
name: 'Crosspoint Status',
|
||||
type: 'boolean',
|
||||
label: 'Crosspoint Status',
|
||||
defaultStyle: {
|
||||
bgcolor: combineRgb(255, 0, 0)
|
||||
},
|
||||
options: [
|
||||
{
|
||||
id: 'outID',
|
||||
type: 'dropdown',
|
||||
label: 'OUTPUT',
|
||||
choices: this.getOutputsList(false),
|
||||
default: this.getFirstOutID(false)
|
||||
},
|
||||
{
|
||||
id: 'xpt',
|
||||
type: 'dropdown',
|
||||
label: 'INPUT',
|
||||
choices: this.getInputsList(false),
|
||||
default: this.getFirstIptID(false)
|
||||
}
|
||||
],
|
||||
callback: (feedback) => {
|
||||
var out = this.getOutByID( feedback.options.outID );
|
||||
return out.xpt == feedback.options.xpt;
|
||||
}
|
||||
};
|
||||
|
||||
feedbacks.last_pst = {
|
||||
name: 'Last Recalled Preset',
|
||||
type: 'boolean',
|
||||
label: 'Last Recalled Preset',
|
||||
defaultStyle: {
|
||||
bgcolor: combineRgb(255, 0, 0)
|
||||
},
|
||||
options: [
|
||||
{
|
||||
id: 'pst',
|
||||
type: 'dropdown',
|
||||
label: 'PRESET',
|
||||
choices: this.getPresetsList(),
|
||||
default: this.getFirstPstID()
|
||||
}
|
||||
],
|
||||
callback: (feedback) => { return feedback.options.pst == this.getLastPstID(); }
|
||||
};
|
||||
|
||||
feedbacks.connect_status = {
|
||||
name: 'Connection Status',
|
||||
type: 'boolean',
|
||||
label: 'Matrix connection status',
|
||||
defaultStyle: {
|
||||
color: combineRgb(255, 255, 255)
|
||||
},
|
||||
options: [],
|
||||
callback: (feedback) => {
|
||||
return this.getVariableValue('connect_status') == 'ok';
|
||||
}
|
||||
};
|
||||
|
||||
return feedbacks;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,402 @@
|
|||
const { InstanceBase, Regex, runEntrypoint, InstanceStatus, TCPHelper, combineRgb, CompanionVariableValues } = require('@companion-module/base');
|
||||
const configFields = require('./configFields');
|
||||
const actions = require('./actions');
|
||||
const feedbacks = require('./feedbacks');
|
||||
const presets = require('./presets');
|
||||
const variables = require('./variables');
|
||||
|
||||
var tcpCommandBuffer = [];
|
||||
var tcpSendTimeout;
|
||||
var tcpSendTimeoutTime = 100;
|
||||
var currentCmd = false;
|
||||
|
||||
let tcpReceivebuffer = '';
|
||||
|
||||
var INPUTS = [
|
||||
{ id: '1' , label: 'Input #1' , name: 'Input1' , var_name: 'ipt_name_1' },
|
||||
{ id: '2' , label: 'Input #2' , name: 'Input2' , var_name: 'ipt_name_2' },
|
||||
{ id: '3' , label: 'Input #3' , name: 'Input3' , var_name: 'ipt_name_3' },
|
||||
{ id: '4' , label: 'Input #4' , name: 'Input4' , var_name: 'ipt_name_4' }
|
||||
];
|
||||
|
||||
var OUTPUTS = [
|
||||
{ id: '1' , label: 'Output #1' , name: 'Output1' , var_name: 'out_name_1', xpt: undefined, var_xpt: 'xpt_out_1' },
|
||||
{ id: '2' , label: 'Output #2' , name: 'Output2' , var_name: 'out_name_2', xpt: undefined, var_xpt: 'xpt_out_2' },
|
||||
{ id: '3' , label: 'Output #3' , name: 'Output3' , var_name: 'out_name_3', xpt: undefined, var_xpt: 'xpt_out_3' },
|
||||
{ id: '4' , label: 'Output #4' , name: 'Output4' , var_name: 'out_name_4', xpt: undefined, var_xpt: 'xpt_out_4' }
|
||||
];
|
||||
|
||||
const PRESETS = [
|
||||
{ id: '1' , label: 'Preset #1' , name: 'Preset1' , var_name: 'pst_name_1' },
|
||||
{ id: '2' , label: 'Preset #2' , name: 'Preset2' , var_name: 'pst_name_2' },
|
||||
{ id: '3' , label: 'Preset #3' , name: 'Preset3' , var_name: 'pst_name_3' },
|
||||
{ id: '4' , label: 'Preset #4' , name: 'Preset4' , var_name: 'pst_name_4' },
|
||||
{ id: '5' , label: 'Preset #5' , name: 'Preset5' , var_name: 'pst_name_5' },
|
||||
{ id: '6' , label: 'Preset #6' , name: 'Preset6' , var_name: 'pst_name_6' },
|
||||
{ id: '7' , label: 'Preset #7' , name: 'Preset7' , var_name: 'pst_name_7' },
|
||||
{ id: '8' , label: 'Preset #8' , name: 'Preset8' , var_name: 'pst_name_8' }
|
||||
];
|
||||
|
||||
class MixerInstance extends InstanceBase {
|
||||
constructor(internal) {
|
||||
super(internal);
|
||||
Object.assign(this, {
|
||||
...configFields,
|
||||
...actions,
|
||||
...feedbacks,
|
||||
...presets,
|
||||
...variables
|
||||
});
|
||||
}
|
||||
|
||||
async init(config) {
|
||||
this.config = config;
|
||||
|
||||
this.updateActionsDefinitions();
|
||||
this.updateFeedbacksDefinitions();
|
||||
this.updateVariableDefinitions();
|
||||
this.updatePresetsDefinitions();
|
||||
|
||||
// INIT CONNECTION
|
||||
this.initTCP();
|
||||
}
|
||||
|
||||
// When module gets deleted
|
||||
async destroy() { this.killTCP(); }
|
||||
|
||||
async configUpdated(config) {
|
||||
this.killTCP();
|
||||
this.config = config;
|
||||
|
||||
if(this.config.timeout>5===false) this.config.timeout = 5;
|
||||
else if(this.config.timeout>500) this.config.timeout = 500;
|
||||
|
||||
this.updateActionsDefinitions();
|
||||
this.updateFeedbacksDefinitions();
|
||||
this.updateVariableDefinitions();
|
||||
this.updatePresetsDefinitions();
|
||||
|
||||
this.initTCP();
|
||||
}
|
||||
|
||||
updateActionsDefinitions() { this.setActionDefinitions( this.getActions() ); }
|
||||
updateFeedbacksDefinitions() { this.setFeedbackDefinitions( this.getFeedbacks() ); }
|
||||
updateVariableDefinitions() { this.setVariableDefinitions( this.getVariables() ); this.initVariablesValues(); }
|
||||
updatePresetsDefinitions() { this.setPresetDefinitions( this.getPresets() ); }
|
||||
|
||||
// OUTPUTS
|
||||
getOutputsList(all) {
|
||||
var list = OUTPUTS;
|
||||
if(all) list.push( { id: '0', label: 'All Outputs' } );
|
||||
return list;
|
||||
}
|
||||
getOutByID(id) {
|
||||
var out = false;
|
||||
var l = OUTPUTS.length;
|
||||
for(var i=0; i<l; i++) {
|
||||
if(OUTPUTS[i].id == id) {
|
||||
out = OUTPUTS[i];
|
||||
out.num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
getFirstOutID() { return OUTPUTS[0].id; }
|
||||
|
||||
// INPUTS
|
||||
getInputsList() { return INPUTS; }
|
||||
getIptByID(id) {
|
||||
var ipt = false;
|
||||
var l = INPUTS.length;
|
||||
for(var i=0; i<l; i++) {
|
||||
if(INPUTS[i].id == id) {
|
||||
ipt = INPUTS[i];
|
||||
ipt.num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ipt;
|
||||
}
|
||||
getFirstIptID() { return INPUTS[0].id; }
|
||||
|
||||
// PRESETS
|
||||
getPresetsList() { return PRESETS; }
|
||||
getPstByID(id) {
|
||||
var pst = false;
|
||||
var l = PRESETS.length;
|
||||
for(var i=0; i<l; i++) {
|
||||
if(PRESETS[i].id == id) {
|
||||
pst = PRESETS[i];
|
||||
pst.num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pst;
|
||||
}
|
||||
getPstByName(name) {
|
||||
var pst = false;
|
||||
var l = PRESETS.length;
|
||||
for(var i=0; i<l; i++) {
|
||||
if(PRESETS[i].name == name) {
|
||||
pst = PRESETS[i];
|
||||
pst.num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pst;
|
||||
}
|
||||
getFirstPstID() { return PRESETS[0].id; }
|
||||
|
||||
// TCP CONNECTION
|
||||
initTCP() {
|
||||
this.killTCP();
|
||||
|
||||
this.log('info', `PT-MA-HD44M MIXER | INIT TCP CONNECTION >>> ${this.config.host} ${this.config.port}`);
|
||||
|
||||
if(this.config.host && this.config.port) {
|
||||
this.log('info', `PT-MA-HD44M MIXER | Opening TCP connection to ${this.config.host}:${this.config.port}`);
|
||||
this.socket = new TCPHelper(this.config.host, this.config.port, { reconnect: true });
|
||||
|
||||
this.socket.on('status_change', (status, message) => {
|
||||
this.updateStatus(status, message);
|
||||
this.setVariableValues({connect_status: status});
|
||||
this.checkFeedbacks('connect_status');
|
||||
|
||||
this.log('info', `PT-MA-HD44M MIXER | TCP connection status changed >>> ${status}`);
|
||||
if(status=="ok") {
|
||||
this.sendCommand('#get info');
|
||||
}
|
||||
else {
|
||||
this.clearTcpCommandBuffer();
|
||||
}
|
||||
});
|
||||
|
||||
this.socket.on('error', (err) => {
|
||||
this.updateStatus(InstanceStatus.ConnectionFailure, err.message);
|
||||
this.log('error', 'PT-MA-HD44M MIXER | Network error: ' + err.message);
|
||||
});
|
||||
|
||||
this.socket.on('data', (chunk) => {
|
||||
let i = 0;
|
||||
let line = '';
|
||||
let offset = 0;
|
||||
tcpReceivebuffer += chunk.toString();
|
||||
while ((i = tcpReceivebuffer.indexOf('\n', offset)) !== -1) {
|
||||
line = tcpReceivebuffer.slice(offset, i);
|
||||
offset = i + 1;
|
||||
line = line.replaceAll('\r\r', '');
|
||||
if(line!="") this.socket.emit('receiveline', line);
|
||||
}
|
||||
tcpReceivebuffer = tcpReceivebuffer.slice(offset);
|
||||
});
|
||||
this.socket.on('receiveline', (data) => {
|
||||
this.parseReceivedMessage(data.toString());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
killTCP() {
|
||||
this.clearTcpCommandBuffer();
|
||||
tcpReceivebuffer = '';
|
||||
if(this.socket !== undefined) {
|
||||
this.socket.destroy();
|
||||
delete this.socket;
|
||||
}
|
||||
this.setVariableValues({connect_status: 'disconnected'});
|
||||
this.checkFeedbacks('connect_status');
|
||||
}
|
||||
|
||||
// SEND COMMAND
|
||||
sendCommand(cmd, clbk) {
|
||||
if(cmd!='') {
|
||||
tcpCommandBuffer.push({cmd: cmd, clbk: clbk});
|
||||
this.sendNextCommand();
|
||||
}
|
||||
}
|
||||
sendPriorityCommand(cmd, clbk) {
|
||||
if(cmd!='') {
|
||||
tcpCommandBuffer.unshift({cmd: cmd, clbk: clbk});
|
||||
this.sendNextCommand();
|
||||
}
|
||||
}
|
||||
|
||||
async sendNextCommand() {
|
||||
if(tcpSendTimeout || tcpCommandBuffer.length==0) return;
|
||||
tcpSendTimeout = true;
|
||||
var cue = tcpCommandBuffer.shift();
|
||||
var cmd = cue.cmd;
|
||||
var escCmd = unescape(await this.parseVariablesInString(cmd));
|
||||
if(escCmd!="") {
|
||||
this.log('debug', `PT-MA-HD44M MIXER | SENDIND COMMAND >>> ${escCmd} | callback: ${cue.clbk}`);
|
||||
const sendBuf = Buffer.from(escCmd+"\n", 'latin1');
|
||||
if(this.socket !== undefined && this.socket.isConnected) {
|
||||
currentCmd = cue;
|
||||
this.socket.send(sendBuf);
|
||||
tcpSendTimeout = setTimeout(function(self) { self.onSendCommandTimeout(); }, this.config.timeout, this);
|
||||
}
|
||||
else this.log('warn', `PT-MA-HD44M MIXER | CANNOT SEND COMMAND - Socket not connected >>> ${cmd}`);
|
||||
}
|
||||
else if(tcpCommandBuffer.length>0) this.sendNextCommand();
|
||||
}
|
||||
|
||||
onSendCommandTimeout() {
|
||||
this.log('warn', `PT-MA-HD44M MIXER | SEND COMMAND TIMEOUT >>> ${currentCmd.cmd}`);
|
||||
tcpSendTimeout = undefined;
|
||||
currentCmd = false;
|
||||
this.sendNextCommand();
|
||||
}
|
||||
|
||||
clearTcpCommandBuffer() {
|
||||
if(tcpSendTimeout) { clearTimeout(tcpSendTimeout); tcpSendTimeout=undefined; }
|
||||
tcpCommandBuffer = [];
|
||||
currentCmd = false;
|
||||
}
|
||||
|
||||
// PARSE RECEIVED MESSAGE
|
||||
parseReceivedMessage(msg) {
|
||||
if(tcpSendTimeout) { clearTimeout(tcpSendTimeout); tcpSendTimeout=undefined; }
|
||||
|
||||
this.log('debug', `PT-MA-HD44M MIXER | receive message > "${msg}"`);
|
||||
|
||||
let namePos = msg.indexOf("[name=");
|
||||
let endNamePos = msg.indexOf("]");
|
||||
let dataPos = msg.indexOf("[Data=");
|
||||
let endDataPos = msg.indexOf(" : ", dataPos);
|
||||
let xptPos = msg.indexOf("Video matrix");
|
||||
|
||||
// GET INFOS - INPUT NAME
|
||||
if(msg.slice(0,6) == "<Input" && namePos>0 && endNamePos>0) {
|
||||
let ipt = this.getIptByID( msg.substr(6,1) );
|
||||
let name = msg.slice(namePos+6, endNamePos);
|
||||
if(ipt && ipt.name != name) {
|
||||
this.log('info', `PT-MA-HD44M MIXER | INPUT #${ipt.id} - NAME CHANGED >>> ${name}`);
|
||||
ipt.name = name;
|
||||
INPUTS[ipt.num] = ipt;
|
||||
this.setVariableValue(ipt.var_name, name);
|
||||
}
|
||||
}
|
||||
// GET INFOS - OUTPUT NAME
|
||||
else if(msg.slice(0,7) == "<Output" && namePos>0 && endNamePos>0) {
|
||||
let out = this.getOutByID( msg.substr(7,1) );
|
||||
let name = msg.slice(namePos+6, endNamePos);
|
||||
if(out && out.name != name) {
|
||||
this.log('info', `PT-MA-HD44M MIXER | OUTPUT #${out.id} - NAME CHANGED >>> ${name}`);
|
||||
out.name = name;
|
||||
OUTPUTS[out.num] = out;
|
||||
this.setVariableValue(out.var_name, name);
|
||||
}
|
||||
}
|
||||
// GET INFOS - PRESET NAME
|
||||
else if(msg.slice(0,7) == "<Preset" && namePos>0 && endNamePos>0) {
|
||||
let pst = this.getPstByID( msg.substr(7,1) );
|
||||
let name = msg.slice(namePos+6, endNamePos);
|
||||
if(pst && pst.name != name) {
|
||||
this.log('info', `PT-MA-HD44M MIXER | PRESET #${pst.id} - NAME CHANGED >>> ${name}`);
|
||||
pst.name = name;
|
||||
PRESETS[pst.num] = pst;
|
||||
this.setVariableValue(pst.var_name, name);
|
||||
}
|
||||
}
|
||||
|
||||
// OUTPUT XPT
|
||||
else if(msg.slice(0,7) == "<Output" && xptPos>0 && dataPos>0 && endDataPos>0) {
|
||||
let out = this.getOutByID( msg.substr(7,1) );
|
||||
let xpt = (parseInt( msg.slice(dataPos+6, endDataPos) ) + 1).toString();
|
||||
if(out && out.xpt != xpt) {
|
||||
this.log('info', `PT-MA-HD44M MIXER | OUTPUT #${out.id} - XPT CHANGED >>> ${xpt}`);
|
||||
out.xpt = xpt;
|
||||
OUTPUTS[out.num] = out;
|
||||
this.setVariableValue(out.var_xpt, xpt);
|
||||
this.checkFeedbacks('crosspoint_status');
|
||||
}
|
||||
}
|
||||
|
||||
// SET NAME
|
||||
else if(msg.slice(0,8) == "Set name") {
|
||||
let nameID = parseInt(msg.slice(8));
|
||||
let name = msg.slice( msg.indexOf(" > ")+3 );
|
||||
// INPUTS
|
||||
if(nameID<4) {
|
||||
let ipt = INPUTS[nameID];
|
||||
if(ipt.name != name) {
|
||||
this.log('info', `INPUT #${ipt.id} - NAME = ${name}`);
|
||||
ipt.name = name;
|
||||
INPUTS[nameID] = ipt;
|
||||
this.setVariableValue(ipt.var_name, name);
|
||||
}
|
||||
}
|
||||
// OUTPUTS
|
||||
else if(nameID<8) {
|
||||
let out = OUTPUTS[nameID-4];
|
||||
if(out.name != name) {
|
||||
this.log('info', `OUTPUT #${out.id} - NAME = ${name}`);
|
||||
out.name = name;
|
||||
OUTPUTS[nameID-4] = out;
|
||||
this.setVariableValue(out.var_name, name);
|
||||
}
|
||||
}
|
||||
// PRESETS
|
||||
else {
|
||||
let pst = PRESETS[nameID-8];
|
||||
if(pst.name != name) {
|
||||
this.log('info', `PRESET #${pst.id} - NAME = ${name}`);
|
||||
pst.name = name;
|
||||
PRESETS[nameID-8] = pst;
|
||||
this.setVariableValue(pst.var_name, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PRESET
|
||||
else if(msg.slice(0,7) == "Preset:") {
|
||||
let p = msg.split(' ');
|
||||
let pst = this.getPstByName(p[1]);
|
||||
console.log(p);
|
||||
|
||||
// SAVE
|
||||
if(p[2] == "Save") {
|
||||
this.log('info', `PT-MA-HD44M MIXER | PRESET #${pst.id} SAVED >>> ${p[1]}`);
|
||||
this.saveLastPstID(pst.id);
|
||||
}
|
||||
// CALL
|
||||
else if(p[2] == "Call") {
|
||||
this.log('info', `PT-MA-HD44M MIXER | PRESET #${pst.id} RECALLED >>> ${p[1]}`);
|
||||
this.saveLastPstID(pst.id);
|
||||
|
||||
// REFRESH INFO
|
||||
this.sendPriorityCommand('#get info');
|
||||
}
|
||||
// CLEAR
|
||||
else if(p[2] == "Clear") {
|
||||
this.log('info', `PT-MA-HD44M MIXER | PRESET #${pst.id} CLEARED >>> ${p[1]}`);
|
||||
if(this.getLastPstID() == pst.id) this.saveLastPstID(0);
|
||||
}
|
||||
}
|
||||
|
||||
currentCmd = false;
|
||||
|
||||
this.sendNextCommand();
|
||||
}
|
||||
|
||||
// CURRENT PRESET
|
||||
getLastPstID() { return this.getVariableValue('pst_last'); }
|
||||
saveLastPstID(id) {
|
||||
id = parseInt(id);
|
||||
if(id<0 || id>8) return;
|
||||
let last = this.getLastPstID();
|
||||
if(last != id) {
|
||||
this.setVariableValue('pst_last', id.toString());
|
||||
this.checkFeedbacks('last_pst');
|
||||
}
|
||||
}
|
||||
|
||||
// SET VARIABLE VALUE
|
||||
setVariableValue(name, value) {
|
||||
const variables = {};
|
||||
variables[name] = value;
|
||||
this.setVariableValues(variables);
|
||||
}
|
||||
}
|
||||
|
||||
runEntrypoint(MixerInstance, []);
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "purelink-pt-ma-hd44m",
|
||||
"version": "1.0.0",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"format": "prettier -w ."
|
||||
},
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/bitfocus/companion-module-purelink-pt-ma-hd44m.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@companion-module/base": "~1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@companion-module/tools": "^1.3.2"
|
||||
},
|
||||
"prettier": "@companion-module/tools/.prettierrc.json",
|
||||
"packageManager": "yarn@4.9.2"
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
const { combineRgb } = require('@companion-module/base');
|
||||
module.exports = {
|
||||
getPresets() {
|
||||
const presets = {};
|
||||
|
||||
// CROSSPOINTS
|
||||
var outList = this.getOutputsList(false);
|
||||
var iptList = this.getInputsList(false);
|
||||
outList.forEach((out) => {
|
||||
iptList.forEach((ipt) => {
|
||||
|
||||
presets[`xpt_${out.id}_${ipt.id}`] = {
|
||||
type: 'button',
|
||||
category: out.label+" - XPT",
|
||||
style: {
|
||||
text: `OUT#${out.id} \nIN#${ipt.id}`,
|
||||
size: '16',
|
||||
color: combineRgb(255, 255, 255),
|
||||
bgcolor: combineRgb(0, 0, 0)
|
||||
},
|
||||
steps: [{
|
||||
down: [{
|
||||
actionId: 'setCrosspoint',
|
||||
options: { out: out.id, ipt: ipt.id }
|
||||
}]
|
||||
}],
|
||||
feedbacks: [
|
||||
{
|
||||
feedbackId: 'crosspoint_status',
|
||||
options: { outID: out.id, xpt: ipt.id },
|
||||
style: { bgcolor: combineRgb(255, 0, 0) }
|
||||
},
|
||||
{
|
||||
feedbackId: 'connect_status',
|
||||
options: {},
|
||||
isInverted: true,
|
||||
style: { color: combineRgb(255, 80, 80), bgcolor: combineRgb(80, 0, 0) }
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
// RECALL PRESETS
|
||||
var pstList = this.getPresetsList(false);
|
||||
pstList.forEach((pst) => {
|
||||
presets[`recall_pst${pst.id}`] = {
|
||||
type: 'button',
|
||||
category: "Preset - Recall",
|
||||
style: {
|
||||
text: `Recall \nPST#${pst.id}`,
|
||||
size: '16',
|
||||
color: combineRgb(24, 76, 119),
|
||||
bgcolor: combineRgb(128, 198, 255)
|
||||
},
|
||||
steps: [{
|
||||
down: [{
|
||||
actionId: 'recallPreset',
|
||||
options: { pst: pst.id }
|
||||
}]
|
||||
}],
|
||||
feedbacks: [
|
||||
{
|
||||
feedbackId: 'last_pst',
|
||||
options: { pst: pst.id },
|
||||
style: { color: combineRgb(255, 255, 255), bgcolor: combineRgb(27, 158, 62) }
|
||||
},
|
||||
{
|
||||
feedbackId: 'connect_status',
|
||||
options: {},
|
||||
isInverted: true,
|
||||
style: { color: combineRgb(255, 80, 80), bgcolor: combineRgb(80, 0, 0) }
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
// SAVE PRESETS
|
||||
pstList.forEach((pst) => {
|
||||
presets[`save_pst${pst.id}`] = {
|
||||
type: 'button',
|
||||
category: "Preset - Save",
|
||||
style: {
|
||||
text: `Save \nPST#${pst.id}`,
|
||||
size: '16',
|
||||
color: combineRgb(0, 0, 0),
|
||||
bgcolor: combineRgb(249, 177, 21)
|
||||
},
|
||||
steps: [{
|
||||
down: [{
|
||||
actionId: 'savePreset',
|
||||
options: { pst: pst.id }
|
||||
}]
|
||||
}],
|
||||
feedbacks: [
|
||||
{
|
||||
feedbackId: 'connect_status',
|
||||
options: {},
|
||||
isInverted: true,
|
||||
style: { color: combineRgb(255, 80, 80), bgcolor: combineRgb(80, 0, 0) }
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
// CLEAR PRESETS
|
||||
pstList.forEach((pst) => {
|
||||
presets[`clear_pst${pst.id}`] = {
|
||||
type: 'button',
|
||||
category: "Preset - Clear",
|
||||
style: {
|
||||
text: `Clear \nPST#${pst.id}`,
|
||||
size: '16',
|
||||
color: combineRgb(255, 255, 255),
|
||||
bgcolor: combineRgb(213, 2, 2)
|
||||
},
|
||||
steps: [{
|
||||
down: [{
|
||||
actionId: 'clearPreset',
|
||||
options: { pst: pst.id }
|
||||
}]
|
||||
}],
|
||||
feedbacks: [
|
||||
{
|
||||
feedbackId: 'connect_status',
|
||||
options: {},
|
||||
isInverted: true,
|
||||
style: { color: combineRgb(255, 80, 80), bgcolor: combineRgb(80, 0, 0) }
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
return presets;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
module.exports = {
|
||||
getVariables() {
|
||||
const variables = [];
|
||||
|
||||
// CONNECTED
|
||||
variables.push({ variableId: 'connect_status', name: 'Connection Status' });
|
||||
|
||||
// INPUTS
|
||||
var list = this.getInputsList(false);
|
||||
list.forEach((i) => {
|
||||
variables.push({ variableId: i.var_name, name: `${i.label} - NAME` });
|
||||
});
|
||||
|
||||
// OUTPUTS
|
||||
list = this.getOutputsList(false);
|
||||
list.forEach((i) => {
|
||||
variables.push({ variableId: i.var_name, name: `${i.label} - NAME` });
|
||||
variables.push({ variableId: i.var_xpt , name: `${i.label} - XPT` });
|
||||
});
|
||||
|
||||
// PRESETS
|
||||
list = this.getPresetsList(false);
|
||||
list.forEach((i) => {
|
||||
variables.push({ variableId: i.var_name, name: `${i.label} - NAME` });
|
||||
});
|
||||
|
||||
// LAST PRESET
|
||||
variables.push({ variableId: "pst_last", name: `Last Recalled Preset` });
|
||||
|
||||
return variables;
|
||||
},
|
||||
initVariablesValues() {
|
||||
const variables = {};
|
||||
|
||||
// INPUTS NAMES
|
||||
var list = this.getInputsList();
|
||||
list.forEach((i) => { variables[i.var_name] = i.label; });
|
||||
|
||||
// OUTPUTS NAMES
|
||||
list = this.getOutputsList();
|
||||
list.forEach((i) => { variables[i.var_name] = i.label; });
|
||||
|
||||
// PRESETS NAMES
|
||||
list = this.getPresetsList();
|
||||
list.forEach((i) => { variables[i.var_name] = i.label; });
|
||||
|
||||
// LAST PRESET
|
||||
variables.pst_last = 0;
|
||||
|
||||
this.setVariableValues(variables);
|
||||
}
|
||||
};
|
||||
Loading…
Reference in New Issue