Command line tools for working with Open Sound Control, built on liblo.
| tool | what it does |
|---|---|
| osctool | interactive and scriptable OSC test tool |
-
Install from a release (recommended)
This is the fastest way and needs no compiler. Pre-built binaries for macOS
and Linux are published on the Releases page. Each release is a .tar.gz that is statically linked against a pinned liblo and contains the osctool binary plus its man page.
Follow these steps top to bottom. Nothing else is required.
-
Download the archive for your platform from the Releases page into any directory, for example your Downloads folder.
-
Unpack it and enter the extracted directory:
tar xzf osctool-*.tar.gz cd osctool-*/
-
Confirm the binary runs. This prints the version and exits:
./osctool -V
-
Install the binary and man page under
/usr/local:sudo install -d /usr/local/bin /usr/local/share/man/man1 sudo install -m 755 osctool /usr/local/bin/osctool sudo install -m 644 man/osctool.1 /usr/local/share/man/man1/osctool.1
-
Verify it is on your PATH:
osctool -V man osctool
You are done. Jump to Using osctool.
Pick exactly one of the six guides below. Each one is complete and
self-contained: it lists every prerequisite, clones the repository, builds,
and installs, ending with sudo make install. There is nothing to jump back
and forth for.
Two flavours are offered per platform:
- Package manager liblo is quick and uses the liblo already packaged for your system.
- Vendored liblo builds a pinned copy of liblo from source for a fully reproducible static binary, independent of whatever is installed. This is how the release binaries are built. It is slower and needs a few extra autotools packages.
# 1. Compiler, make, git. Skip if `xcode-select -p` already prints a path.
xcode-select --install
# 2. Homebrew. Skip if `brew --version` already works.
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 3. Dependencies.
brew install liblo pkg-config
# 4. Clone.
git clone https://github.com/huddx01/osctools.git
cd osctools
# 5. Build.
make
# 6. Install.
sudo make installDNS-SD is part of macOS, so device discovery is always available.
# 1. Compiler, make, git. Skip if `xcode-select -p` already prints a path.
xcode-select --install
# 2. Homebrew. Skip if `brew --version` already works.
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 3. Build dependencies (no liblo, it is built from source below).
brew install pkg-config autoconf automake libtool
# 4. Clone and pull in the pinned liblo submodule.
git clone https://github.com/huddx01/osctools.git
cd osctools
git submodule update --init vendor/liblo
# 5. Build against the vendored liblo.
make STATIC=1 VENDORED=1
# 6. Install.
sudo make installDNS-SD is part of macOS, so device discovery is always available.
To package a redistributable universal (arm64 + x86_64) tarball instead of
installing, run make dist in place of steps 5 and 6.
# 1. Toolchain and liblo.
sudo apt update
sudo apt install -y git build-essential pkg-config liblo-dev
# 2. Optional. Enables mdns (bonjour) discovery.
sudo apt install -y libavahi-compat-libdnssd-dev
# 3. Clone.
git clone https://github.com/huddx01/osctools.git
cd osctools
# 4. Build.
make
# 5. Install.
sudo make installDiscovery on Linux goes through Avahi's Bonjour compatibility layer. If the
optional package in step 2 is absent, the build simply leaves discovery out
and says so when a bonjour command is used.
# 1. Toolchain and autotools (no liblo, it is built from source below).
sudo apt update
sudo apt install -y git build-essential pkg-config autoconf automake libtool
# 2. Optional. Enables mdns (bonjour) discovery.
sudo apt install -y libavahi-compat-libdnssd-dev
# 3. Clone and pull in the pinned liblo submodule.
git clone https://github.com/huddx01/osctools.git
cd osctools
git submodule update --init vendor/liblo
# 4. Build against the vendored liblo.
make STATIC=1 VENDORED=1
# 5. Install.
sudo make install# 1. Toolchain and liblo.
sudo dnf install -y git gcc make pkgconf-pkg-config liblo-devel
# 2. Optional. Enables mdns (bonjour) discovery.
sudo dnf install -y avahi-compat-libdns_sd-devel
# 3. Clone.
git clone https://github.com/huddx01/osctools.git
cd osctools
# 4. Build.
make
# 5. Install.
sudo make installDiscovery on Linux goes through Avahi's Bonjour compatibility layer. If the
optional package in step 2 is absent, the build simply leaves discovery out
and says so when a bonjour command is used.
# 1. Toolchain and autotools (no liblo, it is built from source below).
sudo dnf install -y git gcc make pkgconf-pkg-config autoconf automake libtool
# 2. Optional. Enables mdns (bonjour) discovery.
sudo dnf install -y avahi-compat-libdns_sd-devel
# 3. Clone and pull in the pinned liblo submodule.
git clone https://github.com/huddx01/osctools.git
cd osctools
git submodule update --init vendor/liblo
# 4. Build against the vendored liblo.
make STATIC=1 VENDORED=1
# 5. Install.
sudo make installThese flags can be passed to make:
make STATIC=1 # link liblo statically
make DNSSD=0 # build without discovery even if available
make DNSSD=1 # force discovery on
make STATIC=1 FULLSTATIC=1 DNSSD=0 # no shared dependencies at all (Linux)
make STATIC=1 VENDORED=1 # link liblo statically, built from vendor/liblo
sudo make install # binaries and man pages install
make dist # package a redistributable tarball
make distclean # clean, and also remove the vendored liblo buildSTATIC=1 links liblo in and leaves everything else dynamic, on every
platform. On Linux, FULLSTATIC=1 additionally passes -static for a
binary with no shared libraries at all. That rules out discovery, because
Avahi's compatibility layer reaches the avahi daemon over D-Bus and needs
the shared stack at runtime, so combine it with DNSSD=0. The Makefile
warns if you do not.
make dist always vendors and, on macOS, builds a universal (arm64 +
x86_64) binary regardless of the host architecture. The resulting tarball
includes LICENSE, liblo's own COPYING, and a generated NOTICE
recording exactly which liblo commit was linked in and how.
An interactive and scriptable OSC test utility for bringing up and debugging OSC-controlled devices: watch what a device emits, learn its address map, drive its parameters by hand or from a script, and measure how it responds.
- Interactive prompt with history, context-aware tab completion and live display of incoming messages — you can keep typing while traffic scrolls by
- The same command language at the prompt, on the command line and in scripts, so anything worked out interactively can be pasted into a script
- Learns a device's address map from live traffic and completes on it later, with or without the device present
- Nothing blocks: a two-second fader ramp still shows incoming messages and leaves the prompt usable
- Full OSC 1.0 type set, with types guessed from the values you type
- Record and replay traffic with original timing
- Several targets and listeners at once, changeable while running, each one enable-able on its own and bindable to a single interface
- Bonjour discovery: finds devices that announce themselves, and can announce osctool's own listener in turn
- Everything is remembered between runs, and reported at startup
osctool # interactive prompt
osctool send /1/volume1 0.75 # one shot, then exit
osctool -m -T -S # watch incoming, with time and sender
osctool -f soundcheck.osc # run a scriptDefaults: listen on port 9051, send to localhost:7051. Change with -l
and -t, or from the prompt with listen and target.
Types are guessed from the values, so most of the time you just write them:
send /1/mute 1 # -> i
send /1/volume1 f 0.75 # -> f
send /durec/play f 1 # -> f
send /x true false nil inf # -> T F N I
Be explicit with a type string or per value when needed:
send /x if 42 1.5
send /x i:42 f:1.5 s:if
A bare path is shorthand for send, so /1/mute 1 works too. Timed sends
run in the background:
sweep /output/1/faderlin 0 1 2s # ramp a fader over 2 seconds
repeat /ping -n 1000 -r 50 # 1000 messages at 50 Hz
jobs # what is running
stop 1 # cancel it
Point osctool at a device, let it talk, and every address it emits is recorded with its type string, message count and observed value range:
osctool -l 9001 -L -p mydevice -mLoad that map later and tab completion knows every address, with or without the device present:
osctool -p mydeviceprofile list # the profiles you have, with their sizes
profile load rme
addrs # what was learned, with types and ranges
stats # counts and msg/s per address, busiest first
osctool -m -T -S # timestamps and sender address
osctool -m -F '/level/*' # only these paths
osctool -m -j | jq . # one JSON object per messageFiltering affects the display only. Learning and recording still see everything.
record session.osc # capture with relative timestamps
record stop
play session.osc # replay with original timing
play session.osc 0.5 # at half speed
Where osctool sends and listens is a managed set, changeable while running and remembered between runs.
Every enabled target gets a copy of what you send, so one command can
drive several devices at once. Naming a target first narrows one command to
it — unambiguous, because an OSC address always starts with /:
send /1/mute 1 # every enabled target
send amp /1/mute 1 # only amp
sweep amp /output/1/faderlin 0 1 2s
target localhost:7001 desk # replace the set with one target
target add 192.168.1.9:7001 amp # add another
target # list them
target off amp # keep it, but stop sending to it
target on # re-enable everything
Listeners work the same way, and can be bound to a single interface or IP instead of everything:
listen 9001 # change the port while running
listen add 9002 en0 wifi # a second one, bound to en0, named "wifi"
listen add 9003 127.0.0.1 # loopback only
listen off wifi
listen # list them
Replies come back to the first enabled listener. A target can name a
different one with target via <target> <listener>.
Either kind can also be set from the command line, which replaces whatever the rc file held:
osctool -t device:7001 -l 9001 -b en0
osctool --no-rc ... # ignore and do not update the configDevices that announce themselves over Bonjour need no address typed at all.
osctool browses for _osc._udp at startup and reports what turns up:
bonjour list # what has been seen, numbered
bonjour add 2 # turn a discovery into a target
bonjour advertise # announce our own listener as _osc._udp
On macOS this costs nothing, DNS-SD is part of the system. On Linux it needs
avahi-compat-libdns_sd, and without it the feature is omitted at build time.
Everything except the learned addresses is kept in one file and restored on the next run: endpoints, display switches, filters, and which profile was in use.
config show # the settings, exactly as they are stored
config save # write now, rather than waiting for exit
config reload # discard changes made this session
config clear # back to defaults (not yet written)
config path # where all of this lives
Files live under $XDG_CONFIG_HOME/osctool/, defaulting to
~/.config/osctool/ on both macOS and Linux:
osctool.conf settings and endpoints
history command history
profiles/<name>.prof learned address maps
The config is written when osctool exits. --no-rc skips reading and
writing it entirely.
Sit between a controller and a device to see and reshape the traffic. A relay is a listener that forwards what it receives to the enabled targets:
osctool -l none -r 9000 -t device:7001 --prefix /dev -mrelay 9000 /dev # from the prompt
relay off
| up, down | previous and next command |
| tab | complete; press twice to list the candidates |
| ctrl-a, ctrl-e | start and end of line |
| ctrl-w | delete the previous word |
| ctrl-u, ctrl-k | delete to start of line, to end of line |
| ctrl-l | clear the screen |
| ctrl-c | abandon the current line |
| ctrl-d | quit |
Completion is context sensitive: commands and aliases at the start of a line, learned OSC paths after a command that takes an address.
osctool --help for a summary, help at the prompt for the commands, and
man osctool for the full manual.
src/common/ tool-agnostic modules (line editor, OSC values, profile, util)
src/osctool/ the osctool program
man/ manual pages
Every directory under src/ other than common/ is one program named after
that directory, and the Makefile picks it up automatically. Adding a tool
means creating a directory and dropping sources in.
Uses liblo by Steve Harris, Stephen Sinclair et al. licensed under the GNU Lesser General Public License version 2.1 or later.