@showbridge/lib
Version:
Main library for showbridge protocol router
174 lines (173 loc) • 6.86 kB
JavaScript
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _MIDIProtocol_instances, _MIDIProtocol_getPortName, _MIDIProtocol_findMidiOutput;
import { MIDIMessage } from '../messages/index.js';
import { disabled, logger } from '../utils/index.js';
import { Input, Output } from '@julusian/midi';
import Protocol from './protocol.js';
class MIDIProtocol extends Protocol {
constructor(protocolObj, router) {
super(protocolObj, router);
_MIDIProtocol_instances.add(this);
this.inputs = [];
this.outputs = [];
}
reload(params) {
// if (midi === undefined) {
// logger.error('midi: midi library not loaded skipping reload');
// this.emit('started');
// return;
// }
if (this.virtualInput) {
this.virtualInput.destroy();
delete this.virtualInput;
}
if (this.virtualOutput) {
this.virtualOutput.destroy();
delete this.virtualInput;
}
this.virtualInput = new Input();
this.virtualOutput = new Output();
this.virtualInputName = `showbridge Input`;
this.virtualOutputName = `showbridge Output`;
if (params?.virtualInputName) {
this.virtualInputName = params.virtualInputName;
}
this.virtualInput.openVirtualPort(this.virtualInputName);
this.virtualInput.ignoreTypes(false, false, false);
if (params?.virtualOutputName) {
this.virtualOutputName = params.virtualOutputName;
}
this.virtualOutput.openVirtualPort(this.virtualOutputName);
this.virtualInput.on('message', (deltaTime, msg) => {
try {
const midiMessage = new MIDIMessage(msg, 'virtual');
this.emit('messageIn', midiMessage);
}
catch (error) {
logger.error(`midi: problem processing MIDI message - ${error}`);
}
});
// TODO(jwetzell): look into better way to reload inputs
// TODO(jwetzell): consider letting the user configure the inputs that are loaded
this.inputs.forEach((input) => {
if (input.isPortOpen()) {
input.destroy();
}
});
this.inputs = [];
for (let index = 0; index < this.virtualInput.getPortCount(); index += 1) {
const input = new Input();
this.inputs.push(input);
input.openPort(index);
input.ignoreTypes(false, false, false);
input.on('message', (deltaTime, msg) => {
try {
const midiMessage = new MIDIMessage(msg, __classPrivateFieldGet(this, _MIDIProtocol_instances, "m", _MIDIProtocol_getPortName).call(this, input, index));
this.emit('messageIn', midiMessage);
}
catch (error) {
logger.error(`midi: problem processing MIDI message - ${error}`);
}
});
}
this.outputs.forEach((output) => {
if (output.output.isPortOpen()) {
output.output.destroy();
}
});
this.outputs = [];
for (let index = 0; index < this.virtualOutput.getPortCount(); index += 1) {
const output = new Output();
const outputName = __classPrivateFieldGet(this, _MIDIProtocol_instances, "m", _MIDIProtocol_getPortName).call(this, output, index);
this.outputs.push({
name: outputName,
index,
output,
});
}
this.emit('started');
// TODO(jwetzell): find a way to detect midi device changes
}
send(bytes, port) {
const output = port === undefined ? this.virtualOutput : __classPrivateFieldGet(this, _MIDIProtocol_instances, "m", _MIDIProtocol_findMidiOutput).call(this, port);
if (output === undefined) {
logger.error(`midi: no midi device found with name ${port}`);
return;
}
try {
output.sendMessage(bytes);
}
catch (error) {
logger.error('midi: problem sending midi');
logger.error(error);
}
}
stop() {
this.stopped = true;
this.inputs.forEach((input) => {
input.destroy();
});
this.outputs.forEach((output) => {
output.output.destroy();
});
if (this.virtualInput) {
this.virtualInput.destroy();
}
if (this.virtualOutput) {
this.virtualOutput.destroy();
}
this.emit('stopped');
}
get status() {
const devices = [];
try {
this.inputs.forEach((port, index) => {
if (!this.stopped && port.isPortOpen()) {
devices.push({
type: 'input',
name: __classPrivateFieldGet(this, _MIDIProtocol_instances, "m", _MIDIProtocol_getPortName).call(this, port, index),
});
}
});
this.outputs.forEach((output) => {
devices.push({
type: 'output',
name: output.name,
});
});
}
catch (error) {
logger.error('midi: problem assembling midi status');
logger.error(error);
}
return {
enabled: !disabled.protocols.has('midi'), // && midi !== undefined,
devices,
};
}
}
_MIDIProtocol_instances = new WeakSet(), _MIDIProtocol_getPortName = function _MIDIProtocol_getPortName(port, index) {
if (process.platform === 'linux') {
const rawPortName = port.getPortName(index);
const parts = rawPortName.match(/^(.*):(.*)\s+(\d+:\d+)$/);
if (parts) {
return parts[2];
}
return rawPortName;
}
return port.getPortName(index);
}, _MIDIProtocol_findMidiOutput = function _MIDIProtocol_findMidiOutput(port) {
const foundOutput = this.outputs.find((output) => output.name === port);
if (foundOutput !== undefined && foundOutput.output !== undefined) {
if (!foundOutput.output.isPortOpen()) {
foundOutput.output.openPort(foundOutput.index);
}
return foundOutput.output;
}
return undefined;
};
export default MIDIProtocol;