Difference between revisions of "LilyPond"
(define LilyPond temp folder as variable) |
(fixes use of logs.report and string.gsub) |
||
Line 41: | Line 41: | ||
-- include all systems (pages) | -- include all systems (pages) | ||
-- name is like \LILYTEMP/mainfile-temp-lilypond-21.pdf | -- name is like \LILYTEMP/mainfile-temp-lilypond-21.pdf | ||
− | logs.report("LILYPOND name='" .. name .. "'") | + | logs.report("LILYPOND","name='" .. name .. "'") |
− | syco = 0 | + | local syco = 0 |
− | + | local scname = string.gsub(name, '%.pdf$', '-systems.count') | |
+ | for ts in io.lines(scname) do | ||
syco = ts*1 | syco = ts*1 | ||
end | end | ||
for nr = 1, syco do | for nr = 1, syco do | ||
− | logs.report("LILYPOND including system no." .. nr) | + | logs.report("LILYPOND","including system no." .. nr) |
context("\\externalfigure[" .. string.gsub(name, '%.pdf$', '-' .. nr) .. "]") | context("\\externalfigure[" .. string.gsub(name, '%.pdf$', '-' .. nr) .. "]") | ||
end | end |
Revision as of 15:09, 15 August 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.
Contents
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\LILYTEMP{lilytemp} % name of folder for LilyPond/buffer files \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 .. "'") local syco = 0 local scname = string.gsub(name, '%.pdf$', '-systems.count') for ts in io.lines(scname) 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
Sample Include File
"mysettings.ly" could look like this:
\version "2.16.0" #(ly:set-option (quote no-point-and-click)) #(set-global-staff-size 14) % --- start of setup for single-line output files --- #(define default-toplevel-book-handler print-book-with-defaults-as-systems ) #(define toplevel-book-handler (lambda ( . rest) (set! output-empty-score-list #f) (apply print-book-with-defaults rest))) #(define toplevel-music-handler (lambda ( . rest) (apply collect-music-for-book rest))) #(define toplevel-score-handler (lambda ( . rest) (apply collect-scores-for-book rest))) #(define toplevel-text-handler (lambda ( . rest) (apply collect-scores-for-book rest))) #(set! output-empty-score-list #t) % --- stop single-line setup --- \paper { #(define dump-extents #t) indent = 0\mm ragged-bottom = ##t ragged-last-bottom = ##t print-page-number = ##f line-width = 120\mm oddFooterMarkup = ##f oddHeaderMarkup = ##f bookTitleMarkup = ##f scoreTitleMarkup = ##f } \layout { #(layout-set-staff-size 14) % beware, this resets fonts! % set fonts for rm / ss / tt #(define fonts (make-pango-font-tree "TeX Gyre Schola" "LMSans10" "LMTypewriter10 Regular" (/ 14 20))) \context { \Score \remove "Bar_number_engraver" \override PaperColumn #'keep-inside-line = ##t } \context { \Staff \override TimeSignature #'style = #'numbered } \context { \ChordNames chordChanges = ##t majorSevenSymbol = \markup{ 7+ } } }
Please look up the meaning of settings in LilyPond’s great documentation!
Unfortunately it’s not possible to exchange measures like text width between ConTeXt and LilyPond (at least I’ve no idea how), so you must define sizes manually. And you can’t define LilyPond’s text (lyrics) size with an absolute value, but only relative to staff size...
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.