Skip to content

Instantly share code, notes, and snippets.

@rbnpi
Last active August 6, 2021 22:04
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rbnpi/8011cc9edd18fd07e178 to your computer and use it in GitHub Desktop.
Save rbnpi/8011cc9edd18fd07e178 to your computer and use it in GitHub Desktop.
Sonic Pi command line jukebox. Choose and play Sonic Pi files. Download samples from http://r.newman.ch/rpi/telegram/jukeboxfiles.tar.gz
#!/usr/bin/ruby
#ruby script to give jukebox control over Sonic Pi by Robin Newman, February 2015 (VERSION 2)
#added path variable for sonic-pi-cli so that the program can be used on a Mac as well as a Pi
#utilises sonic_pi_cli by Nick Johnstone which must be installed see https://github.com/Widdershin/sonic-pi-cli
#the program was developed from an initial project to control Sonic Pi via a mobile phone and teh telegram app
#the program will list all files in the program spfiles in the user's root directory, and let you choose by number
#which one to play
#It can also handle a series of files linked by Sonic Pi cue and sync commands, which can be played one after the other
#These are placed in sub folders in the folder linked, and their filenames should be numbered in the order in which they are to be run
#The program can also switch between headphone and hdmi sound output
#Input the command listall to see all the commands recognised
#The program creates the temporary folder /tmp/jukebox where it creates and uses 8 temporary files.
#init.txt, dbf.txt, mlist.txt, comm.txt, llist.txt, coml.txt, linkfiles.txt, mnlist.txt
#These files and the temporary directory are removed when the program is quit
#temp file uses: init.txt and dbf.txt contain preamble commands which are sent to Sonic File before the main music files
#the first initialses !set_sched_ahead_time and !set_volume and sets use_debug false
#The second just contains use_debug false, and is used when linked files are sent to Sonic Pi
#mlist.txt holds the contents of the spfiles folder, with preceding line numbers
#comm.txt holds the filename of the last selected music file to be played
#llist.txt contains a list of the subdirectories in linked containing sets of linked Sonic Pi files (linked with cue and sync commands)
#coml.txt contains the name of the last selected subdirectory in the linked directory
#linkfiles.txt contains the names of the files in the last selected linked files subdirectory
#mnlist.txt is a temporary work file used when adding line numbers to mlist.txt and llist.txt
#PATHNAMES WHICH ARE USED
path="/tmp/jukebox" #path for temporary files folder
spfiles=ENV["HOME"]+"/jukebox/spfiles2" #path for folder cotaining sonic pi files to chose from
linked=ENV["HOME"]+"/jukebox/linkedSP" #path to folder containing folders of linked sonic pi files to play
clipath=ENV["HOME"]+"/user/local/bin"
#adjust on a Mac I use rvm to manage Ruby and so by path was clipath=ENV["HOME"]+"/.rvm/gems/ruby-2.1.2/bin"
#setup temp files and directory
system 'mkdir '+path
f=open(path+'/init.txt','w')
f.puts "use_debug false"
f.puts "set_sched_ahead_time! 2"
f.puts "set_volume! 1"
f.close
f=open(path+'/dbf.txt','w')
f.puts "use_debug false"
f.close
#populate list and linklist output in mlist.txt and llist.txt
system 'ls '+spfiles+' > '+path+'/mnlist.txt'
system 'cat -n '.+path+'/mnlist.txt > '+path+'/mlist.txt'
system 'ls '+linked+' > '+path+'/mnlist.txt'
system 'cat -n '.+path+'/mnlist.txt > '+path+'/llist.txt'
system 'clear'#clear screen
puts 'Sonic Pi Jukebox control program' #title
puts
while true do
print "Enter Command (listall for help): "
$stdout.flush
c=gets.chomp.downcase
system 'clear'
puts 'Sonic Pi Jukebox control program'
puts
if (c[0..3] == "play" and c =~ /^.....\d/) then #play n command (check number is present with regexp)
num=c[5..-1] #get value of <n> to num variable
system "head -'"+num+"' "+path+"/mlist.txt | tail -1 |sed 's/^.......//' > "+path+"/comm.txt 2>&1" #extract filename to comm.txt
file=File.open(path+"/comm.txt","r") #open and comm.txt and read filename to varaible f
f=file.readline.chomp
file.close
system clipath+'/sonic_pi stop' #stop Sonic Pi from playing
system "cat "+path+"/init.txt "+spfiles+"/"+f+" | "+clipath+"/sonic_pi" #send file contents to Sonic Pi with init.txt preamble
puts "Now playing "+f #print file info for user
end
if (c[0..7] == "linkplay" and c =~ /^.........\d/) then #linkplay <n> command (check number is present with regexp)
num=c[9..-1] #get value of <n> to num variable
#get directory name from llist.txt, strip the preceding number and store the directory name in coml.txt
system "head -'"+num+"' "+path+"/llist.txt | tail -1 |sed 's/^.......//' > "+path+"/coml.txt 2>&1"
file=File.open(path+"/coml.txt","r") #open coml.txt, read directory name to variable f
f=file.readline.chomp
file.close
system 'ls '+linked+'/'+f+' > '+path+'/linkfiles.txt' #list contents of directory name in "f" and save in file linkfiles.txt
system clipath+'/sonic_pi stop' #stop Sonic Pi from playing
file=File.open(path+'/linkfiles.txt') #open linkfiles.txt
#read filenames to an array fname
fname=[]
until file.eof()
fname << file.readline().chomp #chomp strips trailing /n
end
numfiles=fname.length - 1 #numfiles contains number of files to process
#process all files except the last
for x in 0..(numfiles-1) do
system "cat "+path+"/dbf.txt "+linked+"/"+f+"/"+fname[x]+" | "+clipath+"/sonic_pi &"
end
#now do last file, which has a different preamble file, init.txt instead of dbf.txt
system "cat "+path+"/init.txt "+linked+"/"+f+"/"+fname[numfiles]+" | "+clipath+"/sonic_pi &"
puts "Now playing "+f #inform teh user what is playing
end
case c #deal with remaining commands in a case statement
when "hp"
system 'amixer cset numid=3 1 >NUL'
puts "Headphone output selected"
when "hdmi"
system 'amixer cset numid=3 2 >NUL'
puts "HDMI oputput selected"
when "list"
system 'cat '+path+'/mlist.txt'
puts "Use play <num> to select"
when "linklist"
system 'cat '+path+'/llist.txt'
puts "Use linkplay <num> to select"
when "stop"
system clipath+'/sonic_pi stop'
when "listall"
puts"Commands: hp (headphones), hdmi (hdmi audio), list (music files), play (num)"
puts" linklist (linked music pieces), linkplay (num)"
puts" stop (playing), quit (program)"
when "quit"
system clipath+'/sonic_pi stop' #stop Sonic Pi
system 'rm -fR '+path #remove temp files
puts "Program ended"
break
else
if c[0..3] != "play" and c[0..7] != "linkplay" then #ignore known commands
puts "You entered "+c+" which is not a recognised command"
end
end
end

