Difference between revisions of "LilyPond"

From Wiki
Jump to navigation Jump to search
(Hint about named LilyPond buffers)
(complete overhaul; deleted documentation for old module)
Line 1: Line 1:
 
< [[Graphics]] | [[Using Graphics]] >
 
< [[Graphics]] | [[Using Graphics]] >
  
[http://lilypond.org LilyPond] is a great music engraver, and you can include LilyPond in ConTeXt source using [[modules:t-lilypond|the lilypond module]].
+
[http://lilypond.org LilyPond] is a great music engraver, and you can include LilyPond in ConTeXt source using [[modules:t-filter|the filter module]] with some setup.
  
== Deprecation Warning ==
+
== Simple Filter Setup ==
  
The LilyPond module doesn't work any more with recent versions of ConTeXt. You can simply replace it with the [http://modules.contextgarden.net/filter Filter module] like this:
+
This works with ConTeXt MkII and MkIV, but takes only the first page of multi-pages scores, and you must create the folder "lilytemp" manually:
  
 
<texcode>
 
<texcode>
Line 19: Line 19:
 
</texcode>
 
</texcode>
  
You can't use <cmd>setuplilypond</cmd> any more, but there is a better replacement: Collect your LilyPond settings in a .ly file, put it in your lilytemp directory and include it from within your lilypond block like this:
+
== Multi Page Filter Setup ==
 +
 
 +
This uses Lua and therefore only works with ConTeXt MkIV. It includes all pages of multi-page scores.
 +
It doesn’t look into the complete (multi-page) PDF, but reads a "-system.count" auxiliary file written by LilyPond that contains the number of systems (pages) and includes the single-system PDFs.
 +
 
 +
<texcode>
 +
\def\ParseLilypondFile#1% #1 is the name of the output file
 +
  {\ctxlua{thirddata.parselilypondfile("#1")}}
 +
 
 +
\startluacode
 +
thirddata = thirddata or {}
 +
 +
-- create temp folder if missing
 +
if not lfs.isdir('lilytemp') then
 +
  lfs.mkdir('lilytemp')
 +
end
 +
 +
function thirddata.parselilypondfile(name)
 +
  -- include all systems (pages)
 +
  -- name is like lilytemp/mainfile-temp-lilypond-21.pdf
 +
  logs.report("LILYPOND name='" .. name .. "'")
 +
  syco = 0
 +
  for ts in io.lines(string.gsub(name, '%.pdf$', '-systems.count')) do
 +
    syco = ts*1
 +
  end
 +
 
 +
  for nr = 1, syco do
 +
    logs.report("LILYPOND including system no." .. nr)
 +
    context("\\externalfigure[" .. string.gsub(name, '%.pdf$', '-' .. nr) .. "]")
 +
  end
 +
end
 +
\stopluacode
 +
 
 +
\usemodule[filter]
 +
\defineexternalfilter[lilypond]
 +
[continue=yes,
 +
readcommand=\ParseLilypondFile,
 +
directory=lilytemp/,
 +
output={\externalfilterbasefile.pdf},
 +
filtercommand={lilypond -dbackend=eps -dinclude-eps-fonts -dno-gs-load-fonts -o"lilytemp/\externalfilterbasefile" "\externalfilterinputfile"}]
 +
</texcode>
 +
 
 +
 
 +
== LilyPond Settings ==
 +
 
 +
Collect your LilyPond settings in a .ly file, put it in your lilytemp directory and include it from within your lilypond block like this:
  
 
<texcode>
 
<texcode>
Line 28: Line 73:
 
</texcode>
 
</texcode>
  
You might want to add <tt>[name=\currentcomponent]</tt> (or name=mymusic) to <cmd>startlilypond</cmd> to avoid recompiling your LilyPond snippets if you change their order. (Default are serially numbered buffer names.)
+
== Named Buffers ==
 +
 
 +
Normally, your LilyPond snippets just get a running number. If you re-order your scores, each one gets re-rendered.
 +
 
 +
You might want to add <tt>[name=\currentcomponent]</tt> (or name=mymusic) to <cmd>startlilypond</cmd> to avoid unnecessary re-rendering.
 +
 
 +
== Example ==
 +
 
 +
(TODO: This is old and might contain deprecated or non-working code. Unchecked.)
  
 
Here's an example of placing score snippets in the body of the text, with fonts in the score & body matching:
 
Here's an example of placing score snippets in the body of the text, with fonts in the score & body matching:
Line 157: Line 210:
 
</texcode>
 
</texcode>
  
== Setup ==
+
== Deprecation ==
 
 
'''The following is outdated, see "Deprecation Warning" above!'''
 
 
 
* First you need a working, recent [http://www.lilypond.org LilyPond] installation (version 2.12.x) plus dependencies like GhostScript.
 
* Install the lilypond module via [[ConTeXt_Minimals#Installing_third_party_modules|ConTeXt minimals]], or get it from [[modules:t-lilypond|ConteXt garden]] or [http://github.com/fiee/ConTeXt/tree/master/t-lilypond/ github] and install it in one of your TeX trees.
 
* Include the lilypond module
 
<texcode>
 
\usemodule[lilypond]
 
</texcode>
 
* If you want, you can change the default settings using <tt>\setuplilypond</tt>
 
* If you need lyrics with accented characters (e.g. umlauts), you '''must''' typeset in UTF-8 encoding (see [[Encodings_and_Regimes]]), because LilyPond doesn't understand anything else. And you need to use UTF-8 without BOM (byte order marker), because ConTeXt doesn't understand BOMs.
 
* Versions from May 2009 on work with LuaTeX ''only.'' Supported is only the latest beta of MkIV.
 
 
 
=== options ===
 
{| style="border: solid 1px black; padding: 0.5em; vertical-align: top; width: 80%;"
 
|- style="border: solid 1px black; padding: 0.5em; vertical-align: top; background: #eeeeee;"
 
! option !! values !! default !! meaning
 
|-
 
| staffsize || number (pt) || 20 || height of the staff
 
|-
 
| linewidth || measure || <cmd>localhsize</cmd> || width of the staff
 
|-
 
| betweensystemspace || measure || 54pt || space between systems
 
|-
 
| align || yes/no || depends on fragment || ragged-right = (not align)
 
|-
 
| indent || measure || 0pt || first line indent
 
|-
 
| time || yes/no || yes || count the time (i.e. show time signature, draw bars, split the staff)?
 
|-
 
| clef || yes/no || yes || show the clef?
 
|-
 
| fragment || yes/no || no || typeset only a snippet (instead of a whole line)?
 
|-
 
| barnumbers || yes/no || no || show measure numbers?
 
|-
 
| showempty || yes/no || no || drop empty staves?
 
|-
 
| seriffont || "name" || "Tex Gyre Schola" || serif font (e.g. for Lyrics and \markup; was Century Schoolbook L before)
 
|-
 
| sansfont || "name" || "LMSans10" || sans serif font (e.g. for chords)
 
|-
 
| monofont || "name" || "LMTypewriter10" || monospace font (normally not used)
 
|-
 
| tmpdir || "name" || "./lilytemp" || directory for temporary files (.tmp, .md5, .eps); gets created if not existant
 
|-
 
| imgdir || "name" || "./lilypdfs" || directory for LilyPond PDFs; gets created if not existant
 
|}
 
 
 
== Snippets ==
 
 
 
<texcode>
 
There are some notes \lilypond{ \relative{bes a c b} } embedded in this line.
 
</texcode>
 
 
 
== Sections ==
 
 
 
E.g. for a songbook you want to place big chunks of LilyPond output (i.e. note staffs) in your text. It behaves like any other graphics, especially similar to embedded [[MetaPost]] code:
 
 
 
<texcode>
 
\section{A Tune}
 
 
 
\startlilypond
 
\relative {
 
\repeat volta 2 {
 
\partial 4 e4 |
 
a2 c4 d |
 
e2 f4 e |
 
d2. c4 |
 
b4. c8 d4 e |
 
a,2 c4 d |
 
e2 f4 e |
 
g,2 a |
 
\partial 2. b2. |
 
}
 
\repeat volta 2 {
 
\partial 4 r4 |
 
f' g f d |
 
e f e c |
 
a b c d |
 
e2. e4 |
 
f g f8 e d4 |
 
e f e c |
 
a c b8 a g4 |
 
}
 
\alternative {
 
{ \partial 2. g2. }
 
{ \partial 2. a2. }
 
}
 
}
 
\stoplilypond
 
 
 
There's nothing to say about this tune yet; someone heard it from Lúnasa.
 
</texcode>
 
 
 
<texcode>
 
\section{Starlight (round)}
 
 
 
\startlilypond
 
<<
 
\context Staff = onlyone <<
 
\clef treble
 
\key a \major
 
\time 6/8
 
\context Voice = one {
 
\relative c'' {
 
a4.^\markup{1.} e' |
 
e8( d cis) b4. |
 
e4.^\markup{2.} d4 d8 |
 
cis( b) a b4 e,8 |
 
a4 a8 gis( a) b |
 
cis4 cis8 b( cis d) |
 
cis( d) e e4 e,8 |
 
fis4 fis8 gis4.
 
}
 
}
 
>>
 
\lyricsto one \new Lyrics {
 
\lyricmode {
 
Star -- light, star -- bright,
 
first star I see to -- night;
 
I wish I may, I wish I might
 
have the wish I wish to -- night.
 
}
 
}
 
>>
 
 
 
\stoplilypond
 
</texcode>
 
 
 
== Font hints ==
 
 
 
LilyPond depends on the fonts that pango/fontconfig can find. But not even all of those will work, e.g. no fonts from the TeX tree (don't know why), only one face per font file etc.
 
Therefore it doesn't use ConTeXt's font setup.
 
 
 
If you want to know which fonts of your system LilyPond can see with which names, try
 
lilypond -dshow-available-fonts any
 
(The 3rd parameter is necessary, but can be anything.)
 
 
 
LilyPond's default text font is Century Schoolbook. You can use it in ConTeXt like this:
 
 
 
<texcode>
 
\usetypescriptfile[type-otf]
 
 
 
\starttypescript[wiki][songbook]
 
\usetypescript [serif] [schoolbook]
 
\definetypeface [songbook] [rm] [serif] [schola] [default]
 
\definetypeface [songbook] [ss] [sans]  [default][default]
 
\definetypeface [songbook] [tt] [mono]  [default][default]
 
\stoptypescript
 
 
 
\usetypescript [wiki] [songbook]
 
\setupbodyfont[songbook, rm, 8.5pt]
 
</texcode>
 
 
 
== Current workarounds ==
 
 
 
This section lists workarounds needed in some circumstances; we surely hope to move them to [[#Older_Workarounds|'''Older Workarounds''']] as soon as possible!
 
 
 
=== Something (LilyPond, GhostScript etc.) isn't found ===
 
 
 
Depending on your setup (path, installation directories, ...) you must call the lilypond app with the full path.
 
 
 
If <tt>pstopdf</tt> can't create PDFs (but LilyPond has made EPS files) it might be that you must set the environment variable <tt>GS_LIB</tt> for GhostScript.
 
 
 
=== LilyPond pre-2.12 ===
 
 
 
The module as of 2009-05-03 works only with LilyPond 2.12 (probably also with some versions of 2.11).
 
 
 
For older versions of LilyPond please use an older version of the module. 2008-09 fits LilyPond 2.10
 
 
 
=== Typesetting fret diagrams ===
 
 
 
Lilypond has commands to typeset fret diagrams for the guitar chords. The most important one is called <code>\fret-diagram</code> and if you want to use it, you need to play a bit with the catcode of the <code>minus</code> sign since ConTeXt is apparently confused by this. In addition, you can't type the example found in [http://lilypond.org/doc/v2.10/Documentation/user/lilypond/Overview-of-text-markup-commands#index-g_t_0040code_007bfret_002ddiagram_007d-935 the Lilypond documentation] on its own because Lilypond won't accept a score with only markup (the fret diagram) and nothing else; you have to place the markup on the page.
 
 
 
All in all, something like this will work:
 
 
 
<texcode>
 
\usemodule[lilypond]
 
\starttext
 
\catcode`\-=11
 
 
 
D chord:
 
\blank
 
 
 
\startlilypond
 
d'' ^ \markup { \fret-diagram #"s:0.75;f:1;6-x;5-x;4-o;3-2-1;2-3-3;1-2-2;" }
 
\stoplilypond
 
\catcode`\-=12
 
 
 
\stoptext
 
</texcode>
 
 
 
If you find a real solution to the <code>catcode</code> problem, please document it here, or report it to the list -- [[User:Arthur|Arthur]]
 
 
 
== Developer's Corner ==
 
 
 
For information how the integration works, please check the module code and its PDF version (both available from [[modules:t-lilypond|LilyPond on Modules]]).  Unlike <tt>lilypond-book</tt> for LaTeX, the module does not use a precompiling step and thus can react to local width changes and the like, even if the LilyPond code is stored in a buffer.
 
 
 
Known bugs:
 
* LilyPond's EPS bounding box is sometimes a bit too small, so sometimes the content is cropped. Perhaps call eps2eps or the like to fix that?
 
 
 
Things that have not been implemented yet include:
 
* work with existing PDFs on systems where LilyPond isn't installed.
 
* make lilypond call back on ConTeXt for included TeX (cf. [http://lsr.dsi.unimi.it/LSR/Item?id=107])
 
* get information from LilyPond about the baseline, for run-in music fragments
 
* tell LilyPond how much space is left on the first page
 
* check and probably work on proper multi-page music
 
* it's not possible to set variables in LilyPond
 
* lots of features
 
 
 
To remember:
 
* see [http://lilypond.org/doc/v2.12/Documentation/ LilyPond Docs]!
 
 
 
--[[User:ChristopherCreutzig|Christopher Creutzig]] after ideas by [[User:Hraban|Hraban]]
 
 
 
== Older Workarounds ==
 
 
 
'''Beware: These relate to the old version of the module and older versions of LilyPond (earlier than 2.7)! Nowadays, LilyPond and epstopdf get called via texmfstart, that works without patching!'''
 
 
 
=== Fonts with ConTeXt MkII ===
 
 
 
For the latest versions of the module work with ConTeXt MkIV (LuaTeX) exclusively, so we moved this to "Older":
 
 
 
<texcode>
 
\starttypescript[wiki][songbook]
 
\usetypescript [serif] [schoolbook] [\defaultencoding]
 
\definetypeface [songbook] [rm] [serif] [schoolbook] [default] [encoding=\defaultencoding]
 
\definetypeface [songbook] [ss] [sans]  [default][default] [encoding=ec]
 
\definetypeface [songbook] [tt] [mono]  [default][default] [encoding=ec]
 
\stoptypescript
 
 
 
\usetypescript [wiki] [songbook]
 
\setupbodyfont[songbook, rm, 8.5pt]
 
</texcode>
 
 
 
=== LilyPond is not found ===
 
 
 
Calling lilypond from command line in Windows fails.
 
 
 
You have two options:
 
* modify the module, so that lilypond is called with the whole path (<code>C:/prog/lilypond/usr/bin/lilypond</code> for example instead of <code>lilypond</code> alone).
 
* place a <code>lilypond.bat</code> somewhere in your search path, calling
 
c:/prog/lilypond/usr/bin/lilypond %1 %2 %3 %4 %5 %6 %7 %8 %9
 
 
 
Calling lilypond from ConTeXt via shell exit (write18) in MacOS X also fails, even if the shell's path is right. (Seems more like write18 wouldn't use the environment.) Modify the module (try <tt>which lilypond</tt> to get its path).
 
 
 
LilyPond 2.7.26 comes without a command line "version", at least in the MacOS X edition, i.e. the <tt>lilypond.sh</tt> script is missing.
 
Here's it's relevant content:
 
 
 
#!/bin/sh
 
## where was the app installed?
 
INSTALLDIR=/Applications
 
 
if [ "$1" == "--print-appdir" ]; then
 
  echo "$INSTALLDIR/LilyPond.app/"
 
  exit 0
 
fi
 
 
# where to put the output
 
export LILYPOND_DESTDIR=`pwd`
 
 
# run the program
 
python "$INSTALLDIR/LilyPond.app/Contents/Resources/lilycall.py" \
 
  "$INSTALLDIR/LilyPond.app/" $@
 
 
 
Save this as <tt>lilypond.sh</tt>, make it executable and symlink it into a directory on your path, e.g.
 
chmod a+x lilypond.sh
 
sudo ln -s lilypond.sh /usr/local/bin/lilypond
 
  
=== LilyPond stops with an 'Unbound variable' error ===
+
The old LilyPond module (t-lilypond) doesn't work any more with recent versions of ConTeXt, therefore we removed its documentation here.
  
The [http://modules.contextgarden.net/t-lilypond LilyPond module] as of 2005-09-12 uses some commands in its header that work only with LilyPond 2.6 (at least no more with 2.7.25); replace "ly:parser-print-score" with "print-score-with-defaults" and "ly:music-scorify" with "scorify-music" for LilyPond 2.7 series.
 
  
 
[[Category:Modules]]
 
[[Category:Modules]]
[[Category:Requests]]
 

Revision as of 23:09, 20 January 2013

< Graphics | Using Graphics >

LilyPond is a great music engraver, and you can include LilyPond in ConTeXt source using the filter module with some setup.

Simple Filter Setup

This works with ConTeXt MkII and MkIV, but takes only the first page of multi-pages scores, and you must create the folder "lilytemp" manually:

\def\readPDFfile#1{\externalfigure[#1]}

\usemodule[filter]
\defineexternalfilter[lilypond]
	[continue=yes,
	readcommand=\readPDFfile,
	directory=lilytemp/, % directory for LilyPond's files
	output={\externalfilterbasefile.pdf},
	filtercommand={lilypond -dbackend=eps -dno-gs-load-fonts -dinclude-eps-fonts -ddelete-intermediate-files -o"lilytemp/\externalfilterbasefile" "\externalfilterinputfile"}]

Multi Page Filter Setup

This uses Lua and therefore only works with ConTeXt MkIV. It includes all pages of multi-page scores. It doesn’t look into the complete (multi-page) PDF, but reads a "-system.count" auxiliary file written by LilyPond that contains the number of systems (pages) and includes the single-system PDFs.

\def\ParseLilypondFile#1% #1 is the name of the output file
  {\ctxlua{thirddata.parselilypondfile("#1")}}

\startluacode
 thirddata = thirddata or {}
 
 -- create temp folder if missing
 if not lfs.isdir('lilytemp') then
   lfs.mkdir('lilytemp')
 end
 
 function thirddata.parselilypondfile(name)
   -- include all systems (pages)
   -- name is like lilytemp/mainfile-temp-lilypond-21.pdf
   logs.report("LILYPOND name='" .. name .. "'")
   syco = 0
   for ts in io.lines(string.gsub(name, '%.pdf$', '-systems.count')) do
     syco = ts*1
   end
   
   for nr = 1, syco do
     logs.report("LILYPOND including system no." .. nr)
     context("\\externalfigure[" .. string.gsub(name, '%.pdf$', '-' .. nr) .. "]")
   end
 end
\stopluacode

\usemodule[filter]
\defineexternalfilter[lilypond]
	[continue=yes,
	readcommand=\ParseLilypondFile,
	directory=lilytemp/,
	output={\externalfilterbasefile.pdf},
	filtercommand={lilypond -dbackend=eps -dinclude-eps-fonts -dno-gs-load-fonts -o"lilytemp/\externalfilterbasefile" "\externalfilterinputfile"}]


LilyPond Settings

Collect your LilyPond settings in a .ly file, put it in your lilytemp directory and include it from within your lilypond block like this:

\startlilypond
\include "mysettings.ly"
...
\stoplilypond

Named Buffers

Normally, your LilyPond snippets just get a running number. If you re-order your scores, each one gets re-rendered.

You might want to add [name=\currentcomponent] (or name=mymusic) to \startlilypond to avoid unnecessary re-rendering.

Example

(TODO: This is old and might contain deprecated or non-working code. Unchecked.)

Here's an example of placing score snippets in the body of the text, with fonts in the score & body matching:

\unprotect

\usemodule[filter]

\traceexternalfilters

\defineexternalfilter
  [lilypond]
  [\c!output=\externalfilterbasefile.pdf,
   \c!filtercommand=\lilypondcommand,
   \c!continue=\v!yes,
   \c!readcommand=\readlilypondoutput,
   %\c!directory=output,
  ]

% frame=on is for testing
\def\readlilypondoutput#1{\setupfloats[location=right,frame=off]\placefigure[]{From \sc{http://lsr.dsi.unimi.it/LSR/Search?q=piano}}{\externalfigure[#1]}}

\def\lilypondcommand%
	{lilypond -dbackend=eps -dno-gs-load-fonts -dinclude-eps-fonts \externalfilterinputfile}
\protect

\setuplayout[textwidth=6in] % matches line-width below
\usetypescript[palatino]
\setupbodyfont[palatino,13pt]

\starttext

\input zapf 

\startlilypond
\layout{
  indent=0\mm
  ragged-right = ##f
}
\paper  {
	myStaffSize = #20
	#(define fonts
	  (make-pango-font-tree "palatino"
		"palatino"
		"palatino"
               (/ myStaffSize 20))) 
  line-width=6\in
  oddFooterMarkup=##f
  oddHeaderMarkup=##f
  bookTitleMarkup = ##f
  scoreTitleMarkup = ##f
 }
global = {
  \key c \major
  \time 4/4
}

sopMusic = \relative c'' {
  c4 c c8[( b)] c4
}
sopWords = \lyricmode {
  hi hi hi hi
}

altoMusic = \relative c' {
  e4 f d e
}
altoWords =\lyricmode {
  ha ha ha ha
}

tenorMusic = \relative c' {
  g4 a f g
}
tenorWords = \lyricmode {
  hu hu hu hu
}

bassMusic = \relative c {
  c4 c g c
}
bassWords = \lyricmode {
  ho ho ho hø
}

\score {
  <<
    \new ChoirStaff <<
      \new Lyrics = "sopranos"
      \new Staff = "women" <<
        \new Voice = "sopranos" { \voiceOne << \global \sopMusic >> }
        \new Voice = "altos" { \voiceTwo << \global \altoMusic >> }
      >>
      \new Lyrics = "altos"
      \new Lyrics = "tenors"
      \new Staff = "men" <<
        \clef bass
        \new Voice = "tenors" { \voiceOne << \global \tenorMusic >> }
        \new Voice = "basses" { \voiceTwo << \global \bassMusic >> }
      >>
      \new Lyrics = "basses"
      \context Lyrics = "sopranos" \lyricsto "sopranos" \sopWords
      \context Lyrics = "altos" \lyricsto "altos" \altoWords
      \context Lyrics = "tenors" \lyricsto "tenors" \tenorWords
      \context Lyrics = "basses" \lyricsto "basses" \bassWords
    >>
    \new PianoStaff <<
      \new Staff <<
        \set Staff.printPartCombineTexts = ##f
        \partcombine
        << \global \sopMusic >>
        << \global \altoMusic >>
      >>
      \new Staff <<
        \clef bass
        \set Staff.printPartCombineTexts = ##f
        \partcombine
        << \global \tenorMusic >>
        << \global \bassMusic >>
      >>
    >>
  >>
}
\stoplilypond
\input zapf
\stoptext

Deprecation

The old LilyPond module (t-lilypond) doesn't work any more with recent versions of ConTeXt, therefore we removed its documentation here.