Announcing monome-rs 1.0

in

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.

Grid & Arc

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;

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;

for 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.);

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;

, 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 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;

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 ;

(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 ; 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;

on all platforms (using tokio), and (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);

(related to the fact that rosc that I use for encoding and decoding the OSC protocol uses 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;

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.);

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.