diff --git a/packages/osc/src/models.ts b/packages/osc/src/models.ts index 169fdf4..e931011 100644 --- a/packages/osc/src/models.ts +++ b/packages/osc/src/models.ts @@ -1,11 +1,18 @@ -export type OSCType = 's' | 'i' | 'f' | 'b' | 'T' | 'F' | 't'; +export type OSCType = 's' | 'i' | 'f' | 'b' | 'T' | 'F' | 't' | 'r'; export type OSCArg = { type: OSCType; - value: string | number | Uint8Array | boolean | OSCTimeTag; + value: string | number | Uint8Array | boolean | OSCTimeTag | OSCColor; }; export type OSCTimeTag = [number, number]; +export type OSCColor = { + r: number; + g: number; + b: number; + a: number; +}; + export type OSCBundle = { timeTag: OSCTimeTag; contents: (OSCBundle | OSCMessage)[]; @@ -17,6 +24,8 @@ export type OSCMessage = { }; export type OSCTypeConverter = { - toBuffer: (value: string | number | Uint8Array | boolean | OSCTimeTag) => Uint8Array | undefined; - fromBuffer: (buffer: Uint8Array) => [string | number | Uint8Array | boolean | OSCTimeTag | undefined, Uint8Array]; + toBuffer: (value: string | number | Uint8Array | boolean | OSCTimeTag | OSCColor) => Uint8Array | undefined; + fromBuffer: ( + buffer: Uint8Array + ) => [string | number | Uint8Array | boolean | OSCTimeTag | OSCColor | undefined, Uint8Array]; }; diff --git a/packages/osc/src/osc-types.ts b/packages/osc/src/osc-types.ts index 0d8f86f..3b72953 100644 --- a/packages/osc/src/osc-types.ts +++ b/packages/osc/src/osc-types.ts @@ -171,4 +171,49 @@ export const oscTypeConverterMap: { [key: string]: OSCTypeConverter } = { return [undefined, bytesAfterFractional]; }, }, + r: { + toBuffer: (color) => { + if (typeof color === 'object' && 'r' in color && 'g' in color && 'b' in color && 'a' in color) { + const view = new DataView(new ArrayBuffer(4)); + + view.setUint8(0, color.r); + view.setUint8(1, color.g); + view.setUint8(2, color.b); + view.setUint8(3, color.a); + + return new Uint8Array(view.buffer); + } + throw new TypeError('osc type r called with non OSCColor object'); + }, + fromBuffer: (buffer) => { + if (buffer.length < 4) { + throw new Error('osc color must be at least 4 bytes'); + } + + const red = buffer[0]; + const green = buffer[1]; + const blue = buffer[2]; + const alpha = buffer[3]; + + if (red !== undefined && green !== undefined && blue !== undefined && alpha !== undefined) { + if ( + typeof red === 'number' && + typeof green === 'number' && + typeof blue === 'number' && + typeof alpha === 'number' + ) { + return [ + { + r: red, + g: green, + b: blue, + a: alpha, + }, + buffer.subarray(4), + ]; + } + } + throw new Error('problem converting osc '); + }, + }, }; diff --git a/packages/osc/tests/message-decode.test.js b/packages/osc/tests/message-decode.test.js index 5dd97a1..8ebf0a4 100644 --- a/packages/osc/tests/message-decode.test.js +++ b/packages/osc/tests/message-decode.test.js @@ -38,6 +38,11 @@ const tests = [ bytes: new Uint8Array([47, 104, 101, 108, 108, 111, 0, 0, 44, 70, 0, 0]), expected: { address: '/hello', args: [{ type: 'F', value: false }] }, }, + { + description: 'simple address color arg', + bytes: new Uint8Array([47, 104, 101, 108, 108, 111, 0, 0, 44, 114, 0, 0, 20, 21, 22, 10]), + expected: { address: '/hello', args: [{ type: 'r', value: { r: 20, g: 21, b: 22, a: 10 } }] }, + }, { 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 139b884..bb5b94f 100644 --- a/packages/osc/tests/message-encode.test.js +++ b/packages/osc/tests/message-encode.test.js @@ -38,6 +38,11 @@ const tests = [ message: { address: '/hello', args: [{ type: 'F', value: false }] }, expected: new Uint8Array([47, 104, 101, 108, 108, 111, 0, 0, 44, 70, 0, 0]), }, + { + description: 'simple address color arg', + message: { address: '/hello', args: [{ type: 'r', value: { r: 20, g: 21, b: 22, a: 10 } }] }, + expected: new Uint8Array([47, 104, 101, 108, 108, 111, 0, 0, 44, 114, 0, 0, 20, 21, 22, 10]), + }, { description: 'osc 1.0 spec example 1', message: { address: '/oscillator/4/frequency', args: [{ type: 'f', value: 440 }] },