Mercurial > hg > beaglert
diff resources/osc/node_modules/osc-min/lib/osc-utilities.js @ 271:fb9c28a4676b prerelease
Added osc example project and node script for testing
author | Liam Donovan <l.b.donovan@qmul.ac.uk> |
---|---|
date | Tue, 17 May 2016 16:01:06 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resources/osc/node_modules/osc-min/lib/osc-utilities.js Tue May 17 16:01:06 2016 +0100 @@ -0,0 +1,741 @@ +// Generated by CoffeeScript 1.10.0 +(function() { + var IsArray, StrictError, TWO_POW_32, UNIX_EPOCH, binpack, getArrayArg, isOscBundleBuffer, makeTimetag, mapBundleList, oscTypeCodes, padding, toOscTypeAndArgs, + hasProp = {}.hasOwnProperty; + + binpack = require("binpack"); + + exports.concat = function(buffers) { + var buffer, copyTo, destBuffer, j, k, l, len, len1, len2, sumLength; + if (!IsArray(buffers)) { + throw new Error("concat must take an array of buffers"); + } + for (j = 0, len = buffers.length; j < len; j++) { + buffer = buffers[j]; + if (!Buffer.isBuffer(buffer)) { + throw new Error("concat must take an array of buffers"); + } + } + sumLength = 0; + for (k = 0, len1 = buffers.length; k < len1; k++) { + buffer = buffers[k]; + sumLength += buffer.length; + } + destBuffer = new Buffer(sumLength); + copyTo = 0; + for (l = 0, len2 = buffers.length; l < len2; l++) { + buffer = buffers[l]; + buffer.copy(destBuffer, copyTo); + copyTo += buffer.length; + } + return destBuffer; + }; + + exports.toOscString = function(str, strict) { + var i, j, nullIndex, ref; + if (!(typeof str === "string")) { + throw new Error("can't pack a non-string into an osc-string"); + } + nullIndex = str.indexOf("\u0000"); + if (nullIndex !== -1 && strict) { + throw StrictError("Can't pack an osc-string that contains NULL characters"); + } + if (nullIndex !== -1) { + str = str.slice(0, nullIndex); + } + for (i = j = 0, ref = padding(str); 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) { + str += "\u0000"; + } + return new Buffer(str); + }; + + exports.splitOscString = function(buffer, strict) { + var i, j, nullIndex, rawStr, ref, ref1, rest, splitPoint, str; + if (!Buffer.isBuffer(buffer)) { + throw StrictError("Can't split something that isn't a buffer"); + } + rawStr = buffer.toString("utf8"); + nullIndex = rawStr.indexOf("\u0000"); + if (nullIndex === -1) { + if (strict) { + throw new Error("All osc-strings must contain a null character"); + } + return { + string: rawStr, + rest: new Buffer(0) + }; + } + str = rawStr.slice(0, nullIndex); + splitPoint = Buffer.byteLength(str) + padding(str); + if (strict && splitPoint > buffer.length) { + throw StrictError("Not enough padding for osc-string"); + } + if (strict) { + for (i = j = ref = Buffer.byteLength(str), ref1 = splitPoint; ref <= ref1 ? j < ref1 : j > ref1; i = ref <= ref1 ? ++j : --j) { + if (buffer[i] !== 0) { + throw StrictError("Not enough or incorrect padding for osc-string"); + } + } + } + rest = buffer.slice(splitPoint, buffer.length); + return { + string: str, + rest: rest + }; + }; + + exports.splitInteger = function(buffer, type) { + var bytes, num, rest, value; + if (type == null) { + type = "Int32"; + } + bytes = (binpack["pack" + type](0)).length; + if (buffer.length < bytes) { + throw new Error("buffer is not big enough for integer type"); + } + num = 0; + value = binpack["unpack" + type](buffer.slice(0, bytes), "big"); + rest = buffer.slice(bytes, buffer.length); + return { + integer: value, + rest: rest + }; + }; + + exports.splitTimetag = function(buffer) { + var a, b, bytes, c, d, fractional, rest, seconds, type; + type = "Int32"; + bytes = (binpack["pack" + type](0)).length; + if (buffer.length < (bytes * 2)) { + throw new Error("buffer is not big enough to contain a timetag"); + } + a = 0; + b = bytes; + seconds = binpack["unpack" + type](buffer.slice(a, b), "big"); + c = bytes; + d = bytes + bytes; + fractional = binpack["unpack" + type](buffer.slice(c, d), "big"); + rest = buffer.slice(d, buffer.length); + return { + timetag: [seconds, fractional], + rest: rest + }; + }; + + UNIX_EPOCH = 2208988800; + + TWO_POW_32 = 4294967296; + + exports.dateToTimetag = function(date) { + return exports.timestampToTimetag(date.getTime() / 1000); + }; + + exports.timestampToTimetag = function(secs) { + var fracSeconds, wholeSecs; + wholeSecs = Math.floor(secs); + fracSeconds = secs - wholeSecs; + return makeTimetag(wholeSecs, fracSeconds); + }; + + exports.timetagToTimestamp = function(timetag) { + var seconds; + seconds = timetag[0] + exports.ntpToFractionalSeconds(timetag[1]); + return seconds - UNIX_EPOCH; + }; + + makeTimetag = function(unixseconds, fracSeconds) { + var ntpFracs, ntpSecs; + ntpSecs = unixseconds + UNIX_EPOCH; + ntpFracs = Math.round(TWO_POW_32 * fracSeconds); + return [ntpSecs, ntpFracs]; + }; + + exports.timetagToDate = function(timetag) { + var date, dd, fracs, fractional, seconds; + seconds = timetag[0], fractional = timetag[1]; + seconds = seconds - UNIX_EPOCH; + fracs = exports.ntpToFractionalSeconds(fractional); + date = new Date(); + date.setTime((seconds * 1000) + (fracs * 1000)); + dd = new Date(); + dd.setUTCFullYear(date.getUTCFullYear()); + dd.setUTCMonth(date.getUTCMonth()); + dd.setUTCDate(date.getUTCDate()); + dd.setUTCHours(date.getUTCHours()); + dd.setUTCMinutes(date.getUTCMinutes()); + dd.setUTCSeconds(date.getUTCSeconds()); + dd.setUTCMilliseconds(fracs * 1000); + return dd; + }; + + exports.deltaTimetag = function(seconds, now) { + var n; + n = (now != null ? now : new Date()) / 1000; + return exports.timestampToTimetag(n + seconds); + }; + + exports.ntpToFractionalSeconds = function(fracSeconds) { + return parseFloat(fracSeconds) / TWO_POW_32; + }; + + exports.toTimetagBuffer = function(timetag) { + var high, low, type; + if (typeof timetag === "number") { + timetag = exports.timestampToTimetag(timetag); + } else if (typeof timetag === "object" && ("getTime" in timetag)) { + timetag = exports.dateToTimetag(timetag); + } else if (timetag.length !== 2) { + throw new Error("Invalid timetag" + timetag); + } + type = "Int32"; + high = binpack["pack" + type](timetag[0], "big"); + low = binpack["pack" + type](timetag[1], "big"); + return exports.concat([high, low]); + }; + + exports.toIntegerBuffer = function(number, type) { + if (type == null) { + type = "Int32"; + } + if (typeof number !== "number") { + throw new Error("cannot pack a non-number into an integer buffer"); + } + return binpack["pack" + type](number, "big"); + }; + + oscTypeCodes = { + s: { + representation: "string", + split: function(buffer, strict) { + var split; + split = exports.splitOscString(buffer, strict); + return { + value: split.string, + rest: split.rest + }; + }, + toArg: function(value, strict) { + if (typeof value !== "string") { + throw new Error("expected string"); + } + return exports.toOscString(value, strict); + } + }, + i: { + representation: "integer", + split: function(buffer, strict) { + var split; + split = exports.splitInteger(buffer); + return { + value: split.integer, + rest: split.rest + }; + }, + toArg: function(value, strict) { + if (typeof value !== "number") { + throw new Error("expected number"); + } + return exports.toIntegerBuffer(value); + } + }, + t: { + representation: "timetag", + split: function(buffer, strict) { + var split; + split = exports.splitTimetag(buffer); + return { + value: split.timetag, + rest: split.rest + }; + }, + toArg: function(value, strict) { + return exports.toTimetagBuffer(value); + } + }, + f: { + representation: "float", + split: function(buffer, strict) { + return { + value: binpack.unpackFloat32(buffer.slice(0, 4), "big"), + rest: buffer.slice(4, buffer.length) + }; + }, + toArg: function(value, strict) { + if (typeof value !== "number") { + throw new Error("expected number"); + } + return binpack.packFloat32(value, "big"); + } + }, + d: { + representation: "double", + split: function(buffer, strict) { + return { + value: binpack.unpackFloat64(buffer.slice(0, 8), "big"), + rest: buffer.slice(8, buffer.length) + }; + }, + toArg: function(value, strict) { + if (typeof value !== "number") { + throw new Error("expected number"); + } + return binpack.packFloat64(value, "big"); + } + }, + b: { + representation: "blob", + split: function(buffer, strict) { + var length, ref; + ref = exports.splitInteger(buffer), length = ref.integer, buffer = ref.rest; + return { + value: buffer.slice(0, length), + rest: buffer.slice(length, buffer.length) + }; + }, + toArg: function(value, strict) { + var size; + if (!Buffer.isBuffer(value)) { + throw new Error("expected node.js Buffer"); + } + size = exports.toIntegerBuffer(value.length); + return exports.concat([size, value]); + } + }, + T: { + representation: "true", + split: function(buffer, strict) { + return { + rest: buffer, + value: true + }; + }, + toArg: function(value, strict) { + if (!value && strict) { + throw new Error("true must be true"); + } + return new Buffer(0); + } + }, + F: { + representation: "false", + split: function(buffer, strict) { + return { + rest: buffer, + value: false + }; + }, + toArg: function(value, strict) { + if (value && strict) { + throw new Error("false must be false"); + } + return new Buffer(0); + } + }, + N: { + representation: "null", + split: function(buffer, strict) { + return { + rest: buffer, + value: null + }; + }, + toArg: function(value, strict) { + if (value && strict) { + throw new Error("null must be false"); + } + return new Buffer(0); + } + }, + I: { + representation: "bang", + split: function(buffer, strict) { + return { + rest: buffer, + value: "bang" + }; + }, + toArg: function(value, strict) { + return new Buffer(0); + } + } + }; + + exports.oscTypeCodeToTypeString = function(code) { + var ref; + return (ref = oscTypeCodes[code]) != null ? ref.representation : void 0; + }; + + exports.typeStringToOscTypeCode = function(rep) { + var code, str; + for (code in oscTypeCodes) { + if (!hasProp.call(oscTypeCodes, code)) continue; + str = oscTypeCodes[code].representation; + if (str === rep) { + return code; + } + } + return null; + }; + + exports.argToTypeCode = function(arg, strict) { + var code, value; + if (((arg != null ? arg.type : void 0) != null) && (typeof arg.type === 'string') && ((code = exports.typeStringToOscTypeCode(arg.type)) != null)) { + return code; + } + value = (arg != null ? arg.value : void 0) != null ? arg.value : arg; + if (strict && (value == null)) { + throw new Error('Argument has no value'); + } + if (typeof value === 'string') { + return 's'; + } + if (typeof value === 'number') { + return 'f'; + } + if (Buffer.isBuffer(value)) { + return 'b'; + } + if (typeof value === 'boolean') { + if (value) { + return 'T'; + } else { + return 'F'; + } + } + if (value === null) { + return 'N'; + } + throw new Error("I don't know what type this is supposed to be."); + }; + + exports.splitOscArgument = function(buffer, type, strict) { + var osctype; + osctype = exports.typeStringToOscTypeCode(type); + if (osctype != null) { + return oscTypeCodes[osctype].split(buffer, strict); + } else { + throw new Error("I don't understand how I'm supposed to unpack " + type); + } + }; + + exports.toOscArgument = function(value, type, strict) { + var osctype; + osctype = exports.typeStringToOscTypeCode(type); + if (osctype != null) { + return oscTypeCodes[osctype].toArg(value, strict); + } else { + throw new Error("I don't know how to pack " + type); + } + }; + + exports.fromOscMessage = function(buffer, strict) { + var address, arg, args, arrayStack, built, j, len, ref, ref1, type, typeString, types; + ref = exports.splitOscString(buffer, strict), address = ref.string, buffer = ref.rest; + if (strict && address[0] !== '/') { + throw StrictError('addresses must start with /'); + } + if (!buffer.length) { + return { + address: address, + args: [] + }; + } + ref1 = exports.splitOscString(buffer, strict), types = ref1.string, buffer = ref1.rest; + if (types[0] !== ',') { + if (strict) { + throw StrictError('Argument lists must begin with ,'); + } + return { + address: address, + args: [] + }; + } + types = types.slice(1, +types.length + 1 || 9e9); + args = []; + arrayStack = [args]; + for (j = 0, len = types.length; j < len; j++) { + type = types[j]; + if (type === '[') { + arrayStack.push([]); + continue; + } + if (type === ']') { + if (arrayStack.length <= 1) { + if (strict) { + throw new StrictError("Mismatched ']' character."); + } + } else { + built = arrayStack.pop(); + arrayStack[arrayStack.length - 1].push({ + type: 'array', + value: built + }); + } + continue; + } + typeString = exports.oscTypeCodeToTypeString(type); + if (typeString == null) { + throw new Error("I don't understand the argument code " + type); + } + arg = exports.splitOscArgument(buffer, typeString, strict); + if (arg != null) { + buffer = arg.rest; + } + arrayStack[arrayStack.length - 1].push({ + type: typeString, + value: arg != null ? arg.value : void 0 + }); + } + if (arrayStack.length !== 1 && strict) { + throw new StrictError("Mismatched '[' character"); + } + return { + address: address, + args: args, + oscType: "message" + }; + }; + + exports.fromOscBundle = function(buffer, strict) { + var bundleTag, convertedElems, ref, ref1, timetag; + ref = exports.splitOscString(buffer, strict), bundleTag = ref.string, buffer = ref.rest; + if (bundleTag !== "\#bundle") { + throw new Error("osc-bundles must begin with \#bundle"); + } + ref1 = exports.splitTimetag(buffer), timetag = ref1.timetag, buffer = ref1.rest; + convertedElems = mapBundleList(buffer, function(buffer) { + return exports.fromOscPacket(buffer, strict); + }); + return { + timetag: timetag, + elements: convertedElems, + oscType: "bundle" + }; + }; + + exports.fromOscPacket = function(buffer, strict) { + if (isOscBundleBuffer(buffer, strict)) { + return exports.fromOscBundle(buffer, strict); + } else { + return exports.fromOscMessage(buffer, strict); + } + }; + + getArrayArg = function(arg) { + if (IsArray(arg)) { + return arg; + } else if (((arg != null ? arg.type : void 0) === "array") && (IsArray(arg != null ? arg.value : void 0))) { + return arg.value; + } else if ((arg != null) && (arg.type == null) && (IsArray(arg.value))) { + return arg.value; + } else { + return null; + } + }; + + toOscTypeAndArgs = function(argList, strict) { + var arg, buff, j, len, oscargs, osctype, ref, thisArgs, thisType, typeCode, value; + osctype = ""; + oscargs = []; + for (j = 0, len = argList.length; j < len; j++) { + arg = argList[j]; + if ((getArrayArg(arg)) != null) { + ref = toOscTypeAndArgs(getArrayArg(arg), strict), thisType = ref[0], thisArgs = ref[1]; + osctype += "[" + thisType + "]"; + oscargs = oscargs.concat(thisArgs); + continue; + } + typeCode = exports.argToTypeCode(arg, strict); + if (typeCode != null) { + value = arg != null ? arg.value : void 0; + if (value === void 0) { + value = arg; + } + buff = exports.toOscArgument(value, exports.oscTypeCodeToTypeString(typeCode), strict); + if (buff != null) { + oscargs.push(buff); + osctype += typeCode; + } + } + } + return [osctype, oscargs]; + }; + + exports.toOscMessage = function(message, strict) { + var address, allArgs, args, old_arg, oscaddr, oscargs, osctype, ref; + address = (message != null ? message.address : void 0) != null ? message.address : message; + if (typeof address !== "string") { + throw new Error("message must contain an address"); + } + args = message != null ? message.args : void 0; + if (args === void 0) { + args = []; + } + if (!IsArray(args)) { + old_arg = args; + args = []; + args[0] = old_arg; + } + oscaddr = exports.toOscString(address, strict); + ref = toOscTypeAndArgs(args, strict), osctype = ref[0], oscargs = ref[1]; + osctype = "," + osctype; + allArgs = exports.concat(oscargs); + osctype = exports.toOscString(osctype); + return exports.concat([oscaddr, osctype, allArgs]); + }; + + exports.toOscBundle = function(bundle, strict) { + var allElems, buff, e, elem, elements, elemstr, error, j, len, oscBundleTag, oscElems, oscTimeTag, ref, ref1, size, timetag; + if (strict && ((bundle != null ? bundle.timetag : void 0) == null)) { + throw StrictError("bundles must have timetags."); + } + timetag = (ref = bundle != null ? bundle.timetag : void 0) != null ? ref : new Date(); + elements = (ref1 = bundle != null ? bundle.elements : void 0) != null ? ref1 : []; + if (!IsArray(elements)) { + elemstr = elements; + elements = []; + elements.push(elemstr); + } + oscBundleTag = exports.toOscString("\#bundle"); + oscTimeTag = exports.toTimetagBuffer(timetag); + oscElems = []; + for (j = 0, len = elements.length; j < len; j++) { + elem = elements[j]; + try { + buff = exports.toOscPacket(elem, strict); + size = exports.toIntegerBuffer(buff.length); + oscElems.push(exports.concat([size, buff])); + } catch (error) { + e = error; + null; + } + } + allElems = exports.concat(oscElems); + return exports.concat([oscBundleTag, oscTimeTag, allElems]); + }; + + exports.toOscPacket = function(bundleOrMessage, strict) { + if ((bundleOrMessage != null ? bundleOrMessage.oscType : void 0) != null) { + if (bundleOrMessage.oscType === "bundle") { + return exports.toOscBundle(bundleOrMessage, strict); + } + return exports.toOscMessage(bundleOrMessage, strict); + } + if (((bundleOrMessage != null ? bundleOrMessage.timetag : void 0) != null) || ((bundleOrMessage != null ? bundleOrMessage.elements : void 0) != null)) { + return exports.toOscBundle(bundleOrMessage, strict); + } + return exports.toOscMessage(bundleOrMessage, strict); + }; + + exports.applyMessageTranformerToBundle = function(transform) { + return function(buffer) { + var bundleTagBuffer, copyIndex, elem, elems, j, k, len, len1, lengthBuff, outBuffer, ref, string, timetagBuffer, totalLength; + ref = exports.splitOscString(buffer), string = ref.string, buffer = ref.rest; + if (string !== "\#bundle") { + throw new Error("osc-bundles must begin with \#bundle"); + } + bundleTagBuffer = exports.toOscString(string); + timetagBuffer = buffer.slice(0, 8); + buffer = buffer.slice(8, buffer.length); + elems = mapBundleList(buffer, function(buffer) { + return exports.applyTransform(buffer, transform, exports.applyMessageTranformerToBundle(transform)); + }); + totalLength = bundleTagBuffer.length + timetagBuffer.length; + for (j = 0, len = elems.length; j < len; j++) { + elem = elems[j]; + totalLength += 4 + elem.length; + } + outBuffer = new Buffer(totalLength); + bundleTagBuffer.copy(outBuffer, 0); + timetagBuffer.copy(outBuffer, bundleTagBuffer.length); + copyIndex = bundleTagBuffer.length + timetagBuffer.length; + for (k = 0, len1 = elems.length; k < len1; k++) { + elem = elems[k]; + lengthBuff = exports.toIntegerBuffer(elem.length); + lengthBuff.copy(outBuffer, copyIndex); + copyIndex += 4; + elem.copy(outBuffer, copyIndex); + copyIndex += elem.length; + } + return outBuffer; + }; + }; + + exports.applyTransform = function(buffer, mTransform, bundleTransform) { + if (bundleTransform == null) { + bundleTransform = exports.applyMessageTranformerToBundle(mTransform); + } + if (isOscBundleBuffer(buffer)) { + return bundleTransform(buffer); + } else { + return mTransform(buffer); + } + }; + + exports.addressTransform = function(transform) { + return function(buffer) { + var ref, rest, string; + ref = exports.splitOscString(buffer), string = ref.string, rest = ref.rest; + string = transform(string); + return exports.concat([exports.toOscString(string), rest]); + }; + }; + + exports.messageTransform = function(transform) { + return function(buffer) { + var message; + message = exports.fromOscMessage(buffer); + return exports.toOscMessage(transform(message)); + }; + }; + + IsArray = Array.isArray; + + StrictError = function(str) { + return new Error("Strict Error: " + str); + }; + + padding = function(str) { + var bufflength; + bufflength = Buffer.byteLength(str); + return 4 - (bufflength % 4); + }; + + isOscBundleBuffer = function(buffer, strict) { + var string; + string = exports.splitOscString(buffer, strict).string; + return string === "\#bundle"; + }; + + mapBundleList = function(buffer, func) { + var e, elem, elems, j, len, nonNullElems, size, thisElemBuffer; + elems = (function() { + var error, ref, results; + results = []; + while (buffer.length) { + ref = exports.splitInteger(buffer), size = ref.integer, buffer = ref.rest; + if (size > buffer.length) { + throw new Error("Invalid bundle list: size of element is bigger than buffer"); + } + thisElemBuffer = buffer.slice(0, size); + buffer = buffer.slice(size, buffer.length); + try { + results.push(func(thisElemBuffer)); + } catch (error) { + e = error; + results.push(null); + } + } + return results; + })(); + nonNullElems = []; + for (j = 0, len = elems.length; j < len; j++) { + elem = elems[j]; + if (elem != null) { + nonNullElems.push(elem); + } + } + return nonNullElems; + }; + +}).call(this);