npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

simple-osc-lib

v1.1.3

Published

Simple to use modern Open Sound Control implementation

Downloads

27

Readme

simple-osc-lib

GitHub package.json version GitHub Actions Workflow Status Coverage

This package provides some node.js utilities for working with OSC, a format for sound and systems control.

Here we implement the OSC 1.1 specification. OSC is a transport-independent protocol, so we don't provide any server objects, as you should be able to use OSC over any transport you like. The most common is probably udp, but tcp is not unheard of.

This package was heavily influenced by the osc-min API

Differences from osc-min

  • no support for the message translation stuff
  • no support for parameter guessing in oscBuildMessage() or oscBuildBundle()
  • added c and r data types
  • zero-dependency package

Input types

  • s :: string - string value (String padded to 32 bit block with nulls)
  • f :: float - numeric value (FloatBE - 32 bits)
  • d :: double - numeric value (DoubleBE - 64 bits)
  • i :: integer - numeric value (Int32BE - 32 bits)
  • b :: blob - node.js Buffer value (Buffer padded to 32 bit block with nulls)
  • T :: true - no value (0 bits)
  • F :: false - no value (0 bits)
  • N :: null - no value (0 bits)
  • I :: bang - no value (0 bits)
  • r :: color - rgbA as an array [R(0-255),G,B,A] (4 x UInt8 - 32 bits)
  • c :: char - Character (Int32BE - 32 bits)
  • t :: timetag - numeric value (pair of UInt32BE - 64 bits)
  • A :: address - non-stander string value, with special processing to ensure a valid osc address string (String padded to 32 bit block with nulls)

Note that type is always a string - i.e. "true" rather than true.

Standard Usage

Options

  • asciiOnly false Prevent non-ASCII characters in strings
  • blockCharacter "¦" Character to delineate 4-byte blocks in debug output (or '')
  • coerceStrings false For string type, coerce input if non-string found.
  • debugCharacter "•", Character to replace nulls in debug output
  • preprocessor <function> osc-message processor
  • strictAddress false Require leading slash (address is always asciiOnly)
  • strictMode false Use strict mode elsewhere
const osc     = require('simple-osc-lib')

const oscRegular = new osc.simpleOscLib( /* options */)

Build an OSC Single Message Buffer for sending

const buffer = oscRegular.buildMessage({
    address : '/hello',
    args    : [
        { type : 'string', value : 'hi' },
        { type : 'string', value : 'there' },
    ],
})

Build an OSC Bundle Buffer for sending

const oscMessage1 = { address : '/hello', args : [...] }
const oscMessage2 = { address : '/goodbye', args : [...] }

// Generate a timetag half a second into the future
const timeTag = oscRegular.getTimeTagBufferFromDelta(0.5)

const buffer = oscRegular.buildBundle({
    timetag : timeTag,
    elements : [oscMessage1, oscMessage2],
})

Decode an OSC Packet from receiving

const oscMessage = oscRegular.readPacket(buffer)

Single message

{
    type    : osc-message,
    address : /goodbye,
    args: [
        { type : 'string', value : 'cruel' },
        { type : 'string', value : 'world' }
    ]
}

Bundle (note that bundles can be nested)

{
    type     : 'osc-bundle',
    timetag  : [ /* date Object */ ],
    elements : [ /* zero or more osc-messages or osc-bundles */ ]
}

Return arguments

The type list above gives the text representation of what will appear in the type field of the osc-message. Additionally, arrays will be nested as such

{
    type    : osc-message,
    address : /goodbye,
    args: [
        { type : 'array',  value : [
            { type : 'string', value : 'cruel' },
            { type : 'string', value : 'world' },
        ]},
    ]
}

timetag Processing of Bundles

This package provides no pre-processing for timetags - they are returned as found, in all circumstances. The OSC 1.1 spec does not clarify the proper handling of timetags in the past, as different implementations do different things with them. A timetag in the past may mean the bundle should be discarded, or it may mean it should be acted on immediately - this behavior is left to your preference. Please do not assume a received timetag refers to a future event.

Overriding default options

