Code Monkey home page Code Monkey logo

node-osc's Introduction

node-osc

A no frills Open Sound Control client and server. Heavily inspired by pyOSC.

Install using npm

npm install node-osc

Written using ESM supports CJS

Supports the latest versions of Node.js 12, 14, and 16 in both ESM + CJS

Example

Sending OSC messages:

import { Client } from 'node-osc';

const client = new Client('127.0.0.1', 3333);
client.send('/oscAddress', 200, () => {
  client.close();
});

Listening for OSC messages:

import { Server } from 'node-osc';

var oscServer = new Server(3333, '0.0.0.0', () => {
  console.log('OSC Server is listening');
});

oscServer.on('message', function (msg) {
  console.log(`Message: ${msg}`);
  oscServer.close();
});

Sending OSC bundles:

import { Bundle, Client } from 'node-osc';

// a bundle without an explicit time tag
const bundle = new Bundle(['/one', 1], ['/two', 2], ['/three', 3]);

// a bundle with a timetag of 10
bundle.append(new Bundle(10, ['/four', 4]));

const client = new Client('127.0.0.1', 3333);
client.send(bundle));

Listening for OSC bundles:

WARNING: Bundle support is Experimental and subject to change at any point.

import { Server } from 'node-osc';

var oscServer = new Server(3333, '0.0.0.0', () => {
  console.log('OSC Server is listening');
});

oscServer.on('bundle', function (bundle) {
  bundle.elements.forEach((element, i) => {
    console.log(`Timestamp: ${bundle.timetag[i]}`);
    console.log(`Message: ${element}`);
  });
  oscServer.close();
});

CJS API

This just works due to conditional exports, isn't that cool!

const { Client, Server } = require('node-osc');

const client = new Client('127.0.0.1', 3333);
var server = new Server(3333, '0.0.0.0');

server.on('listening', () => {
  console.log('OSC Server is listening.');
})

server.on('message', (msg) => {
  console.log(`Message: ${msg}`);
  server.close();
});

client.send('/hello', 'world', (err) => {
  if (err) console.error(err);
  client.close();
});

Typescript

To install type definitions for node-osc:

npm install --save @types/node-osc or yarn add @types/node-osc

The types should then be automatically included by the compiler.

License

LGPL. Please see the file lesser.txt for details.

node-osc's People

Contributors

aatishb avatar bnb avatar dependabot[bot] avatar feelepxyz avatar hanshuebner avatar haroenv avatar jean-emmanuel avatar koopero avatar mylesborins avatar njh avatar pce avatar respectthecode avatar termie avatar yn4v4s avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-osc's Issues

Receiving arrays doesn't work?

Hi there, I'm trying to get an array of data from Synapse about kinect joint positions, it seems to work in Processing, but when I try to receive data in Node, I get a single weird float value instead of an array. Here's the message output:

TUIO message:
[ '#bundle', 2.3283064365386963e-10, [ '/lefthand', 'forward' ] ]
{ address: '127.0.0.1', family: 'IPv4', port: 53499, size: 44 }

Is there any special syntax for receiving a bundle of 3 floats?

mention what OSC stands for

I stumbled across this, but didn't know that OSC is open sound control, so I wasn't sure what it meant or what to google to find it. Eventually I did find it, but it would be useful to put this in the description :)

Can't get import node-osc

Hi,

I have been trying to follow the rabbithole to use node-osc. It is under my node_modules after installing:
Michaels-Mac-Pro:ws-crowdsounds MGW$ npm install node-osc
npm WARN [email protected] No repository field.

  • [email protected]
    added 4 packages from 5 contributors and audited 5 packages in 1.538s
    found 0 vulnerabilities

But then using it as in the Readme:
import { Client } from 'node-osc';
^^^^^^

SyntaxError: Cannot use import statement outside a module

SO I added type module to package.json, then yielding:
node server.js
internal/modules/cjs/loader.js:1173
throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
^

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/MGW/.../ws-crowdsounds/server.js

Found a suggestion that @std/esm cjs might be needed ... but same error...

package.json
{
"name": "ws-crowdsounds",
"version": "1.0.0",
"description": "receive msgs for playing sounds remotely",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC",
"@std/esm": "cjs",
"type":"module",
"dependencies": {
"node-osc": "^5.1.0",
"ws": "^7.3.1"
}
}

Any guidance is appreciated!
~

Strange osc + node crash on refresh of client window..

I was half done writing woohoo the OSC refresh crashes of the past are gone thanks to update of v4.1.6 + node + npm, after tons of refreshes of browser/recompiles failed to crash it... but just for good measure went back to try and refresh one more time = fatal crash!? haha whole computer completely froze up when looking at crashed CLI log. Worse than before where P5LIVE would die (with nearly same message as below) and I'd just have to restart it.

Not sure if the following crash log in CLI means much, but maybe you have an idea where in node-osc or node itself this could be coming from?? Or you can see something I've setup totally wrong below in my server.js + clientside usage of it?

error in CLI:

dgram.js:902
    throw new ERR_SOCKET_DGRAM_NOT_RUNNING();
    ^

