%D \module
%D	[		 file=t-lilypond,
%D		    version=2007.09.02,
%D		         title=\CONTEXT\ User Modules,
%D		   subtitle=LilyPond Connections (Music Typesetting),
%D		    author={Christopher Creutzig, Henning Hraban Ramm, Mojka Miklavec},
%D	          date=\currentdate,
%D	          copyright=Christopher Creutzig]
%C
%C	This module licensed under the GNU GPL.

%D This module serves to include LilyPond music directly in the
%D \CONTEXT\ source, just as \METAPOST\ code can be.
%D It should work from LilyPond version 2.8, but you should always use 
%D the latest stable version of LilyPond (this is tested with 2.10.29).
%D
%D {\bfa Complete list of options:}
%D
%D \starttabulate[|l|l|l|]
%D	\NC	option\NC	default\NC	comment\NC\NR
%D	\HL
%D	\NC	staffsize\NC	20\NC	 in pt	\NC\NR
%D	\NC	indent\NC	0pt\NC	 first line indent	\NC\NR
%D	\NC	time\NC	yes\NC	 count time? (i.e. show time signature, set bars, split line)	\NC\NR
%D	\NC	clef\NC	yes\NC	 show clef?	\NC\NR
%D	\NC	linewidth\NC	\\localhsize\NC		\NC\NR
%D	\NC	betweensystemspace\NC	54pt\NC	space between systems	\NC\NR
%D	\NC	height\NC	\\textheight\NC		\NR
%D	\NC	align\NC	?\NC	 default depends on fragment=...	\NC\NR
%D	\NC	fragment\NC	no\NC		\NC\NR
%D	\NC	barnumbers\NC	no\NC	 show numbers of measures?	\NC\NR
%D	\NC	showempty\NC	no\NC	 drop empty staves?	\NC\NR
%D	\NC	seriffont\NC	"Century Schoolbook L"\NC	 font for e.g. lyrics	\NC\NR
%D	\NC	sansfont\NC	"LMSans10"\NC	 font for e.g. chords	\NC\NR
%D	\NC	monofont\NC	"Courier" \NC	 normally not used	\NC\NR
%D \stoptabulate
%D
%D TODO: Proper support for multipage results.
%D
%D TODO: LilyPond ---> \CONTEXT.
%D
%D As usual, we use a prefix for buffers, \type{\getparameters} etc.:

\writestatus{loading}{LilyPond module}
\startmodule[lilypond]

\unprotect
\def\??lily{lilypond-}

%D Define the text snippets to be placed around fragments.
%D Since LilyPond uses similar syntax to TeX, we must do some catcode fiddling.
\def\lily!slash{/}

\bgroup
\catcode`\/=\@@escape
/catcode`/\=/@@other
/catcode`/#=/@@other
/catcode`/<=/@@begingroup
/catcode`/>=/@@endgroup
/catcode`/{=/@@other
/catcode`/}=/@@other
/catcode`/%=/@@other
/catcode`/-=/@@letter
/gdef/lily!fragmentprefix<
/string^^J
/string^^J
{/string^^J
% ly snippet contents follows:/string^^J
>

/gdef/lily!fragmentsuffix</string^^J
% end ly snippet/string^^J
}/string^^J
>

/gdef/lily!prefix</string^^J
/string^^J
#(ly:set-option (quote no-point-and-click))/string^^J
/string^^J
\version "2.10.29"/string^^J
#(define version-seen? #t)/string^^J
\layout {/string^^J
/iflily!time/else
% switch off time signature (i.e. only one line, no bars)/string^^J
	ragged-last = ##t/string^^J
	\context { \Score timing = ##f }/string^^J
	\context { \Staff \remove "Time_signature_engraver" }/string^^J
/string^^J/fi
/iflily!barnumbers/else
% switch off bar numbers/string^^J
	\context { \Score \remove "Bar_number_engraver" }/string^^J
/fi
/string^^J
/iflily!showempty/else
% drop empty staves/string^^J
	\context { \RemoveEmptyStaffContext }/string^^J
	\context { \Score \override VerticalAxisGroup #'remove-first = ##t }/string^^J
/fi
/string^^J
/iflily!clef/else
% switch off clef sign/string^^J
	\context { \Staff \remove "Clef_engraver" }/string^^J
/fi
/string^^J
	#(define fonts
		(make-pango-font-tree
		/lilypond-seriffont/space
		/lilypond-sansfont/space
		/lilypond-monofont/space
	(/lily!slash/space/lilypond-staffsize/space 20)))/string^^J
/string^^J
}/string^^J
\paper {/string^^J
	#(define dump-extents #t)/string^^J
	ragged-right = /iflily!align ##f/else ##t/fi/string^^J
	indent = /withoutpt/the/lily!indent\pt/string^^J
	line-width = /withoutpt/the/lily!linewidth\pt/string^^J
	vsize = /withoutpt/the/lily!vsize\pt/string^^J
	printpagenumber = ##f/string^^J
	oddFooterMarkup=##f/string^^J
	oddHeaderMarkup=##f/string^^J
	bookTitleMarkup = ##f/string^^J
	scoreTitleMarkup = ##f/string^^J
	ragged-bottom=##t/string^^J
	ragged-last-bottom=##t/string^^J
	between-system-padding = #0/string^^J
	between-system-space = /withoutpt/the/lily!betweensystemspace\pt/string^^J
}/string^^J
>

/gdef/lily!hash<#>
/egroup

\newdimen\lily!linewidth
\newdimen\lily!vsize
\newdimen\lily!indent
\newdimen\lily!betweensystemspace
\newif\iflily!align
\newif\iflily!clef
\newif\iflily!time
\newif\iflily!barnumbers
\newif\iflily!showempty

\newcounter\lily!figures

%D Again, as usual, there is a \type{\setuplilypond} command
%D that accepts the same parameters as \type{\lilypond} and
%D \type{\startlilypond} do in their optional argument.

\def\setuplilypond{%
  \start\catcode`\#=\@@other%
  \dosingleempty\dosetuplilypond%
}

