Initial commit of my folder
This commit is contained in:
477
backend/node_modules/node-osc/docs/API.md
generated
vendored
Normal file
477
backend/node_modules/node-osc/docs/API.md
generated
vendored
Normal file
@ -0,0 +1,477 @@
|
||||
<!-- Generated by JSDoc. Update this documentation by updating the source code. -->
|
||||
|
||||
# API Reference
|
||||
|
||||
> **⚠️ This file is auto-generated from JSDoc comments in the source code.**
|
||||
> To update this documentation, edit the JSDoc comments in the source files and run `npm run docs`.
|
||||
|
||||
This document provides detailed API reference for all classes, methods, and functions in node-osc.
|
||||
|
||||
For usage guides, best practices, and troubleshooting, see the **[Guide](./GUIDE.md)**.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Server](#server)
|
||||
- [Constructor](#server-constructor)
|
||||
- [close()](#server-close)
|
||||
- [Client](#client)
|
||||
- [Constructor](#client-constructor)
|
||||
- [close()](#client-close)
|
||||
- [send()](#client-send)
|
||||
- [Message](#message)
|
||||
- [Constructor](#message-constructor)
|
||||
- [append()](#message-append)
|
||||
- [Bundle](#bundle)
|
||||
- [Constructor](#bundle-constructor)
|
||||
- [append()](#bundle-append)
|
||||
- [Low Level Functions](#low-level-functions)
|
||||
- [encode()](#encode)
|
||||
- [decode()](#decode)
|
||||
|
||||
---
|
||||
|
||||
## Server
|
||||
|
||||
**Extends:** EventEmitter
|
||||
|
||||
OSC Server for receiving messages and bundles over UDP.
|
||||
|
||||
Emits the following events:
|
||||
- 'listening': Emitted when the server starts listening
|
||||
- 'message': Emitted when an OSC message is received (receives msg array and rinfo object)
|
||||
- 'bundle': Emitted when an OSC bundle is received (receives bundle object and rinfo object)
|
||||
- 'error': Emitted when a socket error or decoding error occurs (receives error and rinfo)
|
||||
- Address-specific events: Emitted for each message address (e.g., '/test')
|
||||
|
||||
### Server Constructor
|
||||
|
||||
Creates a new Server instance.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `port` *{number}* - The port to listen on.
|
||||
- `host` *{string}* (optional) - Default: `'127.0.0.1'` - The host address to bind to. Use '0.0.0.0' to listen on all interfaces.
|
||||
- `cb` *{function}* (optional) - Optional callback function called when server starts listening.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```javascript
|
||||
// Create and listen for messages
|
||||
const server = new Server(3333, '0.0.0.0', () => {
|
||||
console.log('Server is listening');
|
||||
});
|
||||
|
||||
server.on('message', (msg, rinfo) => {
|
||||
console.log('Message:', msg);
|
||||
console.log('From:', rinfo.address, rinfo.port);
|
||||
});
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Using async/await with events.once
|
||||
import { once } from 'node:events';
|
||||
|
||||
const server = new Server(3333, '0.0.0.0');
|
||||
await once(server, 'listening');
|
||||
|
||||
server.on('message', (msg) => {
|
||||
console.log('Message:', msg);
|
||||
});
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Listen for specific OSC addresses
|
||||
server.on('/note', (msg) => {
|
||||
const [address, pitch, velocity] = msg;
|
||||
console.log(`Note: ${pitch}, Velocity: ${velocity}`);
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### Server.close()
|
||||
|
||||
Close the server socket.
|
||||
|
||||
This method can be used with either a callback or as a Promise.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `cb` *{function}* (optional) - Optional callback function called when socket is closed.
|
||||
|
||||
**Returns:** *{Promise.<void> | undefined}* - Returns a Promise if no callback is provided.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```javascript
|
||||
// With callback
|
||||
server.close((err) => {
|
||||
if (err) console.error(err);
|
||||
});
|
||||
```
|
||||
|
||||
```javascript
|
||||
// With async/await
|
||||
await server.close();
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Client
|
||||
|
||||
**Extends:** EventEmitter
|
||||
|
||||
OSC Client for sending messages and bundles over UDP.
|
||||
|
||||
Extends EventEmitter and emits the following events:
|
||||
- 'error': Emitted when a socket error occurs
|
||||
|
||||
### Client Constructor
|
||||
|
||||
Creates a new Client instance.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `host` *{string}* - The hostname or IP address of the OSC server.
|
||||
- `port` *{number}* - The port number of the OSC server.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```javascript
|
||||
// Create a client
|
||||
const client = new Client('127.0.0.1', 3333);
|
||||
|
||||
// Send a message with callback
|
||||
client.send('/oscAddress', 200, (err) => {
|
||||
if (err) console.error(err);
|
||||
client.close();
|
||||
});
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Send a message with async/await
|
||||
const client = new Client('127.0.0.1', 3333);
|
||||
await client.send('/oscAddress', 200);
|
||||
await client.close();
|
||||
```
|
||||
|
||||
|
||||
### Client.close()
|
||||
|
||||
Close the client socket.
|
||||
|
||||
This method can be used with either a callback or as a Promise.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `cb` *{function}* (optional) - Optional callback function called when socket is closed.
|
||||
|
||||
**Returns:** *{Promise.<void> | undefined}* - Returns a Promise if no callback is provided.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```javascript
|
||||
// With callback
|
||||
client.close((err) => {
|
||||
if (err) console.error(err);
|
||||
});
|
||||
```
|
||||
|
||||
```javascript
|
||||
// With async/await
|
||||
await client.close();
|
||||
```
|
||||
|
||||
|
||||
### Client.send()
|
||||
|
||||
Send an OSC message or bundle to the server.
|
||||
|
||||
This method can be used with either a callback or as a Promise.
|
||||
Messages can be sent in several formats:
|
||||
- As separate arguments: address followed by values
|
||||
- As a Message or Bundle object
|
||||
- As an array: [address, ...values]
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `args` *{*}* - The message to send. Can be:
|
||||
- (address: string, ...values: any[], callback?: Function)
|
||||
- (message: Message|Bundle, callback?: Function)
|
||||
- (array: Array, callback?: Function)
|
||||
|
||||
**Returns:** *{Promise.<void> | undefined}* - Returns a Promise if no callback is provided.
|
||||
|
||||
**Throws:**
|
||||
|
||||
- *{TypeError}* - If the message format is invalid.
|
||||
- *{ReferenceError}* - If attempting to send on a closed socket.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```javascript
|
||||
// Send with address and arguments
|
||||
client.send('/oscAddress', 200, 'hello', (err) => {
|
||||
if (err) console.error(err);
|
||||
});
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Send with async/await
|
||||
await client.send('/oscAddress', 200, 'hello');
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Send a Message object
|
||||
const msg = new Message('/test', 1, 2, 3);
|
||||
await client.send(msg);
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Send a Bundle object
|
||||
const bundle = new Bundle(['/one', 1], ['/two', 2]);
|
||||
await client.send(bundle);
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Message
|
||||
|
||||
Represents an OSC message with an address and arguments.
|
||||
|
||||
OSC messages consist of an address pattern (string starting with '/')
|
||||
and zero or more arguments of various types.
|
||||
|
||||
### Message Constructor
|
||||
|
||||
Creates a new Message instance.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `address` *{string}* - The OSC address pattern (e.g., '/oscillator/frequency').
|
||||
- `args` *{*}* - Optional arguments to include in the message.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```javascript
|
||||
// Create a message with constructor arguments
|
||||
const msg = new Message('/test', 1, 2, 'hello');
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Create a message and append arguments
|
||||
const msg = new Message('/test');
|
||||
msg.append(1);
|
||||
msg.append('hello');
|
||||
msg.append(3.14);
|
||||
```
|
||||
|
||||
|
||||
### Message.append()
|
||||
|
||||
Append an argument to the message.
|
||||
|
||||
Automatically detects the type based on the JavaScript type:
|
||||
- Integers are encoded as OSC integers
|
||||
- Floats are encoded as OSC floats
|
||||
- Strings are encoded as OSC strings
|
||||
- Booleans are encoded as OSC booleans
|
||||
- Buffers are encoded as OSC blobs
|
||||
- Arrays are recursively appended
|
||||
- Objects with a 'type' property are used as-is
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `arg` *{*}* - The argument to append. Can be:
|
||||
- A primitive value (number, string, boolean)
|
||||
- A Buffer (encoded as blob)
|
||||
- An array of values (will be recursively appended)
|
||||
- An object with 'type' and 'value' properties for explicit type control
|
||||
|
||||
**Throws:**
|
||||
|
||||
- *{Error}* - If the argument type cannot be encoded.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```javascript
|
||||
const msg = new Message('/test');
|
||||
msg.append(42); // Integer
|
||||
msg.append(3.14); // Float
|
||||
msg.append('hello'); // String
|
||||
msg.append(true); // Boolean
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Append multiple values at once
|
||||
msg.append([1, 2, 3]);
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Explicitly specify type
|
||||
msg.append({ type: 'float', value: 42 });
|
||||
msg.append({ type: 'blob', value: Buffer.from('data') });
|
||||
```
|
||||
|
||||
```javascript
|
||||
// MIDI messages (4 bytes: port, status, data1, data2)
|
||||
msg.append({ type: 'midi', value: { port: 0, status: 144, data1: 60, data2: 127 } });
|
||||
msg.append({ type: 'm', value: Buffer.from([0, 144, 60, 127]) });
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Bundle
|
||||
|
||||
Represents an OSC bundle containing multiple messages or nested bundles.
|
||||
|
||||
OSC bundles allow multiple messages to be sent together, optionally with
|
||||
a timetag indicating when the bundle should be processed.
|
||||
|
||||
### Bundle Constructor
|
||||
|
||||
Creates a new Bundle instance.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `timetagOrElement` *{number | Message | Bundle | Array}* (optional) - Timetag, or if not a number, the first element and timetag will default to 0.
|
||||
- `elements` *{Message | Bundle | Array}* - Messages or bundles to include.
|
||||
Arrays will be automatically converted to Message objects.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```javascript
|
||||
// Create a bundle without a timetag
|
||||
const bundle = new Bundle(['/one', 1], ['/two', 2]);
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Create a bundle with a timetag
|
||||
const bundle = new Bundle(10, ['/one', 1], ['/two', 2]);
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Nest bundles
|
||||
const bundle1 = new Bundle(['/one', 1]);
|
||||
const bundle2 = new Bundle(['/two', 2]);
|
||||
bundle1.append(bundle2);
|
||||
```
|
||||
|
||||
|
||||
### Bundle.append()
|
||||
|
||||
Append a message or bundle to this bundle.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `element` *{Message | Bundle | Array}* - The message or bundle to append.
|
||||
Arrays will be automatically converted to Message objects.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```javascript
|
||||
const bundle = new Bundle();
|
||||
bundle.append(['/test', 1]);
|
||||
bundle.append(new Message('/test2', 2));
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Append a nested bundle
|
||||
const bundle1 = new Bundle(['/one', 1]);
|
||||
const bundle2 = new Bundle(['/two', 2]);
|
||||
bundle1.append(bundle2);
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Low Level Functions
|
||||
|
||||
These functions provide low-level access to OSC encoding and decoding for advanced use cases.
|
||||
|
||||
### encode()
|
||||
|
||||
Encode an OSC message or bundle to a Buffer.
|
||||
|
||||
This low-level function converts OSC messages and bundles into binary format
|
||||
for transmission or storage. Useful for sending OSC over custom transports
|
||||
(WebSocket, TCP, HTTP), storing to files, or implementing custom OSC routers.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `message` *{Object}* - OSC message or bundle object with oscType property
|
||||
|
||||
**Returns:** *{Buffer}* - The encoded OSC data ready for transmission
|
||||
|
||||
**Examples:**
|
||||
|
||||
```javascript
|
||||
// Encode a message
|
||||
import { Message, encode } from 'node-osc';
|
||||
|
||||
const message = new Message('/oscillator/frequency', 440);
|
||||
const buffer = encode(message);
|
||||
console.log('Encoded bytes:', buffer.length);
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Encode a bundle
|
||||
import { Bundle, encode } from 'node-osc';
|
||||
|
||||
const bundle = new Bundle(['/one', 1], ['/two', 2]);
|
||||
const buffer = encode(bundle);
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Send over WebSocket
|
||||
const buffer = encode(message);
|
||||
websocket.send(buffer);
|
||||
```
|
||||
|
||||
|
||||
### decode()
|
||||
|
||||
Decode a Buffer containing OSC data into a message or bundle object.
|
||||
|
||||
This low-level function parses binary OSC data back into JavaScript objects.
|
||||
Useful for receiving OSC over custom transports, reading from files,
|
||||
or implementing custom OSC routers.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `buffer` *{Buffer}* - The Buffer containing OSC data
|
||||
|
||||
**Returns:** *{Object}* - The decoded OSC message or bundle. Messages have
|
||||
{oscType: 'message', address: string, args: Array}, bundles have
|
||||
{oscType: 'bundle', timetag: number, elements: Array}
|
||||
|
||||
**Throws:**
|
||||
|
||||
- *{Error}* - If the buffer contains malformed OSC data
|
||||
|
||||
**Examples:**
|
||||
|
||||
```javascript
|
||||
// Decode received data
|
||||
import { decode } from 'node-osc';
|
||||
|
||||
const decoded = decode(buffer);
|
||||
if (decoded.oscType === 'message') {
|
||||
console.log('Address:', decoded.address);
|
||||
console.log('Arguments:', decoded.args);
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Round-trip encode/decode
|
||||
import { Message, encode, decode } from 'node-osc';
|
||||
|
||||
const original = new Message('/test', 42, 'hello');
|
||||
const buffer = encode(original);
|
||||
const decoded = decode(buffer);
|
||||
console.log(decoded.address); // '/test'
|
||||
```
|
||||
|
||||
|
||||
605
backend/node_modules/node-osc/docs/GUIDE.md
generated
vendored
Normal file
605
backend/node_modules/node-osc/docs/GUIDE.md
generated
vendored
Normal file
@ -0,0 +1,605 @@
|
||||
# node-osc Guide
|
||||
|
||||
This guide provides best practices, patterns, and detailed information for using node-osc effectively.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Events](#events)
|
||||
- [Error Handling](#error-handling)
|
||||
- [Type System](#type-system)
|
||||
- [Best Practices](#best-practices)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
|
||||
## Events
|
||||
|
||||
The `Server` class extends `EventEmitter` and emits several events for different scenarios.
|
||||
|
||||
### Server Events
|
||||
|
||||
#### `listening`
|
||||
|
||||
Emitted when the server starts listening for messages.
|
||||
|
||||
```javascript
|
||||
server.on('listening', () => {
|
||||
console.log('Server is ready to receive messages');
|
||||
});
|
||||
```
|
||||
|
||||
#### `message`
|
||||
|
||||
Emitted when an OSC message is received.
|
||||
|
||||
**Parameters:**
|
||||
- `msg` (Array): The message as an array where the first element is the address and subsequent elements are arguments
|
||||
- `rinfo` (Object): Remote address information
|
||||
- `address` (string): The sender's IP address
|
||||
- `port` (number): The sender's port number
|
||||
|
||||
```javascript
|
||||
server.on('message', (msg, rinfo) => {
|
||||
const [address, ...args] = msg;
|
||||
console.log(`Received ${address} from ${rinfo.address}:${rinfo.port}`);
|
||||
console.log('Arguments:', args);
|
||||
});
|
||||
```
|
||||
|
||||
#### `bundle`
|
||||
|
||||
Emitted when an OSC bundle is received.
|
||||
|
||||
**Parameters:**
|
||||
- `bundle` (Object): The bundle object
|
||||
- `timetag` (number): The bundle's timetag
|
||||
- `elements` (Array): Array of messages or nested bundles
|
||||
- `rinfo` (Object): Remote address information
|
||||
|
||||
```javascript
|
||||
server.on('bundle', (bundle, rinfo) => {
|
||||
console.log(`Received bundle with timetag ${bundle.timetag}`);
|
||||
bundle.elements.forEach((element) => {
|
||||
console.log('Element:', element);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### Address-Specific Events
|
||||
|
||||
The server also emits events for each message address received. This allows you to listen for specific OSC addresses without filtering in your code.
|
||||
|
||||
```javascript
|
||||
// Listen specifically for messages to /note
|
||||
server.on('/note', (msg, rinfo) => {
|
||||
const [address, pitch, velocity] = msg;
|
||||
console.log(`Note: ${pitch}, Velocity: ${velocity}`);
|
||||
});
|
||||
|
||||
// Listen for /oscillator/frequency
|
||||
server.on('/oscillator/frequency', (msg) => {
|
||||
const [address, freq] = msg;
|
||||
console.log(`Frequency set to ${freq} Hz`);
|
||||
});
|
||||
```
|
||||
|
||||
#### `error`
|
||||
|
||||
Emitted when there's an error decoding an incoming message or a socket error.
|
||||
|
||||
**Parameters:**
|
||||
- `error` (Error): The error object
|
||||
- `rinfo` (Object): Remote address information (for decode errors)
|
||||
|
||||
```javascript
|
||||
server.on('error', (error, rinfo) => {
|
||||
if (rinfo) {
|
||||
console.error(`Error from ${rinfo.address}:${rinfo.port}: ${error.message}`);
|
||||
} else {
|
||||
console.error('Socket error:', error.message);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Client Events
|
||||
|
||||
#### `error`
|
||||
|
||||
Emitted when a socket error occurs.
|
||||
|
||||
```javascript
|
||||
client.on('error', (error) => {
|
||||
console.error('Client error:', error.message);
|
||||
});
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
Proper error handling is essential for robust OSC applications.
|
||||
|
||||
### Client Errors
|
||||
|
||||
#### Sending on Closed Socket
|
||||
|
||||
If you try to send a message after closing the client, a `ReferenceError` will be thrown:
|
||||
|
||||
```javascript
|
||||
const client = new Client('127.0.0.1', 3333);
|
||||
await client.close();
|
||||
|
||||
try {
|
||||
await client.send('/test', 123);
|
||||
} catch (err) {
|
||||
console.error(err.message); // "Cannot send message on closed socket."
|
||||
console.error(err.code); // "ERR_SOCKET_DGRAM_NOT_RUNNING"
|
||||
}
|
||||
```
|
||||
|
||||
**Prevention:** Always ensure the client is open before sending:
|
||||
|
||||
```javascript
|
||||
const client = new Client('127.0.0.1', 3333);
|
||||
try {
|
||||
await client.send('/test', 123);
|
||||
} finally {
|
||||
await client.close(); // Close after sending
|
||||
}
|
||||
```
|
||||
|
||||
#### Invalid Message Format
|
||||
|
||||
Passing an invalid message format will throw a `TypeError`:
|
||||
|
||||
```javascript
|
||||
try {
|
||||
await client.send(12345); // Not a valid message format
|
||||
} catch (err) {
|
||||
console.error(err.message); // "That Message Just Doesn't Seem Right"
|
||||
}
|
||||
```
|
||||
|
||||
### Server Errors
|
||||
|
||||
#### Decoding Errors
|
||||
|
||||
When the server receives malformed OSC data, it emits an `'error'` event rather than throwing:
|
||||
|
||||
```javascript
|
||||
server.on('error', (err, rinfo) => {
|
||||
console.error(`Decode error from ${rinfo.address}: ${err.message}`);
|
||||
});
|
||||
```
|
||||
|
||||
### Error Handling Patterns
|
||||
|
||||
#### With Callbacks
|
||||
|
||||
```javascript
|
||||
client.send('/test', 123, (err) => {
|
||||
if (err) {
|
||||
console.error('Send failed:', err);
|
||||
return;
|
||||
}
|
||||
console.log('Message sent successfully');
|
||||
});
|
||||
```
|
||||
|
||||
#### With Async/Await
|
||||
|
||||
```javascript
|
||||
try {
|
||||
await client.send('/test', 123);
|
||||
console.log('Message sent successfully');
|
||||
} catch (err) {
|
||||
console.error('Send failed:', err);
|
||||
}
|
||||
```
|
||||
|
||||
#### Always Close Resources
|
||||
|
||||
Use try/finally to ensure resources are cleaned up even if errors occur:
|
||||
|
||||
```javascript
|
||||
const client = new Client('127.0.0.1', 3333);
|
||||
try {
|
||||
await client.send('/test', 123);
|
||||
await client.send('/test', 456);
|
||||
} catch (err) {
|
||||
console.error('Error sending:', err);
|
||||
} finally {
|
||||
await client.close(); // Always executes
|
||||
}
|
||||
```
|
||||
|
||||
## Type System
|
||||
|
||||
OSC supports several data types. node-osc automatically detects types for common JavaScript values:
|
||||
|
||||
| JavaScript Type | OSC Type | Description |
|
||||
|----------------|----------|-------------|
|
||||
| Integer number | `integer` | Whole numbers (e.g., 42, -10, 0) |
|
||||
| Float number | `float` | Decimal numbers (e.g., 3.14, -0.5) |
|
||||
| String | `string` | Text values (e.g., "hello") |
|
||||
| Boolean | `boolean` | true or false |
|
||||
| Buffer | `blob` | Binary data |
|
||||
| MIDI object/Buffer | `midi` | MIDI messages (4 bytes: port, status, data1, data2) |
|
||||
|
||||
### Automatic Type Detection
|
||||
|
||||
```javascript
|
||||
const msg = new Message('/test');
|
||||
msg.append(42); // → integer
|
||||
msg.append(3.14); // → float
|
||||
msg.append('hello'); // → string
|
||||
msg.append(true); // → boolean
|
||||
```
|
||||
|
||||
### Explicit Type Control
|
||||
|
||||
For advanced use cases, you can explicitly specify types:
|
||||
|
||||
```javascript
|
||||
const msg = new Message('/test');
|
||||
|
||||
// Force a whole number to be sent as float
|
||||
msg.append({ type: 'float', value: 42 });
|
||||
|
||||
// Use shorthand type notation
|
||||
msg.append({ type: 'f', value: 42 }); // 'f' = float
|
||||
msg.append({ type: 'i', value: 3.14 }); // 'i' = integer (truncates)
|
||||
msg.append({ type: 's', value: 'text' }); // 's' = string
|
||||
msg.append({ type: 'b', value: Buffer.from('data') }); // 'b' = blob
|
||||
msg.append({ type: 'm', value: { port: 0, status: 144, data1: 60, data2: 127 } }); // 'm' = MIDI
|
||||
```
|
||||
|
||||
### Supported Type Tags
|
||||
|
||||
- `'i'` or `'integer'` - 32-bit integer
|
||||
- `'f'` or `'float'` - 32-bit float
|
||||
- `'s'` or `'string'` - OSC string
|
||||
- `'b'` or `'blob'` - Binary blob
|
||||
- `'m'` or `'midi'` - MIDI message (4 bytes)
|
||||
- `'boolean'` - Boolean value (true/false)
|
||||
- `'T'` - True
|
||||
- `'F'` - False
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Use Async/Await for Cleaner Code
|
||||
|
||||
Prefer async/await over callbacks for more readable code:
|
||||
|
||||
```javascript
|
||||
// ✅ Good - Clean and readable
|
||||
async function sendMessages() {
|
||||
const client = new Client('127.0.0.1', 3333);
|
||||
try {
|
||||
await client.send('/test', 1);
|
||||
await client.send('/test', 2);
|
||||
await client.send('/test', 3);
|
||||
} finally {
|
||||
await client.close();
|
||||
}
|
||||
}
|
||||
|
||||
// ❌ Less ideal - Callback pyramid
|
||||
function sendMessages() {
|
||||
const client = new Client('127.0.0.1', 3333);
|
||||
client.send('/test', 1, (err) => {
|
||||
if (err) return console.error(err);
|
||||
client.send('/test', 2, (err) => {
|
||||
if (err) return console.error(err);
|
||||
client.send('/test', 3, (err) => {
|
||||
if (err) return console.error(err);
|
||||
client.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Always Close Resources
|
||||
|
||||
Always close clients and servers when done to prevent resource leaks:
|
||||
|
||||
```javascript
|
||||
const client = new Client('127.0.0.1', 3333);
|
||||
try {
|
||||
await client.send('/test', 123);
|
||||
} finally {
|
||||
await client.close(); // Always close
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Use Address-Specific Event Listeners
|
||||
|
||||
For better code organization, use address-specific event listeners:
|
||||
|
||||
```javascript
|
||||
// ✅ Good - Clear and organized
|
||||
server.on('/note', (msg) => {
|
||||
handleNote(msg);
|
||||
});
|
||||
|
||||
server.on('/control', (msg) => {
|
||||
handleControl(msg);
|
||||
});
|
||||
|
||||
// ❌ Less ideal - Manual routing
|
||||
server.on('message', (msg) => {
|
||||
const [address] = msg;
|
||||
if (address === '/note') handleNote(msg);
|
||||
else if (address === '/control') handleControl(msg);
|
||||
});
|
||||
```
|
||||
|
||||
### 4. Handle Errors Gracefully
|
||||
|
||||
Always implement error handling for both clients and servers:
|
||||
|
||||
```javascript
|
||||
// Client
|
||||
try {
|
||||
await client.send('/test', 123);
|
||||
} catch (err) {
|
||||
console.error('Failed to send:', err.message);
|
||||
}
|
||||
|
||||
// Server
|
||||
server.on('error', (err, rinfo) => {
|
||||
console.error(`Server error from ${rinfo?.address}:`, err.message);
|
||||
});
|
||||
```
|
||||
|
||||
### 5. Use Bundles for Related Messages
|
||||
|
||||
When sending multiple related messages, use bundles for atomic operations:
|
||||
|
||||
```javascript
|
||||
// ✅ Good - Atomic operation
|
||||
const bundle = new Bundle(
|
||||
['/synth/freq', 440],
|
||||
['/synth/amp', 0.5],
|
||||
['/synth/gate', 1]
|
||||
);
|
||||
await client.send(bundle);
|
||||
|
||||
// ❌ Less ideal - Separate messages (not atomic)
|
||||
await client.send('/synth/freq', 440);
|
||||
await client.send('/synth/amp', 0.5);
|
||||
await client.send('/synth/gate', 1);
|
||||
```
|
||||
|
||||
### 6. Listen on All Interfaces for Network Access
|
||||
|
||||
If you need to receive messages from other machines:
|
||||
|
||||
```javascript
|
||||
// Listen on all interfaces (accessible from network)
|
||||
const server = new Server(3333, '0.0.0.0');
|
||||
|
||||
// Only localhost (default, more secure)
|
||||
const server = new Server(3333, '127.0.0.1');
|
||||
```
|
||||
|
||||
### 7. Use Descriptive OSC Addresses
|
||||
|
||||
Follow OSC naming conventions with hierarchical addresses:
|
||||
|
||||
```javascript
|
||||
// ✅ Good - Hierarchical and descriptive
|
||||
await client.send('/synth/oscillator/1/frequency', 440);
|
||||
await client.send('/mixer/channel/3/volume', 0.8);
|
||||
|
||||
// ❌ Less ideal - Flat and unclear
|
||||
await client.send('/freq1', 440);
|
||||
await client.send('/vol3', 0.8);
|
||||
```
|
||||
|
||||
### 8. Validate Input Data
|
||||
|
||||
Validate data before sending to avoid runtime errors:
|
||||
|
||||
```javascript
|
||||
function sendNote(pitch, velocity) {
|
||||
if (typeof pitch !== 'number' || pitch < 0 || pitch > 127) {
|
||||
throw new Error('Invalid pitch: must be 0-127');
|
||||
}
|
||||
if (typeof velocity !== 'number' || velocity < 0 || velocity > 127) {
|
||||
throw new Error('Invalid velocity: must be 0-127');
|
||||
}
|
||||
return client.send('/note', pitch, velocity);
|
||||
}
|
||||
```
|
||||
|
||||
### 9. Wait for Server Ready
|
||||
|
||||
Always wait for the server to be listening before sending messages:
|
||||
|
||||
```javascript
|
||||
import { once } from 'node:events';
|
||||
|
||||
const server = new Server(3333, '0.0.0.0');
|
||||
|
||||
// Wait for server to be ready
|
||||
await once(server, 'listening');
|
||||
|
||||
// Now safe to send messages
|
||||
console.log('Server ready!');
|
||||
```
|
||||
|
||||
### 10. Use Parallel Sends When Appropriate
|
||||
|
||||
When sending multiple independent messages, use `Promise.all` for better performance:
|
||||
|
||||
```javascript
|
||||
// Send multiple messages in parallel
|
||||
await Promise.all([
|
||||
client.send('/track/1/volume', 0.8),
|
||||
client.send('/track/2/volume', 0.6),
|
||||
client.send('/track/3/volume', 0.9)
|
||||
]);
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Messages Not Being Received
|
||||
|
||||
**Possible causes and solutions:**
|
||||
|
||||
1. **Firewall blocking UDP traffic**
|
||||
- Check your firewall settings
|
||||
- Ensure the UDP port is open
|
||||
- Try with localhost first (`127.0.0.1`)
|
||||
|
||||
2. **Wrong host binding**
|
||||
- Server: Use `'0.0.0.0'` to listen on all interfaces
|
||||
- Server: Use `'127.0.0.1'` for localhost only
|
||||
- Client: Match the server's IP address
|
||||
|
||||
3. **Port mismatch**
|
||||
- Ensure client and server use the same port number
|
||||
- Check if another process is using the port
|
||||
|
||||
4. **Network connectivity**
|
||||
- Test with localhost first (`127.0.0.1`)
|
||||
- Verify network connectivity between machines
|
||||
- Check if devices are on the same network
|
||||
|
||||
### "Cannot send message on closed socket"
|
||||
|
||||
This error occurs when trying to send after closing the client:
|
||||
|
||||
```javascript
|
||||
// ❌ Wrong - Sending after close
|
||||
await client.close();
|
||||
await client.send('/test', 123); // Error!
|
||||
|
||||
// ✅ Correct - Send before close
|
||||
await client.send('/test', 123);
|
||||
await client.close();
|
||||
```
|
||||
|
||||
### Server Not Listening
|
||||
|
||||
Ensure you wait for the server to start before sending messages:
|
||||
|
||||
```javascript
|
||||
const server = new Server(3333, '0.0.0.0');
|
||||
|
||||
// Wait for server to be ready
|
||||
await new Promise(resolve => server.on('listening', resolve));
|
||||
|
||||
// Now safe to send messages
|
||||
console.log('Server ready!');
|
||||
```
|
||||
|
||||
### Messages Lost or Dropped
|
||||
|
||||
UDP is unreliable by design and messages can be lost:
|
||||
|
||||
**Solutions:**
|
||||
1. Use TCP-based OSC if reliability is critical (requires custom implementation)
|
||||
2. Implement acknowledgment messages
|
||||
3. Add retry logic for critical messages
|
||||
4. Use bundles to ensure related messages arrive together
|
||||
|
||||
### High CPU Usage
|
||||
|
||||
If you're seeing high CPU usage:
|
||||
|
||||
1. **Check for infinite loops** in event handlers
|
||||
2. **Rate limit** message sending if sending many messages
|
||||
3. **Use bundles** instead of many individual messages
|
||||
4. **Close unused connections** to free resources
|
||||
|
||||
### Memory Leaks
|
||||
|
||||
To prevent memory leaks:
|
||||
|
||||
1. **Always close** clients and servers when done
|
||||
2. **Remove event listeners** when no longer needed
|
||||
3. **Avoid** creating new clients/servers in loops
|
||||
4. **Reuse** client/server instances when possible
|
||||
|
||||
```javascript
|
||||
// ✅ Good - Proper cleanup
|
||||
const server = new Server(3333);
|
||||
const handler = (msg) => console.log(msg);
|
||||
server.on('message', handler);
|
||||
|
||||
// Later, clean up
|
||||
server.removeListener('message', handler);
|
||||
await server.close();
|
||||
```
|
||||
|
||||
## Advanced Topics
|
||||
|
||||
### Custom Transports
|
||||
|
||||
The `encode` and `decode` functions allow you to use OSC over custom transports:
|
||||
|
||||
```javascript
|
||||
import { encode, decode, Message } from 'node-osc';
|
||||
import WebSocket from 'ws';
|
||||
|
||||
// WebSocket server
|
||||
const wss = new WebSocket.Server({ port: 8080 });
|
||||
wss.on('connection', (ws) => {
|
||||
ws.on('message', (data) => {
|
||||
const oscMsg = decode(data);
|
||||
console.log('Received:', oscMsg);
|
||||
});
|
||||
});
|
||||
|
||||
// WebSocket client
|
||||
const ws = new WebSocket('ws://localhost:8080');
|
||||
const message = new Message('/test', 123);
|
||||
ws.send(encode(message));
|
||||
```
|
||||
|
||||
### Timetags in Bundles
|
||||
|
||||
OSC bundles support timetags for scheduling:
|
||||
|
||||
```javascript
|
||||
// Immediate execution (timetag = 0)
|
||||
const bundle = new Bundle(['/test', 1], ['/test', 2]);
|
||||
|
||||
// Scheduled execution (timetag in OSC time)
|
||||
const futureTime = Date.now() / 1000 + 5; // 5 seconds from now
|
||||
const scheduledBundle = new Bundle(futureTime, ['/test', 1]);
|
||||
```
|
||||
|
||||
**Note:** The server receives the timetag but does not automatically schedule execution. You must implement scheduling logic if needed.
|
||||
|
||||
### Performance Optimization
|
||||
|
||||
For high-throughput applications:
|
||||
|
||||
1. **Reuse client instances** instead of creating new ones
|
||||
2. **Use bundles** to send multiple messages together
|
||||
3. **Batch messages** and send periodically rather than immediately
|
||||
4. **Use binary blobs** for large data instead of many arguments
|
||||
5. **Profile your code** to identify bottlenecks
|
||||
|
||||
```javascript
|
||||
// ✅ Good - Reuse client
|
||||
const client = new Client('127.0.0.1', 3333);
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
await client.send('/test', i);
|
||||
}
|
||||
await client.close();
|
||||
|
||||
// ❌ Bad - Creating many clients
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const client = new Client('127.0.0.1', 3333);
|
||||
await client.send('/test', i);
|
||||
await client.close();
|
||||
}
|
||||
```
|
||||
|
||||
## Further Reading
|
||||
|
||||
- [API Documentation](./API.md) - Complete API reference
|
||||
- [OSC Specification](http://opensoundcontrol.org/spec-1_0) - Official OSC 1.0 specification
|
||||
- [Examples](../examples/) - Working code examples
|
||||
- [Main README](../README.md) - Quick start guide
|
||||
81
backend/node_modules/node-osc/docs/README.md
generated
vendored
Normal file
81
backend/node_modules/node-osc/docs/README.md
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
# node-osc Documentation
|
||||
|
||||
Welcome to the node-osc documentation! This directory contains comprehensive documentation for the node-osc library.
|
||||
|
||||
## Documentation Overview
|
||||
|
||||
### 📚 [API Reference](./API.md)
|
||||
**Complete API documentation for all classes and functions**
|
||||
|
||||
Auto-generated from JSDoc comments in the source code. This is your reference for:
|
||||
- All classes: `Server`, `Client`, `Message`, `Bundle`
|
||||
- All methods and their parameters
|
||||
- Low-level functions: `encode()` and `decode()`
|
||||
- Return types and error conditions
|
||||
- Code examples for each API
|
||||
|
||||
> **Note:** This file is automatically generated. To update it, edit the JSDoc comments in the source code and run `npm run docs`.
|
||||
|
||||
### 📘 [Usage Guide](./GUIDE.md)
|
||||
**Best practices, patterns, and troubleshooting**
|
||||
|
||||
A comprehensive guide covering:
|
||||
- Event handling patterns
|
||||
- Error handling strategies
|
||||
- OSC type system details
|
||||
- Best practices for production use
|
||||
- Troubleshooting common issues
|
||||
- Advanced topics like custom transports and performance optimization
|
||||
|
||||
## Quick Navigation
|
||||
|
||||
**New to node-osc?**
|
||||
1. Start with the [main README](../README.md) for a quick introduction and installation
|
||||
2. Try the [examples](../examples/) to see working code
|
||||
3. Read the [Usage Guide](./GUIDE.md) to learn best practices
|
||||
4. Reference the [API documentation](./API.md) as needed
|
||||
|
||||
**Looking for something specific?**
|
||||
- **How to send/receive messages** → [API Reference](./API.md) (Server and Client sections)
|
||||
- **How to handle errors** → [Usage Guide](./GUIDE.md#error-handling)
|
||||
- **Type system and data types** → [Usage Guide](./GUIDE.md#type-system)
|
||||
- **Working with bundles** → [API Reference](./API.md#bundle)
|
||||
- **Troubleshooting** → [Usage Guide](./GUIDE.md#troubleshooting)
|
||||
- **Code examples** → [Examples directory](../examples/)
|
||||
- **Advanced use cases** → [Usage Guide](./GUIDE.md#advanced-topics)
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- **[Examples](../examples/)** - Working code examples for various use cases
|
||||
- **[Main README](../README.md)** - Quick start and project overview
|
||||
- **[OSC Specification](http://opensoundcontrol.org/spec-1_0)** - Official OSC protocol documentation
|
||||
|
||||
## Contributing to Documentation
|
||||
|
||||
### Updating API Documentation
|
||||
|
||||
The API documentation is automatically generated from JSDoc comments:
|
||||
|
||||
1. Edit JSDoc comments in the source files (`lib/**/*.mjs`)
|
||||
2. Run `npm run docs` to regenerate `API.md`
|
||||
3. Review the changes and commit
|
||||
|
||||
### Updating the Usage Guide
|
||||
|
||||
The Usage Guide (`GUIDE.md`) is manually maintained. When editing:
|
||||
|
||||
- Keep it focused on patterns, best practices, and how-to content
|
||||
- Avoid duplicating API details (link to API.md instead)
|
||||
- Include practical code examples
|
||||
- Update the table of contents if adding new sections
|
||||
|
||||
## Documentation Structure Philosophy
|
||||
|
||||
Our documentation is organized to minimize duplication while maximizing usefulness:
|
||||
|
||||
- **README.md** (main) → Quick start, basic examples, installation
|
||||
- **API.md** → Complete API reference with all technical details
|
||||
- **GUIDE.md** → How to use the library effectively, patterns, and troubleshooting
|
||||
- **examples/** → Working code you can run and learn from
|
||||
|
||||
This structure ensures you can find what you need without reading through repeated content.
|
||||
Reference in New Issue
Block a user