How to create a start/options menu?

Hi everyone,

Relatively new to SC. I have written some code, making use of ATK ambisonic toolkit, to encode/decode in a few different configurations (i.e. from stereo to binaural, stereo to quad, stereo to periphonic, etc.). What I would like to do, is have a start menu screen (probably buttons on a GUI), so I can select which one of the programs to run.

I’m sure that there are several ways of doing this - but I don’t know where to start and I can’t seem to find any clear method in any tutorials.

Is there anyone who might be able to help me with this?

Many thanks in advance!
Mike

You should make a Startup file:

https://doc.sccode.org/Reference/StartupFile.html

and here you can for ex put a GUI with buttons that run different files.

"pathToFile.scd".load will run the code in the file
Document.open("pathToFile.scd") will open the file in the IDE editor

I have a menu that opens as a strip on the right side of my screen with the IDE with a bunch of things that I use often. I click a button to run the code and shift-click it to open the file in the editor. Here’s a basic version of it:

(
var w, files;
w= Window("menu", Rect(Window.screenBounds.width-100, Window.screenBounds.height-300, 100, 300)).front;
w.addFlowLayout(0@0, 0@5);

// put the full paths to the files you want in the menu in this array
files= [
	"/Path/to/afile.scd",
	"/Path/to/anotherFile.scd"
];
	
StaticText(w.view, 100@30).string_("Files:").align_(\center);

files.do({ |it|
	Button(w.view, 100@30)
	.states_([[it.basename.removeExtension, Color.black, Color.white]])
	.action_({
			it.load;
	})
	.mouseDownAction_({ |view, x, y, mod|
			if (mod.isShift, { Document.open(it); });
		})
});

)

You can also use the Menu and ToolBar classes, which are very good for presenting multiple options in a menu or list format, including things like checkboxes for the current item etc. The code for toolbars tends to be cleaner and simpler than doing comparable things with Buttons. The help files for these should have very detailed examples.

1 Like

Thanks very much. I have that working with a button menu in a floating window, with links to my three programs and is working - but I’ve now got to try and a bit of CPU power (I’m using a RPi) by running the installation headless. Could I do the same thing with a text-based menu?

Maybe you should explain the whole idea of what you’re trying to do and you might get some more helpful answers. It could sound like you would want to control the RPi from the outside, so why not use an old phone and TouchOSC or any of the free alternatives? Or send OSC from an other computer? Or do you have a screen and keyboard connected to the pi and need to control it like that?

Since all communication in SC between server and language also is using OSC there are a lot of possibilities…

Of course. What I am actually doing is setting up a real-time ambisonic encoder/decoder (using ATK), so I can send in a stereo signal via line in, transform and then decode to a number of options (i.e. binaural, multi-speaker arrays, etc.). One the Pi is booted and running the correct program it just needs to sit there, but would like to have the menu options on start-up as simple as possible for end user with absolutely no experience.

Like I said, it does work nicely with the GUI buttons but I’ve had to strip back to a headless config to squeeze the last juice out of the Raspberry! What I have in mind is a text based menu (like old school teletext!). Maybe I need to do this at Pi bootup, before sc3 launched?

You could also use command line arguments to sclang, which are available from thisProcess.argv.

I’m not sure if SC has a way to pause for user text input, except for GUI. (Edit: On a hunch, I tried reading from a Pipe("/dev/stdin", "r") but it failed – it doesn’t block the interpreter to wait for user input. That was my only guess – I think SC has no equivalent of the old Basic language input statement. So a text-based menu is likely not an option.) But command line arguments are certain to be supported.

hjh

By ‘headless’ you mean that the Pi doesn’t have a screen and you ssh into it from a different computer or that it does have a screen and you are just not using a desktop environment and still want to use a keyboard input?

If you want an end user to have a clean and simple interface then maybe a small display hat with a menu and buttons to choose between the options and a python script interfacing with SC via OSC?

If you do want keyboard input into the Pi then as James said, command line arguments or writing straight to sclang, or I guess you could make a script with a terminal interface in a different language like python and send OSC to SC, using screen to have several terminal sessions open.

Yes, I’m ssh’ing in via my Mac and using lite version of OS, so there’s no desktop. Adding a small screen was my original idea (I’ve got a case with a 7" touch screen which I was going to use) - but if I install any kind of desktop, then the performance drops. I think a Pi4 will be able to cope with the desktop, so might have to bite the bullet and upgrade. I’m no python programmer - so the other way around it could be to create a startup menu on the Pi before which launches different startup files for sc3. Thanks for your help (both!) will keep plugging away!

just a quick thought - if what you’re trying to do is to setup correct monitoring based on what interfaces are present, I do that by checking whether s.options.outDevice etc contains certain strings and then launch the appropriate monitoring.

Hi there, yes that’s the kind of thing (the user will choose whether they are for instance, listening on headphones with binaural output, or if they are listening on four or 8 speakers). I have the s.options.outDevice defined in each program and this seems to work, I just have to work out a nice way of switching between the options.

You can save this script into an scd file:

var argv = CollStream(thisProcess.argv);
var key, value;

while {
	key = argv.next;
	key.notNil
} {
	value = argv.next;
	switch(key.asSymbol)
	{ \speakerArrayFormat } {
		// here, set the value for speaker array format...
		"Using speaker array '%'\n".postf(value);
	}
	{ \sampleRate } {
		s.options.sampleRate = value.asInteger;
		"Using sample rate %\n".postf(value);
	}
	// ... etc, more parameters
	{ "Unknown option '%'".format(key) }
};

0.exit;

Then, at the commandline:

sclang path/to/your-script.scd sampleRate 48000 speakerArrayFormat ring8

compiling class library...
... snip lots of paths...

*** Welcome to SuperCollider 3.13.0-dev. *** For help type ctrl-c ctrl-h (Emacs) or :SChelp (vim) or ctrl-U (sced/gedit).
Using sample rate 48000
Using speaker array 'ring8'
...

hjh

Thank you! This looks like the answer, I’ll give it a go later.