Using libmonome on MacOS

Hi folks,

I’ve built libmonome on macOS 10.14.6, hoping to write an app that talks directly to the grid, rather than requiring the user to run serialosc.

Trying to run the examples but they all hang.

I’ve deactivated serialosc.

I can try various things but I thought I’d ask here first before I spend a lot of time on it.


Seems to hang on select():

(lldb) target create "build/examples/simple"
Current executable set to 'build/examples/simple' (x86_64).
(lldb) run
Process 735 launched: '/Users/holliday/libmonome/build/examples/simple' (x86_64)
Process 735 stopped
* thread #1, queue = '', stop reason = signal SIGSTOP
    frame #0: 0x00007fff5ab1061a libsystem_kernel.dylib`__select + 10
->  0x7fff5ab1061a <+10>: jae    0x7fff5ab10624            ; <+20>
    0x7fff5ab1061c <+12>: movq   %rax, %rdi
    0x7fff5ab1061f <+15>: jmp    0x7fff5ab09421            ; cerror
    0x7fff5ab10624 <+20>: retq   
Target 0: (simple) stopped.
(lldb) bt
* thread #1, queue = '', stop reason = signal SIGSTOP
  * frame #0: 0x00007fff5ab1061a libsystem_kernel.dylib`__select + 10
    frame #1: 0x00000001000d01c8 libmonome.1.dylib`monome_event_loop + 152
    frame #2: 0x0000000100000e88 simple`main + 120
    frame #3: 0x0000000100000d34 simple`start + 52

did you modify simple.c? if so, can you share?

if not, you at least have to change the device string if you don’t want to use serialosc.

i’ll dig out a mac and sanity-check real quick. i think i have 10.14.6 somewhere.

… yeah, working for me. 2016 MBP with the adapter, macOS 10.14.6, a relatively recent m128.

(i have some kind of waf/cython problem that seems obnoxious to fix, so built this with gcc and whatever build of libmonome i already had installed… so i guess that doesn’t technically rule out some recently-introduced problem with the lib.)

here’s the test, takes a device string instead of hardcoded UDP address, and doesn’t initialize with a port number.

or wait… do you just mean that the program never exits and is always in select waiting for monome events? that’s all it’s supposed to do - it’s a very basic example.

you would want to run this in a thread, handle disconnect/reconnect events, yadda yadda.

Thanks for the help @zebra. I didn’t modify simple.c.

I’m not sure what device string to use. When I use your example, I get:

error opening device: /dev/ttyUSB0

The path /dev/ttyUSB0 doesn’t exist on my machine. I tried /dev/ttyu0 and got the same error.

sorry right. that is the default dev path for linux, it just counts up with more ttyUSB devices.
on macos you get a string related to the device serial number (or something.)
e.g. on mine it’s /dev/tty.usbserial-m1000364 right now but yours will be something different.

Hmm I don’t see anything resembling /dev/tty.usbserial-* or including the grid’s serial number. (The grid does appear in the USB device tree)

welp, i dunno then. nothing changes in /dev/ when you plug/unplug the grid?

here’s my device tree if it helps

embp:examples emb$  ioreg -p IOUSB 
+-o Root  <class IORegistryEntry, id 0x100000100, retain 16>
  +-o AppleUSBXHCI Root Hub Simulation@00000000  <class AppleUSBRootHubDevice, id 0x100000f10, registered, matched, active, busy 0 (3 ms), retain 14>
  +-o AppleUSBXHCI Root Hub Simulation@14000000  <class AppleUSBRootHubDevice, id 0x100000f27, registered, matched, active, busy 0 (2 ms), retain 12>
    +-o monome@14100000  <class AppleUSBDevice, id 0x10002754b, registered, matched, active, busy 0 (18 ms), retain 20>

if it’s an old grid model you might need an FTDI driver? is that still a thing?

Well I rebooted, and loaded/unloaded serialosc, and the /dev/tty.usbserial-m******* appeared. The example now works. So that’s progress :slight_smile:

How can I auto-detect that path?

I suppose I’m not clear on how I should go about writing a macOS app that interfaces with the grid as simply and automatically as possible.

It seems at first glance that the Apple-recommended way to this would be to write an application-space driver using IOKit. OTOH, perhaps I should just assume that any grid user will have serialosc running? (For example Mark Eats Sequencer seems to assume serialosc is running. It also doesn’t use libmonome as best I can tell.)

well, libmonome is low-level.

serialosc itself is an example of a higher-level device management layer. it does indeed use iokit on macos.

What does iokitlib.c actually do? I don’t see any other use of IOKit in serialosc.

it is the platform-specific implementation of the “detector” process for macOS.
talks to other parts of serialosc through IPC.

has very simple job of notifiying other components of serialosc of connected/disconnected device paths through IPC

send_connect(const char *devnode)
	sosc_ipc_msg_t msg = {

	msg.connection.devnode = (char *) devnode;
	sosc_ipc_msg_write(STDOUT_FILENO, &msg);

I don’t see any other use of IOKit in serialosc.

it’s x-platform by design, and platform-specific stuff is only needed here and there, like in this “detector” component.

i should say i didn’t author serialosc and don’t have detailed insights on it.

Any idea why a detector would be implemented as a separate process? Seems odd.

serialosc is heavily multi-processed. e.g. spawns server process for each device.

again i didn’t author it but i can think of several reasons:

  • fault tolerance (this is why e.g. chrome is multi-process)
  • precisely b/c it’s platform-specific (libudev and windows versions are totally different)
  • easy ‘big-hammer’ lifecycle mgmt from the supervisor daemon

i dunno, it’s not an uncommon pattern in systems development, love it or hate it.

but anyways, i typically don’t want to use OSC either for applications talking to grid, and just roll my own monitor thread. serialosc detector is a fine example and the architecture makes it very easy to re-use.

[mod hat] i’ve changed the title of the topic; assuming we’ve addressed the original question and are moving on to more general questions.

Do you have any tips on the monitor thread approach?

Where should look for the protocol used by the grid?


The serial reference and osc reference are linked from the grid docs page. Lots of grid communication code if you go digging in monome repos (libavr32, …) in addition to libmonome.