annotate node_modules/node-osc/lib/osc.js @ 101:52e44ee1c791 tip master

enabled all scores in autostart script
author Rob Canning <rc@kiben.net>
date Tue, 21 Apr 2015 16:20:57 +0100
parents cd921abc8887
children
rev   line source
rob@77 1 var min = require('osc-min');
rob@77 2 var dgram = require('dgram');
rob@77 3 var util = require('util');
rob@77 4 var events = require('events');
rob@77 5 var jspack = require('jspack').jspack;
rob@77 6
rob@77 7 ////////////////////
rob@77 8 // OSC Message
rob@77 9 ////////////////////
rob@77 10
rob@77 11
rob@77 12 function Message(address) {
rob@77 13 this.oscType = "message";
rob@77 14 this.address = address;
rob@77 15 this.args = [];
rob@77 16
rob@77 17 for (var i = 1; i < arguments.length; i++) {
rob@77 18 this.append(arguments[i]);
rob@77 19 }
rob@77 20 }
rob@77 21
rob@77 22 Message.prototype = {
rob@77 23 append: function (arg) {
rob@77 24 switch (typeof arg) {
rob@77 25 case 'object':
rob@77 26 if (arg.type) {
rob@77 27 this.args.push(arg);
rob@77 28 } else {
rob@77 29 throw new Error("don't know how to encode object " + arg)
rob@77 30 }
rob@77 31 break;
rob@77 32 case 'number':
rob@77 33 if (Math.floor(arg) == arg) {
rob@77 34 var argOut = new Argument('integer', arg);
rob@77 35 this.args.push(argOut);
rob@77 36 } else {
rob@77 37 var argOut = new Argument('float', arg);
rob@77 38 this.args.push(argOut);
rob@77 39 }
rob@77 40 break;
rob@77 41 case 'string':
rob@77 42 var argOut = new Argument('string', arg);
rob@77 43 this.args.push(argOut);
rob@77 44 break;
rob@77 45 default:
rob@77 46 throw new Error("don't know how to encode " + arg);
rob@77 47 }
rob@77 48 }
rob@77 49 }
rob@77 50
rob@77 51 exports.Message = Message;
rob@77 52
rob@77 53 function Argument(type, value){
rob@77 54 this.type = type;
rob@77 55 this.value = value;
rob@77 56 }
rob@77 57
rob@77 58 ////////////////////
rob@77 59 // OSC Client
rob@77 60 ////////////////////
rob@77 61
rob@77 62 var Client = function (host, port) {
rob@77 63 this.host = host;
rob@77 64 this.port = port;
rob@77 65 this._sock = dgram.createSocket('udp4');
rob@77 66 }
rob@77 67
rob@77 68 Client.prototype = {
rob@77 69 send: function (message) {
rob@77 70 switch (typeof message) {
rob@77 71 case 'object':
rob@77 72 var buf = min.toBuffer(message);
rob@77 73 this._sock.send(buf, 0, buf.length, this.port, this.host);
rob@77 74 break;
rob@77 75 case 'string':
rob@77 76 mes = new Message(arguments[0]);
rob@77 77 for (var i = 1; i < arguments.length; i++) {
rob@77 78 mes.append(arguments[i]);
rob@77 79 }
rob@77 80 var buf = min.toBuffer(mes);
rob@77 81 this._sock.send(buf, 0, buf.length, this.port, this.host);
rob@77 82 break;
rob@77 83 default:
rob@77 84 throw new Error("That Message Just Doesn't Seem Right");
rob@77 85 }
rob@77 86 }
rob@77 87 }
rob@77 88
rob@77 89 exports.Client = Client;
rob@77 90
rob@77 91 ////////////////////
rob@77 92 // OSC Message encoding and decoding functions
rob@77 93 ////////////////////
rob@77 94
rob@77 95 function ShortBuffer(type, buf, requiredLength)
rob@77 96 {
rob@77 97 this.type = "ShortBuffer";
rob@77 98 var message = "buffer [";
rob@77 99 for (var i = 0; i < buf.length; i++) {
rob@77 100 if (i) {
rob@77 101 message += ", ";
rob@77 102 }
rob@77 103 message += buf.charCodeAt(i);
rob@77 104 }
rob@77 105 message += "] too short for " + type + ", " + requiredLength + " bytes required";
rob@77 106 this.message = message;
rob@77 107 }
rob@77 108
rob@77 109 function TString (value) { this.value = value; }
rob@77 110 TString.prototype = {
rob@77 111 typetag: 's',
rob@77 112 decode: function (data) {
rob@77 113 var end = 0;
rob@77 114 while (data[end] && end < data.length) {
rob@77 115 end++;
rob@77 116 }
rob@77 117 if (end == data.length) {
rob@77 118 throw Error("OSC string not null terminated");
rob@77 119 }
rob@77 120 this.value = data.toString('ascii', 0, end);
rob@77 121 var nextData = parseInt(Math.ceil((end + 1) / 4.0) * 4);
rob@77 122 return data.slice(nextData);
rob@77 123 },
rob@77 124 encode: function (buf, pos) {
rob@77 125 var len = Math.ceil((this.value.length + 1) / 4.0) * 4;
rob@77 126 return jspack.PackTo('>' + len + 's', buf, pos, [ this.value ]);
rob@77 127 }
rob@77 128 }
rob@77 129 exports.TString = TString;
rob@77 130
rob@77 131 function TInt (value) { this.value = value; }
rob@77 132 TInt.prototype = {
rob@77 133 typetag: 'i',
rob@77 134 decode: function (data) {
rob@77 135 if (data.length < 4) {
rob@77 136 throw new ShortBuffer('int', data, 4);
rob@77 137 }
rob@77 138
rob@77 139 this.value = jspack.Unpack('>i', data.slice(0, 4))[0];
rob@77 140 return data.slice(4);
rob@77 141 },
rob@77 142 encode: function (buf, pos) {
rob@77 143 return jspack.PackTo('>i', buf, pos, [ this.value ]);
rob@77 144 }
rob@77 145 }
rob@77 146 exports.TInt = TInt;
rob@77 147
rob@77 148 function TTime (value) { this.value = value; }
rob@77 149 TTime.prototype = {
rob@77 150 typetag: 't',
rob@77 151 decode: function (data) {
rob@77 152 if (data.length < 8) {
rob@77 153 throw new ShortBuffer('time', data, 8);
rob@77 154 }
rob@77 155 var raw = jspack.Unpack('>LL', data.slice(0, 8));
rob@77 156 var secs = raw[0];
rob@77 157 var fracs = raw[1];
rob@77 158 this.value = secs + fracs / 4294967296;
rob@77 159 return data.slice(8);
rob@77 160 },
rob@77 161 encode: function (buf, pos) {
rob@77 162 return jspack.PackTo('>LL', buf, pos, this.value);
rob@77 163 }
rob@77 164 }
rob@77 165 exports.TTime = TTime;
rob@77 166
rob@77 167 function TFloat (value) { this.value = value; }
rob@77 168 TFloat.prototype = {
rob@77 169 typetag: 'f',
rob@77 170 decode: function (data) {
rob@77 171 if (data.length < 4) {
rob@77 172 throw new ShortBuffer('float', data, 4);
rob@77 173 }
rob@77 174
rob@77 175 this.value = jspack.Unpack('>f', data.slice(0, 4))[0];
rob@77 176 return data.slice(4);
rob@77 177 },
rob@77 178 encode: function (buf, pos) {
rob@77 179 return jspack.PackTo('>f', buf, pos, [ this.value ]);
rob@77 180 }
rob@77 181 }
rob@77 182 exports.TFloat = TFloat;
rob@77 183
rob@77 184 function TBlob (value) { this.value = value; }
rob@77 185 TBlob.prototype = {
rob@77 186 typetag: 'b',
rob@77 187 decode: function (data) {
rob@77 188 var length = jspack.Unpack('>i', data.slice(0, 4))[0];
rob@77 189 var nextData = parseInt(Math.ceil((length) / 4.0) * 4) + 4;
rob@77 190 this.value = data.slice(4, length + 4);
rob@77 191 return data.slice(nextData);
rob@77 192 },
rob@77 193 encode: function (buf, pos) {
rob@77 194 var len = Math.ceil((this.value.length) / 4.0) * 4;
rob@77 195 return jspack.PackTo('>i' + len + 's', buf, pos, [len, this.value]);
rob@77 196 }
rob@77 197 }
rob@77 198 exports.TBlob = TBlob;
rob@77 199
rob@77 200 function TDouble (value) { this.value = value; }
rob@77 201 TDouble.prototype = {
rob@77 202 typetag: 'd',
rob@77 203 decode: function (data) {
rob@77 204 if (data.length < 8) {
rob@77 205 throw new ShortBuffer('double', data, 8);
rob@77 206 }
rob@77 207 this.value = jspack.Unpack('>d', data.slice(0, 8))[0];
rob@77 208 return data.slice(8);
rob@77 209 },
rob@77 210 encode: function (buf, pos) {
rob@77 211 return jspack.PackTo('>d', buf, pos, [ this.value ]);
rob@77 212 }
rob@77 213 }
rob@77 214 exports.TDouble = TDouble;
rob@77 215
rob@77 216 // for each OSC type tag we use a specific constructor function to decode its respective data
rob@77 217 var tagToConstructor = { 'i': function () { return new TInt },
rob@77 218 'f': function () { return new TFloat },
rob@77 219 's': function () { return new TString },
rob@77 220 'b': function () { return new TBlob },
rob@77 221 'd': function () { return new TDouble } };
rob@77 222
rob@77 223 function decode (data) {
rob@77 224 // this stores the decoded data as an array
rob@77 225 var message = [];
rob@77 226
rob@77 227 // we start getting the <address> and <rest> of OSC msg /<address>\0<rest>\0<typetags>\0<data>
rob@77 228 var address = new TString;
rob@77 229 data = address.decode(data);
rob@77 230
rob@77 231 // Checking if we received a bundle (typical for TUIO/OSC)
rob@77 232 if (address.value == '#bundle') {
rob@77 233 var time = new TTime;
rob@77 234 data = time.decode(data);
rob@77 235
rob@77 236 message.push('#bundle');
rob@77 237 message.push(time.value);
rob@77 238
rob@77 239 var length, part;
rob@77 240 while(data.length > 0) {
rob@77 241 length = new TInt;
rob@77 242 data = length.decode(data);
rob@77 243
rob@77 244 part = data.slice(0, length.value);
rob@77 245 //message = message.concat(decode(part));
rob@77 246 message.push(decode(part));
rob@77 247
rob@77 248 data = data.slice(length.value, data.length);
rob@77 249 }
rob@77 250
rob@77 251 } else if (data.length > 0) {
rob@77 252 message.push(address.value);
rob@77 253
rob@77 254 // if we have rest, maybe we have some typetags... let see...
rob@77 255
rob@77 256 // now we advance on the old rest, getting <typetags>
rob@77 257 var typetags = new TString;
rob@77 258 data = typetags.decode(data);
rob@77 259 typetags = typetags.value;
rob@77 260 // so we start building our message list
rob@77 261 if (typetags[0] != ',') {
rob@77 262 throw "invalid type tag in incoming OSC message, must start with comma";
rob@77 263 }
rob@77 264 for (var i = 1; i < typetags.length; i++) {
rob@77 265 var constructor = tagToConstructor[typetags[i]];
rob@77 266 if (!constructor) {
rob@77 267 throw "Unsupported OSC type tag " + typetags[i] + " in incoming message";
rob@77 268 }
rob@77 269 var argument = constructor();
rob@77 270 data = argument.decode(data);
rob@77 271 message.push(argument.value);
rob@77 272 }
rob@77 273 }
rob@77 274
rob@77 275 return message;
rob@77 276 };
rob@77 277
rob@77 278
rob@77 279
rob@77 280 ////////////////////
rob@77 281 // OSC Server
rob@77 282 ////////////////////
rob@77 283
rob@77 284 var Server = function(port, host) {
rob@77 285 var _callbacks, server;
rob@77 286 events.EventEmitter.call(this);
rob@77 287 _callbacks = [];
rob@77 288 this.port = port;
rob@77 289 this.host = host;
rob@77 290 this._sock = dgram.createSocket('udp4');
rob@77 291 this._sock.bind(port);
rob@77 292 server = this;
rob@77 293 this._sock.on('message', function (msg, rinfo) {
rob@77 294 try {
rob@77 295 var decoded = decode(msg);
rob@77 296 // [<address>, <typetags>, <values>*]
rob@77 297 if (decoded) {
rob@77 298 server.emit('message', decoded, rinfo);
rob@77 299 server.emit(decoded[0], decoded, rinfo);
rob@77 300 }
rob@77 301 }
rob@77 302 catch (e) {
rob@77 303 console.log("can't decode incoming message: " + e.message);
rob@77 304 }
rob@77 305 });
rob@77 306 this.kill = function() {
rob@77 307 this._sock.close();
rob@77 308 };
rob@77 309 }
rob@77 310
rob@77 311 util.inherits(Server, events.EventEmitter);
rob@77 312
rob@77 313 exports.Server = Server;
rob@77 314
rob@77 315