mirror of
https://github.com/jwetzell/osc-js.git
synced 2026-08-06 07:43:43 +00:00
89 lines
2.9 KiB
TypeScript
89 lines
2.9 KiB
TypeScript
import { messageFromBuffer, messageToBuffer } from "./message";
|
|
import { OSCBundle } from "./models";
|
|
import { oscTypeConverterMap } from "./osc-types";
|
|
|
|
export function bundleFromBuffer(bytes: Buffer): OSCBundle | undefined {
|
|
if (bytes.length < 8) {
|
|
throw new Error('bundle has to be at least 20 bytes');
|
|
}
|
|
|
|
if (bytes.subarray(0, 7).toString('ascii') !== '#bundle') {
|
|
throw new Error('bundle must start with #bundle');
|
|
}
|
|
|
|
const [bundleHeader, bytesAfterHeader] = oscTypeConverterMap.s.fromBuffer(bytes);
|
|
let [timeTag, bytesAfterTimeTag] = oscTypeConverterMap.t.fromBuffer(bytesAfterHeader);
|
|
|
|
if (!Array.isArray(timeTag)) {
|
|
throw new Error('problem getting bundle time tag');
|
|
}
|
|
|
|
const bundleContents = [];
|
|
|
|
let endOfBundle = false;
|
|
|
|
let [contentSize, remainingBytes] = oscTypeConverterMap.i.fromBuffer(bytesAfterTimeTag);
|
|
if (typeof contentSize === 'number') {
|
|
while (!endOfBundle) {
|
|
if (remainingBytes.length < contentSize) {
|
|
throw new Error('bundle does not contain enough data');
|
|
}
|
|
|
|
const bundleContentBytes = remainingBytes.subarray(0, contentSize);
|
|
|
|
if (bundleContentBytes[0] === 35) {
|
|
// # character indicating contents is a bundle
|
|
const content = bundleFromBuffer(bundleContentBytes);
|
|
if (content) {
|
|
bundleContents.push(content);
|
|
}
|
|
} else if (bundleContentBytes[0] === 47) {
|
|
const content = messageFromBuffer(bundleContentBytes);
|
|
if (content) {
|
|
bundleContents.push(content);
|
|
}
|
|
} else {
|
|
throw new Error('bundle contents does not look like a OSC message or bundle');
|
|
}
|
|
|
|
remainingBytes = remainingBytes.subarray(contentSize);
|
|
if (remainingBytes.length === 0) {
|
|
endOfBundle = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
timeTag,
|
|
contents: bundleContents,
|
|
};
|
|
}
|
|
|
|
export function bundleToBuffer(bundle: OSCBundle): Buffer {
|
|
const headerBuffer = oscTypeConverterMap.s.toBuffer('#bundle');
|
|
|
|
if (headerBuffer === undefined) {
|
|
throw new Error('problem encoding buffer header');
|
|
}
|
|
|
|
const timeTagBuffer = oscTypeConverterMap.t.toBuffer(bundle.timeTag);
|
|
|
|
if (timeTagBuffer === undefined) {
|
|
throw new Error('problem encoding buffer time tag');
|
|
}
|
|
|
|
const contentsBuffers: Buffer[] = [];
|
|
|
|
bundle.contents.forEach((bundleContent) => {
|
|
if ('address' in bundleContent) {
|
|
const contentBuffer = messageToBuffer(bundleContent);
|
|
const contentSizeBuffer = oscTypeConverterMap.i.toBuffer(contentBuffer.length);
|
|
|
|
if (contentBuffer && contentSizeBuffer) {
|
|
contentsBuffers.push(Buffer.concat([contentSizeBuffer, contentBuffer]));
|
|
}
|
|
}
|
|
});
|
|
|
|
return Buffer.concat([headerBuffer, timeTagBuffer, ...contentsBuffers]);
|
|
} |