Options are set when initializing the class - they can be accessed or changed at any time by accessing the options key.

  • asciiOnly - Limit strings to ASCII characters.
  • blockCharacter - Character to delineate 4-byte blocks in debug output (or '')
  • debugCharacter - Character to replace NULLs in debug output.
  • preprocessor - osc-message processor, take a single argument of an osc-message. Only run on individual messages.
  • strictAddress - Use strict address mode (all string rules, must begin with slash).
  • strictMode - Use strict mode.

By default, no strict mode options are enabled.

The preprocessor can be used as a callback for each message received. See section below for an example

"The code is more what you'd call 'guidelines' than actual rules." --– Barbossa, Pirates of the Caribbean

Exported Functions and Data Structures

Modules

simple-osc-lib

Simple OSC communication for nodeJS

simple-osc-lib~simpleOscLib

Kind: inner class of simple-osc-lib

new simpleOscLib(options)

| Param | Type | Description | | --- | --- | --- | | options | object | simple-osc-lib options. | | options.asciiOnly | Boolean | Limit strings to ASCII characters. | | options.blockCharacter | String | Character to delineate 4-byte blocks in debug output (or '') | | options.debugCharacter | String | Character to replace NULLs in debug output. | | options.preprocessor | String | osc-message processor | | options.strictAddress | Boolean | Use strict address mode (all string rules, must begin with slash). | | options.strictMode | Boolean | Use strict mode. |

simpleOscLib.encodeBufferChunk(type, value) ⇒ Buffer

Encode an OSC Data chunk - low level function

Kind: instance method of simpleOscLib
Returns: Buffer - buffer padded to 32-bit blocks with NULLs

| Param | Type | Description | | --- | --- | --- | | type | String | OSC Data type string/char | | value | * | Value for data (must be null for null types) |

simpleOscLib.decodeBufferChunk(type, buffer_in) ⇒ Object

Decode an OSC Data chunk - low level function

Kind: instance method of simpleOscLib
Returns: Object - Contains the type, value, and unused portion of the buffer

| Param | Type | Description | | --- | --- | --- | | type | String | OSC Data type | | buffer_in | Buffer | buffer padded to 32-bit blocks with NULLs |

simpleOscLib.getDateFromTimeTagArray(timetag) ⇒ Date

Get a date object from a timetag array

Kind: instance method of simpleOscLib

| Param | Type | Description | | --- | --- | --- | | timetag | Array | 2 element array for a timetag [unix seconds, fractional seconds] |

simpleOscLib.getTypeStringFromChar(type) ⇒ String

Resolve a character type into the human readable name

Kind: instance method of simpleOscLib

| Param | Type | Description | | --- | --- | --- | | type | String | single character type |

simpleOscLib.getTypeCharFromStringOrChar(type) ⇒ String

Resolve a type from a character or string with error checking

Kind: instance method of simpleOscLib

| Param | Type | Description | | --- | --- | --- | | type | String | character type string or single character |

simpleOscLib.getTimeTagBufferFromTimestamp(number) ⇒ Buffer

Generate a timetag buffer from a timestamp

Kind: instance method of simpleOscLib
Returns: Buffer - 8 byte / 32 bit buffer

| Param | Type | Description | | --- | --- | --- | | number | Number | timestamp (from epoch) |

simpleOscLib.getTimeTagBufferFromDate(date) ⇒ Buffer

Generate a timetag buffer from a date instance

Kind: instance method of simpleOscLib
Returns: Buffer - 8 byte / 32 bit buffer

| Param | Type | Description | | --- | --- | --- | | date | Date | javascript date instance |

simpleOscLib.getTimeTagBufferFromDelta(seconds, now) ⇒ Buffer

Generate a timetag buffer for [seconds] in the future

Kind: instance method of simpleOscLib
Returns: Buffer - 8 byte / 32 bit buffer

| Param | Type | Default | Description | | --- | --- | --- | --- | | seconds | Number | | seconds in the future | | now | Number | null | | point to calculate from (in ms!!) |

simpleOscLib.printableBuffer(buffer_in, rep_char, blockChar) ⇒ String

Format a buffer for console.log()

Kind: instance method of simpleOscLib

| Param | Type | Description | | --- | --- | --- | | buffer_in | Buffer | buffer | | rep_char | String | Character to replace nulls in buffer | | blockChar | String | Character to delineate 4-byte blocks in buffer (or '') |

simpleOscLib.buildMessage(oscMessageObject) ⇒ Buffer

