Supercollider headless autostart and/or single_click.sh

@Giedrius: redirectin the stdout and stderr to log files is very helpful - thanks
@mzero: with the exports i managed to run sclang (supercollider) as root (great! thanks)

so tried to autostart supercollider with:

pi@raspberrypi:~ $ sudo crontab -e

@reboot /bin/bash /home/pi/autostart.sh

autostart.sh looks like this:

#!/bin/bash
export XAUTHORITY=/home/pi/.Xauthority
export DISPLAY=:0
su root -c “/usr/bin/jackd -P75 -dalsa -dhw:1 -p64 -n3 -s -r48000 > /home/pi/jack.log 2>&1 &”
su root -c “sclang -D /home/pi/start.scd > /home/pi/sc.log 2>&1”

i could start sclang automatically with every “sudo reboot” for a while - but only with reboots

with boots sclang (log) complains:

No protocol specified
QXcbConnection: Could not connect to display :0

after a while sclang also complains after reboots

Invalid MIT-MAGIC-COOKIE-1 keyQXcbConnection: Could not connect to display :0

sometimes i can fix this with

grep ‘pam_xauth.so’ /etc/pam.d/* | awk -F “:” ‘{ printf “%s\t(%s)\n”, $2, $1}’

but the problem comes back

my other attempts to start sclang in /usr/local/etc/pisound/click.sh with
“sh /home/pi/autostart.sh” or “sclang -D /home/pi/start.scd” result in this boost error message:

terminate called after throwing an instance of ‘boost::exception_detail::clone_impl<boost::exception_detail::error_info_injectorboost::system::system_error >’
what(): assign: Operation not permitted
Aborted

hmm… somehow im stuck

crontab isn’t going to be a reliable way to start this because it runs independently at boot from the processes that will start up the X server - which must be in place before you run sclang. This is because at each X startup the .Xauthority file is re-written with a random string (the cookie). If sclang starts first, the X lib will read the XAUTHORITY file at process start, and get a value from the previous X start.

If you are going to call sclang from either click.sh or single_click.sh, then do it like so:

nohup sclang .... > /tmp/sclang-log 2>&1 &

There is no reason to use the su root -c construct, since in both root’s crontab, and the pisound click scripts, they are already running as root.

hi mzero,

thank you for helping me with this.
i still don’t get nohup sclang in click.sh to work without that boost error.
but your hint that sclang needs to wait till Xserver is started helps a lot.
so i delayed the cron job about 20 seconds.

sudo crontab -e

@reboot sleep 20 && /bin/bash /home/pi/autostart.sh

and now its also starts with powering up the pi !

i think i am happy with this till i get sc with the button to work

best wishes

Hi All, Thanks for all the help. I feel like we’re close here. I can now get Jack to start from the button, but I get the same boost error with slang even when using nohup. What is the recommended way of getting rid of the boost error when using click.sh?

Thanks,
Carl

Could you post the entire sc log when the exception occurs (if it’s a lot of output, you may post it to some pastebin service and link it here)? I found this post describing the same boost exception: https://stackoverflow.com/questions/23614370/strange-exception-throw-assign-operation-not-permitted

I am not sure where the difference of it working and not working via button scripts would come from though.

Sure, first here is the jack.log:
jackdmp 1.9.10 Copyright 2001-2005 Paul Davis and others. Copyright 2004-2014 Grame. jackdmp comes with ABSOLUTELY NO WARRANTY This is free software, and you are welcome to redistribute it under certain conditions; see the file COPYING for details JACK server starting in realtime mode with priority 75 self-connect-mode is "Don't restrict self connect requests" audio_reservation_init Acquire audio card Audio1 creating alsa driver ... hw:1|hw:1|64|3|48000|0|0|nomon|swmeter|soft-mode|32bit configuring for 48000Hz, period = 64 frames (1.3 ms), buffer = 3 periods ALSA: final selected sample format for capture: 32bit integer little-endian ALSA: use 3 periods for capture ALSA: final selected sample format for playback: 32bit integer little-endian ALSA: use 3 periods for playback

and then I can confirm that jackd is running by using top.

And here is the sc.log:
terminate called after throwing an instance of 'boost::exception_detail::clone_$ what(): assign: Operation not permitted

That’s the whole log. This is from pushing the button once.

Carl

Hi All, still haven’t been able to get this working. Any ideas on how to move forward?

Carl

Hi all, I finally installed Supercollider (through the very handy pisound-config app) and managed to get all audio + midi working (took me a while since i’m new to linux). I also made a script to run sc in headless mode. It works if I just execute it from the terminal but not through the button.

Here’s my script:

#!/bin/sh
. /usr/local/pisound/scripts/common/common.sh

PATH=$PATH:/usr/local/bin:/usr/bin
export DISPLAY=:0.0
flash_leds 1
sleep 0.5
flash_leds 20
sclang ~/Documents/SuperCollider/main.scd

In both cases (from terminal or through the button) the leds flashes but if I run it through the button the sc code doesn’t work.
Help would be much appreciated!

Just wanted to add that I followed the autorun instructions here:
http://supercollider.github.io/development/building-raspberrypi
and managed to get SC to run on startup. Still not with the button but this will do for now.

1 Like

Ive just fixed this exact problem on the Organelle …
this is cause because the headless operation of sclang does not like reassignment of the stdin.

Ive found that the workaround is to attach a pipe to the input

so what i do is something like :

(cd /home/pi/patch; echo " " | sclang start.scd & echo $! > /tmp/sclang.pid)

this means that sclang has an stdin stream so is happy, but still executes start.scd.
most of this is sugar, but part of my normal practice, e.g. i like to run starts scripts in my patch directory, and also record the pid so that I’ve something to kill it later with :wink:

2 Likes

Thank you! Does this work when executing the script from the button?

I’ve not tested yet on pisound, but should do … it’s the same cause.
Btw: I’d also check to see if your sclang is using 100% cpu (via top) , if so that requires another fix.

Hi! Thanks so much for this help, but it’s not working with the pisound. I’m using the following script:

#!/bin/bash
. /usr/local/pisound/scripts/common/common.sh

PATH=$PATH:/usr/local/bin:/usr/bin
export DISPLAY=:0.0
flash_leds 1
sleep 5 #can be lower (5) for rpi3
(cd /home/pi; echo " " | sclang mycode.scd > /tmp/sclang.log)

when I run the above script manually on the command line the SC code works and I get a full log detailing SuperCollider’s startup.

However, if I start the script from the button, SC does not work and the log file only has one line in it:
“compiling class library…”

Any ideas why SuperCollider isn’t starting up fully when executing the script from the button?

Hi, I built sclang as written on http://supercollider.github.io/development/building-raspberrypi under ‘Compiling SC natively on Raspberry Pi Raspbian Lite’ heading. (the sclang from apt-get doesn’t seem to be able to run in headless mode)

Then I ran the script as you showed with a couple of modifications:

  • adding killall sclang.
  • & at the end of the last line.
  • HOME variable initialization.
  • Removed sleep.
#!/bin/bash
. /usr/local/pisound/scripts/common/common.sh

PATH=$PATH:/usr/local/bin:/usr/bin
export DISPLAY=:0.0
export HOME=/home/pi
flash_leds 1
killall sclang
(cd /home/pi; echo " " | sclang mycode.scd > /tmp/sclang.log) &

Sleep may be useful if sclang would get started during boot time, but shouldn’t be necessary when starting using the button.

The & at the end of the last command is needed so that sclang is started as a background process, and the Pisound’s button doesn’t block until sclang is terminated - without it, it would become unresponsive until sclang exits. (I’m considering simplifying this and making all scripts executed by the button to be executed in background in future versions)

I had this in mycode.scd:

s.waitForBoot{ {SinOsc.ar([400, 404])}.play }

The contents of /tmp/sclang.log after clicking the button are:

compiling class library...
        Found 610 primitives.
        Compiling directory '/usr/local/share/SuperCollider/SCClassLibrary'
        Compiling directory '/usr/local/share/SuperCollider/Extensions'
WARNING: Could not open directory: '/home/pi/.local/share/SuperCollider/Extensions'
        To resolve this, either create the directory or remove it from your compilation paths.

ERROR: Class extension for nonexistent class 'HistoryGui'
     In file:'deprecated/3.9/HistoryGui.sc'
        numentries = 1013163 / 11348984 = 0.089
        4106 method selectors, 2764 classes
        method table size 7046068 bytes, big table size 45395936
        Number of Symbols 11181
        Byte Code Size 303235
        compiled 355 files in 0.70 seconds

Info: 4 methods are currently overwritten by extensions. To see which, execute:
MethodOverride.printAll

compile done
localhost : setting clientID to 0.
internal : setting clientID to 0.
Class tree inited in 0.06 seconds


*** Welcome to SuperCollider 3.9.0-beta1. *** For help type ctrl-c ctrl-h (Emacs) or :SChelp (vim) or ctrl-U (sced/gedit).
booting server 'localhost' on address: 127.0.0.1:57110
Found 0 LADSPA plugins
jackdmp 1.9.11
Copyright 2001-2005 Paul Davis and others.
Copyright 2004-2016 Grame.
jackdmp comes with ABSOLUTELY NO WARRANTY
This is free software, and you are welcome to redistribute it
under certain conditions; see the file COPYING for details
JACK server starting in realtime mode with priority 10
self-connect-mode is "Don't restrict self connect requests"
creating alsa driver ... hw:pisound|hw:pisound|128|2|48000|0|0|nomon|swmeter|-|32bit
configuring for 48000Hz, period = 128 frames (2.7 ms), buffer = 2 periods
ALSA: final selected sample format for capture: 32bit integer little-endian
ALSA: use 2 periods for capture
ALSA: final selected sample format for playback: 32bit integer little-endian
ALSA: use 2 periods for playback
port created: Midi-Through:midi/playback_1
port created: Midi-Through:midi/capture_1
port created: pisound:midi/playback_1
port created: pisound:midi/capture_1
JackDriver: client name is 'SuperCollider'
SC_AudioDriver: sample rate = 48000.000000, driver's block size = 128
JackDriver: connected  system:capture_1 to SuperCollider:in_1
JackDriver: connected  system:capture_2 to SuperCollider:in_2
JackDriver: connected  SuperCollider:out_1 to system:playback_1
JackDriver: connected  SuperCollider:out_2 to system:playback_2
SuperCollider 3 server ready.
JackDriver: max output latency 5.3 ms
Shared memory server interface initialized
FAILURE IN SERVER /s_new Group 1 not found
Requested notification messages from server 'localhost'
localhost: server process's maxLogins (1) matches my options.
localhost: keeping clientID (0) as confirmed by server process.

And ps does show that there’s sc and jack processes running:

pi@raspberrypi:~ $ ps -ef
...
root     22679     1  0 12:47 ?        00:00:00 /bin/bash /usr/local/pisound/scripts/pisound-btn/start_sclang.sh 1
root     22681 22679  1 12:47 ?        00:00:04 sclang mycode.scd
root     22705 22681  2 12:47 ?        00:00:06 scsynth -u 57110 -a 1024 -i 2 -o 2 -b 1026 -R 0 -C 0 -l 1
root     22712     1  7 12:47 ?        00:00:19 /usr/local/bin/jackd -T -ndefault -dalsa -r48000 -p128 -n2 -Xseq -D -Chw:pisound -Phw:pisound

However, I don’t get any audio output…

So it looks like on my system it gets further, not sure what’s different from yours.

Any ideas about the missing audio output?

1 Like

Thanks for doing all this! I think the issue is that the Default Group in SuperCollider doesn’t automatically get created when running from the command line. So add ‘s.initTree;’ after the waitforboot command in your mycode.scd file. And then I think you might get sound.

Hi All, I just tried to new startup script with the s.initTree line and it works! This is fantastic news. How can we contribute a new startup script for SuperCollider to the default Pisound software? It’d be great to have this all sorted out for everyone going forward.

6 Likes

Hey! Great to hear it worked!

You may contribute the new scripts to the Pisound repository, by forking it and creating a pull request once the changes are applied.

You could use the Pure Data as an example. The ‘common’ folder has 2 scripts which define start_puredata and stop_puredata shell functions which are common for The Button and the Pisound App. The start function expects to get the full path to the patch to start as the first argument. The stop function kills all Pure Data instances, in the future this may change to deal only with the exact instance that was started by The Button or the App. (so you should kill all sclang instances in your stop script at this time).

The actual ‘entry point’ scripts for The Button are in here: https://github.com/BlokasLabs/pisound/tree/master/scripts/pisound-btn

The Button specific start_puredata.sh script then includes the common script: . /usr/local/pisound/scripts/common/start_puredata.sh. (The repository is checked out by default to /usr/local/pisound/ during Pisound software setup.) Then it goes on doing The Button specific things, like searching for a Pure Data patch to load in various locations, and once found, invoking the common start_puredata function.

The button actions in pisound-config are populated based on the script filename, so if you’d create /usr/local/pisound/scripts/pisound-btn/start_supercollider.sh, you’d get Start Supercollider entry in the script picker menu.

Feel free to ask us any questions. :slight_smile:

yeah I had the trouble with the default group not initialising in time.
and found the root cause was (or seemed to be) a couple of timing issues between sclang and scsynth

what ive resorted to is

// boot the server
s.boot;
s.doWhenBooted {
	(
        Routine( {
               1.wait;
		~mainOut = ~mainOutDef.add.play;
		~mainPatch.load;
        }).play;
	)
};

theoretically, wait is not required, but in practice I found that without it the default group would not be ready for the first synth to play…

fyi… here what I’m doing is… having a central output for the hardware, so i can do fun stuff, like measure intput and output audio peaks (i should rename mainoutput to hardwareIO or something ;)) , then what i do is actually load the ‘real’ patch file.
this is for the Organelle, so allows me to basically launch different patch files whilst having a central patch file for dealing with hardware configuration.
(you can see more details over at the organelle.io forum)
i plan to do the same thing on the pisound once ive ironed out the issues on the Organelle.

1 Like

talk of coincidences I was researching another issue with SC (not deallocating synths correctly!)
and found this bug report :slight_smile:

it appears 3.9 (beta1) has a known issue, with waitForBoot and doWhenBooted.
its quite a long bug report, so can quite determine if they think a solution will be found for 3.9.0 or if its going to wait till 3.9.1… but seems the workaround I’m using might be temporary which is good news.

It bothers everyone, it’ll be fixed soon. There is a branch that has the fix in it already, if necessary: https://github.com/adcxyz/supercollider/tree/lockClientIDWhileRunning