Merge pull request #29 from stagehacks/lint-n-pretty

Lint n pretty
This commit is contained in:
2022-12-15 13:14:16 -06:00
committed by GitHub
32 changed files with 749 additions and 696 deletions
+1 -1
View File
@@ -20,6 +20,6 @@ module.exports = {
'no-use-before-define': 'off',
'space-infix-ops': 'warn',
'no-bitwise': 'off',
'no-restricted-globals': 'off'
'no-restricted-globals': 'off',
},
};
-1
View File
@@ -42,4 +42,3 @@ jobs:
node-version: 18
- run: npm ci
- run: npm run release
-1
View File
@@ -1,7 +1,6 @@
.DS_Store
node_modules
.vscode
/dist
package-lock.json
package-lock.json
+3
View File
@@ -0,0 +1,3 @@
{
"recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
}
+8
View File
@@ -0,0 +1,8 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"eslint.validate": ["javascript"]
}
+1 -3
View File
@@ -88,14 +88,12 @@
<th>Pin:</th>
<td><input id="device-settings-pin" type="checkbox" /></td>
</tr>
<tbody id="device-settings-fields">
</tbody>
<tbody id="device-settings-fields"></tbody>
</table>
<h3>No Device Selected</h3>
</div>
</div>
</div>
<div id="all-devices"></div>
+127 -124
View File
@@ -1,4 +1,11 @@
const { app, BrowserWindow, Menu, ipcMain, nativeTheme, dialog } = require('electron');
const {
app,
BrowserWindow,
Menu,
ipcMain,
nativeTheme,
dialog,
} = require('electron');
const { autoUpdater } = require('electron-updater');
const path = require('path');
@@ -10,7 +17,6 @@ let manualUpdateCheck = false;
let menuObj;
let mainWindow;
const menuTemplate = [
...(isMac ? [{ role: 'appMenu' }] : []),
{
@@ -19,17 +25,17 @@ const menuTemplate = [
{
label: 'Clear Saved Data',
id: 'resetViews',
click (menuItem, window, event) {
click(menuItem, window, event) {
mainWindow.webContents.send('resetViews');
}
},
},
{
label: 'Reload App',
role: 'reload'
role: 'reload',
},
{ type: 'separator' },
...(isMac ? [{ role: 'close' }] : [{ role: 'quit' }])
]
...(isMac ? [{ role: 'close' }] : [{ role: 'quit' }]),
],
},
{ role: 'editMenu' },
{
@@ -42,31 +48,31 @@ const menuTemplate = [
accelerator: 'CommandOrControl+1',
id: 'window1',
enabled: true,
click (menuItem, window, event) {
mainWindow.webContents.send('loadSlot',1);
}
click(menuItem, window, event) {
mainWindow.webContents.send('loadSlot', 1);
},
},
{
label: 'Arrangement 2',
accelerator: 'CommandOrControl+2',
id: 'window2',
enabled: true,
click (menuItem, window, event) {
mainWindow.webContents.send('loadSlot',2);
}
click(menuItem, window, event) {
mainWindow.webContents.send('loadSlot', 2);
},
},
{
label: 'Arrangement 3',
accelerator: 'CommandOrControl+3',
id: 'window3',
enabled: true,
click (menuItem, window, event) {
mainWindow.webContents.send('loadSlot',3);
}
click(menuItem, window, event) {
mainWindow.webContents.send('loadSlot', 3);
},
},
{ type: 'separator' },
{ role: 'toggleDevTools' }
]
{ role: 'toggleDevTools' },
],
},
{
label: 'Device',
@@ -76,9 +82,9 @@ const menuTemplate = [
accelerator: 'CommandOrControl+F',
id: 'deviceSearch',
enabled: true,
click (menuItem, window, event) {
click(menuItem, window, event) {
mainWindow.webContents.send('searchAll');
}
},
},
{ type: 'separator' },
{
@@ -88,23 +94,23 @@ const menuTemplate = [
accelerator: 'CommandOrControl+P',
id: 'devicePin',
enabled: false,
click (menuItem, window, event) {
click(menuItem, window, event) {
mainWindow.webContents.send(
'setActiveDevicePinned',
menuItem.checked
);
}
},
},
{
label: 'Delete',
accelerator: 'CommandOrControl+Backspace',
id: 'deviceDelete',
enabled: false,
click (menuItem, window, event) {
click(menuItem, window, event) {
mainWindow.webContents.send('deleteActive');
}
}
]
},
},
],
},
{
label: 'Help',
@@ -112,67 +118,64 @@ const menuTemplate = [
submenu: [
{
label: 'About',
role: 'about'
role: 'about',
},
{
label: 'Check for Updates',
click: ()=>{
click: () => {
// set manual update flag
manualUpdateCheck = true
manualUpdateCheck = true;
autoUpdater.checkForUpdates();
}
},
},
{
label: 'Enable Auto Update',
click: ()=>{
mainWindow.webContents.send('setAutoUpdate',!autoUpdate);
}
}
]
click: () => {
mainWindow.webContents.send('setAutoUpdate', !autoUpdate);
},
},
],
},
];
const windowMac = {
width: 1500,
height: 900,
titleBarStyle: 'hiddenInset',
transparent: true,
frame: false,
show: false,
// backgroundColor: "#333333",
vibrancy: 'window',
visualEffectState: 'followWindow',
webPreferences: {
contextIsolation: false,
nodeIntegration: true,
preload: path.join(__dirname, 'preload.js'),
},
}
const windowWin = {
width: 1500,
height: 900,
backgroundColor: "#333333",
titleBarStyle: 'hiddenInset',
transparent: true,
frame: false,
show: false,
// backgroundColor: "#333333",
vibrancy: 'window',
visualEffectState: 'followWindow',
webPreferences: {
contextIsolation: false,
nodeIntegration: true,
preload: path.join(__dirname, 'preload.js'),
},
}
};
if (isWin)
{
app.setAppUserModelId(app.name);
const windowWin = {
width: 1500,
height: 900,
backgroundColor: '#333333',
webPreferences: {
contextIsolation: false,
nodeIntegration: true,
preload: path.join(__dirname, 'preload.js'),
},
};
if (isWin) {
app.setAppUserModelId(app.name);
}
const createWindow = () => {
nativeTheme.themeSource = 'dark';
if(isMac){
if (isMac) {
mainWindow = new BrowserWindow(windowMac);
}else{
} else {
mainWindow = new BrowserWindow(windowWin);
}
@@ -192,7 +195,7 @@ const createWindow = () => {
app.whenReady().then(() => {
createWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
@@ -224,134 +227,134 @@ ipcMain.on('setDevicePin', (event, arg) => {
menuObj.getMenuItemById('devicePin').checked = arg;
});
// Autoupdate logic
ipcMain.on('checkForUpdates', (event, arg)=>{
ipcMain.on('checkForUpdates', (event, arg) => {
autoUpdater.checkForUpdates();
})
});
ipcMain.on('setAutoUpdate', (event, _autoUpdate) => {
autoUpdate = _autoUpdate;
ipcMain.on('setAutoUpdate', (event, _autoUpdate)=>{
autoUpdate = _autoUpdate
// update menu item for enabling/disabling auto update
menuTemplate[menuTemplate.length-1].submenu[2].label = autoUpdate ? 'Disable Auto Update' : 'Enable Auto Update';
menuTemplate[menuTemplate.length - 1].submenu[2].label = autoUpdate
? 'Disable Auto Update'
: 'Enable Auto Update';
menuObj = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(menuObj);
})
});
// this can be set to true to bypass the download update dialog and skip straight to install prompt
autoUpdater.autoDownload = false;
autoUpdater.on('update-available', (updateInfo) => {
// skip prompting to download if autoDownload is set
if(autoUpdater.autoDownload){
if (autoUpdater.autoDownload) {
return;
}
const msg = `Version v${updateInfo.version} is available. Would you like to download it?`
const msg = `Version v${updateInfo.version} is available. Would you like to download it?`;
const title = 'Update Available';
let dialogOpts = {}
let dialogOpts = {};
if(isMac){
if (isMac) {
dialogOpts = {
type: 'info',
buttons: ['Download', 'Cancel'],
title: 'Update Available',
message: title,
detail: msg
}
}else{
detail: msg,
};
} else {
dialogOpts = {
type: 'info',
buttons: ['Download', 'Cancel'],
title: 'Update Available',
message: msg
}
message: msg,
};
}
dialog.showMessageBox(mainWindow,dialogOpts).then((returnValue) => {
dialog.showMessageBox(mainWindow, dialogOpts).then((returnValue) => {
// download was clicked
if (returnValue.response === 0){
if (returnValue.response === 0) {
autoUpdater.downloadUpdate();
}
})
})
});
});
autoUpdater.on('update-downloaded',(event)=>{
autoUpdater.on('update-downloaded', (event) => {
const title = 'Update Downloaded';
const msg = `Version v${event.version} has been downloaded. Would you like to install this update now?`
const msg = `Version v${event.version} has been downloaded. Would you like to install this update now?`;
let dialogOpts = {}
if(isMac){
let dialogOpts = {};
if (isMac) {
dialogOpts = {
type: 'info',
buttons: ['Install', 'Later'],
title: 'Update Available',
message: title,
detail: msg
}
}else{
detail: msg,
};
} else {
dialogOpts = {
type: 'info',
buttons: ['Install', 'Later'],
title: 'Update Available',
message: msg
}
message: msg,
};
}
dialog.showMessageBox(mainWindow,dialogOpts).then((returnValue) => {
if (returnValue.response === 0) autoUpdater.quitAndInstall()
})
})
autoUpdater.on('update-not-available',(updateInfo)=>{
if(manualUpdateCheck){
let dialogOpts = {}
const msg = `There is no update available at this time. Latest version is v${updateInfo.version}`
if(isMac){
dialog.showMessageBox(mainWindow, dialogOpts).then((returnValue) => {
if (returnValue.response === 0) autoUpdater.quitAndInstall();
});
});
autoUpdater.on('update-not-available', (updateInfo) => {
if (manualUpdateCheck) {
let dialogOpts = {};
const msg = `There is no update available at this time. Latest version is v${updateInfo.version}`;
if (isMac) {
dialogOpts = {
type: 'info',
buttons: ['Ok'],
title: 'No Update Available',
message: 'No Update Available',
detail: msg
}
}else{
detail: msg,
};
} else {
dialogOpts = {
type: 'info',
buttons: ['Ok'],
title: 'No Update Available',
message: msg
}
message: msg,
};
}
dialog.showMessageBox(mainWindow,dialogOpts)
dialog.showMessageBox(mainWindow, dialogOpts);
// revert manual update flag
manualUpdateCheck = false;
}
})
});
autoUpdater.on('error',(error,message)=>{
let dialogOpts = {}
if(isMac){
autoUpdater.on('error', (error, message) => {
let dialogOpts = {};
if (isMac) {
dialogOpts = {
type: 'error',
buttons: ['Ok'],
title: 'Update Error',
message: 'Update Error',
detail: error.message
}
}else{
detail: error.message,
};
} else {
dialogOpts = {
type: 'error',
buttons: ['Ok'],
title: 'Update Error',
message: error.message
}
message: error.message,
};
}
dialog.showMessageBox(mainWindow,dialogOpts)
})
dialog.showMessageBox(mainWindow, dialogOpts);
});
+38 -35
View File
@@ -1,41 +1,44 @@
const notarize = require('@electron/notarize');
const fs = require('fs')
const path = require('path')
const fs = require('fs');
const path = require('path');
module.exports = async function (params) {
if (process.platform !== 'darwin') {
console.log('Only need to notarize MacOS, skipping')
return
}
const appId = 'com.stagehacks.cueview'
if (process.platform !== 'darwin') {
console.log('Only need to notarize MacOS, skipping');
return;
}
const appPath = path.join(
params.appOutDir,
`${params.packager.appInfo.productFilename}.app`
)
const appId = 'com.stagehacks.cueview';
if (!fs.existsSync(appPath)) {
console.error('App file not found skipping notarization.');
return;
}
if(process.env.APPLE_ID === undefined || process.env.APPLE_ID_PASSWORD === undefined){
console.log('Apple ID and Password must be set in order to notarize.')
return;
}
const appPath = path.join(
params.appOutDir,
`${params.packager.appInfo.productFilename}.app`
);
try {
console.log(`Notarizing ${appId} found at ${appPath}`)
await notarize.notarize({
appBundleId: appId,
appPath,
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_ID_PASSWORD,
})
console.log(`Done notarizing ${appId}`)
} catch (error) {
console.log('There was an error notarizing.')
console.error(error)
}
}
if (!fs.existsSync(appPath)) {
console.error('App file not found skipping notarization.');
return;
}
if (
process.env.APPLE_ID === undefined ||
process.env.APPLE_ID_PASSWORD === undefined
) {
console.log('Apple ID and Password must be set in order to notarize.');
return;
}
try {
console.log(`Notarizing ${appId} found at ${appPath}`);
await notarize.notarize({
appBundleId: appId,
appPath,
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_ID_PASSWORD,
});
console.log(`Done notarizing ${appId}`);
} catch (error) {
console.log('There was an error notarizing.');
console.error(error);
}
};
+1 -1
View File
@@ -1,2 +1,2 @@
<p><em>Art-Net</em> requires no configuration.</p>
<p>Art-Net™ Designed by and Copyright Artistic Licence Holdings Ltd</p>
<p>Art-Net™ Designed by and Copyright Artistic Licence Holdings Ltd</p>
+32 -34
View File
@@ -1,8 +1,8 @@
const _ = require('lodash');
exports.config = {
defaultName: "Art-Net",
connectionType: "UDPsocket",
defaultName: 'Art-Net',
connectionType: 'UDPsocket',
heartbeatInterval: 10000,
searchOptions: {
type: 'UDPsocket',
@@ -10,10 +10,10 @@ exports.config = {
devicePort: 6454,
listenPort: 6454,
mayChangePort: false,
validateResponse (msg, info, devices) {
return msg.toString('utf8', 0, 7) === "Art-Net";
}
}
validateResponse(msg, info, devices) {
return msg.toString('utf8', 0, 7) === 'Art-Net';
},
},
};
exports.defaultPort = 6454;
@@ -25,14 +25,14 @@ exports.ready = function ready(_device) {
};
exports.data = function data(_device, buf) {
if(buf.length < 18){
return
if (buf.length < 18) {
return;
}
const universeIndex = buf.readUInt8(14);
const device = _device;
let universe = device.data.universes[universeIndex];
if(!universe){
if (!universe) {
device.data.universes[universeIndex] = {};
universe = device.data.universes[universeIndex];
}
@@ -41,10 +41,10 @@ exports.data = function data(_device, buf) {
universe.subnet = buf.readUInt8(15);
universe.opCode = buf.readUInt8(9);
universe.version = buf.readUInt16BE(10);
universe.slots = buf.slice(18)
universe.slots = buf.slice(18);
device.data.ip = device.addresses[0];
if(!_.includes(device.data.orderedUniverses, universeIndex)){
if (!_.includes(device.data.orderedUniverses, universeIndex)) {
device.data.orderedUniverses.push(universeIndex);
device.data.orderedUniverses.sort();
universe.slotElems = [];
@@ -54,49 +54,47 @@ exports.data = function data(_device, buf) {
device.update('elementCache');
}
device.update("universeData", {
device.update('universeData', {
universeIndex,
universe
universe,
});
};
exports.heartbeat = function heartbeat(device) {
};
exports.heartbeat = function heartbeat(device) {};
let lastUpdate = Date.now();
exports.update = function update(_device, _document, updateType, updateData){
const device = _device
exports.update = function update(_device, _document, updateType, updateData) {
const device = _device;
const data = updateData;
const document = _document;
if(updateType === "universeData" && data.universe){
if(Date.now() - lastUpdate > 1000){
if (updateType === 'universeData' && data.universe) {
if (Date.now() - lastUpdate > 1000) {
lastUpdate = Date.now();
device.update("elementCache");
device.update('elementCache');
}
const $elem = document.getElementById(`universe-${data.universeIndex}`);
if($elem && data.universe.slotElemsSet){
for(let i = 0; i < 512; i++){
if ($elem && data.universe.slotElemsSet) {
for (let i = 0; i < 512; i++) {
data.universe.slotElems[i].innerText = data.universe.slots[i];
}
document.getElementById(`universe-${data.universeIndex}-sequence`).innerText = data.universe.sequence;
}else{
document.getElementById(
`universe-${data.universeIndex}-sequence`
).innerText = data.universe.sequence;
} else {
device.draw();
device.update("elementCache");
device.update('elementCache');
}
}else if(updateType === "elementCache"){
device.data.orderedUniverses.forEach(universeIndex => {
for(let i = 0; i < 512; i++){
device.data.universes[universeIndex].slotElems[i] = document.getElementById(`${universeIndex}-${i}`);
} else if (updateType === 'elementCache') {
device.data.orderedUniverses.forEach((universeIndex) => {
for (let i = 0; i < 512; i++) {
device.data.universes[universeIndex].slotElems[i] =
document.getElementById(`${universeIndex}-${i}`);
}
device.data.universes[universeIndex].slotElemsSet = true;
});
}
}
};
+10 -7
View File
@@ -2,14 +2,17 @@
<h4>Shell/ECU &rarr; Network</h4>
<ul>
<li>Enable <em>&#10004; TCP OSC</em>. The TCP format dropdown does not matter.</li>
<li>Enable <em>Third Party OSC</em></li>
<li>
Enable <em>&#10004; TCP OSC</em>. The TCP format dropdown does not matter.
</li>
<li>Enable <em>Third Party OSC</em></li>
</ul>
If the "Third Party OSC" option is not available, Eos must be updated to 3.1 or newer.
If the "Third Party OSC" option is not available, Eos must be updated to 3.1 or
newer.
<h4>System Settings &rarr; Show Control &rarr; OSC</h4>
<ul>
<li>Enable <em>&#10004; OSC RX</em></li>
<li>Enable <em>&#10004; OSC TX</em></li>
<li>All other fields may be left to defaults or blank.</li>
</ul>
<li>Enable <em>&#10004; OSC RX</em></li>
<li>Enable <em>&#10004; OSC TX</em></li>
<li>All other fields may be left to defaults or blank.</li>
</ul>
+34 -11
View File
@@ -4,8 +4,8 @@ const path = require('path');
const Cue = require('./cue');
exports.config = {
defaultName: "ETC Eos",
connectionType: "osc",
defaultName: 'ETC Eos',
connectionType: 'osc',
defaultPort: 3032,
mayChangePort: false,
searchOptions: {
@@ -17,9 +17,9 @@ exports.config = {
testPort: 3032,
validateResponse(msg, info) {
return msg.toString().indexOf('/eos/out');
}
}
}
},
},
};
exports.ready = function ready(_device) {
const device = _device;
@@ -53,7 +53,18 @@ exports.data = function data(_device, osc) {
device.send(`/eos/get/cue/${addressParts[4]}/index/${i}`);
}
} else if (
match(addressParts, [ 'eos', 'out', 'get','cue', '*', '*', '*', 'list', '*', '*',])
match(addressParts, [
'eos',
'out',
'get',
'cue',
'*',
'*',
'*',
'list',
'*',
'*',
])
) {
this.deviceInfoUpdate(device, 'status', 'ok');
if (
@@ -76,7 +87,19 @@ exports.data = function data(_device, osc) {
delete device.data.EOS.cueLists[addressParts[4]][addressParts[5]];
device.draw();
} else if (
match(addressParts, ['eos', 'out', 'get', 'cue', '*', '*', '*', 'actions', 'list', '*', '*'])
match(addressParts, [
'eos',
'out',
'get',
'cue',
'*',
'*',
'*',
'actions',
'list',
'*',
'*',
])
) {
if (osc.args.length === 3) {
device.data.EOS.cueLists[addressParts[4]][addressParts[5]][0].extLinks =
@@ -130,13 +153,13 @@ exports.heartbeat = function heartbeat(device) {
device.send('/eos/ping');
};
function match(testArray, patternArray){
function match(testArray, patternArray) {
let out = true;
if(testArray.length !== patternArray.length){
if (testArray.length !== patternArray.length) {
return false;
}
patternArray.forEach((patternPart, i)=> {
if(testArray[i] !== patternPart && patternPart !== "*"){
patternArray.forEach((patternPart, i) => {
if (testArray[i] !== patternPart && patternPart !== '*') {
out = false;
}
});
+2 -2
View File
@@ -1,4 +1,4 @@
<h3>Connection Requirements</h3>
<ul>
<li>Requires no password on the projector</li>
</ul>
<li>Requires no password on the projector</li>
</ul>
+27 -29
View File
@@ -2,7 +2,7 @@ const md5 = require('md5');
exports.config = {
defaultName: 'PJLink Projector',
connectionType: "TCPsocket",
connectionType: 'TCPsocket',
heartbeatInterval: 5000,
heartbeatTimeout: 15000,
defaultPort: 4352,
@@ -12,28 +12,29 @@ exports.config = {
searchBuffer: Buffer.from([0x25, 0x32, 0x53, 0x52, 0x43, 0x48, 0x0d]),
devicePort: 4352,
listenPort: 4352,
validateResponse (msg, info) {
validateResponse(msg, info) {
console.log(msg.toString());
return msg.toString().indexOf('%2ACKN=') >= 0;
}
},
},
fields: [{
key: "password",
label: "Pass",
type: "textinput",
value: "",
action: function(device){
device.plugin.heartbeat(device);
}
}]
}
fields: [
{
key: 'password',
label: 'Pass',
type: 'textinput',
value: '',
action(device) {
device.plugin.heartbeat(device);
},
},
],
};
exports.ready = function ready(device) {
// Power status query
// device.send("%1POWR ?\r");
};
const PJLinkCmds = [
'%1POWR=',
'%1INPT=',
@@ -44,8 +45,8 @@ const PJLinkCmds = [
'%1INF1=',
'%1INF2=',
'%2SNUM=',
'%2SVER='
]
'%2SVER=',
];
let passwordMD5 = false;
let passwordSeed = false;
@@ -114,44 +115,41 @@ function processPJLink(_device, str, that) {
device.draw();
}
exports.data = function data(device, message) {
exports.data = function data(_device, message) {
this.deviceInfoUpdate(device, 'status', 'ok');
const msg = message.toString();
//console.log(msg);
const device = _device;
if (msg.substring(0, 8) === 'PJLINK 1') {
passwordSeed = msg.substring(9, 17);
passwordMD5 = md5(`${passwordSeed}${device.fields.password}`);
device.data.authentication = "ON";
device.data.authentication = 'ON';
device.send(
`${passwordMD5}%1POWR ?\r%1INPT ?\r%1AVMT ?\r%1ERST ?\r%1LAMP ?\r%1NAME ?\r%1INF1 ?\r%1INF2 ?\r%2SNUM ?\r%2SVER ?\r`
);
device.draw();
}else if(msg.substring(0, 8) === 'PJLINK 0') {
device.data.authentication = "OFF";
} else if (msg.substring(0, 8) === 'PJLINK 0') {
device.data.authentication = 'OFF';
device.draw();
}else if(msg.startsWith('PJLINK ERRA')) {
} else if (msg.startsWith('PJLINK ERRA')) {
device.data.passwordOK = false;
device.draw();
}
if(PJLinkCmds.includes(msg.substring(0,7))){
processPJLink(device,msg,this);
if (PJLinkCmds.includes(msg.substring(0, 7))) {
processPJLink(device, msg, this);
device.data.passwordOK = true;
}
};
exports.heartbeat = function heartbeat(device) {
passwordMD5 = md5(`${passwordSeed}${device.fields.password}`);
if (device.fields.password.length>0) {
if (device.fields.password.length > 0) {
device.send(
`${passwordMD5}%1POWR ?\r%1INPT ?\r%1AVMT ?\r%1ERST ?\r%1LAMP ?\r%1NAME ?\r%1INF1 ?\r%1INF2 ?\r%2SNUM ?\r%2SVER ?\r`
);
}else{
} else {
device.send(
`%1POWR ?\r%1INPT ?\r%1AVMT ?\r%1ERST ?\r%1LAMP ?\r%1NAME ?\r%1INF1 ?\r%1INF2 ?\r%2SNUM ?\r%2SVER ?\r`
);
+1 -1
View File
@@ -7,7 +7,7 @@
.ok {
color: #79b757;
}
table{
table {
margin-bottom: 30px;
width: 350px;
}
+3 -3
View File
@@ -1,5 +1,5 @@
<h3>Connection Requirements</h3>
<ul>
<li><em>View</em> permission enabled in OSC Access</li>
<li>Provide passcode if necessary</li>
</ul>
<li><em>View</em> permission enabled in OSC Access</li>
<li>Provide passcode if necessary</li>
</ul>
+194 -158
View File
@@ -3,8 +3,8 @@ const fs = require('fs');
const path = require('path');
exports.config = {
defaultName: "QLab",
connectionType: "osc",
defaultName: 'QLab',
connectionType: 'osc',
heartbeatInterval: 50,
heartbeatTimeout: 2000,
mayChangePort: true,
@@ -12,31 +12,38 @@ exports.config = {
type: 'Bonjour',
bonjourName: 'qlab',
},
fields: [{
key: "passcode",
label: "Pass",
type: "textinput",
value: "",
action: function(device){
device.send('/workspaces');
}
}]
}
fields: [
{
key: 'passcode',
label: 'Pass',
type: 'textinput',
value: '',
action(device) {
device.send('/workspaces');
},
},
],
};
let lastElapsedUpdate = Date.now();
let interval = 5;
let heartbeatCount = 0;
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"]';
const cueTemplate = _.template(fs.readFileSync(path.join(__dirname, `cue.ejs`)));
const tileTemplate = _.template(fs.readFileSync(path.join(__dirname, `tile.ejs`)));
const cartTemplate = _.template(fs.readFileSync(path.join(__dirname, `cart.ejs`)));
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"]';
const cueTemplate = _.template(
fs.readFileSync(path.join(__dirname, `cue.ejs`))
);
const tileTemplate = _.template(
fs.readFileSync(path.join(__dirname, `tile.ejs`))
);
const cartTemplate = _.template(
fs.readFileSync(path.join(__dirname, `cart.ejs`))
);
exports.ready = function ready(device) {
device.send(`/version`);
@@ -49,36 +56,34 @@ exports.data = function data(_device, oscData) {
const oscAddressParts = oscData.address.split('/');
oscAddressParts.shift();
if(match(oscAddressParts, ["reply", "version"])){
if (match(oscAddressParts, ['reply', 'version'])) {
const json = JSON.parse(oscData.args[0]);
device.data.version = json.data;
this.deviceInfoUpdate(device, 'status', 'ok');
}else if(match(oscAddressParts, ["reply", "workspaces"])){
} else if (match(oscAddressParts, ['reply', 'workspaces'])) {
const json = JSON.parse(oscData.args[0]);
device.data.workspaces = {};
json.data.forEach(wksp => {
json.data.forEach((wksp) => {
device.data.workspaces[wksp.uniqueID] = {
uniqueID: wksp.uniqueID,
displayName: wksp.displayName,
cueLists: {},
cues: {}
}
device.send(`/workspace/${wksp.uniqueID}/connect`, device.fields.passcode);
cues: {},
};
device.send(
`/workspace/${wksp.uniqueID}/connect`,
device.fields.passcode
);
});
}else if(match(oscAddressParts, ["reply", "workspace", "*", "connect"])){
} else if (match(oscAddressParts, ['reply', 'workspace', '*', 'connect'])) {
device.send(`/workspace/${oscAddressParts[2]}/updates`, [
{ type: 'i', value: 1 },
]);
device.send(`/workspace/${oscAddressParts[2]}/cueLists`);
}else if(match(oscAddressParts, ["reply", "workspace", "*", "cueLists"])){
} else if (match(oscAddressParts, ['reply', 'workspace', '*', 'cueLists'])) {
this.deviceInfoUpdate(device, 'status', 'ok');
const workspace = device.data.workspaces[oscAddressParts[2]];
const json = JSON.parse(oscData.args[0]);
@@ -86,13 +91,12 @@ exports.data = function data(_device, oscData) {
workspace.cueLists = {};
workspace.cues = {};
if(json.status=="denied"){
if (json.status === 'denied') {
device.data.permission = false;
}else if(json.data){
} else if (json.data) {
device.data.permission = true;
json.data.forEach(cueList => {
json.data.forEach((cueList) => {
workspace.cueLists[cueList.uniqueID] = cueList;
addCueToWorkspace(workspace, cueList);
});
@@ -100,35 +104,51 @@ exports.data = function data(_device, oscData) {
device.draw();
setTimeout(() => {
json.data.forEach(ql => {
json.data.forEach((ql) => {
workspace.cueLists[ql.uniqueID] = ql;
getValuesForKeys(device, json.workspace_id, ql);
});
}, 0);
}
}else if(match(oscAddressParts, ["reply", "cue_id", "*", "children"]) || match(oscAddressParts, ["reply", "workspace", "*", "cue_id", "*", "children"])){
} else if (
match(oscAddressParts, ['reply', 'cue_id', '*', 'children']) ||
match(oscAddressParts, [
'reply',
'workspace',
'*',
'cue_id',
'*',
'children',
])
) {
const json = JSON.parse(oscData.args[0]);
const workspace = device.data.workspaces[json.workspace_id];
const cueID = json.address.substring(55, 91);
const cue = workspace.cues[cueID];
if(!_.isEqual(cue.cues, json.data)){
if (!_.isEqual(cue.cues, json.data)) {
workspace.cueLists[cueID].cues = json.data;
addCueToWorkspace(workspace, workspace.cueLists[cueID]);
device.draw();
getValuesForKeys(device, json.workspace_id, cue);
}
}else if(match(oscAddressParts, ["reply", "cue_id", "*", "valuesForKeys"]) || match(oscAddressParts, ["reply", "workspace", "*", "cue_id", "*", "valuesForKeys"])){
} else if (
match(oscAddressParts, ['reply', 'cue_id', '*', 'valuesForKeys']) ||
match(oscAddressParts, [
'reply',
'workspace',
'*',
'cue_id',
'*',
'valuesForKeys',
])
) {
const json = JSON.parse(oscData.args[0]);
const cueValues = json.data;
const workspace = device.data.workspaces[json.workspace_id];
let cue = workspace.cues[cueValues.uniqueID];
if(!cue){
if (!cue) {
workspace.cues[cueValues.uniqueID] = {};
cue = workspace.cues[cueValues.uniqueID];
}
@@ -144,7 +164,7 @@ exports.data = function data(_device, oscData) {
cue.flagged = cueValues.isFlagged;
cue.paused = cueValues.isPaused;
cue.type = cueValues.type;
//cue.cues = cueValues.children;
// cue.cues = cueValues.children;
cue.preWait = cueValues.preWait;
cue.postWait = cueValues.postWait;
cue.duration = cueValues.currentDuration;
@@ -160,52 +180,55 @@ exports.data = function data(_device, oscData) {
cue.postWaitElapsed = cueValues.postWaitElapsed;
// QLab 5 fix
if(cueValues.type=="Group" || cueValues.type=="Cue List"){
cue.cues = cueValues.children;
}else{
cue.cues = undefined;
if (cueValues.type === 'Group' || cueValues.type === 'Cue List') {
cue.cues = cueValues.children;
} else {
cue.cues = undefined;
}
const nestedGroupModes = [];
const nestedGroupPosition = [];
let obj = cue;
let sum = 0;
if(obj.cues){
sum+=obj.cues.length;
if (obj.cues) {
sum += obj.cues.length;
}
while(obj.parent !== "[root group of cue lists]"){
while (obj.parent !== '[root group of cue lists]') {
let pos = _.findIndex(workspace.cues[obj.parent].cues, {
uniqueID: obj.uniqueID,
});
pos = Math.abs(pos - workspace.cues[obj.parent].cues.length) - 1;
let pos = _.findIndex(workspace.cues[obj.parent].cues, {uniqueID: obj.uniqueID});
pos = Math.abs(pos - workspace.cues[obj.parent].cues.length)-1;
if(obj.cues === undefined){
if (obj.cues === undefined) {
sum += pos;
}
nestedGroupPosition.unshift(sum);
if(obj.cues){
sum+=pos;
if (obj.cues) {
sum += pos;
nestedGroupModes.unshift(obj.groupMode);
}else{
} else {
nestedGroupModes.unshift(workspace.cues[obj.parent].groupMode);
}
obj = workspace.cues[obj.parent];
obj = workspace.cues[obj.parent];
}
cue.nestedGroupModes = nestedGroupModes;
cue.nestedGroupPosition = nestedGroupPosition;
device.update("updateCueData", {'cue': cue, 'allCues': workspace.cues, 'workspace': workspace});
}else if(match(oscAddressParts, ["reply", "cue_id", "*", "preWaitElapsed"])){
device.update('updateCueData', {
cue,
allCues: workspace.cues,
workspace,
});
} else if (
match(oscAddressParts, ['reply', 'cue_id', '*', 'preWaitElapsed'])
) {
const json = JSON.parse(oscData.args[0]);
const workspace = device.data.workspaces[json.workspace_id];
const cue = workspace.cues[json.address.substring(55, 91)];
@@ -213,10 +236,14 @@ exports.data = function data(_device, oscData) {
cue.preWaitElapsed = json.data;
lastElapsedUpdate = Date.now();
device.update("updateCueData", {'cue': cue, 'allCues': workspace.cues, 'workspace': workspace});
}else if(match(oscAddressParts, ["reply", "cue_id", "*", "actionElapsed"])){
device.update('updateCueData', {
cue,
allCues: workspace.cues,
workspace,
});
} else if (
match(oscAddressParts, ['reply', 'cue_id', '*', 'actionElapsed'])
) {
const json = JSON.parse(oscData.args[0]);
const workspace = device.data.workspaces[json.workspace_id];
const cue = workspace.cues[json.address.substring(55, 91)];
@@ -224,10 +251,14 @@ exports.data = function data(_device, oscData) {
cue.actionElapsed = json.data;
lastElapsedUpdate = Date.now();
device.update("updateCueData", {'cue': cue, 'allCues': workspace.cues, 'workspace': workspace});
}else if(match(oscAddressParts, ["reply", "cue_id", "*", "postWaitElapsed"])){
device.update('updateCueData', {
cue,
allCues: workspace.cues,
workspace,
});
} else if (
match(oscAddressParts, ['reply', 'cue_id', '*', 'postWaitElapsed'])
) {
const json = JSON.parse(oscData.args[0]);
const workspace = device.data.workspaces[json.workspace_id];
const cue = workspace.cues[json.address.substring(55, 91)];
@@ -235,158 +266,163 @@ exports.data = function data(_device, oscData) {
cue.postWaitElapsed = json.data;
lastElapsedUpdate = Date.now();
device.update("updateCueData", {'cue': cue, 'allCues': workspace.cues, 'workspace': workspace});
}else if(match(oscAddressParts, ["update", "workspace", "*", "cue_id", "*"])){
device.update('updateCueData', {
cue,
allCues: workspace.cues,
workspace,
});
} else if (
match(oscAddressParts, ['update', 'workspace', '*', 'cue_id', '*'])
) {
const workspace = device.data.workspaces[oscAddressParts[2]];
if(workspace){
if (workspace) {
const cueLists = Object.keys(workspace.cueLists);
const cueID = oscAddressParts[4];
if(cueID !== "[root group of cue lists"){
if(cueLists.includes(cueID)){
device.send(`/workspace/${workspace.uniqueID}/cue_id/${cueID}/children`);
if (cueID !== '[root group of cue lists') {
if (cueLists.includes(cueID)) {
device.send(
`/workspace/${workspace.uniqueID}/cue_id/${cueID}/children`
);
}
device.send(`/workspace/${oscAddressParts[2]}/cue_id/${cueID}/valuesForKeys`, [
{type: 's', value: valuesForKeysString}
]);
device.send(
`/workspace/${oscAddressParts[2]}/cue_id/${cueID}/valuesForKeys`,
[{ type: 's', value: valuesForKeysString }]
);
}
}
}else if(match(oscAddressParts, ["update", "workspace", "*"])){
} else if (match(oscAddressParts, ['update', 'workspace', '*'])) {
// occurs when cue lists are reordered or a list is deleted
device.send(`/workspace/${oscAddressParts[2]}/cueLists`);
}else if(match(oscAddressParts, ["update", "workspace", "*", "dashboard"])){
} else if (
match(oscAddressParts, ['update', 'workspace', '*', 'dashboard'])
) {
// this workspace might be new, let's check
if(device.data.workspaces[oscAddressParts[2]] === undefined){
console.log("new workspace!");
if (device.data.workspaces[oscAddressParts[2]] === undefined) {
console.log('new workspace!');
device.send('/workspaces');
}
}else if(match(oscAddressParts, ["update", "workspace", "*", "cueList", "*", "playbackPosition"])){
} else if (
match(oscAddressParts, [
'update',
'workspace',
'*',
'cueList',
'*',
'playbackPosition',
])
) {
const workspace = device.data.workspaces[oscAddressParts[2]];
if(workspace){
if (workspace) {
const cue = workspace.cues[oscData.args[0]];
if(cue){
workspace.playbackPosition = oscData.args[0] ? cue.uniqueID : "";
device.update("updatePlaybackPosition", {'cue': cue});
if (cue) {
workspace.playbackPosition = oscData.args[0] ? cue.uniqueID : '';
device.update('updatePlaybackPosition', { cue });
}
}
}else if(match(oscAddressParts, ["update", "workspace", "*", "disconnect"])){
} else if (
match(oscAddressParts, ['update', 'workspace', '*', 'disconnect'])
) {
delete device.data.workspaces[oscAddressParts[2]];
device.draw();
}else{
} else {
// console.log(address)
}
};
exports.update = function update(device, doc, updateType, data){
if(updateType === "updateCueData"){
exports.update = function update(device, doc, updateType, data) {
if (updateType === 'updateCueData') {
const $elem = doc.getElementById(data.cue.uniqueID);
if($elem){
if(data.cue.type === "Cue List"){
if ($elem) {
if (data.cue.type === 'Cue List') {
$elem.outerHTML = `<h3>${data.workspace.displayName} &mdash; ${data.cue.name}</h3>`;
}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.type === 'Cart') {
$elem.outerHTML = cartTemplate({
tileTemplate,
cueList: data.cue,
allCues: data.workspace.cues,
});
} else if (data.cue.cartPosition && data.cue.cartPosition[0] !== 0) {
// checking that the parent cue is a cart cue
const parentCue = data.workspace.cues[data.cue.parent];
if(parentCue && parentCue.type === "Cart"){
if (parentCue && parentCue.type === 'Cart') {
$elem.outerHTML = tileTemplate(data);
}else{
} else {
$elem.outerHTML = cueTemplate(data);
}
}else{
}
} else {
$elem.outerHTML = cueTemplate(data);
}
}
}else if(updateType === "updatePlaybackPosition"){
Array.from(doc.getElementsByClassName("playback-position")).forEach(
($elem, index, array) => {
$elem.classList.remove("playback-position");
});
} else if (updateType === 'updatePlaybackPosition') {
Array.from(doc.getElementsByClassName('playback-position')).forEach(
($elem, index, array) => {
$elem.classList.remove('playback-position');
}
);
const $elem = doc.getElementById(data.cue.uniqueID);
$elem.classList.add("playback-position");
$elem.scrollIntoView({behavior: "smooth", block: "center"});
$elem.classList.add('playback-position');
$elem.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
}
};
function addCueToWorkspace(_workspace, cue){
function addCueToWorkspace(_workspace, cue) {
const workspace = _workspace;
workspace.cues[cue.uniqueID] = cue;
workspace.cues[cue.uniqueID].nestedGroupModes = [];
workspace.cues[cue.uniqueID].nestedGroupPosition = [];
if(cue.cues){
if (cue.cues) {
// this cue has children so add them as well
cue.cues.forEach(childCue => {
cue.cues.forEach((childCue) => {
addCueToWorkspace(workspace, childCue);
});
}
}
function getValuesForKeys(device, workspaceID, cue){
device.send(`/workspace/${workspaceID}/cue_id/${cue.uniqueID}/valuesForKeys`, [
{type: 's', value: valuesForKeysString}
]);
if(cue.cues){
cue.cues.forEach(childCue => {
function getValuesForKeys(device, workspaceID, cue) {
device.send(
`/workspace/${workspaceID}/cue_id/${cue.uniqueID}/valuesForKeys`,
[{ type: 's', value: valuesForKeysString }]
);
if (cue.cues) {
cue.cues.forEach((childCue) => {
getValuesForKeys(device, workspaceID, childCue);
});
}
}
function match(testArray, patternArray){
function match(testArray, patternArray) {
let out = true;
if(testArray.length !== patternArray.length){
if (testArray.length !== patternArray.length) {
return false;
}
patternArray.forEach((patternPart, i)=> {
if(testArray[i] !== patternPart && patternPart !== "*"){
patternArray.forEach((patternPart, i) => {
if (testArray[i] !== patternPart && patternPart !== '*') {
out = false;
}
});
return out;
}
exports.heartbeat = function heartbeat(device) {
heartbeatCount++;
if(Date.now() - lastElapsedUpdate > 300){
if (Date.now() - lastElapsedUpdate > 300) {
interval = 24;
}else{
} else {
interval = 1;
}
if(heartbeatCount % interval === 0){
if (heartbeatCount % interval === 0) {
device.send(`/cue_id/active/preWaitElapsed`);
device.send(`/cue_id/active/actionElapsed`);
device.send(`/cue_id/active/postWaitElapsed`);
}
};
};
+1 -1
View File
@@ -155,7 +155,7 @@ tr.playback-position .q-gray-text {
border-color: #925fc0;
}
.gMode-6 {
border-color: #D05B15;
border-color: #d05b15;
}
.gMode-,
.gMode-0 {
+1 -1
View File
@@ -1 +1 @@
<p><em>sACN</em> requires no configuration.</p>
<p><em>sACN</em> requires no configuration.</p>
+42 -50
View File
@@ -1,44 +1,40 @@
const _ = require('lodash');
exports.config = {
defaultName: "sACN",
connectionType: "multicast",
defaultPort: 5568,
defaultName: 'sACN',
connectionType: 'multicast',
heartbeatInterval: 5000,
defaultPort: 5568,
mayChangePort: false,
searchOptions: {
type: "multicast",
type: 'multicast',
address: getMulticastGroup(1),
port: 5568,
validateResponse (msg, info) {
return msg.toString('utf8', 4, 13) === "ASC-E1.17";
}
}
}
validateResponse(msg, info) {
return msg.toString('utf8', 4, 13) === 'ASC-E1.17';
},
},
};
exports.ready = function ready(device) {
const d = device;
d.data.universes = {};
d.data.source = "Unknown Source";
d.data.source = 'Unknown Source';
d.data.orderedUniverses = [];
// device.draw();
for(let i = 1; i <= 16; i++){
for (let i = 1; i <= 16; i++) {
d.connection.addMembership(getMulticastGroup(i));
}
};
exports.data = function data(_device, buf) {
const universeIndex = buf.readUInt16BE(113);
const device = _device;
let universe = device.data.universes[universeIndex];
if(!universe){
if (!universe) {
device.data.universes[universeIndex] = {};
universe = device.data.universes[universeIndex];
}
@@ -48,7 +44,7 @@ exports.data = function data(_device, buf) {
universe.cid = buf.toString('hex', 22, 38);
universe.slots = buf.slice(126);
if(buf.readUInt8(125) !== 0){
if (buf.readUInt8(125) !== 0) {
universe.startCode = buf.readUInt8(125);
}
@@ -56,74 +52,70 @@ exports.data = function data(_device, buf) {
device.displayName = `${device.data.source} sACN`;
device.data.ip = device.addresses[0];
if(!_.includes(device.data.orderedUniverses, universeIndex)){
if (!_.includes(device.data.orderedUniverses, universeIndex)) {
device.data.orderedUniverses.push(universeIndex);
device.data.orderedUniverses.sort();
universe.slotElems = [];
universe.slotElemsSet = false;
device.draw();
device.update("elementCache")
device.update('elementCache');
}
device.update("universeData", {
device.update('universeData', {
universeIndex,
universe,
startCode: universe.startCode
startCode: universe.startCode,
});
};
exports.heartbeat = function heartbeat(device) {
};
exports.heartbeat = function heartbeat(device) {};
let lastUpdate = Date.now();
exports.update = function update(_device, doc, updateType, updateData){
exports.update = function update(_device, doc, updateType, updateData) {
const device = _device;
const data = updateData;
if(updateType === "universeData" && data.universe){
if(Date.now() - lastUpdate > 1000){
if (updateType === 'universeData' && data.universe) {
if (Date.now() - lastUpdate > 1000) {
lastUpdate = Date.now();
device.update("elementCache")
device.update('elementCache');
}
const $elem = doc.getElementById(`universe-${data.universeIndex}`);
if($elem && data.universe.slotElemsSet){
if(data.universe.priority > 0){
for(let i = 0; i < 512; i++){
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.universeIndex}-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"
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{
} else {
device.draw();
device.update("elementCache")
device.update('elementCache');
}
}else if(updateType === "elementCache"){
device.data.orderedUniverses.forEach(universeIndex => {
for(let i = 0; i < 512; i++){
device.data.universes[universeIndex].slotElems[i] = doc.getElementById(`${universeIndex}-${i}`);
} else if (updateType === 'elementCache') {
device.data.orderedUniverses.forEach((universeIndex) => {
for (let i = 0; i < 512; i++) {
device.data.universes[universeIndex].slotElems[i] = doc.getElementById(
`${universeIndex}-${i}`
);
}
device.data.universes[universeIndex].slotElemsSet = true;
});
}
}
};
// From https://github.com/hhromic/e131-node/blob/master/lib/e131.js
function getMulticastGroup(universe) {
@@ -131,4 +123,4 @@ function getMulticastGroup(universe) {
throw new RangeError('universe should be in the range [1-63999]');
}
return `239.255.${universe >> 8}.${universe & 0xff}`;
}
}
+8 -9
View File
@@ -1,6 +1,6 @@
exports.config = {
defaultName: "Dataton Watchout",
connectionType: "TCPsocket",
defaultName: 'Dataton Watchout',
connectionType: 'TCPsocket',
heartbeatInterval: 500,
defaultPort: 3040,
mayChangePort: false,
@@ -8,11 +8,11 @@ exports.config = {
type: 'TCPport',
searchBuffer: Buffer.from('authenticate 1\n', 'ascii'),
testPort: 3040,
validateResponse (msg, info) {
validateResponse(msg, info) {
return msg.toString().substring(0, 5) === 'Ready';
}
}
}
},
},
};
exports.ready = function ready(device) {
device.send('authenticate 1\n');
@@ -24,12 +24,11 @@ exports.data = function data(_device, _message) {
if (message.substring(0, 5) === 'Ready') {
device.send('getStatus\n');
}else if (message.substring(0, 5) === 'Reply') {
} else if (message.substring(0, 5) === 'Reply') {
const arr = message.split(' ');
device.data.showName = '';
let i = 0;
while (arr[i][arr[i].length - 1] !== '"') {
i++;
+5 -5
View File
@@ -1,6 +1,6 @@
exports.config = {
defaultName: "X32 Mixer",
connectionType: "osc-udp",
defaultName: 'X32 Mixer',
connectionType: 'osc-udp',
heartbeatInterval: 9000,
defaultPort: 10023,
mayChangePort: false,
@@ -11,9 +11,9 @@ exports.config = {
listenPort: 0,
validateResponse(msg, info) {
return msg.toString().indexOf('/xinfo') === 0;
}
}
}
},
},
};
exports.ready = function ready(device) {
const d = device;
+5 -5
View File
@@ -1,6 +1,6 @@
exports.config = {
defaultName: "X Air Mixer",
connectionType: "UDPsocket",
defaultName: 'X Air Mixer',
connectionType: 'UDPsocket',
heartbeatInterval: 10000,
defaultPort: 10024,
mayChangePort: false,
@@ -11,9 +11,9 @@ exports.config = {
listenPort: 0,
validateResponse(msg, info) {
return msg.toString().indexOf('/xinfo') === 0;
}
}
}
},
},
};
exports.ready = function ready(device) {
const d = device;
+1 -1
View File
@@ -128,7 +128,7 @@ input[type='range']::-webkit-slider-runnable-track {
border-radius: 4px;
}
.infin{
.infin {
font-size: 20px;
vertical-align: middle;
}
+60 -54
View File
@@ -16,13 +16,13 @@ window.init = function init() {
ipcRenderer.send('enableSearchAll');
// load autoUpdate setting from storage and send to main process
const autoUpdate = JSON.parse(localStorage.getItem('autoUpdate'))
if(autoUpdate !== undefined && autoUpdate !== null){
if(autoUpdate){
const autoUpdate = JSON.parse(localStorage.getItem('autoUpdate'));
if (autoUpdate !== undefined && autoUpdate !== null) {
if (autoUpdate) {
ipcRenderer.send('checkForUpdates');
}
// send message so main process knows the state of autoUpdate
ipcRenderer.send('setAutoUpdate', autoUpdate)
ipcRenderer.send('setAutoUpdate', autoUpdate);
}
PLUGINS.init(() => {
@@ -35,31 +35,39 @@ window.init = function init() {
SEARCH.searchAll();
};
document.getElementById('device-settings-table').onclick = function settingsClick(e) {
e.stopPropagation();
};
document.getElementById('device-settings-name').onchange = function nameChange(e) {
e.stopPropagation();
DEVICE.changeActiveName(e.target.value);
};
document.getElementById('device-settings-plugin-dropdown').onchange = function dropdownChange(e) {
e.stopPropagation();
DEVICE.changeActiveType(e.target.value);
};
document.getElementById('device-settings-table').onclick =
function settingsClick(e) {
e.stopPropagation();
};
document.getElementById('device-settings-ip').onchange = function ipChange(e) {
document.getElementById('device-settings-name').onchange =
function nameChange(e) {
e.stopPropagation();
DEVICE.changeActiveName(e.target.value);
};
document.getElementById('device-settings-plugin-dropdown').onchange =
function dropdownChange(e) {
e.stopPropagation();
DEVICE.changeActiveType(e.target.value);
};
document.getElementById('device-settings-ip').onchange = function ipChange(
e
) {
e.stopPropagation();
DEVICE.changeActiveIP(e.target.value);
};
document.getElementById('device-settings-port').onchange = function portChange(e) {
e.stopPropagation();
DEVICE.changeActivePort(e.target.value);
};
document.getElementById('device-settings-port').onchange =
function portChange(e) {
e.stopPropagation();
DEVICE.changeActivePort(e.target.value);
};
document.getElementById('device-settings-pin').onchange = function pinChange(e) {
document.getElementById('device-settings-pin').onchange = function pinChange(
e
) {
e.stopPropagation();
if (e.target.checked) {
VIEW.pinActiveDevice();
@@ -68,7 +76,6 @@ window.init = function init() {
}
};
document.getElementById('save-slot-1').onclick = function slot1click(e) {
e.stopPropagation();
SAVESLOTS.loadSlot(1);
@@ -84,10 +91,11 @@ window.init = function init() {
SAVESLOTS.loadSlot(3);
};
document.getElementById('refresh-device-button').onclick = function refreshClick(e) {
e.stopPropagation();
DEVICE.refreshActive();
};
document.getElementById('refresh-device-button').onclick =
function refreshClick(e) {
e.stopPropagation();
DEVICE.refreshActive();
};
document.getElementById('device-list').onclick = function listClick(e) {
e.stopPropagation();
@@ -97,26 +105,25 @@ window.init = function init() {
}
};
document.getElementById('add-device-button').onchange = function addDeviceClick(e) {
DEVICE.registerDevice({
type: e.target.value,
defaultName: 'New Device',
port: undefined,
addresses: [],
});
e.target.selectedIndex = 0;
document.getElementById('add-device-button').onchange =
function addDeviceClick(e) {
DEVICE.registerDevice({
type: e.target.value,
defaultName: 'New Device',
port: undefined,
addresses: [],
});
e.target.selectedIndex = 0;
SAVESLOTS.saveAll();
};
SAVESLOTS.saveAll();
};
document.onkeyup = function keyUp(e) {
if(e.key === 'ArrowUp'){
if (e.key === 'ArrowUp') {
VIEW.selectPreviousDevice();
}else if(e.key === 'ArrowDown'){
} else if (e.key === 'ArrowDown') {
VIEW.selectNextDevice();
}else if(e.key === 'Tab'){
} else if (e.key === 'Tab') {
if (
document.activeElement.tagName !== 'INPUT' &&
document.activeElement.tagName !== 'SELECT'
@@ -124,10 +131,11 @@ window.init = function init() {
document.getElementById('device-settings-name').select();
}
}
};
document.getElementById('device-list-col').onclick = function deviceListClick(e) {
document.getElementById('device-list-col').onclick = function deviceListClick(
e
) {
try {
document
.querySelector('#device-list .active-device')
@@ -170,22 +178,20 @@ ipcRenderer.on('resetViews', (event, message) => {
});
ipcRenderer.on('loadSlot', (event, slot) => {
if(slot){
if (slot) {
SAVESLOTS.loadSlot(slot);
}
});
// message from main process to set autoUpdate state
ipcRenderer.on('setAutoUpdate',(event,autoUpdate)=>{
localStorage.setItem('autoUpdate',autoUpdate);
if(autoUpdate){
ipcRenderer.on('setAutoUpdate', (event, autoUpdate) => {
localStorage.setItem('autoUpdate', autoUpdate);
if (autoUpdate) {
ipcRenderer.send('checkForUpdates');
}
// message to main process that we have updated the state
ipcRenderer.send('setAutoUpdate',autoUpdate);
})
ipcRenderer.send('setAutoUpdate', autoUpdate);
});
function switchClass(element, className) {
try {
@@ -195,4 +201,4 @@ function switchClass(element, className) {
}
element.classList.add(className);
}
window.switchClass = switchClass;
window.switchClass = switchClass;
+2 -2
View File
@@ -69,7 +69,7 @@ function registerDevice(newDevice) {
devices[id].plugin = PLUGINS.all[newDevice.type];
if (
Object.keys(devices[id].fields).length == 0 &&
Object.keys(devices[id].fields).length === 0 &&
PLUGINS.all[newDevice.type].config.fields
) {
PLUGINS.all[newDevice.type].config.fields.forEach((field) => {
@@ -206,7 +206,7 @@ function initDeviceConnection(id) {
device.send = (data) => {};
}
//device.plugin = plugins[type];
// device.plugin = plugins[type];
return true;
}
+4 -4
View File
@@ -118,13 +118,13 @@ a {
width: 210px;
pointer-events: none;
}
#device-inspector{
#device-inspector {
position: absolute;
bottom: 0px;
width: 100%;
}
#device-tools {
/* position: absolute;
/* position: absolute;
bottom: 210px;
left: 0px;*/
width: 100%;
@@ -265,7 +265,7 @@ input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input:disabled{
input:disabled {
color: gray;
cursor: not-allowed;
}
@@ -341,6 +341,6 @@ select.button:focus {
}
/* only allow select on input fields */
body :not(input):not(select):not(textarea) {
body :not(input):not(select):not(textarea) {
user-select: none;
}
+1 -1
View File
@@ -1 +1 @@
window.init();
window.init();
+28 -32
View File
@@ -10,20 +10,20 @@ const allPlugins = {};
module.exports.all = allPlugins;
module.exports.init = function init(callback) {
let pluginDirectoryPath = path.normalize(path.join(__dirname, `../plugins`));
const pluginDirectoryPath = path.normalize(path.join(__dirname, `../plugins`));
console.log(`Loading plugin files... ${pluginDirectoryPath}`);
fs.readdir(pluginDirectoryPath, (err, files) => {
files.forEach((plugin)=>{
files.forEach((plugin) => {
if (plugin[0] !== '.') {
console.log(`${plugin} started`);
// eslint-disable-next-line import/no-dynamic-require
allPlugins[plugin] = require(path.join(pluginDirectoryPath, `/${plugin}/main.js`));
allPlugins[plugin] = require(path.join(
pluginDirectoryPath,
`/${plugin}/main.js`
));
const p = allPlugins[plugin];
@@ -35,50 +35,46 @@ module.exports.init = function init(callback) {
};
p.template = _.template(
fs.readFileSync(path.join(pluginDirectoryPath, `/${plugin}/template.ejs`),
fs.readFileSync(
path.join(pluginDirectoryPath, `/${plugin}/template.ejs`),
'utf8'
)
);
p.info = _.template(
fs.readFileSync(path.join(pluginDirectoryPath, `/${plugin}/info.html`),
fs.readFileSync(
path.join(pluginDirectoryPath, `/${plugin}/info.html`),
'utf8'
)
);
// if (p.heartbeatTimeout === undefined || p.heartbeatTimeout < 50) {
if (p.config.heartbeatTimeout) {
p.heartbeatTimeout = p.config.heartbeatInterval * 1.5;
} else {
p.heartbeatTimeout = 10000;
}
// }
//if (p.heartbeatTimeout === undefined || p.heartbeatTimeout < 50) {
if(p.config.heartbeatTimeout){
p.heartbeatTimeout = p.config.heartbeatInterval * 1.5;
}else{
p.heartbeatTimeout = 10000;
}
//}
if(p.config.heartbeatInterval){
p.heartbeatInterval = Math.max(50, p.config.heartbeatInterval);
}else{
p.heartbeatInterval = 5000;
}
// p.fields = {};
// if(p.config.fields){
// p.config.fields.forEach(field => {
// p.fields[field.key] = field.value;
// });
// }
if (p.config.heartbeatInterval) {
p.heartbeatInterval = Math.max(50, p.config.heartbeatInterval);
} else {
p.heartbeatInterval = 5000;
}
// p.fields = {};
// if(p.config.fields){
// p.config.fields.forEach(field => {
// p.fields[field.key] = field.value;
// });
// }
// if (p.heartbeatInterval === undefined || p.heartbeatInterval < 50) {
// p.heartbeatInterval = 5000;
// }
}
});
callback();
});
};
+5 -13
View File
@@ -19,7 +19,7 @@ function loadSlot(slotIndex) {
VIEW.toggleSlotButtons(slotIndex);
activeSlot = slotIndex;
Object.keys(DEVICE.all).forEach((d)=>{
Object.keys(DEVICE.all).forEach((d) => {
DEVICE.changePinIndex(DEVICE.all[d], false);
});
VIEW.resetPinned();
@@ -33,7 +33,6 @@ function loadSlot(slotIndex) {
if (device.id === savedDevice.id) {
VIEW.pinDevice(device);
VIEW.switchDevice(device.id);
} else if (
device.addresses[0] === savedDevice.addresses[0] &&
device.type === savedDevice.type &&
@@ -43,12 +42,10 @@ function loadSlot(slotIndex) {
VIEW.switchDevice(device.id);
}
});
});
};
}
module.exports.loadSlot = loadSlot;
module.exports.loadDevices = function loadDevices() {
console.log(`Loading ${savedDevices.length} saved devices...`);
@@ -60,12 +57,11 @@ module.exports.loadDevices = function loadDevices() {
port: savedDevices[i].port,
addresses: savedDevices[i].addresses,
id: savedDevices[i].id,
fields: savedDevices[i].fields
fields: savedDevices[i].fields,
});
}
};
module.exports.saveAll = function saveAll() {
console.log('Saving...');
const currentPins = VIEW.getPinnedDevices();
@@ -75,7 +71,7 @@ module.exports.saveAll = function saveAll() {
savedSlots[activeSlot][i] = {
addresses: currentPins[i].addresses,
type: currentPins[i].type,
id: currentPins[i].id
id: currentPins[i].id,
};
}
localStorage.setItem('savedSlots', JSON.stringify(savedSlots));
@@ -94,15 +90,13 @@ module.exports.saveAll = function saveAll() {
defaultName: device.defaultName,
port: device.port,
id: device.id,
fields: device.fields
fields: device.fields,
};
i++;
});
localStorage.setItem('savedDevices', JSON.stringify(savedDevices));
};
module.exports.deleteFromSlots = function deleteFromSlots(device) {
for (let i = 1; i <= 3; i++) {
console.log(savedSlots);
@@ -114,12 +108,10 @@ module.exports.deleteFromSlots = function deleteFromSlots(device) {
}
};
module.exports.reloadActiveSlot = function reloadActiveSlot() {
loadSlot(activeSlot);
};
module.exports.resetSlots = function resetSlots() {
localStorage.clear();
};
+32 -38
View File
@@ -15,13 +15,17 @@ let allServers = false;
function getServers() {
const interfaces = os.networkInterfaces();
const result = [];
Object.keys(interfaces).forEach((key) => {
const addresses = interfaces[key];
for (let i = addresses.length; i--; ) {
const address = addresses[i];
if (address.family === 'IPv4' && !address.internal && address.address.substring(0, 3)!="169") {
if (
address.family === 'IPv4' &&
!address.internal &&
address.address.substring(0, 3) !== '169'
) {
const subnet = ip.subnet(address.address, address.netmask);
let current = ip.toLong(subnet.firstAddress);
const last = ip.toLong(subnet.lastAddress) - 1;
@@ -31,7 +35,6 @@ function getServers() {
}
});
return result;
}
const searchSockets = [];
@@ -43,9 +46,9 @@ function searchAll() {
ipcRenderer.send('disableSearchAll', '');
document.getElementById('search-button').style.opacity = 0.2;
// Removed this block to fix #21
// Removed this block to fix #21
// "After adding devices via search, searching again leaves all devices stuck in reload state"
//
//
// Object.keys(DEVICE.all).forEach((i) => {
// DEVICE.infoUpdate(DEVICE.all[i], 'status', 'refresh');
// });
@@ -63,26 +66,21 @@ function searchAll() {
Object.keys(PLUGINS.all).forEach((p) => {
const plugin = PLUGINS.all[p];
try {
const t = plugin.config.searchOptions.type;
if(t === 'TCPport'){
if (t === 'TCPport') {
if (TCPFlag) {
searchTCP(p, plugin.config);
}
}else if(t === 'Bonjour'){
} else if (t === 'Bonjour') {
searchBonjour(p, plugin.config);
}else if(t === 'UDPsocket'){
} else if (t === 'UDPsocket') {
searchUDP(p, plugin.config);
}else if(t === 'multicast'){
} else if (t === 'multicast') {
searchMulticast(p, plugin.config);
}
} catch (err) {
console.error(`Unable to search for plugin ${p}`);
}
@@ -102,14 +100,11 @@ function searchAll() {
ipcRenderer.send('enableSearchAll', '');
}, 10000);
};
}
module.exports.searchAll = searchAll;
function searchBonjour(pluginType, plugin) {
bonjour.find({ type: plugin.searchOptions.bonjourName }, (e) => {
const validAddresses = [];
e.addresses.forEach((address) => {
if (address.indexOf(':') === -1) {
@@ -124,20 +119,22 @@ function searchBonjour(pluginType, plugin) {
addresses: validAddresses,
});
});
};
}
function searchTCP(pluginType, plugin) {
for (let i = 0; i < allServers.length; i++) {
TCPtest(allServers[i], pluginType, plugin);
}
};
}
function TCPtest(ipAddr, pluginType, plugin) {
const client = net.createConnection(plugin.searchOptions.testPort, ipAddr, () => {
client.write(plugin.searchOptions.searchBuffer);
});
const client = net.createConnection(
plugin.searchOptions.testPort,
ipAddr,
() => {
client.write(plugin.searchOptions.searchBuffer);
}
);
client.on('data', (data) => {
if (plugin.searchOptions.validateResponse(data)) {
DEVICE.registerDevice({
@@ -152,14 +149,12 @@ function TCPtest(ipAddr, pluginType, plugin) {
client.on('error', (err) => {
// no device here
});
};
}
function searchUDP(pluginType, plugin) {
const i = searchSockets.push(dgram.createSocket('udp4')) - 1;
searchSockets[i].bind(plugin.searchOptions.listenPort, () => {
// searchSockets[i].send(
// plugin.searchOptions.searchBuffer,
// plugin.searchOptions.devicePort,
@@ -205,16 +200,15 @@ function searchUDP(pluginType, plugin) {
searchSockets[i].on('listening', () => {
searchSockets[i].setBroadcast(true);
searchSockets[i].send(
plugin.searchOptions.searchBuffer,
plugin.searchOptions.devicePort,
'255.255.255.255',
(err) => {
// console.log(err)
}
);
plugin.searchOptions.searchBuffer,
plugin.searchOptions.devicePort,
'255.255.255.255',
(err) => {
// console.log(err)
}
);
});
};
}
function searchMulticast(pluginType, plugin) {
const socket = dgram.createSocket('udp4');
+72 -69
View File
@@ -12,9 +12,7 @@ module.exports.init = function init() {
populatePluginLists();
};
function drawDeviceFrame(id) {
const $deviceDrawArea = document.getElementById(`device-${id}-draw-area`);
const $devicePinned = document.getElementById(`device-${id}-pinned`);
@@ -30,7 +28,8 @@ function drawDeviceFrame(id) {
// scrollbar styles are inline to prevent the styles flickering in
str += '<style>';
str += '::-webkit-scrollbar {background-color: black;width: 12px;}';
str += '::-webkit-scrollbar-track, ::-webkit-scrollbar-corner {background-color: #2b2b2b;}';
str +=
'::-webkit-scrollbar-track, ::-webkit-scrollbar-corner {background-color: #2b2b2b;}';
str +=
'::-webkit-scrollbar-thumb {background-color: #6b6b6b;border-radius: 16px;border: 3px solid #2b2b2b;}';
str += '::-webkit-scrollbar-button {display:none;}';
@@ -51,7 +50,6 @@ function drawDeviceFrame(id) {
$deviceDrawArea.contentWindow.document.write(str);
$deviceDrawArea.contentWindow.document.close();
if (d.pinIndex) {
$devicePinned.style.display = 'block';
} else {
@@ -59,62 +57,60 @@ function drawDeviceFrame(id) {
}
return true;
}
};
function generateBodyHTML(d){
let str = "";
function generateBodyHTML(d) {
let str = '';
if (d.status === 'ok') {
try {
str += PLUGINS.all[d.type].template({
data: d.data,
listName: (d.displayName || d.defaultName)
listName: d.displayName || d.defaultName,
});
} catch (err) {
console.log(err);
str += '<h3>Plugin Template Error</h3>';
}
} else {
str += `<header><h1>${(d.displayName || d.defaultName)}</h1></header>`;
str += `<header><h1>${d.displayName || d.defaultName}</h1></header>`;
str += "<div class='not-responding'>";
str += `<h2><em>${d.type}</em> is not responding to requests for data.</h2>`;
str += `<h3>IP <em>${d.addresses[0]}</em></h3>`;
str += `<h3>Port <em>${d.port}</em></h3>`;
str += '<hr></div>';
str += `<div class="device-info">${PLUGINS.all[d.type].info()}<div>`;
}
return str;
}
module.exports.draw = function draw(device) {
const d = device;
const $deviceDrawArea = document.getElementById(`device-${d.id}-draw-area`);
if($deviceDrawArea){
const scriptEl = $deviceDrawArea.contentWindow.document.createRange().createContextualFragment(generateBodyHTML(d));
if ($deviceDrawArea) {
const scriptEl = $deviceDrawArea.contentWindow.document
.createRange()
.createContextualFragment(generateBodyHTML(d));
$deviceDrawArea.contentWindow.document.body.replaceChildren(scriptEl);
}else{
} else {
drawDeviceFrame(d.id);
}
d.drawn = true;
};
module.exports.update = function update(device, type, data){
module.exports.update = function update(device, type, data) {
const doc = document.getElementById(`device-${device.id}-draw-area`);
if(doc){
PLUGINS.all[device.type].update(device, doc.contentWindow.document, type, data);
if (doc) {
PLUGINS.all[device.type].update(
device,
doc.contentWindow.document,
type,
data
);
}
}
};
module.exports.addDeviceToList = function addDeviceToList(device) {
const d = device;
@@ -135,21 +131,20 @@ module.exports.addDeviceToList = function addDeviceToList(device) {
if (elem == null) {
document
.getElementById('device-list')
.insertAdjacentHTML('beforeend', `<a class='device' id='${d.id}'>${html}</a>`);
.insertAdjacentHTML(
'beforeend',
`<a class='device' id='${d.id}'>${html}</a>`
);
} else {
elem.innerHTML = html;
}
};
module.exports.removeDeviceFromList = function removeDeviceFromList(device) {
const d = device;
document.getElementById(d.id).remove();
};
function switchDevice(id) {
if (activeDevice && activeDevice.pinIndex === false) {
document.getElementById(`device-${activeDevice.id}`).remove();
@@ -165,7 +160,9 @@ function switchDevice(id) {
cols--;
}
document.getElementById('all-devices').style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
document.getElementById(
'all-devices'
).style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
if (id === undefined) {
// document.getElementById('refresh-device-button').style.opacity = 0.2;
@@ -182,47 +179,59 @@ function switchDevice(id) {
if (!$deviceWrapper) {
const html = `<div class="col device-wrapper" id="device-${i}"><img id="device-${i}-pinned" class="device-pin" src="src/img/outline_push_pin_white_18dp.png"><iframe id="device-${i}-draw-area" class="draw-area"></iframe></div>`;
document.getElementById('all-devices').insertAdjacentHTML('afterbegin', html);
document
.getElementById('all-devices')
.insertAdjacentHTML('afterbegin', html);
$deviceWrapper = document.getElementById(`device-${i}`);
}
window.switchClass(document.getElementById(id), 'active-device');
drawDeviceFrame(id);
window.switchClass(document.getElementById(`device-${id}`), 'active-device-outline');
window.switchClass(
document.getElementById(`device-${id}`),
'active-device-outline'
);
document.getElementById('device-settings-table').style.display = 'block';
document.getElementById('device-settings-plugin-dropdown').value = activeDevice.type;
document.getElementById('device-settings-name').value = activeDevice.displayName || activeDevice.defaultName || '';
document.getElementById('device-settings-ip').value = activeDevice.addresses[0] || '';
document.getElementById('device-settings-port').value = activeDevice.port || '';
document.getElementById('device-settings-pin').checked = activeDevice.pinIndex;
document.getElementById('device-settings-plugin-dropdown').value =
activeDevice.type;
document.getElementById('device-settings-name').value =
activeDevice.displayName || activeDevice.defaultName || '';
document.getElementById('device-settings-ip').value =
activeDevice.addresses[0] || '';
document.getElementById('device-settings-port').value =
activeDevice.port || '';
document.getElementById('device-settings-pin').checked =
activeDevice.pinIndex;
if(activeDevice.plugin.config.mayChangePort){
if (activeDevice.plugin.config.mayChangePort) {
document.getElementById('device-settings-port').disabled = false;
}else{
} else {
document.getElementById('device-settings-port').disabled = true;
}
document.getElementById('device-settings-fields').innerHTML = "";
document.getElementById('device-settings-fields').innerHTML = '';
if(activeDevice.plugin.config.fields){
let fields = activeDevice.plugin.config.fields;
if (activeDevice.plugin.config.fields) {
const fields = activeDevice.plugin.config.fields;
fields.forEach(field => {
let $elem = document.createElement("input");
$elem.type = "text";
$elem.value = activeDevice.fields[field.key];// || field.value;
fields.forEach((field) => {
const $elem = document.createElement('input');
$elem.type = 'text';
$elem.value = activeDevice.fields[field.key]; // || field.value;
$elem.name = field.key;
$elem.onchange = function(e){
$elem.onchange = function onchange(e) {
activeDevice.fields[field.key] = $elem.value;
field.action(activeDevice);
saveAll();
}
};
if(field.type=="textinput"){
let rowHTML =`<tr><th>${field.label}:</th><td colspan="3" id="${field.key}"></td></tr>`;
document.getElementById('device-settings-fields').insertAdjacentHTML("beforeend", rowHTML);
if (field.type === 'textinput') {
const rowHTML = `<tr><th>${field.label}:</th><td colspan="3" id="${field.key}"></td></tr>`;
document
.getElementById('device-settings-fields')
.insertAdjacentHTML('beforeend', rowHTML);
document.getElementById(field.key).appendChild($elem);
}
});
@@ -230,15 +239,13 @@ function switchDevice(id) {
ipcRenderer.send('enableDeviceDropdown', '');
ipcRenderer.send('setDevicePin', !DEVICE.all[id].pinIndex === false);
};
}
module.exports.switchDevice = switchDevice;
module.exports.getActiveDevice = function getActiveDevice() {
return activeDevice;
};
module.exports.pinActiveDevice = function pinActiveDevice() {
if (activeDevice === undefined) {
return;
@@ -249,7 +256,6 @@ module.exports.pinActiveDevice = function pinActiveDevice() {
DEVICE.changeActivePinIndex(true);
};
module.exports.unpinActiveDevice = function unpinActiveDevice() {
if (activeDevice === undefined) {
return;
@@ -258,19 +264,16 @@ module.exports.unpinActiveDevice = function unpinActiveDevice() {
DEVICE.changeActivePinIndex(false);
};
module.exports.pinDevice = function pinDevice(device) {
pinnedDevices.push(device);
DEVICE.changePinIndex(device, true);
};
module.exports.unpinDevice = function unpinDevice(device) {
pinnedDevices.push(device);
DEVICE.changePinIndex(device, false);
};
module.exports.resetPinned = function resetPinned() {
pinnedDevices.length = 0;
activeDevice = false;
@@ -285,12 +288,10 @@ module.exports.resetPinned = function resetPinned() {
document.getElementById('all-devices').innerHTML = '';
};
module.exports.getPinnedDevices = function getPinnedDevices() {
return pinnedDevices;
};
module.exports.toggleSlotButtons = function toggleSlotButtons(slotIndex) {
if (slotIndex === 1) {
document.getElementById('save-slot-1').classList.add('active');
@@ -307,7 +308,6 @@ module.exports.toggleSlotButtons = function toggleSlotButtons(slotIndex) {
}
};
module.exports.selectPreviousDevice = function selectPreviousDevice() {
if (activeDevice === undefined) {
return;
@@ -317,20 +317,22 @@ module.exports.selectPreviousDevice = function selectPreviousDevice() {
switchDevice(keys[prevIndex]);
};
module.exports.selectNextDevice = function selectNextDevice() {
if (activeDevice === undefined) {
return;
}
const keys = Object.keys(DEVICE.all);
const prevIndex = Math.min(keys.length - 1, keys.indexOf(activeDevice.id) + 1);
const prevIndex = Math.min(
keys.length - 1,
keys.indexOf(activeDevice.id) + 1
);
switchDevice(keys[prevIndex]);
};
function populatePluginLists() {
let typeSelect = '';
let addSelect = '<option value="" disabled selected hidden>&nbsp;+&nbsp;</option>';
let addSelect =
'<option value="" disabled selected hidden>&nbsp;+&nbsp;</option>';
Object.keys(PLUGINS.all).forEach((pluginType) => {
const plugin = PLUGINS.all[pluginType];
@@ -338,6 +340,7 @@ function populatePluginLists() {
typeSelect += `<option value='${pluginType}'>${plugin.config.defaultName}</option>`;
});
document.getElementById('device-settings-plugin-dropdown').innerHTML = typeSelect;
document.getElementById('device-settings-plugin-dropdown').innerHTML =
typeSelect;
document.getElementById('add-device-button').innerHTML = addSelect;
};
}