I’m happy to announce the release of monome-rs
1.0, the first stable version
of a Rust crate (the idiomatic name for a Rust library)
that aims at easing the use of monome devices in this
language.
monome devices are beautiful control devices that don’t do anything in themselves, but that one can use and program with in order to do anything. Often they are used to do live music performances.
The crate is feature complete, and has the following features:
- Enumerating monome devices plugged to a host, and connecting to multiple devices (of different or the same type) on the same host;
- Using standard and custom port for
serialosc
the daemon that is usually running manages those devices; - Receiving plug/unplug events to dynamically recover from difficult situations (someone unplugging your device when playing live, etc.);
- All the standard OSC methods, with an API that
is a tad higher level sometimes. For example, there is a method to set all the
LEDs on a grid, appropriately converted to
map
calls using bitmask if they are not setting intensity and are just on/off, to help save a bit of bandwidth; - Support for arc and grid of various sizes (64, 128, 256, two or four encoders), tilt sensors, encoder presses;
- Portable on all OSes and architecture (Windows/Linux/Mac, ARM, x86,
x86_64, probably more, but this is what I tested), including the Bela
platform, which I’m using for a project that uses
monome-rs
; - It uses asynchronous and event-driven networking on all platforms (using tokio), and lock-free message queues (using crossbeam) for optimum and predictable performances in soft or hard real-time environment;
- A minimal number of dynamic allocations (related to the fact that
rosc that I use for encoding and decoding
the OSC protocol uses
Vec
in its API. The allocators appears in the profile with a low single digit figure); - Complete documentation for every little attribute or method of the API;
- A variety of examples for various devices and features (tilt sensors, device enumeration, arc, grid, etc.);
- Continuous integration and some unit tests (with and without device, so that it can run on travis containers.
Rust is very good for this kind of work. Using Tokio for network input/output
was a bit strange at first (most people that I met who also tried Tokio had the
same initial reaction), but was in fact very flexible and easy to use once I got
hold of a couple concepts. Using Crossbeam to have a good lock-free queue (to
avoid blocking the user threads) instead of the default channel()
allowed to
have even more reliable performances in real-time scenario, and this was very
easy to use (for the user, it’s just a lock-free queue after all).
I’ve written a few programs in Rust that use this library while developing it. Some run on desktop OSes (without a single code change or configuration between different targets) but also on the Bela platform, which is a Beaglebone black with a special shield on top that runs a real-time Xenomai kernel and allows for easy high performance low-latency embedded audio programming.
Performance is very good and predictable, which is important for real-time
interactive music applications. I’ve written an mlr
clone in Rust running with very low
latency audio callback on my Macbook Pro 15”
2016 that uses less than 3%
CPU total (and this number is very stable), while polling for inputs and
updating the 128 leds of my monome grid at 100Hz. Admittedly, the DSP complexity
of this program isn’t very high but it’s a real project updating every LED on
the device at a good refresh rate, which hints at the fact that a low single
digit percent is a good ballpark figure for the highest CPU usage this library
will use, leaving ample room for real computations (DSP code, other devices,
GUI, etc.).
Like most libraries in the Rust ecosystem, it is dual-licensed under Apache 2 and MIT, and the sources are available on GitHub, but Rust programmers probably want to simply add:
[dependencies]
monome-rs="1.0"
to their Cargo.toml
, and start using it, after having read the docs at
https://docs.rs/monome-rs.
I welcome any kind of feedback or contribution. Feel free to send patch or open issues on GitHub: https://github.com/padenot/monome-rs. It’s feature complete (I think?), but I’ll keep maintaining it for the foreseeable future, since I’m using it (both on desktop and Bela) in my other projects.
Directly attacking the monome serial protocol will probably happen later, when I’ll start experimenting with smaller SOCs (such as the famous STM32) that don’t run Linux, I’ll probably implement the serial protocol as a separate library with more or less the same API.