Sonic Pi Jukebox Program (version 2)

change: path variable added for sonic-pi-cli binary sonic_pi so program can be configured to work on a Mac as well as a Pi

The jukebox.rb program, downloaded from the next file, should be run in an xterminal window in the gui, with Sonic Pi also loaded and running. Requires installation of sonic-pi-cli from https://github.com/Widdershin/sonic-pi-cli

Install this with:

cd ~

git clone https://github.com/Widdershin/sonic-pi-cli.git

followed by

sudo gem install sonic-pi-cli

You should first have some Sonic Pi files in place ready to be chose by the jukebox. You can download some sample files in the Pi home directory with wget http://r.newman.ch/rpi/telegram/jukeboxfiles.tar.gz

Untar the files with tar zxvf jukeboxfiles.tar.gz

The folder contains three further tarred files

tar zxvf jukeboxfiles/linkedSP.tar.gz

tar zxvf jukeboxfiles/samplesv2.tar.gz

tar zxvf jukeboxfiles/spfilesv2.tar.gz

Then save the file jukebox.rb from this gist to your homw directory

You may have to alter the path varaibles at the start of teh program to suit your system. e g to alter desired locations of the Sonic Pi music and samples files, or to allow for different locations of the sonic_pi cli binary file. You can find the location by typing which sonic_pi in a terminal window

Start the file with ./jukebox.rb (or with ruby jukebox.rb

Listall gives the commands

@rbnpi
Copy link
Author

rbnpi commented Feb 15, 2015

As a suggestion, why not download the finalist entries in the Sonic Pi competition from https://github.com/raspberrypilearning/sonic-pi-comp-finalists
put them in a folder finalists on your Pi home directory and amend the path variable in line 29 to point to it.

spfiles=ENV["HOME"]+"/finalists" #path for folder cotaining sonic pi files to chose from

Have fun!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment