arc4all laptop lua arc scripting v0.1


script laptop and arc integration using lua

I love Lua. It’s so comfortable to use when programming little scripts for norns or little plugins for neovim. The other weekend I wanted to use the arc to control some shader parameters in a TouchDesigner patch. It took me a bit to figure out how OSC works in TouchDesigner and decided it would be nice to have a little command-line utility that discovers what port your Arc is listening on and handles that connection for you. The result is a little piece of code that I felt like sharing in the spirit of threads like Norns for laptops: hopefully if you’re like me and enjoy writing Lua to interact with the Arc more than wrangling Max/MSP, this can be inspiring. Soon I’d like to rewrite it to be a little more robust and friendly.


Arc, Lua with luasocket and losc, serialosc.


To use, you’ll need Lua installed on your laptop, as well as the packages luasocket and losc,
which you can install with LuaRocks by invoking

luarocks install luasocket
luarocks install losc

You’ll also need serialosc.


Plug in your arc and then open a terminal.
Usage is

lua /path/to/arc4all.lua '/relative/path/to/handler-script'

For example, if your terminal instance is in the folder containing arc4all,
and you want to run the example touchdesigner script, you would invoke

lua arc4all.lua 'examples/touchdesigner'

At the time of this writing, arc4all is a blocking process until interrupted with CTRL+C (you might need to hit this twice).
Arc4all optionally broadcasts OSC data on port 9000 in the form of the following messages:

/val1 f
/val2 f
/val3 f
/val4 f

At the moment, arc4all listens for the following messages on port 8000:

/redraw n f

where n is the ring number (1-indexed) and f is a float to be interpreted by the handler script. The ring number can also be absorbed into the message address, for example

/redraw1 f

It also listens for


and forwards the (arbitrary) message contents to the handler script.


The handler script is required by arc4all and is expected to return a Lua table
with the following three functions: delta, redraw and configure.
If delta returns a float, that float will be broadcast on port 9000.
The redraw function is called with a ring number and a float and is expected to return an array of 64 integers 0–15 to represent the states of the arc LEDs.
The configure function allows the behavior of the script to be altered over OSC.
As an example, the touchdesigner.lua handler script imagines the arc as 4 configurable knobs
that send their current value when turned. The max, min and step size of these values is configurable over OSC.


v0.1 – Github


i was just looking into how i might use my arc with bitwig, to visualize modulations and affect device macros - and this seems like it might be a nice way to do that.

i’m completely new to lua - but from reading your description, i understand i would need to write a new handler script to do the interpretation with bitwig? i know the bitwig script expects integers for most messages (configurable to a resolution of 128 or 1024).

i was thinking i could have the arc dial send messages to device parameters 1-4

/device/param/n/value i

(n = device param 1-4)

and have the led rings receive the modulated values of device parameters 5-8

/device/param/n/modulatedValue i

(n = device param 5-8)

would this be achievable with your script?

thanks for making this :slight_smile:


Yeah, it’s definitely doable, but might need a little more tweaking than just writing a little handler script—which is great actually, I knew how I had things set up was a bit too constrained, and this gives me the perfect excuse to do it right.

Is there someplace I can read about using OSC to control Bitwig? I don’t use it myself, so it would be helpful to know how to support your use case :smiley:

1 Like


i’m using the “driven by moss” extension which adds extensive controller/communication support to bitwig.

there’s a chapter in the (very long) manual that documents OSC setup/config/messages

starts at page 145 (!)


Wait. I have built one of these and would love to share!!! Hold on.

Okay, so, here is the BitWig script. It was written by a buddy online.
MonomeArc4.bwextension (18.8 KB)

It uses a protocol written by @Dewb to discover the port and allow communication:

It leverages the DrivenbyMoss extension for OSC

The lights on the arc display shifts in automation and such, but do not have a way of showing modulation (which is something I was going to work on with my friend, but he wasn’t as familiar with JS to make it happen).

I will see if I can get the uncompiled code from him, in case you are up for expanding it!

I love the idea of this toolset for allowing for arc to work with anything the accepts OSC tho! That is awesome.

Last edit! Here is the uncompiled code for the arc script:

Made by user @kirkwoodwest.


Re: arc control of Bitwig; so there are a lot of close similarities but also a lot of important differences between these solutions! Which approach makes sense depends on what you want to do and what you want to have to think about.

The bitwig-serialosc-example and @kirkwoodwest’s bitwig-arc4 extension don’t require DrivenByMoss; they negotiate between serialosc OSC messages and the Bitwig API directly. The serialosc example uses the Bitwig Javascript extension system and if you want to customize it, the idea is you’d clone and modify it; it doesn’t have a separation between the serialosc plumbing and “user script” logic. Bitwig-arc4 is a complete opinionated arc control script as a Bitwig Java extension. If you want to modify/customize either of these things, you’re going to have to think about serialosc connection mechanics, OSC, and the Bitwig API all at once. This might be easier to explain with some diagrams:

arc4all offers another set of possibilities. You can let arc4all handle the serialosc business, so you don’t need to get involved in the details of device setup. On the Bitwig side, the DrivenByMoss extension serves the same purpose; it creates OSC endpoints and messages for most key Bitwig functionality, so you don’t need to get involved in the details of the Bitwig API and extension registration. Then your user script just needs to negotiate between the arc OSC events and the DrivenByMoss ones. Here’s a diagram of that flow, plus doing the same thing with Max/MSP, which is very similar:

This pattern is much better suited to customizability, because user script injection is at the core of the design, and the scope of what you have to care about is smaller. But it does mean you have more moving parts and more programs running at once, and if you want do do something not exposed by the DrivenByMoss OSC endpoints, you have no recourse. (Which is probably not a problem in practice, the DBM model is pretty comprehensive.)

edit: “monomeserial” on those diagrams should instead read “monome serial protocol”, not to be confused with the old monomeserial library.