Menu order confuses path

Originally posted on Github repo. Might have been wrong place for this cuz no response.

Using menu.add_item to build a configuration menu, with Backlight(backlight) as a test class.

DotHAT on Pi3 using dothat/advanced/menu.py as source file to rewrite.

menu.add_item(‘Blue Order/Launch’, Backlight(backlight))
menu.add_item(‘Blue Order/Main patch/E-mu Modular/Fat square’, Backlight(backlight))
menu.add_item(‘Blue Order/Main patch/E-mu Modular/Fat Saw’, Backlight(backlight))
menu.add_item(‘Blue Order/Main patch/Steinway/Hall performance’, Backlight(backlight))
menu.add_item(‘Blue Order/Main patch/Steinway/Honky tonk’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/1’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/2’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/3’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/4’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/5’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/6’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/7’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/8’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/9’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/10’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/11’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/12’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/13’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/14’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/15’, Backlight(backlight))
menu.add_item(‘Blue Order/Channel assignments/16’, Backlight(backlight))
menu.add_item(‘Blue Order/Reverb’, Backlight(backlight))
menu.add_item(‘Blue Order/Chorus’, Backlight(backlight))
menu.add_item(‘AmSynth/Launch’, Backlight(backlight))
menu.add_item(‘Pure Data/Launch’, Backlight(backlight))
menu.add_item(‘Effects/Launch’, Backlight(backlight))

The root menu shows:
Blue Order
E-mu Modular
Steinway
Channel assignments
AmSynth
Pure Data
Effects

But, E-mu Modular, Steinway, and Channel assignments are supposed to be sub-menu items as defined in the path defined in each menu.add_item. Also, they are missing from their parent item of Blue Order.

Choosing a menu item such as Steinway yields this sequence of sub-menu items…

Steinway>Main patch>Blue Order>Honky tonk

…which is totally out of sequence as defined in menu.add_item.

Am I missing something here? Some weird punctuation treatment of spaces or something?

Doesn’t look like you’re missing anything so I delved into the code and found a tiny bug which would explain the problem.

I’ve pushed up a fix: https://github.com/pimoroni/dot3k/commit/76abe35fd6e80cf3ee06d88e2eeaa647f92ccb94

Are you able to grab the latest Dot3k library from GitHub and give it a go?

Cool. That fixed the ordering. Thanks for the fast response.

Now I’ve got an issue with menu functions firing on script launch instead of menu item choice.

Added this function to simply print out the intended menu item value, as a test.

def channel( ch ):
print ch
return

menu.add_item(‘Blue Order/Main patch/E-mu Modular/Fat square’, channel(“45”))
menu.add_item(‘Blue Order/Main patch/E-mu Modular/Fat Saw’, channel(“56”))

When I run the script, those values print out immediately instead of when they are chosen in the menu. Also, actually choosing them in the menu has no output. Any ideas?

When you assign a function into the menu, like channel("45") you are actually assigning the result of running that function, since there’s no language construct to differentiate between “pass this function and parameter for running later” and “run right now.”

Normally when you assign a function, you pass it by name only so there’s no confusion.

There’s a right to get around this, however, in the form of an anonymous function. In Python these are called lambdas and take the form:

lambda arg1, arg2: arg1+arg2

Lambda functions can accept arguments, and return the result of a simple expression or, crucially, of executing another function.

You can change your menu item assignments to:

menu.add_item('Blue Order/Main patch/E-mu Modular/Fat square', lambda: channel("45"))
menu.add_item('Blue Order/Main patch/E-mu Modular/Fat Saw', lambda: channel("56"))

This is basically a shorthand for something like this:

def channel_45():
    channel(45)

def channel_56():
    chanel(56)

menu.add_item('Blue Order/Main patch/E-mu Modular/Fat square', channel_45)
menu.add_item('Blue Order/Main patch/E-mu Modular/Fat Saw', channel_56)

ah, thanks!

In the meantime, I did some Python homework and hacked together a class for it. Working now and I have a sweet synth patch selector using the DotHAT. Either way I ended up learning some more Python, which is part what all this tinkering is all about.

Thanks for taking the time to answer my noob question, it gives me good options for making the menu more versatile. Also appreciate the code comments in the existing plugins.