Hmm. Not sure that the example you give would work. Looking at the code for save-and-run-buffer (in sonic-pi-server.rb) below:
server.add_method("/save-and-run-buffer") do |args|
gui_id = args[0]
buffer_id = args[1]
code = args[2].force_encoding("utf-8")
workspace = args[3]
sp.__save_buffer(buffer_id, code)
sp.__spider_eval code, {workspace: workspace}
end
it requires several parameters. You can supply a gui_id and a buffer_id (eg workspace_eight) but you can’t get at code (which is the text from the editor buffer in the gui, which is sent from there and saved in the workspace_eight.spi file and then evaluated and run.
Instead I have produced code which can play the last-saved code placed in that file. It will not pick up any changes you make on the editor screen until you press run (which then invokes save-and-run OSC command). However it is still useful.
I have also used it from TouchOSC with buttons to play any saved buffer. The only drawback is that if you stop an instance playing, which you can also do using the stopAll command I also implement, you can only do that once as it also stops the live loop running to poll input from TouchOSC, I also have another version which uses a python script and (for convenience) the sonic-pi-cli gem file, and this will let you run and stop buffer runs repeatedly, although at present it has hardcoded pathnames which need to be rewritten with environmental variables instead. Not sure its worth the effort. It is based on my previously published jukebox script written back in 2015.
define :pvalue do #this functions reads from server-output.log
#the dynamically allocated port used for incoming commands to sonic-pi server.
value='' #initialise variable
#read server-output.log
File.open(ENV['HOME']+'/.sonic-pi/log/server-output.log','r') do |f1|
while l = f1.gets
if l.include?"Listen port:" #find line containing Listen port:
value = l.split(" ").last.to_i #extract port
break
end
end
f1.close #close file
end
return value #return found port value
end
#function to run contents of buffer 0-9
define :runBuff do |n|
buf=["_zero","_one","_two","_three","_four","_five","_six","_seven","_eight","_nine"]
f=ENV['HOME']+"/.sonic-pi/store/default/workspace"+buf[n]+".spi"
k="run_file '#{f}'"
osc_send "localhost",pvalue,"/run-code","rbnguid",k
end
#function to stop all running jobs
define :stopAll do
osc_send "localhost",pvalue, "/stop-all-jobs"
end
I had fun with the runBuff command using it to overlay instances of Frere Jaques. I put this code in buffer 3:
#frere jaques
use_bpm 180
f=[:c4,:d4,:e4,:c4]*2+[:e4,:f4,:g4]*2+[:g4,:a4,:g4,:f4,:e4,:c4]*2+[:c4,:g3,:c4]*2
d=[1,1,1,1,1,1,1,1,1,1,2,1,1,2,0.5,0.5,0.5,0.5,1,1,0.5,0.5,0.5,0.5,1,1,1,1,2,1,1,2]
use_synth :tri
f.zip(d) do |n,d|
play n,release: d
sleep d
end
I put the code for :pvalue, :runBuff and :stopAll in the init.rb file in my .sonic-pi folder, so that they can be called at any time once Sonic Pi has started.
Then in a separate buffer I tried
#note instances all played at 180bpm in buffer 3
#this use_bpm just varies separation
use_bpm 180 #try 190,220,240,300 etc
6.times do #vary number of instances 2-6
runBuff 3
sleep 8
end