\def\dosetuplilypond[#1]{%
  \stop% restore \catcode`\#
  \getparameters[\??lily][#1]%
}

%D We set the following defaults:
\setuplilypond
	[staffsize=20,
	indent=0pt,
	betweensystemspace=54pt,
	time=\v!yes,
	clef=\v!yes,
	align=?,	% default depends on fragment=...
	fragment=\v!no,
	barnumbers=\v!no,
	showshowemptyempty=\v!no,
	seriffont="Century Schoolbook L", % LilyPond default font
	sansfont="LMSans10",
	monofont="Bitstream Vera Sans Mono",
	]

%D If you want to know which fonts of your system LilyPond can see
%D with which names, try \type{lilypond -dshow-available-fonts any}.
%D (The 3rd parameter is necessary, but can be anything.)
%D There are a lot of restrictions, e.g. no fonts from the \TeX\ tree (don't know why),
%D only one face per font file etc.

%D \type{\startlilypond} is a multistage implementation, because
%D end-of-line characters must be treated specially in the
%D \type{\startlilypond}\textellipsis\type{\stoplilypond} range.
\def\startlilypond{%
	\bgroup%
	\catcode`\#=\@@other%
	\dosingleempty\dostartlilypond%
}

\def\dostartlilypond[#1]{%
	\obeylines%
	\dodostartlilypond[{#1}]%
}

\long\def\dodostartlilypond[#1]#2\stoplilypond{%
	\egroup% from \startlilypond
	\bgroup%
%D The default of the \type{linewidth} parameter is the local \type{\hsize}.
	\setlocalhsize
	\getparameters[\??lily][linewidth=\the\localhsize,height=\the\textheight,#1]%
	\lily!linewidth\dimexpr\getvalue{\??lily linewidth}\relax
	\lily!vsize\dimexpr\getvalue{\??lily height}\relax
	\lily!indent\dimexpr\getvalue{\??lily indent}\relax
	\lily!betweensystemspace\dimexpr\getvalue{\??lily betweensystemspace}\relax
%D The default of \type{align} depends on whether we typeset a fragment:
	\@EAEAEA\doifelse\getvalue{\??lily align}{\v!yes}%
		\lily!aligntrue\lily!alignfalse
	\@EAEAEA\doif\getvalue{\??lily fragment}{\v!no}{%
		\@EAEAEA\doif\getvalue{\??lily align}?
			\lily!aligntrue
	}%
	\@EAEAEA\doifelse\getvalue{\??lily time}\v!yes
		\lily!timetrue\lily!timefalse
	\@EAEAEA\doifelse\getvalue{\??lily barnumbers}\v!yes
		\lily!barnumberstrue\lily!barnumbersfalse
	\@EAEAEA\doifelse\getvalue{\??lily showempty}\v!yes
		\lily!showemptytrue\lily!showemptyfalse
	\@EAEAEA\doifelse\getvalue{\??lily clef}\v!yes
		\lily!cleftrue\lily!cleffalse
%D We are using a counter to keep the different LilyPond pieces
%D separate.	This allows to typeset them only once, during the
%D first run.
%D
%D TODO: This won't work any longer once we pass the remaining
%D vertical space to LilyPond.
	%\global\advance\lily!figures\plusone
	\doglobal\increment\lily!figures
	\edef\lily!filename{\bufferprefix lilypond-\lily!figures}%\the
	%\writestatus{buffering}{\lily!filename}
	%\startmode[*\v!first]% 
	\def\obeyedlines{\string^^J}%
	\convertargument#2\to\ascii
	\expanded{%
	\setbuffer[lilypond-\lily!figures]%\the
	\lily!prefix
	\lily!hash(set-global-staff-size \getvalue{\??lily staffsize})\string^^J%
	\ifundefined{\??lily fragment}\else\lily!fragmentprefix\fi
	%% TODO: Option "packed"
	\ascii%
	\ifundefined{\??lily fragment}\else\lily!fragmentsuffix\fi
	}% expanded
	\endbuffer%
%D
%D Generating a PDF directly always creates a whole page, so we generate EPS first.
%D
%D If \type{\ifeof18} creates an error for you, your pdfe\TeX\ is too old.
%D just change it to \type{\iftrue} then.
%D (\type{\ifeof18} checks whether \type{\write18} is disabled.)
	
	%\def\LP{echo LILYPOND \lily!filename.tmp}
	%\def\PDF{echo PStoPDF \lily!filename.eps}
	\def\LP{texmfstart --ifchanged=\lily!filename.tmp --exec bin:lilypond -b eps -dno-gs-load-fonts -dinclude-eps-fonts \lily!filename.tmp}
	\def\PDF{texmfstart --ifchanged=\lily!filename.eps pstopdf \lily!filename.eps}
%D The following line is needed for Lua\TeX, where buffers are kept in memory
%D in contrast to other (older) flavours of \TeX\ where they're written to a
%D file automatically. We have to require writing to a file explicitely
%D with \type{\savebuffer}.
	\ifx\directlua\undefined \else \savebuffer[lilypond-\the\lily!figures]\fi
%D
%D If \type{\ifeof18} creates an error for you, your pdfetex is too old.
%D just change it to \iftrue then.	 (\type{\ifeof18} checks whether \type{\write18}
%D is disabled.)
%D
	\ifeof18
		%\writestatus{DEBUG-w18}{\LP}%
		\expanded{\installprogram{\LP}}%
		\doif\jobsuffix{pdf}{%
			\installprogram{\PDF}%
		}%
	\else
		%\writestatus{DEBUG-EXE}{\LP}%
		\executesystemcommand{\LP}%
		\doif\jobsuffix{pdf}{%
			\executesystemcommand{\PDF}%
		}%
	\fi
	%\stopmode% only first run
	\doifelse\jobsuffix{pdf}
		{\def\lily!img{\lily!filename .pdf}}%
		{\def\lily!img{\lily!filename .eps}}%
%D
%D TODO: Get the relevant dimension directly from LilyPond,
%D to place the instrument name into the left margin for
%D short snippets as well.
%D
%D If we are not in the middle of some text, we have to check
%D whether LilyPond created an image that is wider than requested:
%D It places the instrument names in the left margin.
%D
	\ifvmode
		\getfiguredimensions[\lily!filename.pdf]%
		\leavevmode%
		\newdimen\FigWidth
		\FigWidth=\figurewidth
		\ifdim\FigWidth>\localhsize
			\!!dimena=\localhsize
			\advance\!!dimena by-\FigWidth
			\noindent\hskip\!!dimena
		\fi
	\fi
	\externalfigure[\lily!img]%
	\egroup%
}%

%D For short snippets, we define an inline alternative to
%D our start/stop pair:
\def\lilypond{\dosingleempty\dolilypond}

\def\dolilypond[#1]#2{\startlilypond[#1]#2\stoplilypond}

\stopmodule

\protect \doifnotmode{demo}{\endinput}
%D End of file

\starttext

\startbuffer[sample]
\subject{Telemann, TWV 40:11}
\startlilypond
	\relative c' {
		\set Staff.instrumentName = flute
		\key fis \minor
		\time 3/4
		\partial 4
		r8 fis'8 | fis4. cis8 a cis | fis, a cis fis a fis |
		b, d fis b d b | eis,, gis cis eis gis b, |
		a fis' gis, fis' cis eis | fis,4 r8
		a' gis fis | e gis, a e' fis cis |
		d fis, gis b e d | cis4 \trill r8
		cis b a | b dis e gis cis, b |
		a e' dis fis b, a | gis4 \trill r8
	}
\stoplilypond
\stopbuffer

The input
\typebuffer[sample]
is typeset as
\getbuffer[sample]

\type{\startlilypond} accepts options, as in\crlf
\type{\startlilypond[staffsize=24, linewidth=14cm, indent=5cm, time=no, clef=no]}:
\nobreak
\startlilypond[staffsize=18,linewidth=14cm,indent=5cm,time=no,clef=no]
	\relative c' {
		\key fis \minor
		\time 3/4
		\partial 4
		r8 fis'8 | fis4. cis8 a cis | fis, a cis fis a fis |
		b, d fis b d b | eis,, gis cis eis gis b, |
		a fis' gis, fis' cis eis | fis,4 r8
		a' gis fis | e gis, a e' fis cis |
		d fis, gis b e d | cis4 \trill r8
		cis b a | b dis e gis cis, b |
		a e' dis fis b, a | gis4 \trill r8
	}
\stoplilypond

It is also possible to mix text and music:
\lower 8.2pt\hbox{\lilypond[fragment=true,staffsize=16,time=no]{g'}} is a g.

(Seems like this still doesn't work...)

TODO: The \type{\lower} in the example above should not be necessary.

\stoptext