View Source OSCx.Message (OSCx v0.1.1)
A module and struct for manipulating and representing OSC messages.
The struct has two keys:
address:
representing the OSC address. Defaults to the root address of"/"
arguments:
an Elixir list of arguments. Defults to an empty list[]
.
The arguments list can include a range of values, such as:
- Integer, e.g.
1
- Float, e.g.
4.2
- String, e.g.
"Hello, world"
- Bitstring (binary), e.g.
<<10, 123, 34, 56>>
(encodes to an OSC Blob) - Atom, e.g.
:tremelo
(encodes to an OSC Symbol) %{midi: value}
(encodes the the 4-byte value to an OSC MIDI type)%{seconds: seconds, fraction: fraction}
or%{time: value}
wherevalue
is a 64-bit integer (encodes to an OSC Time tag)%{rgba: [r, g, b, a]}
(encodes to an RGBA colour wherer
,g
,b
anda
are all integers)- List, e.g.
[1, 2, 3]
(encodes to an OSC Array) true
which encodes to the OSC type: Truefalse
which encodes to the OSC type: Falsenil
or:null
which encodes to the OSC type: Null:impulse
which encodes to the OSC type: Impulse
The two main functions are:
encode/1
which takes an%OSCx.Message{}
struct and encodes it to the OSC message formatdecode/1
which takes an OSC message recieved (e.g. via UDP) and decodes it into an%OSCx.Message{}
struct.
To learn more about how this library encodes and decodes OSC data, see: Arguments and types.
Structure of OSC messages
OSC messages are made up of three parts:
- Address which represents the function you want to control starting with a forward slash e.g.
"/status"
- Tag type string: which lists the data types in the data payload, in the order they occur. Note that some older implementations of OSC may omit the OSC Type Tag string.
- Arguments: the data payload which could be any of the OSC types.
Creating a message
When you create a message, you only need to specify the address and the arguments like this:
iex> my_msg = %OSCx.Message{address: "/target/address", arguments: [1, 2.0, "string data"]}
The tag type string is automatically generated when the message is encoded:
# Encode the message above
iex> encoded_msg = my_msg |> OSCx.encode()
# Inspect the message to see how it is encoded
# The OSCx.Decoder.inspect() shows:
# - the character code of each byte
# - its printable utf8 value
# - underscore (_) is used to denote either a 0 value or padding
# - (D) is a non-printable data value
iex> encoded_msg |> OSCx.Decoder.inspect()
[
{0, ["47 '/'", "116 't'", "97 'a'", "114 'r'"]},
{1, ["103 'g'", "101 'e'", "116 't'", "47 '/'"]},
{2, ["97 'a'", "100 'd'", "100 'd'", "114 'r'"]},
{3, ["101 'e'", "115 's'", "115 's'", "0 (_)"]},
{4, ["44 ','", "105 'i'", "102 'f'", "115 's'"]},
{5, ["0 (_)", "0 (_)", "0 (_)", "0 (_)"]},
{6, ["0 (_)", "0 (_)", "0 (_)", "1 (D)"]},
{7, ["64 '@'", "0 (_)", "0 (_)", "0 (_)"]},
{8, ["115 's'", "116 't'", "114 'r'", "105 'i'"]},
{9, ["110 'n'", "103 'g'", "32 ' '", "100 'd'"]},
{10, ["97 'a'", "116 't'", "97 'a'", "0 (_)"]}
]
You can see on row number 4, the automatically encoded type string of ,ifs
which means integer, float and string which was created for the OSC message arguments of [1, 2.0, "string data"]
.
Transmitting and receiving messages
OSC messages are independent from any specific transport mechanism, and can be transmitted and receivied over a variety of networks, including Ethernet, Wi-Fi, and the Internet.
Using UDP
Even though OSC messages are transport mechanism agnostic, they are commonly sent and received using UDP sockets.
The Erlang :gen_utp
module can be used for this purpose. It provides the functions necessary for communicating with sockets using the UDP protocol.
Example
# IP or host and port number for the UDP connection
ip_address = '127.0.0.1' # This could be changed to named address, like 'localhost'
port_num = 57110 # In this example, this is the default port used by SuperCollider
# Open a port
{:ok, port} = :gen_udp.open(0, [:binary, {:active, true}])
# Encode the message
osc_message = %OSCx.Message{address: "/version", arguments: []} |> OSCx.encode()
# Send message
:gen_udp.send(port, ip_address, port_num, osc_message)
More information
See the OSC specification website at: https://opensoundcontrol.stanford.edu/index.html
Summary
Functions
Decodes a binary OSC message.
Encodes an %OSCx.Message{}
struct to an OSC binary message.
Convenience function for creating an %OSCx.Message{}
struct.
Functions
Decodes a binary OSC message.
Example
# Binary OSC message
iex> bin_msg = <<47, 115, 116, 97, 116, 117, 115, 0, 44, 0, 0, 0>>
<<47, 115, 116, 97, 116, 117, 115, 0, 44, 0, 0, 0>>
iex> decoded_msg = OSCx.Message.decode(bin_msg)
%OSCx.Message{address: "/status", arguments: []}
In practice, use OSCx.decode/1
instead which can accept messages or bundles.
Encodes an %OSCx.Message{}
struct to an OSC binary message.
This function takes a populated %OSCx.Message{}
struct as its first and only parameter.
It returns a binary message in the format:
<OSC address> followed by an <OSC type tag string> followed by <zero or more OSC arguments>.
In practice, use OSCx.encode/1
instead which can accept messages or bundles.
Example
iex> %OSCx.Message{address: "/status", arguments: []} |> OSCx.Message.encode()
<<47, 115, 116, 97, 116, 117, 115, 0, 44, 0, 0, 0>>
Convenience function for creating an %OSCx.Message{}
struct.
Optionally takes a keyword list as it's first parameter, recognising any of the following keys:
address:
the OSC adress string, for exampleaddress: "/synth/play_note"
arguments:
a list of arguments, for examplearguments: [440.5]
Example
iex> OSCx.Message.new(address: "/synth/play_chord", arguments: [440.0, 445.0, 450.0])
%OSCx.Message{
address: "/synth/play_chord",
arguments: [440.0, 445.0, 450.0],
}