├── .gitignore ├── README.md ├── index.html ├── lib ├── osc.min.js └── osc.min.js.map ├── package-lock.json ├── package.json └── server.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_STORE -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hydra-osc [WIP] 2 | 3 | Minimum example sending osc messages to and from hydra in the browser. 4 | 5 | Current version uses (osc-js)[https://github.com/adzialocha/osc-js], would like to switch to browserglue. 6 | 7 | To use: 8 | 1. install node.js on your operating system 9 | 2. run `npm install` to install dependencies 10 | 3. run the local websocket server `node server.js` 11 | 4. paste the following code in hydra editor: 12 | 13 | ```javascript 14 | await loadScript("https://cdn.jsdelivr.net/gh/ojack/hydra-osc/lib/osc.min.js") 15 | 16 | _osc = new OSC() 17 | _osc.open() 18 | 19 | _osc.on("*", (m) => { console.log(m.address, m.args)}) 20 | 21 | ``` 22 | Open the browser console to see osc messages logged from your local system. The local osc messages should be sent to the ports specified in `server.js` 23 | 24 | More complete example (live at https://hydra.ojack.xyz/?sketch_id=8XySbQWWCzK4AaDF) 25 | ```javascript 26 | /* 27 | Example using osc-js to bridge local udp / osc messages to the browser via websockets. For more information, see: https://github.com/ojack/hydra-osc 28 | and follow instructions to run a local websocket server. 29 | */ 30 | await loadScript("https://cdn.jsdelivr.net/gh/ojack/hydra-osc/lib/osc.min.js") 31 | 32 | _osc = new OSC() 33 | _osc.open() 34 | 35 | /* example to receive osc */ 36 | 37 | _osc.on("*", (m) => { console.log(m.address, m.args)}) 38 | 39 | hue = 0 40 | _osc.on("/hue", (m) => { 41 | console.log(m) 42 | hue = m.args[0]/255 43 | }) 44 | 45 | shape(4).color(-1, 1).hue(() => hue).out() 46 | 47 | /* example to send osc */ 48 | 49 | send = (address = "", args) => { 50 | var message = new OSC.Message(address, args) 51 | _osc.send(message); 52 | } 53 | 54 | // execute this line to send an osc message 55 | send('/hi', "hello") 56 | ``` 57 | 58 | This is only meant as an example. For easier use while livecoding, the implementation should allow overwriting old event handlers with new ones, and follow an api similar to the atom-hydra implementation of osc: https://github.com/hydra-synth/atom-hydra/blob/master/lib/osc-loader.js 59 | 60 | 61 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /lib/osc.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).OSC=e()}(this,(function(){"use strict";function t(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function e(e){for(var n=1;n1&&"/"===e[e.length-1]&&(e=e.slice(0,e.length-1)),e.length>1&&"/"!==e[0]&&(e="/".concat(e)),e;throw new Error("OSC prepareAddress() needs addresses of type array or string")}function P(t){if(!v(t))throw new Error("OSC prepareRegExPattern() needs strings");return t.replace(/\./g,"\\.").replace(/\(/g,"\\(").replace(/\)/g,"\\)").replace(/\{/g,"(").replace(/\}/g,")").replace(/,/g,"|").replace(/\[!/g,"[^").replace(/\?/g,".").replace(/\*/g,".*")}var I=function(){function t(){n(this,t),this.data=[],this.byteLength=0}return o(t,[{key:"add",value:function(t){var e=t.pack();return this.byteLength+=e.byteLength,this.data.push(e),this}},{key:"merge",value:function(){var t=new Uint8Array(this.byteLength),e=0;return this.data.forEach((function(n){t.set(n,e),e+=n.byteLength})),t}}]),t}(),D=function(){function t(e){n(this,t),this.value=e,this.offset=0}return o(t,[{key:"pack",value:function(t,e){if(!t||!e)throw new Error("OSC Atomic cant't be packed without given method or byteLength");var n=new Uint8Array(e),r=new DataView(n.buffer);if(m(this.value))throw new Error("OSC Atomic cant't be encoded with empty value");return r[t](this.offset,this.value,!1),n}},{key:"unpack",value:function(t,e,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;if(!(t&&e&&n))throw new Error("OSC Atomic cant't be unpacked without given dataView, method or byteLength");if(!(t instanceof DataView))throw new Error("OSC Atomic expects an instance of type DataView");return this.value=t[e](r,!1),this.offset=r+n,this.offset}}]),t}(),j=function(t){s(r,t);var e=f(r);function r(t){if(n(this,r),t&&!p(t))throw new Error("OSC AtomicInt32 constructor expects value of type number");return e.call(this,t)}return o(r,[{key:"pack",value:function(){return h(a(r.prototype),"pack",this).call(this,"setInt32",4)}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return h(a(r.prototype),"unpack",this).call(this,t,"getInt32",4,e)}}]),r}(D),x="utf-8";function B(t){if(O("Buffer"))return Buffer.from(t).toString(x);if(O("TextDecoder"))return new TextDecoder(x).decode(new Int8Array(t));for(var e="",n=0;n1&&void 0!==arguments[1]?arguments[1]:0;if(!(t instanceof DataView))throw new Error("OSC AtomicString expects an instance of type DataView");for(var n,r=e,o=[];r0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(n(this,t),!p(e)||!p(r))throw new Error("OSC Timetag constructor expects values of type integer number");this.seconds=e,this.fractions=r}return o(t,[{key:"timestamp",value:function(t){var e;if("number"==typeof t){e=t/1e3;var n=Math.floor(e);return this.seconds=n+T,this.fractions=Math.round(L*(e-n)),t}return 1e3*((e=this.seconds-T)+Math.round(this.fractions/L))}}]),t}(),M=function(t){s(r,t);var e=f(r);function r(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Date.now();n(this,r);var o=new _;return t instanceof _?o=t:p(t)?o.timestamp(t):b(t)&&o.timestamp(t.getTime()),e.call(this,o)}return o(r,[{key:"pack",value:function(){if(m(this.value))throw new Error("OSC AtomicTimetag can not be encoded with empty value");var t=this.value,e=t.seconds,n=t.fractions,r=new Uint8Array(8),o=new DataView(r.buffer);return o.setInt32(0,e,!1),o.setInt32(4,n,!1),r}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(!(t instanceof DataView))throw new Error("OSC AtomicTimetag expects an instance of type DataView");var n=t.getUint32(e,!1),r=t.getUint32(e+4,!1);return this.value=new _(n,r),this.offset=e+8,this.offset}}]),r}(D),V=function(t){s(r,t);var e=f(r);function r(t){if(n(this,r),t&&!k(t))throw new Error("OSC AtomicBlob constructor expects value of type Uint8Array");return e.call(this,t)}return o(r,[{key:"pack",value:function(){if(m(this.value))throw new Error("OSC AtomicBlob can not be encoded with empty value");var t=S(this.value.byteLength),e=new Uint8Array(t+4);return new DataView(e.buffer).setInt32(0,this.value.byteLength,!1),e.set(this.value,4),e}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(!(t instanceof DataView))throw new Error("OSC AtomicBlob expects an instance of type DataView");var n=t.getInt32(e,!1);return this.value=new Uint8Array(t.buffer,e+4,n),this.offset=S(e+4+n),this.offset}}]),r}(D),U=function(t){s(r,t);var e=f(r);function r(t){if(n(this,r),t&&!d(t))throw new Error("OSC AtomicFloat32 constructor expects value of type float");return e.call(this,t)}return o(r,[{key:"pack",value:function(){return h(a(r.prototype),"pack",this).call(this,"setFloat32",4)}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return h(a(r.prototype),"unpack",this).call(this,t,"getFloat32",4,e)}}]),r}(D),N=function(t){s(r,t);var e=f(r);function r(t){if(n(this,r),t&&!d(t))throw new Error("OSC AtomicFloat64 constructor expects value of type float");return e.call(this,t)}return o(r,[{key:"pack",value:function(){return h(a(r.prototype),"pack",this).call(this,"setFloat64",8)}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return h(a(r.prototype),"unpack",this).call(this,t,"getFloat64",8,e)}}]),r}(D),R=BigInt("9223372036854775807"),F=BigInt("-9223372036854775808"),W=function(t){s(r,t);var e=f(r);function r(t){if(n(this,r),t&&"bigint"!=typeof t)throw new Error("OSC AtomicInt64 constructor expects value of type BigInt");if(t&&(tR))throw new Error("OSC AtomicInt64 value is out of bounds");var o;return t&&(o=BigInt.asIntN(64,t)),e.call(this,o)}return o(r,[{key:"pack",value:function(){return h(a(r.prototype),"pack",this).call(this,"setBigInt64",8)}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return h(a(r.prototype),"unpack",this).call(this,t,"getBigInt64",8,e)}}]),r}(D),q=BigInt("18446744073709551615"),z=function(t){s(r,t);var e=f(r);function r(t){if(n(this,r),t&&"bigint"!=typeof t)throw new Error("OSC AtomicUInt64 constructor expects value of type BigInt");if(t&&(t<0||t>q))throw new Error("OSC AtomicUInt64 value is out of bounds");var o;return t&&(o=BigInt.asUintN(64,t)),e.call(this,o)}return o(r,[{key:"pack",value:function(){return h(a(r.prototype),"pack",this).call(this,"setBigUint64",8)}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return h(a(r.prototype),"unpack",this).call(this,t,"getBigUint64",8,e)}}]),r}(D),G=function(){function t(e,r){var o=this;if(n(this,t),this.offset=0,this.address="",this.types="",this.args=[],!m(e)){if(!v(e)&&!w(e))throw new Error("OSC Message constructor first argument (address) must be a string or array");this.address=A(e)}if(!m(r)){if(!w(r))throw new Error("OSC Message constructor second argument (args) must be an array");r.forEach((function(t){return o.add(t.type,t.value)}))}}return o(t,[{key:"add",value:function(t,e){if(m(t))throw new Error("OSC Message needs a valid OSC Atomic Data Type");null===e||m(e)||this.args.push(e),this.types+=t}},{key:"pack",value:function(){var t=this;if(0===this.address.length||"/"!==this.address[0])throw new Error("OSC Message has an invalid address");var e=new I;if(e.add(new H(this.address)),e.add(new H(",".concat(this.types))),this.args.length>0){var n;if(this.args.length>this.types.length)throw new Error("OSC Message argument and type tag mismatch");this.args.forEach((function(r,o){var i=t.types[o];if("i"===i)n=new j(r);else if("h"===i)n=new W(r);else if("t"===i)n=new z(r);else if("f"===i)n=new U(r);else if("d"===i)n=new N(r);else if("s"===i)n=new H(r);else{if("b"!==i)throw new Error("OSC Message found unknown argument type");n=new V(r)}e.add(n)}))}return e.merge()}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(!(t instanceof DataView))throw new Error("OSC Message expects an instance of type DataView.");var n=new H;n.unpack(t,e);var r=new H;if(r.unpack(t,n.offset),0===n.value.length||"/"!==n.value[0])throw new Error("OSC Message found malformed or missing address string");if(0===r.value.length&&","!==r.value[0])throw new Error("OSC Message found malformed or missing type string");for(var o,i,s=r.offset,a=[],u=1;u0&&(o=a.shift()),a.length>0&&a[0]instanceof Array&&(i=a.shift()),t=e.call(this,o,i),a.length>0&&(t.types=a.map((function(t){return C(t)})).join(""),t.args=a),t}return o(r,[{key:"add",value:function(t){h(a(r.prototype),"add",this).call(this,C(t),t)}}]),r}(G),J="#bundle",K=function(){function t(){var e=this;n(this,t),this.offset=0,this.timetag=new M,this.bundleElements=[];for(var r=arguments.length,o=new Array(r),i=0;i0&&(o[0]instanceof Date||p(o[0])?this.timetag=new M(o[0]):w(o[0])?(o[0].forEach((function(t){e.add(t)})),o.length>1&&(o[1]instanceof Date||p(o[0]))&&(this.timetag=new M(o[1]))):o.forEach((function(t){e.add(t)})))}return o(t,[{key:"timestamp",value:function(t){if(!p(t))throw new Error("OSC Bundle needs an integer for setting the timestamp");this.timetag=new M(t)}},{key:"add",value:function(e){if(!(e instanceof Z||e instanceof t))throw new Error("OSC Bundle contains only Messages and Bundles");this.bundleElements.push(e)}},{key:"pack",value:function(){var t=new I;return t.add(new H(J)),this.timetag||(this.timetag=new M),t.add(this.timetag),this.bundleElements.forEach((function(e){t.add(new j(e.pack().byteLength)),t.add(e)})),t.merge()}},{key:"unpack",value:function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(!(e instanceof DataView))throw new Error("OSC Bundle expects an instance of type DataView");var r=new H;if(r.unpack(e,n),r.value!==J)throw new Error("OSC Bundle does not contain a valid #bundle head");var o=new M,i=o.unpack(e,r.offset);for(this.bundleElements=[];i1&&void 0!==arguments[1]?arguments[1]:0;if(!(t instanceof DataView))throw new Error("OSC Packet expects an instance of type DataView");if(t.byteLength%4!=0)throw new Error("OSC Packet byteLength has to be a multiple of four");var n,r=new H;return r.unpack(t,e),(n=r.value===J?new K:new Z).unpack(t,e),this.offset=n.offset,this.value=n,this.offset}}]),t}(),X={discardLateMessages:!1},Y=function(){function t(r){n(this,t),this.options=e(e({},X),r),this.addressHandlers=[],this.eventHandlers={open:[],error:[],close:[]},this.uuid=0}return o(t,[{key:"dispatch",value:function(t,e){var n=this;if(!(t instanceof Q))throw new Error("OSC EventHander dispatch() accepts only arguments of type Packet");if(!t.value)throw new Error("OSC EventHander dispatch() can't read empty Packets");if(t.value instanceof K){var r=t.value;return r.bundleElements.forEach((function(t){if(t instanceof K){if(r.timetag.value.timestamp()1&&(i=e[1]);var s=null;if(e.length>2)if(p(e[2]))s=e[2];else{if(!(e[2]instanceof Date))throw new Error("OSC EventHandler timestamp has to be a number or Date");s=e[2].getTime()}var a=null;if(e.length>=3&&(a=e[3]),s){var u=Date.now();if(u>s&&!this.options.discardLateMessages)return this.call(o,i,a);var c=this;return setTimeout((function(){c.call(o,i,a)}),s-u),!0}return this.call(o,i,a)}},{key:"on",value:function(t,e){if(!v(t)&&!w(t))throw new Error("OSC EventHandler accepts only strings or arrays for address patterns");if(!g(e))throw new Error("OSC EventHandler callback has to be a function");this.uuid+=1;var n={id:this.uuid,callback:e};if(v(t)&&t in this.eventHandlers)return this.eventHandlers[t].push(n),this.uuid;var r=A(t);return r in this.addressHandlers||(this.addressHandlers[r]=[]),this.addressHandlers[r].push(n),this.uuid}},{key:"off",value:function(t,e){if(!v(t)&&!w(t))throw new Error("OSC EventHandler accepts only strings or arrays for address patterns");if(!p(e))throw new Error("OSC EventHandler subscription id has to be a number");var n,r;return v(t)&&t in this.eventHandlers?(n=t,r=this.eventHandlers):(n=A(t),r=this.addressHandlers),n in r&&r[n].some((function(t,o){return t.id===e&&(r[n].splice(o,1),!0)}))}}]),t}(),$="undefined"!=typeof __dirname?require("dgram"):void 0,tt=-1,et=0,nt=1,rt=2,ot=3,it={type:"udp4",open:{host:"localhost",port:41234,exclusive:!1},send:{host:"localhost",port:41235}};function st(t,n){return e(e(e(e({},it),t),n),{},{open:e(e(e({},it.open),t.open),n.open),send:e(e(e({},it.send),t.send),n.send)})}var at=function(){function t(){var e=this,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(n(this,t),!$)throw new Error("DatagramPlugin can not be used in browser context");this.options=st({},r),this.socket=$.createSocket(this.options.type),this.socketStatus=tt,this.socket.on("message",(function(t,n){e.notify(t,n)})),this.socket.on("error",(function(t){e.notify("error",t)})),this.notify=function(){}}return o(t,[{key:"registerNotify",value:function(t){this.notify=t}},{key:"status",value:function(){return this.socketStatus}},{key:"open",value:function(){var t=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=e(e({},this.options.open),n),o=r.port,i=r.exclusive;this.socketStatus=et,this.socket.bind({address:r.host,port:o,exclusive:i},(function(){t.socketStatus=nt,t.notify("open")}))}},{key:"close",value:function(){var t=this;this.socketStatus=rt,this.socket.close((function(){t.socketStatus=ot,t.notify("close")}))}},{key:"send",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=e(e({},this.options.send),n),o=r.port,i=r.host;this.socket.send(Buffer.from(t),0,t.byteLength,o,i)}}]),t}(),ut="undefined"!=typeof __dirname?require("dgram"):void 0,ct="undefined"!=typeof __dirname?require("isomorphic-ws").Server:void 0,ft=-1,lt=0,ht=1,pt=2,dt=3,vt={udpServer:{host:"localhost",port:41234,exclusive:!1},udpClient:{host:"localhost",port:41235},wsServer:{host:"localhost",port:8080},receiver:"ws"};function wt(t,n){return e(e(e(e({},vt),t),n),{},{udpServer:e(e(e({},vt.udpServer),t.udpServer),n.udpServer),udpClient:e(e(e({},vt.udpClient),t.udpClient),n.udpClient),wsServer:e(e(e({},vt.wsServer),t.wsServer),n.wsServer)})}var yt=function(){function t(){var e=this,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(n(this,t),!ut||!ct)throw new Error("BridgePlugin can not be used in browser context");this.options=wt({},r),this.websocket=null,this.socket=ut.createSocket("udp4"),this.socketStatus=ft,this.socket.on("message",(function(t){e.send(t,{receiver:"ws"}),e.notify(t.buffer)})),this.socket.on("error",(function(t){e.notify("error",t)})),this.notify=function(){}}return o(t,[{key:"registerNotify",value:function(t){this.notify=t}},{key:"status",value:function(){return this.socketStatus}},{key:"open",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=wt(this.options,e);this.socketStatus=lt,this.socket.bind({address:n.udpServer.host,port:n.udpServer.port,exclusive:n.udpServer.exclusive},(function(){var e={};n.wsServer.server?e.server=n.wsServer.server:e=n.wsServer,t.websocket=new ct(e),t.websocket.binaryType="arraybuffer",t.websocket.on("listening",(function(){t.socketStatus=ht,t.notify("open")})),t.websocket.on("error",(function(e){t.notify("error",e)})),t.websocket.on("connection",(function(e){e.on("message",(function(e,n){t.send(e,{receiver:"udp"}),t.notify(new Uint8Array(e),n)}))}))}))}},{key:"close",value:function(){var t=this;this.socketStatus=pt,this.socket.close((function(){t.websocket.close((function(){t.socketStatus=dt,t.notify("close")}))}))}},{key:"send",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=wt(this.options,e),r=n.receiver;if("udp"===r){var o=t instanceof Buffer?t:Buffer.from(t);this.socket.send(o,0,o.byteLength,n.udpClient.port,n.udpClient.host)}else{if("ws"!==r)throw new Error("BridgePlugin can not send message to unknown receiver");this.websocket.clients.forEach((function(e){e.send(t,{binary:!0})}))}}}]),t}(),gt="undefined"==typeof global?window:global,kt="undefined"==typeof __dirname?gt.WebSocket:require("isomorphic-ws"),bt=-1,mt=0,St=1,Ot=2,Et=3,Ct={host:"localhost",port:8080,secure:!1},At=function(){function t(r){if(n(this,t),!kt)throw new Error("WebsocketClientPlugin can't find a WebSocket class");this.options=e(e({},Ct),r),this.socket=null,this.socketStatus=bt,this.notify=function(){}}return o(t,[{key:"registerNotify",value:function(t){this.notify=t}},{key:"status",value:function(){return this.socketStatus}},{key:"open",value:function(){var t=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=e(e({},this.options),n),o=r.port,i=r.host,s=r.secure;this.socket&&this.close();var a=s?"wss":"ws",u={address:i,family:a,port:o,size:0};this.socket=new kt("".concat(a,"://").concat(i,":").concat(o)),this.socket.binaryType="arraybuffer",this.socketStatus=mt,this.socket.onopen=function(){t.socketStatus=St,t.notify("open")},this.socket.onclose=function(){t.socketStatus=Et,t.notify("close")},this.socket.onerror=function(e){t.notify("error",e)},this.socket.onmessage=function(e){t.notify(e.data,u)}}},{key:"close",value:function(){this.socketStatus=Ot,this.socket.close()}},{key:"send",value:function(t){this.socket.send(t)}}]),t}(),Pt="undefined"!=typeof __dirname?require("isomorphic-ws").Server:void 0,It=-1,Dt=0,jt=1,xt=2,Bt=3,Ht={host:"localhost",port:8080},Tt=function(){function t(r){if(n(this,t),!Pt)throw new Error("WebsocketServerPlugin can not be used in browser context");this.options=e(e({},Ht),r),this.socket=null,this.socketStatus=It,this.notify=function(){}}return o(t,[{key:"registerNotify",value:function(t){this.notify=t}},{key:"status",value:function(){return this.socketStatus}},{key:"open",value:function(){var t=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=e(e({},this.options),n),o=r.port,i=r.host,s={address:i,family:"wsserver",port:o,size:0};this.socket&&this.close(),r.server?this.socket=new Pt({server:r.server}):this.socket=new Pt({host:i,port:o}),this.socket.binaryType="arraybuffer",this.socketStatus=Dt,this.socket.on("listening",(function(){t.socketStatus=jt,t.notify("open")})),this.socket.on("error",(function(e){t.notify("error",e)})),this.socket.on("connection",(function(e){e.on("message",(function(e){t.notify(new Uint8Array(e),s)}))}))}},{key:"close",value:function(){var t=this;this.socketStatus=xt,this.socket.close((function(){t.socketStatus=Bt,t.notify("close")}))}},{key:"send",value:function(t){this.socket.clients.forEach((function(e){e.send(t,{binary:!0})}))}}]),t}(),Lt={discardLateMessages:!1,plugin:new At},_t=function(){function t(r){if(n(this,t),r&&!y(r))throw new Error("OSC options argument has to be an object.");this.options=e(e({},Lt),r),this.eventHandler=new Y({discardLateMessages:this.options.discardLateMessages});var o=this.eventHandler;this.options.plugin&&this.options.plugin.registerNotify&&this.options.plugin.registerNotify((function(){return o.notify.apply(o,arguments)}))}return o(t,[{key:"on",value:function(t,e){if(!v(t)||!g(e))throw new Error("OSC on() needs event- or address string and callback function");return this.eventHandler.on(t,e)}},{key:"off",value:function(t,e){if(!v(t)||!p(e))throw new Error("OSC off() needs string and number (subscriptionId) to unsubscribe");return this.eventHandler.off(t,e)}},{key:"open",value:function(t){if(t&&!y(t))throw new Error("OSC open() options argument needs to be an object");if(!this.options.plugin||!g(this.options.plugin.open))throw new Error("OSC Plugin API #open is not implemented!");return this.options.plugin.open(t)}},{key:"status",value:function(){if(!this.options.plugin||!g(this.options.plugin.status))throw new Error("OSC Plugin API #status is not implemented!");return this.options.plugin.status()}},{key:"close",value:function(){if(!this.options.plugin||!g(this.options.plugin.close))throw new Error("OSC Plugin API #close is not implemented!");return this.options.plugin.close()}},{key:"send",value:function(t,e){if(!this.options.plugin||!g(this.options.plugin.send))throw new Error("OSC Plugin API #send is not implemented!");if(!(t instanceof G||t instanceof Z||t instanceof K||t instanceof Q))throw new Error("OSC send() needs Messages, Bundles or Packets");if(e&&!y(e))throw new Error("OSC send() options argument has to be an object");return this.options.plugin.send(t.pack(),e)}}]),t}();return _t.STATUS={IS_NOT_INITIALIZED:-1,IS_CONNECTING:0,IS_OPEN:1,IS_CLOSING:2,IS_CLOSED:3},_t.Packet=Q,_t.Bundle=K,_t.Message=Z,_t.TypedMessage=G,_t.DatagramPlugin=at,_t.WebsocketClientPlugin=At,_t.WebsocketServerPlugin=Tt,_t.BridgePlugin=yt,_t})); 2 | //# sourceMappingURL=osc.min.js.map 3 | -------------------------------------------------------------------------------- /lib/osc.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"osc.min.js","sources":["../src/common/utils.js","../src/common/helpers.js","../src/atomic.js","../src/atomic/int32.js","../src/atomic/string.js","../src/atomic/timetag.js","../src/atomic/blob.js","../src/atomic/float32.js","../src/atomic/float64.js","../src/atomic/int64.js","../src/atomic/uint64.js","../src/message.js","../src/bundle.js","../src/packet.js","../src/events.js","../src/plugin/dgram.js","../src/plugin/bridge.js","../src/plugin/wsclient.js","../src/plugin/wsserver.js","../src/osc.js"],"sourcesContent":["/**\n * Check if given object is an integer number\n * @param {*} n\n * @return {boolean}\n */\nexport function isInt(n) {\n return Number(n) === n && n % 1 === 0\n}\n\n/**\n * Check if given object is a float number\n * @param {*} n\n * @return {boolean}\n */\nexport function isFloat(n) {\n return Number(n) === n && n % 1 !== 0\n}\n\n/**\n * Check if given object is a number\n * @param {*} n\n * @return {boolean}\n */\nexport function isNumber(n) {\n return Number(n) === n\n}\n\n/**\n * Check if given object is a string\n * @param {*} n\n * @return {boolean}\n */\nexport function isString(n) {\n return typeof n === 'string'\n}\n\n/**\n * Check if given object is an array\n * @param {*} n\n * @return {boolean}\n */\nexport function isArray(n) {\n return Object.prototype.toString.call(n) === '[object Array]'\n}\n\n/**\n * Check if given object is an object\n * @param {*} n\n * @return {boolean}\n */\nexport function isObject(n) {\n return Object.prototype.toString.call(n) === '[object Object]'\n}\n\n/**\n * Check if given object is a function\n * @param {*} n\n * @return {boolean}\n */\nexport function isFunction(n) {\n return typeof n === 'function'\n}\n\n/**\n * Check if given object is a Uint8Array\n * @param {*} n\n * @return {boolean}\n */\nexport function isBlob(n) {\n return n instanceof Uint8Array\n}\n\n/**\n * Check if given object is a Date\n * @param {*} n\n * @return {boolean}\n */\nexport function isDate(n) {\n return n instanceof Date\n}\n\n/**\n * Check if given object is undefined\n * @param {*} n\n * @return {boolean}\n */\nexport function isUndefined(n) {\n return typeof n === 'undefined'\n}\n\n/**\n * Return the next multiple of four\n * @param {number} n\n */\nexport function pad(n) {\n return (n + 3) & ~0x03\n}\n\n/**\n * Checks if environment provides a feature\n * @param {string} name Name of needed feature\n * @return {boolean}\n */\nexport function hasProperty(name) {\n return Object.prototype.hasOwnProperty.call(\n (typeof global !== 'undefined' ? global : window), // eslint-disable-line no-undef\n name,\n )\n}\n\n/**\n * Wrap binary data in DataView\n * @param {*} obj\n * @return {DataView}\n */\nexport function dataView(obj) {\n if (obj.buffer) {\n return new DataView(obj.buffer)\n } else if (obj instanceof ArrayBuffer) {\n return new DataView(obj)\n }\n\n return new DataView(new Uint8Array(obj))\n}\n","import {\n isArray,\n isBlob,\n isFloat,\n isInt,\n isString,\n} from './utils'\n\n/**\n * Checks type of given object and returns the regarding OSC\n * Type tag character\n * @param {*} item Any object\n * @return {string} OSC Type tag character\n */\nexport function typeTag(item) {\n if (isInt(item)) {\n return 'i'\n } else if (isFloat(item)) {\n return 'f'\n } else if (isString(item)) {\n return 's'\n } else if (isBlob(item)) {\n return 'b'\n }\n\n throw new Error('OSC typeTag() found unknown value type')\n}\n\n/**\n * Sanitizes an OSC-ready Address Pattern\n * @param {array|string} obj Address as string or array of strings\n * @return {string} Corrected address string\n *\n * @example\n * // all calls return '/test/path' string:\n * prepareAddress('test/path')\n * prepareAddress('/test/path/')\n * prepareAddress([test, path])\n */\nexport function prepareAddress(obj) {\n let address = ''\n\n if (isArray(obj)) {\n return `/${obj.join('/')}`\n } else if (isString(obj)) {\n address = obj\n\n // remove slash at ending of address\n if (address.length > 1 && address[address.length - 1] === '/') {\n address = address.slice(0, address.length - 1)\n }\n\n // add slash at beginning of address\n if (address.length > 1 && address[0] !== '/') {\n address = `/${address}`\n }\n\n return address\n }\n\n throw new Error('OSC prepareAddress() needs addresses of type array or string')\n}\n\n/**\n * Make an OSC address pattern javascript-regex-ready\n * @param {string} str OSC address pattern\n * @return {string} Javascript RegEx string\n */\nexport function prepareRegExPattern(str) {\n let pattern\n\n if (!(isString(str))) {\n throw new Error('OSC prepareRegExPattern() needs strings')\n }\n\n pattern = str.replace(/\\./g, '\\\\.')\n pattern = pattern.replace(/\\(/g, '\\\\(')\n pattern = pattern.replace(/\\)/g, '\\\\)')\n\n pattern = pattern.replace(/\\{/g, '(')\n pattern = pattern.replace(/\\}/g, ')')\n pattern = pattern.replace(/,/g, '|')\n\n pattern = pattern.replace(/\\[!/g, '[^')\n\n pattern = pattern.replace(/\\?/g, '.')\n pattern = pattern.replace(/\\*/g, '.*')\n\n return pattern\n}\n\n/**\n * Holds a list of items and helps to merge them\n * into a single array of packed binary data\n */\nexport default class EncodeHelper {\n /**\n * Create a new EncodeHelper instance\n */\n constructor() {\n /** @type {array} data */\n this.data = []\n /** @type {number} byteLength */\n this.byteLength = 0\n }\n\n /**\n * Packs an item and adds it to the list\n * @param {*} item Any object\n * @return {EncodeHelper}\n */\n add(item) {\n const buffer = item.pack()\n this.byteLength += buffer.byteLength\n this.data.push(buffer)\n\n return this\n }\n\n /**\n * Merge all added items into one Uint8Array\n * @return {Uint8Array} Merged binary data array of all items\n */\n merge() {\n const result = new Uint8Array(this.byteLength)\n let offset = 0\n\n this.data.forEach((data) => {\n result.set(data, offset)\n offset += data.byteLength\n })\n\n return result\n }\n}\n","import { isUndefined } from './common/utils'\n\n/**\n * Base class for OSC Atomic Data Types\n */\nexport default class Atomic {\n /**\n * Create an Atomic instance\n * @param {*} [value] Initial value of any type\n */\n constructor(value) {\n /** @type {*} value */\n this.value = value\n /** @type {number} offset */\n this.offset = 0\n }\n\n /**\n * Interpret the given value of this entity as packed binary data\n * @param {string} method The DataView method to write to the ArrayBuffer\n * @param {number} byteLength Size of array in bytes\n * @return {Uint8Array} Packed binary data\n */\n pack(method, byteLength) {\n if (!(method && byteLength)) {\n throw new Error('OSC Atomic cant\\'t be packed without given method or byteLength')\n }\n\n const data = new Uint8Array(byteLength)\n const dataView = new DataView(data.buffer)\n\n if (isUndefined(this.value)) {\n throw new Error('OSC Atomic cant\\'t be encoded with empty value')\n }\n\n // use DataView to write to ArrayBuffer\n dataView[method](this.offset, this.value, false)\n\n // always return binary Uint8Array after packing\n return data\n }\n\n /**\n * Unpack binary data from DataView according to the given format\n * @param {DataView} dataView The DataView holding the binary representation of the value\n * @param {string} method The DataView method to read the format from the ArrayBuffer\n * @param {number} byteLength Size of array in bytes\n * @param {number} [initialOffset=0] Offset of DataView before unpacking\n * @return {number} Offset after unpacking\n */\n unpack(dataView, method, byteLength, initialOffset = 0) {\n if (!(dataView && method && byteLength)) {\n throw new Error('OSC Atomic cant\\'t be unpacked without given dataView, method or byteLength')\n }\n\n if (!(dataView instanceof DataView)) {\n throw new Error('OSC Atomic expects an instance of type DataView')\n }\n\n // use DataView to read from ArrayBuffer and add offset\n this.value = dataView[method](initialOffset, false)\n this.offset = initialOffset + byteLength\n\n // always return offset number after unpacking\n return this.offset\n }\n}\n","import { isInt } from '../common/utils'\n\nimport Atomic from '../atomic'\n\n/**\n * 32-bit big-endian two's complement integer OSC Atomic Data Type\n */\nexport default class AtomicInt32 extends Atomic {\n /**\n * Create an AtomicInt32 instance\n * @param {number} [value] Initial integer value\n */\n constructor(value) {\n if (value && !isInt(value)) {\n throw new Error('OSC AtomicInt32 constructor expects value of type number')\n }\n\n super(value)\n }\n\n /**\n * Interpret the given number as packed binary data\n * @return {Uint8Array} Packed binary data\n */\n pack() {\n return super.pack('setInt32', 4)\n }\n\n /**\n * Unpack binary data from DataView and read a Int32 number\n * @param {DataView} dataView The DataView holding the binary representation of the value\n * @param {number} [initialOffset=0] Offset of DataView before unpacking\n * @return {number} Offset after unpacking\n */\n unpack(dataView, initialOffset = 0) {\n return super.unpack(dataView, 'getInt32', 4, initialOffset)\n }\n}\n","import {\n hasProperty,\n isString,\n isUndefined,\n pad,\n} from '../common/utils'\n\nimport Atomic from '../atomic'\n\n/** Slice size of large strings for fallback method */\nconst STR_SLICE_SIZE = 65537\n\n/** Text encoding format */\nconst STR_ENCODING = 'utf-8'\n\n/**\n * Helper method to decode a string using different methods depending on environment\n * @param {array} charCodes Array of char codes\n * @return {string} Decoded string\n */\nfunction charCodesToString(charCodes) {\n // Use these methods to be able to convert large strings\n if (hasProperty('Buffer')) {\n return Buffer.from(charCodes).toString(STR_ENCODING)\n } else if (hasProperty('TextDecoder')) {\n return new TextDecoder(STR_ENCODING) // eslint-disable-line no-undef\n .decode(new Int8Array(charCodes))\n }\n\n // Fallback method\n let str = ''\n\n for (let i = 0; i < charCodes.length; i += STR_SLICE_SIZE) {\n str += String.fromCharCode.apply(\n null,\n charCodes.slice(i, i + STR_SLICE_SIZE),\n )\n }\n\n return str\n}\n\n/**\n * A sequence of non-null ASCII characters OSC Atomic Data Type\n */\nexport default class AtomicString extends Atomic {\n /**\n * Create an AtomicString instance\n * @param {string} [value] Initial string value\n */\n constructor(value) {\n if (value && !isString(value)) {\n throw new Error('OSC AtomicString constructor expects value of type string')\n }\n\n super(value)\n }\n\n /**\n * Interpret the given string as packed binary data\n * @return {Uint8Array} Packed binary data\n */\n pack() {\n if (isUndefined(this.value)) {\n throw new Error('OSC AtomicString can not be encoded with empty value')\n }\n\n // add 0-3 null characters for total number of bits a multiple of 32\n const terminated = `${this.value}\\u0000`\n const byteLength = pad(terminated.length)\n\n const buffer = new Uint8Array(byteLength)\n\n for (let i = 0; i < terminated.length; i += 1) {\n buffer[i] = terminated.charCodeAt(i)\n }\n\n return buffer\n }\n\n /**\n * Unpack binary data from DataView and read a string\n * @param {DataView} dataView The DataView holding the binary representation of the string\n * @param {number} [initialOffset=0] Offset of DataView before unpacking\n * @return {number} Offset after unpacking\n */\n unpack(dataView, initialOffset = 0) {\n if (!(dataView instanceof DataView)) {\n throw new Error('OSC AtomicString expects an instance of type DataView')\n }\n\n let offset = initialOffset\n let charcode\n const charCodes = []\n\n for (; offset < dataView.byteLength; offset += 1) {\n charcode = dataView.getUint8(offset)\n\n // check for terminating null character\n if (charcode !== 0) {\n charCodes.push(charcode)\n } else {\n offset += 1\n break\n }\n }\n\n if (offset === dataView.length) {\n throw new Error('OSC AtomicString found a malformed OSC string')\n }\n\n /** @type {number} offset */\n this.offset = pad(offset)\n /** @type {string} value */\n this.value = charCodesToString(charCodes)\n\n return this.offset\n }\n}\n","import {\n isDate,\n isInt,\n isUndefined,\n} from '../common/utils'\n\nimport Atomic from '../atomic'\n\n/** 70 years in seconds */\nexport const SECONDS_70_YEARS = 2208988800\n/** 2^32 */\nexport const TWO_POWER_32 = 4294967296\n\n/**\n * Timetag helper class for representing NTP timestamps\n * and conversion between them and javascript representation\n */\nexport class Timetag {\n /**\n * Create a Timetag instance\n * @param {number} [seconds=0] Initial NTP *seconds* value\n * @param {number} [fractions=0] Initial NTP *fractions* value\n */\n constructor(seconds = 0, fractions = 0) {\n if (!(isInt(seconds) && isInt(fractions))) {\n throw new Error('OSC Timetag constructor expects values of type integer number')\n }\n\n /** @type {number} seconds */\n this.seconds = seconds\n /** @type {number} fractions */\n this.fractions = fractions\n }\n\n /**\n * Converts from NTP to JS representation and back\n * @param {number} [milliseconds] Converts from JS milliseconds to NTP.\n * Leave empty for converting from NTP to JavaScript representation\n * @return {number} Javascript timestamp\n */\n timestamp(milliseconds) {\n let seconds\n\n if (typeof milliseconds === 'number') {\n seconds = milliseconds / 1000\n const rounded = Math.floor(seconds)\n\n this.seconds = rounded + SECONDS_70_YEARS\n this.fractions = Math.round(TWO_POWER_32 * (seconds - rounded))\n\n return milliseconds\n }\n\n seconds = this.seconds - SECONDS_70_YEARS\n return (seconds + Math.round(this.fractions / TWO_POWER_32)) * 1000\n }\n}\n\n/**\n * 64-bit big-endian fixed-point time tag, semantics\n * defined below OSC Atomic Data Type\n */\nexport default class AtomicTimetag extends Atomic {\n /**\n * Create a AtomicTimetag instance\n * @param {number|Timetag|Date} [value] Initial date, leave empty if\n * you want it to be the current date\n */\n constructor(value = Date.now()) {\n let timetag = new Timetag()\n\n if (value instanceof Timetag) {\n timetag = value\n } else if (isInt(value)) {\n timetag.timestamp(value)\n } else if (isDate(value)) {\n timetag.timestamp(value.getTime())\n }\n\n super(timetag)\n }\n\n /**\n * Interpret the given timetag as packed binary data\n * @return {Uint8Array} Packed binary data\n */\n pack() {\n if (isUndefined(this.value)) {\n throw new Error('OSC AtomicTimetag can not be encoded with empty value')\n }\n\n const { seconds, fractions } = this.value\n const data = new Uint8Array(8)\n const dataView = new DataView(data.buffer)\n\n dataView.setInt32(0, seconds, false)\n dataView.setInt32(4, fractions, false)\n\n return data\n }\n\n /**\n * Unpack binary data from DataView and read a timetag\n * @param {DataView} dataView The DataView holding the binary representation of the timetag\n * @param {number} [initialOffset=0] Offset of DataView before unpacking\n * @return {number} Offset after unpacking\n */\n unpack(dataView, initialOffset = 0) {\n if (!(dataView instanceof DataView)) {\n throw new Error('OSC AtomicTimetag expects an instance of type DataView')\n }\n\n const seconds = dataView.getUint32(initialOffset, false)\n const fractions = dataView.getUint32(initialOffset + 4, false)\n\n /** @type {Timetag} value */\n this.value = new Timetag(seconds, fractions)\n /** @type {number} offset */\n this.offset = initialOffset + 8\n\n return this.offset\n }\n}\n","import {\n isBlob,\n isUndefined,\n pad,\n} from '../common/utils'\n\nimport Atomic from '../atomic'\n\n/**\n * 8-bit bytes of arbitrary binary data OSC Atomic Data Type\n */\nexport default class AtomicBlob extends Atomic {\n /**\n * Create an AtomicBlob instance\n * @param {Uint8Array} [value] Binary data\n */\n constructor(value) {\n if (value && !isBlob(value)) {\n throw new Error('OSC AtomicBlob constructor expects value of type Uint8Array')\n }\n\n super(value)\n }\n\n /**\n * Interpret the given blob as packed binary data\n * @return {Uint8Array} Packed binary data\n */\n pack() {\n if (isUndefined(this.value)) {\n throw new Error('OSC AtomicBlob can not be encoded with empty value')\n }\n\n const byteLength = pad(this.value.byteLength)\n const data = new Uint8Array(byteLength + 4)\n const dataView = new DataView(data.buffer)\n\n // an int32 size count\n dataView.setInt32(0, this.value.byteLength, false)\n // followed by 8-bit bytes of arbitrary binary data\n data.set(this.value, 4)\n\n return data\n }\n\n /**\n * Unpack binary data from DataView and read a blob\n * @param {DataView} dataView The DataView holding the binary representation of the blob\n * @param {number} [initialOffset=0] Offset of DataView before unpacking\n * @return {number} Offset after unpacking\n */\n unpack(dataView, initialOffset = 0) {\n if (!(dataView instanceof DataView)) {\n throw new Error('OSC AtomicBlob expects an instance of type DataView')\n }\n\n const byteLength = dataView.getInt32(initialOffset, false)\n\n /** @type {Uint8Array} value */\n this.value = new Uint8Array(dataView.buffer, initialOffset + 4, byteLength)\n /** @type {number} offset */\n this.offset = pad(initialOffset + 4 + byteLength)\n\n return this.offset\n }\n}\n","import { isNumber } from '../common/utils'\n\nimport Atomic from '../atomic'\n\n/**\n * 32-bit big-endian IEEE 754 floating point number OSC Atomic Data Type\n */\nexport default class AtomicFloat32 extends Atomic {\n /**\n * Create an AtomicFloat32 instance\n * @param {number} [value] Float number\n */\n constructor(value) {\n if (value && !isNumber(value)) {\n throw new Error('OSC AtomicFloat32 constructor expects value of type float')\n }\n\n super(value)\n }\n\n /**\n * Interpret the given number as packed binary data\n * @return {Uint8Array} Packed binary data\n */\n pack() {\n return super.pack('setFloat32', 4)\n }\n\n /**\n * Unpack binary data from DataView and read a Float32 number\n * @param {DataView} dataView The DataView holding the binary representation of the value\n * @param {number} [initialOffset=0] Offset of DataView before unpacking\n * @return {number} Offset after unpacking\n */\n unpack(dataView, initialOffset = 0) {\n return super.unpack(dataView, 'getFloat32', 4, initialOffset)\n }\n}\n","import { isNumber } from '../common/utils'\n\nimport Atomic from '../atomic'\n\n/**\n * 64-bit big-endian IEEE 754 floating point number OSC Atomic Data Type\n */\nexport default class AtomicFloat64 extends Atomic {\n /**\n * Create an AtomicFloat64 instance\n * @param {number} [value] Float number\n */\n constructor(value) {\n if (value && !isNumber(value)) {\n throw new Error('OSC AtomicFloat64 constructor expects value of type float')\n }\n\n super(value)\n }\n\n /**\n * Interpret the given number as packed binary data\n * @return {Uint8Array} Packed binary data\n */\n pack() {\n return super.pack('setFloat64', 8)\n }\n\n /**\n * Unpack binary data from DataView and read a Float64 number\n * @param {DataView} dataView The DataView holding the binary representation of the value\n * @param {number} [initialOffset=0] Offset of DataView before unpacking\n * @return {number} Offset after unpacking\n */\n unpack(dataView, initialOffset = 0) {\n return super.unpack(dataView, 'getFloat64', 8, initialOffset)\n }\n}\n","import Atomic from '../atomic'\n\nconst MAX_INT64 = BigInt('9223372036854775807')\nconst MIN_INT64 = BigInt('-9223372036854775808')\n\n/**\n * 64-bit big-endian two's complement integer OSC Atomic Data Type\n */\nexport default class AtomicInt64 extends Atomic {\n /**\n * Create an AtomicInt64 instance\n * @param {number} [value] Initial integer value\n */\n constructor(value) {\n if (value && typeof value !== 'bigint') {\n throw new Error('OSC AtomicInt64 constructor expects value of type BigInt')\n }\n\n if (value && (value < MIN_INT64 || value > MAX_INT64)) {\n throw new Error('OSC AtomicInt64 value is out of bounds')\n }\n\n let tmp\n if (value) {\n tmp = BigInt.asIntN(64, value)\n }\n\n super(tmp)\n }\n\n /**\n * Interpret the given number as packed binary data\n * @return {Uint8Array} Packed binary data\n */\n pack() {\n return super.pack('setBigInt64', 8)\n }\n\n /**\n * Unpack binary data from DataView and read a Int64 number\n * @param {DataView} dataView The DataView holding the binary representation of the value\n * @param {number} [initialOffset=0] Offset of DataView before unpacking\n * @return {number} Offset after unpacking\n */\n unpack(dataView, initialOffset = 0) {\n return super.unpack(dataView, 'getBigInt64', 8, initialOffset)\n }\n}\n","import Atomic from '../atomic'\n\nconst MAX_UINT64 = BigInt('18446744073709551615')\n\n/**\n * Unsigned 64-bit big-endian two's complement integer OSC Atomic Data Type\n */\nexport default class AtomicUInt64 extends Atomic {\n /**\n * Create an AtomicUInt64 instance\n * @param {number} [value] Initial integer value\n */\n constructor(value) {\n if (value && typeof value !== 'bigint') {\n throw new Error('OSC AtomicUInt64 constructor expects value of type BigInt')\n }\n\n if (value && (value < 0 || value > MAX_UINT64)) {\n throw new Error('OSC AtomicUInt64 value is out of bounds')\n }\n\n let tmp\n if (value) {\n tmp = BigInt.asUintN(64, value)\n }\n\n super(tmp)\n }\n\n /**\n * Interpret the given number as packed binary data\n * @return {Uint8Array} Packed binary data\n */\n pack() {\n return super.pack('setBigUint64', 8)\n }\n\n /**\n * Unpack binary data from DataView and read a UInt64 number\n * @param {DataView} dataView The DataView holding the binary representation of the value\n * @param {number} [initialOffset=0] Offset of DataView before unpacking\n * @return {number} Offset after unpacking\n */\n unpack(dataView, initialOffset = 0) {\n return super.unpack(dataView, 'getBigUint64', 8, initialOffset)\n }\n}\n","import {\n isArray,\n isString,\n isUndefined,\n} from './common/utils'\n\nimport Helper, { typeTag, prepareAddress } from './common/helpers'\n\nimport AtomicBlob from './atomic/blob'\nimport AtomicFloat32 from './atomic/float32'\nimport AtomicFloat64 from './atomic/float64'\nimport AtomicInt32 from './atomic/int32'\nimport AtomicInt64 from './atomic/int64'\nimport AtomicUInt64 from './atomic/uint64'\nimport AtomicString from './atomic/string'\n\n/**\n * A TypedMessage consists of an OSC address and an optional array of typed OSC arguments.\n *\n * ## Supported types\n *\n * - `i` - int32\n * - `f` - float32\n * - `s` - string\n * - `b` - blob\n * - `h` - int64\n * - `t` - uint64\n * - `d` - double\n * - `T` - True (no argument data)\n * - `F` - False (no argument data)\n * - `N` - Nil (no argument data)\n * - `I` - Infinitum (no argument data)\n *\n */\nexport class TypedMessage {\n /**\n * Create a TypedMessage instance\n * @param {array|string} address Address\n * @param {array} args Arguments\n *\n * @example\n * const message = new TypedMessage(['test', 'path'])\n * message.add('d', 123.123456789)\n * message.add('s', 'hello')\n *\n * @example\n * const message = new TypedMessage('/test/path', [\n * { type: 'i', value: 123 },\n * { type: 'd', value: 123.123 },\n * { type: 'h', value: 0xFFFFFFn },\n * { type: 'T', value: null },\n * ])\n */\n constructor(address, args) {\n /**\n * @type {number} offset\n * @private\n */\n this.offset = 0\n /** @type {string} address */\n this.address = ''\n /** @type {string} types */\n this.types = ''\n /** @type {array} args */\n this.args = []\n\n if (!isUndefined(address)) {\n if (!(isString(address) || isArray(address))) {\n throw new Error('OSC Message constructor first argument (address) must be a string or array')\n }\n this.address = prepareAddress(address)\n }\n\n if (!isUndefined(args)) {\n if (!isArray(args)) {\n throw new Error('OSC Message constructor second argument (args) must be an array')\n }\n args.forEach((item) => this.add(item.type, item.value))\n }\n }\n\n /**\n * Add an OSC Atomic Data Type to the list of elements\n * @param {string} type\n * @param {*} item\n */\n add(type, item) {\n if (isUndefined(type)) {\n throw new Error('OSC Message needs a valid OSC Atomic Data Type')\n }\n\n // Some data types e.g. Boolean does not require item\n if (!(item === null || isUndefined(item))) {\n this.args.push(item)\n }\n\n this.types += type\n }\n\n /**\n * Interpret the Message as packed binary data\n * @return {Uint8Array} Packed binary data\n */\n pack() {\n if (this.address.length === 0 || this.address[0] !== '/') {\n throw new Error('OSC Message has an invalid address')\n }\n\n const encoder = new Helper()\n\n // OSC Address Pattern and Type string\n encoder.add(new AtomicString(this.address))\n encoder.add(new AtomicString(`,${this.types}`))\n\n // followed by zero or more OSC Arguments\n if (this.args.length > 0) {\n let argument\n\n if (this.args.length > this.types.length) {\n throw new Error('OSC Message argument and type tag mismatch')\n }\n\n this.args.forEach((value, index) => {\n const type = this.types[index]\n if (type === 'i') {\n argument = new AtomicInt32(value)\n } else if (type === 'h') {\n argument = new AtomicInt64(value)\n } else if (type === 't') {\n argument = new AtomicUInt64(value)\n } else if (type === 'f') {\n argument = new AtomicFloat32(value)\n } else if (type === 'd') {\n argument = new AtomicFloat64(value)\n } else if (type === 's') {\n argument = new AtomicString(value)\n } else if (type === 'b') {\n argument = new AtomicBlob(value)\n } else {\n throw new Error('OSC Message found unknown argument type')\n }\n\n encoder.add(argument)\n })\n }\n\n return encoder.merge()\n }\n\n /**\n * Unpack binary data to read a Message\n * @param {DataView} dataView The DataView holding the binary representation of a Message\n * @param {number} [initialOffset=0] Offset of DataView before unpacking\n * @return {number} Offset after unpacking\n */\n unpack(dataView, initialOffset = 0) {\n if (!(dataView instanceof DataView)) {\n throw new Error('OSC Message expects an instance of type DataView.')\n }\n\n // read address pattern\n const address = new AtomicString()\n address.unpack(dataView, initialOffset)\n\n // read type string\n const types = new AtomicString()\n types.unpack(dataView, address.offset)\n\n if (address.value.length === 0 || address.value[0] !== '/') {\n throw new Error('OSC Message found malformed or missing address string')\n }\n\n if (types.value.length === 0 && types.value[0] !== ',') {\n throw new Error('OSC Message found malformed or missing type string')\n }\n\n let { offset } = types\n let next\n let type\n\n const args = []\n\n // read message arguments (OSC Atomic Data Types)\n for (let i = 1; i < types.value.length; i += 1) {\n type = types.value[i]\n\n if (type === 'i') {\n next = new AtomicInt32()\n } else if (type === 'h') {\n next = new AtomicInt64()\n } else if (type === 't') {\n next = new AtomicUInt64()\n } else if (type === 'f') {\n next = new AtomicFloat32()\n } else if (type === 'd') {\n next = new AtomicFloat64()\n } else if (type === 's') {\n next = new AtomicString()\n } else if (type === 'b') {\n next = new AtomicBlob()\n } else if (type === 'T' || type === 'F') {\n next = null\n } else if (type === 'N') {\n next = null\n } else if (type === 'I') {\n next = null\n } else {\n throw new Error('OSC Message found non-standard argument type')\n }\n\n if (next !== null) {\n offset = next.unpack(dataView, offset)\n args.push(next.value)\n }\n }\n\n this.offset = offset\n this.address = address.value\n this.types = types.value\n this.args = args\n\n return this.offset\n }\n}\n\n/**\n * An OSC message consists of an OSC Address Pattern followed\n * by an OSC Type Tag String followed by zero or more OSC Arguments\n */\nexport default class Message extends TypedMessage {\n /**\n * Create a Message instance\n * @param {array|string} args Address\n * @param {...*} args OSC Atomic Data Types\n *\n * @example\n * const message = new Message(['test', 'path'], 50, 100.52, 'test')\n *\n * @example\n * const message = new Message('/test/path', 51.2)\n */\n constructor(...args) {\n let address\n if (args.length > 0) {\n address = args.shift()\n }\n\n let oscArgs\n if (args.length > 0) {\n if (args[0] instanceof Array) {\n oscArgs = args.shift()\n }\n }\n\n super(address, oscArgs)\n\n if (args.length > 0) {\n this.types = args.map((item) => typeTag(item)).join('')\n this.args = args\n }\n }\n\n /**\n * Add an OSC Atomic Data Type to the list of elements\n * @param {*} item\n */\n add(item) {\n super.add(typeTag(item), item)\n }\n}\n","import EncodeHelper from './common/helpers'\nimport { isArray, isInt } from './common/utils'\n\nimport AtomicInt32 from './atomic/int32'\nimport AtomicString from './atomic/string'\nimport AtomicTimetag from './atomic/timetag'\nimport Message from './message'\n\n/** OSC Bundle string */\nexport const BUNDLE_TAG = '#bundle'\n\n/**\n * An OSC Bundle consist of a Timetag and one or many Bundle Elements.\n * The elements are either OSC Messages or more OSC Bundles\n */\nexport default class Bundle {\n /**\n * Create a Bundle instance\n * @param {...*} [args] Timetag and elements. See examples for options\n *\n * @example\n * const bundle = new Bundle(new Date() + 500)\n *\n * @example\n * const message = new Message('/test/path', 51.2)\n * const anotherBundle = new Bundle([message], Date.now() + 1500)\n *\n * @example\n * const message = new Message('/test/path', 51.2)\n * const anotherMessage = new Message('/test/message', 'test', 12)\n * const anotherBundle = new Bundle(message, anotherMessage)\n */\n constructor(...args) {\n /**\n * @type {number} offset\n * @private\n */\n this.offset = 0\n /** @type {AtomicTimetag} timetag */\n this.timetag = new AtomicTimetag()\n /** @type {array} bundleElements */\n this.bundleElements = []\n\n if (args.length > 0) {\n // first argument is an Date or js timestamp (number)\n if (args[0] instanceof Date || isInt(args[0])) {\n this.timetag = new AtomicTimetag(args[0])\n } else if (isArray(args[0])) {\n // first argument is an Array of Bundle elements\n args[0].forEach((item) => {\n this.add(item)\n })\n\n // second argument is an Date or js timestamp (number)\n if (args.length > 1 && (args[1] instanceof Date || isInt(args[0]))) {\n this.timetag = new AtomicTimetag(args[1])\n }\n } else {\n // take all arguments as Bundle elements\n args.forEach((item) => {\n this.add(item)\n })\n }\n }\n }\n\n /**\n * Take a JavaScript timestamp to set the Bundle's timetag\n * @param {number} ms JS timestamp in milliseconds\n *\n * @example\n * const bundle = new Bundle()\n * bundle.timestamp(Date.now() + 5000) // in 5 seconds\n */\n timestamp(ms) {\n if (!isInt(ms)) {\n throw new Error('OSC Bundle needs an integer for setting the timestamp')\n }\n\n this.timetag = new AtomicTimetag(ms)\n }\n\n /**\n * Add a Message or Bundle to the list of elements\n * @param {Bundle|Message} item\n */\n add(item) {\n if (!(item instanceof Message || item instanceof Bundle)) {\n throw new Error('OSC Bundle contains only Messages and Bundles')\n }\n\n this.bundleElements.push(item)\n }\n\n /**\n * Interpret the Bundle as packed binary data\n * @return {Uint8Array} Packed binary data\n */\n pack() {\n const encoder = new EncodeHelper()\n\n // an OSC Bundle consists of the OSC-string \"#bundle\"\n encoder.add(new AtomicString(BUNDLE_TAG))\n\n // followed by an OSC Time Tag\n if (!this.timetag) {\n this.timetag = new AtomicTimetag()\n }\n\n encoder.add(this.timetag)\n\n // followed by zero or more OSC Bundle Elements\n this.bundleElements.forEach((item) => {\n encoder.add(new AtomicInt32(item.pack().byteLength))\n encoder.add(item)\n })\n\n return encoder.merge()\n }\n\n /**\n * Unpack binary data to read a Bundle\n * @param {DataView} dataView The DataView holding the binary representation of a Bundle\n * @param {number} [initialOffset=0] Offset of DataView before unpacking\n * @return {number} Offset after unpacking\n */\n unpack(dataView, initialOffset = 0) {\n if (!(dataView instanceof DataView)) {\n throw new Error('OSC Bundle expects an instance of type DataView')\n }\n\n // read the beginning bundle string\n const parentHead = new AtomicString()\n parentHead.unpack(dataView, initialOffset)\n\n if (parentHead.value !== BUNDLE_TAG) {\n throw new Error('OSC Bundle does not contain a valid #bundle head')\n }\n\n // read the timetag\n const timetag = new AtomicTimetag()\n let offset = timetag.unpack(dataView, parentHead.offset)\n\n // read the bundle elements\n this.bundleElements = []\n\n while (offset < dataView.byteLength) {\n const head = new AtomicString()\n const size = new AtomicInt32()\n\n offset = size.unpack(dataView, offset)\n\n // check if Packet is a Bundle or a Message\n let item\n head.unpack(dataView, offset)\n\n if (head.value === BUNDLE_TAG) {\n item = new Bundle()\n } else {\n item = new Message()\n }\n\n offset = item.unpack(dataView, offset)\n\n this.bundleElements.push(item)\n }\n\n this.offset = offset\n this.timetag = timetag\n\n return this.offset\n }\n}\n","import AtomicString from './atomic/string'\nimport Bundle, { BUNDLE_TAG } from './bundle'\nimport Message from './message'\n\n/**\n * The unit of transmission of OSC is an OSC Packet. The contents\n * of an OSC packet must be either an OSC Message or an OSC Bundle\n */\nexport default class Packet {\n /**\n * Create a Packet instance holding a Message or Bundle\n * @param {Message|Bundle} [value] Initial Packet value\n */\n constructor(value) {\n if (value && !(value instanceof Message || value instanceof Bundle)) {\n throw new Error('OSC Packet value has to be Message or Bundle')\n }\n\n /** @type {Message|Bundle} value */\n this.value = value\n /**\n * @type {number} offset\n * @private\n */\n this.offset = 0\n }\n\n /**\n * Packs the Packet value. This implementation is more like\n * a wrapper due to OSC specifications, you could also skip the\n * Packet and directly work with the Message or Bundle instance\n * @return {Uint8Array} Packed binary data\n *\n * @example\n * const message = new Message('/test/path', 21.5, 'test')\n * const packet = new Packet(message)\n * const packetBinary = packet.pack() // then send it via udp etc.\n *\n * // or skip the Packet for convenience\n * const messageBinary = message.pack()\n */\n pack() {\n if (!this.value) {\n throw new Error('OSC Packet can not be encoded with empty body')\n }\n\n return this.value.pack()\n }\n\n /**\n * Unpack binary data from DataView to read Messages or Bundles\n * @param {DataView} dataView The DataView holding a binary representation of a Packet\n * @param {number} [initialOffset=0] Offset of DataView before unpacking\n * @return {number} Offset after unpacking\n */\n unpack(dataView, initialOffset = 0) {\n if (!(dataView instanceof DataView)) {\n throw new Error('OSC Packet expects an instance of type DataView')\n }\n\n if (dataView.byteLength % 4 !== 0) {\n throw new Error('OSC Packet byteLength has to be a multiple of four')\n }\n\n const head = new AtomicString()\n head.unpack(dataView, initialOffset)\n\n let item\n\n // check if Packet is a Bundle or a Message\n if (head.value === BUNDLE_TAG) {\n item = new Bundle()\n } else {\n item = new Message()\n }\n\n item.unpack(dataView, initialOffset)\n\n this.offset = item.offset\n this.value = item\n\n return this.offset\n }\n}\n","import {\n dataView,\n isArray,\n isFunction,\n isInt,\n isString,\n} from './common/utils'\n\nimport {\n prepareAddress,\n prepareRegExPattern,\n} from './common/helpers'\n\nimport Bundle from './bundle'\nimport Message from './message'\nimport Packet from './packet'\n\n/**\n * Default options\n * @private\n */\nconst defaultOptions = {\n discardLateMessages: false,\n}\n\n/**\n * EventHandler to notify listeners on matching OSC messages and\n * status changes of plugins\n */\nexport default class EventHandler {\n /**\n * Create an EventHandler instance\n * @param {object} options Custom options\n */\n constructor(options) {\n /**\n * @type {object} options\n * @private\n */\n this.options = { ...defaultOptions, ...options }\n /**\n * @type {array} addressHandlers\n * @private\n */\n this.addressHandlers = []\n /**\n * @type {object} eventHandlers\n * @private\n */\n this.eventHandlers = {\n open: [],\n error: [],\n close: [],\n }\n /**\n * @type {number} uuid\n * @private\n */\n this.uuid = 0\n }\n\n /**\n * Internally used method to dispatch OSC Packets. Extracts\n * given Timetags and dispatches them accordingly\n * @param {Packet} packet\n * @param {*} [rinfo] Remote address info\n * @return {boolean} Success state\n * @private\n */\n dispatch(packet, rinfo) {\n if (!(packet instanceof Packet)) {\n throw new Error('OSC EventHander dispatch() accepts only arguments of type Packet')\n }\n\n if (!packet.value) {\n throw new Error('OSC EventHander dispatch() can\\'t read empty Packets')\n }\n\n if (packet.value instanceof Bundle) {\n const bundle = packet.value\n\n return bundle.bundleElements.forEach((bundleItem) => {\n if (bundleItem instanceof Bundle) {\n if (bundle.timetag.value.timestamp() < bundleItem.timetag.value.timestamp()) {\n throw new Error('OSC Bundle timestamp is older than the timestamp of enclosed Bundles')\n }\n return this.dispatch(bundleItem)\n } else if (bundleItem instanceof Message) {\n const message = bundleItem\n return this.notify(\n message.address,\n message,\n bundle.timetag.value.timestamp(),\n rinfo,\n )\n }\n\n throw new Error('OSC EventHander dispatch() can\\'t dispatch unknown Packet value')\n })\n } else if (packet.value instanceof Message) {\n const message = packet.value\n return this.notify(message.address, message, 0, rinfo)\n }\n\n throw new Error('OSC EventHander dispatch() can\\'t dispatch unknown Packet value')\n }\n\n /**\n * Internally used method to invoke listener callbacks. Uses regular\n * expression pattern matching for OSC addresses\n * @param {string} name OSC address or event name\n * @param {*} [data] The data of the event\n * @param {*} [rinfo] Remote address info\n * @return {boolean} Success state\n * @private\n */\n call(name, data, rinfo) {\n let success = false\n\n // call event handlers\n if (isString(name) && name in this.eventHandlers) {\n this.eventHandlers[name].forEach((handler) => {\n handler.callback(data, rinfo)\n success = true\n })\n\n return success\n }\n\n // call address handlers\n const handlerKeys = Object.keys(this.addressHandlers)\n const handlers = this.addressHandlers\n\n handlerKeys.forEach((key) => {\n let foundMatch = false\n\n const regex = new RegExp(prepareRegExPattern(prepareAddress(name)), 'g')\n const test = regex.test(key)\n\n // found a matching address in our callback handlers\n if (test && key.length === regex.lastIndex) {\n foundMatch = true\n }\n\n if (!foundMatch) {\n // try matching address from callback handlers (when given)\n const reverseRegex = new RegExp(prepareRegExPattern(prepareAddress(key)), 'g')\n const reverseTest = reverseRegex.test(name)\n\n if (reverseTest && name.length === reverseRegex.lastIndex) {\n foundMatch = true\n }\n }\n\n if (foundMatch) {\n handlers[key].forEach((handler) => {\n handler.callback(data, rinfo)\n success = true\n })\n }\n })\n\n return success\n }\n\n /**\n * Notify the EventHandler of incoming OSC messages or status\n * changes (*open*, *close*, *error*). Handles OSC address patterns\n * and executes timed messages. Use binary arrays when\n * handling directly incoming network data. Packet's or Messages can\n * also be used\n * @param {...*} args\n * The OSC address pattern / event name as string}. For convenience and\n * Plugin API communication you can also use Message or Packet instances\n * or ArrayBuffer, Buffer instances (low-level access). The latter will\n * automatically be unpacked\n * When using a string you can also pass on data as a second argument\n * (any type). All regarding listeners will be notified with this data.\n * As a third argument you can define a javascript timestamp (number or\n * Date instance) for timed notification of the listeners.\n * @param {*} [rinfo] Remote address info\n * @return {boolean} Success state of notification\n *\n * @example\n * const socket = dgram.createSocket('udp4')\n * socket.on('message', (message) => {\n * this.notify(message)\n * })\n *\n * @example\n * this.notify('error', error.message)\n *\n * @example\n * const message = new OSC.Message('/test/path', 55)\n * this.notify(message)\n *\n * @example\n * const message = new OSC.Message('/test/path', 55)\n * // override timestamp\n * this.notify(message.address, message, Date.now() + 5000)\n */\n notify(...args) {\n if (args.length === 0) {\n throw new Error('OSC EventHandler can not be called without any argument')\n }\n\n // check for incoming dispatchable OSC data\n if (args[0] instanceof Packet) {\n return this.dispatch(args[0], args[1])\n } else if (args[0] instanceof Bundle || args[0] instanceof Message) {\n return this.dispatch(new Packet(args[0]), args[1])\n } else if (!isString(args[0])) {\n const packet = new Packet()\n packet.unpack(dataView(args[0]))\n return this.dispatch(packet, args[1])\n }\n\n const name = args[0]\n\n // data argument\n let data = null\n\n if (args.length > 1) {\n data = args[1]\n }\n\n // timestamp argument\n let timestamp = null\n\n if (args.length > 2) {\n if (isInt(args[2])) {\n timestamp = args[2]\n } else if (args[2] instanceof Date) {\n timestamp = args[2].getTime()\n } else {\n throw new Error('OSC EventHandler timestamp has to be a number or Date')\n }\n }\n\n // remote address info\n let rinfo = null\n\n if (args.length >= 3) {\n rinfo = args[3]\n }\n\n // notify now or later\n if (timestamp) {\n const now = Date.now()\n\n // is message outdated?\n if (now > timestamp) {\n if (!this.options.discardLateMessages) {\n return this.call(name, data, rinfo)\n }\n }\n\n // notify later\n const that = this\n\n setTimeout(() => {\n that.call(name, data, rinfo)\n }, timestamp - now)\n\n return true\n }\n\n return this.call(name, data, rinfo)\n }\n\n /**\n * Subscribe to a new address or event you want to listen to\n * @param {string} name The OSC address or event name\n * @param {function} callback Callback function on notification\n * @return {number} Subscription identifier (needed to unsubscribe)\n */\n on(name, callback) {\n if (!(isString(name) || isArray(name))) {\n throw new Error('OSC EventHandler accepts only strings or arrays for address patterns')\n }\n\n if (!isFunction(callback)) {\n throw new Error('OSC EventHandler callback has to be a function')\n }\n\n // get next id\n this.uuid += 1\n\n // prepare handler\n const handler = {\n id: this.uuid,\n callback,\n }\n\n // register event listener\n if (isString(name) && name in this.eventHandlers) {\n this.eventHandlers[name].push(handler)\n return this.uuid\n }\n\n // register address listener\n const address = prepareAddress(name)\n\n if (!(address in this.addressHandlers)) {\n this.addressHandlers[address] = []\n }\n\n this.addressHandlers[address].push(handler)\n\n return this.uuid\n }\n\n /**\n * Unsubscribe listener from event notification or address handler\n * @param {string} name The OSC address or event name\n * @param {number} subscriptionId Subscription id to identify the handler\n * @return {boolean} Success state\n */\n off(name, subscriptionId) {\n if (!(isString(name) || isArray(name))) {\n throw new Error('OSC EventHandler accepts only strings or arrays for address patterns')\n }\n\n if (!isInt(subscriptionId)) {\n throw new Error('OSC EventHandler subscription id has to be a number')\n }\n\n let key\n let haystack\n\n // event or address listener\n if (isString(name) && name in this.eventHandlers) {\n key = name\n haystack = this.eventHandlers\n } else {\n key = prepareAddress(name)\n haystack = this.addressHandlers\n }\n\n // remove the entry\n if (key in haystack) {\n return haystack[key].some((item, index) => {\n if (item.id === subscriptionId) {\n haystack[key].splice(index, 1)\n return true\n }\n\n return false\n })\n }\n\n return false\n }\n}\n","const dgram = typeof __dirname !== 'undefined' ? require('dgram') : undefined\n\n/**\n * Status flags\n * @private\n */\nconst STATUS = {\n IS_NOT_INITIALIZED: -1,\n IS_CONNECTING: 0,\n IS_OPEN: 1,\n IS_CLOSING: 2,\n IS_CLOSED: 3,\n}\n\n/**\n * Default options for open method\n * @private\n */\nconst defaultOpenOptions = {\n host: 'localhost',\n port: 41234,\n exclusive: false,\n}\n\n/**\n * Default options for send method\n * @private\n */\nconst defaultSendOptions = {\n host: 'localhost',\n port: 41235,\n}\n\n/**\n * Default options\n * @private\n */\nconst defaultOptions = {\n type: 'udp4',\n open: defaultOpenOptions,\n send: defaultSendOptions,\n}\n\n/**\n * Helper method to merge nested objects\n * @private\n */\nfunction mergeOptions(base, custom) {\n return {\n ...defaultOptions,\n ...base,\n ...custom,\n open: { ...defaultOptions.open, ...base.open, ...custom.open },\n send: { ...defaultOptions.send, ...base.send, ...custom.send },\n }\n}\n\n/**\n * OSC plugin for simple OSC messaging via udp client\n * and udp server\n */\nexport default class DatagramPlugin {\n /**\n * Create an OSC Plugin instance with given options. Defaults to\n * localhost:41234 for server and localhost:41235 for client messaging\n * @param {object} [options] Custom options\n * @param {string} [options.type='udp4'] 'udp4' or 'udp6'\n * @param {string} [options.open.host='localhost'] Hostname of udp server to bind to\n * @param {number} [options.open.port=41234] Port of udp server to bind to\n * @param {boolean} [options.open.exclusive=false] Exclusive flag\n * @param {string} [options.send.host='localhost'] Hostname of udp client for messaging\n * @param {number} [options.send.port=41235] Port of udp client for messaging\n *\n * @example\n * const plugin = new OSC.DatagramPlugin({ send: { port: 9912 } })\n * const osc = new OSC({ plugin: plugin })\n */\n constructor(customOptions = {}) {\n if (!dgram) {\n throw new Error('DatagramPlugin can not be used in browser context')\n }\n\n /**\n * @type {object} options\n * @private\n */\n this.options = mergeOptions({}, customOptions)\n\n /**\n * @type {object} socket\n * @private\n */\n this.socket = dgram.createSocket(this.options.type)\n /**\n * @type {number} socketStatus\n * @private\n */\n this.socketStatus = STATUS.IS_NOT_INITIALIZED\n\n // register events\n this.socket.on('message', (message, rinfo) => {\n this.notify(message, rinfo)\n })\n\n this.socket.on('error', (error) => {\n this.notify('error', error)\n })\n\n /**\n * @type {function} notify\n * @private\n */\n this.notify = () => {}\n }\n\n /**\n * Internal method to hook into osc library's\n * EventHandler notify method\n * @param {function} fn Notify callback\n * @private\n */\n registerNotify(fn) {\n this.notify = fn\n }\n\n /**\n * Returns the current status of the connection\n * @return {number} Status ID\n */\n status() {\n return this.socketStatus\n }\n\n /**\n * Bind a udp socket to a hostname and port\n * @param {object} [customOptions] Custom options\n * @param {string} [customOptions.host='localhost'] Hostname of udp server to bind to\n * @param {number} [customOptions.port=41234] Port of udp server to bind to\n * @param {boolean} [customOptions.exclusive=false] Exclusive flag\n */\n open(customOptions = {}) {\n const options = { ...this.options.open, ...customOptions }\n const { port, exclusive } = options\n\n this.socketStatus = STATUS.IS_CONNECTING\n\n this.socket.bind({\n address: options.host,\n port,\n exclusive,\n }, () => {\n this.socketStatus = STATUS.IS_OPEN\n this.notify('open')\n })\n }\n\n /**\n * Close udp socket\n */\n close() {\n this.socketStatus = STATUS.IS_CLOSING\n\n this.socket.close(() => {\n this.socketStatus = STATUS.IS_CLOSED\n this.notify('close')\n })\n }\n\n /**\n * Send an OSC Packet, Bundle or Message. Use options here for\n * custom port and hostname, otherwise the global options will\n * be taken\n * @param {Uint8Array} binary Binary representation of OSC Packet\n * @param {object} [customOptions] Custom options for udp socket\n * @param {string} [customOptions.host] Hostname of udp client\n * @param {number} [customOptions.port] Port of udp client\n */\n send(binary, customOptions = {}) {\n const options = { ...this.options.send, ...customOptions }\n const { port, host } = options\n\n this.socket.send(Buffer.from(binary), 0, binary.byteLength, port, host)\n }\n}\n","const dgram = typeof __dirname !== 'undefined' ? require('dgram') : undefined\nconst WebSocketServer = typeof __dirname !== 'undefined' ? require('isomorphic-ws').Server : undefined\n\n/**\n * Status flags\n * @private\n */\nconst STATUS = {\n IS_NOT_INITIALIZED: -1,\n IS_CONNECTING: 0,\n IS_OPEN: 1,\n IS_CLOSING: 2,\n IS_CLOSED: 3,\n}\n\n/**\n * Default options\n * @private\n */\nconst defaultOptions = {\n udpServer: {\n host: 'localhost',\n port: 41234,\n exclusive: false,\n },\n udpClient: {\n host: 'localhost',\n port: 41235,\n },\n wsServer: {\n host: 'localhost',\n port: 8080,\n },\n receiver: 'ws',\n}\n\n/**\n * Helper method to merge nested objects\n * @private\n */\nfunction mergeOptions(base, custom) {\n return {\n ...defaultOptions,\n ...base,\n ...custom,\n udpServer: { ...defaultOptions.udpServer, ...base.udpServer, ...custom.udpServer },\n udpClient: { ...defaultOptions.udpClient, ...base.udpClient, ...custom.udpClient },\n wsServer: { ...defaultOptions.wsServer, ...base.wsServer, ...custom.wsServer },\n }\n}\n\n/**\n * OSC plugin for setting up communication between a Websocket\n * client and a udp client with a bridge inbetween\n */\nexport default class BridgePlugin {\n /**\n * Create an OSC Bridge instance with given options. Defaults to\n * localhost:41234 for udp server, localhost:41235 for udp client and\n * localhost:8080 for Websocket server\n * @param {object} [options] Custom options\n * @param {string} [options.udpServer.host='localhost'] Hostname of udp server to bind to\n * @param {number} [options.udpServer.port=41234] Port of udp server to bind to\n * @param {boolean} [options.udpServer.exclusive=false] Exclusive flag\n * @param {string} [options.udpClient.host='localhost'] Hostname of udp client for messaging\n * @param {number} [options.udpClient.port=41235] Port of udp client for messaging\n * @param {string} [options.wsServer.host='localhost'] Hostname of Websocket server\n * @param {number} [options.wsServer.port=8080] Port of Websocket server\n * @param {http.Server|https.Server} [options.wsServer.server] Use existing Node.js HTTP/S server\n * @param {string} [options.receiver='ws'] Where messages sent via 'send' method will be\n * delivered to, 'ws' for Websocket clients, 'udp' for udp client\n *\n * @example\n * const plugin = new OSC.BridgePlugin({ wsServer: { port: 9912 } })\n * const osc = new OSC({ plugin: plugin })\n *\n * @example Using an existing HTTP server\n * const http = require('http')\n * const httpServer = http.createServer();\n * const plugin = new OSC.BridgePlugin({ wsServer: { server: httpServer } })\n * const osc = new OSC({ plugin: plugin })\n */\n constructor(customOptions = {}) {\n if (!dgram || !WebSocketServer) {\n throw new Error('BridgePlugin can not be used in browser context')\n }\n\n /** @type {object} options\n * @private\n */\n this.options = mergeOptions({}, customOptions)\n\n /**\n * @type {object} websocket\n * @private\n */\n this.websocket = null\n\n /**\n * @type {object} socket\n * @private\n */\n this.socket = dgram.createSocket('udp4')\n /**\n * @type {number} socketStatus\n * @private\n */\n this.socketStatus = STATUS.IS_NOT_INITIALIZED\n\n // register udp events\n this.socket.on('message', (message) => {\n this.send(message, { receiver: 'ws' })\n this.notify(message.buffer)\n })\n\n this.socket.on('error', (error) => {\n this.notify('error', error)\n })\n\n /**\n * @type {function} notify\n * @private\n */\n this.notify = () => {}\n }\n\n /**\n * Internal method to hook into osc library's\n * EventHandler notify method\n * @param {function} fn Notify callback\n * @private\n */\n registerNotify(fn) {\n this.notify = fn\n }\n\n /**\n * Returns the current status of the connection\n * @return {number} Status ID\n */\n status() {\n return this.socketStatus\n }\n\n /**\n * Bind a udp socket to a hostname and port\n * @param {object} [customOptions] Custom options\n * @param {string} [customOptions.host='localhost'] Hostname of udp server to bind to\n * @param {number} [customOptions.port=41234] Port of udp server to bind to\n * @param {boolean} [customOptions.exclusive=false] Exclusive flag\n */\n open(customOptions = {}) {\n const options = mergeOptions(this.options, customOptions)\n\n this.socketStatus = STATUS.IS_CONNECTING\n\n // bind udp server\n this.socket.bind({\n address: options.udpServer.host,\n port: options.udpServer.port,\n exclusive: options.udpServer.exclusive,\n }, () => {\n let wsServerOptions = {}\n if (options.wsServer.server) wsServerOptions.server = options.wsServer.server\n else wsServerOptions = options.wsServer\n // bind Websocket server\n this.websocket = new WebSocketServer(wsServerOptions)\n this.websocket.binaryType = 'arraybuffer'\n\n // register Websocket events\n this.websocket.on('listening', () => {\n this.socketStatus = STATUS.IS_OPEN\n this.notify('open')\n })\n\n this.websocket.on('error', (error) => {\n this.notify('error', error)\n })\n\n this.websocket.on('connection', (client) => {\n client.on('message', (message, rinfo) => {\n this.send(message, { receiver: 'udp' })\n this.notify(new Uint8Array(message), rinfo)\n })\n })\n })\n }\n\n /**\n * Close udp socket and Websocket server\n */\n close() {\n this.socketStatus = STATUS.IS_CLOSING\n\n // close udp socket\n this.socket.close(() => {\n // close Websocket\n this.websocket.close(() => {\n this.socketStatus = STATUS.IS_CLOSED\n this.notify('close')\n })\n })\n }\n\n /**\n * Send an OSC Packet, Bundle or Message. Use options here for\n * custom receiver, otherwise the global options will be taken\n * @param {Uint8Array} binary Binary representation of OSC Packet\n * @param {object} [customOptions] Custom options\n * @param {string} [customOptions.udpClient.host='localhost'] Hostname of udp client for messaging\n * @param {number} [customOptions.udpClient.port=41235] Port of udp client for messaging\n * @param {string} [customOptions.receiver='ws'] Messages will be delivered to Websocket ('ws')\n * clients or udp client ('udp')\n */\n send(binary, customOptions = {}) {\n const options = mergeOptions(this.options, customOptions)\n const { receiver } = options\n\n if (receiver === 'udp') {\n // send data to udp client\n const data = binary instanceof Buffer ? binary : Buffer.from(binary)\n this.socket.send(\n data,\n 0,\n data.byteLength,\n options.udpClient.port,\n options.udpClient.host,\n )\n } else if (receiver === 'ws') {\n // send data to all Websocket clients\n this.websocket.clients.forEach((client) => {\n client.send(binary, { binary: true })\n })\n } else {\n throw new Error('BridgePlugin can not send message to unknown receiver')\n }\n }\n}\n","// eslint-disable-next-line no-undef\nconst scope = typeof global === 'undefined' ? window : global\nconst WebSocket = typeof __dirname === 'undefined' ? scope.WebSocket : require('isomorphic-ws')\n\n/**\n * Status flags\n * @private\n */\nconst STATUS = {\n IS_NOT_INITIALIZED: -1,\n IS_CONNECTING: 0,\n IS_OPEN: 1,\n IS_CLOSING: 2,\n IS_CLOSED: 3,\n}\n\n/**\n * Default options\n * @private\n */\nconst defaultOptions = {\n host: 'localhost',\n port: 8080,\n secure: false,\n}\n\n/**\n * OSC plugin for a Websocket client running in node or browser context\n */\nexport default class WebsocketClientPlugin {\n /**\n * Create an OSC WebsocketClientPlugin instance with given options.\n * Defaults to *localhost:8080* for connecting to a Websocket server\n * @param {object} [options] Custom options\n * @param {string} [options.host='localhost'] Hostname of Websocket server\n * @param {number} [options.port=8080] Port of Websocket server\n * @param {boolean} [options.secure=false] Use wss:// for secure connections\n *\n * @example\n * const plugin = new OSC.WebsocketClientPlugin({ port: 9912 })\n * const osc = new OSC({ plugin: plugin })\n */\n constructor(customOptions) {\n if (!WebSocket) {\n throw new Error('WebsocketClientPlugin can\\'t find a WebSocket class')\n }\n\n /**\n * @type {object} options\n * @private\n */\n this.options = { ...defaultOptions, ...customOptions }\n\n /**\n * @type {object} socket\n * @private\n */\n this.socket = null\n /**\n * @type {number} socketStatus\n * @private\n */\n this.socketStatus = STATUS.IS_NOT_INITIALIZED\n\n /**\n * @type {function} notify\n * @private\n */\n this.notify = () => {}\n }\n\n /**\n * Internal method to hook into osc library's\n * EventHandler notify method\n * @param {function} fn Notify callback\n * @private\n */\n registerNotify(fn) {\n this.notify = fn\n }\n\n /**\n * Returns the current status of the connection\n * @return {number} Status identifier\n */\n status() {\n return this.socketStatus\n }\n\n /**\n * Connect to a Websocket server. Defaults to global options\n * @param {object} [customOptions] Custom options\n * @param {string} [customOptions.host] Hostname of Websocket server\n * @param {number} [customOptions.port] Port of Websocket server\n * @param {boolean} [customOptions.secure] Use wss:// for secure connections\n */\n open(customOptions = {}) {\n const options = { ...this.options, ...customOptions }\n const { port, host, secure } = options\n\n // close socket when already given\n if (this.socket) {\n this.close()\n }\n\n // create websocket client\n const protocol = secure ? 'wss' : 'ws'\n const rinfo = {\n address: host,\n family: protocol,\n port,\n size: 0,\n }\n\n this.socket = new WebSocket(`${protocol}://${host}:${port}`)\n this.socket.binaryType = 'arraybuffer'\n this.socketStatus = STATUS.IS_CONNECTING\n\n // register events\n this.socket.onopen = () => {\n this.socketStatus = STATUS.IS_OPEN\n this.notify('open')\n }\n\n this.socket.onclose = () => {\n this.socketStatus = STATUS.IS_CLOSED\n this.notify('close')\n }\n\n this.socket.onerror = (error) => {\n this.notify('error', error)\n }\n\n this.socket.onmessage = (message) => {\n this.notify(message.data, rinfo)\n }\n }\n\n /**\n * Close Websocket\n */\n close() {\n this.socketStatus = STATUS.IS_CLOSING\n this.socket.close()\n }\n\n /**\n * Send an OSC Packet, Bundle or Message to Websocket server\n * @param {Uint8Array} binary Binary representation of OSC Packet\n */\n send(binary) {\n this.socket.send(binary)\n }\n}\n","const WebSocketServer = typeof __dirname !== 'undefined' ? require('isomorphic-ws').Server : undefined\n\n/**\n * Status flags\n * @private\n */\nconst STATUS = {\n IS_NOT_INITIALIZED: -1,\n IS_CONNECTING: 0,\n IS_OPEN: 1,\n IS_CLOSING: 2,\n IS_CLOSED: 3,\n}\n\n/**\n * Default options\n * @private\n */\nconst defaultOptions = {\n host: 'localhost',\n port: 8080,\n}\n\n/**\n * OSC plugin for a Websocket client running in node or browser context\n */\nexport default class WebsocketServerPlugin {\n /**\n * Create an OSC WebsocketServerPlugin instance with given options.\n * Defaults to *localhost:8080* for the Websocket server\n * @param {object} [options] Custom options\n * @param {string} [options.host='localhost'] Hostname of Websocket server\n * @param {number} [options.port=8080] Port of Websocket server\n * @param {http.Server|https.Server} [options.server] Use existing Node.js HTTP/S server\n *\n * @example\n * const plugin = new OSC.WebsocketServerPlugin({ port: 9912 })\n * const osc = new OSC({ plugin: plugin })\n *\n * osc.open() // start server\n * @example Using an existing HTTP server\n * const http = require('http')\n * const httpServer = http.createServer();\n * const plugin = new OSC.WebsocketServerPlugin({ server: httpServer })\n * const osc = new OSC({ plugin: plugin })\n */\n constructor(customOptions) {\n if (!WebSocketServer) {\n throw new Error('WebsocketServerPlugin can not be used in browser context')\n }\n\n /**\n * @type {object} options\n * @private\n */\n this.options = { ...defaultOptions, ...customOptions }\n\n /**\n * @type {object} socket\n * @private\n */\n this.socket = null\n /**\n * @type {number} socketStatus\n * @private\n */\n this.socketStatus = STATUS.IS_NOT_INITIALIZED\n\n /**\n * @type {function} notify\n * @private\n */\n this.notify = () => {}\n }\n\n /**\n * Internal method to hook into osc library's\n * EventHandler notify method\n * @param {function} fn Notify callback\n * @private\n */\n registerNotify(fn) {\n this.notify = fn\n }\n\n /**\n * Returns the current status of the connection\n * @return {number} Status identifier\n */\n status() {\n return this.socketStatus\n }\n\n /**\n * Start a Websocket server. Defaults to global options\n * @param {object} [customOptions] Custom options\n * @param {string} [customOptions.host] Hostname of Websocket server\n * @param {number} [customOptions.port] Port of Websocket server\n */\n open(customOptions = {}) {\n const options = { ...this.options, ...customOptions }\n const { port, host } = options\n const rinfo = {\n address: host,\n family: 'wsserver',\n port,\n size: 0,\n }\n\n // close socket when already given\n if (this.socket) {\n this.close()\n }\n\n // create websocket server\n if (options.server) {\n this.socket = new WebSocketServer({ server: options.server })\n } else {\n this.socket = new WebSocketServer({ host, port })\n }\n\n this.socket.binaryType = 'arraybuffer'\n this.socketStatus = STATUS.IS_CONNECTING\n\n // register events\n this.socket.on('listening', () => {\n this.socketStatus = STATUS.IS_OPEN\n this.notify('open')\n })\n\n this.socket.on('error', (error) => {\n this.notify('error', error)\n })\n\n this.socket.on('connection', (client) => {\n client.on('message', (message) => {\n this.notify(new Uint8Array(message), rinfo)\n })\n })\n }\n\n /**\n * Close Websocket server\n */\n close() {\n this.socketStatus = STATUS.IS_CLOSING\n\n this.socket.close(() => {\n this.socketStatus = STATUS.IS_CLOSED\n this.notify('close')\n })\n }\n\n /**\n * Send an OSC Packet, Bundle or Message to Websocket clients\n * @param {Uint8Array} binary Binary representation of OSC Packet\n */\n send(binary) {\n this.socket.clients.forEach((client) => {\n client.send(binary, { binary: true })\n })\n }\n}\n","import {\n isFunction,\n isInt,\n isObject,\n isString,\n} from './common/utils'\n\nimport Bundle from './bundle'\nimport EventHandler from './events'\nimport Message, { TypedMessage } from './message'\nimport Packet from './packet'\n\nimport DatagramPlugin from './plugin/dgram'\nimport BridgePlugin from './plugin/bridge'\nimport WebsocketClientPlugin from './plugin/wsclient'\nimport WebsocketServerPlugin from './plugin/wsserver'\n\n/**\n * Default options\n * @private\n */\nconst defaultOptions = {\n discardLateMessages: false,\n plugin: new WebsocketClientPlugin(),\n}\n\n/**\n * Status flags\n */\nconst STATUS = {\n IS_NOT_INITIALIZED: -1,\n IS_CONNECTING: 0,\n IS_OPEN: 1,\n IS_CLOSING: 2,\n IS_CLOSED: 3,\n}\n\n/**\n * OSC interface to send OSC Packets and listen to status changes and\n * incoming message events. Offers a Plugin API for different network\n * protocols, defaults to a simple Websocket client for OSC communication\n * between a browser js-app and a js-node server\n *\n * @example\n * const osc = new OSC()\n *\n * osc.on('/input/test', message => {\n * // print incoming OSC message arguments\n * console.log(message.args)\n * })\n *\n * osc.on('open', () => {\n * const message = new Message('/test/path', 55.12, 'hello')\n * osc.send(message)\n * })\n *\n * osc.open({ host: '192.168.178.115', port: 9012 })\n */\nclass OSC {\n /**\n * Create an OSC instance with given options\n * @param {object} [options] Custom options\n * @param {boolean} [options.discardLateMessages=false] Ignore incoming\n * messages when given timetag lies in the past\n * @param {Plugin} [options.plugin=WebsocketClientPlugin] Add a connection plugin\n * to this interface, defaults to a plugin with Websocket client.\n * Open README.md for further information on how to handle plugins or\n * how to write your own with the Plugin API\n *\n * @example\n * const osc = new OSC() // default options with Websocket client\n *\n * @example\n * const osc = new OSC({ discardLateMessages: true })\n *\n * @example\n * const websocketPlugin = new OSC.WebsocketClientPlugin()\n * const osc = new OSC({ plugin: websocketPlugin })\n */\n constructor(options) {\n if (options && !isObject(options)) {\n throw new Error('OSC options argument has to be an object.')\n }\n\n /**\n * @type {object} options\n * @private\n */\n this.options = { ...defaultOptions, ...options }\n /**\n * @type {EventHandler} eventHandler\n * @private\n */\n this.eventHandler = new EventHandler({\n discardLateMessages: this.options.discardLateMessages,\n })\n\n // pass EventHandler's notify() to plugin\n const { eventHandler } = this\n if (this.options.plugin && this.options.plugin.registerNotify) {\n this.options.plugin.registerNotify((...args) => eventHandler.notify(...args))\n }\n }\n\n /**\n * Listen to a status-change event or incoming OSC message with\n * address pattern matching\n * @param {string} eventName Event name or OSC address pattern\n * @param {function} callback Function which is called on notification\n * @return {number} Subscription id (needed to unsubscribe)\n *\n * @example\n * // will be called when server receives /in!trument/* for example\n * osc.on('/instrument/1', message => {\n * console.log(message)\n * })\n *\n * @example\n * // will be called for every message since it uses the wildcard symbol\n * osc.on('*', message => {\n * console.log(message)\n * })\n *\n * @example\n * // will be called on network socket error\n * osc.on('error', message => {\n * console.log(message)\n * })\n */\n on(eventName, callback) {\n if (!(isString(eventName) && isFunction(callback))) {\n throw new Error('OSC on() needs event- or address string and callback function')\n }\n\n return this.eventHandler.on(eventName, callback)\n }\n\n /**\n * Unsubscribe an event listener\n * @param {string} eventName Event name or OSC address pattern\n * @param {number} subscriptionId The subscription id\n * @return {boolean} Success state\n *\n * @example\n * const listenerId = osc.on('error', message => {\n * console.log(message)\n * })\n * osc.off('error', listenerId) // unsubscribe from error event\n */\n off(eventName, subscriptionId) {\n if (!(isString(eventName) && isInt(subscriptionId))) {\n throw new Error('OSC off() needs string and number (subscriptionId) to unsubscribe')\n }\n\n return this.eventHandler.off(eventName, subscriptionId)\n }\n\n /**\n * Open network socket with plugin. This method is used by\n * plugins and is not available without (see Plugin API for more information)\n * @param {object} [options] Custom global options for plugin instance\n *\n * @example\n * const osc = new OSC({ plugin: new OSC.DatagramPlugin() })\n * osc.open({ host: '127.0.0.1', port: 8080 })\n */\n open(options) {\n if (options && !isObject(options)) {\n throw new Error('OSC open() options argument needs to be an object')\n }\n\n if (!(this.options.plugin && isFunction(this.options.plugin.open))) {\n throw new Error('OSC Plugin API #open is not implemented!')\n }\n\n return this.options.plugin.open(options)\n }\n\n /**\n * Returns the current status of the connection. See *STATUS* for\n * different possible states. This method is used by plugins\n * and is not available without (see Plugin API for more information)\n * @return {number} Status identifier\n *\n * @example\n * import OSC, { STATUS } from 'osc'\n * const osc = new OSC()\n * if (osc.status() === STATUS.IS_CONNECTING) {\n * // do something\n * }\n */\n status() {\n if (!(this.options.plugin && isFunction(this.options.plugin.status))) {\n throw new Error('OSC Plugin API #status is not implemented!')\n }\n\n return this.options.plugin.status()\n }\n\n /**\n * Close connection. This method is used by plugins and is not\n * available without (see Plugin API for more information)\n */\n close() {\n if (!(this.options.plugin && isFunction(this.options.plugin.close))) {\n throw new Error('OSC Plugin API #close is not implemented!')\n }\n\n return this.options.plugin.close()\n }\n\n /**\n * Send an OSC Packet, Bundle or Message. This method is used by plugins\n * and is not available without (see Plugin API for more information)\n * @param {Packet|Bundle|Message} packet OSC Packet, Bundle or Message instance\n * @param {object} [options] Custom options\n *\n * @example\n * const osc = new OSC({ plugin: new OSC.DatagramPlugin() })\n * osc.open({ host: '127.0.0.1', port: 8080 })\n *\n * const message = new OSC.Message('/test/path', 55.1, 57)\n * osc.send(message)\n *\n * // send message again to custom address\n * osc.send(message, { host: '192.168.178.115', port: 9001 })\n */\n send(packet, options) {\n if (!(this.options.plugin && isFunction(this.options.plugin.send))) {\n throw new Error('OSC Plugin API #send is not implemented!')\n }\n\n if (!(packet instanceof TypedMessage\n || packet instanceof Message\n || packet instanceof Bundle\n || packet instanceof Packet)\n ) {\n throw new Error('OSC send() needs Messages, Bundles or Packets')\n }\n\n if (options && !isObject(options)) {\n throw new Error('OSC send() options argument has to be an object')\n }\n\n return this.options.plugin.send(packet.pack(), options)\n }\n}\n\n// expose status flags\nOSC.STATUS = STATUS\n\n// expose OSC classes\nOSC.Packet = Packet\nOSC.Bundle = Bundle\nOSC.Message = Message\nOSC.TypedMessage = TypedMessage\n\n// expose plugins\nOSC.DatagramPlugin = DatagramPlugin\nOSC.WebsocketClientPlugin = WebsocketClientPlugin\nOSC.WebsocketServerPlugin = WebsocketServerPlugin\nOSC.BridgePlugin = BridgePlugin\n\nexport default OSC\n"],"names":["isInt","n","Number","isNumber","isString","isArray","Object","prototype","toString","call","isObject","isFunction","isBlob","Uint8Array","isDate","Date","isUndefined","pad","hasProperty","name","hasOwnProperty","global","window","dataView","obj","buffer","DataView","ArrayBuffer","typeTag","item","Error","prepareAddress","address","join","length","slice","prepareRegExPattern","str","replace","EncodeHelper","data","byteLength","pack","push","this","result","offset","forEach","set","Atomic","value","method","initialOffset","AtomicInt32","STR_ENCODING","charCodesToString","charCodes","Buffer","from","TextDecoder","decode","Int8Array","i","String","fromCharCode","apply","AtomicString","terminated","charCodeAt","charcode","getUint8","SECONDS_70_YEARS","TWO_POWER_32","Timetag","seconds","fractions","milliseconds","rounded","Math","floor","round","AtomicTimetag","now","timetag","timestamp","getTime","setInt32","getUint32","AtomicBlob","getInt32","AtomicFloat32","AtomicFloat64","MAX_INT64","BigInt","MIN_INT64","AtomicInt64","tmp","asIntN","MAX_UINT64","AtomicUInt64","asUintN","TypedMessage","args","types","_this","add","type","encoder","Helper","argument","index","_this2","merge","unpack","next","Message","oscArgs","shift","Array","map","BUNDLE_TAG","Bundle","bundleElements","ms","parentHead","head","size","Packet","defaultOptions","discardLateMessages","EventHandler","options","addressHandlers","eventHandlers","open","error","close","uuid","packet","rinfo","bundle","bundleItem","dispatch","message","notify","success","handler","callback","handlerKeys","keys","handlers","key","foundMatch","regex","RegExp","test","lastIndex","reverseRegex","that","setTimeout","id","subscriptionId","haystack","some","splice","dgram","__dirname","require","undefined","STATUS","host","port","exclusive","send","mergeOptions","base","custom","DatagramPlugin","customOptions","socket","createSocket","socketStatus","on","fn","bind","_this3","binary","WebSocketServer","Server","udpServer","udpClient","wsServer","receiver","BridgePlugin","websocket","wsServerOptions","server","binaryType","client","clients","scope","WebSocket","secure","WebsocketClientPlugin","protocol","family","onopen","onclose","onerror","onmessage","WebsocketServerPlugin","plugin","OSC","eventHandler","registerNotify","eventName","off","status","IS_NOT_INITIALIZED","IS_CONNECTING","IS_OPEN","IS_CLOSING","IS_CLOSED"],"mappings":"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"} -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hydra-osc", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "isomorphic-ws": { 8 | "version": "4.0.1", 9 | "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", 10 | "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==" 11 | }, 12 | "osc-js": { 13 | "version": "2.2.0", 14 | "resolved": "https://registry.npmjs.org/osc-js/-/osc-js-2.2.0.tgz", 15 | "integrity": "sha512-FrgvR8oTDv/nK489lDQXtg72z3pzP3RbtP6E/J+LRvvogGP8YgW4/F4t7RdrNR1T1cCQxkS9newmXlp3g14F6w==", 16 | "requires": { 17 | "isomorphic-ws": "4.0.1", 18 | "ws": "8.3.0" 19 | } 20 | }, 21 | "ws": { 22 | "version": "8.3.0", 23 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz", 24 | "integrity": "sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hydra-osc", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "osc-js": "^2.2.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const OSC = require('osc-js') 2 | 3 | const config = { 4 | receiver: 'ws', // @param {string} Where messages sent via 'send' method will be delivered to, 'ws' for Websocket clients, 'udp' for udp client 5 | udpServer: { 6 | host: 'localhost', // @param {string} Hostname of udp server to bind to 7 | port: 41234, // @param {number} Port of udp server to bind to 8 | exclusive: false // @param {boolean} Exclusive flag 9 | }, 10 | udpClient: { 11 | host: 'localhost', // @param {string} Hostname of udp client for messaging 12 | port: 41235 // @param {number} Port of udp client for messaging 13 | }, 14 | wsServer: { 15 | host: 'localhost', // @param {string} Hostname of WebSocket server 16 | port: 8080 // @param {number} Port of WebSocket server 17 | } 18 | } 19 | const osc = new OSC({ plugin: new OSC.BridgePlugin(config) }) 20 | 21 | osc.open() // start a WebSocket server on port 8080 22 | 23 | console.log('osc client running on port', config.udpClient.port) 24 | console.log('osc server running on port', config.udpServer.port) 25 | console.log('websocket server running on port', config.wsServer.port) --------------------------------------------------------------------------------