Overview
Messages and bundles
An OpenSoundControl message is an address and some values: /freq 440.
A bundle is a list of messages and bundles. Everything here is one or
the other: a value is a message, a program is a bundle, a function is a
bundle stored under a name, and so is the machine that runs them.
In OSC a bundle’s elements have no names, so a bundle with a name is a
message whose payload holds the bundle as a blob, and the message
carries the address. That is what a register is, and why
/_s is an address. The same shape has a typetag of its own inside a
message, |, a bundle laid out like a blob.
The machine and its registers
The machine keeps its state in registers — bundles with names, inside the machine’s own bundle:
- the stack,
/_s: operands and results - the environment,
/_e: the names a program has bound - the control,
/_c: the instructions running now - the dump,
/_d: saved contexts, for returning from a call - the input,
/_i: what is waiting to run - the host register,
/_x: what the host bound — its capabilities, as addresses
Because every register is a bundle, the whole machine is one valid OSC bundle at every moment; nothing is serialised on the way out because nothing was ever in another form. Hosts and modules can add registers of their own. The registers has the naming rule and how an address’s first segment selects one; the C reference’s machine page has the run loop.
Two languages
osen is the language people write; the machine runs ose, its
instruction language, one message per instruction, and osen is a module
that turns source into it. Every host runs both. Side by side:
ose |
osen | |
|---|---|---|
| what it is | the machine’s instruction language | the language people write |
| made of | OSC messages, one per instruction | OSC bundles with a syntax |
| bind a name | /@ |
: |
| read a name | /$ |
the bare name |
| call | /! before an address |
(args) /o/fn |
| comment | /#/ |
# |
| separator | one message per element | , — a newline is whitespace |
| files | .ose |
.osen |
The same thing, twice. Binding 10 to /foo and reading it back, in
ose — three instructions, each an OSC message:
/,/i/10 push the integer 10
/@/foo assign it to /foo
/$/foo look /foo up again
and in osen:
/foo : 10,
/foo → : 10
The osen form is not shorthand for the other. It is source text that the
osen module turns into a bundle, which the machine then runs; /foo : 10
never becomes an instruction, it becomes a bundle. An analogy that fits:
ose is to osen roughly as assembly is to C. Everyone porting the machine
needs the instruction set written down; almost nobody writing programs
looks at it.
Addresses are the interface
A host binds what it can do — pins and WiFi, WebAudio, inlets and outlets, Python functions, UDP and files — into its host register as addresses. A program calls a capability on another host the way it calls one on its own. What each host binds: command line, Max, browser, microcontroller, Python.
What travels
A program is a bundle of messages the machine has not run yet. A running machine is a bundle holding its registers, the unrun program among them. Either can be sent. A program that arrives is run there; a machine that arrives continues where it was, and finds the far host’s capabilities in that host’s own host register, which stays where it is. How each host takes what you send, and what carries it: Between hosts.
The layers
A host is a program with the machine inside it, through the kit; a module is a library the host loads or links in, and what it provides lands in the machine as addresses.