Build an OSC message buffer

address is a required key, containing the destination address

args is an array of objects of { type : 'type', value : value }

Kind: instance method of simpleOscLib
Returns: Buffer - 4 byte chunked buffer

| Param | Type | Description | | --- | --- | --- | | oscMessageObject | object | osc message object |

simpleOscLib.buildBundle(oscBundleObject) ⇒ Buffer

Build an OSC bundle buffer

timetag is a required key, containing a timetag buffer

elements can contain objects to be passed to oscBuildMessage or pre-prepared buffers padded to 32-bit blocks with NULLs

Kind: instance method of simpleOscLib
Returns: Buffer - 4 byte chunked buffer

| Param | Type | Description | | --- | --- | --- | | oscBundleObject | object | osc bundle object |

simpleOscLib.readPacket(buffer_in) ⇒ Object

Decode an OSC packet. Useful for when the client might send bundles or messages

Kind: instance method of simpleOscLib
Returns: Object - osc-bundle object or osc-message object

| Param | Type | Description | | --- | --- | --- | | buffer_in | Buffer | buffer padded to 32-bit blocks with NULLs |

simpleOscLib.readBundle(buffer_in) ⇒ Object

Decode an OSC bundle

Kind: instance method of simpleOscLib
Returns: Object - osc-bundle object

| Param | Type | Description | | --- | --- | --- | | buffer_in | Buffer | buffer padded to 32-bit blocks with NULLs |

simpleOscLib.readMessage(buffer_in, options) ⇒ Object

Decode a single OSC message.

Kind: instance method of simpleOscLib
Returns: Object - osc-message object

| Param | Type | Description | | --- | --- | --- | | buffer_in | Buffer | buffer padded to 32-bit blocks with NULLs | | options | Object | options | | options.strictMode | Object | use strict mode | | options.messageCallback | Object | callback to run on each message |

simpleOscLib.redirectMessage(buffer_in, newAddress, callBack) ⇒

Readdress an existing message, including the old address as the first or last string argument

Callback details

The callback takes a function that receives the following parameters

  • newAddressBuffer new destination
  • oldAddressBuffer original address as a string buffer
  • argumentList original argument list
  • argumentBuffer existing argument buffer.

This should return a valid osc buffer. To simply redirect the existing to a new address you could do something like

function redirectCallback(newAddressBuffer, _oldAddressBuffer, argumentList, argumentBuffer) {
    return Buffer.concat([
        newAddressBuffer,
        oscLibInstance.encodeToBuffer('s', `,${argumentList.join('')}`),
        argumentBuffer
    ])
}

Kind: instance method of simpleOscLib
Returns: Buffer

| Param | Type | Description | | --- | --- | --- | | buffer_in | Buffer | original message buffer | | newAddress | String | address for the new message | | callBack | function | callback to apply - must return a buffer |

simpleOscLib.messageBuilder(address) ⇒

Build an osc message in a chainable way.

Chainable methods available - for more complex messages, use buildMessage

myMessage
    .i(20)
    .integer(20)
    .f(1.0)
    .float(1.0)
    .s('hello')
    .string('world')
    .b(buffer)
    .blob(buffer)

To get a transmittable buffer, call myMessage.toBuffer()

To get a human readable version of the buffer, call myMessage.toString()

Kind: instance method of simpleOscLib
Returns: oscBuilder instance

| Param | Type | Description | | --- | --- | --- | | address | String | address to send to |

Example

const myBuffer = oscLib.messageBuilder('/hello').integer(10).float(2.0).string('world').toBuffer()

simple-osc-lib/x32

Extended processing for Behringer X32/M32 consoles. This provides some override and pre-processing tools to make it easier to work with the style of OSC messages the Behringer uses.

simple-osc-lib/x32~x32PreProcessor

Kind: inner class of simple-osc-lib/x32

new x32PreProcessor(options)

| Param | Type | Description | | --- | --- | --- | | options | object | x32 Preprocessor options. | | options.activeNodeTypes | Boolean | Active node message preprocessors from lib/x32_preprocessors (or 'all') | | options.activeRegularTypes | String | Active regular message preprocessors from lib/x32_preprocessors (or 'all') |

x32PreProcessor.readMessage(oscMessage) ⇒ Object

