diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs
index 3475fc2f4..a3ca638aa 100644
--- a/packages/core/controls.mjs
+++ b/packages/core/controls.mjs
@@ -2320,6 +2320,24 @@ export const { miditouch } = registerControl('miditouch');
// TODO: what is this?
export const { polyTouch } = registerControl('polyTouch');
+/**
+ * The host to send open sound control messages to. Requires running the OSC bridge.
+ * @name oschost
+ * @param {string | Pattern} oschost e.g. 'localhost'
+ * @example
+ * note("c4").oschost('127.0.0.1').oscport(57120).osc();
+ */
+export const { oschost } = registerControl('oschost');
+
+/**
+ * The port to send open sound control messages to. Requires running the OSC bridge.
+ * @name oscport
+ * @param {number | Pattern} oscport e.g. 57120
+ * @example
+ * note("c4").oschost('127.0.0.1').oscport(57120).osc();
+ */
+export const { oscport } = registerControl('oscport');
+
export const getControlName = (alias) => {
if (controlAlias.has(alias)) {
return controlAlias.get(alias);
diff --git a/packages/osc/osc.mjs b/packages/osc/osc.mjs
index fe0691522..68caab3a7 100644
--- a/packages/osc/osc.mjs
+++ b/packages/osc/osc.mjs
@@ -4,8 +4,6 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import OSC from 'osc-js';
-
import { logger, parseNumeral, register, isNote, noteToMidi, ClockCollator } from '@strudel/core';
let connection; // Promise
@@ -13,19 +11,18 @@ function connect() {
if (!connection) {
// make sure this runs only once
connection = new Promise((resolve, reject) => {
- const osc = new OSC();
- osc.open();
- osc.on('open', () => {
- const url = osc.options?.plugin?.socket?.url;
- logger(`[osc] connected${url ? ` to ${url}` : ''}`);
- resolve(osc);
+ const ws = new WebSocket('ws://localhost:8080');
+ ws.addEventListener('open', (event) => {
+ logger(`[osc] websocket connected`);
+ resolve(ws);
});
- osc.on('close', () => {
+ ws.addEventListener('close', (event) => {
+ logger(`[osc] websocket closed`);
connection = undefined; // allows new connection afterwards
console.log('[osc] disconnected');
reject('OSC connection closed');
});
- osc.on('error', (err) => reject(err));
+ ws.addEventListener('error', (err) => reject(err));
}).catch((err) => {
connection = undefined;
throw new Error('Could not connect to OSC server. Is it running?');
@@ -61,15 +58,19 @@ export function parseControlsFromHap(hap, cps) {
const collator = new ClockCollator({});
export async function oscTrigger(hap, currentTime, cps = 1, targetTime) {
- const osc = await connect();
+ const ws = await connect();
const controls = parseControlsFromHap(hap, cps);
const keyvals = Object.entries(controls).flat();
+ const ts = collator.calculateTimestamp(currentTime, targetTime) * 1000;
+ const msg = { address: '/dirt/play', args: keyvals, timestamp: ts };
- const ts = Math.round(collator.calculateTimestamp(currentTime, targetTime) * 1000);
- const message = new OSC.Message('/dirt/play', ...keyvals);
- const bundle = new OSC.Bundle([message], ts);
- bundle.timestamp(ts); // workaround for https://github.com/adzialocha/osc-js/issues/60
- osc.send(bundle);
+ if ('oschost' in hap.value) {
+ msg['host'] = hap.value['oschost'];
+ }
+ if ('oscport' in hap.value) {
+ msg['port'] = hap.value['oscport'];
+ }
+ ws.send(JSON.stringify(msg));
}
/**
diff --git a/packages/osc/package.json b/packages/osc/package.json
index bc828d798..ea453e1eb 100644
--- a/packages/osc/package.json
+++ b/packages/osc/package.json
@@ -38,7 +38,8 @@
"homepage": "https://codeberg.org/uzu/strudel#readme",
"dependencies": {
"@strudel/core": "workspace:*",
- "osc-js": "^2.4.1"
+ "osc": "^2.4.5",
+ "ws": "^8.18.3"
},
"devDependencies": {
"pkg": "^5.8.1",
diff --git a/packages/osc/server.js b/packages/osc/server.js
old mode 100644
new mode 100755
index d7ec21c4b..ede35e975
--- a/packages/osc/server.js
+++ b/packages/osc/server.js
@@ -6,70 +6,59 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import OSC from 'osc-js';
+// import OSC from 'osc-js';
-const args = process.argv.slice(2);
-function getArgValue(flag) {
- const i = args.indexOf(flag);
- if (i !== -1) {
- const nextIsFlag = args[i + 1]?.startsWith('--') ?? true;
- if (nextIsFlag) return true;
- return args[i + 1];
- }
-}
+import { WebSocketServer } from 'ws';
+import osc from 'osc';
-let udpClientPort = Number(getArgValue('--port')) || 57120;
-let debug = Number(getArgValue('--debug')) || 0;
+const WS_PORT = 8080; // WebSocket server port
+const OSC_REMOTE_IP = '127.0.0.1';
+const OSC_REMOTE_PORT = 57120;
-const config = {
- receiver: 'ws', // @param {string} Where messages sent via 'send' method will be delivered to, 'ws' for Websocket clients, 'udp' for udp client
- udpServer: {
- host: 'localhost', // @param {string} Hostname of udp server to bind to
- port: 57121, // @param {number} Port of udp client for messaging
- // enabling the following line will receive tidal messages:
- // port: 57120, // @param {number} Port of udp client for messaging
- exclusive: false, // @param {boolean} Exclusive flag
- },
- udpClient: {
- host: 'localhost', // @param {string} Hostname of udp client for messaging
- port: udpClientPort, // @param {number} Port of udp client for messaging
- },
- wsServer: {
- host: 'localhost', // @param {string} Hostname of WebSocket server
- port: 8080, // @param {number} Port of WebSocket server
- },
-};
-
-const osc = new OSC({ plugin: new OSC.BridgePlugin(config) });
-
-if (debug) {
- osc.on('*', (message) => {
- const { address, args } = message;
- let str = '';
- for (let i = 0; i < args.length; i += 2) {
- str += `${args[i]}: ${args[i + 1]} `;
- }
- console.log(`${address} ${str}`);
- });
-}
-
-osc.on('error', (message) => {
- if (message.toString().includes('EADDRINUSE')) {
- console.log(`------ ERROR -------
-a server is already running on port 57121! to stop it:
-1. run "lsof -ti :57121 | xargs kill -9" (macos / linux)
-2. re-run the osc server
-`);
- } else {
- console.log(message);
- }
+const udpPort = new osc.UDPPort({
+ localAddress: '0.0.0.0',
+ localPort: 0,
+ remoteAddress: OSC_REMOTE_IP,
+ remotePort: OSC_REMOTE_PORT,
});
-osc.open();
+udpPort.open();
+console.log(`[Sending OSC] ${OSC_REMOTE_IP}:${OSC_REMOTE_PORT}`);
-console.log('osc client running on port', config.udpClient.port);
-console.log('osc server running on port', config.udpServer.port);
-console.log('websocket server running on port', config.wsServer.port);
-if (debug) {
- console.log('debug logs enabled. incoming messages will appear below');
-}
+udpPort.on('error', (e) => {
+ console.log('Error: ', e);
+});
+
+const wss = new WebSocketServer({ port: WS_PORT });
+console.log(`[Listening WS] ws://localhost:${WS_PORT}`);
+
+wss.on('connection', (ws) => {
+ console.log('New WebSocket connection');
+
+ ws.on('message', (message) => {
+ let osc_host = '127.0.0.1';
+ let osc_port = 57120;
+
+ try {
+ const data = JSON.parse(message);
+ if ('host' in data) {
+ osc_host = data['host'];
+ }
+ if ('port' in data) {
+ osc_port = data['port'];
+ }
+ let msg = { address: data['address'], args: data['args'] };
+ if ('timestamp' in data) {
+ msg = { timeTag: osc.timeTag(0, data['timestamp']), packets: [msg] };
+ }
+
+ udpPort.send(msg, osc_host, osc_port);
+ } catch (err) {
+ console.error('Error parsing message:', err);
+ }
+ });
+
+ ws.on('close', () => {
+ console.log('WebSocket connection closed');
+ });
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 055bb4bc7..7b524ebf9 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -41,7 +41,7 @@ importers:
version: 2.2.7
'@vitest/coverage-v8':
specifier: 3.0.4
- version: 3.0.4(vitest@3.0.4)
+ version: 3.0.4(vitest@3.0.4(@types/debug@4.1.12)(@types/node@22.10.10)(@vitest/ui@3.0.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(yaml@2.7.0))
'@vitest/ui':
specifier: ^3.0.4
version: 3.0.4(vitest@3.0.4)
@@ -415,9 +415,12 @@ importers:
'@strudel/core':
specifier: workspace:*
version: link:../core
- osc-js:
- specifier: ^2.4.1
- version: 2.4.1
+ osc:
+ specifier: ^2.4.5
+ version: 2.4.5
+ ws:
+ specifier: ^8.18.3
+ version: 8.18.3
devDependencies:
pkg:
specifier: ^5.8.1
@@ -2429,6 +2432,70 @@ packages:
'@rtsao/scc@1.1.0':
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
+ '@serialport/binding-mock@10.2.2':
+ resolution: {integrity: sha512-HAFzGhk9OuFMpuor7aT5G1ChPgn5qSsklTFOTUX72Rl6p0xwcSVsRtG/xaGp6bxpN7fI9D/S8THLBWbBgS6ldw==}
+ engines: {node: '>=12.0.0'}
+
+ '@serialport/bindings-cpp@12.0.1':
+ resolution: {integrity: sha512-r2XOwY2dDvbW7dKqSPIk2gzsr6M6Qpe9+/Ngs94fNaNlcTRCV02PfaoDmRgcubpNVVcLATlxSxPTIDw12dbKOg==}
+ engines: {node: '>=16.0.0'}
+
+ '@serialport/bindings-interface@1.2.2':
+ resolution: {integrity: sha512-CJaUd5bLvtM9c5dmO9rPBHPXTa9R2UwpkJ0wdh9JCYcbrPWsKz+ErvR0hBLeo7NPeiFdjFO4sonRljiw4d2XiA==}
+ engines: {node: ^12.22 || ^14.13 || >=16}
+
+ '@serialport/parser-byte-length@12.0.0':
+ resolution: {integrity: sha512-0ei0txFAj+s6FTiCJFBJ1T2hpKkX8Md0Pu6dqMrYoirjPskDLJRgZGLqoy3/lnU1bkvHpnJO+9oJ3PB9v8rNlg==}
+ engines: {node: '>=12.0.0'}
+
+ '@serialport/parser-cctalk@12.0.0':
+ resolution: {integrity: sha512-0PfLzO9t2X5ufKuBO34DQKLXrCCqS9xz2D0pfuaLNeTkyGUBv426zxoMf3rsMRodDOZNbFblu3Ae84MOQXjnZw==}
+ engines: {node: '>=12.0.0'}
+
+ '@serialport/parser-delimiter@11.0.0':
+ resolution: {integrity: sha512-aZLJhlRTjSmEwllLG7S4J8s8ctRAS0cbvCpO87smLvl3e4BgzbVgF6Z6zaJd3Aji2uSiYgfedCdNc4L6W+1E2g==}
+ engines: {node: '>=12.0.0'}
+
+ '@serialport/parser-delimiter@12.0.0':
+ resolution: {integrity: sha512-gu26tVt5lQoybhorLTPsH2j2LnX3AOP2x/34+DUSTNaUTzu2fBXw+isVjQJpUBFWu6aeQRZw5bJol5X9Gxjblw==}
+ engines: {node: '>=12.0.0'}
+
+ '@serialport/parser-inter-byte-timeout@12.0.0':
+ resolution: {integrity: sha512-GnCh8K0NAESfhCuXAt+FfBRz1Cf9CzIgXfp7SdMgXwrtuUnCC/yuRTUFWRvuzhYKoAo1TL0hhUo77SFHUH1T/w==}
+ engines: {node: '>=12.0.0'}
+
+ '@serialport/parser-packet-length@12.0.0':
+ resolution: {integrity: sha512-p1hiCRqvGHHLCN/8ZiPUY/G0zrxd7gtZs251n+cfNTn+87rwcdUeu9Dps3Aadx30/sOGGFL6brIRGK4l/t7MuQ==}
+ engines: {node: '>=8.6.0'}
+
+ '@serialport/parser-readline@11.0.0':
+ resolution: {integrity: sha512-rRAivhRkT3YO28WjmmG4FQX6L+KMb5/ikhyylRfzWPw0nSXy97+u07peS9CbHqaNvJkMhH1locp2H36aGMOEIA==}
+ engines: {node: '>=12.0.0'}
+
+ '@serialport/parser-readline@12.0.0':
+ resolution: {integrity: sha512-O7cywCWC8PiOMvo/gglEBfAkLjp/SENEML46BXDykfKP5mTPM46XMaX1L0waWU6DXJpBgjaL7+yX6VriVPbN4w==}
+ engines: {node: '>=12.0.0'}
+
+ '@serialport/parser-ready@12.0.0':
+ resolution: {integrity: sha512-ygDwj3O4SDpZlbrRUraoXIoIqb8sM7aMKryGjYTIF0JRnKeB1ys8+wIp0RFMdFbO62YriUDextHB5Um5cKFSWg==}
+ engines: {node: '>=12.0.0'}
+
+ '@serialport/parser-regex@12.0.0':
+ resolution: {integrity: sha512-dCAVh4P/pZrLcPv9NJ2mvPRBg64L5jXuiRxIlyxxdZGH4WubwXVXY/kBTihQmiAMPxbT3yshSX8f2+feqWsxqA==}
+ engines: {node: '>=12.0.0'}
+
+ '@serialport/parser-slip-encoder@12.0.0':
+ resolution: {integrity: sha512-0APxDGR9YvJXTRfY+uRGhzOhTpU5akSH183RUcwzN7QXh8/1jwFsFLCu0grmAUfi+fItCkR+Xr1TcNJLR13VNA==}
+ engines: {node: '>=12.0.0'}
+
+ '@serialport/parser-spacepacket@12.0.0':
+ resolution: {integrity: sha512-dozONxhPC/78pntuxpz/NOtVps8qIc/UZzdc/LuPvVsqCoJXiRxOg6ZtCP/W58iibJDKPZPAWPGYeZt9DJxI+Q==}
+ engines: {node: '>=12.0.0'}
+
+ '@serialport/stream@12.0.0':
+ resolution: {integrity: sha512-9On64rhzuqKdOQyiYLYv2lQOh3TZU/D3+IWCR5gk0alPel2nwpp4YwDEGiUBfrQZEdQ6xww0PWkzqth4wqwX3Q==}
+ engines: {node: '>=12.0.0'}
+
'@shikijs/core@1.29.1':
resolution: {integrity: sha512-Mo1gGGkuOYjDu5H8YwzmOuly9vNr8KDVkqj9xiKhhhFS8jisAtDSEWB9hzqRHLVQgFdA310e8XRJcW4tYhRB2A==}
@@ -3681,6 +3748,15 @@ packages:
supports-color:
optional: true
+ debug@4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
debug@4.4.0:
resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
engines: {node: '>=6.0'}
@@ -5290,6 +5366,9 @@ packages:
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
engines: {node: '>=10'}
+ long@4.0.0:
+ resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==}
+
longest-streak@3.1.0:
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
@@ -5673,6 +5752,9 @@ packages:
ms@2.0.0:
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
+ ms@2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@@ -5731,6 +5813,9 @@ packages:
resolution: {integrity: sha512-z8iYzQGBu35ZkTQ9mtR8RqugJZ9RCLn8fv3d7LsgDBzOijGQP3RdKTX4LA7LXw03ZhU5z0l4xfhIMgSES31+cg==}
engines: {node: '>=10'}
+ node-addon-api@7.0.0:
+ resolution: {integrity: sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==}
+
node-addon-api@8.3.0:
resolution: {integrity: sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg==}
engines: {node: ^18 || ^20 || >= 21}
@@ -5769,6 +5854,10 @@ packages:
resolution: {integrity: sha512-yqkmYrMbK1wPrfz7mgeYvA4tBperLg9FQ4S3Sau3nSAkpOA0x0zC8nQ1siBwozy1f4SE8vq2n1WKv99r+PCa1Q==}
engines: {node: '>= 0.6.0'}
+ node-gyp-build@4.6.0:
+ resolution: {integrity: sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==}
+ hasBin: true
+
node-gyp-build@4.8.4:
resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==}
hasBin: true
@@ -5930,6 +6019,9 @@ packages:
osc-js@2.4.1:
resolution: {integrity: sha512-QlSeRKJclL47FNvO1MUCAAp9frmCF9zcYbnf6R9HpcklAst8ZyX3ISsk1v/Vghr/5GmXn0bhVjFXF9h+hfnl4Q==}
+ osc@2.4.5:
+ resolution: {integrity: sha512-Nc4/qcl+vA/CMxiKS1xrYgzjfnyB3W94gZnrkn3eTzihlndbEml6+wj1YQNKBI4r+qrw3obCcEoU7SVH/OxpxA==}
+
own-keys@1.0.1:
resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
engines: {node: '>= 0.4'}
@@ -6689,6 +6781,10 @@ packages:
serialize-javascript@4.0.0:
resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==}
+ serialport@12.0.0:
+ resolution: {integrity: sha512-AmH3D9hHPFmnF/oq/rvigfiAouAKyK/TjnrkwZRYSFZxNggJxwvbAbfYrLeuvq7ktUdhuHdVdSjj852Z55R+uA==}
+ engines: {node: '>=16.0.0'}
+
set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
@@ -6776,6 +6872,9 @@ packages:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
+ slip@1.0.2:
+ resolution: {integrity: sha512-XrcHe3NAcyD3wO+O4I13RcS4/3AF+S9RvGNj9JhJeS02HyImwD2E3QWLrmn9hBfL+fB6yapagwxRkeyYzhk98g==}
+
smart-buffer@4.2.0:
resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
@@ -7651,6 +7750,9 @@ packages:
resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==}
engines: {node: '>=18'}
+ wolfy87-eventemitter@5.2.9:
+ resolution: {integrity: sha512-P+6vtWyuDw+MB01X7UeF8TaHBvbCovf4HPEMF/SV7BdDc1SMTiBy13SRD71lQh4ExFTG1d/WNzDGDCyOKSMblw==}
+
word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
@@ -7773,6 +7875,18 @@ packages:
utf-8-validate:
optional: true
+ ws@8.18.3:
+ resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
xmlcreate@2.0.4:
resolution: {integrity: sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==}
@@ -9769,6 +9883,76 @@ snapshots:
'@rtsao/scc@1.1.0': {}
+ '@serialport/binding-mock@10.2.2':
+ dependencies:
+ '@serialport/bindings-interface': 1.2.2
+ debug: 4.4.0
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
+ '@serialport/bindings-cpp@12.0.1':
+ dependencies:
+ '@serialport/bindings-interface': 1.2.2
+ '@serialport/parser-readline': 11.0.0
+ debug: 4.3.4
+ node-addon-api: 7.0.0
+ node-gyp-build: 4.6.0
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
+ '@serialport/bindings-interface@1.2.2':
+ optional: true
+
+ '@serialport/parser-byte-length@12.0.0':
+ optional: true
+
+ '@serialport/parser-cctalk@12.0.0':
+ optional: true
+
+ '@serialport/parser-delimiter@11.0.0':
+ optional: true
+
+ '@serialport/parser-delimiter@12.0.0':
+ optional: true
+
+ '@serialport/parser-inter-byte-timeout@12.0.0':
+ optional: true
+
+ '@serialport/parser-packet-length@12.0.0':
+ optional: true
+
+ '@serialport/parser-readline@11.0.0':
+ dependencies:
+ '@serialport/parser-delimiter': 11.0.0
+ optional: true
+
+ '@serialport/parser-readline@12.0.0':
+ dependencies:
+ '@serialport/parser-delimiter': 12.0.0
+ optional: true
+
+ '@serialport/parser-ready@12.0.0':
+ optional: true
+
+ '@serialport/parser-regex@12.0.0':
+ optional: true
+
+ '@serialport/parser-slip-encoder@12.0.0':
+ optional: true
+
+ '@serialport/parser-spacepacket@12.0.0':
+ optional: true
+
+ '@serialport/stream@12.0.0':
+ dependencies:
+ '@serialport/bindings-interface': 1.2.2
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
'@shikijs/core@1.29.1':
dependencies:
'@shikijs/engine-javascript': 1.29.1
@@ -10373,7 +10557,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@vitest/coverage-v8@3.0.4(vitest@3.0.4)':
+ '@vitest/coverage-v8@3.0.4(vitest@3.0.4(@types/debug@4.1.12)(@types/node@22.10.10)(@vitest/ui@3.0.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(yaml@2.7.0))':
dependencies:
'@ampproject/remapping': 2.3.0
'@bcoe/v8-coverage': 1.0.2
@@ -11281,6 +11465,11 @@ snapshots:
dependencies:
ms: 2.1.3
+ debug@4.3.4:
+ dependencies:
+ ms: 2.1.2
+ optional: true
+
debug@4.4.0:
dependencies:
ms: 2.1.3
@@ -13150,6 +13339,8 @@ snapshots:
chalk: 4.1.2
is-unicode-supported: 0.1.0
+ long@4.0.0: {}
+
longest-streak@3.1.0: {}
loupe@3.1.2: {}
@@ -13827,6 +14018,9 @@ snapshots:
ms@2.0.0: {}
+ ms@2.1.2:
+ optional: true
+
ms@2.1.3: {}
multimatch@5.0.0:
@@ -13876,6 +14070,9 @@ snapshots:
dependencies:
semver: 7.6.3
+ node-addon-api@7.0.0:
+ optional: true
+
node-addon-api@8.3.0: {}
node-domexception@1.0.0: {}
@@ -13902,6 +14099,9 @@ snapshots:
node-getopt@0.3.2: {}
+ node-gyp-build@4.6.0:
+ optional: true
+
node-gyp-build@4.8.4: {}
node-gyp@10.3.1:
@@ -14153,11 +14353,17 @@ snapshots:
os-tmpdir@1.0.2: {}
- osc-js@2.4.1:
+ osc@2.4.5:
dependencies:
+ long: 4.0.0
+ slip: 1.0.2
+ wolfy87-eventemitter: 5.2.9
ws: 8.18.0
+ optionalDependencies:
+ serialport: 12.0.0
transitivePeerDependencies:
- bufferutil
+ - supports-color
- utf-8-validate
own-keys@1.0.1:
@@ -15052,6 +15258,26 @@ snapshots:
dependencies:
randombytes: 2.1.0
+ serialport@12.0.0:
+ dependencies:
+ '@serialport/binding-mock': 10.2.2
+ '@serialport/bindings-cpp': 12.0.1
+ '@serialport/parser-byte-length': 12.0.0
+ '@serialport/parser-cctalk': 12.0.0
+ '@serialport/parser-delimiter': 12.0.0
+ '@serialport/parser-inter-byte-timeout': 12.0.0
+ '@serialport/parser-packet-length': 12.0.0
+ '@serialport/parser-readline': 12.0.0
+ '@serialport/parser-ready': 12.0.0
+ '@serialport/parser-regex': 12.0.0
+ '@serialport/parser-slip-encoder': 12.0.0
+ '@serialport/parser-spacepacket': 12.0.0
+ '@serialport/stream': 12.0.0
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
set-blocking@2.0.0: {}
set-function-length@1.2.2:
@@ -15194,6 +15420,8 @@ snapshots:
slash@3.0.0: {}
+ slip@1.0.2: {}
+
smart-buffer@4.2.0: {}
socks-proxy-agent@8.0.5:
@@ -16103,6 +16331,8 @@ snapshots:
dependencies:
string-width: 7.2.0
+ wolfy87-eventemitter@5.2.9: {}
+
word-wrap@1.2.5: {}
wordwrap@0.0.3: {}
@@ -16302,6 +16532,8 @@ snapshots:
ws@8.18.0: {}
+ ws@8.18.3: {}
+
xmlcreate@2.0.4: {}
xtend@4.0.2: {}
diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap
index d7e13d4d9..c39bb87bf 100644
--- a/test/__snapshots__/examples.test.mjs.snap
+++ b/test/__snapshots__/examples.test.mjs.snap
@@ -6958,6 +6958,24 @@ exports[`runs examples > example "orbit" example index 0 1`] = `
]
`;
+exports[`runs examples > example "oschost" example index 0 1`] = `
+[
+ "[ 0/1 → 1/1 | note:c4 oschost:127.0.0.1 oscport:57120 ]",
+ "[ 1/1 → 2/1 | note:c4 oschost:127.0.0.1 oscport:57120 ]",
+ "[ 2/1 → 3/1 | note:c4 oschost:127.0.0.1 oscport:57120 ]",
+ "[ 3/1 → 4/1 | note:c4 oschost:127.0.0.1 oscport:57120 ]",
+]
+`;
+
+exports[`runs examples > example "oscport" example index 0 1`] = `
+[
+ "[ 0/1 → 1/1 | note:c4 oschost:127.0.0.1 oscport:57120 ]",
+ "[ 1/1 → 2/1 | note:c4 oschost:127.0.0.1 oscport:57120 ]",
+ "[ 2/1 → 3/1 | note:c4 oschost:127.0.0.1 oscport:57120 ]",
+ "[ 3/1 → 4/1 | note:c4 oschost:127.0.0.1 oscport:57120 ]",
+]
+`;
+
exports[`runs examples > example "outside" example index 0 1`] = `
[
"[ 0/1 → 1/1 | note:A3 ]",