diff --git a/packages/osc/osc.mjs b/packages/osc/osc.mjs index 4e1011b1..30364057 100644 --- a/packages/osc/osc.mjs +++ b/packages/osc/osc.mjs @@ -5,10 +5,35 @@ This program is free software: you can redistribute it and/or modify it under th */ import OSC from 'osc-js'; -import { parseNumeral, Pattern } from '@strudel.cycles/core'; +import { logger, parseNumeral, Pattern } from '@strudel.cycles/core'; + +let connection; // Promise +function connect() { + if (!connection) { + // make sure this runs only once + connection = new Promise((resolve, reject) => { + const osc = new OSC(); + osc.open(); + osc.on('open', () => { + logger('OSC connected!'); + resolve(osc); + }); + osc.on('close', () => { + connection = undefined; // allows new connection afterwards + console.log('osc connection closed'); + reject('OSC connection closed'); + }); + osc.on('error', (err) => reject(err)); + }).catch((err) => { + connection = undefined; + throw new Error('Could not connect to OSC server. Is it running?'); + }); + } else { + console.log('already has connection'); + } + return connection; +} -const comm = new OSC(); -comm.open(); const latency = 0.1; let startedAt = -1; @@ -20,9 +45,10 @@ let startedAt = -1; * @memberof Pattern * @returns Pattern */ -Pattern.prototype.osc = function () { +Pattern.prototype.osc = async function () { + const osc = await connect(); return this._withHap((hap) => { - const onTrigger = (time, hap, currentTime, cps) => { + const onTrigger = (time, hap, currentTime, cps = 1) => { const cycle = hap.wholeOrPart().begin.valueOf(); const delta = hap.duration.valueOf(); // time should be audio time of onset @@ -34,13 +60,12 @@ Pattern.prototype.osc = function () { // make sure n and note are numbers controls.n && (controls.n = parseNumeral(controls.n)); controls.note && (controls.note = parseNumeral(controls.note)); - const keyvals = Object.entries(controls).flat(); const ts = Math.floor(startedAt + (time + latency) * 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 - comm.send(bundle); + osc.send(bundle); }; return hap.setContext({ ...hap.context, onTrigger }); });