This is the processor for X32 style messages

Kind: instance method of x32PreProcessor
Returns: Object - an OSC message object with additional data

| Param | Type | Description | | --- | --- | --- | | oscMessage | Object | an OSC message object |

Example

const osc     = require('simple-osc-lib')
const osc_x32 = require('simple-osc-lib/x32')

const x32Pre = new osc_x32.x32PreProcessor('all')
// or a list of types or wildcards.
//  + dca*, bus*, mtx*, main*, mono*, show*, aux*, chan*
//  + dcaLevel, dcaName, dcaMix, dcaMute etc.
// see source for full listing.

const oscRegular = new osc.simpleOscLib({
    preprocessor : (msg) => x32Pre.readMessage(msg),
})

simple-osc-lib/x32~dB2Float ⇒ Number

Convert a string or number decibel representation to a floating point number

Kind: inner constant of simple-osc-lib/x32
Returns: Number - floating point representation of decibel level 0->1

| Param | Type | Description | | --- | --- | --- | | db_in | String | Number | string or float representation of decibel level +10->-90 |

simple-osc-lib/x32~float2dB ⇒ String

Convert floating point 0->1 to decibel level

Kind: inner constant of simple-osc-lib/x32
Returns: String - text level [+/-##.# dB]

| Param | Type | Description | | --- | --- | --- | | f | Number | 0->1 floating point level |

X32 Pre-Processing

The X32 version of the oscMessage processor adds some additional data, found in the props key.

Additionally the wasProcessed will be set true if the message was covered.

The following example enables all current X32 extra processing - if you are only interesting in a subset you can set to only process what you care about.

Example

const osc     = require('simple-osc-lib')
const osc_x32 = require('simple-osc-lib/x32') // X32 specific processing (optional)

// 'all', or a single entry 'dca*', or an array of entries ['dca*', 'bus*', 'show*']
// see source file for full listing
const x32Pre = new osc_x32.x32PreProcessor('all')

const oscRegular = new osc.simpleOscLib({
    preprocessor : (msg) => x32Pre.readMessage(msg),
})

Standard OSC Messages by subtype

  • showCurrent :: /-show/prepos/current
  • showMode :: /-prefs/show_control
  • auxLevel :: /auxin/[##]/mix/fader
  • auxMute :: /auxin/[##]/mix/on
  • auxName :: /auxin/[##]/config/name
  • busLevel :: /bus/[##]/mix/fader
  • busMute :: /bus/[##]/mix/on
  • busName :: /bus/[##]/config/name
  • chanLevel :: /ch/[##]/mix/fader
  • chanMute :: /ch/[##]/mix/on
  • chanName :: /ch/[##]/config/name
  • dcaLevel :: /dca/[#]/fader
  • dcaMute :: /dca/[#]/on
  • dcaName :: /dca/[#]/config/name
  • mainLevel :: /main/st/mix/fader
  • mainMute :: /main/st/mix/on
  • mainName :: /main/st/config/name
  • monoLevel :: /main/m/mix/fader
  • monoMute :: /main/m/mix/on
  • monoName :: /main/m/config/name
  • mtxLevel :: /mtx/[##]/mix/fader
  • mtxMute :: /mtx/[##]/mix/on
  • mtxName :: /mtx/[##]/config/name
  • showCueDirty :: /-show/showfile/cue/[#]{3}//
  • showSceneDirty :: /-show/showfile/scene/[#]{3}/name
  • showSnippetDirty :: /-show/showfile/snippet/[#]{3}/name

node OSC Messages by subtype

  • auxMix :: node /auxin/[##]/mix
  • auxName :: node /auxin/[##]/config
  • busMix :: node /bus/[##]/mix
  • busName :: node /bus/[##]/config
  • dcaMix :: node /dca/[#]
  • dcaName :: node /dca/[#]/config
  • chanMix :: node /ch/[##]/mix
  • chanName :: node /ch/[##]/config
  • mtxMix :: node /mtx/[##]/mix
  • mtxName :: node /mtx/[##]/config
  • mainMix :: node /main/st/mix
  • mainName :: node /main/st/config
  • monoMix :: node /main/m/mix
  • monoName :: node /main/m/config
  • showCurrent :: node /-show/prepos/current
  • showMode :: node /-prefs/show_control
  • showName :: node /-show/showfile/show
  • showCue :: node /-show/showfile/cue/[###]
  • showScene :: node /-show/showfile/scene/[###]
  • showSnippet :: node /-show/showfile/snippet/[###]

Example Post-Process - Faders

These items will exist in the returned osc-message under the props key. The props.subtype rule will be the name of the operation matched.

const all = {
    index   : 1, 
    subtype : 'someLevel', // operation name
    zIndex : '01', // fader text index, 1-8 for dca, 01-?? for all else
}

const someLevel = {
    ...all,
    level   : {
        float : 0.75,
        db    : '0 dB',
    },
}

const someMute = {
    ..all,
    isOn    : {
        bool : false,
        int  : 0,
        text : 'OFF',
    }
}

const someName = {
    ...all,
    name : 'NAME',
}

const someMix = {
    ...all,
    ...someMute,
    ...someLevel,
}

Example Post-Process - Show Control

These items will exist in the returned osc-message under the props key. The props.subtype rule will be the name of the operation matched.


const showMode = {
    index   : 0,
    name    : 'CUES',
}

const showCue = {
    cueNumber  : '1.0.0',
    cueScene   : -1,
    cueSkip    : false,
    cueSnippet : -1,
    index      : 1,
    name       : 'Cue Name',
}

const showScene = {
    index      : 1,
    name       : 'Scene Name',
    note       : 'Scene Note',
}

const showSnippet = {
    index      : 1,
    name       : 'Snippet Name',
},

// showCueDirty, showSceneDirty and showSnippetDirty
// all have empty properties.

OSC Redirection

You can use the redirectMessage() function to redirect OSC messages without processing the arguments. This is particularly useful if you need to deal with unknown types. By default, the original address is included as the first argument of type string

const newBuffer = oscLib.redirectMessage(originalBuffer, '/newTown')

It also takes a callback - this example rewrites the first argument, an integer to be the square of that integer, and includes the original address as a second argument. Any additional original arguments would be discarded. Not included in this sample is error checking

// square the first argument which is an integer, add the address to the end
function redirectCallback (bufferNewAddress, bufferOldAddress, argList, argBuffer) {
    // Arguments:
    //  - bufferNewAddress is an 4-byte padded buffer from the address you provided
    //                     with all of the usual error checking.
    //
    //  - bufferOldAddress is a 4-byte padded buffer from the original address.
    //
    //                     Note: this is re-encoded from text, so the usual error checking
    //                     on the original address will take place.  If for some reason
    //                     you need this to not occur, consider using the low-level
    //                     functions directly.
    //
    //  - argList          is an Array of the original argument list.  It is not checked for
    //                     array nesting errors *or* valid type definitions. The leading comma
    //                     from the input buffer is stripped, but in strict mode a lack of that
    //                     comma will throw an error.
    //
    //  - argBuffer        the original unaltered argument buffer. In practice, this is the 
    //                     message packet minus `bufferOldAddress` and a 4-byte padded buffer from
    //                     the original argument list.


    // really, we should check that the first item of argList is "i", the integer
    // type, and run catch blocks on both this decodeBufferChunk() and the
    // below encodeBufferChunk()

    const firstArgument = oscLib.decodeBufferChunk('i', argBuffer)


    // return a valid OSC buffer.  simple-osc-lib does not look at this value
    // during the redirectMessage process, so you could fail to return a buffer
    // or return nothing at all.
    //
    // This function could potentially be used for out-of-band processing to read
    // and act on message packets that simple-osc-lib doesn't understand, or you
    // wish to handle yourself.

    return Buffer.concat([
        bufferNewAddress,
        oscLib.encodeBufferChunk('s', ',is'),
        oscLib.encodeBufferChunk('i', firstArgument.value * firstArgument.value),
        bufferOldAddress
    ])
}

const newBuffer = oscLib.redirectMessage(originalBuffer, '/newTown', redirectCallback)

This function could potentially be used for out-of-band processing to read and act on message packets that simple-osc-lib doesn't understand, or you wish to handle yourself - although it does do error checking on the original address. For help in handling the message completely on your own, you will need to look at .decodeBufferChunk() and .encodeBufferChunk()

© 2024 J.T.Sage - ISC License