Skip to content
This repository was archived by the owner on Apr 13, 2025. It is now read-only.

Commit 619f167

Browse files
authored
Merge pull request #254 from noeppi-noeppi/virtual-midi
Virtual midi devices
2 parents 38ebc73 + 3f7f3fe commit 619f167

File tree

6 files changed

+1251
-1245
lines changed

6 files changed

+1251
-1245
lines changed

nodecg-io-debug/package-lock.json

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

nodecg-io-midi-input/extension/index.ts

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as easymidi from "easymidi";
44

55
interface MidiInputServiceConfig {
66
device: string;
7+
virtual?: boolean;
78
}
89

910
export type MidiInputServiceClient = easymidi.Input;
@@ -16,37 +17,49 @@ class MidiService extends ServiceBundle<MidiInputServiceConfig, MidiInputService
1617
async validateConfig(config: MidiInputServiceConfig): Promise<Result<void>> {
1718
const devices: Array<string> = new Array<string>();
1819

19-
easymidi.getInputs().forEach((device) => {
20-
if (device.includes(config.device)) {
21-
devices.push(device);
20+
// Virtual devices can always be created, easymidi will find a
21+
// free name for the matching output
22+
if (!config.virtual) {
23+
easymidi.getInputs().forEach((device) => {
24+
if (device.includes(config.device)) {
25+
devices.push(device);
26+
}
27+
});
28+
if (devices.length === 0) {
29+
return error("No device matched the configured pattern!");
30+
}
31+
if (devices.length > 1) {
32+
return error("The configured pattern is ambiguous!");
2233
}
23-
});
24-
25-
if (devices.length === 0) {
26-
return error("No device matched the configured pattern!");
27-
}
28-
if (devices.length > 1) {
29-
return error("The configured pattern is ambiguous!");
3034
}
35+
3136
return emptySuccess();
3237
}
3338

3439
async createClient(config: MidiInputServiceConfig): Promise<Result<MidiInputServiceClient>> {
35-
this.nodecg.log.info(`Checking device name "${config.device}".`);
36-
let deviceName: string | null = null;
37-
easymidi.getInputs().forEach((device) => {
38-
if (device.includes(config.device) && deviceName === null) {
39-
deviceName = device;
40-
}
41-
});
42-
43-
this.nodecg.log.info(`Connecting to MIDI input device ${deviceName}.`);
44-
if (deviceName !== null) {
45-
const client = new easymidi.Input(deviceName);
46-
this.nodecg.log.info(`Successfully connected to MIDI input device ${deviceName}.`);
40+
if (config.virtual) {
41+
this.nodecg.log.info(`Creating virtual MIDI input device ${config.device}.`);
42+
const client = new easymidi.Input(config.device, true);
43+
this.nodecg.log.info(`Successfully created virtual MIDI input device ${config.device}.`);
4744
return success(client);
4845
} else {
49-
return error("Could not connect to the configured device!");
46+
this.nodecg.log.info(`Checking device name "${config.device}".`);
47+
48+
let deviceName: string | null = null;
49+
easymidi.getInputs().forEach((device) => {
50+
if (device.includes(config.device) && deviceName === null) {
51+
deviceName = device;
52+
}
53+
});
54+
55+
this.nodecg.log.info(`Connecting to MIDI input device ${deviceName}.`);
56+
if (deviceName !== null) {
57+
const client = new easymidi.Input(deviceName);
58+
this.nodecg.log.info(`Successfully connected to MIDI input device ${deviceName}.`);
59+
return success(client);
60+
} else {
61+
return error("Could not connect to the configured device!");
62+
}
5063
}
5164
}
5265

nodecg-io-midi-input/midi-input-schema.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
"device": {
77
"type": "string",
88
"description": "The MIDI device id"
9+
},
10+
"virtual": {
11+
"type": "boolean",
12+
"description": "true to create a virtual device."
913
}
1014
},
1115
"required": ["device"]

nodecg-io-midi-output/extension/index.ts

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as easymidi from "easymidi";
44

55
interface MidiOutputServiceConfig {
66
device: string;
7+
virtual?: boolean;
78
}
89

910
export type MidiOutputServiceClient = easymidi.Output;
@@ -16,38 +17,49 @@ class MidiService extends ServiceBundle<MidiOutputServiceConfig, MidiOutputServi
1617
async validateConfig(config: MidiOutputServiceConfig): Promise<Result<void>> {
1718
const devices: Array<string> = new Array<string>();
1819

19-
easymidi.getOutputs().forEach((device) => {
20-
if (device.includes(config.device)) {
21-
devices.push(device);
20+
// Virtual devices can always be created, easymidi will find a
21+
// free name for the matching input
22+
if (!config.virtual) {
23+
easymidi.getOutputs().forEach((device) => {
24+
if (device.includes(config.device)) {
25+
devices.push(device);
26+
}
27+
});
28+
if (devices.length === 0) {
29+
return error("No device matched the configured pattern.");
30+
}
31+
if (devices.length > 1) {
32+
return error("The configured pattern is ambiguous.");
2233
}
23-
});
24-
25-
if (devices.length === 0) {
26-
return error("No device matched the configured pattern.");
27-
}
28-
if (devices.length > 1) {
29-
return error("The configured pattern is ambiguous.");
3034
}
35+
3136
return emptySuccess();
3237
}
3338

3439
async createClient(config: MidiOutputServiceConfig): Promise<Result<MidiOutputServiceClient>> {
35-
this.nodecg.log.info(`Checking device name "${config.device}".`);
36-
let deviceName: string | null = null;
37-
easymidi.getOutputs().forEach((device) => {
38-
if (device.includes(config.device) && deviceName === null) {
39-
deviceName = device;
40-
}
41-
});
42-
43-
this.nodecg.log.info(`Connecting to MIDI output device ${deviceName}.`);
44-
if (deviceName !== null) {
45-
const client = new easymidi.Output(deviceName);
46-
this.nodecg.log.info(`Successfully connected to MIDI output device ${deviceName}.`);
47-
40+
if (config.virtual) {
41+
this.nodecg.log.info(`Creating virtual MIDI output device ${config.device}.`);
42+
const client = new easymidi.Output(config.device, true);
43+
this.nodecg.log.info(`Successfully created virtual MIDI output device ${config.device}.`);
4844
return success(client);
4945
} else {
50-
return error("Could not connect to the configured device!");
46+
this.nodecg.log.info(`Checking device name "${config.device}".`);
47+
48+
let deviceName: string | null = null;
49+
easymidi.getOutputs().forEach((device) => {
50+
if (device.includes(config.device) && deviceName === null) {
51+
deviceName = device;
52+
}
53+
});
54+
55+
this.nodecg.log.info(`Connecting to MIDI output device ${deviceName}.`);
56+
if (deviceName !== null) {
57+
const client = new easymidi.Output(deviceName);
58+
this.nodecg.log.info(`Successfully connected to MIDI output device ${deviceName}.`);
59+
return success(client);
60+
} else {
61+
return error("Could not connect to the configured device!");
62+
}
5163
}
5264
}
5365

nodecg-io-midi-output/midi-output-schema.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
"device": {
77
"type": "string",
88
"description": "The MIDI device id"
9+
},
10+
"virtual": {
11+
"type": "boolean",
12+
"description": "true to create a virtual device."
913
}
1014
},
1115
"required": ["device"]

0 commit comments

Comments
 (0)