// pymonome // python applications made easy

What version is installed by pip exactly? I’ve just checked pypi and it has version 0.10 which is identical to git master.

pip version 20.1.1

sorry, forgot to mention the problem was with the aiosc module which I believe is 1.4 but the pip version is 1.3

I might be doing something wrong…

//edit
Just double checked and its definitely 1.4… sorry to waste your time.

I’m trying to get the Python grid studies working with a 40h on the latest Ubuntu Studio (Groovy), with Python 3.8 and the latest versions of the study files and Pymonome.

It recognises button presses, but I can’t get the LEDs working. I’m guessing the code only works with varibright models and I’m not sure what needs changing…any thoughts…?

(I’ve seen a note about varibright translation being done via serialosc; it’s on the latest version, 141.)

I have a 40h - I’ve previously got pymonome code working with it - not sure if it was the studies that you’re looking at but one thing to check is that you may need to set the led level to 15 for the LEDs to come on

I’m not at home at the moment but I can check some of your code on my 40h in a few days if you’re still stuck.

1 Like

…thanks, useful to know it can be made to work. I was using 15, but I’ll do some more experimenting…

Both pymonome and serialosc independently support varibright -> monobright translation.

Does you grid work with other apps and implementations (max/pd)? Have you tried using monobright methods in your code, i.e. led_set instead of led_level_set?

Thanks for the reply…I found it worked straight away with my monobright walnut 128, so I’ve switched to using that. :+1:

n00b here, especially Python n00b. I just got my grid, went through serialosc docs and Grid Studies. I can press buttons on my grid and control the printout and led behavior in on_grid_key in the Grid Studies. Now I want to send an osc message to a port on the localhost when I press a button, and this is where I’m in over my head. The studies don’t seem to deal with that. I did install osc4py3 for OSC communications, put its import statements into the first grid study in a way that looked logical, and do its osc_send function right after the grid study prints the key info. OSC Data Monitor shows no activity on the port, so I conclude trying to do this with educated guesses didn’t work out.

Am I on the right track by using the first grid study to send OSC? Do I need to add on a package like osc4py3, or is there already some way that serialosc can be made to send an OSC message? I don’t actually comprehend from the serialosc docs how it could be used to send a message to another port on the localhost.

More detail: the problem is that I don’t understand the syntax of the Python in Grid Studies. I tried to mesh the code for osc4py3 from the section called 1.3.1.2 Sending OSC Messages like this:

#! /usr/bin/env python3

import asyncio
import monome

# Import needed modules from osc4py3
from osc4py3.as_eventloop import *
from osc4py3 import oscbuildparse

# Start theosc4py3 system.
osc_startup()

# Make client channels to send packets.
osc_udp_client("127.0.0.1", 4560, "SonicPi")

# Build a message with autodetection of data types, and send it.
msg = oscbuildparse.OSCMessage("/flag1", None, ["text", 672, 8.871])

class GridStudies(monome.GridApp):
    def __init__(self):
        super().__init__()

    def on_grid_key(self, x, y, s):
        print("key:", x, y, s)
        osc_send(msg, "SonicPi")
        self.grid.led_level_set(x, y, s*15)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    grid_studies = GridStudies()

    def serialosc_device_added(id, type, port):
        print('connecting to {} ({})'.format(id, type))
        asyncio.ensure_future(grid_studies.grid.connect('127.0.0.1', port))

    serialosc = monome.SerialOsc()
    serialosc.device_added_event.add_handler(serialosc_device_added)

    loop.run_until_complete(serialosc.connect())
    loop.run_forever()

except I now realize there should be a osc_process() somewhere (I think).

you can use aiosc for sending OSC in asyncio event loops. pymonome is built on top of aiosc, so it should already be installed on your system.

to send osc using aiosc, modify your grid key handler like this:

import aiosc
...
class GridStudies(monome.GridApp):
...
    def on_grid_key(self, x, y, s):
        print("key:", x, y, s)
        asyncio.ensure_future(aiosc.send(('127.0.0.1', 4560), '/flag1', 'text', 672, 8.871))
        self.grid.led_level_set(x, y, s*15)

or create a wrapper for the Sonic Pi client as follows:

class GridStudies(monome.GridApp):
    def __init__(self, sonic_pi):
        super().__init__()
        self.sonic_pi = sonic_pi

    def on_grid_key(self, x, y, s):
        self.sonic_pi.flag1(...)

class SonicPi(aiosc.OSCProtocol):
    def flag1(self, *args):
        self.send('/flag1', *args)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()

    coro = loop.create_datagram_endpoint(SonicPi, local_addr=('127.0.0.1', 0), remote_addr=('127.0.0.1', 4560))
    transport, sonic_pi = loop.run_until_complete(coro)

    grid_studies = GridStudies(sonic_pi)
    ....
2 Likes

This is fantastic, thank you so much for spoonfeeding. Looking at this part of the Python Tutorial, I see my minimal experience with object oriented programming was making the Grid Studies code almost impossible for me to follow. All I really need to do (for now) is send simple OSC messages to one port so that simply hacking if statements into on_grid_key() based on key values will provide all the control of Sonic Pi that I can currently imagine. In that case, spending the hours it would take to comprehend Python classes would hardly pay off because I’ll surely have forgotten it all by the next time I need to know it.

I’ve verified that Sonic Pi receives the OSC messages. OSCDataMonitor, on the other hand, does not, which is unfortunate because it has been such a good tool in previous applications. For interest, I’ve attached a screenshot showing the data coming through in Sonic Pi and Terminal, but nothing in OSCDataMonitor:

It’s usually not possible for 2 applications to listen on the same port, so if Sonic Pi is launched first, it will occupy the port and OSC Data Monitor will not get any messages (and should fail to open the socket, i wonder why it didn’t).

If you really want to have 2 receiving apps, so you can monitor the messages - run OSC Data Monitor on a separate port and send the messages to both.

Yes, thanks, I just verified that OSC Data Monitor works when Sonic Pi isn’t running.

Except for grid-studies-1.py, I get an invalid syntax error near the top of each Grid Studies file at the line asyncio.async(self.play()). The caret in the terminal points to the ‘a’ in “async” if that helps. Am I missing something?

Right, that’s deprecated syntax in recent Python versions. Use asyncio.ensure_future(self.play()) instead.

1 Like

thanks @artfwo, just ran into this asyncio.ensure_future(self.play()) issue myself.

I’m noticing that I can’t set the leds to anything but off or full brightness in python but that I can in SuperCollider.
python: led_level_set(8, 5, 9) sets to full bright
sc: ~m.levset(8, 5, 8) sets to half bright

looking through monome.py there is a check for varibright but I haven’t figured out how to check within a script

Are you running your scripts on Windows by any chance?

yes, Windows

(I’ve allocated a surface pro 4 for all things monome :), while I was playing around earlier I noticed the leds were blinking 3-4 times per second - got really worried my grid was broken…turns out Windows was doing an update in the background and this little surface was having trouble keeping up)

Right, so windows currently returns grid serial numbers as “Mxxxxxx” with the upper-case “M”. pymonome detects varibright grids by the lowercase “m” followed by numbers, so that’s there the problem comes from.

For now, you can directly modify pymonome source locally to fix the serial number matching regexp, completely disable varibright detection or set grid.varibright to True in your script.

The long-term fix for this would be to mangle serial number a bit in serialosc, so the number is the same across all platforms.

thanks!
great to know it’s a simple fix.

Getting over these little hurdles is balanced by a satisfying amount of fun when things start clicking :slight_smile: