I’v so far used Lilypond twice to make nice, clean music of some classical pieces. If you don’t know what Lilypond is already, it is basically LaTeX, but for music. Since the music notation style is almost always the same across many different genres, LaTeX’s “what you see is what you mean” philosophy applies particularly well to your sheetmusic-making needs.
The basic way you work is — create an .ly file pursuant to the lilypond format, then save it, then call “lilypond [filename]” on it from the terminal, which will generate a .pdf, .ps, and .midi output all for you (that is, if you have a “\layout {}” and also a “\midi {}” in you “\score {}”). If you have dual monitors, then you can open up the .pdf file with evince, and then evince will automatically update to the latest .pdf version by itself (no need to close and re-open the same generated .pdf file).
This workflow is nice, but it could be better. For one, it takes time to switch windows and invoke “lilypond [filename]” every time you want to see a small change done. For me, I like to make sure at least every 1/2 measure or so that what I put in is correct. Thus, switching back and forth between all these windows every 30 seconds makes the whole process very time consuming.
So I wrote a small ruby script (I call it “Autolily”) to automatically invoke lilypond for me:
1 #!/usr/bin/ruby
2 #===============================================================================================================#
3 # Program name: Autolily #
4 # LICENSE: PUBLIC DOMAIN #
5 # This program takes 1 argument, the name of a lilypond file (*.ly), and watches it for changes every 1 second. #
6 # If there has been any change, it simply calls lilypond on it to create a new .pdf/.ps/.midi of it. #
7 # #
8 # Place this script somewhere, like in ~/scripts #
9 # Then, open up a terminal and call it like so: ~/scripts/autolily.rb [lilypond file] #
10 # Be sure to call it from the directory where the lilypond file is located -- i.e., don't do [path/to/file] #
11 # #
12 # To exit, type CTRL-C. #
13 #===============================================================================================================#
14
15 if ARGV.size > 0
16 file = ARGV.shift
17 file_data_orig = ""
18 `ls --full-time`.split("\n").each do |line|
19 if line.split(/\s/).last == file
20 file_data_orig = line
21 break
22 end
23 end
24 file_data_new = ""
25
26 # enter infinite loop -- keep compiling the given lilypond file if it has changed in the past 1 second
27 while true
28 # detect the file size and also timestamp
29 lsarr = `ls --full-time`.split("\n")
30 lsarr.shift # get rid of the first line, since that is the size of all the files in the directory
31
32 # find our file from ls's output!
33 lsarr.each do |line|
34 if line.split(/\s/).last == file
35 file_data_new = line
36 break
37 end
38 end
39
40 # if there is any change detected, run lilypond on it
41 if file_data_orig != file_data_new
42 puts "\n\e[1;4;38;5;226mAutolily: Change detected in given file; invoking lilypond...\e[0m\n"
43 `lilypond "#{file}"`
44 file_data_orig = file_data_new
45 end
46 sleep 1
47 end
48 else
49 puts "No .ly file specified.\n"
50 end
This very simple script is an infinite loop which takes snapshots of the output of the "ls" command every second, and monitors any changes. Only the output line for the given lilypond file is monitored. Whenever this single line changes (any time you save your file, thus changing the modification timestamp of the file), the "lilypond [filename]" command is invoked to generate the .pdf, .ps, .midi outputs.
Now, every single time you save your .ly file, Autolily will run lilypond for you in the background, letting you know of any errors or such (and if you have evince open on the generated .pdf file, evince will update what your sheet music looks like as well).
Memory usage of this script is a bit embarrassing -- I get around 4.5 MB -- but hey, that's Ruby's fault.
Enjoy!
UPDATE November 12, 2009: Added quotes around _file_ so that a filename with spaces works correctly. (Though, if you're a Linux guy like me, you probably don't name your files with spaces in them.)
Hi, Shinobu. I just started working with LP, and immediately found myself wanting a solution like this. Thanks for sharing!
-Billy
Comment by Billy Doughty — November 8, 2009 @ 7:12 pm