%D \module
%D   [       file=t-lilypond,
%D        version=2006.09.27,
%D          title=\CONTEXT\ User Modules,
%D       subtitle=Lilypond Connections (Music Typesetting),
%D         author=Christopher Creutzig \& Henning Hraban Ramm,
%D           date=\currentdate,
%D      copyright=Christopher Creutzig]

%M \usemodule[lilypond]

%D This module serves to include lilypond music directly in the
%D \CONTEXT\ source, just as \METAPOST\ code can be.  Before starting
%D with the implementation, one or two examples are in order.
%D \startbuffer[sample]
%D \startlilypond
%D % Telemann, TWV 40:11
%D \version "2.9.18"
%D 
%D \relative c' {
%D \set Staff.instrumentName = flute
%D \key fis \minor
%D \time 3/4
%D \partial 4
%D 
%D    r8 fis'8 | fis4. cis8 a cis | fis, a cis fis a fis |
%D    b, d fis b d b | eis,, gis cis eis gis b, |
%D    a fis' gis, fis' cis eis | fis,4 r8
%D    a' gis fis | e gis, a e' fis cis |
%D    d fis, gis b e d | cis4 \trill r8
%D    cis b a | b dis e gis cis, b |
%D    a e' dis fis b, a | gis4 \trill r8
%D }
%D \stoplilypond
%D \stopbuffer
%D
%D The input
%D
%D \typebuffer[sample]
%D
%D is typeset as
%D
%D \getbuffer[sample]
%D
%D \type{\startlilypond} accepts options, as in\crlf
%D \type{\startlilypond[staffsize=24, linewidth=14cm, indent=5cm, time=no]}:
%D 
%D \nobreak
%D \startlilypond[staffsize=24,linewidth=14cm,indent=5cm,time=no]
%D \version "2.9.18"
%D \relative c' {
%D \set Staff.instrumentName = flute
%D \key fis \minor
%D \time 3/4
%D \partial 4
%D    r8 fis'8 | fis4. cis8 a cis | fis, a cis fis a fis |
%D    b, d fis b d b | eis,, gis cis eis gis b, |
%D    a fis' gis, fis' cis eis | fis,4 r8
%D    a' gis fis | e gis, a e' fis cis |
%D    d fis, gis b e d | cis4 \trill r8
%D    cis b a | b dis e gis cis, b |
%D    a e' dis fis b, a | gis4 \trill r8
%D }
%D \stoplilypond
%D
%D It is also possible to mix text and music:
%D \lower 8.2pt\hbox{\lilypond[fragment=true,staffsize=16,time=no]{g'}} is a g.
%D
%D TODO: Complete list of options.
%D
%D \startlines
%D  staffsize=20,
%D  indent=0pt,
%D  time=yes,
%D  align=?, % default depends on fragment=...
%D  fragment=no,
%D  barnumbers=no,
%D \stoplines
%D
%D TODO: The \type{\lower} in the example above should not be necessary.
%D
%D TODO: Switches to turn off the clef etc.
%D
%D TODO: Proper support for multipage results.
%D
%D TODO: lilypond -> \CONTEXT.
%D
%D \page
%D Now for the implementation.  As usual, we use a prefix for buffers,
%D \type{\getparameters} etc.:

\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.
\bgroup
\catcode`\/=\@@escape
/catcode`/\=/@@other
/catcode`/#=/@@other
/catcode`/<=/@@begingroup
/catcode`/>=/@@endgroup
/catcode`/{=/@@other
/catcode`/}=/@@other
/catcode`/%=/@@other
/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
%#(set! toplevel-score-handler print-score-with-defaults)/string^^J
%#(set! toplevel-music-handler 
  (lambda (p m) 
   (if (not (eq? (ly:music-property m 'void) #t)) 
        (print-score-with-defaults 
         p (scorify-music m p)))))/string^^J
/string^^J
#(ly:set-option (quote no-point-and-click))/string^^J
/string^^J
#(define version-seen #t)/string^^J
%\version "2.9.18"/string^^J
/iflily!time/else
% switch off time signature/string^^J
\layout {
  ragged-last = ##t
  \context {
   \Score
    timing = ##f
  }/string^^J
  \context {
   \Staff
    \remove "Time_signature_engraver"
  }
}/string^^J
/fi
/iflily!barnumbers/else
% switch off bar numbers/string^^J
\layout {
 \context {
  \Score
   \remove "Bar_number_engraver"
 }
}/string^^J
/fi
\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
}/string^^J
>

/gdef/lily!hash<#>
/egroup

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

\newcount\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{\dosingleempty\dosetuplilypond}

\def\dosetuplilypond[#1]{%
   \getparameters[\??lily][#1]%
}

%D We set the following defaults:
\setuplilypond
  [staffsize=20,
   indent=0pt,
   time=\v!yes,
   align=?,% default depends on fragment=...
   fragment=\v!no,
   barnumbers=\v!no,
   ]

%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{\dosingleempty\dostartlilypond}

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

\long\def\dodostartlilypond[#1]#2\stoplilypond{%
   \egroup% from \dostartlilypond
   \bgroup%
%D The default of the \type{linewidth} parameter is the local
%D \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
%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
%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
   \startmode[*\v!first]% 
   \def\obeyedlines{\string^^J}%
   \convertargument#2\to\ascii
   \expanded{%
   \setbuffer[lilypond-\the\lily!figures]%
   \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
   }%
   \endbuffer%
%D Generating a pdf directly always creates a whole page, so we generate eps first.
%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.)
	\def\LP{texmfstart --ifchanged=\bufferprefix lilypond-\the\lily!figures.tmp --exec bin:lilypond -b eps -dno-gs-load-fonts -dinclude-eps-fonts \bufferprefix lilypond-\the\lily!figures.tmp}
	\def\PDF{texmfstart --ifchanged pstopdf  \bufferprefix lilypond-\the\lily!figures.eps}
	
   \ifeof18
   	\installprogram{\LP}%
	 \doif\jobsuffix{pdf}{%
	      \installprogram{\PDF}%
	  }%
   \else
      \executesystemcommand{\LP}%
      \doif\jobsuffix{pdf}{%
	\executesystemcommand{\PDF}%
      }%
   \fi
   \stopmode% only first run
   \doifelse\jobsuffix{pdf}
     {\edef\lily!img{\bufferprefix lilypond-\the\lily!figures.pdf}}%
     {\edef\lily!img{\bufferprefix lilypond-\the\lily!figures.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 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.
   \ifvmode
      \getfiguredimensions[\bufferprefix lilypond-\the\lily!figures.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}

\protect
%D End of file
