diff --git a/packages/osc/src/message.ts b/packages/osc/src/message.ts index 65151ca..d97d347 100644 --- a/packages/osc/src/message.ts +++ b/packages/osc/src/message.ts @@ -33,12 +33,29 @@ export function messageToBuffer(message: OSCMessage): Uint8Array { throw new Error('problem encoding address'); } - const typeString = message.args.map((arg) => arg.type).join(''); - const typesBuffer = oscTypeConverterMap.s.toBuffer(`,${typeString}`); + let typeString = ',' + + const flatOSCArgs: OSCArg[] = [] + + message.args.forEach((oscArg)=> { + if(Array.isArray(oscArg)){ + typeString += '[' + oscArg.forEach((oscArg)=>{ + typeString += oscArg.type + flatOSCArgs.push(oscArg) + }) + typeString += ']' + }else { + typeString += oscArg.type + flatOSCArgs.push(oscArg) + } + }) + + const typesBuffer = oscTypeConverterMap.s.toBuffer(typeString); if (typesBuffer === undefined) { throw new Error('problem encoding types'); } - const argsBuffer = argsToBuffer(message.args); + const argsBuffer = argsToBuffer(flatOSCArgs); const buffer = new Uint8Array(addressBuffer.length + typesBuffer.length + argsBuffer.length); buffer.set(addressBuffer, 0); buffer.set(typesBuffer, addressBuffer.length); @@ -51,7 +68,7 @@ export function messageFromBuffer(bytes: Uint8Array): [OSCMessage | undefined, U throw new Error('osc message must start with a /'); } - const oscArgs: OSCArg[] = []; + const oscArgs: (OSCArg | OSCArg[])[] = []; const [address, bytesAfterAddress] = oscTypeConverterMap.s.fromBuffer(bytes); if (typeof address === 'string') { @@ -61,9 +78,30 @@ export function messageFromBuffer(bytes: Uint8Array): [OSCMessage | undefined, U throw new Error('osc type string must start with a ,'); } let argsBuffer = bytesAfterType; + let oscArrayArg: OSCArg[] = []; + let insideArgArray = false; for (let index = 1; index < typeString.length; index++) { const argType = typeString.charAt(index) as OSCType; + if (argType === '['){ + if (insideArgArray){ + throw new Error('osc arg array opened without closing previous arg array') + } + oscArrayArg = []; + insideArgArray = true; + continue; + } + + if (argType === ']'){ + if (!insideArgArray){ + throw new Error('osc arg array closed without opening arg array') + } + oscArgs.push(oscArrayArg); + oscArrayArg = []; + insideArgArray = false; + continue; + } + const oscTypeConverter = oscTypeConverterMap[argType]; if (oscTypeConverter === undefined) { throw new Error('unknown OSC type'); @@ -74,7 +112,11 @@ export function messageFromBuffer(bytes: Uint8Array): [OSCMessage | undefined, U type: argType, value: value, }; - oscArgs.push(arg); + if(insideArgArray){ + oscArrayArg.push(arg) + }else { + oscArgs.push(arg); + } } argsBuffer = remainingBytes; } diff --git a/packages/osc/src/models.ts b/packages/osc/src/models.ts index e7a5c69..33946d5 100644 --- a/packages/osc/src/models.ts +++ b/packages/osc/src/models.ts @@ -1,4 +1,4 @@ -export type OSCType = 's' | 'i' | 'f' | 'b' | 'T' | 'F' | 't' | 'r' | 'N'; +export type OSCType = 's' | 'i' | 'f' | 'b' | 'T' | 'F' | 't' | 'r' | 'N' | '[' | ']'; export type OSCArg = { type: OSCType; value: string | number | Uint8Array | boolean | OSCTimeTag | OSCColor | bigint | null; @@ -20,7 +20,7 @@ export type OSCBundle = { export type OSCMessage = { address: string; - args: OSCArg[]; + args: (OSCArg | OSCArg[])[]; }; export type OSCTypeConverter = { diff --git a/packages/osc/tests/message-decode.test.js b/packages/osc/tests/message-decode.test.js index b0298e5..1a66942 100644 --- a/packages/osc/tests/message-decode.test.js +++ b/packages/osc/tests/message-decode.test.js @@ -65,6 +65,13 @@ const tests = [ ]), expected: { address: '/hello', args: [{ type: 'd', value: 12.7654763 }] }, }, + { + description: 'simple address array arg', + bytes: new Uint8Array([ + 47, 104, 101, 108, 108, 111, 0, 0, 44, 91, 100, 105, 93, 0, 0, 0, 0x40, 0x29, 0x87, 0xec, 0x82, 0x74, 0xb9, 0xe6, 0, 0, 3, 232 + ]), + expected: { address: '/hello', args: [[{ type: 'd', value: 12.7654763 }, { type: 'i', value: 1000}]] }, + }, { description: 'osc 1.0 spec example 1', bytes: new Uint8Array([ diff --git a/packages/osc/tests/message-encode.test.js b/packages/osc/tests/message-encode.test.js index d89b50f..e6c51c5 100644 --- a/packages/osc/tests/message-encode.test.js +++ b/packages/osc/tests/message-encode.test.js @@ -60,6 +60,13 @@ const tests = [ 47, 104, 101, 108, 108, 111, 0, 0, 44, 100, 0, 0, 0x40, 0x29, 0x87, 0xec, 0x82, 0x74, 0xb9, 0xe6, ]), }, + { + description: 'simple address array arg', + message: { address: '/hello', args: [[{ type: 'd', value: 12.7654763 }, { type: 'i', value: 1000}]] }, + expected: new Uint8Array([ + 47, 104, 101, 108, 108, 111, 0, 0, 44, 91, 100, 105, 93, 0, 0, 0, 0x40, 0x29, 0x87, 0xec, 0x82, 0x74, 0xb9, 0xe6, 0, 0, 3, 232 + ]), + }, { description: 'osc 1.0 spec example 1', message: { address: '/oscillator/4/frequency', args: [{ type: 'f', value: 440 }] },