Error [ERR_SOCKET_DGRAM_NOT_RUNNING]: Not running
    at healthCheck (dgram.js:902:11)
    at Socket.send (dgram.js:627:3)
    at Client.send (/Users/_purged_/Documents/_purged_/_purged_/p5live/node_modules/node-osc/lib/Client.js:55:20)
    at Socket.<anonymous> (/Users/_purged_/Documents/_purged_/_purged_/p5live/server.js:114:19)
    at Socket.emit (events.js:321:20)
    at /Users/_purged_/Documents/_purged_/_purged_/p5live/node_modules/socket.io/lib/socket.js:528:12
    at processTicksAndRejections (internal/process/task_queues.js:79:11) {
  code: 'ERR_SOCKET_DGRAM_NOT_RUNNING'
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: `node server.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/_purged_/.npm/_logs/2020-03-01T22_00_37_852Z-debug.log

OSC connection script used in P5LIVE (p5.js) clientside:

// global vars
let libs = ["includes/js/socket.io.js"];
let socket, debugIn, debugOut;

// in my setup(): setupOsc('127.0.0.1', 12000, 12001);

function setupOsc(oscHost, oscPortIn, oscPortOut) {
	socket = io.connect('http://127.0.0.1:8082');
	socket.on('connect', function() {
		socket.emit('config', {
			server: { host: oscHost, port: oscPortIn },
			client: { host: oscHost, port: oscPortOut }
		});
	});
	socket.on('message', function(msg) {
		receiveOsc(msg[0], msg.splice(1));
	});
}

From my node server.js:

// OSC
let iop, osc, oscServer, oscClient, isConnected;
if(!online){
	iop = require('socket.io', {transports: ['WebSocket'] }).listen(8082);
	osc = require('node-osc');
}

// OSC
if(!online){
	iop.sockets.on('connection', function (socket) {
		socket.on("config", function (obj) {
			// *** find source of random OSC crash...
			isConnected = true;
	    		oscServer = new osc.Server(obj.server.port, obj.server.host);
			oscClient = new osc.Client(obj.client.host, obj.client.port);
			oscClient.send('/status', socket.sessionId + ' connected');
			oscServer.on('message', function(msg, rinfo) {
				socket.emit("message", msg);
			});
			socket.emit("connected", 1);
		});
	 	socket.on("message", function (obj) {
			oscClient.send.apply(oscClient, obj);
	  	});
		socket.on('disconnect', function(){
			if (isConnected) {
				oscServer.close();
				oscClient.close();
			}
	  	});
	});
}

Buffer deprecation

error: (node:2346) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
(Use node --trace-deprecation ... to show where the warning was created)

I am getting this error when using "node-osc". It seems like the dependency "osc-min" is using a deprecated way of creating buffers. Is there any workaround?

Cannot get to run on Node 20

I'm trying to get this to run on Node 20.14.0 (Typescript) and for the life of me I cannot figure out what's going on. As soon as import { Server, Client } from 'node-osc'; exists in the code, the NodeJS process immediately closes upon launch, no errors or uncaught exceptions - nothing. As soon as I remove the import, everything is working again.

This is my code, but i'm not even calling setupOscClient() or setupOscServer() and it still crashes randomly. I can't get a debugger attached to it either because of this behaviour. Any help would be appreciated.

import { Server, Client } from 'node-osc';

let oscClient: Client | null = null;
let oscServer: Server | null = null;

function setupOscClient() {
    if (globalSettings.enableComs !== '1') {
        return;
    }

    const ipAddress = globalSettings.ipAddress || '127.0.0.1';
    const port = 10024;

    if (oscClient) {
        oscClient.close();
        globalSettings.oscConnected = false;
        saveGlobalSettings();
    }

	try {
		oscClient = new Client(ipAddress, port);
		globalSettings.oscConnected = true;
		saveGlobalSettings();

		ConsoleLog(`Connected to ${ipAddress}:${port}`, LogLevel.INFO, true);
	} catch (err) {
		console.log(err)
	}
    
}

function setupOscServer() {
	const ipAddress = globalSettings.ipAddress || '127.0.0.1';
    const port = 10024;
    
    if (oscServer) {
        oscServer.close();
    }

    oscServer = new Server(port, ipAddress);
    oscServer.on('message', function (msg) {
        ConsoleLog(`Received OSC message: ${msg}`, LogLevel.INFO, true);
        handleIncomingData(msg.toString());
    });

    ConsoleLog(`OSC server listening on port ${port}`, LogLevel.INFO, true);
}


Can't send messsages

I'm getting the following error when trying the client.js script in the examples folder:
'Bad socket type specified. Valid types are: udp4, udp6'
Have I botched the install somehow?

Error: bind ENFILE 0.0.0.0

The below code fails after a dozen of messages.
It takes an incoming message and resends it to 255 ip addresses

var osc = require('node-osc');

var oscServer = new osc.Server(3333, '0.0.0.0');
oscServer.on("message", function (msg, rinfo) {
      console.log(msg);
        try {
        for (var i = 0; i < 255; i++) {
          var ip = '10.0.1.'+i;
          var client = new osc.Client(ip, 3000);
          client.send(msg);
        }
      } catch (e) {
        console.log(e);
      }
});

Console output:

events.js:160
      throw er; // Unhandled 'error' event
      ^

Error: bind ENFILE 0.0.0.0
    at Object.exports._errnoException (util.js:1026:11)
    at exports._exceptionWithHostPort (util.js:1049:20)
    at dgram.js:221:18
    at _combinedTickCallback (internal/process/next_tick.js:77:11)
    at process._tickCallback (internal/process/next_tick.js:98:9)
eightlocal:netscan-node eight$

Broadcast doesn't work

I know there's a pull request concerning this but any updates on alllowing broadcast ? Would be very useful !

Thanks !

Error handling

Could you add some error handling when sending messages please.

eg on line 77 of osc.js you're doing:

this._sock.send(buf, 0, buf.length, this.port, this.host);

But you're not passing a callback. So when the host is not available, Node.js throws an error which can not be catched by try{}catch(){}, crashing my whole program.

Thanks!

Cannot read properties of undefined (reading 'elements')

If the incoming message is malformed or from some senders has no args
then line 34 in Server.mjs seams to throw
if the if else statement is moved inside the try we can catch it instead of throwing
image

but the real issue seams to stem from decode.mjs
where the case of a successful decode but without oscType will cause a void return

install with npm fail

Hi,

I'm using a Mac OS 10.6.8. Afte updating python 2.7.5, npm 1.2.14 and node-gyp 0.10.10, I still can't install node-osc nor osc-min. Here is my log, thanks. Trang

[email protected] install /Users/trang/dev/ConcertSmartphone/node_modules/node-osc/node_modules/osc-min/node_modules/binpack
node-gyp rebuild

Traceback (most recent call last):
File "/usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp", line 18, in
sys.exit(gyp.main(sys.argv[1:]))
File "/usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/init.py", line 523, in main
return gyp_main(args)
File "/usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/init.py", line 508, in gyp_main
generator.GenerateOutput(flat_list, targets, data, params)
File "/usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py", line 2105, in GenerateOutput
part_of_all=qualified_target in needed_targets)
File "/usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py", line 769, in Write
self.Pchify))
File "/usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py", line 1154, in WriteSources
cflags = self.xcode_settings.GetCflags(configname)
File "/usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py", line 260, in GetCflags
sdk_root = self._SdkPath()
File "/usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py", line 247, in _SdkPath
return os.path.join(self._GetSdkBaseDir(),
File "/usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py", line 230, in _GetSdkBaseDir
stderr=subprocess.STDOUT)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 711, in init
errread, errwrite)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1308, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
gyp ERR! configure error
gyp ERR! stack Error: gyp failed with exit code: 1
gyp ERR! stack at ChildProcess.onCpExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:416:16)
gyp ERR! stack at ChildProcess.EventEmitter.emit (events.js:98:17)
gyp ERR! stack at Process.ChildProcess._handle.onexit (child_process.js:754:12)
gyp ERR! System Darwin 10.8.0
gyp ERR! command "node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/trang/dev/ConcertSmartphone/node_modules/node-osc/node_modules/osc-min/node_modules/binpack
gyp ERR! node -v v0.10.0
gyp ERR! node-gyp -v v0.8.5
gyp ERR! not ok
npm ERR! [email protected] install: node-gyp rebuild
npm ERR! sh "-c" "node-gyp rebuild" failed with 1
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is most likely a problem with the binpack package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! node-gyp rebuild
npm ERR! You can get their info via:
npm ERR! npm owner ls binpack
npm ERR! There is likely additional logging output above.

npm ERR! System Darwin 10.8.0
npm ERR! command "node" "/usr/local/bin/npm" "install" "node-osc"
npm ERR! cwd /Users/trang/dev/ConcertSmartphone
npm ERR! node -v v0.10.0
npm ERR! npm -v 1.2.14
npm ERR! code ELIFECYCLE
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /Users/trang/dev/ConcertSmartphone/npm-debug.log
npm ERR! not ok code 0

Support for 'c' Type Tag

🐛 Bug report

It seems that node-osc crashes on receiving datagrams of char type 'c'.

throw er; // Unhandled 'error' event
Error: can't decode incoming message: I don't understand the argument code c
    at Socket.<anonymous> (D:\light-dev\ontime\server\node_modules\node-osc\dist\lib\Server.js:28:23)
    at Socket.emit (events.js:315:20)
    at UDP.onMessage [as onmessage] (dgram.js:919:8)
Emitted 'error' event on Server instance at:
    at Socket.<anonymous> (D:\light-dev\ontime\server\node_modules\node-osc\dist\lib\Server.js:29:14)
    at Socket.emit (events.js:315:20)
    at UDP.onMessage [as onmessage] (dgram.js:919:8)

🧐 Expected behavior

Could we look at a library side catch to avoid application crash?

🌍 System information

Using node-osc 6.0.1 in Windows 10 and nodejs 14.15.3

extend arguments that can be passed to `message.append`

I'm sending a message to VCV rack oscelot.

This is how I create the node-osc client:

const client = new Client('127.0.0.1', 8881);

This is the message I've constructed with new Message and append()

Message {
  oscType: 'message',
  address: '/gliders/fader',
  args: [
    { type: 'i', value: 1 },
    { type: 'f', value: 0.34586167535948037 }
  ]
}

This is the resulting UDP message:

0000   00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00   ..............E.
0010   00 38 48 6c 40 00 40 11 f4 46 7f 00 00 01 7f 00   .8Hl@[email protected]......
0020   00 01 a1 dc 22 b1 00 24 fe 37 2f 67 6c 69 64 65   ...."..$.7/glide
0030   72 73 2f 66 61 64 65 72 00 00 2c 66 66 00 3f 80   rs/fader..,ff.?.
0040   00 00 3e b4 81 04                                 ..>...

As you can see the ff indicates both values are sent as floats despite the type: 'i' indicator on the first argument.

On the receivers end 0 is read as 0 but 1 is encoded as float but interpreted as int and ends up being some large number.

I hope, I'm not missing out something obvious.

ESM + npm+git dependencies

This ESM package cannot be installed via git or github shorthand in my package.json

This is useful for bugfixes, say I found a bug in your library, I would open a PR with a branch on my fork.

I would like to do npm install Raynos/node-osc#my-bug-fix but that branch does not contain the dist directory checked into git.

How would I install a temporary bugfix before the owner has published a new version and require it with commonJS ?

The dist directory only exists in the npm tarball at prePublish and it's not available when installing from github directory.

Test Coverage not working for ESM

The next branch has been converted to 100% ESM. The test suite, while working, is not giving any results for code coverage. This should be dug into, likely an issue with tap / NYC / istanbul

esbuild problem because of binpack (dependency of osc-min)

A packaged project through esbuild with the "strict" option throws Uncaught ReferenceError ReferenceError: twoToThe32 is not defined. This originates from binpack, a dependecy of osc-min.
I'm creating the issue here, since a) osc-min wasn't updated since 5 years and b) of the statement in another Issue (#2 (comment)_)

Dual package hazard and `instanceof`

It looks like this package as published to npm will not work with instanceof

As it's possible for my application to have two copies of Message from dist & src.

DEP0002 - Decoding TUIO

Hi,

I saw this message: "DeprecationWarning: Decoding TUIO is planned to be deprecated. Please open an issue if you rely on this feature." while working around with node-osc.

I might need this feature. As far as i can tell, my client (CasparCG Server) sends out "#bundle" Messages.

I guess than means it used TUIO. Right?

Maybe someone here can help me with my that.

I can provide sample Messages. Either coded or decoded.

cannot resolve 'dgram' error

Hi
I get a can't resolve 'dgram' error, which doesn't really let up as NPM is holding dgram.
Is there a work around this or way to install this into a nextjs project?

Here is the steps to recreate
node v 16.10

yarn create next-app --template typescript
yarn add node-osc

Cannot properly "install" this module: Cannot find module '/home/pi/node/node_modules/node-osc/dist/lib/index.js'

Hi,

I'm doing the installation of this package in a Dockerfile.
This should be the relevant lines of the Dockerfile that I had:
FROM debian
RUN wget https://deb.nodesource.com/setup_lts.x && chmod +x setup_lts.x && bash setup_lts.x && yes | apt install nodejs && npm install -g npm@latest
RUN mkdir -p /home/pi/node && cd /home/pi/node && yes | npm install [email protected] node-osc nodejs-base64

The script that is run inside the container is inside the /home/pi/node directory

However when running I get this error:
Cannot find module '/home/pi/node/node_modules/node-osc/dist/lib/index.js

So after a little dig in the source of this repo I substitute the last line that I provided of Dockerfile with the following:
RUN mkdir -p /home/pi/node && cd /home/pi/node && yes | npm install -g rollup && yes | npm install [email protected] node-osc nodejs-base64 && cd node_modules/node-osc && npm run-script build

And the error disappears. The issue is: it does not seem that npm install node-osc as indicated in README.md is sufficient for the module to be installed properly, or at least not ready to be used.
Now I'm not an expert in nodejs I mostly work with c++. Let me know what you think and if you need any clarifications.

Remove `osc-min` dependency

Summary

Currently node-osc relies on the package osc-min for it's exported functionality toBuffer and fromBuffer to encode and decode OSC messages. The library has not been updated in 5 years and is written in coffee script. Replacing it feels like a good idea.

Implement an implementation of the API definition below using the OSC spec also found below. The two functions should be implemented in an lib/internal/osc.mjs file, included in the package.json as a package import named #osc and have 100% test coverage. lib/internal/decode should be removed.

API Definitions

.fromBuffer(buffer, [strict])

takes a node.js Buffer of a complete OSC Packet and outputs the javascript representation, or throws if the buffer is ill-formed.

strict is an optional parameter that makes the function fail more often.

.toBuffer(object, [strict])

takes a OSC packet javascript representation as defined below and returns a node.js Buffer, or throws if the representation is ill-formed.

See "JavaScript representations of the OSC types" below.

Spec

From https://opensoundcontrol.stanford.edu/spec-1_0.html

Details

Introduction

Open Sound Control (OSC) is an open, transport-independent, message-based protocol developed for communication among computers, sound synthesizers, and other multimedia devices.

OSC Syntax

This section defines the syntax of OSC data.

Atomic Data Types

All OSC data is composed of the following fundamental data types:

int32
32-bit big-endian two’s complement integer
OSC-timetag
64-bit big-endian fixed-point time tag, semantics defined below
float32
32-bit big-endian IEEE 754 floating point number
OSC-string
A sequence of non-null ASCII characters followed by a null, followed by 0-3 additional null characters to make the total number of bits a multiple of 32. (OSC-string examples) In this document, example OSC-strings will be written without the null characters, surrounded by double quotes.
OSC-blob
An int32 size count, followed by that many 8-bit bytes of arbitrary binary data, followed by 0-3 additional zero bytes to make the total number of bits a multiple of 32.

The size of every atomic data type in OSC is a multiple of 32 bits. This guarantees that if the beginning of a block of OSC data is 32-bit aligned, every number in the OSC data will be 32-bit aligned.

OSC Packets

The unit of transmission of OSC is an OSC Packet. Any application that sends OSC Packets is an OSC Client; any application that receives OSC Packets is an OSC Server.

An OSC packet consists of its contents , a contiguous block of binary data, and its size , the number of 8-bit bytes that comprise the contents. The size of an OSC packet is always a multiple of 4.

The underlying network that delivers an OSC packet is responsible for delivering both the contents and the size to the OSC application. An OSC packet can be naturally represented by a datagram by a network protocol such as UDP. In a stream-based protocol such as TCP, the stream should begin with an int32 giving the size of the first packet, followed by the contents of the first packet, followed by the size of the second packet, etc.

The contents of an OSC packet must be either an OSC Message or an OSC Bundle. The first byte of the packet’s contents unambiguously distinguishes between these two alternatives.

OSC Messages

An OSC message consists of an OSC Address Pattern followed by an OSC Type Tag String followed by zero or more OSC Arguments.

Note: some older implementations of OSC may omit the OSC Type Tag string. Until all such implementations are updated, OSC implementations should be robust in the case of a missing OSC Type Tag String.

OSC Address Patterns

An OSC Address Pattern is an OSC-string beginning with the character ‘/’ (forward slash).

OSC Type Tag String

An OSC Type Tag String is an OSC-string beginning with the character ‘,’ (comma) followed by a sequence of characters corresponding exactly to the sequence of OSC Arguments in the given message. Each character after the comma is called an OSC Type Tag and represents the type of the corresponding OSC Argument. (The requirement for OSC Type Tag Strings to start with a comma makes it easier for the recipient of an OSC Message to determine whether that OSC Message is lacking an OSC Type Tag String.)

This table lists the correspondance between each OSC Type Tag and the type of its corresponding OSC Argument:

OSC Type Tag | Type of corresponding argument -- | -- i | int32 f | float32 s | OSC-string b | OSC-blob

The OSC Address of an OSC Method is a symbolic name giving the full path to the OSC Method in the OSC Address Space, starting from the root of the tree. An OSC Method’s OSC Address begins with the character ‘/’ (forward slash), followed by the names of all the containers, in order, along the path from the root of the tree to the OSC Method, separated by forward slash characters, followed by the name of the OSC Method. The syntax of OSC Addresses was chosen to match the syntax of URLs. (OSC Address Examples)

OSC Message Dispatching and Pattern Matching

When an OSC server receives an OSC Message, it must invoke the appropriate OSC Methods in its OSC Address Space based on the OSC Message’s OSC Address Pattern. This process is called dispatching the OSC Message to the OSC Methods that match its OSC Address Pattern. All the matching OSC Methods are invoked with the same argument data, namely, the OSC Arguments in the OSC Message.

The parts of an OSC Address or an OSC Address Pattern are the substrings between adjacent pairs of forward slash characters and the substring after the last forward slash character. (examples)

A received OSC Message must be disptched to every OSC method in the current OSC Address Space whose OSC Address matches the OSC Message’s OSC Address Pattern. An OSC Address Pattern matches an OSC Address if

  1. The OSC Address and the OSC Address Pattern contain the same number of parts; and
  2. Each part of the OSC Address Pattern matches the corresponding part of the OSC Address.

A part of an OSC Address Pattern matches a part of an OSC Address if every consecutive character in the OSC Address Pattern matches the next consecutive substring of the OSC Address and every character in the OSC Address is matched by something in the OSC Address Pattern. These are the matching rules for characters in the OSC Address Pattern:

  1. ?’ in the OSC Address Pattern matches any single character
  2. *’ in the OSC Address Pattern matches any sequence of zero or more characters
  3. A string of characters in square brackets (e.g., “[string]”) in the OSC Address Pattern matches any character in the string. Inside square brackets, the minus sign (-) and exclamation point (!) have special meanings:
    • two characters separated by a minus sign indicate the range of characters between the given two in ASCII collating sequence. (A minus sign at the end of the string has no special meaning.)
    • An exclamation point at the beginning of a bracketed string negates the sense of the list, meaning that the list matches any character not in the list. (An exclamation point anywhere besides the first character after the open bracket has no special meaning.)
  4. A comma-separated list of strings enclosed in curly braces (e.g., “{foo,bar}”) in the OSC Address Pattern matches any of the strings in the list.
  5. Any other character in an OSC Address Pattern can match only the same character.

Temporal Semantics and OSC Time Tags

An OSC server must have access to a representation of the correct current absolute time. OSC does not provide any mechanism for clock synchronization.

When a received OSC Packet contains only a single OSC Message, the OSC Server should invoke the correponding OSC Methods immediately, i.e., as soon as possible after receipt of the packet. Otherwise a received OSC Packet contains an OSC Bundle, in which case the OSC Bundle’s OSC Time Tag determines when the OSC Bundle’s OSC Messages’ corresponding OSC Methods should be invoked. If the time represented by the OSC Time Tag is before or equal to the current time, the OSC Server should invoke the methods immediately (unless the user has configured the OSC Server to discard messages that arrive too late). Otherwise the OSC Time Tag represents a time in the future, and the OSC server must store the OSC Bundle until the specified time and then invoke the appropriate OSC Methods.

Time tags are represented by a 64 bit fixed point number. The first 32 bits specify the number of seconds since midnight on January 1, 1900, and the last 32 bits specify fractional parts of a second to a precision of about 200 picoseconds. This is the representation used by Internet NTP timestamps.The time tag value consisting of 63 zero bits followed by a one in the least signifigant bit is a special case meaning “immediately.”

OSC Messages in the same OSC Bundle are atomic; their corresponding OSC Methods should be invoked in immediate succession as if no other processing took place between the OSC Method invocations.

When an OSC Address Pattern is dispatched to multiple OSC Methods, the order in which the matching OSC Methods are invoked is unspecified. When an OSC Bundle contains multiple OSC Messages, the sets of OSC Methods corresponding to the OSC Messages must be invoked in the same order as the OSC Messages appear in the packet. (example)

When bundles contain other bundles, the OSC Time Tag of the enclosed bundle must be greater than or equal to the OSC Time Tag of the enclosing bundle. The atomicity requirement for OSC Messages in the same OSC Bundle does not apply to OSC Bundles within an OSC Bundle.

Introduction Open Sound Control (OSC) is an open, transport-independent, message-based protocol developed for communication among computers, sound synthesizers, and other multimedia devices.

OSC Syntax
This section defines the syntax of OSC data.

Atomic Data Types
All OSC data is composed of the following fundamental data types:

int32
32-bit big-endian two’s complement integer
OSC-timetag
64-bit big-endian fixed-point time tag, semantics defined below
float32
32-bit big-endian IEEE 754 floating point number
OSC-string
A sequence of non-null ASCII characters followed by a null, followed by 0-3 additional null characters to make the total number of bits a multiple of 32. (OSC-string examples) In this document, example OSC-strings will be written without the null characters, surrounded by double quotes.
OSC-blob
An int32 size count, followed by that many 8-bit bytes of arbitrary binary data, followed by 0-3 additional zero bytes to make the total number of bits a multiple of 32.
The size of every atomic data type in OSC is a multiple of 32 bits. This guarantees that if the beginning of a block of OSC data is 32-bit aligned, every number in the OSC data will be 32-bit aligned.

OSC Packets
The unit of transmission of OSC is an OSC Packet. Any application that sends OSC Packets is an OSC Client; any application that receives OSC Packets is an OSC Server.

An OSC packet consists of its contents , a contiguous block of binary data, and its size , the number of 8-bit bytes that comprise the contents. The size of an OSC packet is always a multiple of 4.

The underlying network that delivers an OSC packet is responsible for delivering both the contents and the size to the OSC application. An OSC packet can be naturally represented by a datagram by a network protocol such as UDP. In a stream-based protocol such as TCP, the stream should begin with an int32 giving the size of the first packet, followed by the contents of the first packet, followed by the size of the second packet, etc.

The contents of an OSC packet must be either an OSC Message or an OSC Bundle. The first byte of the packet’s contents unambiguously distinguishes between these two alternatives.

OSC Messages
An OSC message consists of an OSC Address Pattern followed by an OSC Type Tag String followed by zero or more OSC Arguments.

Note: some older implementations of OSC may omit the OSC Type Tag string. Until all such implementations are updated, OSC implementations should be robust in the case of a missing OSC Type Tag String.

OSC Address Patterns
An OSC Address Pattern is an OSC-string beginning with the character ‘/’ (forward slash).

OSC Type Tag String
An OSC Type Tag String is an OSC-string beginning with the character ‘,’ (comma) followed by a sequence of characters corresponding exactly to the sequence of OSC Arguments in the given message. Each character after the comma is called an OSC Type Tag and represents the type of the corresponding OSC Argument. (The requirement for OSC Type Tag Strings to start with a comma makes it easier for the recipient of an OSC Message to determine whether that OSC Message is lacking an OSC Type Tag String.)

This table lists the correspondance between each OSC Type Tag and the type of its corresponding OSC Argument:

The meaning of each OSC Type Tag
OSC Type Tag Type of corresponding argument
i int32
f float32
s OSC-string
b OSC-blob
Some OSC applications communicate among instances of themselves with additional, nonstandard argument types beyond those specified above. OSC applications are not required to recognize these types; an OSC application should discard any message whose OSC Type Tag String contains any unrecognized OSC Type Tags. An application that does use any additional argument types must encode them with the OSC Type Tags in this table:

OSC Type Tags that must be used for certain nonstandard argument types
OSC Type Tag Type of corresponding argument
h 64 bit big-endian two’s complement integer
t OSC-timetag
d 64 bit (“double”) IEEE 754 floating point number
S Alternate type represented as an OSC-string (for example, for systems that differentiate “symbols” from “strings”)
c an ascii character, sent as 32 bits
r 32 bit RGBA color
m 4 byte MIDI message. Bytes from MSB to LSB are: port id, status byte, data1, data2
T True. No bytes are allocated in the argument data.
F False. No bytes are allocated in the argument data.
N Nil. No bytes are allocated in the argument data.
I Infinitum. No bytes are allocated in the argument data.
[ Indicates the beginning of an array. The tags following are for data in the Array until a close brace tag is reached.
] Indicates the end of an array.
OSC Type Tag String examples.

OSC Arguments
A sequence of OSC Arguments is represented by a contiguous sequence of the binary representations of each argument.

OSC Bundles
An OSC Bundle consists of the OSC-string “#bundle” followed by an OSC Time Tag , followed by zero or more OSC Bundle Elements. The OSC-timetag is a 64-bit fixed point time tag whose semantics are described below.

An OSC Bundle Element consists of its size and its contents. The size is an int32 representing the number of 8-bit bytes in the contents, and will always be a multiple of 4. The contents are either an OSC Message or an OSC Bundle.

Note this recursive definition: bundle may contain bundles.

This table shows the parts of a two-or-more-element OSC Bundle and the size (in 8-bit bytes) of each part.

Parts of an OSC Bundle
Data Size Purpose
OSC-string “#bundle” 8 bytes How to know that this data is a bundle
OSC-timetag 8 bytes Time tag that applies to the entire bundle
Size of first bundle element int32 = 4 bytes
First bundle element’s contents As many bytes as given by “size of first bundle element” First bundle element
Size of second bundle element int32 = 4 bytes
Second bundle element’s contents As many bytes as given by “size of second bundle element” Second bundle element
etc. Addtional bundle elements
OSC Semantics
This section defines the semantics of OSC data.

OSC Address Spaces and OSC Addresses
Every OSC server has a set of OSC Methods. OSC Methods are the potential destinations of OSC messages received by the OSC server and correspond to each of the points of control that the application makes available. “Invoking” an OSC method is analogous to a procedure call; it means supplying the method with arguments and causing the method’s effect to take place.

An OSC Server’s OSC Methods are arranged in a tree strcuture called an OSC Address Space. The leaves of this tree are the OSC Methods and the branch nodes are called OSC Containers. An OSC Server’s OSC Address Space can be dynamic; that is, its contents and shape can change over time.

Each OSC Method and each OSC Container other than the root of the tree has a symbolic name, an ASCII string consiting of printable characters other than the following:

Printable ASCII characters not allowed in names of OSC Methods or OSC Containers
character name ASCII code (decimal)
’ ’ space

number sign 35

  • asterisk 42
    , comma 44
    / forward slash 47
    ? question mark 63
    [ open bracket 91
    ] close bracket 93
    { open curly brace 123
    } close curly brace 125
    The OSC Address of an OSC Method is a symbolic name giving the full path to the OSC Method in the OSC Address Space, starting from the root of the tree. An OSC Method’s OSC Address begins with the character ‘/’ (forward slash), followed by the names of all the containers, in order, along the path from the root of the tree to the OSC Method, separated by forward slash characters, followed by the name of the OSC Method. The syntax of OSC Addresses was chosen to match the syntax of URLs. (OSC Address Examples)

OSC Message Dispatching and Pattern Matching
When an OSC server receives an OSC Message, it must invoke the appropriate OSC Methods in its OSC Address Space based on the OSC Message’s OSC Address Pattern. This process is called dispatching the OSC Message to the OSC Methods that match its OSC Address Pattern. All the matching OSC Methods are invoked with the same argument data, namely, the OSC Arguments in the OSC Message.

The parts of an OSC Address or an OSC Address Pattern are the substrings between adjacent pairs of forward slash characters and the substring after the last forward slash character. (examples)

A received OSC Message must be disptched to every OSC method in the current OSC Address Space whose OSC Address matches the OSC Message’s OSC Address Pattern. An OSC Address Pattern matches an OSC Address if

The OSC Address and the OSC Address Pattern contain the same number of parts; and
Each part of the OSC Address Pattern matches the corresponding part of the OSC Address.
A part of an OSC Address Pattern matches a part of an OSC Address if every consecutive character in the OSC Address Pattern matches the next consecutive substring of the OSC Address and every character in the OSC Address is matched by something in the OSC Address Pattern. These are the matching rules for characters in the OSC Address Pattern:

‘?’ in the OSC Address Pattern matches any single character
‘*’ in the OSC Address Pattern matches any sequence of zero or more characters
A string of characters in square brackets (e.g., “[string]”) in the OSC Address Pattern matches any character in the string. Inside square brackets, the minus sign (-) and exclamation point (!) have special meanings:
two characters separated by a minus sign indicate the range of characters between the given two in ASCII collating sequence. (A minus sign at the end of the string has no special meaning.)
An exclamation point at the beginning of a bracketed string negates the sense of the list, meaning that the list matches any character not in the list. (An exclamation point anywhere besides the first character after the open bracket has no special meaning.)
A comma-separated list of strings enclosed in curly braces (e.g., “{foo,bar}”) in the OSC Address Pattern matches any of the strings in the list.
Any other character in an OSC Address Pattern can match only the same character.
Temporal Semantics and OSC Time Tags
An OSC server must have access to a representation of the correct current absolute time. OSC does not provide any mechanism for clock synchronization.

When a received OSC Packet contains only a single OSC Message, the OSC Server should invoke the correponding OSC Methods immediately, i.e., as soon as possible after receipt of the packet. Otherwise a received OSC Packet contains an OSC Bundle, in which case the OSC Bundle’s OSC Time Tag determines when the OSC Bundle’s OSC Messages’ corresponding OSC Methods should be invoked. If the time represented by the OSC Time Tag is before or equal to the current time, the OSC Server should invoke the methods immediately (unless the user has configured the OSC Server to discard messages that arrive too late). Otherwise the OSC Time Tag represents a time in the future, and the OSC server must store the OSC Bundle until the specified time and then invoke the appropriate OSC Methods.

Time tags are represented by a 64 bit fixed point number. The first 32 bits specify the number of seconds since midnight on January 1, 1900, and the last 32 bits specify fractional parts of a second to a precision of about 200 picoseconds. This is the representation used by Internet NTP timestamps.The time tag value consisting of 63 zero bits followed by a one in the least signifigant bit is a special case meaning “immediately.”

OSC Messages in the same OSC Bundle are atomic; their corresponding OSC Methods should be invoked in immediate succession as if no other processing took place between the OSC Method invocations.

When an OSC Address Pattern is dispatched to multiple OSC Methods, the order in which the matching OSC Methods are invoked is unspecified. When an OSC Bundle contains multiple OSC Messages, the sets of OSC Methods corresponding to the OSC Messages must be invoked in the same order as the OSC Messages appear in the packet. (example)

When bundles contain other bundles, the OSC Time Tag of the enclosed bundle must be greater than or equal to the OSC Time Tag of the enclosing bundle. The atomicity requirement for OSC Messages in the same OSC Bundle does not apply to OSC Bundles within an OSC Bundle.

Creating 2 server instances on same port crashes

When creating a second instance of a server using the same port, node.js will crash with an uncaught exception. We tried catching this with a try but it doesn't seem to work. Any ideas how we could manage this ?

Thanks !

Resending the received message fails with Error: message must contain an address

var osc = require('node-osc');

var ip = '10.0.1.0';
var oscServer = new osc.Server(3333, '0.0.0.0');
oscServer.on("message", function (msg, rinfo) {
      console.log(msg[0]);
      var client = new osc.Client(ip, 3000);
      client.send(msg);
});

I think the message received must be the same type as the message to be sent, which does not seem to be ze case.

In the output I get

/text/1
/Users/eight/repos/netscan-node/node_modules/osc-min/lib/osc-utilities.js:568
      throw new Error("message must contain an address");
      ^

Error: message must contain an address
    at Object.exports.toOscMessage (/Users/eight/repos/netscan-node/node_modules/osc-min/lib/osc-utilities.js:568:13)
    at Object.exports.toOscPacket (/Users/eight/repos/netscan-node/node_modules/osc-min/lib/osc-utilities.js:627:20)
    at Object.exports.toBuffer (/Users/eight/repos/netscan-node/node_modules/osc-min/lib/index.js:143:18)
    at Object.send (/Users/eight/repos/netscan-node/node_modules/node-osc/lib/Client.js:36:27)
    at Server.<anonymous> (/Users/eight/repos/netscan-node/osc.js:7:14)
    at emitTwo (events.js:106:13)
    at Server.emit (events.js:191:7)
    at Socket.<anonymous> (/Users/eight/repos/netscan-node/node_modules/node-osc/lib/Server.js:27:20)
    at emitTwo (events.js:106:13)
    at Socket.emit (events.js:191:7)

OSC Spec 1.1 `legacy optional types`

I need to send MIDI via OSC.

As per the OSC Spec 1.0 (see second table "nonstandard argument types") we should be able to use a OSC Tag Type of m (4 byte MIDI message. Bytes from MSB to LSB are: port id, status byte, data1, data2).

In my code I'd like to do something like this (I'm using TypeScript):

client.send({ address: "/midi", args: [{ type: "m", value: midiMessageBytes as Buffer }] });

I've tested this and I believe the type is being inferred automatically, as my type m is not being received from the device on the receiving end of this message.

Looking into the osc-min package which implements the OSC Spec 1.1, it appears that the legacy optional types have not been implemented (see 3.5.3).

I was wondering if there's a way of circumventing this in node-osc?

Bundled OSC Messages

Is it possible to receive bundled OSC messages? I receive this error from the 'Server.js' every time I try:

Error: can't decode incoming message: invalid type tag in incoming OSC message, must start with comma
at Socket. (/Applications/OSC for OBS.app/Contents/Resources/app/node_modules/node-osc/dist/lib/Server.js:29:23)
at Socket.emit (events.js:315:20)
at UDP.onMessage [as onmessage] (dgram.js:910:8)

Issue: whole numbers are sent as integers

This is quite an annoying issue related round numbers in a float value range.

For example if i want to send float value in range from 0 to 1. Whole numbers 0 and 1 are sent as integers, its quite understandable as javascript is dynamic typed. But i can't find a permanent answer for sending only floats. As a temporary solution i add a very very small fraction to the number, which based on our application logic is irrelevant.

As we do strict type validation on the destination, these messages get thrown away.

Did some tests which demonstrate what i send and what i recieve:

client.send(['/t', 1]);                 // /t 1 (int)
client.send(['/t', 1.00]);              // /t 1 (int)
client.send(['/t', (1).toFixed(2)]);    // /t 1.00 (string)
client.send(['/t', (1.00).toFixed(2)]); // /t 1.00 (string)
client.send(['/t', parseFloat(1)]);     // /t 1 (int)
client.send(['/t', parseFloat(1.00)]);  // /t 1 (int)
client.send(['/t', 1 + 0.00001]);       // /t 1.000 (float)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.