OSC
The OSC screen is where you talk Open Sound Control (OSC 1.0) over UDP by hand. It has three parts:
- Sender: one message, typed arguments, sent when you press Enter.
- Monitor: listens on a port and decodes every packet that arrives.
- Signal generator: sends a value that follows a waveform, many times a second, and draws it.
Signal Lab encodes and decodes OSC itself. What it sends is what the Inspector shows, byte for byte.
Sending a message
- Open OSC.
- In Target host:port, enter the device's IP address or host name and its port, for example
127.0.0.1:9000orstage-mixer.local:9000. - In OSC address, enter the address the device listens for, for example
/mixer/fader/1. - Under Arguments, set each argument's type and value. Press + argument for another; ✕ removes one.
- Press Send, or Enter in any field of the sender.
The line under the buttons says what went out: the address, its size in bytes and the target. Sending the same message again counts up (×2, ×3…), so you can see that a repeated send did something. A failure is shown there instead, and in the console.
The target, address and arguments are kept when you switch screens and when you restart the app.
Fields
| Field | What | Default |
|---|---|---|
| Target host:port | IP:port or host:port of the receiver. An IPv6 address goes in brackets: [::1]:9000. A host name is looked up each time you send; when it has an IPv4 address, that one is used (so localhost reaches a receiver listening on 127.0.0.1), otherwise its IPv6 one. A target without a port is refused. | 127.0.0.1:9000 |
| OSC address | The OSC address, starting with /, parts separated by /. One without the leading / is refused before anything is sent. | /hello/avatar/1 |
| Arguments | Typed values after the address, in order. A message may have none. | one float, 1.0 |
Argument types
The type of each argument is part of the message (its type tag), so a device that expects a float may ignore an int with the same value.
| Type in the list | OSC tag | Value | How you enter it |
|---|---|---|---|
int | i | 32-bit signed integer | a whole number |
float | f | 32-bit floating point | a number, 0.75 |
str | s | text | any text, sent as UTF-8 |
bool | T / F | true or false | true or false from a list; carries no bytes, only the tag |
long | h | 64-bit signed integer | a whole number |
double | d | 64-bit floating point | a number |
nil | N | nothing | no value |
blob | b | bytes | not typed here: it appears, read-only and in hex, when you open a signal that has one |
A number field that does not hold a number sends 0.
TIP
An OSC true is the tag T, not the text "true". A device waiting for a bool silently ignores a string.
Bundles
The sender sends single messages, not bundles. When a bundle (#bundle) arrives, the monitor, the experiment waits and the emulators unpack it: each message inside it is handled on its own, and its time tag is ignored.
Watching a port
To see what a device or a show controller sends:
- In Bind address, enter the address and port to listen on.
0.0.0.0:9000(the default) listens on every network card;127.0.0.1:9000only on this machine. - Press Listen. The field locks while the monitor runs.
- Point the sender at this machine's IP address and that port.
Every packet becomes a row, newest at the top:
| Column | What |
|---|---|
| Time | When it arrived, to the millisecond |
| From | The sender's IP:port |
| Address | The OSC address, or (decode error) when the packet is not valid OSC |
| Args | The argument values; a blob shows as blob[n], nil as nil. For a packet that could not be decoded, why. |
A bundle gives one row per message. The list keeps the latest 300 rows; Clear empties it. Press Stop to close the port. The monitor is also a job in the console strip, so it can be stopped from there.
The monitor reads packets of up to 64 KiB. It decodes the tags i f s S b h d T F N I (S reads as text, I as nil); a packet with any other tag, or cut short, is shown as a decode error rather than dropped.
Turning a message into a wait
Each row has a ⇠ button, Wait for this. It adds a Wait for OSC step to the open experiment that listens on the monitor's Bind address for this address, with an "equals" rule for each text, whole-number and true/false argument — floats, blobs and nil get none — up to 16 rules. Its timeout is 2000 ms. The editor opens with the new step selected.
WARNING
Stop the monitor before you run that experiment. The run opens the same port itself, and two listeners cannot share it.
Driving a waveform
The Signal generator sends one message after another to one address, with a single argument whose value follows a waveform — a fader, a light level, a position. Use it to see how a device follows a moving value, or to load a receiver with a steady stream.
- Set Target host:port and Address. Both are checked when you press Start generator, as the sender checks them.
- Choose a Waveform, its Freq (Hz) and the Rate (pps).
- Set Min and Max, the range of the value.
- Press Start generator. It runs until you press Stop generator or stop its job in the console strip.
| Field | What | Default |
|---|---|---|
| Target host:port | IP:port or host:port of the receiver; a name is looked up once, when the generator starts | 127.0.0.1:9000 |
| Address | The address every message is sent to; it starts with / | /hello/lfo |
| Waveform | The shape of the value over time (below) | sine |
| Freq (Hz) | Cycles of the waveform per second | 1 |
| Rate (pps) | Messages per second, from 0.1 to 5000; a value outside is held to that range | 60 |
| Min, Max | The lowest and highest value. If Max is below Min, the value does not move. | 0, 1 |
| send as int | Round to the nearest whole number and send an int instead of a float | off |
| Waveform | What the value does in each cycle |
|---|---|
| sine | Swings smoothly between Min and Max, starting at the middle and rising |
| triangle | Rises from Min to Max, then falls back to Min, starting at Min |
| saw | A falling sawtooth: starts at Max, falls to Min, then jumps back to Max |
| ramp | A rising sawtooth: starts at Min, rises to Max, then jumps back to Min |
| square | Max for the first half, Min for the second |
| random | A new random value between Min and Max with every message; the frequency is not used |
| constant | Max, every time; the frequency is not used |
The scope
Beside the fields, the scope draws the value as it is sent: the latest 300 points, scaled to fit. Below it are the waveform, frequency and rate, and the last value sent. The scope is updated about 30 times a second however fast the generator sends, so at high rates it shows a sample of the messages, not each one.
If a send fails, the generator stops and the console says why.
In the Inspector
With capture armed (Arm capture in the Inspector), OSC traffic appears with the protocol osc:
| Source | What | Notes |
|---|---|---|
osc-send | Every message the sender, a library signal, an OSC message step or signallab send osc sends | A step that waits for a reply shows as experiment |
osc-monitor | Every packet the monitor receives | A bundle is summarised by its first message and +n more in bundle; a malformed packet has the verdict decode error: … |
osc-gen | The generator's messages | At most one every 100 ms is captured, with the verdict sampled; the next one after skipped messages adds how many were not drawn, as sampled · +5 not shown |
Each frame keeps the bytes it was built from. See Inspector.
Saving and reusing
- Save as a signal. Save… under the buttons keeps the message — target, address and arguments — in the signal library, in a folder you choose. From then on the sender is tied to that signal: Save (or Ctrl+S in the sender) updates it, Save as… makes a copy, and the chip beside them opens it in Signals. Fire it later from Signals or with Ctrl+K from any screen. See Signals.
- Add to an experiment. Add to experiment adds an OSC message step with the same target, address and arguments to the open experiment — right before End, or after the selected step — and opens it. While the experiment runs, nothing can be added; the console says so.
In experiments
| Step | What it does |
|---|---|
| OSC message | Sends one message. Its target, address and text arguments take {{templates}}. With wait for a reply it sends from a port of its own and waits there for the answer in the same step. Details |
| Wait for OSC | Waits for a message whose address matches a pattern and whose arguments pass the rules. Details |
| Emulator | An OSC device that answers by rules for the whole run. See Emulators. |
The OSC message step takes IP:port or host:port like the screen, and its address must start with /. A host name is looked up each time the step sends.
Address patterns
Wait for OSC, the reply of OSC message and the rules of an OSC emulator match addresses with OSC 1.0 patterns:
| Pattern | Matches |
|---|---|
* | any run of characters, also none |
? | exactly one character |
[0-9], [a-c] | one character from the set or range |
[!0-9] | one character not in the set |
{ping,pong} | one of the words |
Wildcards stay within one part between slashes: /cue/* matches /cue/7 but not /cue/7/go, and a pattern matches only an address with the same number of parts. Matching is case-sensitive. A pattern starts with /, has no empty part (//), no spaces, no # and no characters outside ASCII, and is at most 512 characters.
Argument rules compare argument number 0–63 with a value (equals, less than, contains, matches a regular expression and so on); a wait has at most 16. When a bundle arrives, the wait takes it if any message in it matches. See Data and templates for what a matched message gives the steps after it.
From the command line
signallab send osc sends one message as the sender does:
signallab send osc 127.0.0.1:9000 /cue/go f:0.75 s:main✔ sent /cue/go (24 bytes) → 127.0.0.1:9000Each argument is tag:value: i:3, f:0.5, d:1.5, h:64, s:text, b:de ad be ef (hex bytes), or T, F, N on their own. Without a tag, a whole number is i, a number with a decimal point is f, and anything else is s; write s:7 to send the text 7. The target is IP:port or host:port. It exits with 0 when the message went out, 1 when sending failed (a host name that does not resolve included), and 2 when an argument, the address or the target is invalid. signallab fire sends a saved signal. See Command line.
TIP
In Git Bash on Windows, an argument that starts with / is turned into a file path before signallab sees it. Run the command with MSYS_NO_PATHCONV=1 in front, or use PowerShell or cmd.
Problems
| What you see | Usual cause |
|---|---|
… is not a valid address on send | The target has no port, or is neither IP:port nor host:port. |
Cannot resolve … on send | The host name does not resolve on this machine. Check it, or use the IP address. |
OSC addresses start with / (…) | The address has no leading /. |
| The message is sent but the device does nothing | Wrong port or address; a different type than it expects (int instead of float, a text "true" instead of a bool). Watch it in the Inspector, or point the target at the monitor on this machine to see what goes out. |
… is already in use by another program on Listen | Another program — or a running experiment, emulator or a second monitor — has the port. |
… is not an address of this computer | The Bind address IP belongs to another machine. Use 0.0.0.0 or one of this machine's addresses. |
| Packets from other machines never arrive | On Windows, the firewall can keep them out: allow Signal Lab when the app offers it. Local traffic (127.0.0.1) is not affected. See Troubleshooting. |
| (decode error) rows | The sender is not speaking OSC 1.0 on that port, or uses a type tag Signal Lab does not decode. |
On a server, the screen works on the server's network: 127.0.0.1 is the server itself, and the monitor listens on the server's ports. See Server.
Every error message is listed in Error messages.