Port = function (options) {
this.options = options || {};
this.on("data", this.decodeOSC.bind(this));
}n/a
Relay = function (port1, port2, options) {
var o = this.options = options || {};
o.raw = false;
this.port1 = port1;
this.port2 = port2;
this.listen();
}n/a
SLIPPort = function (options) {
var that = this;
var o = this.options = options || {};
o.useSLIP = o.useSLIP === undefined ? true : o.useSLIP;
this.decoder = new slip.Decoder({
onMessage: this.decodeOSC.bind(this),
onError: function (err) {
that.emit("error", err);
}
});
var decodeHandler = o.useSLIP ? this.decodeSLIPData : this.decodeOSC;
this.on("data", decodeHandler.bind(this));
}n/a
SerialPort = function (options) {
this.on("open", this.listen.bind(this));
osc.SLIPPort.call(this, options);
this.options.bitrate = this.options.bitrate || 9600;
this.serialPort = options.serialPort;
if (this.serialPort) {
this.emit("open", this.serialPort);
}
}...
}
}
```
#### Connecting to the serial port and listening for OSC messages
```javascript
// Instantiate a new OSC Serial Port.
var serialPort = new osc.SerialPort({
devicePath: "/dev/cu.usbmodem22131"
});
// Listen for the message event and map the OSC message to the synth.
serialPort.on("message", function (oscMsg) {
console.log("An OSC message was received!", oscMsg);
});
...TCPSocketPort = function (options) {
osc.SLIPPort.call(this, options);
var o = this.options;
o.localAddress = o.localAddress || "127.0.0.1";
o.localPort = o.localPort !== undefined ? o.localPort : 57121;
this.on("open", this.listen.bind(this));
this.socket = options.socket;
if (this.socket) {
this.emit("open", this.socket);
}
}n/a
UDPPort = function (options) {
osc.Port.call(this, options);
this.options.localAddress = this.options.localAddress || "127.0.0.1";
this.options.localPort = this.options.localPort !== undefined ?
this.options.localPort : 57121;
this.options.remoteAddress = this.options.remoteAddress || "127.0.0.1";
this.options.remotePort = this.options.remotePort !== undefined ?
this.options.remotePort : 57121;
this.on("open", this.listen.bind(this));
this.socket = options.socket;
if (this.socket) {
this.emit("open", this.socket);
}
}...
</tr>
</table>
#### Sample Code
```javascript
// Create an osc.js UDP Port listening on port 57121.
var udpPort = new osc.UDPPort({
localAddress: "0.0.0.0",
localPort: 57121
});
// Listen for incoming OSC bundles.
udpPort.on("bundle", function (oscBundle, timeTag, info) {
console.log("An OSC bundle just arrived for time tag", timeTag, ":", oscBundle);
...function WebSocket(address, protocols, options) {
if (this instanceof WebSocket === false) {
return new WebSocket(address, protocols, options);
}
EventEmitter.call(this);
if (protocols && !Array.isArray(protocols) && 'object' === typeof protocols) {
// accept the "options" Object as the 2nd argument
options = protocols;
protocols = null;
}
if ('string' === typeof protocols) {
protocols = [ protocols ];
}
if (!Array.isArray(protocols)) {
protocols = [];
}
this._socket = null;
this._ultron = null;
this._closeReceived = false;
this.bytesReceived = 0;
this.readyState = null;
this.supports = {};
this.extensions = {};
this._binaryType = 'nodebuffer';
if (Array.isArray(address)) {
initAsServerClient.apply(this, address.concat(options));
} else {
initAsClient.apply(this, [address, protocols, options]);
}
}...
};
var p = osc.WebSocketPort.prototype = Object.create(osc.Port.prototype);
p.constructor = osc.WebSocketPort;
p.open = function () {
if (!this.socket || this.socket.readyState > 1) {
this.socket = new osc.WebSocket(this.options.url);
}
osc.WebSocketPort.setupSocketForBinary(this.socket);
var that = this;
this.socket.onopen = function () {
that.emit("open", that.socket);
...function Receiver(extensions, maxPayload) {
if (this instanceof Receiver === false) {
throw new TypeError("Classes can't be function-called");
}
if(typeof extensions==='number'){
maxPayload=extensions;
extensions={};
}
// memory pool for fragmented messages
var fragmentedPoolPrevUsed = -1;
this.fragmentedBufferPool = new BufferPool(1024, function(db, length) {
return db.used + length;
}, function(db) {
return fragmentedPoolPrevUsed = fragmentedPoolPrevUsed >= 0 ?
Math.ceil((fragmentedPoolPrevUsed + db.used) / 2) :
db.used;
});
// memory pool for unfragmented messages
var unfragmentedPoolPrevUsed = -1;
this.unfragmentedBufferPool = new BufferPool(1024, function(db, length) {
return db.used + length;
}, function(db) {
return unfragmentedPoolPrevUsed = unfragmentedPoolPrevUsed >= 0 ?
Math.ceil((unfragmentedPoolPrevUsed + db.used) / 2) :
db.used;
});
this.extensions = extensions || {};
this.maxPayload = maxPayload || 0;
this.currentPayloadLength = 0;
this.state = {
activeFragmentedOperation: null,
lastFragment: false,
masked: false,
opcode: 0,
fragmentedOperation: false
};
this.overflow = [];
this.headerBuffer = new Buffer(10);
this.expectOffset = 0;
this.expectBuffer = null;
this.expectHandler = null;
this.currentMessage = [];
this.currentMessageLength = 0;
this.messageHandlers = [];
this.expectHeader(2, this.processPacket);
this.dead = false;
this.processing = false;
this.onerror = function() {};
this.ontext = function() {};
this.onbinary = function() {};
this.onclose = function() {};
this.onping = function() {};
this.onpong = function() {};
}n/a
function Sender(socket, extensions) {
if (this instanceof Sender === false) {
throw new TypeError("Classes can't be function-called");
}
events.EventEmitter.call(this);
this._socket = socket;
this.extensions = extensions || {};
this.firstFragment = true;
this.compress = false;
this.messageHandlers = [];
this.processing = false;
}n/a
function WebSocketServer(options, callback) {
if (this instanceof WebSocketServer === false) {
return new WebSocketServer(options, callback);
}
events.EventEmitter.call(this);
options = new Options({
host: '0.0.0.0',
port: null,
server: null,
verifyClient: null,
handleProtocols: null,
path: null,
noServer: false,
disableHixie: false,
clientTracking: true,
perMessageDeflate: true,
maxPayload: 100 * 1024 * 1024
}).merge(options);
if (!options.isDefinedAndNonNull('port') && !options.isDefinedAndNonNull('server') && !options.value.noServer) {
throw new TypeError('`port` or a `server` must be provided');
}
var self = this;
if (options.isDefinedAndNonNull('port')) {
this._server = http.createServer(function (req, res) {
var body = http.STATUS_CODES[426];
res.writeHead(426, {
'Content-Length': body.length,
'Content-Type': 'text/plain'
});
res.end(body);
});
this._server.allowHalfOpen = false;
this._server.listen(options.value.port, options.value.host, callback);
this._closeServer = function() { if (self._server) self._server.close(); };
}
else if (options.value.server) {
this._server = options.value.server;
if (options.value.path) {
// take note of the path, to avoid collisions when multiple websocket servers are
// listening on the same http server
if (this._server._webSocketPaths && options.value.server._webSocketPaths[options.value.path]) {
throw new Error('two instances of WebSocketServer cannot listen on the same http server path');
}
if (typeof this._server._webSocketPaths !== 'object') {
this._server._webSocketPaths = {};
}
this._server._webSocketPaths[options.value.path] = 1;
}
}
if (this._server) {
this._onceServerListening = function() { self.emit('listening'); };
this._server.once('listening', this._onceServerListening);
}
if (typeof this._server != 'undefined') {
this._onServerError = function(error) { self.emit('error', error) };
this._server.on('error', this._onServerError);
this._onServerUpgrade = function(req, socket, upgradeHead) {
//copy upgradeHead to avoid retention of large slab buffers used in node core
var head = new Buffer(upgradeHead.length);
upgradeHead.copy(head);
self.handleUpgrade(req, socket, head, function(client) {
self.emit('connection'+req.url, client);
self.emit('connection', client);
});
};
this._server.on('upgrade', this._onServerUpgrade);
}
this.options = options.value;
this.path = options.value.path;
this.clients = [];
}n/a
WebSocketPort = function (options) {
osc.Port.call(this, options);
this.on("open", this.listen.bind(this));
this.socket = options.socket;
if (this.socket) {
if (this.socket.readyState === 1) {
osc.WebSocketPort.setupSocketForBinary(this.socket);
this.emit("open", this.socket);
} else {
this.open();
}
}
}...
</head>
<body></body>
</html>
```
##### Creating an OSC Web Socket Port object:
```javascript
var oscPort = new osc.WebSocketPort({
url: "ws://localhost:8081" // URL to your Web Socket server.
});
```
##### Opening the Port:
```javascript
oscPort.open();
...addDataPart = function (dataPart, dataCollection) {
dataCollection.parts.push(dataPart);
dataCollection.byteLength += dataPart.length;
}...
}
var type = arg.type,
writer = osc.argumentTypes[type].writer;
if (writer) {
var data = osc[writer](arg.value);
osc.addDataPart(data, dataCollection);
}
return arg.type;
};
// Unsupported, non-API function.
osc.collectArguments = function (args, options, dataCollection) {
...annotateArguments = function (args) {
var annotated = [];
for (var i = 0; i < args.length; i++) {
var arg = args[i],
msgArg;
if (typeof (arg) === "object" && arg.type && arg.value !== undefined) {
// We've got an explicitly typed argument.
msgArg = arg;
} else if (osc.isArray(arg)) {
// We've got an array of arguments,
// so they each need to be inferred and expanded.
msgArg = osc.annotateArguments(arg);
} else {
var oscType = osc.inferTypeForArgument(arg);
msgArg = {
type: oscType,
value: arg
};
}
annotated.push(msgArg);
}
return annotated;
}...
dataCollection = dataCollection || {
byteLength: 0,
parts: []
};
if (!options.metadata) {
args = osc.annotateArguments(args);
}
var typeTagString = ",",
currPartIdx = dataCollection.parts.length;
for (var i = 0; i < args.length; i++) {
var arg = args[i];
...byteArray = function (obj) {
if (obj instanceof Uint8Array) {
return obj;
}
var buf = obj.buffer ? obj.buffer : obj;
if (!(buf instanceof ArrayBuffer) && (typeof buf.length === "undefined" || typeof buf === "string")) {
throw new Error("Can't wrap a non-array-like object as Uint8Array. Object was: " +
JSON.stringify(obj, null, 2));
}
// TODO gh-39: This is a potentially unsafe algorithm;
// if we're getting anything other than a TypedArrayView (such as a DataView),
// we really need to determine the range of the view it is viewing.
return new Uint8Array(buf);
}...
/**
* Writes a raw collection of bytes to a new ArrayBuffer.
*
* @param {Array-like} data a collection of octets
* @return {ArrayBuffer} a buffer containing the OSC-formatted blob
*/
osc.writeBlob = function (data) {
data = osc.byteArray(data);
var len = data.byteLength,
paddedLen = (len + 3) & ~0x03,
offset = 4, // Extra 4 bytes is for the size.
blobLen = paddedLen + offset,
arr = new Uint8Array(blobLen),
dv = new DataView(arr.buffer);
...collectArguments = function (args, options, dataCollection) {
if (!osc.isArray(args)) {
args = typeof args === "undefined" ? [] : [args];
}
dataCollection = dataCollection || {
byteLength: 0,
parts: []
};
if (!options.metadata) {
args = osc.annotateArguments(args);
}
var typeTagString = ",",
currPartIdx = dataCollection.parts.length;
for (var i = 0; i < args.length; i++) {
var arg = args[i];
typeTagString += osc.writeArgument(arg, dataCollection);
}
var typeData = osc.writeString(typeTagString);
dataCollection.byteLength += typeData.byteLength;
dataCollection.parts.splice(currPartIdx, 0, typeData);
return dataCollection;
}...
* Writes the specified arguments.
*
* @param {Array} args an array of arguments
* @param {Object} options options for writing
* @return {Uint8Array} a buffer containing the OSC-formatted argument type tag and values
*/
osc.writeArguments = function (args, options) {
var argCollection = osc.collectArguments(args, options);
return osc.joinParts(argCollection);
};
// Unsupported, non-API function.
osc.joinParts = function (dataCollection) {
var buf = new Uint8Array(dataCollection.byteLength),
parts = dataCollection.parts,
...collectBundlePackets = function (bundle, options, dataCollection) {
dataCollection = dataCollection || {
byteLength: 0,
parts: []
};
osc.addDataPart(osc.writeString("#bundle"), dataCollection);
osc.addDataPart(osc.writeTimeTag(bundle.timeTag), dataCollection);
for (var i = 0; i < bundle.packets.length; i++) {
var packet = bundle.packets[i],
collector = packet.address ? osc.collectMessageParts : osc.collectBundlePackets,
packetCollection = collector(packet, options);
dataCollection.byteLength += packetCollection.byteLength;
osc.addDataPart(osc.writeInt32(packetCollection.byteLength), dataCollection);
dataCollection.parts = dataCollection.parts.concat(packetCollection.parts);
}
return dataCollection;
}...
osc.writeBundle = function (bundle, options) {
if (!osc.isValidBundle(bundle)) {
throw new Error("An OSC bundle must contain 'timeTag' and 'packets' properties. " +
"Bundle was: " + JSON.stringify(bundle, null, 2));
}
options = options || osc.defaults;
var bundleCollection = osc.collectBundlePackets(bundle, options);
return osc.joinParts(bundleCollection);
};
osc.isValidBundle = function (bundle) {
return bundle.timeTag !== undefined && bundle.packets !== undefined;
};
...collectMessageParts = function (msg, options, dataCollection) {
dataCollection = dataCollection || {
byteLength: 0,
parts: []
};
osc.addDataPart(osc.writeString(msg.address), dataCollection);
return osc.collectArguments(msg.args, options, dataCollection);
}...
options = options || osc.defaults;
if (!osc.isValidMessage(msg)) {
throw new Error("An OSC message must contain a valid address. Message was: " +
JSON.stringify(msg, null, 2));
}
var msgCollection = osc.collectMessageParts(msg, options);
return osc.joinParts(msgCollection);
};
osc.isValidMessage = function (msg) {
return msg.address && msg.address.indexOf("/") === 0;
};
...copyByteArray = function (source, target, offset) {
if (osc.isTypedArrayView(source) && osc.isTypedArrayView(target)) {
target.set(source, offset);
} else {
var start = offset === undefined ? 0 : offset,
len = Math.min(target.length - offset, source.length);
for (var i = 0, j = start; i < len; i++, j++) {
target[j] = source[i];
}
}
return target;
}...
osc.joinParts = function (dataCollection) {
var buf = new Uint8Array(dataCollection.byteLength),
parts = dataCollection.parts,
offset = 0;
for (var i = 0; i < parts.length; i++) {
var part = parts[i];
osc.copyByteArray(part, buf, offset);
offset += part.length;
}
return buf;
};
// Unsupported, non-API function.
...dataView = function (obj, offset, length) {
if (obj.buffer) {
return new DataView(obj.buffer, offset, length);
}
if (obj instanceof ArrayBuffer) {
return new DataView(obj, offset, length);
}
return new DataView(new Uint8Array(obj), offset, length);
}...
* @param {Object} [options] read options
* @param {Object} [offsetState] an offsetState object that stores the current offset into dv
* @return {Object} the OSC message, formatted as a JavaScript object containing "address" and "args" properties
*/
osc.readMessage = function (data, options, offsetState) {
options = options || osc.defaults;
var dv = osc.dataView(data, data.byteOffset, data.byteLength);
offsetState = offsetState || {
idx: 0
};
var address = osc.readString(dv, offsetState);
return osc.readMessageContents(address, dv, options, offsetState);
};
...fireBundleEvents = function (port, bundle, timeTag, packetInfo) {
port.emit("bundle", bundle, timeTag, packetInfo);
for (var i = 0; i < bundle.packets.length; i++) {
var packet = bundle.packets[i];
osc.firePacketEvents(port, packet, bundle.timeTag, packetInfo);
}
}...
"use strict";
// Unsupported, non-API function.
osc.firePacketEvents = function (port, packet, timeTag, packetInfo) {
if (packet.address) {
port.emit("message", packet, timeTag, packetInfo);
} else {
osc.fireBundleEvents(port, packet, timeTag, packetInfo);
}
};
// Unsupported, non-API function.
osc.fireBundleEvents = function (port, bundle, timeTag, packetInfo) {
port.emit("bundle", bundle, timeTag, packetInfo);
for (var i = 0; i < bundle.packets.length; i++) {
...fireClosedPortSendError = function (port, msg) {
msg = msg || "Can't send packets on a closed osc.Port object. Please open (or reopen) this Port by calling open().";
port.emit("error", msg);
}...
p.listen = function () {
osc.listenToTransport(this, chrome.serial, "connectionId");
};
p.sendRaw = function (encoded) {
if (!this.connectionId) {
osc.fireClosedPortSendError(this);
return;
}
var that = this;
// TODO gh-39: This is unsafe; we should only access the underlying
// buffer within the range of its view.
...firePacketEvents = function (port, packet, timeTag, packetInfo) {
if (packet.address) {
port.emit("message", packet, timeTag, packetInfo);
} else {
osc.fireBundleEvents(port, packet, timeTag, packetInfo);
}
}...
};
// Unsupported, non-API function.
osc.fireBundleEvents = function (port, bundle, timeTag, packetInfo) {
port.emit("bundle", bundle, timeTag, packetInfo);
for (var i = 0; i < bundle.packets.length; i++) {
var packet = bundle.packets[i];
osc.firePacketEvents(port, packet, bundle.timeTag, packetInfo);
}
};
osc.fireClosedPortSendError = function (port, msg) {
msg = msg || "Can't send packets on a closed osc.Port object. Please open (or reopen) this Port by calling open()."
;;
port.emit("error", msg);
...inferTypeForArgument = function (arg) {
var type = typeof arg;
// TODO: This is freaking hideous.
switch (type) {
case "boolean":
return arg ? "T" : "F";
case "string":
return "s";
case "number":
return "f";
case "undefined":
return "N";
case "object":
if (arg === null) {
return "N";
} else if (arg instanceof Uint8Array ||
arg instanceof ArrayBuffer) {
return "b";
} else if (typeof arg.high === "number" && typeof arg.low === "number") {
return "h";
}
break;
}
throw new Error("Can't infer OSC argument type for value: " +
JSON.stringify(arg, null, 2));
}...
// We've got an explicitly typed argument.
msgArg = arg;
} else if (osc.isArray(arg)) {
// We've got an array of arguments,
// so they each need to be inferred and expanded.
msgArg = osc.annotateArguments(arg);
} else {
var oscType = osc.inferTypeForArgument(arg);
msgArg = {
type: oscType,
value: arg
};
}
annotated.push(msgArg);
...isArray = function (obj) {
return obj && Object.prototype.toString.call(obj) === "[object Array]";
}...
typeTag += "]";
return typeTag;
};
osc.writeArgument = function (arg, dataCollection) {
if (osc.isArray(arg)) {
return osc.writeArrayArguments(arg, dataCollection);
}
var type = arg.type,
writer = osc.argumentTypes[type].writer;
if (writer) {
...isBuffer = function (obj) {
return osc.isBufferEnv && obj instanceof Buffer;
}...
*
* @param {Array-like or Array-wrapping} obj an array-like or array-wrapping object
* @returns {Buffer|Uint8Array} a buffer object
*/
// Unsupported, non-API function.
osc.nativeBuffer = function (obj) {
if (osc.isBufferEnv) {
return osc.isBuffer(obj) ? obj :
new Buffer(obj.buffer ? obj : new Uint8Array(obj));
}
return osc.isTypedArrayView(obj) ? obj : new Uint8Array(obj);
};
// Unsupported, non-API function
...isTypedArrayView = function (obj) {
return obj.buffer && obj.buffer instanceof ArrayBuffer;
}...
// Unsupported, non-API function.
osc.nativeBuffer = function (obj) {
if (osc.isBufferEnv) {
return osc.isBuffer(obj) ? obj :
new Buffer(obj.buffer ? obj : new Uint8Array(obj));
}
return osc.isTypedArrayView(obj) ? obj : new Uint8Array(obj);
};
// Unsupported, non-API function
osc.copyByteArray = function (source, target, offset) {
if (osc.isTypedArrayView(source) && osc.isTypedArrayView(target)) {
target.set(source, offset);
} else {
...isValidBundle = function (bundle) {
return bundle.timeTag !== undefined && bundle.packets !== undefined;
}...
* Writes an OSC bundle.
*
* @param {Object} a bundle object containing "timeTag" and "packets" properties
* @param {object} [options] write options
* @return {Uint8Array} an array of bytes containing the message
*/
osc.writeBundle = function (bundle, options) {
if (!osc.isValidBundle(bundle)) {
throw new Error("An OSC bundle must contain 'timeTag' and 'packets' properties. " +
"Bundle was: " + JSON.stringify(bundle, null, 2));
}
options = options || osc.defaults;
var bundleCollection = osc.collectBundlePackets(bundle, options);
...isValidMessage = function (msg) {
return msg.address && msg.address.indexOf("/") === 0;
}...
* @param {Object} msg a message object containing "address" and "args" properties
* @param {Object} [options] write options
* @return {Uint8Array} an array of bytes containing the OSC message
*/
osc.writeMessage = function (msg, options) {
options = options || osc.defaults;
if (!osc.isValidMessage(msg)) {
throw new Error("An OSC message must contain a valid address. Message was: " +
JSON.stringify(msg, null, 2));
}
var msgCollection = osc.collectMessageParts(msg, options);
return osc.joinParts(msgCollection);
};
...joinParts = function (dataCollection) {
var buf = new Uint8Array(dataCollection.byteLength),
parts = dataCollection.parts,
offset = 0;
for (var i = 0; i < parts.length; i++) {
var part = parts[i];
osc.copyByteArray(part, buf, offset);
offset += part.length;
}
return buf;
}...
*
* @param {Array} args an array of arguments
* @param {Object} options options for writing
* @return {Uint8Array} a buffer containing the OSC-formatted argument type tag and values
*/
osc.writeArguments = function (args, options) {
var argCollection = osc.collectArguments(args, options);
return osc.joinParts(argCollection);
};
// Unsupported, non-API function.
osc.joinParts = function (dataCollection) {
var buf = new Uint8Array(dataCollection.byteLength),
parts = dataCollection.parts,
offset = 0;
...jsToNTPTime = function (jsTime) {
var secs = jsTime / 1000,
secsWhole = Math.floor(secs),
secsFrac = secs - secsWhole,
ntpSecs = secsWhole + osc.SECS_70YRS,
ntpFracs = Math.round(osc.TWO_32 * secsFrac);
return [ntpSecs, ntpFracs];
}...
* values. The first represents the number of seconds since January 1, 1900; the second, fractions of a second.
* "Native" JavaScript timestamps are specified as a Number representing milliseconds since January 1, 1970.
*
* @param {Object} timeTag time tag object containing either a native JS timestamp (in ms) or a NTP timestamp pair
* @return {Uint8Array} raw bytes for the written time tag
*/
osc.writeTimeTag = function (timeTag) {
var raw = timeTag.raw ? timeTag.raw : osc.jsToNTPTime(timeTag.native),
arr = new Uint8Array(8), // Two Unit32s.
dv = new DataView(arr.buffer);
osc.writeInt32(raw[0], dv, 0);
osc.writeInt32(raw[1], dv, 4);
return arr;
...nativeBuffer = function (obj) {
if (osc.isBufferEnv) {
return osc.isBuffer(obj) ? obj :
new Buffer(obj.buffer ? obj : new Uint8Array(obj));
}
return osc.isTypedArrayView(obj) ? obj : new Uint8Array(obj);
}...
var p = osc.Port.prototype = Object.create(EventEmitter.prototype);
p.constructor = osc.Port;
p.send = function (oscPacket) {
var args = Array.prototype.slice.call(arguments),
encoded = this.encodeOSC(oscPacket),
buf = osc.nativeBuffer(encoded);
args[0] = buf;
this.sendRaw.apply(this, args);
};
p.encodeOSC = function (packet) {
// TODO gh-39: This is unsafe; we should only access the underlying
...ntpToJSTime = function (secs1900, frac) {
var secs1970 = secs1900 - osc.SECS_70YRS,
decimals = frac / osc.TWO_32,
msTime = (secs1970 + decimals) * 1000;
return msTime;
}...
* @param {DataView} dv the DataView instance to read from
* @param {Object} offsetState an offset state object containing the current index into dv
* @param {Object} a time tag object containing both the raw NTP as well as the converted native (i.e. JS/UNIX) time
*/
osc.readTimeTag = function (dv, offsetState) {
var secs1900 = osc.readPrimitive(dv, "getUint32", 4, offsetState),
frac = osc.readPrimitive(dv, "getUint32", 4, offsetState),
native = (secs1900 === 0 && frac === 1) ? Date.now() : osc.ntpToJSTime(secs1900, frac);
return {
raw: [secs1900, frac],
native: native
};
};
...readArgument = function (argType, typeTagString, dv, options, offsetState) {
var typeSpec = osc.argumentTypes[argType];
if (!typeSpec) {
throw new Error("'" + argType + "' is not a valid OSC type tag. Type tag string was: " + typeTagString);
}
var argReader = typeSpec.reader,
arg = osc[argReader](dv, offsetState);
if (options.metadata) {
arg = {
type: argType,
value: arg
};
}
return arg;
}...
"without a matching close array tag ('[]'). Type tag was: " + typeTagString);
}
var typesInArray = fromArrayOpen.slice(0, endArrayIdx);
arg = osc.readArgumentsIntoArray([], typesInArray, typeTagString, dv, options, offsetState);
i += endArrayIdx + 2;
} else {
arg = osc.readArgument(argType, typeTagString, dv, options, offsetState);
i++;
}
arr.push(arg);
}
return arr;
...readArguments = function (dv, options, offsetState) {
var typeTagString = osc.readString(dv, offsetState);
if (typeTagString.indexOf(",") !== 0) {
// Despite what the OSC 1.0 spec says,
// it just doesn't make sense to handle messages without type tags.
// scsynth appears to read such messages as if they have a single
// Uint8 argument. sclang throws an error if the type tag is omitted.
throw new Error("A malformed type tag string was found while reading " +
"the arguments of an OSC message. String was: " +
typeTagString, " at offset: " + offsetState.idx);
}
var argTypes = typeTagString.substring(1).split(""),
args = [];
osc.readArgumentsIntoArray(args, argTypes, typeTagString, dv, options, offsetState);
return args;
}...
// Unsupported, non-API function.
osc.readMessageContents = function (address, dv, options, offsetState) {
if (address.indexOf("/") !== 0) {
throw new Error("A malformed OSC address was found while reading " +
"an OSC message. String was: " + address);
}
var args = osc.readArguments(dv, options, offsetState);
return {
address: address,
args: args.length === 1 && options.unpackSingleArgs ? args[0] : args
};
};
...readArgumentsIntoArray = function (arr, argTypes, typeTagString, dv, options, offsetState) {
var i = 0;
while (i < argTypes.length) {
var argType = argTypes[i],
arg;
if (argType === "[") {
var fromArrayOpen = argTypes.slice(i + 1),
endArrayIdx = fromArrayOpen.indexOf("]");
if (endArrayIdx < 0) {
throw new Error("Invalid argument type tag: an open array type tag ('[') was found " +
"without a matching close array tag ('[]'). Type tag was: " + typeTagString);
}
var typesInArray = fromArrayOpen.slice(0, endArrayIdx);
arg = osc.readArgumentsIntoArray([], typesInArray, typeTagString, dv, options, offsetState);
i += endArrayIdx + 2;
} else {
arg = osc.readArgument(argType, typeTagString, dv, options, offsetState);
i++;
}
arr.push(arg);
}
return arr;
}...
"the arguments of an OSC message. String was: " +
typeTagString, " at offset: " + offsetState.idx);
}
var argTypes = typeTagString.substring(1).split(""),
args = [];
osc.readArgumentsIntoArray(args, argTypes, typeTagString, dv, options, offsetState
);
return args;
};
// Unsupported, non-API function.
osc.readArgument = function (argType, typeTagString, dv, options, offsetState) {
var typeSpec = osc.argumentTypes[argType];
...readBlob = function (dv, offsetState) {
var len = osc.readInt32(dv, offsetState),
paddedLen = (len + 3) & ~0x03,
blob = new Uint8Array(dv.buffer, offsetState.idx, len);
offsetState.idx += paddedLen;
return blob;
}n/a
readBundle = function (dv, options, offsetState) {
return osc.readPacket(dv, options, offsetState);
}n/a
readBundleContents = function (dv, options, offsetState, len) {
var timeTag = osc.readTimeTag(dv, offsetState),
packets = [];
while (offsetState.idx < len) {
var packetSize = osc.readInt32(dv, offsetState),
packetLen = offsetState.idx + packetSize,
packet = osc.readPacket(dv, options, offsetState, packetLen);
packets.push(packet);
}
return {
timeTag: timeTag,
packets: packets
};
}...
idx: 0
};
var header = osc.readString(dv, offsetState),
firstChar = header[0];
if (firstChar === "#") {
return osc.readBundleContents(dv, options, offsetState, len);
} else if (firstChar === "/") {
return osc.readMessageContents(header, dv, options, offsetState);
}
throw new Error("The header of an OSC packet didn't contain an OSC address or a #bundle string." +
" Header was: " + header);
};
...readChar32 = function (dv, offsetState) {
var charCode = osc.readPrimitive(dv, "getUint32", 4, offsetState);
return String.fromCharCode(charCode);
}n/a
readColor = function (dv, offsetState) {
var bytes = new Uint8Array(dv.buffer, offsetState.idx, 4),
alpha = bytes[3] / 255;
offsetState.idx += 4;
return {
r: bytes[0],
g: bytes[1],
b: bytes[2],
a: alpha
};
}n/a
readFalse = function () {
return false;
}n/a
readFloat32 = function (dv, offsetState) {
return osc.readPrimitive(dv, "getFloat32", 4, offsetState);
}n/a
readFloat64 = function (dv, offsetState) {
return osc.readPrimitive(dv, "getFloat64", 8, offsetState);
}n/a
readImpulse = function () {
return 1.0;
}n/a
readInt32 = function (dv, offsetState) {
return osc.readPrimitive(dv, "getInt32", 4, offsetState);
}...
* Reads an OSC blob ("b") (i.e. a Uint8Array).
*
* @param {DataView} dv a DataView instance to read from
* @param {Object} offsetState an offsetState object used to store the current offset index into dv
* @return {Uint8Array} the data that was read
*/
osc.readBlob = function (dv, offsetState) {
var len = osc.readInt32(dv, offsetState),
paddedLen = (len + 3) & ~0x03,
blob = new Uint8Array(dv.buffer, offsetState.idx, len);
offsetState.idx += paddedLen;
return blob;
};
...readInt64 = function (dv, offsetState) {
var high = osc.readPrimitive(dv, "getInt32", 4, offsetState),
low = osc.readPrimitive(dv, "getInt32", 4, offsetState);
if (Long) {
return new Long(low, high);
} else {
return {
high: high,
low: low,
unsigned: false
};
}
}n/a
readMIDIBytes = function (dv, offsetState) {
var midi = new Uint8Array(dv.buffer, offsetState.idx, 4);
offsetState.idx += 4;
return midi;
}n/a
readMessage = function (data, options, offsetState) {
options = options || osc.defaults;
var dv = osc.dataView(data, data.byteOffset, data.byteLength);
offsetState = offsetState || {
idx: 0
};
var address = osc.readString(dv, offsetState);
return osc.readMessageContents(address, dv, options, offsetState);
}n/a
readMessageContents = function (address, dv, options, offsetState) {
if (address.indexOf("/") !== 0) {
throw new Error("A malformed OSC address was found while reading " +
"an OSC message. String was: " + address);
}
var args = osc.readArguments(dv, options, offsetState);
return {
address: address,
args: args.length === 1 && options.unpackSingleArgs ? args[0] : args
};
}...
var dv = osc.dataView(data, data.byteOffset, data.byteLength);
offsetState = offsetState || {
idx: 0
};
var address = osc.readString(dv, offsetState);
return osc.readMessageContents(address, dv, options, offsetState);
};
// Unsupported, non-API function.
osc.readMessageContents = function (address, dv, options, offsetState) {
if (address.indexOf("/") !== 0) {
throw new Error("A malformed OSC address was found while reading " +
"an OSC message. String was: " + address);
...readNull = function () {
return null;
}n/a
readPacket = function (data, options, offsetState, len) {
var dv = osc.dataView(data, data.byteOffset, data.byteLength);
len = len === undefined ? dv.byteLength : len;
offsetState = offsetState || {
idx: 0
};
var header = osc.readString(dv, offsetState),
firstChar = header[0];
if (firstChar === "#") {
return osc.readBundleContents(dv, options, offsetState, len);
} else if (firstChar === "/") {
return osc.readMessageContents(header, dv, options, offsetState);
}
throw new Error("The header of an OSC packet didn't contain an OSC address or a #bundle string." +
" Header was: " + header);
}...
they should be caught and handled using
<code>try</code>/<code>catch</code>.
```javascript
var msg;
try {
msg = osc.readPacket(rawPacket);
} catch (error) {
console.log("An error occurred: ", error.message);
}
```
The osc.js Low-Level API
------------------------
...readPrimitive = function (dv, readerName, numBytes, offsetState) {
var val = dv[readerName](offsetState.idx, false);
offsetState.idx += numBytes;
return val;
}...
* Reads an OSC int32 ("i") value.
*
* @param {DataView} dv a DataView containing the raw bytes
* @param {Object} offsetState an offsetState object used to store the current offset index into dv
* @return {Number} the number that was read
*/
osc.readInt32 = function (dv, offsetState) {
return osc.readPrimitive(dv, "getInt32", 4, offsetState);
};
/**
* Writes an OSC int32 ("i") value.
*
* @param {Number} val the number to write
* @param {DataView} [dv] a DataView instance to write the number into
...readString = function (dv, offsetState) {
var charCodes = [],
idx = offsetState.idx;
for (; idx < dv.byteLength; idx++) {
var charCode = dv.getUint8(idx);
if (charCode !== 0) {
charCodes.push(charCode);
} else {
idx++;
break;
}
}
// Round to the nearest 4-byte block.
idx = (idx + 3) & ~0x03;
offsetState.idx = idx;
return String.fromCharCode.apply(null, charCodes);
}...
*
* @param {DataView} dv a DataView instance to read from
* @param {Object} offsetState the offsetState object that stores the current offset into dv
* @param {Oobject} [options] read options
* @return {Array} an array of the OSC arguments that were read
*/
osc.readArguments = function (dv, options, offsetState) {
var typeTagString = osc.readString(dv, offsetState);
if (typeTagString.indexOf(",") !== 0) {
// Despite what the OSC 1.0 spec says,
// it just doesn't make sense to handle messages without type tags.
// scsynth appears to read such messages as if they have a single
// Uint8 argument. sclang throws an error if the type tag is omitted.
throw new Error("A malformed type tag string was found while reading " +
"the arguments of an OSC message. String was: " +
...readTimeTag = function (dv, offsetState) {
var secs1900 = osc.readPrimitive(dv, "getUint32", 4, offsetState),
frac = osc.readPrimitive(dv, "getUint32", 4, offsetState),
native = (secs1900 === 0 && frac === 1) ? Date.now() : osc.ntpToJSTime(secs1900, frac);
return {
raw: [secs1900, frac],
native: native
};
}...
osc.isValidBundle = function (bundle) {
return bundle.timeTag !== undefined && bundle.packets !== undefined;
};
// Unsupported, non-API function.
osc.readBundleContents = function (dv, options, offsetState, len) {
var timeTag = osc.readTimeTag(dv, offsetState),
packets = [];
while (offsetState.idx < len) {
var packetSize = osc.readInt32(dv, offsetState),
packetLen = offsetState.idx + packetSize,
packet = osc.readPacket(dv, options, offsetState, packetLen);
...readTrue = function () {
return true;
}n/a
relay = function (from, to, eventName, sendFnName, transformFn, sendArgs) {
eventName = eventName || "message";
sendFnName = sendFnName || "send";
transformFn = transformFn || function () {};
sendArgs = sendArgs ? [null].concat(sendArgs) : [];
var listener = function (data) {
sendArgs[0] = data;
data = transformFn(data);
to[sendFnName].apply(to, sendArgs);
};
from.on(eventName, listener);
return {
eventName: eventName,
listener: listener
};
}...
};
// Unsupported, non-API function.
osc.relayPorts = function (from, to, o) {
var eventName = o.raw ? "raw" : "osc",
sendFnName = o.raw ? "sendRaw" : "send";
return osc.relay(from, to, eventName, sendFnName, o.transform);
};
// Unsupported, non-API function.
osc.stopRelaying = function (from, relaySpec) {
from.removeListener(relaySpec.eventName, relaySpec.listener);
};
...relayPorts = function (from, to, o) {
var eventName = o.raw ? "raw" : "osc",
sendFnName = o.raw ? "sendRaw" : "send";
return osc.relay(from, to, eventName, sendFnName, o.transform);
}...
};
p.listen = function () {
if (this.port1Spec && this.port2Spec) {
this.close();
}
this.port1Spec = osc.relayPorts(this.port1, this.port2, this.options);
this.port2Spec = osc.relayPorts(this.port2, this.port1, this.options);
// Bind port close listeners to ensure that the relay
// will stop forwarding messages if one of its ports close.
// Users are still responsible for closing the underlying ports
// if necessary.
var closeListener = this.close.bind(this);
...stopRelaying = function (from, relaySpec) {
from.removeListener(relaySpec.eventName, relaySpec.listener);
}...
// if necessary.
var closeListener = this.close.bind(this);
this.port1.on("close", closeListener);
this.port2.on("close", closeListener);
};
p.close = function () {
osc.stopRelaying(this.port1, this.port1Spec);
osc.stopRelaying(this.port2, this.port2Spec);
this.emit("close", this.port1, this.port2);
};
// If we're in a require-compatible environment, export ourselves.
if (typeof module !== "undefined" && module.exports) {
...timeTag = function (secs, now) {
secs = secs || 0;
now = now || Date.now();
var nowSecs = now / 1000,
nowWhole = Math.floor(nowSecs),
nowFracs = nowSecs - nowWhole,
secsWhole = Math.floor(secs),
secsFracs = secs - secsWhole,
fracs = nowFracs + secsFracs;
if (fracs > 1) {
var fracsWhole = Math.floor(fracs),
fracsFracs = fracs - fracsWhole;
secsWhole += fracsWhole;
fracs = fracsFracs;
}
var ntpSecs = nowWhole + secsWhole + osc.SECS_70YRS,
ntpFracs = Math.round(osc.TWO_32 * fracs);
return {
raw: [ntpSecs, ntpFracs]
};
}...
});
```
##### Sending OSC bundles:
```javascript
oscPort.on("ready", function () {
oscPort.send({
timeTag: osc.timeTag(60), // Schedules this bundle 60 seconds from now.
packets: [
{
address: "/carrier/frequency",
args: 440
},
{
address: "/carrier/amplitude"
...writeArgument = function (arg, dataCollection) {
if (osc.isArray(arg)) {
return osc.writeArrayArguments(arg, dataCollection);
}
var type = arg.type,
writer = osc.argumentTypes[type].writer;
if (writer) {
var data = osc[writer](arg.value);
osc.addDataPart(data, dataCollection);
}
return arg.type;
}...
};
osc.writeArrayArguments = function (args, dataCollection) {
var typeTag = "[";
for (var i = 0; i < args.length; i++) {
var arg = args[i];
typeTag += osc.writeArgument(arg, dataCollection);
}
typeTag += "]";
return typeTag;
};
...writeArguments = function (args, options) {
var argCollection = osc.collectArguments(args, options);
return osc.joinParts(argCollection);
}n/a
writeArrayArguments = function (args, dataCollection) {
var typeTag = "[";
for (var i = 0; i < args.length; i++) {
var arg = args[i];
typeTag += osc.writeArgument(arg, dataCollection);
}
typeTag += "]";
return typeTag;
}...
typeTag += "]";
return typeTag;
};
osc.writeArgument = function (arg, dataCollection) {
if (osc.isArray(arg)) {
return osc.writeArrayArguments(arg, dataCollection);
}
var type = arg.type,
writer = osc.argumentTypes[type].writer;
if (writer) {
var data = osc[writer](arg.value);
...writeBlob = function (data) {
data = osc.byteArray(data);
var len = data.byteLength,
paddedLen = (len + 3) & ~0x03,
offset = 4, // Extra 4 bytes is for the size.
blobLen = paddedLen + offset,
arr = new Uint8Array(blobLen),
dv = new DataView(arr.buffer);
// Write the size.
osc.writeInt32(len, dv);
// Since we're writing to a real ArrayBuffer,
// we don't need to pad the remaining bytes.
arr.set(data, offset);
return arr;
}n/a
writeBundle = function (bundle, options) {
if (!osc.isValidBundle(bundle)) {
throw new Error("An OSC bundle must contain 'timeTag' and 'packets' properties. " +
"Bundle was: " + JSON.stringify(bundle, null, 2));
}
options = options || osc.defaults;
var bundleCollection = osc.collectBundlePackets(bundle, options);
return osc.joinParts(bundleCollection);
}...
* @param {Object} [options] write options
* @return {Uint8Array} an array of bytes containing the message
*/
osc.writePacket = function (packet, options) {
if (osc.isValidMessage(packet)) {
return osc.writeMessage(packet, options);
} else if (osc.isValidBundle(packet)) {
return osc.writeBundle(packet, options);
} else {
throw new Error("The specified packet was not recognized as a valid OSC message or bundle." +
" Packet was: " + JSON.stringify(packet, null, 2));
}
};
// Unsupported, non-API.
...writeChar32 = function (str, dv, offset) {
var charCode = str.charCodeAt(0);
if (charCode === undefined || charCode < -1) {
return undefined;
}
return osc.writePrimitive(charCode, dv, "setUint32", 4, offset);
}n/a
writeColor = function (color) {
var alpha = Math.round(color.a * 255),
arr = new Uint8Array([color.r, color.g, color.b, alpha]);
return arr;
}n/a
writeFloat32 = function (val, dv, offset) {
return osc.writePrimitive(val, dv, "setFloat32", 4, offset);
}n/a
writeFloat64 = function (val, dv, offset) {
return osc.writePrimitive(val, dv, "setFloat64", 8, offset);
}n/a
writeInt32 = function (val, dv, offset) {
return osc.writePrimitive(val, dv, "setInt32", 4, offset);
}...
paddedLen = (len + 3) & ~0x03,
offset = 4, // Extra 4 bytes is for the size.
blobLen = paddedLen + offset,
arr = new Uint8Array(blobLen),
dv = new DataView(arr.buffer);
// Write the size.
osc.writeInt32(len, dv);
// Since we're writing to a real ArrayBuffer,
// we don't need to pad the remaining bytes.
arr.set(data, offset);
return arr;
};
...writeInt64 = function (val, dv, offset) {
var arr = new Uint8Array(8);
arr.set(osc.writePrimitive(val.high, dv, "setInt32", 4, offset), 0);
arr.set(osc.writePrimitive(val.low, dv, "setInt32", 4, offset + 4), 4);
return arr;
}n/a
writeMIDIBytes = function (bytes) {
bytes = osc.byteArray(bytes);
var arr = new Uint8Array(4);
arr.set(bytes);
return arr;
}n/a
writeMessage = function (msg, options) {
options = options || osc.defaults;
if (!osc.isValidMessage(msg)) {
throw new Error("An OSC message must contain a valid address. Message was: " +
JSON.stringify(msg, null, 2));
}
var msgCollection = osc.collectMessageParts(msg, options);
return osc.joinParts(msgCollection);
}...
*
* @param {Object} a bundle or message object
* @param {Object} [options] write options
* @return {Uint8Array} an array of bytes containing the message
*/
osc.writePacket = function (packet, options) {
if (osc.isValidMessage(packet)) {
return osc.writeMessage(packet, options);
} else if (osc.isValidBundle(packet)) {
return osc.writeBundle(packet, options);
} else {
throw new Error("The specified packet was not recognized as a valid OSC message or bundle." +
" Packet was: " + JSON.stringify(packet, null, 2));
}
};
...writePacket = function (packet, options) {
if (osc.isValidMessage(packet)) {
return osc.writeMessage(packet, options);
} else if (osc.isValidBundle(packet)) {
return osc.writeBundle(packet, options);
} else {
throw new Error("The specified packet was not recognized as a valid OSC message or bundle." +
" Packet was: " + JSON.stringify(packet, null, 2));
}
}...
<code>options</code>: (optional) An options object, described below; <br />
<code>offsetState</code>: (optional) an offset state object containing an <code>idx</
code> property that specifies the offset index into <code>data</code>; <br />
<code>length</code> the length (in bytes) to read from <code>data</code>
</td>
<td>An osc.js message or bundle object</td>
</tr>
<tr>
<td><code>osc.writePacket()</code></td>
<td>Writes an OSC message or bundle object to a binary array.</td>
<td>
<code>packate</code>: An osc.js message or bundle object;<br />
<code>options</code>: (optional) An options object, described below<br />
</td>
<td>A <code>Uint8Array</code></td>
</tr>
...writePrimitive = function (val, dv, writerName, numBytes, offset) {
offset = offset === undefined ? 0 : offset;
var arr;
if (!dv) {
arr = new Uint8Array(numBytes);
dv = new DataView(arr.buffer);
} else {
arr = new Uint8Array(dv.buffer);
}
dv[writerName](offset, val, false);
return arr;
}...
* Writes an OSC int32 ("i") value.
*
* @param {Number} val the number to write
* @param {DataView} [dv] a DataView instance to write the number into
* @param {Number} [offset] an offset into dv
*/
osc.writeInt32 = function (val, dv, offset) {
return osc.writePrimitive(val, dv, "setInt32", 4, offset);
};
/**
* Reads an OSC int64 ("h") value.
*
* @param {DataView} dv a DataView containing the raw bytes
* @param {Object} offsetState an offsetState object used to store the current offset index into dv
...writeString = function (str) {
var terminated = str + "\u0000",
len = terminated.length,
paddedLen = (len + 3) & ~0x03,
arr = new Uint8Array(paddedLen);
for (var i = 0; i < terminated.length; i++) {
var charCode = terminated.charCodeAt(i);
arr[i] = charCode;
}
return arr;
}...
currPartIdx = dataCollection.parts.length;
for (var i = 0; i < args.length; i++) {
var arg = args[i];
typeTagString += osc.writeArgument(arg, dataCollection);
}
var typeData = osc.writeString(typeTagString);
dataCollection.byteLength += typeData.byteLength;
dataCollection.parts.splice(currPartIdx, 0, typeData);
return dataCollection;
};
/**
...writeTimeTag = function (timeTag) {
var raw = timeTag.raw ? timeTag.raw : osc.jsToNTPTime(timeTag.native),
arr = new Uint8Array(8), // Two Unit32s.
dv = new DataView(arr.buffer);
osc.writeInt32(raw[0], dv, 0);
osc.writeInt32(raw[1], dv, 4);
return arr;
}...
osc.collectBundlePackets = function (bundle, options, dataCollection) {
dataCollection = dataCollection || {
byteLength: 0,
parts: []
};
osc.addDataPart(osc.writeString("#bundle"), dataCollection);
osc.addDataPart(osc.writeTimeTag(bundle.timeTag), dataCollection);
for (var i = 0; i < bundle.packets.length; i++) {
var packet = bundle.packets[i],
collector = packet.address ? osc.collectMessageParts : osc.collectBundlePackets,
packetCollection = collector(packet, options);
dataCollection.byteLength += packetCollection.byteLength;
...Port = function (options) {
this.options = options || {};
this.on("data", this.decodeOSC.bind(this));
}n/a
constructor = function (options) {
this.options = options || {};
this.on("data", this.decodeOSC.bind(this));
}n/a
decodeOSC = function (data, packetInfo) {
data = osc.byteArray(data);
this.emit("raw", data, packetInfo);
try {
var packet = osc.readPacket(data, this.options);
this.emit("osc", packet, packetInfo);
osc.firePacketEvents(this, packet, undefined, packetInfo);
} catch (err) {
this.emit("error", err);
}
}n/a
encodeOSC = function (packet) {
// TODO gh-39: This is unsafe; we should only access the underlying
// buffer within the range of its view.
packet = packet.buffer ? packet.buffer : packet;
var encoded;
try {
encoded = osc.writePacket(packet, this.options);
} catch (err) {
this.emit("error", err);
}
return encoded;
}...
};
var p = osc.Port.prototype = Object.create(EventEmitter.prototype);
p.constructor = osc.Port;
p.send = function (oscPacket) {
var args = Array.prototype.slice.call(arguments),
encoded = this.encodeOSC(oscPacket),
buf = osc.nativeBuffer(encoded);
args[0] = buf;
this.sendRaw.apply(this, args);
};
p.encodeOSC = function (packet) {
...send = function (oscPacket) {
var args = Array.prototype.slice.call(arguments),
encoded = this.encodeOSC(oscPacket),
buf = osc.nativeBuffer(encoded);
args[0] = buf;
this.sendRaw.apply(this, args);
}...
});
```
##### Sending OSC messages:
```javascript
// For most Ports, send() should only be called after the "ready" event fires.
oscPort.on("ready", function () {
oscPort.send({
address: "/carrier/frequency",
args: 440
});
});
```
##### Sending OSC bundles:
...Relay = function (port1, port2, options) {
var o = this.options = options || {};
o.raw = false;
this.port1 = port1;
this.port2 = port2;
this.listen();
}n/a
close = function () {
osc.stopRelaying(this.port1, this.port1Spec);
osc.stopRelaying(this.port2, this.port2Spec);
this.emit("close", this.port1, this.port2);
}...
p.open = function () {
this.port1.open();
this.port2.open();
};
p.listen = function () {
if (this.port1Spec && this.port2Spec) {
this.close();
}
this.port1Spec = osc.relayPorts(this.port1, this.port2, this.options);
this.port2Spec = osc.relayPorts(this.port2, this.port1, this.options);
// Bind port close listeners to ensure that the relay
// will stop forwarding messages if one of its ports close.
...constructor = function (port1, port2, options) {
var o = this.options = options || {};
o.raw = false;
this.port1 = port1;
this.port2 = port2;
this.listen();
}n/a
listen = function () {
if (this.port1Spec && this.port2Spec) {
this.close();
}
this.port1Spec = osc.relayPorts(this.port1, this.port2, this.options);
this.port2Spec = osc.relayPorts(this.port2, this.port1, this.options);
// Bind port close listeners to ensure that the relay
// will stop forwarding messages if one of its ports close.
// Users are still responsible for closing the underlying ports
// if necessary.
var closeListener = this.close.bind(this);
this.port1.on("close", closeListener);
this.port2.on("close", closeListener);
}...
var osc = require("osc"),
http = require("http"),
WebSocket = require("ws");
// Create an Express server app
// and serve up a directory of static files.
var app = require("express").express(),
server = app.listen(8081);
app.use("/", express.static(__dirname + "/static"));
// Listen for Web Socket requests.
var wss = new WebSocket.Server({
server: server
});
...open = function () {
this.port1.open();
this.port2.open();
}...
var oscPort = new osc.WebSocketPort({
url: "ws://localhost:8081" // URL to your Web Socket server.
});
```
##### Opening the Port:
```javascript
oscPort.open();
```
##### Listening for incoming OSC messages:
```javascript
oscPort.on("message", function (oscMsg) {
console.log("An OSC message just arrived!", oscMsg);
});
...SLIPPort = function (options) {
var that = this;
var o = this.options = options || {};
o.useSLIP = o.useSLIP === undefined ? true : o.useSLIP;
this.decoder = new slip.Decoder({
onMessage: this.decodeOSC.bind(this),
onError: function (err) {
that.emit("error", err);
}
});
var decodeHandler = o.useSLIP ? this.decodeSLIPData : this.decodeOSC;
this.on("data", decodeHandler.bind(this));
}n/a
constructor = function (options) {
var that = this;
var o = this.options = options || {};
o.useSLIP = o.useSLIP === undefined ? true : o.useSLIP;
this.decoder = new slip.Decoder({
onMessage: this.decodeOSC.bind(this),
onError: function (err) {
that.emit("error", err);
}
});
var decodeHandler = o.useSLIP ? this.decodeSLIPData : this.decodeOSC;
this.on("data", decodeHandler.bind(this));
}n/a
decodeSLIPData = function (data, packetInfo) {
// TODO: Get packetInfo through SLIP decoder.
this.decoder.decode(data, packetInfo);
}n/a
encodeOSC = function (packet) {
// TODO gh-39: This is unsafe; we should only access the underlying
// buffer within the range of its view.
packet = packet.buffer ? packet.buffer : packet;
var framed;
try {
var encoded = osc.writePacket(packet, this.options);
framed = slip.encode(encoded);
} catch (err) {
this.emit("error", err);
}
return framed;
}...
};
var p = osc.Port.prototype = Object.create(EventEmitter.prototype);
p.constructor = osc.Port;
p.send = function (oscPacket) {
var args = Array.prototype.slice.call(arguments),
encoded = this.encodeOSC(oscPacket),
buf = osc.nativeBuffer(encoded);
args[0] = buf;
this.sendRaw.apply(this, args);
};
p.encodeOSC = function (packet) {
...SerialPort = function (options) {
this.on("open", this.listen.bind(this));
osc.SLIPPort.call(this, options);
this.options.bitrate = this.options.bitrate || 9600;
this.serialPort = options.serialPort;
if (this.serialPort) {
this.emit("open", this.serialPort);
}
}...
}
}
```
#### Connecting to the serial port and listening for OSC messages
```javascript
// Instantiate a new OSC Serial Port.
var serialPort = new osc.SerialPort({
devicePath: "/dev/cu.usbmodem22131"
});
// Listen for the message event and map the OSC message to the synth.
serialPort.on("message", function (oscMsg) {
console.log("An OSC message was received!", oscMsg);
});
...close = function () {
if (this.serialPort) {
this.serialPort.close();
}
}...
p.open = function () {
this.port1.open();
this.port2.open();
};
p.listen = function () {
if (this.port1Spec && this.port2Spec) {
this.close();
}
this.port1Spec = osc.relayPorts(this.port1, this.port2, this.options);
this.port2Spec = osc.relayPorts(this.port2, this.port1, this.options);
// Bind port close listeners to ensure that the relay
// will stop forwarding messages if one of its ports close.
...constructor = function (options) {
this.on("open", this.listen.bind(this));
osc.SLIPPort.call(this, options);
this.options.bitrate = this.options.bitrate || 9600;
this.serialPort = options.serialPort;
if (this.serialPort) {
this.emit("open", this.serialPort);
}
}n/a
listen = function () {
var that = this;
this.serialPort.on("data", function (data) {
that.emit("data", data, undefined);
});
this.serialPort.on("error", function (err) {
that.emit("error", err);
});
this.serialPort.on("close", function (err) {
if (err) {
that.emit("error", err);
} else {
that.emit("close");
}
});
that.emit("ready");
}...
var osc = require("osc"),
http = require("http"),
WebSocket = require("ws");
// Create an Express server app
// and serve up a directory of static files.
var app = require("express").express(),
server = app.listen(8081);
app.use("/", express.static(__dirname + "/static"));
// Listen for Web Socket requests.
var wss = new WebSocket.Server({
server: server
});
...open = function () {
if (this.serialPort) {
// If we already have a serial port, close it and open a new one.
this.once("close", this.open.bind(this));
this.close();
return;
}
var that = this;
this.serialPort = new SerialPort(this.options.devicePath, {
baudrate: this.options.bitrate,
autoOpen: false
});
this.serialPort.open(function() {
that.emit("open", that.serialPort);
});
}...
var oscPort = new osc.WebSocketPort({
url: "ws://localhost:8081" // URL to your Web Socket server.
});
```
##### Opening the Port:
```javascript
oscPort.open();
```
##### Listening for incoming OSC messages:
```javascript
oscPort.on("message", function (oscMsg) {
console.log("An OSC message just arrived!", oscMsg);
});
...sendRaw = function (encoded) {
if (!this.serialPort || !this.serialPort.isOpen()) {
osc.fireClosedPortSendError(this);
return;
}
var that = this;
this.serialPort.write(encoded, function (err) {
if (err) {
that.emit("error", err);
}
});
}n/a
TCPSocketPort = function (options) {
osc.SLIPPort.call(this, options);
var o = this.options;
o.localAddress = o.localAddress || "127.0.0.1";
o.localPort = o.localPort !== undefined ? o.localPort : 57121;
this.on("open", this.listen.bind(this));
this.socket = options.socket;
if (this.socket) {
this.emit("open", this.socket);
}
}n/a
close = function () {
this.socket.end();
}...
p.open = function () {
this.port1.open();
this.port2.open();
};
p.listen = function () {
if (this.port1Spec && this.port2Spec) {
this.close();
}
this.port1Spec = osc.relayPorts(this.port1, this.port2, this.options);
this.port2Spec = osc.relayPorts(this.port2, this.port1, this.options);
// Bind port close listeners to ensure that the relay
// will stop forwarding messages if one of its ports close.
...constructor = function (options) {
osc.SLIPPort.call(this, options);
var o = this.options;
o.localAddress = o.localAddress || "127.0.0.1";
o.localPort = o.localPort !== undefined ? o.localPort : 57121;
this.on("open", this.listen.bind(this));
this.socket = options.socket;
if (this.socket) {
this.emit("open", this.socket);
}
}n/a
listen = function () {
var that = this;
this.socket.on("data", function (msg) {
that.emit("data", msg, undefined);
});
this.socket.on("error", function (err) {
that.emit("error", err);
});
this.socket.on("close", function (err) {
if (err) {
that.emit("error", err);
} else {
that.emit("close");
}
});
this.socket.on("connect", function () {
that.emit("ready");
});
}...
var osc = require("osc"),
http = require("http"),
WebSocket = require("ws");
// Create an Express server app
// and serve up a directory of static files.
var app = require("express").express(),
server = app.listen(8081);
app.use("/", express.static(__dirname + "/static"));
// Listen for Web Socket requests.
var wss = new WebSocket.Server({
server: server
});
...open = function (address, port) {
var o = this.options;
address = address || o.address;
port = port !== undefined ? port : o.port;
if (!this.socket) {
this.socket = net.connect({
port: port,
host: address
});
} else {
this.socket.connect(port, address);
}
this.emit("open", this.socket);
}...
var oscPort = new osc.WebSocketPort({
url: "ws://localhost:8081" // URL to your Web Socket server.
});
```
##### Opening the Port:
```javascript
oscPort.open();
```
##### Listening for incoming OSC messages:
```javascript
oscPort.on("message", function (oscMsg) {
console.log("An OSC message just arrived!", oscMsg);
});
...sendRaw = function (encoded) {
if (!this.socket) {
return;
}
encoded = new Buffer(encoded);
try {
this.socket.write(encoded);
} catch (err) {
this.emit("error", err);
}
}n/a
UDPPort = function (options) {
osc.Port.call(this, options);
this.options.localAddress = this.options.localAddress || "127.0.0.1";
this.options.localPort = this.options.localPort !== undefined ?
this.options.localPort : 57121;
this.options.remoteAddress = this.options.remoteAddress || "127.0.0.1";
this.options.remotePort = this.options.remotePort !== undefined ?
this.options.remotePort : 57121;
this.on("open", this.listen.bind(this));
this.socket = options.socket;
if (this.socket) {
this.emit("open", this.socket);
}
}...
</tr>
</table>
#### Sample Code
```javascript
// Create an osc.js UDP Port listening on port 57121.
var udpPort = new osc.UDPPort({
localAddress: "0.0.0.0",
localPort: 57121
});
// Listen for incoming OSC bundles.
udpPort.on("bundle", function (oscBundle, timeTag, info) {
console.log("An OSC bundle just arrived for time tag", timeTag, ":", oscBundle);
...setupMulticast = function (that) {
if (that.options.multicastTTL !== undefined) {
that.socket.setMulticastTTL(that.options.multicastTTL);
}
if (that.options.multicastMembership) {
if (typeof that.options.multicastMembership === "string") {
that.options.multicastMembership = [that.options.multicastMembership];
}
that.options.multicastMembership.forEach(function (addr) {
if (typeof addr === "string") {
that.socket.addMembership(addr);
} else {
that.socket.addMembership(addr.address, addr.interface);
}
});
}
}n/a
close = function () {
if (this.socket) {
this.socket.close();
}
}...
p.open = function () {
this.port1.open();
this.port2.open();
};
p.listen = function () {
if (this.port1Spec && this.port2Spec) {
this.close();
}
this.port1Spec = osc.relayPorts(this.port1, this.port2, this.options);
this.port2Spec = osc.relayPorts(this.port2, this.port1, this.options);
// Bind port close listeners to ensure that the relay
// will stop forwarding messages if one of its ports close.
...constructor = function (options) {
osc.Port.call(this, options);
this.options.localAddress = this.options.localAddress || "127.0.0.1";
this.options.localPort = this.options.localPort !== undefined ?
this.options.localPort : 57121;
this.options.remoteAddress = this.options.remoteAddress || "127.0.0.1";
this.options.remotePort = this.options.remotePort !== undefined ?
this.options.remotePort : 57121;
this.on("open", this.listen.bind(this));
this.socket = options.socket;
if (this.socket) {
this.emit("open", this.socket);
}
}n/a
listen = function () {
if (!this.socket) {
return;
}
var that = this;
this.socket.on("message", function (msg, rinfo) {
that.emit("data", msg, rinfo);
});
this.socket.on("error", function (error) {
that.emit("error", error);
});
this.socket.on("close", function () {
that.emit("close");
});
that.emit("ready");
}...
var osc = require("osc"),
http = require("http"),
WebSocket = require("ws");
// Create an Express server app
// and serve up a directory of static files.
var app = require("express").express(),
server = app.listen(8081);
app.use("/", express.static(__dirname + "/static"));
// Listen for Web Socket requests.
var wss = new WebSocket.Server({
server: server
});
...open = function () {
var that = this;
if (this.socket) {
return;
}
this.socket = dgram.createSocket("udp4");
function onBound() {
osc.UDPPort.setupMulticast(that);
if (that.options.broadcast) {
that.socket.setBroadcast(that.options.broadcast);
}
that.emit("open", that.socket);
}
this.socket.bind(this.options.localPort, this.options.localAddress, onBound);
}...
var oscPort = new osc.WebSocketPort({
url: "ws://localhost:8081" // URL to your Web Socket server.
});
```
##### Opening the Port:
```javascript
oscPort.open();
```
##### Listening for incoming OSC messages:
```javascript
oscPort.on("message", function (oscMsg) {
console.log("An OSC message just arrived!", oscMsg);
});
...sendRaw = function (encoded, address, port) {
if (!this.socket) {
osc.fireClosedPortSendError(this);
return;
}
var length = encoded.byteLength !== undefined ? encoded.byteLength : encoded.length,
that = this;
address = address || this.options.remoteAddress;
port = port !== undefined ? port : this.options.remotePort;
this.socket.send(encoded, 0, length, port, address, function (err) {
if (err) {
that.emit("error", err);
}
});
}n/a
function WebSocket(address, protocols, options) {
if (this instanceof WebSocket === false) {
return new WebSocket(address, protocols, options);
}
EventEmitter.call(this);
if (protocols && !Array.isArray(protocols) && 'object' === typeof protocols) {
// accept the "options" Object as the 2nd argument
options = protocols;
protocols = null;
}
if ('string' === typeof protocols) {
protocols = [ protocols ];
}
if (!Array.isArray(protocols)) {
protocols = [];
}
this._socket = null;
this._ultron = null;
this._closeReceived = false;
this.bytesReceived = 0;
this.readyState = null;
this.supports = {};
this.extensions = {};
this._binaryType = 'nodebuffer';
if (Array.isArray(address)) {
initAsServerClient.apply(this, address.concat(options));
} else {
initAsClient.apply(this, [address, protocols, options]);
}
}...
};
var p = osc.WebSocketPort.prototype = Object.create(osc.Port.prototype);
p.constructor = osc.WebSocketPort;
p.open = function () {
if (!this.socket || this.socket.readyState > 1) {
this.socket = new osc.WebSocket(this.options.url);
}
osc.WebSocketPort.setupSocketForBinary(this.socket);
var that = this;
this.socket.onopen = function () {
that.emit("open", that.socket);
...function Receiver(extensions, maxPayload) {
if (this instanceof Receiver === false) {
throw new TypeError("Classes can't be function-called");
}
if(typeof extensions==='number'){
maxPayload=extensions;
extensions={};
}
// memory pool for fragmented messages
var fragmentedPoolPrevUsed = -1;
this.fragmentedBufferPool = new BufferPool(1024, function(db, length) {
return db.used + length;
}, function(db) {
return fragmentedPoolPrevUsed = fragmentedPoolPrevUsed >= 0 ?
Math.ceil((fragmentedPoolPrevUsed + db.used) / 2) :
db.used;
});
// memory pool for unfragmented messages
var unfragmentedPoolPrevUsed = -1;
this.unfragmentedBufferPool = new BufferPool(1024, function(db, length) {
return db.used + length;
}, function(db) {
return unfragmentedPoolPrevUsed = unfragmentedPoolPrevUsed >= 0 ?
Math.ceil((unfragmentedPoolPrevUsed + db.used) / 2) :
db.used;
});
this.extensions = extensions || {};
this.maxPayload = maxPayload || 0;
this.currentPayloadLength = 0;
this.state = {
activeFragmentedOperation: null,
lastFragment: false,
masked: false,
opcode: 0,
fragmentedOperation: false
};
this.overflow = [];
this.headerBuffer = new Buffer(10);
this.expectOffset = 0;
this.expectBuffer = null;
this.expectHandler = null;
this.currentMessage = [];
this.currentMessageLength = 0;
this.messageHandlers = [];
this.expectHeader(2, this.processPacket);
this.dead = false;
this.processing = false;
this.onerror = function() {};
this.ontext = function() {};
this.onbinary = function() {};
this.onclose = function() {};
this.onping = function() {};
this.onpong = function() {};
}n/a
function Sender(socket, extensions) {
if (this instanceof Sender === false) {
throw new TypeError("Classes can't be function-called");
}
events.EventEmitter.call(this);
this._socket = socket;
this.extensions = extensions || {};
this.firstFragment = true;
this.compress = false;
this.messageHandlers = [];
this.processing = false;
}n/a
function WebSocketServer(options, callback) {
if (this instanceof WebSocketServer === false) {
return new WebSocketServer(options, callback);
}
events.EventEmitter.call(this);
options = new Options({
host: '0.0.0.0',
port: null,
server: null,
verifyClient: null,
handleProtocols: null,
path: null,
noServer: false,
disableHixie: false,
clientTracking: true,
perMessageDeflate: true,
maxPayload: 100 * 1024 * 1024
}).merge(options);
if (!options.isDefinedAndNonNull('port') && !options.isDefinedAndNonNull('server') && !options.value.noServer) {
throw new TypeError('`port` or a `server` must be provided');
}
var self = this;
if (options.isDefinedAndNonNull('port')) {
this._server = http.createServer(function (req, res) {
var body = http.STATUS_CODES[426];
res.writeHead(426, {
'Content-Length': body.length,
'Content-Type': 'text/plain'
});
res.end(body);
});
this._server.allowHalfOpen = false;
this._server.listen(options.value.port, options.value.host, callback);
this._closeServer = function() { if (self._server) self._server.close(); };
}
else if (options.value.server) {
this._server = options.value.server;
if (options.value.path) {
// take note of the path, to avoid collisions when multiple websocket servers are
// listening on the same http server
if (this._server._webSocketPaths && options.value.server._webSocketPaths[options.value.path]) {
throw new Error('two instances of WebSocketServer cannot listen on the same http server path');
}
if (typeof this._server._webSocketPaths !== 'object') {
this._server._webSocketPaths = {};
}
this._server._webSocketPaths[options.value.path] = 1;
}
}
if (this._server) {
this._onceServerListening = function() { self.emit('listening'); };
this._server.once('listening', this._onceServerListening);
}
if (typeof this._server != 'undefined') {
this._onServerError = function(error) { self.emit('error', error) };
this._server.on('error', this._onServerError);
this._onServerUpgrade = function(req, socket, upgradeHead) {
//copy upgradeHead to avoid retention of large slab buffers used in node core
var head = new Buffer(upgradeHead.length);
upgradeHead.copy(head);
self.handleUpgrade(req, socket, head, function(client) {
self.emit('connection'+req.url, client);
self.emit('connection', client);
});
};
this._server.on('upgrade', this._onServerUpgrade);
}
this.options = options.value;
this.path = options.value.path;
this.clients = [];
}...
// and serve up a directory of static files.
var app = require("express").express(),
server = app.listen(8081);
app.use("/", express.static(__dirname + "/static"));
// Listen for Web Socket requests.
var wss = new WebSocket.Server({
server: server
});
// Listen for Web Socket connections.
wss.on("connection", function (socket) {
var socketPort = new osc.WebSocketPort({
socket: socket
...function buildHostHeader(isSecure, hostname, port) {
var headerHost = hostname;
if (hostname) {
if ((isSecure && (port != 443)) || (!isSecure && (port != 80))){
headerHost = headerHost + ':' + port;
}
}
return headerHost;
}n/a
function connect(address, fn) {
var client = new WS(address);
if (typeof fn === 'function') {
client.on('open', fn);
}
return client;
}...
p.open = function () {
var that = this,
connectionOpts = {
bitrate: that.options.bitrate
};
chrome.serial.connect(this.options.devicePath, connectionOpts, function (info) {
that.connectionId = info.connectionId;
that.emit("open", info);
});
};
p.listen = function () {
osc.listenToTransport(this, chrome.serial, "connectionId");
...function connect(address, fn) {
var client = new WS(address);
if (typeof fn === 'function') {
client.on('open', fn);
}
return client;
}n/a
function createServer(options, fn) {
var server = new WS.Server(options);
if (typeof fn === 'function') {
server.on('connection', fn);
}
return server;
}n/a
function EventEmitter() {
EventEmitter.init.call(this);
}n/a
function Receiver(extensions, maxPayload) {
if (this instanceof Receiver === false) {
throw new TypeError("Classes can't be function-called");
}
if(typeof extensions==='number'){
maxPayload=extensions;
extensions={};
}
// memory pool for fragmented messages
var fragmentedPoolPrevUsed = -1;
this.fragmentedBufferPool = new BufferPool(1024, function(db, length) {
return db.used + length;
}, function(db) {
return fragmentedPoolPrevUsed = fragmentedPoolPrevUsed >= 0 ?
Math.ceil((fragmentedPoolPrevUsed + db.used) / 2) :
db.used;
});
// memory pool for unfragmented messages
var unfragmentedPoolPrevUsed = -1;
this.unfragmentedBufferPool = new BufferPool(1024, function(db, length) {
return db.used + length;
}, function(db) {
return unfragmentedPoolPrevUsed = unfragmentedPoolPrevUsed >= 0 ?
Math.ceil((unfragmentedPoolPrevUsed + db.used) / 2) :
db.used;
});
this.extensions = extensions || {};
this.maxPayload = maxPayload || 0;
this.currentPayloadLength = 0;
this.state = {
activeFragmentedOperation: null,
lastFragment: false,
masked: false,
opcode: 0,
fragmentedOperation: false
};
this.overflow = [];
this.headerBuffer = new Buffer(10);
this.expectOffset = 0;
this.expectBuffer = null;
this.expectHandler = null;
this.currentMessage = [];
this.currentMessageLength = 0;
this.messageHandlers = [];
this.expectHeader(2, this.processPacket);
this.dead = false;
this.processing = false;
this.onerror = function() {};
this.ontext = function() {};
this.onbinary = function() {};
this.onclose = function() {};
this.onping = function() {};
this.onpong = function() {};
}n/a
add = function (data) {
if (this.dead) return;
var dataLength = data.length;
if (dataLength == 0) return;
if (this.expectBuffer == null) {
this.overflow.push(data);
return;
}
var toRead = Math.min(dataLength, this.expectBuffer.length - this.expectOffset);
fastCopy(toRead, data, this.expectBuffer, this.expectOffset);
this.expectOffset += toRead;
if (toRead < dataLength) {
this.overflow.push(data.slice(toRead));
}
while (this.expectBuffer && this.expectOffset == this.expectBuffer.length) {
var bufferForHandler = this.expectBuffer;
this.expectBuffer = null;
this.expectOffset = 0;
this.expectHandler.call(this, bufferForHandler);
}
}n/a
allocateFromPool = function (length, isFragmented) {
return (isFragmented ? this.fragmentedBufferPool : this.unfragmentedBufferPool).get(length);
}n/a
applyExtensions = function (messageBuffer, fin, compressed, callback) {
var self = this;
if (compressed) {
this.extensions[PerMessageDeflate.extensionName].decompress(messageBuffer, fin, function(err, buffer) {
if (self.dead) return;
if (err) {
callback(new Error('invalid compressed data'));
return;
}
callback(null, buffer);
});
} else {
callback(null, messageBuffer);
}
}n/a
cleanup = function () {
this.dead = true;
this.overflow = null;
this.headerBuffer = null;
this.expectBuffer = null;
this.expectHandler = null;
this.unfragmentedBufferPool = null;
this.fragmentedBufferPool = null;
this.state = null;
this.currentMessage = null;
this.onerror = null;
this.ontext = null;
this.onbinary = null;
this.onclose = null;
this.onping = null;
this.onpong = null;
}n/a
endPacket = function () {
if (this.dead) return;
if (!this.state.fragmentedOperation) this.unfragmentedBufferPool.reset(true);
else if (this.state.lastFragment) this.fragmentedBufferPool.reset(true);
this.expectOffset = 0;
this.expectBuffer = null;
this.expectHandler = null;
if (this.state.lastFragment && this.state.opcode === this.state.activeFragmentedOperation) {
// end current fragmented operation
this.state.activeFragmentedOperation = null;
}
this.currentPayloadLength = 0;
this.state.lastFragment = false;
this.state.opcode = this.state.activeFragmentedOperation != null ? this.state.activeFragmentedOperation : 0;
this.state.masked = false;
this.expectHeader(2, this.processPacket);
}n/a
error = function (reason, protocolErrorCode) {
if (this.dead) return;
this.reset();
if(typeof reason == 'string'){
this.onerror(new Error(reason), protocolErrorCode);
}
else if(reason.constructor == Error){
this.onerror(reason, protocolErrorCode);
}
else{
this.onerror(new Error("An error occured"),protocolErrorCode);
}
return this;
}n/a
expectData = function (length, handler) {
if (length == 0) {
handler(null);
return;
}
this.expectBuffer = this.allocateFromPool(length, this.state.fragmentedOperation);
this.expectHandler = handler;
var toRead = length;
while (toRead > 0 && this.overflow.length > 0) {
var fromOverflow = this.overflow.pop();
if (toRead < fromOverflow.length) this.overflow.push(fromOverflow.slice(toRead));
var read = Math.min(fromOverflow.length, toRead);
fastCopy(read, fromOverflow, this.expectBuffer, this.expectOffset);
this.expectOffset += read;
toRead -= read;
}
}n/a
expectHeader = function (length, handler) {
if (length == 0) {
handler(null);
return;
}
this.expectBuffer = this.headerBuffer.slice(this.expectOffset, this.expectOffset + length);
this.expectHandler = handler;
var toRead = length;
while (toRead > 0 && this.overflow.length > 0) {
var fromOverflow = this.overflow.pop();
if (toRead < fromOverflow.length) this.overflow.push(fromOverflow.slice(toRead));
var read = Math.min(fromOverflow.length, toRead);
fastCopy(read, fromOverflow, this.expectBuffer, this.expectOffset);
this.expectOffset += read;
toRead -= read;
}
}n/a
flush = function () {
if (this.processing || this.dead) return;
var handler = this.messageHandlers.shift();
if (!handler) return;
this.processing = true;
var self = this;
handler(function() {
self.processing = false;
self.flush();
});
}n/a
maxPayloadExceeded = function (length) {
if (this.maxPayload=== undefined || this.maxPayload === null || this.maxPayload < 1) {
return false;
}
var fullLength = this.currentPayloadLength + length;
if (fullLength < this.maxPayload) {
this.currentPayloadLength = fullLength;
return false;
}
this.error('payload cannot exceed ' + this.maxPayload + ' bytes', 1009);
this.messageBuffer=[];
this.cleanup();
return true;
}n/a
processPacket = function (data) {
if (this.extensions[PerMessageDeflate.extensionName]) {
if ((data[0] & 0x30) != 0) {
this.error('reserved fields (2, 3) must be empty', 1002);
return;
}
} else {
if ((data[0] & 0x70) != 0) {
this.error('reserved fields must be empty', 1002);
return;
}
}
this.state.lastFragment = (data[0] & 0x80) == 0x80;
this.state.masked = (data[1] & 0x80) == 0x80;
var compressed = (data[0] & 0x40) == 0x40;
var opcode = data[0] & 0xf;
if (opcode === 0) {
if (compressed) {
this.error('continuation frame cannot have the Per-message Compressed bits', 1002);
return;
}
// continuation frame
this.state.fragmentedOperation = true;
this.state.opcode = this.state.activeFragmentedOperation;
if (!(this.state.opcode == 1 || this.state.opcode == 2)) {
this.error('continuation frame cannot follow current opcode', 1002);
return;
}
}
else {
if (opcode < 3 && this.state.activeFragmentedOperation != null) {
this.error('data frames after the initial data frame must have opcode 0', 1002);
return;
}
if (opcode >= 8 && compressed) {
this.error('control frames cannot have the Per-message Compressed bits', 1002);
return;
}
this.state.compressed = compressed;
this.state.opcode = opcode;
if (this.state.lastFragment === false) {
this.state.fragmentedOperation = true;
this.state.activeFragmentedOperation = opcode;
}
else this.state.fragmentedOperation = false;
}
var handler = opcodes[this.state.opcode];
if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode, 1002);
else {
handler.start.call(this, data);
}
}n/a
reset = function () {
if (this.dead) return;
this.state = {
activeFragmentedOperation: null,
lastFragment: false,
masked: false,
opcode: 0,
fragmentedOperation: false
};
this.fragmentedBufferPool.reset(true);
this.unfragmentedBufferPool.reset(true);
this.expectOffset = 0;
this.expectBuffer = null;
this.expectHandler = null;
this.overflow = [];
this.currentMessage = [];
this.currentMessageLength = 0;
this.messageHandlers = [];
this.currentPayloadLength = 0;
}n/a
unmask = function (mask, buf, binary) {
if (mask != null && buf != null) bufferUtil.unmask(buf, mask);
if (binary) return buf;
return buf != null ? buf.toString('utf8') : '';
}n/a
function Sender(socket, extensions) {
if (this instanceof Sender === false) {
throw new TypeError("Classes can't be function-called");
}
events.EventEmitter.call(this);
this._socket = socket;
this.extensions = extensions || {};
this.firstFragment = true;
this.compress = false;
this.messageHandlers = [];
this.processing = false;
}n/a
function EventEmitter() {
EventEmitter.init.call(this);
}n/a
applyExtensions = function (data, fin, compress, callback) {
if (compress && data) {
if ((data.buffer || data) instanceof ArrayBuffer) {
data = getArrayBuffer(data);
}
this.extensions[PerMessageDeflate.extensionName].compress(data, fin, callback);
} else {
callback(null, data);
}
}n/a
close = function (code, data, mask, cb) {
if (typeof code !== 'undefined') {
if (typeof code !== 'number' ||
!ErrorCodes.isValidErrorCode(code)) throw new Error('first argument must be a valid error code number');
}
code = code || 1000;
var dataBuffer = new Buffer(2 + (data ? Buffer.byteLength(data) : 0));
writeUInt16BE.call(dataBuffer, code, 0);
if (dataBuffer.length > 2) dataBuffer.write(data, 2);
var self = this;
this.messageHandlers.push(function(callback) {
self.frameAndSend(0x8, dataBuffer, true, mask);
callback();
if (typeof cb == 'function') cb();
});
this.flush();
}...
p.open = function () {
this.port1.open();
this.port2.open();
};
p.listen = function () {
if (this.port1Spec && this.port2Spec) {
this.close();
}
this.port1Spec = osc.relayPorts(this.port1, this.port2, this.options);
this.port2Spec = osc.relayPorts(this.port2, this.port1, this.options);
// Bind port close listeners to ensure that the relay
// will stop forwarding messages if one of its ports close.
...flush = function () {
if (this.processing) return;
var handler = this.messageHandlers.shift();
if (!handler) return;
this.processing = true;
var self = this;
handler(function() {
self.processing = false;
self.flush();
});
}n/a
frameAndSend = function (opcode, data, finalFragment, maskData, compressed, cb) {
var canModifyData = false;
if (!data) {
try {
this._socket.write(new Buffer([opcode | (finalFragment ? 0x80 : 0), 0 | (maskData ? 0x80 : 0)].concat(maskData ? [0, 0, 0,
0] : [])), 'binary', cb);
}
catch (e) {
if (typeof cb == 'function') cb(e);
else this.emit('error', e);
}
return;
}
if (!Buffer.isBuffer(data)) {
canModifyData = true;
if (data && (typeof data.byteLength !== 'undefined' || typeof data.buffer !== 'undefined')) {
data = getArrayBuffer(data);
} else {
//
// If people want to send a number, this would allocate the number in
// bytes as memory size instead of storing the number as buffer value. So
// we need to transform it to string in order to prevent possible
// vulnerabilities / memory attacks.
//
if (typeof data === 'number') data = data.toString();
data = new Buffer(data);
}
}
var dataLength = data.length
, dataOffset = maskData ? 6 : 2
, secondByte = dataLength;
if (dataLength >= 65536) {
dataOffset += 8;
secondByte = 127;
}
else if (dataLength > 125) {
dataOffset += 2;
secondByte = 126;
}
var mergeBuffers = dataLength < 32768 || (maskData && !canModifyData);
var totalLength = mergeBuffers ? dataLength + dataOffset : dataOffset;
var outputBuffer = new Buffer(totalLength);
outputBuffer[0] = finalFragment ? opcode | 0x80 : opcode;
if (compressed) outputBuffer[0] |= 0x40;
switch (secondByte) {
case 126:
writeUInt16BE.call(outputBuffer, dataLength, 2);
break;
case 127:
writeUInt32BE.call(outputBuffer, 0, 2);
writeUInt32BE.call(outputBuffer, dataLength, 6);
}
if (maskData) {
outputBuffer[1] = secondByte | 0x80;
var mask = getRandomMask();
outputBuffer[dataOffset - 4] = mask[0];
outputBuffer[dataOffset - 3] = mask[1];
outputBuffer[dataOffset - 2] = mask[2];
outputBuffer[dataOffset - 1] = mask[3];
if (mergeBuffers) {
bufferUtil.mask(data, mask, outputBuffer, dataOffset, dataLength);
try {
this._socket.write(outputBuffer, 'binary', cb);
}
catch (e) {
if (typeof cb == 'function') cb(e);
else this.emit('error', e);
}
}
else {
bufferUtil.mask(data, mask, data, 0, dataLength);
try {
this._socket.write(outputBuffer, 'binary');
this._socket.write(data, 'binary', cb);
}
catch (e) {
if (typeof cb == 'function') cb(e);
else this.emit('error', e);
}
}
}
else {
outputBuffer[1] = secondByte;
if (mergeBuffers) {
data.copy(outputBuffer, dataOffset);
try {
this._socket.write(outputBuffer, 'binary', cb);
}
catch (e) {
if (typeof cb == 'function') cb(e);
else this.emit('error', e);
}
}
else {
try {
this._socket.write(outputBuffer, 'binary');
this._socket.write(data, 'binary', cb);
}
catch (e) {
if (typeof cb == 'function') cb(e);
else this.emit('error', e);
}
}
}
}n/a
ping = function (data, options) {
var mask = options && options.mask;
var self = this;
this.messageHandlers.push(function(callback) {
self.frameAndSend(0x9, data || '', true, mask);
callback();
});
this.flush();
}n/a
pong = function (data, options) {
var mask = options && options.mask;
var self = this;
this.messageHandlers.push(function(callback) {
self.frameAndSend(0xa, data || '', true, mask);
callback();
});
this.flush();
}n/a
send = function (data, options, cb) {
var finalFragment = options && options.fin === false ? false : true;
var mask = options && options.mask;
var compress = options && options.compress;
var opcode = options && options.binary ? 2 : 1;
if (this.firstFragment === false) {
opcode = 0;
compress = false;
} else {
this.firstFragment = false;
this.compress = compress;
}
if (finalFragment) this.firstFragment = true
var compressFragment = this.compress;
var self = this;
this.messageHandlers.push(function(callback) {
self.applyExtensions(data, finalFragment, compressFragment, function(err, data) {
if (err) {
if (typeof cb == 'function') cb(err);
else self.emit('error', err);
return;
}
self.frameAndSend(opcode, data, finalFragment, mask, compress, cb);
callback();
});
});
this.flush();
}...
});
```
##### Sending OSC messages:
```javascript
// For most Ports, send() should only be called after the "ready" event fires.
oscPort.on("ready", function () {
oscPort.send({
address: "/carrier/frequency",
args: 440
});
});
```
##### Sending OSC bundles:
...function WebSocketServer(options, callback) {
if (this instanceof WebSocketServer === false) {
return new WebSocketServer(options, callback);
}
events.EventEmitter.call(this);
options = new Options({
host: '0.0.0.0',
port: null,
server: null,
verifyClient: null,
handleProtocols: null,
path: null,
noServer: false,
disableHixie: false,
clientTracking: true,
perMessageDeflate: true,
maxPayload: 100 * 1024 * 1024
}).merge(options);
if (!options.isDefinedAndNonNull('port') && !options.isDefinedAndNonNull('server') && !options.value.noServer) {
throw new TypeError('`port` or a `server` must be provided');
}
var self = this;
if (options.isDefinedAndNonNull('port')) {
this._server = http.createServer(function (req, res) {
var body = http.STATUS_CODES[426];
res.writeHead(426, {
'Content-Length': body.length,
'Content-Type': 'text/plain'
});
res.end(body);
});
this._server.allowHalfOpen = false;
this._server.listen(options.value.port, options.value.host, callback);
this._closeServer = function() { if (self._server) self._server.close(); };
}
else if (options.value.server) {
this._server = options.value.server;
if (options.value.path) {
// take note of the path, to avoid collisions when multiple websocket servers are
// listening on the same http server
if (this._server._webSocketPaths && options.value.server._webSocketPaths[options.value.path]) {
throw new Error('two instances of WebSocketServer cannot listen on the same http server path');
}
if (typeof this._server._webSocketPaths !== 'object') {
this._server._webSocketPaths = {};
}
this._server._webSocketPaths[options.value.path] = 1;
}
}
if (this._server) {
this._onceServerListening = function() { self.emit('listening'); };
this._server.once('listening', this._onceServerListening);
}
if (typeof this._server != 'undefined') {
this._onServerError = function(error) { self.emit('error', error) };
this._server.on('error', this._onServerError);
this._onServerUpgrade = function(req, socket, upgradeHead) {
//copy upgradeHead to avoid retention of large slab buffers used in node core
var head = new Buffer(upgradeHead.length);
upgradeHead.copy(head);
self.handleUpgrade(req, socket, head, function(client) {
self.emit('connection'+req.url, client);
self.emit('connection', client);
});
};
this._server.on('upgrade', this._onServerUpgrade);
}
this.options = options.value;
this.path = options.value.path;
this.clients = [];
}...
// and serve up a directory of static files.
var app = require("express").express(),
server = app.listen(8081);
app.use("/", express.static(__dirname + "/static"));
// Listen for Web Socket requests.
var wss = new WebSocket.Server({
server: server
});
// Listen for Web Socket connections.
wss.on("connection", function (socket) {
var socketPort = new osc.WebSocketPort({
socket: socket
...function EventEmitter() {
EventEmitter.init.call(this);
}n/a
close = function (callback) {
// terminate all associated clients
var error = null;
try {
for (var i = 0, l = this.clients.length; i < l; ++i) {
this.clients[i].terminate();
}
}
catch (e) {
error = e;
}
// remove path descriptor, if any
if (this.path && this._server._webSocketPaths) {
delete this._server._webSocketPaths[this.path];
if (Object.keys(this._server._webSocketPaths).length == 0) {
delete this._server._webSocketPaths;
}
}
// close the http server if it was internally created
try {
if (typeof this._closeServer !== 'undefined') {
this._closeServer();
}
}
finally {
if (this._server) {
this._server.removeListener('listening', this._onceServerListening);
this._server.removeListener('error', this._onServerError);
this._server.removeListener('upgrade', this._onServerUpgrade);
}
delete this._server;
}
if(callback)
callback(error);
else if(error)
throw error;
}...
p.open = function () {
this.port1.open();
this.port2.open();
};
p.listen = function () {
if (this.port1Spec && this.port2Spec) {
this.close();
}
this.port1Spec = osc.relayPorts(this.port1, this.port2, this.options);
this.port2Spec = osc.relayPorts(this.port2, this.port1, this.options);
// Bind port close listeners to ensure that the relay
// will stop forwarding messages if one of its ports close.
...handleUpgrade = function (req, socket, upgradeHead, cb) {
// check for wrong path
if (this.options.path) {
var u = url.parse(req.url);
if (u && u.pathname !== this.options.path) return;
}
if (typeof req.headers.upgrade === 'undefined' || req.headers.upgrade.toLowerCase() !== 'websocket') {
abortConnection(socket, 400, 'Bad Request');
return;
}
if (req.headers['sec-websocket-key1']) handleHixieUpgrade.apply(this, arguments);
else handleHybiUpgrade.apply(this, arguments);
}n/a
addEventListener = function (method, listener) {
var target = this;
function onMessage (data, flags) {
if (flags.binary && this.binaryType === 'arraybuffer')
data = new Uint8Array(data).buffer;
listener.call(target, new MessageEvent(data, !!flags.binary, target));
}
function onClose (code, message) {
listener.call(target, new CloseEvent(code, message, target));
}
function onError (event) {
event.type = 'error';
event.target = target;
listener.call(target, event);
}
function onOpen () {
listener.call(target, new OpenEvent(target));
}
if (typeof listener === 'function') {
if (method === 'message') {
// store a reference so we can return the original function from the
// addEventListener hook
onMessage._listener = listener;
this.on(method, onMessage);
} else if (method === 'close') {
// store a reference so we can return the original function from the
// addEventListener hook
onClose._listener = listener;
this.on(method, onClose);
} else if (method === 'error') {
// store a reference so we can return the original function from the
// addEventListener hook
onError._listener = listener;
this.on(method, onError);
} else if (method === 'open') {
// store a reference so we can return the original function from the
// addEventListener hook
onOpen._listener = listener;
this.on(method, onOpen);
} else {
this.on(method, listener);
}
}
}n/a
function close(code, data) {
if (this.readyState === WebSocket.CLOSED) return;
if (this.readyState === WebSocket.CONNECTING) {
this.readyState = WebSocket.CLOSED;
return;
}
if (this.readyState === WebSocket.CLOSING) {
if (this._closeReceived && this._isServer) {
this.terminate();
}
return;
}
var self = this;
try {
this.readyState = WebSocket.CLOSING;
this._closeCode = code;
this._closeMessage = data;
var mask = !this._isServer;
this._sender.close(code, data, mask, function(err) {
if (err) self.emit('error', err);
if (self._closeReceived && self._isServer) {
self.terminate();
} else {
// ensure that the connection is cleaned up even when no response of closing handshake.
clearTimeout(self._closeTimer);
self._closeTimer = setTimeout(cleanupWebsocketResources.bind(self, true), closeTimeout);
}
});
} catch (e) {
this.emit('error', e);
}
}...
p.open = function () {
this.port1.open();
this.port2.open();
};
p.listen = function () {
if (this.port1Spec && this.port2Spec) {
this.close();
}
this.port1Spec = osc.relayPorts(this.port1, this.port2, this.options);
this.port2Spec = osc.relayPorts(this.port2, this.port1, this.options);
// Bind port close listeners to ensure that the relay
// will stop forwarding messages if one of its ports close.
...function pauser() {
if (this.readyState !== WebSocket.OPEN) throw new Error('not opened');
return this._socket.pause();
}n/a
function ping(data, options, dontFailWhenClosed) {
if (this.readyState !== WebSocket.OPEN) {
if (dontFailWhenClosed === true) return;
throw new Error('not opened');
}
options = options || {};
if (typeof options.mask === 'undefined') options.mask = !this._isServer;
this._sender.ping(data, options);
}n/a
pong = function (data, options, dontFailWhenClosed) {
if (this.readyState !== WebSocket.OPEN) {
if (dontFailWhenClosed === true) return;
throw new Error('not opened');
}
options = options || {};
if (typeof options.mask === 'undefined') options.mask = !this._isServer;
this._sender.pong(data, options);
}n/a
function resume() {
if (this.readyState !== WebSocket.OPEN) throw new Error('not opened');
return this._socket.resume();
}n/a
function send(data, options, cb) {
if (typeof options === 'function') {
cb = options;
options = {};
}
if (this.readyState !== WebSocket.OPEN) {
if (typeof cb === 'function') cb(new Error('not opened'));
else throw new Error('not opened');
return;
}
if (!data) data = '';
if (this._queue) {
var self = this;
this._queue.push(function() { self.send(data, options, cb); });
return;
}
options = options || {};
options.fin = true;
if (typeof options.binary === 'undefined') {
options.binary = (data instanceof ArrayBuffer || data instanceof Buffer ||
data instanceof Uint8Array ||
data instanceof Uint16Array ||
data instanceof Uint32Array ||
data instanceof Int8Array ||
data instanceof Int16Array ||
data instanceof Int32Array ||
data instanceof Float32Array ||
data instanceof Float64Array);
}
if (typeof options.mask === 'undefined') options.mask = !this._isServer;
if (typeof options.compress === 'undefined') options.compress = true;
if (!this.extensions[PerMessageDeflate.extensionName]) {
options.compress = false;
}
var readable = typeof stream.Readable === 'function'
? stream.Readable
: stream.Stream;
if (data instanceof readable) {
startQueue(this);
var self = this;
sendStream(this, data, options, function send(error) {
process.nextTick(function tock() {
executeQueueSends(self);
});
if (typeof cb === 'function') cb(error);
});
} else {
this._sender.send(data, options, cb);
}
}...
});
```
##### Sending OSC messages:
```javascript
// For most Ports, send() should only be called after the "ready" event fires.
oscPort.on("ready", function () {
oscPort.send({
address: "/carrier/frequency",
args: 440
});
});
```
##### Sending OSC bundles:
...function stream(options, cb) {
if (typeof options === 'function') {
cb = options;
options = {};
}
var self = this;
if (typeof cb !== 'function') throw new Error('callback must be provided');
if (this.readyState !== WebSocket.OPEN) {
if (typeof cb === 'function') cb(new Error('not opened'));
else throw new Error('not opened');
return;
}
if (this._queue) {
this._queue.push(function () { self.stream(options, cb); });
return;
}
options = options || {};
if (typeof options.mask === 'undefined') options.mask = !this._isServer;
if (typeof options.compress === 'undefined') options.compress = true;
if (!this.extensions[PerMessageDeflate.extensionName]) {
options.compress = false;
}
startQueue(this);
function send(data, final) {
try {
if (self.readyState !== WebSocket.OPEN) throw new Error('not opened');
options.fin = final === true;
self._sender.send(data, options);
if (!final) process.nextTick(cb.bind(null, null, send));
else executeQueueSends(self);
} catch (e) {
if (typeof cb === 'function') cb(e);
else {
delete self._queue;
self.emit('error', e);
}
}
}
process.nextTick(cb.bind(null, null, send));
}n/a
function terminate() {
if (this.readyState === WebSocket.CLOSED) return;
if (this._socket) {
this.readyState = WebSocket.CLOSING;
// End the connection
try { this._socket.end(); }
catch (e) {
// Socket error during end() call, so just destroy it right now
cleanupWebsocketResources.call(this, true);
return;
}
// Add a timeout to ensure that the connection is completely
// cleaned up within 30 seconds, even if the clean close procedure
// fails for whatever reason
// First cleanup any pre-existing timeout from an earlier "terminate" call,
// if one exists. Otherwise terminate calls in quick succession will leak timeouts
// and hold the program open for `closeTimout` time.
if (this._closeTimer) { clearTimeout(this._closeTimer); }
this._closeTimer = setTimeout(cleanupWebsocketResources.bind(this, true), closeTimeout);
} else if (this.readyState === WebSocket.CONNECTING) {
cleanupWebsocketResources.call(this, true);
}
}n/a
WebSocketPort = function (options) {
osc.Port.call(this, options);
this.on("open", this.listen.bind(this));
this.socket = options.socket;
if (this.socket) {
if (this.socket.readyState === 1) {
osc.WebSocketPort.setupSocketForBinary(this.socket);
this.emit("open", this.socket);
} else {
this.open();
}
}
}...
</head>
<body></body>
</html>
```
##### Creating an OSC Web Socket Port object:
```javascript
var oscPort = new osc.WebSocketPort({
url: "ws://localhost:8081" // URL to your Web Socket server.
});
```
##### Opening the Port:
```javascript
oscPort.open();
...setupSocketForBinary = function (socket) {
socket.binaryType = osc.isNode ? "nodebuffer" : "arraybuffer";
}...
osc.WebSocketPort = function (options) {
osc.Port.call(this, options);
this.on("open", this.listen.bind(this));
this.socket = options.socket;
if (this.socket) {
if (this.socket.readyState === 1) {
osc.WebSocketPort.setupSocketForBinary(this.socket);
this.emit("open", this.socket);
} else {
this.open();
}
}
};
...close = function (code, reason) {
this.socket.close(code, reason);
}...
p.open = function () {
this.port1.open();
this.port2.open();
};
p.listen = function () {
if (this.port1Spec && this.port2Spec) {
this.close();
}
this.port1Spec = osc.relayPorts(this.port1, this.port2, this.options);
this.port2Spec = osc.relayPorts(this.port2, this.port1, this.options);
// Bind port close listeners to ensure that the relay
// will stop forwarding messages if one of its ports close.
...constructor = function (options) {
osc.Port.call(this, options);
this.on("open", this.listen.bind(this));
this.socket = options.socket;
if (this.socket) {
if (this.socket.readyState === 1) {
osc.WebSocketPort.setupSocketForBinary(this.socket);
this.emit("open", this.socket);
} else {
this.open();
}
}
}n/a
listen = function () {
var that = this;
this.socket.onmessage = function (e) {
that.emit("data", e.data, e);
};
this.socket.onerror = function (err) {
that.emit("error", err);
};
this.socket.onclose = function (e) {
that.emit("close", e);
};
that.emit("ready");
}...
var osc = require("osc"),
http = require("http"),
WebSocket = require("ws");
// Create an Express server app
// and serve up a directory of static files.
var app = require("express").express(),
server = app.listen(8081);
app.use("/", express.static(__dirname + "/static"));
// Listen for Web Socket requests.
var wss = new WebSocket.Server({
server: server
});
...open = function () {
if (!this.socket || this.socket.readyState > 1) {
this.socket = new osc.WebSocket(this.options.url);
}
osc.WebSocketPort.setupSocketForBinary(this.socket);
var that = this;
this.socket.onopen = function () {
that.emit("open", that.socket);
};
}...
var oscPort = new osc.WebSocketPort({
url: "ws://localhost:8081" // URL to your Web Socket server.
});
```
##### Opening the Port:
```javascript
oscPort.open();
```
##### Listening for incoming OSC messages:
```javascript
oscPort.on("message", function (oscMsg) {
console.log("An OSC message just arrived!", oscMsg);
});
...sendRaw = function (encoded) {
if (!this.socket || this.socket.readyState !== 1) {
osc.fireClosedPortSendError(this);
return;
}
this.socket.send(encoded);
}n/a
Port = function (options) {
this.options = options || {};
this.on("data", this.decodeOSC.bind(this));
}n/a
Relay = function (port1, port2, options) {
var o = this.options = options || {};
o.raw = false;
this.port1 = port1;
this.port2 = port2;
this.listen();
}n/a
SLIPPort = function (options) {
var that = this;
var o = this.options = options || {};
o.useSLIP = o.useSLIP === undefined ? true : o.useSLIP;
this.decoder = new slip.Decoder({
onMessage: this.decodeOSC.bind(this),
onError: function (err) {
that.emit("error", err);
}
});
var decodeHandler = o.useSLIP ? this.decodeSLIPData : this.decodeOSC;
this.on("data", decodeHandler.bind(this));
}n/a
function WebSocket(address, protocols, options) {
if (this instanceof WebSocket === false) {
return new WebSocket(address, protocols, options);
}
EventEmitter.call(this);
if (protocols && !Array.isArray(protocols) && 'object' === typeof protocols) {
// accept the "options" Object as the 2nd argument
options = protocols;
protocols = null;
}
if ('string' === typeof protocols) {
protocols = [ protocols ];
}
if (!Array.isArray(protocols)) {
protocols = [];
}
this._socket = null;
this._ultron = null;
this._closeReceived = false;
this.bytesReceived = 0;
this.readyState = null;
this.supports = {};
this.extensions = {};
this._binaryType = 'nodebuffer';
if (Array.isArray(address)) {
initAsServerClient.apply(this, address.concat(options));
} else {
initAsClient.apply(this, [address, protocols, options]);
}
}...
};
var p = osc.WebSocketPort.prototype = Object.create(osc.Port.prototype);
p.constructor = osc.WebSocketPort;
p.open = function () {
if (!this.socket || this.socket.readyState > 1) {
this.socket = new osc.WebSocket(this.options.url);
}
osc.WebSocketPort.setupSocketForBinary(this.socket);
var that = this;
this.socket.onopen = function () {
that.emit("open", that.socket);
...WebSocketPort = function (options) {
osc.Port.call(this, options);
this.on("open", this.listen.bind(this));
this.socket = options.socket;
if (this.socket) {
if (this.socket.readyState === 1) {
osc.WebSocketPort.setupSocketForBinary(this.socket);
this.emit("open", this.socket);
} else {
this.open();
}
}
}...
</head>
<body></body>
</html>
```
##### Creating an OSC Web Socket Port object:
```javascript
var oscPort = new osc.WebSocketPort({
url: "ws://localhost:8081" // URL to your Web Socket server.
});
```
##### Opening the Port:
```javascript
oscPort.open();
...addDataPart = function (dataPart, dataCollection) {
dataCollection.parts.push(dataPart);
dataCollection.byteLength += dataPart.length;
}...
}
var type = arg.type,
writer = osc.argumentTypes[type].writer;
if (writer) {
var data = osc[writer](arg.value);
osc.addDataPart(data, dataCollection);
}
return arg.type;
};
// Unsupported, non-API function.
osc.collectArguments = function (args, options, dataCollection) {
...annotateArguments = function (args) {
var annotated = [];
for (var i = 0; i < args.length; i++) {
var arg = args[i],
msgArg;
if (typeof (arg) === "object" && arg.type && arg.value !== undefined) {
// We've got an explicitly typed argument.
msgArg = arg;
} else if (osc.isArray(arg)) {
// We've got an array of arguments,
// so they each need to be inferred and expanded.
msgArg = osc.annotateArguments(arg);
} else {
var oscType = osc.inferTypeForArgument(arg);
msgArg = {
type: oscType,
value: arg
};
}
annotated.push(msgArg);
}
return annotated;
}...
dataCollection = dataCollection || {
byteLength: 0,
parts: []
};
if (!options.metadata) {
args = osc.annotateArguments(args);
}
var typeTagString = ",",
currPartIdx = dataCollection.parts.length;
for (var i = 0; i < args.length; i++) {
var arg = args[i];
...byteArray = function (obj) {
if (obj instanceof Uint8Array) {
return obj;
}
var buf = obj.buffer ? obj.buffer : obj;
if (!(buf instanceof ArrayBuffer) && (typeof buf.length === "undefined" || typeof buf === "string")) {
throw new Error("Can't wrap a non-array-like object as Uint8Array. Object was: " +
JSON.stringify(obj, null, 2));
}
// TODO gh-39: This is a potentially unsafe algorithm;
// if we're getting anything other than a TypedArrayView (such as a DataView),
// we really need to determine the range of the view it is viewing.
return new Uint8Array(buf);
}...
/**
* Writes a raw collection of bytes to a new ArrayBuffer.
*
* @param {Array-like} data a collection of octets
* @return {ArrayBuffer} a buffer containing the OSC-formatted blob
*/
osc.writeBlob = function (data) {
data = osc.byteArray(data);
var len = data.byteLength,
paddedLen = (len + 3) & ~0x03,
offset = 4, // Extra 4 bytes is for the size.
blobLen = paddedLen + offset,
arr = new Uint8Array(blobLen),
dv = new DataView(arr.buffer);
...collectArguments = function (args, options, dataCollection) {
if (!osc.isArray(args)) {
args = typeof args === "undefined" ? [] : [args];
}
dataCollection = dataCollection || {
byteLength: 0,
parts: []
};
if (!options.metadata) {
args = osc.annotateArguments(args);
}
var typeTagString = ",",
currPartIdx = dataCollection.parts.length;
for (var i = 0; i < args.length; i++) {
var arg = args[i];
typeTagString += osc.writeArgument(arg, dataCollection);
}
var typeData = osc.writeString(typeTagString);
dataCollection.byteLength += typeData.byteLength;
dataCollection.parts.splice(currPartIdx, 0, typeData);
return dataCollection;
}...
* Writes the specified arguments.
*
* @param {Array} args an array of arguments
* @param {Object} options options for writing
* @return {Uint8Array} a buffer containing the OSC-formatted argument type tag and values
*/
osc.writeArguments = function (args, options) {
var argCollection = osc.collectArguments(args, options);
return osc.joinParts(argCollection);
};
// Unsupported, non-API function.
osc.joinParts = function (dataCollection) {
var buf = new Uint8Array(dataCollection.byteLength),
parts = dataCollection.parts,
...collectBundlePackets = function (bundle, options, dataCollection) {
dataCollection = dataCollection || {
byteLength: 0,
parts: []
};
osc.addDataPart(osc.writeString("#bundle"), dataCollection);
osc.addDataPart(osc.writeTimeTag(bundle.timeTag), dataCollection);
for (var i = 0; i < bundle.packets.length; i++) {
var packet = bundle.packets[i],
collector = packet.address ? osc.collectMessageParts : osc.collectBundlePackets,
packetCollection = collector(packet, options);
dataCollection.byteLength += packetCollection.byteLength;
osc.addDataPart(osc.writeInt32(packetCollection.byteLength), dataCollection);
dataCollection.parts = dataCollection.parts.concat(packetCollection.parts);
}
return dataCollection;
}...
osc.writeBundle = function (bundle, options) {
if (!osc.isValidBundle(bundle)) {
throw new Error("An OSC bundle must contain 'timeTag' and 'packets' properties. " +
"Bundle was: " + JSON.stringify(bundle, null, 2));
}
options = options || osc.defaults;
var bundleCollection = osc.collectBundlePackets(bundle, options);
return osc.joinParts(bundleCollection);
};
osc.isValidBundle = function (bundle) {
return bundle.timeTag !== undefined && bundle.packets !== undefined;
};
...collectMessageParts = function (msg, options, dataCollection) {
dataCollection = dataCollection || {
byteLength: 0,
parts: []
};
osc.addDataPart(osc.writeString(msg.address), dataCollection);
return osc.collectArguments(msg.args, options, dataCollection);
}...
options = options || osc.defaults;
if (!osc.isValidMessage(msg)) {
throw new Error("An OSC message must contain a valid address. Message was: " +
JSON.stringify(msg, null, 2));
}
var msgCollection = osc.collectMessageParts(msg, options);
return osc.joinParts(msgCollection);
};
osc.isValidMessage = function (msg) {
return msg.address && msg.address.indexOf("/") === 0;
};
...copyByteArray = function (source, target, offset) {
if (osc.isTypedArrayView(source) && osc.isTypedArrayView(target)) {
target.set(source, offset);
} else {
var start = offset === undefined ? 0 : offset,
len = Math.min(target.length - offset, source.length);
for (var i = 0, j = start; i < len; i++, j++) {
target[j] = source[i];
}
}
return target;
}...
osc.joinParts = function (dataCollection) {
var buf = new Uint8Array(dataCollection.byteLength),
parts = dataCollection.parts,
offset = 0;
for (var i = 0; i < parts.length; i++) {
var part = parts[i];
osc.copyByteArray(part, buf, offset);
offset += part.length;
}
return buf;
};
// Unsupported, non-API function.
...dataView = function (obj, offset, length) {
if (obj.buffer) {
return new DataView(obj.buffer, offset, length);
}
if (obj instanceof ArrayBuffer) {
return new DataView(obj, offset, length);
}
return new DataView(new Uint8Array(obj), offset, length);
}...
* @param {Object} [options] read options
* @param {Object} [offsetState] an offsetState object that stores the current offset into dv
* @return {Object} the OSC message, formatted as a JavaScript object containing "address" and "args" properties
*/
osc.readMessage = function (data, options, offsetState) {
options = options || osc.defaults;
var dv = osc.dataView(data, data.byteOffset, data.byteLength);
offsetState = offsetState || {
idx: 0
};
var address = osc.readString(dv, offsetState);
return osc.readMessageContents(address, dv, options, offsetState);
};
...fireBundleEvents = function (port, bundle, timeTag, packetInfo) {
port.emit("bundle", bundle, timeTag, packetInfo);
for (var i = 0; i < bundle.packets.length; i++) {
var packet = bundle.packets[i];
osc.firePacketEvents(port, packet, bundle.timeTag, packetInfo);
}
}...
"use strict";
// Unsupported, non-API function.
osc.firePacketEvents = function (port, packet, timeTag, packetInfo) {
if (packet.address) {
port.emit("message", packet, timeTag, packetInfo);
} else {
osc.fireBundleEvents(port, packet, timeTag, packetInfo);
}
};
// Unsupported, non-API function.
osc.fireBundleEvents = function (port, bundle, timeTag, packetInfo) {
port.emit("bundle", bundle, timeTag, packetInfo);
for (var i = 0; i < bundle.packets.length; i++) {
...fireClosedPortSendError = function (port, msg) {
msg = msg || "Can't send packets on a closed osc.Port object. Please open (or reopen) this Port by calling open().";
port.emit("error", msg);
}...
p.listen = function () {
osc.listenToTransport(this, chrome.serial, "connectionId");
};
p.sendRaw = function (encoded) {
if (!this.connectionId) {
osc.fireClosedPortSendError(this);
return;
}
var that = this;
// TODO gh-39: This is unsafe; we should only access the underlying
// buffer within the range of its view.
...firePacketEvents = function (port, packet, timeTag, packetInfo) {
if (packet.address) {
port.emit("message", packet, timeTag, packetInfo);
} else {
osc.fireBundleEvents(port, packet, timeTag, packetInfo);
}
}...
};
// Unsupported, non-API function.
osc.fireBundleEvents = function (port, bundle, timeTag, packetInfo) {
port.emit("bundle", bundle, timeTag, packetInfo);
for (var i = 0; i < bundle.packets.length; i++) {
var packet = bundle.packets[i];
osc.firePacketEvents(port, packet, bundle.timeTag, packetInfo);
}
};
osc.fireClosedPortSendError = function (port, msg) {
msg = msg || "Can't send packets on a closed osc.Port object. Please open (or reopen) this Port by calling open()."
;;
port.emit("error", msg);
...inferTypeForArgument = function (arg) {
var type = typeof arg;
// TODO: This is freaking hideous.
switch (type) {
case "boolean":
return arg ? "T" : "F";
case "string":
return "s";
case "number":
return "f";
case "undefined":
return "N";
case "object":
if (arg === null) {
return "N";
} else if (arg instanceof Uint8Array ||
arg instanceof ArrayBuffer) {
return "b";
} else if (typeof arg.high === "number" && typeof arg.low === "number") {
return "h";
}
break;
}
throw new Error("Can't infer OSC argument type for value: " +
JSON.stringify(arg, null, 2));
}...
// We've got an explicitly typed argument.
msgArg = arg;
} else if (osc.isArray(arg)) {
// We've got an array of arguments,
// so they each need to be inferred and expanded.
msgArg = osc.annotateArguments(arg);
} else {
var oscType = osc.inferTypeForArgument(arg);
msgArg = {
type: oscType,
value: arg
};
}
annotated.push(msgArg);
...isArray = function (obj) {
return obj && Object.prototype.toString.call(obj) === "[object Array]";
}...
typeTag += "]";
return typeTag;
};
osc.writeArgument = function (arg, dataCollection) {
if (osc.isArray(arg)) {
return osc.writeArrayArguments(arg, dataCollection);
}
var type = arg.type,
writer = osc.argumentTypes[type].writer;
if (writer) {
...isBuffer = function (obj) {
return osc.isBufferEnv && obj instanceof Buffer;
}...
*
* @param {Array-like or Array-wrapping} obj an array-like or array-wrapping object
* @returns {Buffer|Uint8Array} a buffer object
*/
// Unsupported, non-API function.
osc.nativeBuffer = function (obj) {
if (osc.isBufferEnv) {
return osc.isBuffer(obj) ? obj :
new Buffer(obj.buffer ? obj : new Uint8Array(obj));
}
return osc.isTypedArrayView(obj) ? obj : new Uint8Array(obj);
};
// Unsupported, non-API function
...isTypedArrayView = function (obj) {
return obj.buffer && obj.buffer instanceof ArrayBuffer;
}...
// Unsupported, non-API function.
osc.nativeBuffer = function (obj) {
if (osc.isBufferEnv) {
return osc.isBuffer(obj) ? obj :
new Buffer(obj.buffer ? obj : new Uint8Array(obj));
}
return osc.isTypedArrayView(obj) ? obj : new Uint8Array(obj);
};
// Unsupported, non-API function
osc.copyByteArray = function (source, target, offset) {
if (osc.isTypedArrayView(source) && osc.isTypedArrayView(target)) {
target.set(source, offset);
} else {
...isValidBundle = function (bundle) {
return bundle.timeTag !== undefined && bundle.packets !== undefined;
}...
* Writes an OSC bundle.
*
* @param {Object} a bundle object containing "timeTag" and "packets" properties
* @param {object} [options] write options
* @return {Uint8Array} an array of bytes containing the message
*/
osc.writeBundle = function (bundle, options) {
if (!osc.isValidBundle(bundle)) {
throw new Error("An OSC bundle must contain 'timeTag' and 'packets' properties. " +
"Bundle was: " + JSON.stringify(bundle, null, 2));
}
options = options || osc.defaults;
var bundleCollection = osc.collectBundlePackets(bundle, options);
...isValidMessage = function (msg) {
return msg.address && msg.address.indexOf("/") === 0;
}...
* @param {Object} msg a message object containing "address" and "args" properties
* @param {Object} [options] write options
* @return {Uint8Array} an array of bytes containing the OSC message
*/
osc.writeMessage = function (msg, options) {
options = options || osc.defaults;
if (!osc.isValidMessage(msg)) {
throw new Error("An OSC message must contain a valid address. Message was: " +
JSON.stringify(msg, null, 2));
}
var msgCollection = osc.collectMessageParts(msg, options);
return osc.joinParts(msgCollection);
};
...joinParts = function (dataCollection) {
var buf = new Uint8Array(dataCollection.byteLength),
parts = dataCollection.parts,
offset = 0;
for (var i = 0; i < parts.length; i++) {
var part = parts[i];
osc.copyByteArray(part, buf, offset);
offset += part.length;
}
return buf;
}...
*
* @param {Array} args an array of arguments
* @param {Object} options options for writing
* @return {Uint8Array} a buffer containing the OSC-formatted argument type tag and values
*/
osc.writeArguments = function (args, options) {
var argCollection = osc.collectArguments(args, options);
return osc.joinParts(argCollection);
};
// Unsupported, non-API function.
osc.joinParts = function (dataCollection) {
var buf = new Uint8Array(dataCollection.byteLength),
parts = dataCollection.parts,
offset = 0;
...jsToNTPTime = function (jsTime) {
var secs = jsTime / 1000,
secsWhole = Math.floor(secs),
secsFrac = secs - secsWhole,
ntpSecs = secsWhole + osc.SECS_70YRS,
ntpFracs = Math.round(osc.TWO_32 * secsFrac);
return [ntpSecs, ntpFracs];
}...
* values. The first represents the number of seconds since January 1, 1900; the second, fractions of a second.
* "Native" JavaScript timestamps are specified as a Number representing milliseconds since January 1, 1970.
*
* @param {Object} timeTag time tag object containing either a native JS timestamp (in ms) or a NTP timestamp pair
* @return {Uint8Array} raw bytes for the written time tag
*/
osc.writeTimeTag = function (timeTag) {
var raw = timeTag.raw ? timeTag.raw : osc.jsToNTPTime(timeTag.native),
arr = new Uint8Array(8), // Two Unit32s.
dv = new DataView(arr.buffer);
osc.writeInt32(raw[0], dv, 0);
osc.writeInt32(raw[1], dv, 4);
return arr;
...nativeBuffer = function (obj) {
if (osc.isBufferEnv) {
return osc.isBuffer(obj) ? obj :
new Buffer(obj.buffer ? obj : new Uint8Array(obj));
}
return osc.isTypedArrayView(obj) ? obj : new Uint8Array(obj);
}...
var p = osc.Port.prototype = Object.create(EventEmitter.prototype);
p.constructor = osc.Port;
p.send = function (oscPacket) {
var args = Array.prototype.slice.call(arguments),
encoded = this.encodeOSC(oscPacket),
buf = osc.nativeBuffer(encoded);
args[0] = buf;
this.sendRaw.apply(this, args);
};
p.encodeOSC = function (packet) {
// TODO gh-39: This is unsafe; we should only access the underlying
...ntpToJSTime = function (secs1900, frac) {
var secs1970 = secs1900 - osc.SECS_70YRS,
decimals = frac / osc.TWO_32,
msTime = (secs1970 + decimals) * 1000;
return msTime;
}...
* @param {DataView} dv the DataView instance to read from
* @param {Object} offsetState an offset state object containing the current index into dv
* @param {Object} a time tag object containing both the raw NTP as well as the converted native (i.e. JS/UNIX) time
*/
osc.readTimeTag = function (dv, offsetState) {
var secs1900 = osc.readPrimitive(dv, "getUint32", 4, offsetState),
frac = osc.readPrimitive(dv, "getUint32", 4, offsetState),
native = (secs1900 === 0 && frac === 1) ? Date.now() : osc.ntpToJSTime(secs1900, frac);
return {
raw: [secs1900, frac],
native: native
};
};
...readArgument = function (argType, typeTagString, dv, options, offsetState) {
var typeSpec = osc.argumentTypes[argType];
if (!typeSpec) {
throw new Error("'" + argType + "' is not a valid OSC type tag. Type tag string was: " + typeTagString);
}
var argReader = typeSpec.reader,
arg = osc[argReader](dv, offsetState);
if (options.metadata) {
arg = {
type: argType,
value: arg
};
}
return arg;
}...
"without a matching close array tag ('[]'). Type tag was: " + typeTagString);
}
var typesInArray = fromArrayOpen.slice(0, endArrayIdx);
arg = osc.readArgumentsIntoArray([], typesInArray, typeTagString, dv, options, offsetState);
i += endArrayIdx + 2;
} else {
arg = osc.readArgument(argType, typeTagString, dv, options, offsetState);
i++;
}
arr.push(arg);
}
return arr;
...readArguments = function (dv, options, offsetState) {
var typeTagString = osc.readString(dv, offsetState);
if (typeTagString.indexOf(",") !== 0) {
// Despite what the OSC 1.0 spec says,
// it just doesn't make sense to handle messages without type tags.
// scsynth appears to read such messages as if they have a single
// Uint8 argument. sclang throws an error if the type tag is omitted.
throw new Error("A malformed type tag string was found while reading " +
"the arguments of an OSC message. String was: " +
typeTagString, " at offset: " + offsetState.idx);
}
var argTypes = typeTagString.substring(1).split(""),
args = [];
osc.readArgumentsIntoArray(args, argTypes, typeTagString, dv, options, offsetState);
return args;
}...
// Unsupported, non-API function.
osc.readMessageContents = function (address, dv, options, offsetState) {
if (address.indexOf("/") !== 0) {
throw new Error("A malformed OSC address was found while reading " +
"an OSC message. String was: " + address);
}
var args = osc.readArguments(dv, options, offsetState);
return {
address: address,
args: args.length === 1 && options.unpackSingleArgs ? args[0] : args
};
};
...readArgumentsIntoArray = function (arr, argTypes, typeTagString, dv, options, offsetState) {
var i = 0;
while (i < argTypes.length) {
var argType = argTypes[i],
arg;
if (argType === "[") {
var fromArrayOpen = argTypes.slice(i + 1),
endArrayIdx = fromArrayOpen.indexOf("]");
if (endArrayIdx < 0) {
throw new Error("Invalid argument type tag: an open array type tag ('[') was found " +
"without a matching close array tag ('[]'). Type tag was: " + typeTagString);
}
var typesInArray = fromArrayOpen.slice(0, endArrayIdx);
arg = osc.readArgumentsIntoArray([], typesInArray, typeTagString, dv, options, offsetState);
i += endArrayIdx + 2;
} else {
arg = osc.readArgument(argType, typeTagString, dv, options, offsetState);
i++;
}
arr.push(arg);
}
return arr;
}...
"the arguments of an OSC message. String was: " +
typeTagString, " at offset: " + offsetState.idx);
}
var argTypes = typeTagString.substring(1).split(""),
args = [];
osc.readArgumentsIntoArray(args, argTypes, typeTagString, dv, options, offsetState
);
return args;
};
// Unsupported, non-API function.
osc.readArgument = function (argType, typeTagString, dv, options, offsetState) {
var typeSpec = osc.argumentTypes[argType];
...readBlob = function (dv, offsetState) {
var len = osc.readInt32(dv, offsetState),
paddedLen = (len + 3) & ~0x03,
blob = new Uint8Array(dv.buffer, offsetState.idx, len);
offsetState.idx += paddedLen;
return blob;
}n/a
readBundle = function (dv, options, offsetState) {
return osc.readPacket(dv, options, offsetState);
}n/a
readBundleContents = function (dv, options, offsetState, len) {
var timeTag = osc.readTimeTag(dv, offsetState),
packets = [];
while (offsetState.idx < len) {
var packetSize = osc.readInt32(dv, offsetState),
packetLen = offsetState.idx + packetSize,
packet = osc.readPacket(dv, options, offsetState, packetLen);
packets.push(packet);
}
return {
timeTag: timeTag,
packets: packets
};
}...
idx: 0
};
var header = osc.readString(dv, offsetState),
firstChar = header[0];
if (firstChar === "#") {
return osc.readBundleContents(dv, options, offsetState, len);
} else if (firstChar === "/") {
return osc.readMessageContents(header, dv, options, offsetState);
}
throw new Error("The header of an OSC packet didn't contain an OSC address or a #bundle string." +
" Header was: " + header);
};
...readChar32 = function (dv, offsetState) {
var charCode = osc.readPrimitive(dv, "getUint32", 4, offsetState);
return String.fromCharCode(charCode);
}n/a
readColor = function (dv, offsetState) {
var bytes = new Uint8Array(dv.buffer, offsetState.idx, 4),
alpha = bytes[3] / 255;
offsetState.idx += 4;
return {
r: bytes[0],
g: bytes[1],
b: bytes[2],
a: alpha
};
}n/a
readFalse = function () {
return false;
}n/a
readFloat32 = function (dv, offsetState) {
return osc.readPrimitive(dv, "getFloat32", 4, offsetState);
}n/a
readFloat64 = function (dv, offsetState) {
return osc.readPrimitive(dv, "getFloat64", 8, offsetState);
}n/a
readImpulse = function () {
return 1.0;
}n/a
readInt32 = function (dv, offsetState) {
return osc.readPrimitive(dv, "getInt32", 4, offsetState);
}...
* Reads an OSC blob ("b") (i.e. a Uint8Array).
*
* @param {DataView} dv a DataView instance to read from
* @param {Object} offsetState an offsetState object used to store the current offset index into dv
* @return {Uint8Array} the data that was read
*/
osc.readBlob = function (dv, offsetState) {
var len = osc.readInt32(dv, offsetState),
paddedLen = (len + 3) & ~0x03,
blob = new Uint8Array(dv.buffer, offsetState.idx, len);
offsetState.idx += paddedLen;
return blob;
};
...readInt64 = function (dv, offsetState) {
var high = osc.readPrimitive(dv, "getInt32", 4, offsetState),
low = osc.readPrimitive(dv, "getInt32", 4, offsetState);
if (Long) {
return new Long(low, high);
} else {
return {
high: high,
low: low,
unsigned: false
};
}
}n/a
readMIDIBytes = function (dv, offsetState) {
var midi = new Uint8Array(dv.buffer, offsetState.idx, 4);
offsetState.idx += 4;
return midi;
}n/a
readMessage = function (data, options, offsetState) {
options = options || osc.defaults;
var dv = osc.dataView(data, data.byteOffset, data.byteLength);
offsetState = offsetState || {
idx: 0
};
var address = osc.readString(dv, offsetState);
return osc.readMessageContents(address, dv, options, offsetState);
}n/a
readMessageContents = function (address, dv, options, offsetState) {
if (address.indexOf("/") !== 0) {
throw new Error("A malformed OSC address was found while reading " +
"an OSC message. String was: " + address);
}
var args = osc.readArguments(dv, options, offsetState);
return {
address: address,
args: args.length === 1 && options.unpackSingleArgs ? args[0] : args
};
}...
var dv = osc.dataView(data, data.byteOffset, data.byteLength);
offsetState = offsetState || {
idx: 0
};
var address = osc.readString(dv, offsetState);
return osc.readMessageContents(address, dv, options, offsetState);
};
// Unsupported, non-API function.
osc.readMessageContents = function (address, dv, options, offsetState) {
if (address.indexOf("/") !== 0) {
throw new Error("A malformed OSC address was found while reading " +
"an OSC message. String was: " + address);
...readNull = function () {
return null;
}n/a
readPacket = function (data, options, offsetState, len) {
var dv = osc.dataView(data, data.byteOffset, data.byteLength);
len = len === undefined ? dv.byteLength : len;
offsetState = offsetState || {
idx: 0
};
var header = osc.readString(dv, offsetState),
firstChar = header[0];
if (firstChar === "#") {
return osc.readBundleContents(dv, options, offsetState, len);
} else if (firstChar === "/") {
return osc.readMessageContents(header, dv, options, offsetState);
}
throw new Error("The header of an OSC packet didn't contain an OSC address or a #bundle string." +
" Header was: " + header);
}...
they should be caught and handled using
<code>try</code>/<code>catch</code>.
```javascript
var msg;
try {
msg = osc.readPacket(rawPacket);
} catch (error) {
console.log("An error occurred: ", error.message);
}
```
The osc.js Low-Level API
------------------------
...readPrimitive = function (dv, readerName, numBytes, offsetState) {
var val = dv[readerName](offsetState.idx, false);
offsetState.idx += numBytes;
return val;
}...
* Reads an OSC int32 ("i") value.
*
* @param {DataView} dv a DataView containing the raw bytes
* @param {Object} offsetState an offsetState object used to store the current offset index into dv
* @return {Number} the number that was read
*/
osc.readInt32 = function (dv, offsetState) {
return osc.readPrimitive(dv, "getInt32", 4, offsetState);
};
/**
* Writes an OSC int32 ("i") value.
*
* @param {Number} val the number to write
* @param {DataView} [dv] a DataView instance to write the number into
...readString = function (dv, offsetState) {
var charCodes = [],
idx = offsetState.idx;
for (; idx < dv.byteLength; idx++) {
var charCode = dv.getUint8(idx);
if (charCode !== 0) {
charCodes.push(charCode);
} else {
idx++;
break;
}
}
// Round to the nearest 4-byte block.
idx = (idx + 3) & ~0x03;
offsetState.idx = idx;
return String.fromCharCode.apply(null, charCodes);
}...
*
* @param {DataView} dv a DataView instance to read from
* @param {Object} offsetState the offsetState object that stores the current offset into dv
* @param {Oobject} [options] read options
* @return {Array} an array of the OSC arguments that were read
*/
osc.readArguments = function (dv, options, offsetState) {
var typeTagString = osc.readString(dv, offsetState);
if (typeTagString.indexOf(",") !== 0) {
// Despite what the OSC 1.0 spec says,
// it just doesn't make sense to handle messages without type tags.
// scsynth appears to read such messages as if they have a single
// Uint8 argument. sclang throws an error if the type tag is omitted.
throw new Error("A malformed type tag string was found while reading " +
"the arguments of an OSC message. String was: " +
...readTimeTag = function (dv, offsetState) {
var secs1900 = osc.readPrimitive(dv, "getUint32", 4, offsetState),
frac = osc.readPrimitive(dv, "getUint32", 4, offsetState),
native = (secs1900 === 0 && frac === 1) ? Date.now() : osc.ntpToJSTime(secs1900, frac);
return {
raw: [secs1900, frac],
native: native
};
}...
osc.isValidBundle = function (bundle) {
return bundle.timeTag !== undefined && bundle.packets !== undefined;
};
// Unsupported, non-API function.
osc.readBundleContents = function (dv, options, offsetState, len) {
var timeTag = osc.readTimeTag(dv, offsetState),
packets = [];
while (offsetState.idx < len) {
var packetSize = osc.readInt32(dv, offsetState),
packetLen = offsetState.idx + packetSize,
packet = osc.readPacket(dv, options, offsetState, packetLen);
...readTrue = function () {
return true;
}n/a
relay = function (from, to, eventName, sendFnName, transformFn, sendArgs) {
eventName = eventName || "message";
sendFnName = sendFnName || "send";
transformFn = transformFn || function () {};
sendArgs = sendArgs ? [null].concat(sendArgs) : [];
var listener = function (data) {
sendArgs[0] = data;
data = transformFn(data);
to[sendFnName].apply(to, sendArgs);
};
from.on(eventName, listener);
return {
eventName: eventName,
listener: listener
};
}...
};
// Unsupported, non-API function.
osc.relayPorts = function (from, to, o) {
var eventName = o.raw ? "raw" : "osc",
sendFnName = o.raw ? "sendRaw" : "send";
return osc.relay(from, to, eventName, sendFnName, o.transform);
};
// Unsupported, non-API function.
osc.stopRelaying = function (from, relaySpec) {
from.removeListener(relaySpec.eventName, relaySpec.listener);
};
...relayPorts = function (from, to, o) {
var eventName = o.raw ? "raw" : "osc",
sendFnName = o.raw ? "sendRaw" : "send";
return osc.relay(from, to, eventName, sendFnName, o.transform);
}...
};
p.listen = function () {
if (this.port1Spec && this.port2Spec) {
this.close();
}
this.port1Spec = osc.relayPorts(this.port1, this.port2, this.options);
this.port2Spec = osc.relayPorts(this.port2, this.port1, this.options);
// Bind port close listeners to ensure that the relay
// will stop forwarding messages if one of its ports close.
// Users are still responsible for closing the underlying ports
// if necessary.
var closeListener = this.close.bind(this);
...stopRelaying = function (from, relaySpec) {
from.removeListener(relaySpec.eventName, relaySpec.listener);
}...
// if necessary.
var closeListener = this.close.bind(this);
this.port1.on("close", closeListener);
this.port2.on("close", closeListener);
};
p.close = function () {
osc.stopRelaying(this.port1, this.port1Spec);
osc.stopRelaying(this.port2, this.port2Spec);
this.emit("close", this.port1, this.port2);
};
// If we're in a require-compatible environment, export ourselves.
if (typeof module !== "undefined" && module.exports) {
...timeTag = function (secs, now) {
secs = secs || 0;
now = now || Date.now();
var nowSecs = now / 1000,
nowWhole = Math.floor(nowSecs),
nowFracs = nowSecs - nowWhole,
secsWhole = Math.floor(secs),
secsFracs = secs - secsWhole,
fracs = nowFracs + secsFracs;
if (fracs > 1) {
var fracsWhole = Math.floor(fracs),
fracsFracs = fracs - fracsWhole;
secsWhole += fracsWhole;
fracs = fracsFracs;
}
var ntpSecs = nowWhole + secsWhole + osc.SECS_70YRS,
ntpFracs = Math.round(osc.TWO_32 * fracs);
return {
raw: [ntpSecs, ntpFracs]
};
}...
});
```
##### Sending OSC bundles:
```javascript
oscPort.on("ready", function () {
oscPort.send({
timeTag: osc.timeTag(60), // Schedules this bundle 60 seconds from now.
packets: [
{
address: "/carrier/frequency",
args: 440
},
{
address: "/carrier/amplitude"
...writeArgument = function (arg, dataCollection) {
if (osc.isArray(arg)) {
return osc.writeArrayArguments(arg, dataCollection);
}
var type = arg.type,
writer = osc.argumentTypes[type].writer;
if (writer) {
var data = osc[writer](arg.value);
osc.addDataPart(data, dataCollection);
}
return arg.type;
}...
};
osc.writeArrayArguments = function (args, dataCollection) {
var typeTag = "[";
for (var i = 0; i < args.length; i++) {
var arg = args[i];
typeTag += osc.writeArgument(arg, dataCollection);
}
typeTag += "]";
return typeTag;
};
...writeArguments = function (args, options) {
var argCollection = osc.collectArguments(args, options);
return osc.joinParts(argCollection);
}n/a
writeArrayArguments = function (args, dataCollection) {
var typeTag = "[";
for (var i = 0; i < args.length; i++) {
var arg = args[i];
typeTag += osc.writeArgument(arg, dataCollection);
}
typeTag += "]";
return typeTag;
}...
typeTag += "]";
return typeTag;
};
osc.writeArgument = function (arg, dataCollection) {
if (osc.isArray(arg)) {
return osc.writeArrayArguments(arg, dataCollection);
}
var type = arg.type,
writer = osc.argumentTypes[type].writer;
if (writer) {
var data = osc[writer](arg.value);
...writeBlob = function (data) {
data = osc.byteArray(data);
var len = data.byteLength,
paddedLen = (len + 3) & ~0x03,
offset = 4, // Extra 4 bytes is for the size.
blobLen = paddedLen + offset,
arr = new Uint8Array(blobLen),
dv = new DataView(arr.buffer);
// Write the size.
osc.writeInt32(len, dv);
// Since we're writing to a real ArrayBuffer,
// we don't need to pad the remaining bytes.
arr.set(data, offset);
return arr;
}n/a
writeBundle = function (bundle, options) {
if (!osc.isValidBundle(bundle)) {
throw new Error("An OSC bundle must contain 'timeTag' and 'packets' properties. " +
"Bundle was: " + JSON.stringify(bundle, null, 2));
}
options = options || osc.defaults;
var bundleCollection = osc.collectBundlePackets(bundle, options);
return osc.joinParts(bundleCollection);
}...
* @param {Object} [options] write options
* @return {Uint8Array} an array of bytes containing the message
*/
osc.writePacket = function (packet, options) {
if (osc.isValidMessage(packet)) {
return osc.writeMessage(packet, options);
} else if (osc.isValidBundle(packet)) {
return osc.writeBundle(packet, options);
} else {
throw new Error("The specified packet was not recognized as a valid OSC message or bundle." +
" Packet was: " + JSON.stringify(packet, null, 2));
}
};
// Unsupported, non-API.
...writeChar32 = function (str, dv, offset) {
var charCode = str.charCodeAt(0);
if (charCode === undefined || charCode < -1) {
return undefined;
}
return osc.writePrimitive(charCode, dv, "setUint32", 4, offset);
}n/a
writeColor = function (color) {
var alpha = Math.round(color.a * 255),
arr = new Uint8Array([color.r, color.g, color.b, alpha]);
return arr;
}n/a
writeFloat32 = function (val, dv, offset) {
return osc.writePrimitive(val, dv, "setFloat32", 4, offset);
}n/a
writeFloat64 = function (val, dv, offset) {
return osc.writePrimitive(val, dv, "setFloat64", 8, offset);
}n/a
writeInt32 = function (val, dv, offset) {
return osc.writePrimitive(val, dv, "setInt32", 4, offset);
}...
paddedLen = (len + 3) & ~0x03,
offset = 4, // Extra 4 bytes is for the size.
blobLen = paddedLen + offset,
arr = new Uint8Array(blobLen),
dv = new DataView(arr.buffer);
// Write the size.
osc.writeInt32(len, dv);
// Since we're writing to a real ArrayBuffer,
// we don't need to pad the remaining bytes.
arr.set(data, offset);
return arr;
};
...writeInt64 = function (val, dv, offset) {
var arr = new Uint8Array(8);
arr.set(osc.writePrimitive(val.high, dv, "setInt32", 4, offset), 0);
arr.set(osc.writePrimitive(val.low, dv, "setInt32", 4, offset + 4), 4);
return arr;
}n/a
writeMIDIBytes = function (bytes) {
bytes = osc.byteArray(bytes);
var arr = new Uint8Array(4);
arr.set(bytes);
return arr;
}n/a
writeMessage = function (msg, options) {
options = options || osc.defaults;
if (!osc.isValidMessage(msg)) {
throw new Error("An OSC message must contain a valid address. Message was: " +
JSON.stringify(msg, null, 2));
}
var msgCollection = osc.collectMessageParts(msg, options);
return osc.joinParts(msgCollection);
}...
*
* @param {Object} a bundle or message object
* @param {Object} [options] write options
* @return {Uint8Array} an array of bytes containing the message
*/
osc.writePacket = function (packet, options) {
if (osc.isValidMessage(packet)) {
return osc.writeMessage(packet, options);
} else if (osc.isValidBundle(packet)) {
return osc.writeBundle(packet, options);
} else {
throw new Error("The specified packet was not recognized as a valid OSC message or bundle." +
" Packet was: " + JSON.stringify(packet, null, 2));
}
};
...writePacket = function (packet, options) {
if (osc.isValidMessage(packet)) {
return osc.writeMessage(packet, options);
} else if (osc.isValidBundle(packet)) {
return osc.writeBundle(packet, options);
} else {
throw new Error("The specified packet was not recognized as a valid OSC message or bundle." +
" Packet was: " + JSON.stringify(packet, null, 2));
}
}...
<code>options</code>: (optional) An options object, described below; <br />
<code>offsetState</code>: (optional) an offset state object containing an <code>idx</
code> property that specifies the offset index into <code>data</code>; <br />
<code>length</code> the length (in bytes) to read from <code>data</code>
</td>
<td>An osc.js message or bundle object</td>
</tr>
<tr>
<td><code>osc.writePacket()</code></td>
<td>Writes an OSC message or bundle object to a binary array.</td>
<td>
<code>packate</code>: An osc.js message or bundle object;<br />
<code>options</code>: (optional) An options object, described below<br />
</td>
<td>A <code>Uint8Array</code></td>
</tr>
...writePrimitive = function (val, dv, writerName, numBytes, offset) {
offset = offset === undefined ? 0 : offset;
var arr;
if (!dv) {
arr = new Uint8Array(numBytes);
dv = new DataView(arr.buffer);
} else {
arr = new Uint8Array(dv.buffer);
}
dv[writerName](offset, val, false);
return arr;
}...
* Writes an OSC int32 ("i") value.
*
* @param {Number} val the number to write
* @param {DataView} [dv] a DataView instance to write the number into
* @param {Number} [offset] an offset into dv
*/
osc.writeInt32 = function (val, dv, offset) {
return osc.writePrimitive(val, dv, "setInt32", 4, offset);
};
/**
* Reads an OSC int64 ("h") value.
*
* @param {DataView} dv a DataView containing the raw bytes
* @param {Object} offsetState an offsetState object used to store the current offset index into dv
...writeString = function (str) {
var terminated = str + "\u0000",
len = terminated.length,
paddedLen = (len + 3) & ~0x03,
arr = new Uint8Array(paddedLen);
for (var i = 0; i < terminated.length; i++) {
var charCode = terminated.charCodeAt(i);
arr[i] = charCode;
}
return arr;
}...
currPartIdx = dataCollection.parts.length;
for (var i = 0; i < args.length; i++) {
var arg = args[i];
typeTagString += osc.writeArgument(arg, dataCollection);
}
var typeData = osc.writeString(typeTagString);
dataCollection.byteLength += typeData.byteLength;
dataCollection.parts.splice(currPartIdx, 0, typeData);
return dataCollection;
};
/**
...writeTimeTag = function (timeTag) {
var raw = timeTag.raw ? timeTag.raw : osc.jsToNTPTime(timeTag.native),
arr = new Uint8Array(8), // Two Unit32s.
dv = new DataView(arr.buffer);
osc.writeInt32(raw[0], dv, 0);
osc.writeInt32(raw[1], dv, 4);
return arr;
}...
osc.collectBundlePackets = function (bundle, options, dataCollection) {
dataCollection = dataCollection || {
byteLength: 0,
parts: []
};
osc.addDataPart(osc.writeString("#bundle"), dataCollection);
osc.addDataPart(osc.writeTimeTag(bundle.timeTag), dataCollection);
for (var i = 0; i < bundle.packets.length; i++) {
var packet = bundle.packets[i],
collector = packet.address ? osc.collectMessageParts : osc.collectBundlePackets,
packetCollection = collector(packet, options);
dataCollection.byteLength += packetCollection.byteLength;
...