From f1346920f64c571a1475d3ded295b9637560c6bc Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Thu, 31 Aug 2000 13:11:43 +0200 Subject: [PATCH] release: 1.3.82 ====== * engraver.ly: cleanups. * etf2ly: robustness fixes, handle mac files as well. * Smobified Translator and Translator_group, junked Translator_group_identifier. * \pushproperty and \popproperty withing \translator, similar to predefining \property, ie. \translator { [...] \pushproperty [..] } \translator { [...] \popproperty [..] } (these \pushes and \pops are delayed until instantiation, so if you do \score { \pushproperty #'basicFooProperties #'bla #VALUE1 \context Voice { \pushproperty #'basicFooProperties #'bar #VALUE2 [..] } } then the setting for basicFooProperties contains both (bla . VALUE1) and (bar . VALUE2). * allow \pushproperty #'symbol [..] as well as \pushproperty #'(symbol1 symbol2 ... ) 1.3.81.j --- CHANGES | 45 +- .../ntweb/guile-1.3.4-gnu-windows.patch | 0 Documentation/regression-test.tely | 2 +- Documentation/user/mudela-book.tely | 392 ++++++++++-------- VERSION | 4 +- buildscripts/pmx2ly.py | 25 ++ configure | 70 ++-- ...gle-acc.ly => accidental-single-double.ly} | 5 +- input/test/pushproperty.ly | 22 +- input/trip.ly | 2 + lily/audio-element-info.cc | 16 +- lily/auto-change-iterator.cc | 2 +- lily/axis-group-engraver.cc | 12 +- lily/axis-group-interface.cc | 8 +- lily/bar-engraver.cc | 2 +- lily/bar-number-engraver.cc | 22 +- lily/break-align-engraver.cc | 7 + lily/change-iterator.cc | 2 +- lily/clef-engraver.cc | 26 +- lily/engraver-group-engraver.cc | 33 +- lily/grace-engraver-group.cc | 6 - lily/grace-performer-group.cc | 7 +- lily/identifier.cc | 8 +- lily/include/audio-element-info.hh | 2 +- lily/include/grace-engraver-group.hh | 1 - lily/include/grace-performer-group.hh | 1 - lily/include/identifier.hh | 3 - lily/include/lyric-phrasing-engraver.hh | 2 +- lily/include/music-iterator.hh | 27 +- lily/include/music-wrapper-iterator.hh | 1 - lily/include/sequential-music-iterator.hh | 2 - lily/include/translation-property.hh | 6 + lily/include/translator-group.hh | 48 ++- lily/include/translator.hh | 23 +- lily/key-engraver.cc | 10 +- lily/lexer.ll | 5 +- lily/lyric-phrasing-engraver.cc | 274 +----------- lily/mark-engraver.cc | 18 +- lily/music-iterator.cc | 5 - lily/music-output-def.cc | 9 +- lily/music-wrapper-iterator.cc | 7 - lily/parser.yy | 30 +- lily/part-combine-music-iterator.cc | 25 +- lily/performer-group-performer.cc | 52 ++- lily/performer.cc | 3 +- lily/piano-pedal-engraver.cc | 11 +- lily/property-engraver.cc | 11 +- lily/property-iterator.cc | 35 +- lily/repeat-engraver.cc | 2 +- lily/score-element.cc | 5 +- lily/score-performer.cc | 2 +- lily/score.cc | 3 +- lily/sequential-music-iterator.cc | 8 - lily/syllable-group.cc | 268 ++++++++++++ lily/translator-group-initializer.cc | 95 +++++ lily/translator-group.cc | 373 +++++++++-------- lily/translator.cc | 101 ++++- lily/voice-devnull-engraver.cc | 33 +- ly/engraver.ly | 281 +++++++------ make/out/lilypond.lsm | 8 +- make/out/lilypond.spec | 4 +- mutopia/Coriolan/coriolan-paper.ly | 2 +- .../Coriolan/coriolan-part-combine-paper.ly | 2 +- scm/generic-property.scm | 2 +- scripts/abc2ly.py | 5 +- scripts/etf2ly.py | 77 +++- scripts/mudela-book.py | 145 +++++-- 67 files changed, 1576 insertions(+), 1169 deletions(-) delete mode 100644 Documentation/ntweb/guile-1.3.4-gnu-windows.patch create mode 100644 buildscripts/pmx2ly.py rename input/test/{double-single-acc.ly => accidental-single-double.ly} (71%) create mode 100644 lily/syllable-group.cc create mode 100644 lily/translator-group-initializer.cc diff --git a/CHANGES b/CHANGES index c40a746004..cb52b11d60 100644 --- a/CHANGES +++ b/CHANGES @@ -1,19 +1,36 @@ ---- ../lilypond-1.3.81/CHANGES Mon Aug 28 11:59:46 2000 -++ b/CHANGES Sat Sep 2 23:13:32 2000 -@@ -1,3 +1,13 @@ -1.3.80.tca1 -=========== -* Added Documentation/user/mb-latex.tex, mudela-book+latex example - file and test case. Some work on Documentation/user/mudela-book.tely +1.3.82 +====== + +* engraver.ly: cleanups. + +* etf2ly: robustness fixes, handle mac files as well. + +* Smobified Translator and Translator_group, junked +Translator_group_identifier. + -* mudela-book.py: any combination of \verb, \begin{verbatim} - @code and @example and mudela should work as expected. +* \pushproperty and \popproperty withing \translator, similar to +predefining \property, ie. -* dropped [].extend that depend on python 1.5.2 + \translator { [...] \pushproperty [..] } + \translator { [...] \popproperty [..] } - 1.3.80.gp1 - ========== - 1.3.81.jcn1 +(these \pushes and \pops are delayed until instantiation, so if you do + + + \score { + \pushproperty #'basicFooProperties #'bla #VALUE1 + \context Voice { \pushproperty #'basicFooProperties #'bar #VALUE2 + [..] + } + } + +then the setting for basicFooProperties contains both (bla . VALUE1) +and (bar . VALUE2). + +* allow \pushproperty #'symbol [..] as well as \pushproperty #'(symbol1 symbol2 ... ) + +1.3.81.jcn1 =========== * Activated regex for windows. @@ -22,6 +39,8 @@ * Added configure messages for metapost checking. +1.3.81 +====== 1.3.80.gp1 ========== diff --git a/Documentation/ntweb/guile-1.3.4-gnu-windows.patch b/Documentation/ntweb/guile-1.3.4-gnu-windows.patch deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Documentation/regression-test.tely b/Documentation/regression-test.tely index 39ae494574..c157ffa346 100644 --- a/Documentation/regression-test.tely +++ b/Documentation/regression-test.tely @@ -67,7 +67,7 @@ A sharp sign after a double sharp sign, as well as a flat sign after a double flat sign is automatically prepended with a natural sign. -@mudelafile{double-single-acc.ly} +@mudelafile{accidental-single-double.ly} @section Stems diff --git a/Documentation/user/mudela-book.tely b/Documentation/user/mudela-book.tely index 5eb5410c9d..6c7bdacef2 100644 --- a/Documentation/user/mudela-book.tely +++ b/Documentation/user/mudela-book.tely @@ -1,7 +1,8 @@ \input texinfo @c -*-texinfo-*- @setfilename mudela-book.info @settitle mudela-book Manual -@afourpaper + + @titlepage @title mudela-book Manual @subtitle Integrating mudela with La@TeX{} and TeXinfo @@ -67,21 +68,16 @@ except that this permission notice may be stated in a translation approved by the Free Software Foundation. @end ifinfo -@tex -\def\preMudelaExample{\vspace{0.5cm}} -@end tex -@contents + @node Top, , , (dir) @top - @section Introduction -[TODO: THIS MANUAL IS NOT FINISHED YET. FIXME.] +[TODO: THIS MANUAL IS OUTDATED. FIXME.] -@ignore Mudela-book is a script that process your La@TeX{} file and with great help from GNU LilyPond it translates blocks of mudela code it finds inside @code{mudela} environments to tex or eps graphics. It then @@ -92,194 +88,252 @@ Mudela-book will do its best to try to align the music to the left and right margins. Currently the most used papersizes and one- and twocolumn mode is supported, but if you use the geometry-package from La@TeX{} or change the margins things will break. -@end ignore - -@file{mudela-book} is a script that helps integrating mudela and -La@TeX{} or mudela and TeXinfo. mudela-book runs Lilypond on fragments -of mudela in your source file, and includes the results into a -document that can be processed with La@TeX{}, makeinfo or texi2dvi. -The result is a text document with formatted music integrated. This document assumes you have basic knowledge of GNU LilyPond and -La@TeX{} or texinfo. +La@TeX{}. -@ignore -Mudela-book will do its best to try to align the music to the left and -right margins. Currently the most used papersizes and twocolumn mode -in La@TeX{} are supported. But if you change the margins, things will break. -@end ignore - -@section Tutorial when using TeXinfo - -It is easies to learn by examples. A theme by Vagn Holmboe: - -@mudela[mbverbatim, intertext="will produce this music:"] +So what does this look like? Well, here is an example: +@mudela[veryverbatim, intertext="produces this music:"] \score{ \notes\relative c'{ \time 5/8; [e16( g b c a g][e a b d] | )e2 d,8 | [e16( g b c a g][e a b d] | )b2 [a16( f] | [e a b d] )e4 c8 | [es16( bes a as g es][d c b! )g] | - [f( a b d b a][f a b d] | )e2 [f16( e] | [f, a b d] )e4. | - [a,16 a a a a a][a a a a] + [f( a b d b a][f a b d] | )e2 } } @end mudela - - -You can see that mudela code is put between the @code{@@mudela} -and @code{@@end mudela} command. Mudela-book will insert some -code before sending your mudela code to Lilypond, to make the -music respect the margins. So the mudela code that was actually -sendt to Lilypond, will be something like this (removed the -music to save space): - +If you are lucky, the above example show a nice feature of LilyPond +and La@TeX{}. Since LilyPond can output the music as @TeX{} graphics, +La@TeX{} can insert pagebreaks between the lines of music. + +Notice that there is no @code{\paper} statement in the example +above. Mudela-book will insert some code for you that defines the +linewidth and the font to use. If you don't want to change the default, +there is no need to put an empty @code{\paper@{@}} inside the @code{\score}. +In the example above, something like +this might be inserted before your code: @example \include "paper16.ly" -\paper @{ linewidth = 455.00000 \pt; @} - -\score@{ - YOUR MUDELA CODE +\paper@{ \paper_sixteen + linewidth = 390.\pt; + castingalgorithm = \Gourlay; @} @end example +The actual values for linewidth will differ depending on papersize and +number of columns. Also, if you use a different fontsize for the +music, another file than @code{paper16.ly} will be included. -Compare the previous examples with this short block: +If you want to make the music not so wide, you can insert a +@code{\paper} statement that set the linewidth: -@mudela[mbverbatim, intertext="that produces this music:"] -c' d' e' +@mudela[veryverbatim, intertext="produces this music:"] +\score{ + \notes\relative c'{ + \time 5/8; + [e16( g b c a g][e a b d] | )e2 d,8 | + [e16( g b c a g][e a b d] | )b2 [a16( f] | + [e a b d] )e4 c8 | [es16( bes a as g es][d c b! )g] | + [f( a b d b a][f a b d] | )e2 + } + \paper{linewidth = 10.\cm;} +} @end mudela -You can see that the mudela code is -not complete, there are no @code{\score} keyword. This made -mudela-book threat the content of the block a little different. -This will be fed Lilypond: -@example -\include "paper16.ly" -\paper @{ linewidth = -1.00000 \pt; @} -\score @{ - \notes @{ - YOUR MUDELA CODE - @} - \paper@{ @} -@} -@end example - -@code{linewidth = -1.00000 \pt;} tell Lilypond not to break -the music. If you enter too much music, the music will go -beyond the right margin. +Very often, if you mix music and text, the music is often only a +few notes or at most a few bars. This music should be as short as +possible and not stretched to be aligned to the right margin. -You can set the linewidth yourself: +If you only write voice-contents in the mudela block, mudela-book +will set the @code{linewidth} variable to -1, so Lilypond +will make the music as short as possible but without breaking the +line. Here is a well know harmonic progression: +@mudela[veryverbatim, intertext="produce a well known harmonic progression:"] + +@end mudela -@mudela[mbverbatim, intertext="produces this music:"] -\score{ - \notes\relative c'{c d e f | g a b c | c b a g | f e d c} - \paper { indent = 0.0 \cm; linewidth = 4.0 \cm; } -} +If you want to place music examples in the text, +@mudela[eps] + @end mudela +, you can use the @code{eps} option. This will create the music as +eps graphics and include it into the document with the +@code{\includegraphics} command. -There is also a short version of the @code{@@mudela} command. -The code -@example -@@mudela@{ YOUR MUDELA CODE @} +The code used look like this: +@example +@@mudela[eps] + +@@end mudela @end example -is short for - +You can also use the @code{eps} option if the block is a complete +mudela source. This 5 cm long empty line, +@mudela[eps] +\score{ + \notes{s} + \paper{ linewidth = 5.\cm;} +} +@end mudela +was created with this code: @example -@@mudela -\context Staff \context Voice @{ YOUR MUDELA CODE @} +@@mudela[eps] +\score@{ + \notes@{s@} + \paper@{ linewidth = 5.\cm;@} +@} @@end mudela @end example +To avoid that La@TeX{} places the music on a line of its one, there should +be no empty lines between the normal text and the mudela +environment. + +You can also use @code{mudelafile} (on a separate line, FIXME), to +include another file. -@section TeXinfo reference +@section Fontsize options You can use all lilypond fontsizes in +mudela-book. The default 16pt fontsize is probably to big to be +included in the middle of the text, 11pt or 13pt is probably better. -Your code should look something like this: +The code can look like this: @example -@@mudela[options, go, here] - YOUR MUDELA CODE +@@mudela[13pt, eps] + @@end mudela @end example -or +The following options set the fontsize: +@itemize +@item @code{11pt} +@mudela[11pt, eps] + \relative c'{ + r16 [c d e][f d e c] [g'8 c][b-\prall c] | + [d16 g, a b][c a b g][d'8 g f-\prall g] + } +@end mudela +@item @code{13pt} +@mudela[13pt, eps] + \relative c'{ + r16 [c d e][f d e c] [g'8 c][b-\prall c] | + [d16 g, a b][c a b g][d'8 g f-\prall g] + } +@end mudela +@item @code{16pt} +@mudela[16pt, eps] + \relative c'{ + r16 [c d e][f d e c] [g'8 c][b-\prall c] | + [d16 g, a b][c a b g][d'8 g f-\prall g] + } +@end mudela +@item @code{20pt} +@mudela[20pt, eps] + \relative c'{ + r16 [c d e][f d e c] [g'8 c][b-\prall c] | + [d16 g, a b][c a b g][d'8 g f-\prall g] + } +@end mudela +@item @code{26pt} +@mudela[26pt, eps] + \relative c'{ + r16 [c d e][f d e c] [g'8 c][b-\prall c] | + [d16 g, a b][c a b g][d'8 g f-\prall g] + } +@end mudela +@end itemize -@example -@@mudela[option, go, here]@{ YOUR MUDELA CODE @} -@end example -Mudelabook knows the default margins, and this papersizes: -@itemize @bullet -@item @code{@@afourpaper} -@item @code{@@afourwide} -@item @code{@@smallbook} +@section More options +@itemize +@item The @code{singleline} option set @code{linewidth} to -1.0. +@item The @code{multiline} option set @code{linewidth} to a value letting +the music be aligned to the right margin. The music can span several +lines. @end itemize -@code{@@pagesizes} are not supported. +@section Just in case... +The options @code{fragment} and @code{nonfragment} will override +mudela-book when it scans the mudela code to see if it is voice +contents or complete code. This might be useful if mudela-book choose +wrong. -@section La@TeX{} reference +Since there is no finder's fee which doubles every year, there is no +need to wait for the price money to grow. So send a bug report today +if you need this one of these options. -@example -\begin[option, go, here]@{mudela@} - YOUR MUDELA CODE -\end@{mudela@} -@end example +@section Examples -@example -\mudela@{ YOUR MUDELA CODE @} -@end example +This was all options to @code{\begin}. The rest of the mudela +document will show some ways you can use mudela in +La@TeX{} documents. It will also act as a simple test-suite for +mudela-book. You can place @code{eps} mudela in and marginspars just +as any other included eps graphics. -The 'geometry' package is is not supported. The most popular -papersizes should work. +@mudela +\score{ + \notes\relative c'{ + \time 12/8; + r4-\fermata [b16-.( )b-.] [f'8-- dis16-.( )dis-. gis8--] + [f16-.( )f-. dis8-- gis16-.( )gis-.] cis4.-\fermata | + + r4.-\fermata [cis,16 cis g'8 f16 f b8][g16 g f8 b16 b] dis4.-\fermata + } + \paper{linewidth = 7.\cm;} +} +@end mudela -Mudela-book know about the @code{\onecolumn} and -@code{\twocolumn} commands. -@section Options +To the right you can see some bars from the trumpet fanfara from the +beginning of the fantastic street opera ``Houdini the Great'', by the +Danish composer Andy Pape. The music is put inside a +@code{floatingfigure} environment, and the music will be aligned by +the right marging if you set floatingfigure width and mudela linewidth +to the same value. The code looks like this: -@table @samp -@item eps - the music is created as eps graphics that can be inserted in - the middle of a text line, not only as a separate paragraph. - (La@TeX{} only) -@item verbatim - CONTENTS is copied into the TeX source enclosed in a verbatim block. -@item 11pt, 13pt, 16pt, 20pt, 26pt - set the fontsize to use for the music -@item singleline - linewidth = -1. -@item multiline - linewidth = textwidth -@item fragment -@item nonfragment - Override mudela-book autodetection of what type of code is in the - mudela block, voice contents or complete code. -@end table +@mudela[verbatim] +\score{ + \notes\relative c'{ + \time 12/8; + r4.-\fermata [b16-.( )b-.] [f'8-- dis16-.( )dis-. gis8--] + [f16-.( )f-. dis8-- gis16-.( )gis-.] cis8.-\fermata | + + r4.-\fermata [cis,16 cis g'8 f16 f b8] + [g16 g f8 b16 b] dis4.-\fermata + } + \paper{linewidth = 7.\cm;} +} +@end mudela + +If you have a lot of small music examples like this in the middle of +your text, you might get a nicer look by using ``double'' line +spacing. Put the @code{\linespread@{1.6@}} command into the preamble of +your document. Then the line spacing will not be increased between the +lines where you have music printed with the smallest font size. + +Mudela-book does know about @code{\onecolumn} and @code{\twocolumn}. +So the music will be adjusted to the new linewith: + +Verbatim environments will also ignore the page margins. That is +a feature of La@TeX{}. (But you usually put things inside a verbatim +environment when you don't want La@TeX{} to do any linebreaking) @section Texinfo behavior + [TODO] @section Invocation + @file{mudela-book} is a script that helps integrating mudela and La@TeX{}. mudela-book runs LilyPond on fragments of mudela in your source file, and includes the results into document that can be processed with La@TeX{}. The result is a text document with formatted music integrated. -@example -mudela-book -M --outdir=out inputfile.tely -@end example -will create @code{out/inputfile.texi}, depencencies in -@code{out/inputfile.dep} and lots of other files in @code{out/} - -If you are processing a latex file, the file to give to -latex has ext @file{.latex} +Lilypond will by default create all output files in directory @file{out}. +The file to give to latex has ext @file{.latex}. -If you are processing a texinfo file, you can use the -@code{--no-pictures} command line optino if you are not going -to create html output. - -@ignore @strong{About the input} If the file contains the ``block'' @@ -299,48 +353,48 @@ defined to nothing by default, and the user can redefine them to whatever he wants. @code{\begin} takes the following options: -@end ignore +@table @samp +@item eps + the music is created as eps graphics that can be inserted in + the middle of a text line, not only as a separate paragraph +@item verbatim + CONTENTS is copied into the TeX source enclosed in a verbatim block. +@item 11pt, 13pt, 16pt, 20pt, 26pt + set the fontsize to use for the music +@item singleline + linewidth = -1. +@item multiline + linewidth = textwidth +@item fragment +@item nonfragment + Override mudela-book autodetection of what type of code is in the + mudela block, voice contents or complete code. +@end table -@subsection Command line options @table @samp -@item -f, --format= - Specify the document type to process, @code{latex} or @code{texi}. - @file{mudela-book} usually figure out this automatically. -@item --default-music-fontsize=??pt +@item --default-mudela-fontsize=??pt Set the fontsize to use for mudela if no fontsize is given as option. -@item --force-music-fontsize=??pt +@item --force-mudela-fontsize=??pt Force all mudela to use this fontsize, overriding options given to \begin@{mudela@} -@item -I DIR, --include=DIR - include path -@item -M, --dependencies - Write dependencies to out-www/filename.dep -@item --dep-prefix=PREF - prepend PREF before each -M dependency -@item -n, --no-lily - don't run lilypond -@item --no-pictures - don't generate pictures -@item --read-lys - don't write ly files. This way you can do - @example - mudela-book file.tely - convert-mudela - mudela-book --read-lys - @end example @item --outname=FILE The name of La@TeX{} file to output. If this option is not given, - the output name derived from the input name. -@item --outdir= - where to place generated files -@item --version - print version information +the output name derived from the input name. +@item --out-www=DIRECTORY + The name of the directory to output lilypond output and input to. + This must be a name; the subdirectory will be created in the cwd. [FIXME] @item --help Print a short help message +@item --dependencies + Write dependencies to out-www/filename.dep +@item --force-verbatim + Make all mudela verbatim. +@item --initfile=FILE + read command definitions from @file{FILE} @end table @@ -356,16 +410,12 @@ The La@TeX{} \includeonly@{...@} command is ignored. Ignores almost all La@TeX{} commands that changes margins and linewidths. -La@TeX{} comments can confuse mudela-book: -@example -% this music will be displayed: \mudela@{c d e@} -@end example - @section Authors @email{hanwen@@cs.uu.nl, Han-Wen Nienhuys}, @uref{http://www.cs.uu.nl/people/hanwen} -@email{tca@@gnu.org, Tom Cato Amundsen} +@email{tomato@@xoommail.com, Tom Cato Amundsen} + @bye diff --git a/VERSION b/VERSION index a3a3c8c7a9..7992718877 100644 --- a/VERSION +++ b/VERSION @@ -1,8 +1,8 @@ PACKAGE_NAME=LilyPond MAJOR_VERSION=1 MINOR_VERSION=3 -PATCH_LEVEL=81 -MY_PATCH_LEVEL=tca1 +PATCH_LEVEL=82 +MY_PATCH_LEVEL= # use the above to send patches: MY_PATCH_LEVEL is always empty for a # released version. diff --git a/buildscripts/pmx2ly.py b/buildscripts/pmx2ly.py new file mode 100644 index 0000000000..58d32cb4bb --- /dev/null +++ b/buildscripts/pmx2ly.py @@ -0,0 +1,25 @@ +#!@PYTHON@ +import string + +ls = open ('barsant.pmx').readlines () +def stripcomment (l): + return re.sub ('^%.*$', '', l) + +ls = map (stripcomment, ls) +ls = filter (lambda x: x <> '', ls) + +opening = ls[0] +ls = ls[1:] + +opening = map (string.atoi, re.split ('[\t ]+', opening)) +(nv,noinst,mtrnuml,mtrdenl,mtrnump,mtrdenp,xmtrnum0,isig) = tuple (opening) + + +opening = ls[0] +ls = ls[1:] +opening = map (string.atoi, re.split ('[\t ]+', opening)) +(npages,nsyst,musicsize,fracindent) = tuple (opening) + +for l in ls: + pass + diff --git a/configure b/configure index 2b07fc6941..9a6dc78d56 100755 --- a/configure +++ b/configure @@ -2703,20 +2703,26 @@ echo "configure:2699: checking for working metafont mode" >&5 break; fi done + echo "$ac_t""$MFMODE" 1>&6 + echo $ac_n "checking for mfplain.mp""... $ac_c" 1>&6 +echo "configure:2710: checking for mfplain.mp" >&5 # # For now let people define these in their environments # : ${MFPLAIN_MP=`kpsewhich mp mfplain.mp`} + echo "$ac_t""$MFPLAIN_MP" 1>&6 + echo $ac_n "checking for inimetapost flags""... $ac_c" 1>&6 +echo "configure:2718: checking for inimetapost flags" >&5 if test ${INIMETAPOST} = "inimp" ; then : ${INIMETAPOST_FLAGS=''} else : ${INIMETAPOST_FLAGS='-interaction=nonstopmode'} fi + echo "$ac_t""$INIMETAPOST_FLAGS" 1>&6 rm -f mfput.* - echo "$ac_t""$MFMODE" 1>&6 @@ -2741,7 +2747,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2745: checking for $ac_word" >&5 +echo "configure:2751: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_KPSEWHICH'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2772,7 +2778,7 @@ done test -n "$KPSEWHICH" || KPSEWHICH="no" echo $ac_n "checking for tfm path""... $ac_c" 1>&6 -echo "configure:2776: checking for tfm path" >&5 +echo "configure:2782: checking for tfm path" >&5 TFM_FONTS="cmr msam" @@ -2800,13 +2806,13 @@ echo "configure:2776: checking for tfm path" >&5 ## First, let's just see if we can find Guile at all. echo $ac_n "checking "for guile-config"""... $ac_c" 1>&6 -echo "configure:2804: checking "for guile-config"" >&5 +echo "configure:2810: checking "for guile-config"" >&5 for guile_config in guile-config $target-guile-config $build-guile-config; do echo "$ac_t"""$guile_config"" 1>&6 if ! $guile_config --version > /dev/null 2>&1 ; then echo "configure: warning: "cannot execute $guile_config"" 1>&2 echo $ac_n "checking "if we are cross compiling"""... $ac_c" 1>&6 -echo "configure:2810: checking "if we are cross compiling"" >&5 +echo "configure:2816: checking "if we are cross compiling"" >&5 guile_config=error else break @@ -2817,7 +2823,7 @@ echo "configure:2810: checking "if we are cross compiling"" >&5 exit 1 fi echo $ac_n "checking "Guile version"""... $ac_c" 1>&6 -echo "configure:2821: checking "Guile version"" >&5 +echo "configure:2827: checking "Guile version"" >&5 need_guile_version="1.3.4" guile_version=`expr "\`$guile_config --version 2>&1\`" : ".*\($need_guile_version\).*"` echo "$ac_t"""$guile_version"" 1>&6 @@ -2830,7 +2836,7 @@ echo "configure:2821: checking "Guile version"" >&5 ## The GUILE_FLAGS macro. echo $ac_n "checking for Guile""... $ac_c" 1>&6 -echo "configure:2834: checking for Guile" >&5 +echo "configure:2840: checking for Guile" >&5 if ! $guile_config link > /dev/null ; then echo "$ac_t"""cannot execute $guile_config"" 1>&6 { echo "configure: error: "cannot find guile-config; is Guile installed?"" 1>&2; exit 1; } @@ -2845,7 +2851,7 @@ echo "configure:2834: checking for Guile" >&5 # Extract the first word of "guile", so it can be a program name with args. set dummy guile; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2849: checking for $ac_word" >&5 +echo "configure:2855: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_GUILE'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2895,17 +2901,17 @@ fi do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2899: checking for $ac_hdr" >&5 +echo "configure:2905: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2909: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2915: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2932,7 +2938,7 @@ fi done echo $ac_n "checking for kpse_find_file in -lkpathsea""... $ac_c" 1>&6 -echo "configure:2936: checking for kpse_find_file in -lkpathsea" >&5 +echo "configure:2942: checking for kpse_find_file in -lkpathsea" >&5 ac_lib_var=`echo kpathsea'_'kpse_find_file | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2940,7 +2946,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lkpathsea $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2964: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2987,12 +2993,12 @@ fi for ac_func in kpse_find_file do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2991: checking for $ac_func" >&5 +echo "configure:2997: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3028: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3047,7 +3053,7 @@ done fi echo $ac_n "checking whether to use kpathsea""... $ac_c" 1>&6 -echo "configure:3051: checking whether to use kpathsea" >&5 +echo "configure:3057: checking whether to use kpathsea" >&5 if test $kpathsea_b = yes; then echo "$ac_t""yes" 1>&6 KPATHSEA=1 @@ -3065,7 +3071,7 @@ EOF echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6 -echo "configure:3069: checking for 8-bit clean memcmp" >&5 +echo "configure:3075: checking for 8-bit clean memcmp" >&5 if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3073,7 +3079,7 @@ else ac_cv_func_memcmp_clean=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3096: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_memcmp_clean=yes else @@ -3104,12 +3110,12 @@ echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6 test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}" echo $ac_n "checking for vprintf""... $ac_c" 1>&6 -echo "configure:3108: checking for vprintf" >&5 +echo "configure:3114: checking for vprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3145: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_vprintf=yes" else @@ -3159,12 +3165,12 @@ fi if test "$ac_cv_func_vprintf" != yes; then echo $ac_n "checking for _doprnt""... $ac_c" 1>&6 -echo "configure:3163: checking for _doprnt" >&5 +echo "configure:3169: checking for _doprnt" >&5 if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3200: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func__doprnt=yes" else @@ -3217,12 +3223,12 @@ fi for ac_func in memmem snprintf vsnprintf gettext isinf do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3221: checking for $ac_func" >&5 +echo "configure:3227: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3258: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3287,7 +3293,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3291: checking for $ac_word" >&5 +echo "configure:3297: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_MAKEINFO'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3320,7 +3326,7 @@ test -n "$MAKEINFO" || MAKEINFO="error" # Extract the first word of "perl", so it can be a program name with args. set dummy perl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3324: checking for $ac_word" >&5 +echo "configure:3330: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else diff --git a/input/test/double-single-acc.ly b/input/test/accidental-single-double.ly similarity index 71% rename from input/test/double-single-acc.ly rename to input/test/accidental-single-double.ly index 923d03e16e..c2d73e131a 100644 --- a/input/test/double-single-acc.ly +++ b/input/test/accidental-single-double.ly @@ -13,6 +13,9 @@ gis g ges g | } \score { < \context Staff \thenotes - \context NoteNames \thenotes + \context NoteNames { + \pushproperty #'basicNoteNameProperties #'no-spacing-rods ##f + \thenotes + } > } diff --git a/input/test/pushproperty.ly b/input/test/pushproperty.ly index 7ca018f9b9..0ab097c1a3 100644 --- a/input/test/pushproperty.ly +++ b/input/test/pushproperty.ly @@ -49,10 +49,6 @@ Incorrect (\popproperty costs memory): \popproperty #'( ... ) #'symbolA \popproperty #'( ... ) #'symbolB - - - - the syntax isn't likely to stay, so it is advisable to use identifiers, eg. @@ -64,15 +60,21 @@ use identifiers, eg. \score { \notes \relative c' { - c4( + c4-.( \context Voice \pushproperty #'(basicDotsProperties basicStemProperties basicNoteColumnProperties basicScriptProperties basicTextProperties) #'direction #-1 - ) c4 ( - ) c4 ( - \context Voice \pushproperty #'(basicSlurProperties) #'direction #-1 - ) c4 ( \context Voice \popproperty #'(basicDotsProperties basicStemProperties + ) c4-. ( + ) c4-. ( + \context Voice \pushproperty #'basicSlurProperties #'direction #-1 + ) c4-. ( \context Voice \popproperty #'(basicDotsProperties basicStemProperties basicScriptProperties basicTextProperties) #'direction - ) c4 () c4 + ) c4-. () c4-. +} + +\paper { +\translator { \VoiceContext + \pushproperty #'basicNoteHeadProperties #'font-size #-2 +} } } diff --git a/input/trip.ly b/input/trip.ly index 750a0f6eb7..ed3e877acd 100644 --- a/input/trip.ly +++ b/input/trip.ly @@ -15,6 +15,8 @@ TODO: * tremolo +* lyrics. + %} \version "1.3.59"; diff --git a/lily/audio-element-info.cc b/lily/audio-element-info.cc index 5580b6f0b8..c9f99c7732 100644 --- a/lily/audio-element-info.cc +++ b/lily/audio-element-info.cc @@ -7,11 +7,12 @@ */ #include "audio-element-info.hh" -#include "request.hh" +#include "translator-group.hh" Audio_element_info::Audio_element_info (Audio_element*s_l, Music *r_l) { elem_l_ = s_l; + origin_trans_l_ =0; req_l_ = r_l; } @@ -20,10 +21,19 @@ Audio_element_info::Audio_element_info() { elem_l_ = 0; req_l_ = 0; + origin_trans_l_ =0; } + Link_array -Audio_element_info::origin_trans_l_arr (Translator*) const +Audio_element_info::origin_trans_l_arr (Translator* end) const { - return origin_trans_l_arr_; + Translator * t = origin_trans_l_; + Link_array r; + do { + r.push (t); + t = t->daddy_trans_l_; + } while (t && t != end->daddy_trans_l_); + + return r; } diff --git a/lily/auto-change-iterator.cc b/lily/auto-change-iterator.cc index 2c9de1f717..0ae3021d46 100644 --- a/lily/auto-change-iterator.cc +++ b/lily/auto-change-iterator.cc @@ -49,7 +49,7 @@ Auto_change_iterator::change_to (Music_iterator *it, String to_type, Translator_group * dest = it->report_to_l ()->find_create_translator_l (to_type, to_id); current->remove_translator_p (last); - dest->add_translator (last); + dest->add_group_translator (last); } else { diff --git a/lily/axis-group-engraver.cc b/lily/axis-group-engraver.cc index 606c93ef8b..57d42f3113 100644 --- a/lily/axis-group-engraver.cc +++ b/lily/axis-group-engraver.cc @@ -27,8 +27,7 @@ protected: virtual void process_acknowledged (); virtual Spanner* get_spanner_p () const; virtual void add_element (Score_element*) ; -public: - +public: VIRTUAL_COPY_CONS(Translator); Axis_group_engraver (); }; @@ -83,7 +82,7 @@ Axis_group_engraver::do_removal_processing () && gh_number_p (gh_cdr (dims))) staffline_p_->set_elt_property ("extra-extent-Y", dims); -Score_element * it = unsmob_element (get_property ("currentCommandColumn")); + Score_element * it = unsmob_element (get_property ("currentCommandColumn")); Pointer_group_interface (it, "bounded-by-me").add_element (staffline_p_); staffline_p_->set_bound(RIGHT,it); @@ -98,6 +97,10 @@ Axis_group_engraver::acknowledge_element (Score_element_info i) elts_.push (i.elem_l_); } +/* + maybe should check if our parent_l is set, because we now get a + cyclic parent relationship if we have two Axis_group_engravers in + the context. */ void Axis_group_engraver::process_acknowledged () { @@ -120,8 +123,7 @@ Axis_group_engraver::add_element (Score_element*e) } //////////////////////////////////////////////////////// - -// maybenot sucsh a good idea after all. +// maybenot such a good idea after all., to put classes in .cc #include "hara-kiri-group-spanner.hh" #include "rhythmic-head.hh" diff --git a/lily/axis-group-interface.cc b/lily/axis-group-interface.cc index a156379adb..4d7db9b452 100644 --- a/lily/axis-group-interface.cc +++ b/lily/axis-group-interface.cc @@ -77,11 +77,11 @@ Axis_group_interface::set_axes (Score_element*me,Axis a1, Axis a2) SCM sa1= gh_int2scm (a1); SCM sa2 = gh_int2scm (a2); - SCM prop = me->get_elt_property ("axes"); + SCM axes = me->get_elt_property ("axes"); - if (!gh_pair_p (prop) - || scm_memq (sa1, prop) == SCM_BOOL_F - || scm_memq (sa2, prop) == SCM_BOOL_F) + if (!gh_pair_p (axes) + || scm_memq (sa1, axes) == SCM_BOOL_F + || scm_memq (sa2, axes) == SCM_BOOL_F) { SCM ax = gh_cons (sa1, SCM_EOL); if (a1 != a2) diff --git a/lily/bar-engraver.cc b/lily/bar-engraver.cc index dfa4d906fa..bbb1af8238 100644 --- a/lily/bar-engraver.cc +++ b/lily/bar-engraver.cc @@ -90,7 +90,7 @@ Bar_engraver::do_removal_processing () void Bar_engraver::do_process_music() { - Translator * t = daddy_grav_l ()->get_simple_translator ("Timing_engraver"); + Translator * t = daddy_grav_l ()->get_simple_translator ("Timing_engraver"); // UGH.! Timing_engraver * te = dynamic_cast(t); String which = (te) ? te->which_bar () : ""; diff --git a/lily/bar-number-engraver.cc b/lily/bar-number-engraver.cc index 34a0cb2eae..4fe7d7172f 100644 --- a/lily/bar-number-engraver.cc +++ b/lily/bar-number-engraver.cc @@ -15,18 +15,18 @@ #include "item.hh" #include "moment.hh" #include "engraver.hh" -#include "protected-scm.hh" +#include "translator-group.hh" + class Bar_number_engraver : public Engraver { protected: Item* text_p_; - Protected_scm staffs_; - protected: virtual void do_pre_move_processing (); virtual void acknowledge_element (Score_element_info); + virtual void do_creation_processing (); void create_items(); void do_process_music (); public: @@ -58,9 +58,16 @@ ADD_THIS_TRANSLATOR(Bar_number_engraver); Bar_number_engraver::Bar_number_engraver () { text_p_ =0; - staffs_ = SCM_EOL; } +void +Bar_number_engraver::do_creation_processing () +{ + /* + ugh: need to share code with mark_engraver + */ + daddy_trans_l_->set_property ("staffsFound", SCM_EOL); +} @@ -70,7 +77,10 @@ Bar_number_engraver::acknowledge_element (Score_element_info inf) Score_element * s = inf.elem_l_; if (Staff_symbol::has_interface (s)) { - staffs_ = gh_cons (inf.elem_l_->self_scm (), staffs_); + SCM sts = get_property ("staffsFound"); + SCM thisstaff = inf.elem_l_->self_scm (); + if (scm_memq (thisstaff, sts) == SCM_BOOL_F) + daddy_trans_l_->set_property ("staffsFound", gh_cons (thisstaff, sts)); } else if (text_p_ && dynamic_cast (s) @@ -88,7 +98,7 @@ Bar_number_engraver::do_pre_move_processing () { if (text_p_) { - text_p_->set_elt_property ("side-support-elements", staffs_); + text_p_->set_elt_property ("side-support-elements", get_property ("staffsFound")); typeset_element (text_p_); text_p_ =0; } diff --git a/lily/break-align-engraver.cc b/lily/break-align-engraver.cc index b48f31b25a..aa3bc9760c 100644 --- a/lily/break-align-engraver.cc +++ b/lily/break-align-engraver.cc @@ -19,6 +19,7 @@ class Break_align_engraver : public Engraver Item *align_l_; Protected_scm column_alist_; protected: + virtual void do_removal_processing (); virtual void acknowledge_element(Score_element_info i); virtual void do_pre_move_processing (); void add_column (SCM); @@ -40,6 +41,12 @@ Break_align_engraver::add_column (SCM smob) typeset_element (e); } +void +Break_align_engraver::do_removal_processing () +{ + column_alist_ = SCM_EOL; +} + void Break_align_engraver::do_pre_move_processing () { diff --git a/lily/change-iterator.cc b/lily/change-iterator.cc index 08fdc53271..730e4adc8e 100644 --- a/lily/change-iterator.cc +++ b/lily/change-iterator.cc @@ -66,7 +66,7 @@ Change_iterator::do_process_and_next (Moment m) Translator_group * dest = report_to_l ()->find_create_translator_l (to_type, to_id); current->remove_translator_p (last); - dest->add_translator (last); + dest->add_group_translator (last); } else { diff --git a/lily/clef-engraver.cc b/lily/clef-engraver.cc index df8b2eb23f..d448e71648 100644 --- a/lily/clef-engraver.cc +++ b/lily/clef-engraver.cc @@ -11,6 +11,7 @@ #include +#include "translator-group.hh" #include "key-item.hh" #include "local-key-item.hh" #include "bar.hh" @@ -18,14 +19,14 @@ #include "staff-symbol-referencer.hh" #include "debug.hh" #include "command-request.hh" -#include "array.hh" #include "engraver.hh" #include "direction.hh" #include "side-position-interface.hh" #include "item.hh" /// where is c-0 in the staff? -class Clef_engraver : public Engraver { +class Clef_engraver : public Engraver +{ Item * clef_p_; Item * octavate_p_; Clef_change_req * clef_req_l_; @@ -50,15 +51,11 @@ public: Clef_engraver(); bool first_b_; - - Protected_scm current_settings_; }; Clef_engraver::Clef_engraver() { - current_settings_ = SCM_EOL; - first_b_ = true; clef_glyph_ = SCM_EOL; clef_p_ = 0; @@ -108,13 +105,14 @@ Clef_engraver::set_type (String s) c0_position_i_ -= (int) octave_dir_ * 7; - SCM basic = get_property ("basicClefItemProperties"); - current_settings_ = gh_cons (gh_cons (ly_symbol2scm ("glyph"), clef_glyph_), basic); - current_settings_ = - gh_cons (gh_cons (ly_symbol2scm ("c0-position"), - gh_int2scm (c0_position_i_)), - current_settings_); - + SCM basic = ly_symbol2scm ("basicClefItemProperties"); + SCM c0 = ly_symbol2scm ("c0-position"); + SCM gl = ly_symbol2scm ("glyph"); + daddy_trans_l_->execute_single_pushpop_property (basic, gl, SCM_UNDEFINED); + daddy_trans_l_->execute_single_pushpop_property (basic, c0, SCM_UNDEFINED); + daddy_trans_l_->execute_single_pushpop_property (basic, gl, clef_glyph_); + daddy_trans_l_->execute_single_pushpop_property (basic, c0, gh_int2scm (c0_position_i_)); + return true; } @@ -178,7 +176,7 @@ Clef_engraver::create_clef() { if (!clef_p_) { - Item *c= new Item ( current_settings_); + Item *c= new Item (get_property ("basicClefItemProperties")); announce_element (c, clef_req_l_); Staff_symbol_referencer::set_interface (c); diff --git a/lily/engraver-group-engraver.cc b/lily/engraver-group-engraver.cc index c12283e8e4..847bb5d13e 100644 --- a/lily/engraver-group-engraver.cc +++ b/lily/engraver-group-engraver.cc @@ -27,38 +27,33 @@ Engraver_group_engraver::announce_element (Score_element_info info) void Engraver_group_engraver::do_announces() { - for (Cons *p = trans_p_list_.head_; p; p = p->next_) + for (SCM p = trans_group_list_; gh_pair_p (p); p =gh_cdr ( p)) { - if (Engraver_group_engraver *trg = dynamic_cast (p->car_)) - trg->do_announces (); + Translator * t = unsmob_translator (gh_car (p)); + dynamic_cast (t)->do_announces (); } - + while (announce_info_arr_.size ()) { for (int j =0; j < announce_info_arr_.size(); j++) { Score_element_info info = announce_info_arr_[j]; - for (Cons *p = trans_p_list_.head_; p; p = p->next_) + for (SCM p = simple_trans_list_; gh_pair_p (p); p = gh_cdr (p)) { - if (!dynamic_cast (p->car_)) - { - Engraver * eng = dynamic_cast (p->car_); - if (eng && eng!= info.origin_trans_l_arr (this)[0]) - eng->acknowledge_element (info); - } + Translator * t = unsmob_translator (gh_car (p)); + Engraver * eng = dynamic_cast (t); + if (eng && eng!= info.origin_trans_l_) + eng->acknowledge_element (info); } } - announce_info_arr_.clear (); - for (Cons *p = trans_p_list_.head_; p; p = p->next_) + for (SCM p = simple_trans_list_; gh_pair_p (p); p = gh_cdr ( p)) { - if (!dynamic_cast (p->car_)) - { - Engraver * eng = dynamic_cast (p->car_); - if (eng) - eng->process_acknowledged (); - } + Translator * t = unsmob_translator (gh_car (p)); + Engraver * eng = dynamic_cast (t); + if (eng) + eng->process_acknowledged (); } } } diff --git a/lily/grace-engraver-group.cc b/lily/grace-engraver-group.cc index f7b66a62c3..ae3a2f5a3e 100644 --- a/lily/grace-engraver-group.cc +++ b/lily/grace-engraver-group.cc @@ -85,12 +85,6 @@ Grace_engraver_group::each (Method_pointer method) } -void -Grace_engraver_group::each (Const_method_pointer method) const -{ - if (calling_self_b_) - Engraver_group_engraver::each (method); -} ADD_THIS_TRANSLATOR(Grace_engraver_group); diff --git a/lily/grace-performer-group.cc b/lily/grace-performer-group.cc index fcfad2a339..4bf89fe1da 100644 --- a/lily/grace-performer-group.cc +++ b/lily/grace-performer-group.cc @@ -87,12 +87,7 @@ Grace_performer_group::each (Method_pointer method) } -void -Grace_performer_group::each (Const_method_pointer method) const -{ - if (calling_self_b_) - Performer_group_performer::each (method); -} + /* don't let the commands trickle up. diff --git a/lily/identifier.cc b/lily/identifier.cc index d3d0e7221b..bedc2f9dfd 100644 --- a/lily/identifier.cc +++ b/lily/identifier.cc @@ -11,12 +11,12 @@ JUNKTHIS! */ #include + #include "music-output-def.hh" #include "score.hh" #include "identifier.hh" #include "my-lily-lexer.hh" #include "debug.hh" -#include "translator-group.hh" #include "ly-smobs.icc" @@ -81,8 +81,6 @@ Class ## _identifier::do_print () const { \ } - -DEFAULT_PRINT(Translator_group); DEFAULT_PRINT(Score); DEFAULT_PRINT(Music_output_def); @@ -93,8 +91,6 @@ Class ## _identifier::do_str () const { \ return String (#Class); \ } - -DUMMY_STR(Translator_group); DUMMY_STR(Score); DUMMY_STR(Music_output_def); DUMMY_STR(Duration); @@ -151,10 +147,8 @@ Class ## _identifier::Class ## _identifier (Class ## _identifier const &s) \ IMPLEMENT_ID_CLASS(Duration); -IMPLEMENT_ID_CLASS(Translator_group); IMPLEMENT_ID_CLASS(Score); IMPLEMENT_ID_CLASS(Music_output_def); -VIRTUAL_ACCESSOR(Translator_group); VIRTUAL_ACCESSOR(Music_output_def); DEFAULT_ACCESSOR(Duration); DEFAULT_ACCESSOR(Score); diff --git a/lily/include/audio-element-info.hh b/lily/include/audio-element-info.hh index 2d09970ab4..b3b805ca07 100644 --- a/lily/include/audio-element-info.hh +++ b/lily/include/audio-element-info.hh @@ -19,7 +19,7 @@ struct Audio_element_info { Audio_element * elem_l_; Music *req_l_; - Link_array origin_trans_l_arr_; + Translator * origin_trans_l_; Link_array origin_trans_l_arr (Translator*) const; Audio_element_info (Audio_element*, Music*); diff --git a/lily/include/grace-engraver-group.hh b/lily/include/grace-engraver-group.hh index 5c63b4fd2a..2ba5768a67 100644 --- a/lily/include/grace-engraver-group.hh +++ b/lily/include/grace-engraver-group.hh @@ -28,7 +28,6 @@ protected: virtual void finish (); virtual void process (); virtual void each (Method_pointer); - virtual void each (Const_method_pointer) const; virtual void do_removal_processing () ; virtual void typeset_element (Score_element*); virtual bool do_try_music (Music *m); diff --git a/lily/include/grace-performer-group.hh b/lily/include/grace-performer-group.hh index cfeb9884a0..5b05625b09 100644 --- a/lily/include/grace-performer-group.hh +++ b/lily/include/grace-performer-group.hh @@ -27,7 +27,6 @@ protected: virtual void finish (); virtual void process (); virtual void each (Method_pointer); - virtual void each (Const_method_pointer) const; virtual void do_removal_processing () ; virtual void play_element (Audio_element*); virtual bool do_try_music (Music *m); diff --git a/lily/include/identifier.hh b/lily/include/identifier.hh index 02587ce978..2e39b1ff47 100644 --- a/lily/include/identifier.hh +++ b/lily/include/identifier.hh @@ -15,7 +15,6 @@ #include "smobs.hh" -class Translator_group_identifier; class Output_def_identifier; class Score_identifier; class Duration_identifier; @@ -43,7 +42,6 @@ struct Identifier : public Input { void error (String) const; String str () const; - IDACCESSOR(Translator_group) IDACCESSOR(Music_output_def) IDACCESSOR(Score) IDACCESSOR(Duration) @@ -69,7 +67,6 @@ struct Class ## _identifier : Identifier {\ }\ -DECLARE_ID_CLASS(Translator_group); DECLARE_ID_CLASS(Duration); DECLARE_ID_CLASS(Score); DECLARE_ID_CLASS(Music_output_def); diff --git a/lily/include/lyric-phrasing-engraver.hh b/lily/include/lyric-phrasing-engraver.hh index e00a1c159c..cda6f6584a 100644 --- a/lily/include/lyric-phrasing-engraver.hh +++ b/lily/include/lyric-phrasing-engraver.hh @@ -66,7 +66,7 @@ protected: virtual void acknowledge_element(Score_element_info); virtual void process_acknowledged (); virtual void do_pre_move_processing(); - + virtual void do_removal_processing (); private: void record_notehead(const String &context_id, Score_element * notehead); void record_lyric(const String &context_id, Score_element * lyric); diff --git a/lily/include/music-iterator.hh b/lily/include/music-iterator.hh index d1293bb409..561e9c11eb 100644 --- a/lily/include/music-iterator.hh +++ b/lily/include/music-iterator.hh @@ -37,12 +37,12 @@ protected: Do the actual printing. This should be overriden in derived classes. It is called by #print#, in the public interface */ - virtual void do_print () const; + virtual void do_print() const; /** Find a bottom notation context to deliver requests to. */ - virtual Translator_group* get_req_translator_l (); + virtual Translator_group* get_req_translator_l(); /** Get an iterator for MUS, inheriting the translation unit from THIS. @@ -63,32 +63,32 @@ public: Do the reporting. Will try MUSIC_L_ in its own translator first, then its children. Returns the iterator that succeeded */ - Music_iterator *try_music (Music*) const; + Music_iterator * try_music (Music *) const; /** The translation unit that we this iterator is reporting to now. */ - Translator_group*report_to_l () const; + Translator_group*report_to_l() const; void set_translator (Translator_group*); /** Get an iterator matching the type of MUS, and use TRANS to find an accompanying translation unit */ - static Music_iterator* static_get_iterator_p (Music *); - void init_translator (Music *, Translator_group *); + static Music_iterator* static_get_iterator_p (Music * mus); + void init_translator (Music *, Translator_group *); - Music_iterator (); + Music_iterator(); /// Find the next interesting point in time. - virtual Moment next_moment () const; + virtual Moment next_moment() const; + ///Are we finished with this piece of music? - virtual bool ok () const; + virtual bool ok() const; - virtual ~Music_iterator (); + virtual ~Music_iterator(); - virtual Music *get_next_music (); ///Report all musical information that occurs between now and UNTIL void process_and_next (Moment until); @@ -97,9 +97,8 @@ public: Construct sub-iterators, and set the translator to report to. */ - virtual void construct_children (); - - void print () const; + virtual void construct_children(); + void print() const; }; #endif // MUSIC_ITERATOR_HH diff --git a/lily/include/music-wrapper-iterator.hh b/lily/include/music-wrapper-iterator.hh index a9c5143825..8200709e52 100644 --- a/lily/include/music-wrapper-iterator.hh +++ b/lily/include/music-wrapper-iterator.hh @@ -27,7 +27,6 @@ public: virtual void construct_children () ; virtual Moment next_moment () const; virtual bool ok () const; - virtual Music *get_next_music (); protected: virtual void do_print () const; diff --git a/lily/include/sequential-music-iterator.hh b/lily/include/sequential-music-iterator.hh index 8888e462b9..79f493fa87 100644 --- a/lily/include/sequential-music-iterator.hh +++ b/lily/include/sequential-music-iterator.hh @@ -25,8 +25,6 @@ public: virtual Moment next_moment () const; virtual bool ok () const; - virtual Music* get_next_music (); - protected: virtual void do_print() const; virtual void do_process_and_next (Moment); diff --git a/lily/include/translation-property.hh b/lily/include/translation-property.hh index 0b887470fc..c8a4950783 100644 --- a/lily/include/translation-property.hh +++ b/lily/include/translation-property.hh @@ -39,6 +39,7 @@ public: class Push_translation_property : public Music { public: + VIRTUAL_COPY_CONS(Music); }; /** @@ -51,7 +52,12 @@ public: class Pop_translation_property : public Music { public: + VIRTUAL_COPY_CONS(Music); }; +void apply_push_property (Translator_group*trans, SCM syms, SCM eprop, SCM val); +void apply_pop_property (Translator_group*trans, SCM syms, SCM eprop); + + #endif // PROPERTY_HH diff --git a/lily/include/translator-group.hh b/lily/include/translator-group.hh index 5bb0d08e28..126c232c8d 100644 --- a/lily/include/translator-group.hh +++ b/lily/include/translator-group.hh @@ -14,46 +14,58 @@ #include "lily-proto.hh" #include "virtual-methods.hh" #include "translator.hh" -#include "cons.hh" #include "parray.hh" - +#include "smobs.hh" // egcs typedef void (Translator::*Method_pointer)(void); -typedef void (Translator::*Const_method_pointer)(void) const; + class Scheme_hash_table; + +/* + should make a struct out of this, and move SCM list stuff in here. + */ +struct Translator_group_initializer { + static SCM modify_definition (SCM, SCM, bool); + + static void set_acceptor (Translator*,SCM accepts, bool add); + static void add_element (Translator*,SCM name); + static void remove_element (Translator*,SCM name); + static void add_last_element (Translator*,SCM name); + static void apply_pushpop_property (Translator*trans, SCM syms, SCM eprop, SCM val); + static void add_push_property (Translator*, SCM,SCM,SCM); + static void add_pop_property (Translator*, SCM,SCM); + +}; + /** Make some kind of Elements from Requests. Elements are made by hierarchically grouped Translators */ class Translator_group : public virtual Translator { - Array consists_str_arr_; - Array accepts_str_arr_; - Array consists_end_str_arr_; - Scheme_hash_table *properties_dict_; + Scheme_hash_table *properties_dict () const; int iterator_count_; - friend class Interpretation_context_handle; -protected: - Cons_list trans_p_list_; + friend class Interpretation_context_handle; +protected: + ~Translator_group (); public: + SCM add_translator (SCM, Translator*); + void execute_single_pushpop_property (SCM prop, SCM sym, SCM val); SCM get_property (SCM name_sym) const; void set_property (String var_name, SCM value); void set_property (SCM var_sym, SCM value); Translator_group *where_defined (SCM name_sym) const; String id_str_; - void add_last_element (String s); VIRTUAL_COPY_CONS(Translator); - - void set_acceptor (String accepts, bool add); - void set_element (String elt, bool add); - Translator_group(Translator_group const &); Translator_group(); - void add_translator (Translator *trans_p); + void add_simple_translator (Translator *trans_p); + void add_group_translator (Translator *trans_p); + /// Score_register = 0, Staff_registers = 1, etc) Translator_group* ancestor_l (int l=1); @@ -63,14 +75,12 @@ public: void terminate_translator (Translator*r_l); Translator *remove_translator_p (Translator*trans_l); void check_removal (); - Translator *get_simple_translator (String) const; Translator_group *find_existing_translator_l (String n, String id); Translator_group *find_create_translator_l (String n, String id); Link_array path_to_acceptable_translator (String alias, Music_output_def*) const; Translator_group*get_default_interpreter(); - virtual ~Translator_group (); protected: bool try_music_on_nongroup_children (Music *m); @@ -84,7 +94,7 @@ protected: virtual void do_creation_processing(); virtual void do_removal_processing(); virtual void each (Method_pointer); - virtual void each (Const_method_pointer) const; + }; #endif // TRANSLATOR_GROUP_HH diff --git a/lily/include/translator.hh b/lily/include/translator.hh index a40fd07275..2cca991105 100644 --- a/lily/include/translator.hh +++ b/lily/include/translator.hh @@ -17,12 +17,13 @@ #include "lily-guile.hh" #include "parray.hh" #include "input.hh" - +#include "smobs.hh" /** Make some kind of #Element#s from Requests. Elements are made by hierarchically grouped #Translator#s */ class Translator : public Input { + void init (); public: Music_output_def * output_def_l_; String type_str_; @@ -33,7 +34,6 @@ public: VIRTUAL_COPY_CONS(Translator); Translator (Translator const &); Translator (); - virtual ~Translator (); Translator_group * daddy_trans_l_ ; @@ -65,7 +65,19 @@ public: virtual Moment now_mom () const; -protected: + /* + ugh: bubbled up from Translator_group. + */ + SCM consists_name_list_; + SCM end_consists_name_list_; + SCM accepts_name_list_; + SCM simple_trans_list_; + SCM trans_group_list_; + SCM properties_scm_; + SCM property_pushes_; + DECLARE_SMOBS(Translator, dummy); + +public: /* UGH. Clean this up. */ @@ -78,7 +90,8 @@ protected: PROCESSED_REQS, ACKED_REQS, MOVE_DONE - } status; + } status_; // junkme +protected: /* @see{try_request} @@ -112,5 +125,5 @@ extern Dictionary *global_translator_dict_p; void add_translator (Translator*trans_p); Translator*get_translator_l (String s); - +Translator *unsmob_translator (SCM); #endif // TRANSLATOR_HH diff --git a/lily/key-engraver.cc b/lily/key-engraver.cc index f19ddf1c1f..8fcae86fd2 100644 --- a/lily/key-engraver.cc +++ b/lily/key-engraver.cc @@ -22,7 +22,8 @@ /** Make the key signature. */ -class Key_engraver : public Engraver { +class Key_engraver : public Engraver +{ void create_key(bool); void read_req (Key_change_req const * r); @@ -37,6 +38,7 @@ public: protected: virtual void do_creation_processing(); + virtual void do_removal_processing (); virtual bool do_try_music (Music *req_l); virtual void do_process_music(); virtual void do_pre_move_processing(); @@ -45,6 +47,12 @@ protected: }; +void +Key_engraver::do_removal_processing () +{ + old_accs_ = SCM_EOL; // unprotect can be called from dtor. +} + Key_engraver::Key_engraver () { keyreq_l_ = 0; diff --git a/lily/lexer.ll b/lily/lexer.ll index 90f4ba43f4..09378ba961 100644 --- a/lily/lexer.ll +++ b/lily/lexer.ll @@ -39,7 +39,7 @@ #include "identifier.hh" #include "version.hh" #include "mudela-version.hh" - +#include "translator-group.hh" void strip_trailing_white (String&); void strip_leading_white (String&); @@ -477,6 +477,9 @@ My_lily_lexer::scan_escaped_word (String str) } else if (gh_number_p (sid)) { yylval.scm = sid; return NUMBER_IDENTIFIER; + } else if (Translator* tr = unsmob_translator (sid)) { + yylval.scm = sid; + return TRANSLATOR_IDENTIFIER; } else if (Music * mus =unsmob_music (sid)) { yylval.scm = sid; diff --git a/lily/lyric-phrasing-engraver.cc b/lily/lyric-phrasing-engraver.cc index c17f9ce515..5cc40bc936 100644 --- a/lily/lyric-phrasing-engraver.cc +++ b/lily/lyric-phrasing-engraver.cc @@ -10,10 +10,7 @@ #include "lyric-phrasing-engraver.hh" #include "note-head.hh" #include "translator-group.hh" -#include "side-position-interface.hh" -#include "ly-smobs.icc" #include "spanner.hh" -#include "paper-def.hh" String get_context_id(Translator_group * ancestor, const char * type); @@ -56,6 +53,17 @@ Lyric_phrasing_engraver::~Lyric_phrasing_engraver() */ } +void +Lyric_phrasing_engraver::do_removal_processing () +{ + /* + but do need to unprotect alist_, since Engravers are gc'd now. + */ + + voice_alist_ = SCM_EOL; +} + + Syllable_group * Lyric_phrasing_engraver::lookup_context_id(const String &context_id) { @@ -275,263 +283,3 @@ Lyric_phrasing_engraver::do_pre_move_processing () -/*=========================================================================================*/ - -/** Syllable_group is a class to be smobbed and entered as data in the association list - member of the Lyric_phrasing_engraver class. -*/ - -Syllable_group::Syllable_group() -{ - first_in_phrase_b_=true; - melisma_b_ = false; - clear(); -} - -void -Syllable_group::clear() -{ - notehead_l_=0; - lyric_list_.clear(); - longest_lyric_l_=0; - shortest_lyric_l_=0; - melisma_b_ = false; - group_translation_f_ = 0.0; -} - -void -Syllable_group::copy( Syllable_group *from) -{ - notehead_l_ = from->notehead_l_; - lyric_list_ = from->lyric_list_; - longest_lyric_l_ = from->longest_lyric_l_; - shortest_lyric_l_ = from->shortest_lyric_l_; - melisma_b_ = from->melisma_b_; - alignment_i_ = from->alignment_i_; - first_in_phrase_b_ = from->first_in_phrase_b_; - group_translation_f_ = from->group_translation_f_; -} - -void -Syllable_group::set_first_in_phrase(bool f) -{ - first_in_phrase_b_ = f; -} - -void -Syllable_group::set_notehead(Score_element * notehead) -{ - if(!notehead_l_) { - /* there should only be a single notehead, so silently ignore any extras */ - notehead_l_=notehead; - } -} - -void -Syllable_group::add_lyric(Score_element * lyric) -{ - lyric_list_.push(lyric); - /* record longest and shortest lyrics */ - if( longest_lyric_l_ ) { - if(lyric->extent(X_AXIS).length() > (longest_lyric_l_->extent(X_AXIS)).length()) - longest_lyric_l_ = lyric; - if(lyric->extent(X_AXIS).length() < (shortest_lyric_l_->extent(X_AXIS)).length()) - shortest_lyric_l_ = lyric; - } - else - longest_lyric_l_ = shortest_lyric_l_ = lyric; -} - -void -Syllable_group::add_extender(Score_element * extender) -{ - if(notehead_l_ && melisma_b_) { - dynamic_cast(extender)->set_bound (RIGHT, notehead_l_); - // should the extender finish at the right of the last note of the melisma, or the left? - // Comments in lyric-extender.hh say left, but right looks better to me. GP. - - // Left: -// extender->set_elt_property("right-trim-amount", gh_double2scm(0.0)); - - // Right: - Real ss = extender->paper_l ()->get_var ("staffspace"); - extender->set_elt_property("right-trim-amount", - gh_double2scm(-notehead_l_->extent(X_AXIS).length()/ss)); - } -} - -bool -Syllable_group::set_lyric_align(const char *punc, Score_element *default_notehead_l) -{ - if(lyric_list_.size()==0) { - // No lyrics: nothing to do. - return true; - } - - Score_element * lyric; - alignment_i_ = appropriate_alignment(punc); - - // If there was no notehead in the matching voice context, use the first - // notehead caught from any voice context (any port in a storm). - if(!notehead_l_) { - notehead_l_ = default_notehead_l; - } - - group_translation_f_ = amount_to_translate(); - - // set the x alignment of each lyric - for(int l = 0; l < lyric_list_.size(); l++) { - lyric = lyric_list_[l]; - lyric->set_elt_property("self-alignment-X", gh_int2scm(alignment_i_)); - // centre on notehead ... if we have one. - if(notehead_l_) { - lyric->set_parent(notehead_l_, X_AXIS); - lyric->add_offset_callback (Side_position::centered_on_parent, X_AXIS); - // reference is on the right of the notehead; move it left half way, and add translation - lyric->translate_axis (group_translation_f_-(notehead_l_->extent(X_AXIS)).center(), X_AXIS); - } - } - return (notehead_l_); -} - -/** determine the distance to translate lyrics to get correct alignment - Rules: If alignment is centre, translate = 0 - Otherwise, - If (length of longest lyric) < 2 * (length of shortest lyric), - - centre longest lyric on notehead - Otherwise - - move so shortest lyric just reaches notehead centre -*/ -Real -Syllable_group::amount_to_translate() -{ - Real translate = 0.0; - if(alignment_i_ != CENTER) { - // FIXME: do we really know the lyric extent here? Some font sizing comes later? - if((longest_lyric_l_->extent(X_AXIS)).length() < - (shortest_lyric_l_->extent(X_AXIS)).length() * 2 ) - translate = alignment_i_*(longest_lyric_l_->extent(X_AXIS)).length()/2; - else - translate = alignment_i_*(shortest_lyric_l_->extent(X_AXIS)).length(); - } - return translate; -} - - -/** determine what alignment we want. - Rules: if first_in_phrase_b_ is set, then alignment is LEFT. - otherwise if each syllable ends in punctuation, then alignment is RIGHT - otherwise alignment is centre. -*/ -int -Syllable_group::appropriate_alignment(const char *punc) -{ - if(first_in_phrase_b_) - return LEFT; - - Score_element * lyric; - bool end_phrase = true; - - for(int l = 0; l < lyric_list_.size() && end_phrase; l++) { - lyric = lyric_list_[l]; - SCM lyric_scm = lyric->get_elt_property("text"); - String lyric_str = gh_string_p(lyric_scm)?ly_scm2string(lyric_scm):""; - char lastchar; - if(lyric_str.length_i()>0) { - lastchar = lyric_str[lyric_str.length_i()-1]; - /* If it doesn't end in punctuation then it ain't an end of phrase */ - if(! strchr(punc, lastchar)) { - /* Special case: trailing space. Here examine the previous character and reverse the - sense of the test (i.e. trailing space makes a break without punctuation, or - suppresses a break with punctuation). - This behaviour can be suppressed by including a space in the - phrasingPunctuation property, in which case trailing space always means - the same as punctuation. - - FIXME: The extra space throws alignment out a bit. - */ - if(lastchar == ' ') { - if(lyric_str.length_i()>1) { - lastchar = lyric_str[lyric_str.length_i()-2]; - if(strchr(punc, lastchar)) - end_phrase=false; - } - } - else - end_phrase=false; - } - } - } - if(end_phrase) - return RIGHT; - - return CENTER; -} - -/** We don't know about the melisma until after the initial alignment work is done, so go - back and fix the alignment when we DO know. -*/ -void -Syllable_group::adjust_melisma_align() -{ - if(notehead_l_ && lyric_list_.size()) { - // override any previous offset adjustments - Real translation = -group_translation_f_; - // melisma aligning: - switch (alignment_i_) { - // case LEFT: // that's all - case CENTER: // move right so smallest lyric is left-aligned on notehead - translation += (shortest_lyric_l_->extent(X_AXIS)).length()/2; - break; - case RIGHT: // move right so smallest lyric is left-aligned on notehead - translation += (shortest_lyric_l_->extent(X_AXIS)).length(); - break; - } - group_translation_f_ += translation; - for(int l = 0; l < lyric_list_.size(); l++) { - lyric_list_[l]->translate_axis (translation, X_AXIS); - } - } -} - - -bool -Syllable_group::is_empty() -{ - return lyric_list_.size()==0; -} - -void -Syllable_group::next_lyric() -{ - first_in_phrase_b_ = (alignment_i_ == RIGHT); - clear(); -} - -/* SMOB */ - - - -SCM -Syllable_group::mark_smob (SCM) -{ - return SCM_EOL; -} - -int -Syllable_group::print_smob (SCM, SCM port, scm_print_state * ) -{ - scm_puts ("#", port); - return 1; -} - -IMPLEMENT_UNSMOB(Syllable_group, voice_entry); -IMPLEMENT_SIMPLE_SMOBS(Syllable_group); -IMPLEMENT_DEFAULT_EQUAL_P(Syllable_group); - -SCM -Syllable_group::make_entry () -{ - Syllable_group *vi = new Syllable_group; - return vi->smobbed_self (); -} diff --git a/lily/mark-engraver.cc b/lily/mark-engraver.cc index b57bafa3e2..9ada64765f 100644 --- a/lily/mark-engraver.cc +++ b/lily/mark-engraver.cc @@ -15,7 +15,7 @@ #include "lily-guile.hh" #include "paper-column.hh" #include "paper-def.hh" -#include "protected-scm.hh" + #include "side-position-interface.hh" #include "staff-symbol-referencer.hh" #include "item.hh" @@ -32,7 +32,6 @@ public: Mark_engraver (); protected: Item* text_p_; - Protected_scm staffs_; protected: virtual void do_pre_move_processing (); @@ -41,6 +40,8 @@ protected: virtual bool do_try_music (Music *req_l); virtual void do_process_music (); virtual void do_post_move_processing (); + virtual void do_creation_processing (); + private: Mark_req * mark_req_l_; }; @@ -53,9 +54,13 @@ Mark_engraver::Mark_engraver () { text_p_ =0; mark_req_l_ = 0; - staffs_ = SCM_EOL; } +void +Mark_engraver::do_creation_processing () +{ + daddy_trans_l_->set_property ("staffsFound", SCM_EOL); // ugh: sharing with barnumber grav. +} void @@ -64,7 +69,10 @@ Mark_engraver::acknowledge_element (Score_element_info inf) Score_element * s = inf.elem_l_; if (Staff_symbol::has_interface (s)) { - staffs_ = gh_cons (inf.elem_l_->self_scm (), staffs_); + SCM sts = get_property ("staffsFound"); + SCM thisstaff = inf.elem_l_->self_scm (); + if (scm_memq (thisstaff, sts) == SCM_BOOL_F) + daddy_trans_l_->set_property ("staffsFound", gh_cons (thisstaff, sts)); } else if (text_p_ && Bar::has_interface (s)) { @@ -81,7 +89,7 @@ Mark_engraver::do_pre_move_processing () { if (text_p_) { - text_p_->set_elt_property("side-support-elements" , staffs_); + text_p_->set_elt_property("side-support-elements" , get_property ("staffsFound")); typeset_element (text_p_); text_p_ =0; } diff --git a/lily/music-iterator.cc b/lily/music-iterator.cc index 39478c2d05..bfa597527b 100644 --- a/lily/music-iterator.cc +++ b/lily/music-iterator.cc @@ -223,8 +223,3 @@ Music_iterator::try_music_in_children (Music * ) const return 0; } -Music* -Music_iterator::get_next_music () -{ - return 0; -} diff --git a/lily/music-output-def.cc b/lily/music-output-def.cc index 07895d86e2..a0107291a5 100644 --- a/lily/music-output-def.cc +++ b/lily/music-output-def.cc @@ -50,15 +50,17 @@ Music_output_def::assign_translator (Translator_group*tp) { tp->warning (_("Interpretation context with empty type")); } - - translator_p_dict_p_->set (s, new Translator_group_identifier (tp, 0)); + + SCM tr = tp->self_scm (); + scm_unprotect_object (tr); + translator_p_dict_p_->set (s, tr); } Translator* Music_output_def::find_translator_l (String name) const { if (translator_p_dict_p_->elem_b (name)) - return translator_p_dict_p_->elem (name)->access_content_Translator_group (false); + return unsmob_translator (translator_p_dict_p_->scm_elem (name)); map::const_iterator ki =global_translator_dict_p->find (name); @@ -77,6 +79,7 @@ Music_output_def::get_global_translator_p () if (!t) error (_f ("can't find `%s' context", "Score")); t = t->clone (); + t->output_def_l_ = this; Global_translator *g = dynamic_cast (t); t->add_processing (); diff --git a/lily/music-wrapper-iterator.cc b/lily/music-wrapper-iterator.cc index 17931466a1..af658cf72a 100644 --- a/lily/music-wrapper-iterator.cc +++ b/lily/music-wrapper-iterator.cc @@ -63,10 +63,3 @@ Music_wrapper_iterator::try_music_in_children (Music *m) const { return child_iter_p_->try_music (m); } - - -Music* -Music_wrapper_iterator::get_next_music () -{ - return child_iter_p_->get_next_music (); -} diff --git a/lily/parser.yy b/lily/parser.yy index bb7b882e36..84a0b042d8 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -198,14 +198,14 @@ yylex (YYSTYPE *s, void * v_l) %token CHORDMODIFIER_PITCH %token DURATION_IDENTIFIER %token IDENTIFIER -%token TRANS_IDENTIFIER + %token SCORE_IDENTIFIER %token MUSIC_OUTPUT_DEF_IDENTIFIER %token NUMBER_IDENTIFIER %token REQUEST_IDENTIFIER -%token MUSIC_IDENTIFIER +%token MUSIC_IDENTIFIER TRANSLATOR_IDENTIFIER %token STRING_IDENTIFIER SCM_IDENTIFIER %token DURATION RESTNAME %token STRING @@ -388,7 +388,7 @@ identifier_init: $$ = (new Music_output_def_identifier ($1, MUSIC_OUTPUT_DEF_IDENTIFIER))->self_scm(); } | translator_spec_block { - $$ = (new Translator_group_identifier ($1, TRANS_IDENTIFIER))->self_scm(); + $$ = $1->self_scm (); } | Music { $$ = $1->self_scm (); @@ -418,8 +418,10 @@ translator_spec_block: ; translator_spec_body: - TRANS_IDENTIFIER { - $$ = $1->access_content_Translator_group (true); + TRANSLATOR_IDENTIFIER { + SCM trs = $1; + Translator*tr = unsmob_translator (trs); + $$ = dynamic_cast (tr->clone ()); $$-> set_spot (THIS->here_input ()); } | TYPE STRING semicolon { @@ -449,23 +451,31 @@ translator_spec_body: tg->set_property (ly_scm2string ($2), v); } + | translator_spec_body PUSHPROPERTY + embedded_scm embedded_scm embedded_scm { + Translator_group_initializer::add_push_property ($$, $3, $4, $5); + } + | translator_spec_body POPPROPERTY + embedded_scm embedded_scm { + Translator_group_initializer::add_pop_property ($$, $3, $4); + } | translator_spec_body NAME STRING semicolon { $$->type_str_ = ly_scm2string ($3); } | translator_spec_body CONSISTS STRING semicolon { - dynamic_cast ($$)-> set_element (ly_scm2string ($3), true); + Translator_group_initializer::add_element ($$, $3); } | translator_spec_body CONSISTSEND STRING semicolon { - dynamic_cast ($$)-> set_element (ly_scm2string ($3), true); + Translator_group_initializer::add_last_element ($$, $3); } | translator_spec_body ACCEPTS STRING semicolon { - dynamic_cast ($$)-> set_acceptor (ly_scm2string ($3), true); + Translator_group_initializer::set_acceptor ($$, $3,true); } | translator_spec_body DENIES STRING semicolon { - dynamic_cast ($$)-> set_acceptor (ly_scm2string ($3), false); + Translator_group_initializer::set_acceptor ($$, $3,false); } | translator_spec_body REMOVE STRING semicolon { - dynamic_cast ($$)-> set_element (ly_scm2string ($3), false); + Translator_group_initializer::remove_element ($$, $3); } ; diff --git a/lily/part-combine-music-iterator.cc b/lily/part-combine-music-iterator.cc index 17e79b2423..3a72a587a9 100644 --- a/lily/part-combine-music-iterator.cc +++ b/lily/part-combine-music-iterator.cc @@ -8,7 +8,6 @@ #include "part-combine-music.hh" #include "part-combine-music-iterator.hh" -#include "sequential-music-iterator.hh" #include "translator-group.hh" #include "musical-request.hh" #include "warn.hh" @@ -102,7 +101,7 @@ Part_combine_music_iterator::change_to (Music_iterator *it, String to_type, Translator_group * dest = it->report_to_l ()->find_create_translator_l (to_type, to_id); current->remove_translator_p (last); - dest->add_translator (last); + dest->add_group_translator (last); } else { @@ -124,8 +123,6 @@ Pitch_interrogate_req* second_spanish_inquisition; // won't strike twice Rhythm_interrogate_req* first_rhythmic_inquisition; Rhythm_interrogate_req* second_rhythmic_inquisition; -#include - void Part_combine_music_iterator::do_process_and_next (Moment m) { @@ -133,23 +130,14 @@ Part_combine_music_iterator::do_process_and_next (Moment m) now_ = next_moment (); - Music* first_music = 0; - Music* second_music = 0; - /* Hmm, shouldn't we check per iterator if next_moment < m? */ if (first_iter_p_->ok ()) - { - first_music = first_iter_p_->get_next_music (); - first_iter_p_->process_and_next (m); - } + first_iter_p_->process_and_next (m); if (second_iter_p_->ok ()) - { - second_music = second_iter_p_->get_next_music (); - second_iter_p_->process_and_next (m); - } + second_iter_p_->process_and_next (m); Music_iterator::do_process_and_next (m); @@ -199,13 +187,6 @@ Part_combine_music_iterator::do_process_and_next (Moment m) Array* first_durations = &first_rhythmic_inquisition->duration_arr_; Array* second_durations = &second_rhythmic_inquisition->duration_arr_; - if (!first_durations->empty ()) - cout << "first_durations: " << first_durations->top ().length_mom ().str () << endl; - - // if (Rhythmic_req *r = dynamic_cast (first_music)) - if (first_music) - cout << "first_music: " << first_music->length_mom ().str (); - SCM interval = SCM_BOOL_F; if (first_pitches->size () && second_pitches->size ()) { diff --git a/lily/performer-group-performer.cc b/lily/performer-group-performer.cc index 7a38830b53..0c07bf694f 100644 --- a/lily/performer-group-performer.cc +++ b/lily/performer-group-performer.cc @@ -22,48 +22,44 @@ Performer_group_performer::announce_element (Audio_element_info info) Performer::announce_element (info); } + + void Performer_group_performer::do_announces() { - for (Cons *p = trans_p_list_.head_; p; p = p->next_) + for (SCM p = trans_group_list_; gh_pair_p (p); p =gh_cdr ( p)) { - if (Performer_group_performer *trg = dynamic_cast (p->car_)) - trg->do_announces (); + Translator * t = unsmob_translator (gh_car (p)); + dynamic_cast (t)->do_announces (); } - - - while (announce_info_arr_.size ()) { for (int j =0; j < announce_info_arr_.size(); j++) { Audio_element_info info = announce_info_arr_[j]; - for (Cons *p = trans_p_list_.head_; p; p = p->next_) - { - if (!dynamic_cast (p->car_)) - { - Performer * eng = dynamic_cast (p->car_); - // urg, huh? core dump? - //if (eng && eng!= info.origin_trans_l_arr ()[0]) - if (eng && info.origin_trans_l_arr (this).size () - && eng!= info.origin_trans_l_arr (this)[0]) - eng->acknowledge_element (info); - } - } - announce_info_arr_.clear (); - - - for (Cons *p = trans_p_list_.head_; p; p = p->next_) + + for (SCM p = simple_trans_list_; gh_pair_p (p); p = gh_cdr (p)) { - if (!dynamic_cast (p->car_)) - { - Performer * eng = dynamic_cast (p->car_); - if (eng) - eng->process_acknowledged (); - } + Translator * t = unsmob_translator (gh_car (p)); + Performer * eng = dynamic_cast (t); + if (eng && eng!= info.origin_trans_l_) + eng->acknowledge_element (info); } } + announce_info_arr_.clear (); + for (SCM p = simple_trans_list_; gh_pair_p (p); p = gh_cdr ( p)) + { + Translator * t = unsmob_translator (gh_car (p)); + Performer * eng = dynamic_cast (t); + if (eng) + eng->process_acknowledged (); + } } } + + + + + diff --git a/lily/performer.cc b/lily/performer.cc index fe706b01f9..8cf1c972f7 100644 --- a/lily/performer.cc +++ b/lily/performer.cc @@ -45,6 +45,7 @@ Performer::process_acknowledged () void Performer::announce_element (Audio_element_info i) { - i.origin_trans_l_arr_.push (this); + if (!i.origin_trans_l_) + i.origin_trans_l_= this; daddy_perf_l()->announce_element (i); } diff --git a/lily/piano-pedal-engraver.cc b/lily/piano-pedal-engraver.cc index 6b1fd8f7c1..b9688e5de7 100644 --- a/lily/piano-pedal-engraver.cc +++ b/lily/piano-pedal-engraver.cc @@ -182,15 +182,8 @@ Piano_pedal_engraver::do_process_music () if (gh_string_p (s)) { - if (p->name_ == String ("Sustain")) - { - // fixme: Item should be sufficient. - p->item_p_ = new Item (get_property ("basicSustainPedalProperties")); - } - else - { - p->item_p_ = new Item (get_property ("basicPedalProperties")); - } + String propname = String ("basic")+ p->name_ + "PedalProperties"; + p->item_p_ = new Item (get_property (propname.ch_C())); p->item_p_->set_elt_property ("text", s); // guh diff --git a/lily/property-engraver.cc b/lily/property-engraver.cc index e7baf2ec25..1e5a16b931 100644 --- a/lily/property-engraver.cc +++ b/lily/property-engraver.cc @@ -9,11 +9,14 @@ #include "lily-guile.hh" #include "engraver.hh" -#include "protected-scm.hh" #include "dictionary.hh" #include "score-element.hh" #include "scm-hash.hh" +/* + JUNKME: should use pushproperty everywhere. + + */ class Property_engraver : public Engraver { /* @@ -99,12 +102,12 @@ Property_engraver::apply_properties (SCM p, Score_element *e) SCM type_p = gh_cadr (entry); SCM elt_prop_sym = gh_caddr (entry); - SCM preset = e->get_elt_property (elt_prop_sym); // scm_assq(elt_prop_sym, e->property_alist_); - if (preset != SCM_EOL) + SCM preset = scm_assq(elt_prop_sym, e->mutable_property_alist_); + if (preset != SCM_BOOL_F) continue; SCM val = get_property (prop_sym); - + if (val == SCM_UNDEFINED) ; // Not defined in context. else if (gh_apply (type_p, scm_listify (val, SCM_UNDEFINED)) diff --git a/lily/property-iterator.cc b/lily/property-iterator.cc index 0e50832e64..41b0ed5406 100644 --- a/lily/property-iterator.cc +++ b/lily/property-iterator.cc @@ -28,20 +28,11 @@ void Push_property_iterator::do_process_and_next (Moment m) { SCM syms = music_l_->get_mus_property ("symbols"); - SCM eprop = music_l_->get_mus_property ("element-property"); + SCM eprop = music_l_->get_mus_property ("element-property"); SCM val = music_l_->get_mus_property ("element-value"); - for (SCM s = syms; gh_pair_p (s); s = gh_cdr (s)) - { - SCM sym = gh_car (s); - if (gh_symbol_p(sym)) - { - SCM prev = report_to_l ()->get_property (sym); - - prev = gh_cons (gh_cons (eprop, val), prev); - report_to_l ()->set_property (gh_car (s), prev); - } - } + Translator_group_initializer::apply_pushpop_property (report_to_l (), syms,eprop, val); + Music_iterator::do_process_and_next (m); } @@ -50,23 +41,7 @@ Pop_property_iterator::do_process_and_next (Moment m) { SCM syms = music_l_->get_mus_property ("symbols"); SCM eprop = music_l_->get_mus_property ("element-property"); - for (SCM s = syms; gh_pair_p (s); s = gh_cdr (s)) - { - SCM sym = gh_car (s); - if (gh_symbol_p(sym)) - { - SCM prev = report_to_l ()->get_property (sym); - - SCM newprops= SCM_EOL ; - while (gh_pair_p (prev) && gh_caar (prev) != eprop) - { - newprops = gh_cons (gh_car (prev), newprops); - prev = gh_cdr (prev); - } - - newprops = scm_reverse_x (newprops, gh_cdr (prev)); - report_to_l ()->set_property (sym, newprops); - } - } + Translator_group_initializer::apply_pushpop_property (report_to_l (), syms, eprop, SCM_UNDEFINED); + Music_iterator::do_process_and_next (m); } diff --git a/lily/repeat-engraver.cc b/lily/repeat-engraver.cc index 9874744414..2cae99cb09 100644 --- a/lily/repeat-engraver.cc +++ b/lily/repeat-engraver.cc @@ -208,7 +208,7 @@ Repeat_engraver::do_process_music () return; Bar_engraver* bar_engraver_l = dynamic_cast - (daddy_grav_l ()->get_simple_translator ("Bar_engraver")); + (daddy_grav_l ()->get_simple_translator ("Bar_engraver")); // UGH /* Do all the events that need to be done now. diff --git a/lily/score-element.cc b/lily/score-element.cc index 49493167f3..26a62293fc 100644 --- a/lily/score-element.cc +++ b/lily/score-element.cc @@ -189,10 +189,13 @@ Score_element::paper_l () const Lookup const * Score_element::lookup_l () const { + /* + URG junkthis, caching is clumsy. + */ if (!lookup_l_) { Score_element * urg = (Score_element*)this; - SCM sz = urg->remove_elt_property ("fontsize"); + SCM sz = urg->remove_elt_property ("font-size"); int i = (gh_number_p (sz)) ? gh_scm2int (sz) : 0; diff --git a/lily/score-performer.cc b/lily/score-performer.cc index ad868ae9e3..1908644904 100644 --- a/lily/score-performer.cc +++ b/lily/score-performer.cc @@ -47,7 +47,7 @@ void Score_performer::announce_element (Audio_element_info info) { announce_info_arr_.push (info); - info.origin_trans_l_arr_.push (this); + /* huh? diff --git a/lily/score.cc b/lily/score.cc index 75e397aab8..4f33c853f1 100644 --- a/lily/score.cc +++ b/lily/score.cc @@ -95,7 +95,8 @@ Score::run_translator (Music_output_def *odef_l) } Music_output * output = trans_p->get_output_p(); - delete trans_p; + scm_unprotect_object (trans_p->self_scm ()); + if(verbose_global_b) progress_indication (_f ("elapsed time: %.2f seconds", timer.read ())); diff --git a/lily/sequential-music-iterator.cc b/lily/sequential-music-iterator.cc index d98dc5738f..d99381cf54 100644 --- a/lily/sequential-music-iterator.cc +++ b/lily/sequential-music-iterator.cc @@ -139,11 +139,3 @@ Sequential_music_iterator::try_music_in_children (Music *m) const { return iter_p_ ? iter_p_->try_music (m) : 0; } - -Music* -Sequential_music_iterator::get_next_music () -{ - if (cursor_ && gh_pair_p (cursor_)) - return unsmob_music (gh_car (cursor_)); - return 0; -} diff --git a/lily/syllable-group.cc b/lily/syllable-group.cc new file mode 100644 index 0000000000..a0cf73d270 --- /dev/null +++ b/lily/syllable-group.cc @@ -0,0 +1,268 @@ +#include + +#include "lyric-phrasing-engraver.hh" +#include "note-head.hh" +#include "translator-group.hh" +#include "side-position-interface.hh" +#include "ly-smobs.icc" +#include "spanner.hh" +#include "paper-def.hh" + + +/*=========================================================================================*/ + +/** Syllable_group is a class to be smobbed and entered as data in the association list + member of the Lyric_phrasing_engraver class. +*/ + +Syllable_group::Syllable_group() +{ + first_in_phrase_b_=true; + melisma_b_ = false; + clear(); +} + +void +Syllable_group::clear() +{ + notehead_l_=0; + lyric_list_.clear(); + longest_lyric_l_=0; + shortest_lyric_l_=0; + melisma_b_ = false; + group_translation_f_ = 0.0; +} + +void +Syllable_group::copy( Syllable_group *from) +{ + notehead_l_ = from->notehead_l_; + lyric_list_ = from->lyric_list_; + longest_lyric_l_ = from->longest_lyric_l_; + shortest_lyric_l_ = from->shortest_lyric_l_; + melisma_b_ = from->melisma_b_; + alignment_i_ = from->alignment_i_; + first_in_phrase_b_ = from->first_in_phrase_b_; + group_translation_f_ = from->group_translation_f_; +} + +void +Syllable_group::set_first_in_phrase(bool f) +{ + first_in_phrase_b_ = f; +} + +void +Syllable_group::set_notehead(Score_element * notehead) +{ + if(!notehead_l_) { + /* there should only be a single notehead, so silently ignore any extras */ + notehead_l_=notehead; + } +} + +void +Syllable_group::add_lyric(Score_element * lyric) +{ + lyric_list_.push(lyric); + /* record longest and shortest lyrics */ + if( longest_lyric_l_ ) { + if(lyric->extent(X_AXIS).length() > (longest_lyric_l_->extent(X_AXIS)).length()) + longest_lyric_l_ = lyric; + if(lyric->extent(X_AXIS).length() < (shortest_lyric_l_->extent(X_AXIS)).length()) + shortest_lyric_l_ = lyric; + } + else + longest_lyric_l_ = shortest_lyric_l_ = lyric; +} + +void +Syllable_group::add_extender(Score_element * extender) +{ + if(notehead_l_ && melisma_b_) { + dynamic_cast(extender)->set_bound (RIGHT, notehead_l_); + // should the extender finish at the right of the last note of the melisma, or the left? + // Comments in lyric-extender.hh say left, but right looks better to me. GP. + + // Left: +// extender->set_elt_property("right-trim-amount", gh_double2scm(0.0)); + + // Right: + Real ss = extender->paper_l ()->get_var ("staffspace"); + extender->set_elt_property("right-trim-amount", + gh_double2scm(-notehead_l_->extent(X_AXIS).length()/ss)); + } +} + +bool +Syllable_group::set_lyric_align(const char *punc, Score_element *default_notehead_l) +{ + if(lyric_list_.size()==0) { + // No lyrics: nothing to do. + return true; + } + + Score_element * lyric; + alignment_i_ = appropriate_alignment(punc); + + // If there was no notehead in the matching voice context, use the first + // notehead caught from any voice context (any port in a storm). + if(!notehead_l_) { + notehead_l_ = default_notehead_l; + } + + group_translation_f_ = amount_to_translate(); + + // set the x alignment of each lyric + for(int l = 0; l < lyric_list_.size(); l++) { + lyric = lyric_list_[l]; + lyric->set_elt_property("self-alignment-X", gh_int2scm(alignment_i_)); + // centre on notehead ... if we have one. + if(notehead_l_) { + lyric->set_parent(notehead_l_, X_AXIS); + lyric->add_offset_callback (Side_position::centered_on_parent, X_AXIS); + // reference is on the right of the notehead; move it left half way, and add translation + lyric->translate_axis (group_translation_f_-(notehead_l_->extent(X_AXIS)).center(), X_AXIS); + } + } + return (notehead_l_); +} + +/** determine the distance to translate lyrics to get correct alignment + Rules: If alignment is centre, translate = 0 + Otherwise, + If (length of longest lyric) < 2 * (length of shortest lyric), + - centre longest lyric on notehead + Otherwise + - move so shortest lyric just reaches notehead centre +*/ +Real +Syllable_group::amount_to_translate() +{ + Real translate = 0.0; + if(alignment_i_ != CENTER) { + // FIXME: do we really know the lyric extent here? Some font sizing comes later? + if((longest_lyric_l_->extent(X_AXIS)).length() < + (shortest_lyric_l_->extent(X_AXIS)).length() * 2 ) + translate = alignment_i_*(longest_lyric_l_->extent(X_AXIS)).length()/2; + else + translate = alignment_i_*(shortest_lyric_l_->extent(X_AXIS)).length(); + } + return translate; +} + + +/** determine what alignment we want. + Rules: if first_in_phrase_b_ is set, then alignment is LEFT. + otherwise if each syllable ends in punctuation, then alignment is RIGHT + otherwise alignment is centre. +*/ +int +Syllable_group::appropriate_alignment(const char *punc) +{ + if(first_in_phrase_b_) + return LEFT; + + Score_element * lyric; + bool end_phrase = true; + + for(int l = 0; l < lyric_list_.size() && end_phrase; l++) { + lyric = lyric_list_[l]; + SCM lyric_scm = lyric->get_elt_property("text"); + String lyric_str = gh_string_p(lyric_scm)?ly_scm2string(lyric_scm):""; + char lastchar; + if(lyric_str.length_i()>0) { + lastchar = lyric_str[lyric_str.length_i()-1]; + /* If it doesn't end in punctuation then it ain't an end of phrase */ + if(! strchr(punc, lastchar)) { + /* Special case: trailing space. Here examine the previous character and reverse the + sense of the test (i.e. trailing space makes a break without punctuation, or + suppresses a break with punctuation). + This behaviour can be suppressed by including a space in the + phrasingPunctuation property, in which case trailing space always means + the same as punctuation. + + FIXME: The extra space throws alignment out a bit. + */ + if(lastchar == ' ') { + if(lyric_str.length_i()>1) { + lastchar = lyric_str[lyric_str.length_i()-2]; + if(strchr(punc, lastchar)) + end_phrase=false; + } + } + else + end_phrase=false; + } + } + } + if(end_phrase) + return RIGHT; + + return CENTER; +} + +/** We don't know about the melisma until after the initial alignment work is done, so go + back and fix the alignment when we DO know. +*/ +void +Syllable_group::adjust_melisma_align() +{ + if(notehead_l_ && lyric_list_.size()) { + // override any previous offset adjustments + Real translation = -group_translation_f_; + // melisma aligning: + switch (alignment_i_) { + // case LEFT: // that's all + case CENTER: // move right so smallest lyric is left-aligned on notehead + translation += (shortest_lyric_l_->extent(X_AXIS)).length()/2; + break; + case RIGHT: // move right so smallest lyric is left-aligned on notehead + translation += (shortest_lyric_l_->extent(X_AXIS)).length(); + break; + } + group_translation_f_ += translation; + for(int l = 0; l < lyric_list_.size(); l++) { + lyric_list_[l]->translate_axis (translation, X_AXIS); + } + } +} + + +bool +Syllable_group::is_empty() +{ + return lyric_list_.size()==0; +} + +void +Syllable_group::next_lyric() +{ + first_in_phrase_b_ = (alignment_i_ == RIGHT); + clear(); +} + +/* SMOB */ +SCM +Syllable_group::mark_smob (SCM) +{ + return SCM_EOL; +} + +int +Syllable_group::print_smob (SCM, SCM port, scm_print_state * ) +{ + scm_puts ("#", port); + return 1; +} + +IMPLEMENT_UNSMOB(Syllable_group, voice_entry); +IMPLEMENT_SIMPLE_SMOBS(Syllable_group); +IMPLEMENT_DEFAULT_EQUAL_P(Syllable_group); + +SCM +Syllable_group::make_entry () +{ + Syllable_group *vi = new Syllable_group; + return vi->smobbed_self (); +} diff --git a/lily/translator-group-initializer.cc b/lily/translator-group-initializer.cc new file mode 100644 index 0000000000..b7a5aecf28 --- /dev/null +++ b/lily/translator-group-initializer.cc @@ -0,0 +1,95 @@ + /* + translator-group-initializer.cc -- implement Translator_group_initializer + + source file of the GNU LilyPond music typesetter + + (c) 2000 Han-Wen Nienhuys + + */ + +#include "translator-group.hh" +#include "warn.hh" + + +void +Translator_group_initializer::set_acceptor (Translator *me,SCM name, bool add) +{ + if (add) + me->accepts_name_list_ = gh_append2 (me->accepts_name_list_, gh_cons (name, SCM_EOL)); + else + me->accepts_name_list_ = scm_delete_x (name, me->accepts_name_list_); +} + + +SCM +Translator_group_initializer::modify_definition (SCM list, SCM str, bool add) +{ + String s = ly_scm2string (str); + if (!get_translator_l (s)) + error (_ ("Program has no such type")); + + if (add) + { + if (scm_memq (str, list) != SCM_BOOL_F) + { + warning (_f("Already contains: `%s'", s)); + warning (_f("Not adding translator: `%s'", s)); + } + else + list= gh_cons (str, list); + } + else + { + list = scm_delete_x (str, list); + } + return list; +} + + + +void +Translator_group_initializer::remove_element (Translator *me,SCM s) +{ + me->end_consists_name_list_ = modify_definition (me->end_consists_name_list_, s, false); + me->consists_name_list_ = modify_definition (me->consists_name_list_, s, false); +} + +void +Translator_group_initializer::add_element (Translator *me,SCM s) +{ + me->consists_name_list_ = modify_definition (me->consists_name_list_, s, true); +} + +void +Translator_group_initializer::add_last_element (Translator *me,SCM s) +{ + me->end_consists_name_list_ = modify_definition (me->end_consists_name_list_, s, true); +} +void +Translator_group_initializer::add_push_property (Translator * me, + SCM props, SCM syms, SCM vals) +{ + me->property_pushes_ = gh_cons (gh_list (props, syms, vals, SCM_UNDEFINED), + me->property_pushes_); +} + +void +Translator_group_initializer::add_pop_property (Translator * me, + SCM props, SCM syms) +{ + me->property_pushes_ = gh_cons (gh_list (props, syms, SCM_UNDEFINED), + me->property_pushes_); +} + +/* + Do it. SYMS maybe a symbol or a list of symbols. VAL is + SCM_UNDEFINED in case of a pop +*/ +void +Translator_group_initializer::apply_pushpop_property (Translator *trans, SCM syms, SCM eprop, SCM val) +{ + if (gh_symbol_p (syms)) + dynamic_cast(trans)->execute_single_pushpop_property (syms, eprop, val); + else for (SCM s = syms; gh_pair_p (s); s = gh_cdr (s)) + dynamic_cast(trans)->execute_single_pushpop_property (gh_car (s), eprop, val); +} diff --git a/lily/translator-group.cc b/lily/translator-group.cc index 8d92fb8ac1..d2b7c83a04 100644 --- a/lily/translator-group.cc +++ b/lily/translator-group.cc @@ -17,111 +17,78 @@ Translator_group::Translator_group (Translator_group const&s) : Translator(s) { - consists_str_arr_ = s.consists_str_arr_; - consists_end_str_arr_ = s.consists_end_str_arr_; - accepts_str_arr_ = s.accepts_str_arr_; iterator_count_ =0; - properties_dict_ = new Scheme_hash_table (*s.properties_dict_); + + Scheme_hash_table * tab = new Scheme_hash_table (*s.properties_dict ()); + properties_scm_ = tab->self_scm (); + scm_unprotect_object (tab->self_scm( )); +} + +Scheme_hash_table* +Translator_group::properties_dict () const +{ + return Scheme_hash_table::unsmob (properties_scm_); } Translator_group::~Translator_group () { assert (removable_b()); - trans_p_list_.junk (); - scm_unprotect_object (properties_dict_->self_scm ()); } Translator_group::Translator_group() { iterator_count_ = 0; - properties_dict_ = new Scheme_hash_table ; + Scheme_hash_table *tab = new Scheme_hash_table ; + properties_scm_ = tab->self_scm (); + + scm_unprotect_object (tab->self_scm ()); } void Translator_group::check_removal() { - Cons *next =0; - for (Cons *p = trans_p_list_.head_; p; p = next) + SCM next = SCM_EOL; + for (SCM p = trans_group_list_; gh_pair_p (p); p = next) { - next = p->next_; - if (Translator_group *trg = dynamic_cast (p->car_)) - { - trg->check_removal (); - if (trg->removable_b()) - terminate_translator (trg); - } + next = gh_cdr (p); + + Translator_group *trg = dynamic_cast (unsmob_translator (gh_car (p))); + + trg->check_removal (); + if (trg->removable_b()) + terminate_translator (trg); } } -void -Translator_group::add_translator (Translator *trans_p) + +SCM +Translator_group::add_translator (SCM list, Translator *t) { - trans_p_list_.append (new Killing_cons (trans_p,0)); + list = gh_append2 (list, gh_cons (t->self_scm (), SCM_EOL)); + t->daddy_trans_l_ = this; + t->output_def_l_ = output_def_l_; + t->add_processing (); - trans_p->daddy_trans_l_ = this; - trans_p->output_def_l_ = output_def_l_; - trans_p->add_processing (); + return list; } - void -Translator_group::set_acceptor (String accepts, bool add) +Translator_group::add_simple_translator (Translator*t) { - if (add) - accepts_str_arr_.push (accepts); - else - for (int i=accepts_str_arr_.size (); i--; ) - if (accepts_str_arr_[i] == accepts) - accepts_str_arr_.del (i); + simple_trans_list_ = add_translator (simple_trans_list_, t); } - void -Translator_group::add_last_element (String s) +Translator_group::add_group_translator (Translator *t) { - if (!get_translator_l (s)) - error (_ ("Program has no such type")); - - for (int i=consists_end_str_arr_.size (); i--; ) - if (consists_end_str_arr_[i] == s) - warning (_f ("Already contains: `%s'", s)); - - consists_end_str_arr_.push (s); + trans_group_list_ = add_translator (trans_group_list_,t); } -void -Translator_group::set_element (String s, bool add) -{ - if (!get_translator_l (s)) - error (_ ("Program has no such type")); - if (add) - { - for (int i=consists_str_arr_.size (); i--; ) - if (consists_str_arr_[i] == s) - warning (_f("Already contains: `%s'", s)); - - consists_str_arr_.push (s); - } - else - { - for (int i=consists_str_arr_.size (); i--; ) - if (consists_str_arr_[i] == s) - consists_str_arr_.del (i); - for (int i=consists_end_str_arr_.size (); i--; ) - if (consists_end_str_arr_[i] == s) - consists_end_str_arr_.del (i); - } -} + bool Translator_group::removable_b() const { - for (Cons *p = trans_p_list_.head_; p; p = p->next_) - { - if (dynamic_cast (p->car_)) - return false; - } - - return !iterator_count_; + return trans_group_list_ == SCM_EOL && ! iterator_count_; } Translator_group * @@ -131,10 +98,11 @@ Translator_group::find_existing_translator_l (String n, String id) return this; Translator_group* r = 0; - for (Cons *p = trans_p_list_.head_; !r && p; p = p->next_) + for (SCM p = trans_group_list_; !r && gh_pair_p (p); p = gh_cdr (p)) { - if (Translator_group *trg = dynamic_cast (p->car_)) - r = trg->find_existing_translator_l (n, id); + Translator * t = unsmob_translator (gh_car (p)); + + r = dynamic_cast (t)->find_existing_translator_l (n, id); } return r; @@ -143,10 +111,11 @@ Translator_group::find_existing_translator_l (String n, String id) Link_array Translator_group::path_to_acceptable_translator (String type, Music_output_def* odef) const { - Link_array accepted_arr; - for (int i=0; i < accepts_str_arr_.size (); i++) + Link_array accepted_arr; + for (SCM s = accepts_name_list_; gh_pair_p (s); s = gh_cdr (s)) { - Translator *t = odef->find_translator_l (accepts_str_arr_[i]); + + Translator *t = odef->find_translator_l (ly_scm2string (gh_car (s))); if (!t || !dynamic_cast (t)) continue; accepted_arr.push (dynamic_cast (t)); @@ -198,7 +167,7 @@ Translator_group::find_create_translator_l (String n, String id) { Translator_group * new_group = dynamic_cast(path[i]->clone ()); - current->add_translator (new_group); + current->add_group_translator (new_group); current = new_group; } current->id_str_ = id; @@ -221,12 +190,10 @@ Translator_group::try_music_on_nongroup_children (Music *m) { bool hebbes_b =false; - for (Cons *p = trans_p_list_.head_; !hebbes_b && p; p = p->next_) + + for (SCM p = simple_trans_list_; !hebbes_b && gh_pair_p (p); p = gh_cdr (p)) { - if (!dynamic_cast (p->car_)) - { - hebbes_b = p->car_->try_music (m); - } + hebbes_b = unsmob_translator (gh_car (p))->try_music (m); } return hebbes_b; } @@ -256,17 +223,14 @@ Translator_group::ancestor_l (int level) return daddy_trans_l_->ancestor_l (level-1); } - - - - void Translator_group::terminate_translator (Translator*r_l) { r_l->removal_processing(); Translator * trans_p =remove_translator_p (r_l); - - delete trans_p; + /* + forget trans_p, GC does the rest. + */ } @@ -277,28 +241,20 @@ Translator * Translator_group::remove_translator_p (Translator*trans_l) { assert (trans_l); - - for (Cons **pp = &trans_p_list_.head_; *pp; pp = &(*pp)->next_) - if ((*pp)->car_ == trans_l) - { - Cons *r = trans_p_list_.remove_cons (pp); - r->car_ =0; - trans_l->daddy_trans_l_ =0; - delete r; - return trans_l; - } - return 0; + trans_group_list_ = scm_delq_x (trans_l->self_scm (), trans_group_list_); + trans_l->daddy_trans_l_ = 0; + return trans_l; } Translator* Translator_group::get_simple_translator (String type) const { - for (Cons *p = trans_p_list_.head_; p; p = p->next_) + for (SCM p = simple_trans_list_; gh_pair_p (p); p =gh_cdr (p)) { - if (classname (p->car_) == type) - return p->car_; + if (classname (unsmob_translator (gh_car (p))) == type) + return unsmob_translator (gh_car (p)); } if (daddy_trans_l_) return daddy_trans_l_->get_simple_translator (type); @@ -309,7 +265,7 @@ Translator_group::get_simple_translator (String type) const bool Translator_group::is_bottom_translator_b () const { - return !accepts_str_arr_.size (); + return accepts_name_list_ == SCM_EOL; } @@ -317,16 +273,17 @@ Translator_group::is_bottom_translator_b () const Translator_group* Translator_group::get_default_interpreter() { - if (accepts_str_arr_.size()) + if (gh_pair_p (accepts_name_list_)) { - Translator*t = output_def_l ()->find_translator_l (accepts_str_arr_[0]); + String str = ly_scm2string (gh_car (accepts_name_list_)); + Translator*t = output_def_l ()->find_translator_l (str); if (!t) { - warning (_f ("can't find or create: `%s'", accepts_str_arr_[0])); + warning (_f ("can't find or create: `%s'", str)); t = this; } Translator_group * g= dynamic_cast (t->clone ()); - add_translator (g); + add_group_translator (g); if (!g->is_bottom_translator_b ()) return g->get_default_interpreter (); @@ -336,105 +293,90 @@ Translator_group::get_default_interpreter() return this; } -void -Translator_group::each (Method_pointer method) +static void +static_each (SCM list, Method_pointer method) { - for (Cons *p = trans_p_list_.head_; p; p = p->next_) - (p->car_->*method) (); + for (SCM p = list; gh_pair_p (p); p = gh_cdr(p)) + (unsmob_translator (gh_car (p))->*method) (); + } - void -Translator_group::each (Const_method_pointer method) const +Translator_group::each (Method_pointer method) { - for (Cons *p = trans_p_list_.head_; p; p = p->next_) - (p->car_->*method) (); + static_each (simple_trans_list_, method); + static_each (trans_group_list_, method); } void Translator_group::do_print() const { #ifndef NPRINT - if (!flower_dstream) - return ; - - gh_display (properties_dict_->self_scm ()); - if (status == ORPHAN) - { - DEBUG_OUT << "consists of: "; - for (int i=0; i < consists_str_arr_.size (); i++) - DEBUG_OUT << consists_str_arr_[i] << ", "; - DEBUG_OUT << "\naccepts: "; - for (int i=0; i < accepts_str_arr_.size (); i++) - DEBUG_OUT << accepts_str_arr_[i] << ", "; - } - else - { - if (id_str_.length_i ()) - DEBUG_OUT << "ID: " << id_str_ ; - DEBUG_OUT << " iterators: " << iterator_count_<< '\n'; - } - each (&Translator::print); #endif } -void -Translator_group::do_pre_move_processing () +static SCM +trans_list (SCM namelist, Music_output_def *mdef) { - each (&Translator::pre_move_processing); -} - -void -Translator_group::do_post_move_processing () -{ - each (&Translator::post_move_processing); -} - -void -Translator_group::do_process_music () -{ - each (&Translator::process_music); -} - -void -Translator_group::do_creation_processing () -{ - each (&Translator::creation_processing); + SCM l = SCM_EOL; + for (SCM s = namelist; gh_pair_p (s) ; s = gh_cdr (s)) + { + Translator * t = mdef->find_translator_l (ly_scm2string (gh_car (s))); + if (!t) + warning (_f ("can't find: `%s'", s)); + else + { + Translator * tr = t->clone (); + SCM str = tr->self_scm (); + l = gh_cons (str, l); + scm_unprotect_object (str); + } + } + return l; } -void -Translator_group::do_removal_processing () -{ - each (&Translator::removal_processing); -} void Translator_group::do_add_processing () { - for (int i=0; i < consists_str_arr_.size(); i++) + assert (simple_trans_list_== SCM_EOL); + + SCM correct_order = scm_reverse (property_pushes_); // pity of the mem. + for (SCM s = correct_order; gh_pair_p (s); s = gh_cdr (s)) { - String s = consists_str_arr_[i]; - Translator * t = output_def_l ()->find_translator_l (s); - if (!t) - warning (_f ("can't find: `%s'", s)); - else - add_translator (t->clone ()); + SCM entry = gh_car (s); + SCM val = gh_cddr (entry); + val = gh_pair_p (val) ? gh_car (val) : SCM_UNDEFINED; + + Translator_group_initializer::apply_pushpop_property (this, gh_car (entry), + gh_cadr (entry), + val); } - for (int i=0; i-- < consists_end_str_arr_.size (); i++) - { - String s = consists_end_str_arr_[i]; - Translator * t = output_def_l ()->find_translator_l (s); - if (!t) - warning (_f ("can't find: `%s'", s)); - else - add_translator (t->clone ()); + + SCM l1 = trans_list (consists_name_list_, output_def_l ()); + SCM l2 =trans_list (end_consists_name_list_, output_def_l ()); + l1 = scm_reverse_x (l1, l2); + + simple_trans_list_ = l1; + for (SCM s = l1; gh_pair_p (s) ; s = gh_cdr (s)) + { + Translator * t = unsmob_translator (gh_car (s)); + + t->daddy_trans_l_ = this; + t->output_def_l_ = output_def_l_; + t->add_processing (); } + + } +/* + PROPERTIES + */ Translator_group* Translator_group::where_defined (SCM sym) const { - if (properties_dict_->elem_b (sym)) + if (properties_dict ()->elem_b (sym)) { return (Translator_group*)this; } @@ -445,9 +387,9 @@ Translator_group::where_defined (SCM sym) const SCM Translator_group::get_property (SCM sym) const { - if (properties_dict_->elem_b (sym)) + if (properties_dict ()->elem_b (sym)) { - return properties_dict_->get (sym); + return properties_dict ()->get (sym); } if (daddy_trans_l_) @@ -465,7 +407,78 @@ Translator_group::set_property (String id, SCM val) void Translator_group::set_property (SCM sym, SCM val) { - properties_dict_->set (sym, val); + properties_dict ()->set (sym, val); } +/* + Push or pop (depending on value of VAL) a single entry (ELTPROP . VAL) + entry from a translator property list by name of PROP +*/ +void +Translator_group::execute_single_pushpop_property (SCM prop, SCM eltprop, SCM val) +{ + if (gh_symbol_p(prop)) + { + if (val != SCM_UNDEFINED) + { + SCM prev = get_property (prop); + prev = gh_cons (gh_cons (eltprop, val), prev); + set_property (prop, prev); + } + else + { + SCM prev = get_property (prop); + + SCM newprops= SCM_EOL ; + while (gh_pair_p (prev) && gh_caar (prev) != eltprop) + { + newprops = gh_cons (gh_car (prev), newprops); + prev = gh_cdr (prev); + } + + if (gh_pair_p (prev)) + { + newprops = scm_reverse_x (newprops, gh_cdr (prev)); + set_property (prop, newprops); + } + } + } +} + + + + + +/* + STUBS +*/ +void +Translator_group::do_pre_move_processing () +{ + each (&Translator::pre_move_processing); +} + +void +Translator_group::do_post_move_processing () +{ + each (&Translator::post_move_processing); +} + +void +Translator_group::do_process_music () +{ + each (&Translator::process_music); +} + +void +Translator_group::do_creation_processing () +{ + each (&Translator::creation_processing); +} + +void +Translator_group::do_removal_processing () +{ + each (&Translator::removal_processing); +} diff --git a/lily/translator.cc b/lily/translator.cc index 68db603831..6605eaae0c 100644 --- a/lily/translator.cc +++ b/lily/translator.cc @@ -12,6 +12,7 @@ #include "translator-group.hh" #include "moment.hh" +#include "ly-smobs.icc" char const* Translator::name() const @@ -23,20 +24,42 @@ Translator::~Translator () { } +void +Translator::init () +{ + status_ = ORPHAN; + simple_trans_list_ = SCM_EOL; + trans_group_list_ = SCM_EOL; + properties_scm_ = SCM_EOL; + accepts_name_list_ = SCM_EOL; + consists_name_list_ = SCM_EOL; + end_consists_name_list_ = SCM_EOL; + property_pushes_ = SCM_EOL; + daddy_trans_l_ =0; +} + Translator::Translator () { - status = ORPHAN; - daddy_trans_l_ = 0; + init (); output_def_l_ = 0; + smobify_self (); + } Translator::Translator (Translator const &s) : Input (s) { - status = ORPHAN; - daddy_trans_l_ =0; + init (); + + consists_name_list_ = scm_list_copy (s.consists_name_list_); + end_consists_name_list_ = scm_list_copy (s.end_consists_name_list_); + accepts_name_list_ = scm_list_copy (s.accepts_name_list_); + property_pushes_ = scm_list_copy (s.property_pushes_); + output_def_l_ = s.output_def_l_; type_str_ = s.type_str_; + + smobify_self (); } bool @@ -62,11 +85,11 @@ Translator::now_mom () const void Translator::add_processing () { - if (status > ORPHAN) + if (status_ > ORPHAN) return; do_add_processing (); - status = VIRGIN; + status_ = VIRGIN; } void @@ -97,40 +120,40 @@ Translator::do_print () const void Translator::creation_processing () { - if (status >= CREATION_INITED) + if (status_ >= CREATION_INITED) return ; do_creation_processing (); - status = CREATION_INITED; + status_ = CREATION_INITED; } void Translator::post_move_processing () { - if (status >= MOVE_INITED) + if (status_ >= MOVE_INITED) return; creation_processing (); do_post_move_processing (); - status = MOVE_INITED; + status_ = MOVE_INITED; } void Translator::removal_processing () { - if (status == ORPHAN) + if (status_ == ORPHAN) return; creation_processing (); do_removal_processing (); // elegancy ... - // status = ORPHAN; + // status_ = ORPHAN; } bool Translator::try_music (Music * r) { - if (status < MOVE_INITED) + if (status_ < MOVE_INITED) post_move_processing (); return do_try_music (r); @@ -139,12 +162,12 @@ Translator::try_music (Music * r) void Translator::process_music () { - if (status < PROCESSED_REQS) + if (status_ < PROCESSED_REQS) post_move_processing (); - else if (status >= PROCESSED_REQS) + else if (status_ >= PROCESSED_REQS) return; - status = PROCESSED_REQS; + status_ = PROCESSED_REQS; do_process_music (); } @@ -152,7 +175,7 @@ void Translator::pre_move_processing () { do_pre_move_processing (); - status = CREATION_INITED; + status_ = CREATION_INITED; } @@ -199,3 +222,47 @@ void Translator::do_removal_processing () { } + + +/* + + SMOBS + +*/ +SCM +Translator::mark_smob (SCM sm) +{ + Translator * me = (Translator*) SCM_CELL_WORD_1(sm); + scm_gc_mark (me->consists_name_list_); + scm_gc_mark (me->accepts_name_list_); + scm_gc_mark (me->end_consists_name_list_); + scm_gc_mark (me->simple_trans_list_); + scm_gc_mark (me->trans_group_list_); + scm_gc_mark (me->property_pushes_); + return me->properties_scm_; +} + + +int +Translator::print_smob (SCM s, SCM port, scm_print_state *) +{ + Translator *sc = (Translator *) gh_cdr (s); + + scm_puts ("#name (), port); + scm_display (sc->simple_trans_list_, port); + /* + don't try to print properties, that is too much hassle. + */ + scm_puts (" >", port); + + + + return 1; +} + + + +IMPLEMENT_UNSMOB(Translator, translator); +IMPLEMENT_SMOBS(Translator); +IMPLEMENT_DEFAULT_EQUAL_P(Translator); diff --git a/lily/voice-devnull-engraver.cc b/lily/voice-devnull-engraver.cc index ed5e782706..a6684ed454 100644 --- a/lily/voice-devnull-engraver.cc +++ b/lily/voice-devnull-engraver.cc @@ -22,30 +22,27 @@ protected: ADD_THIS_TRANSLATOR (Voice_devnull_engraver); +static char const *junk_interfaces[] = { + // "beam-interface", + "slur-interface", + "tie-interface", + "text-item-interface", + "text-script-interface", + "dynamic-interface", + "crescendo-interface", + 0 +}; + void Voice_devnull_engraver::acknowledge_element (Score_element_info i) { if (daddy_trans_l_->id_str_ == "two" && (to_boolean (get_property ("unison")) || to_boolean (get_property ("unisilence")))) - { - static char const *junk[] = { - // "beam-interface", - "slur-interface", - "tie-interface", - "text-item-interface", - "text-script-interface", - "dynamic-interface", - "crescendo-interface", - 0 - }; - for (char const **p = junk; *p; *p++) + for (char const **p = junk_interfaces; *p; p++) + if (i.elem_l_->has_interface (ly_symbol2scm (*p))) { - if (i.elem_l_->has_interface (ly_symbol2scm (*p))) - { - i.elem_l_->suicide (); - return; - } + i.elem_l_->suicide (); + return; } - } } diff --git a/ly/engraver.ly b/ly/engraver.ly index 0d1408d4c1..3671d3c46c 100644 --- a/ly/engraver.ly +++ b/ly/engraver.ly @@ -6,8 +6,6 @@ StaffContext=\translator { \type "Engraver_group_engraver"; \name Staff ; \consists "Output_property_engraver"; - barAuto = ##t - voltaVisibility = ##t Generic_property_list = #generic-staff-properties \consists "Property_engraver"; @@ -16,36 +14,11 @@ StaffContext=\translator { % Bar_engraver must be first so default bars aren't overwritten % with empty ones. - voltaPadding = #5 % urg, in \pt - voltaMinimumSpace = #25 % urg, in \pt - - StaffMinimumVerticalExtent = #(cons -4.0 4.0) \consists "Repeat_engraver"; - % name, glyph id, c0 position - supportedClefTypes = #'( - ("treble" . ("clefs-G" -2)) - ("violin" . ("clefs-G" -2)) - ("G" . ("clefs-G" -2)) - ("G2" . ("clefs-G" -2)) - ("french" . ("clefs-G" -4 )) - ("soprano" . ("clefs-C" -4 )) - ("mezzosoprano" . ("clefs-C" -2 )) - ("alto" . ("clefs-C" 0 )) - ("tenor" . ("clefs-C" 2 )) - ("baritone" . ("clefs-C" 4 )) - ("varbaritone" . ("clefs-F" 0)) - ("bass" . ("clefs-F" 2 )) - ("F" . ( "clefs-F" 2)) - ("subbass" . ("clefs-F" 4)) - ) - % where is c0 in this clef? - clefPitches = #'(("clefs-G" . -4) - ("clefs-C" . 0) - ("clefs-F" . 4)) - + \consists "Clef_engraver"; \consists "Key_engraver"; \consists "Time_signature_engraver"; @@ -56,23 +29,19 @@ StaffContext=\translator { \consistsend "Axis_group_engraver"; - - %{ The Instrument_name_engraver puts the name of the instrument (\property Staff.instrument; Staff.instr for subsequent lines) to the left of a staff. - Usually, you only want this in the full score, not in the parts. + This is commented out, so you don't get funny things on the + PianoStaff \consists "Instrument_name_engraver"; %} - defaultClef = #"treble" - \consists "Separating_line_group_engraver"; \accepts "Voice"; - dynamicStyle = #"dynamic" }; \translator{\StaffContext } @@ -83,14 +52,10 @@ StaffContext=\translator { \consists "System_start_delimiter_engraver"; systemStartDelimiterGlyph = #'bracket - - \accepts "Staff"; \accepts "RhythmicStaff"; \accepts "GrandStaff"; \accepts "PianoStaff"; - - \accepts "Lyrics"; \accepts "ChordNames"; } @@ -104,13 +69,17 @@ RhythmicStaffContext=\translator{ Generic_property_list = #generic-staff-properties - barSize = 4.0 * \staffspace ; + barSize = 4.0 * \staffspace ; % urg: pt + \consists "Pitch_squash_engraver"; \consists "Separating_line_group_engraver"; \name RhythmicStaff; - voltaPadding = #5 % urg, in \pt - voltaMinimumSpace = #15 % urg, in \pt + \pushproperty #'basicVoltaSpannerProperties #'minimum-space #15 % urg, in \pt + \pushproperty #'basicVoltaSpannerProperties #'padding #5 % urg, in \pt + + + \consists "Repeat_engraver"; \consists "Bar_engraver"; \consists "Time_signature_engraver"; @@ -124,10 +93,8 @@ VoiceContext = \translator { \type "Engraver_group_engraver"; \name Voice; - dynamicPadding = #3 % urg, in \pt - dynamicMinimumSpace = #6 % urg, in \pt - Generic_property_list = #generic-voice-properties + \consists "Output_property_engraver"; \consists "Dynamic_engraver"; % must come before text_engraver. @@ -143,24 +110,18 @@ VoiceContext = \translator { \consists "Chord_tremolo_engraver"; \consists "Melisma_engraver"; - textScriptPadding = #3.0 \consists "Text_engraver"; \consists "A2_engraver"; \consists "Voice_devnull_engraver"; - % ugh : set these in Score context, please. + startSustain = #"Ped." stopSustain = #"*" stopStartSustain = #"*Ped." startUnaChorda = #"una chorda" stopUnaChorda = #"tre chorde" - - soloText = #"Solo" - soloIIText = #"Solo II" - aDueText = #"\\`a2" - soloADue = ##t - splitInterval = #'(0 . 1) - + % should make separate lists for stopsustain and startsustain + \consists "Piano_pedal_engraver"; \consists "Script_engraver"; \consists "Script_column_engraver"; @@ -192,18 +153,19 @@ GraceContext=\translator { \consists "Align_note_column_engraver"; \consists "Rhythmic_column_engraver"; - \consists "Dynamic_engraver"; - \consists "Text_engraver"; + + \consists "Dynamic_engraver";% in Grace ??? + \consists "Text_engraver"; % in Grace ??? \consists "Property_engraver"; - stemStyle = #"grace" - flagStyle = #"grace" + \pushproperty #'basicStemProperties #'style #"grace" + \pushproperty #'basicStemProperties #'flag-style #"grace" + \pushproperty #'basicStemProperties #'stem-length #6.0 + \pushproperty #'basicStemProperties #'direction #1 + \pushproperty #'(basicNoteHeadProperties basicStemProperties basicBeamProperties basicTextScriptProperties basicSlurProperties basicLocalKeyProperties) #'font-size #-1 + weAreGraceContext = ##t - fontSize = #-1 - - stemLength = #6.0 - verticalDirection = \up ; graceAccidentalSpace= 1.5 * \staffspace; }; @@ -365,40 +327,71 @@ OrchestralPartStaffContext = \translator { ScoreContext = \translator { \type Score_engraver; \name Score; - - marginScriptPadding = #10 % urg, in \pt + \consists "Timing_engraver"; \consists "Output_property_engraver"; - - %bracketCollapseHeight = #10 % \pt \consists "System_start_delimiter_engraver"; - -% \consists "Score_priority_engraver"; + \consists "Mark_engraver"; \consists "Break_align_engraver"; - breakAlignOrder = #'( - Instrument_name - Left_edge_item - Span_bar - Breathing_sign - Clef_item - Key_item - Staff_bar - Time_signature - Stanza_number - ) \consists "Spacing_engraver"; \consists "Vertical_align_engraver"; \consists "Lyric_phrasing_engraver"; - automaticPhrasing = ##t; - \consists "Bar_number_engraver"; + + + \accepts "Staff"; + \accepts "StaffGroup"; + \accepts "RhythmicStaff"; + \accepts "Lyrics"; + \accepts "ChordNames"; + \accepts "GrandStaff"; + \accepts "ChoirStaff"; + \accepts "PianoStaff"; + \accepts "NoteNames"; + + soloText = #"Solo" + soloIIText = #"Solo II" + aDueText = #"\\`a2" + soloADue = ##t + splitInterval = #'(0 . 1) + + defaultClef = #"treble" + + StaffMinimumVerticalExtent = #(cons -4.0 4.0) + + barAuto = ##t + voltaVisibility = ##t + % name, glyph id, c0 position + supportedClefTypes = #'( + ("treble" . ("clefs-G" -2)) + ("violin" . ("clefs-G" -2)) + ("G" . ("clefs-G" -2)) + ("G2" . ("clefs-G" -2)) + ("french" . ("clefs-G" -4 )) + ("soprano" . ("clefs-C" -4 )) + ("mezzosoprano" . ("clefs-C" -2 )) + ("alto" . ("clefs-C" 0 )) + ("tenor" . ("clefs-C" 2 )) + ("baritone" . ("clefs-C" 4 )) + ("varbaritone" . ("clefs-F" 0)) + ("bass" . ("clefs-F" 2 )) + ("F" . ( "clefs-F" 2)) + ("subbass" . ("clefs-F" 4)) + ) + % where is c0 in this clef? + clefPitches = #'(("clefs-G" . -4) + ("clefs-C" . 0) + ("clefs-F" . 4)) + + + automaticPhrasing = ##t; alignmentReference = \down; defaultClef = #"treble" defaultBarType = #"|" - systemStartDelimiterGlyph = #'bar-line + systemStartDelimiterGlyph = #'bar-line % % what order to print accs. We could compute this, @@ -409,17 +402,27 @@ ScoreContext = \translator { (6 . -1) (2 . -1) (5 . -1 ) (1 . -1) (4 . -1) (0 . -1) (3 . -1) (3 . 1) (0 . 1) (4 . 1) (1 . 1) (5 . 1) (2 . 1) (6 . 1) ) + breakAlignOrder = #'( + Instrument_name + Left_edge_item + Span_bar + Breathing_sign + Clef_item + Key_item + Staff_bar + Time_signature + Stanza_number + ) + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % default settings, mainly for breakable items - % in alphabetical order % TODO: uniform naming.; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % - % distances are given in stafflinethickness (thicknesses) and staffspace (distances) + % distances are given in stafflinethickness (thicknesses) and + % staffspace (distances) % - - basicBarProperties = #`( (break-align-symbol . Staff_bar) (barsize-procedure . ,Bar::get_staff_bar_size) @@ -501,17 +504,20 @@ ScoreContext = \translator { (dot-count . 1) (interfaces . (dot-interface)) ) - basicDynamicLineSpannerProperties = #`( - (interfaces . (dynamic-interface axis-group-interface)) - (axes . ( 1)) - ) - basicDynamicTextProperties = # `( + basicDynamicTextProperties = # `( (style . "dynamic") (interfaces . (dynamic-interface)) (molecule-callback . ,Text_item::brew_molecule) (script-priority . 100) (self-alignment-Y . 0) ) + + basicDynamicLineSpannerProperties = #`( + (interfaces . (dynamic-interface axis-group-interface)) + (axes . ( 1)) + (padding . 3) + (minimum-space . 6) + ) leftEdgeBasicProperties = #`( (break-align-symbol . Left_edge_item) (breakable . #t) @@ -531,6 +537,13 @@ ScoreContext = \translator { (minimum-length . 0.5) (molecule-callback . ,Hyphen_spanner::brew_molecule) ) + + basicInstrumentNameProperties = #`( + (breakable . #t) + (molecule-callback . ,Text_item::brew_molecule) + (break-align-symbol . Instrument_name) + (visibility-lambda . ,begin-of-line-visible) + ) basicKeyProperties = #`( (molecule-callback . ,Key_item::brew_molecule) (interfaces . (key-item-interface)) @@ -565,6 +578,7 @@ ScoreContext = \translator { (breakable . #t) (interfaces . (mark-interface)) (visibility-lambda . ,end-of-line-invisible) + (padding . 4.0) ) basicMultiMeasureRestProperties = #`( (spacing-procedure . ,Multi_measure_rest::set_spacing_rods) @@ -594,13 +608,6 @@ ScoreContext = \translator { (axes 0) (rank . -1) ) - basicPedalProperties = #`( - (molecule-callback . ,Text_item::brew_molecule) - (style . "italic") - (no-spacing-rods . #t) - (self-alignment-X . 0) - - ) basicTextProperties = #`( ) basicRestProperties = #`( (interfaces . (rest-interface rhythmic-head-interface)) @@ -658,20 +665,6 @@ ScoreContext = \translator { (break-align-symbol . Clef_item) (visibility-lambda . ,begin-of-line-visible) ) - basicStemProperties = #`( - (before-line-breaking-callback . ,Stem::before_line_breaking) - (molecule-callback . ,Stem::brew_molecule) - - ; if stem is on middle line, choose this direction. - (default-neutral-direction . 1) - (interfaces . (stem-interface)) - ) - basicSustainPedalProperties = #`( - (no-spacing-rods . #t) - (molecule-callback . ,Sustain_pedal::brew_molecule) - (self-alignment-X . 0) - (interfaces . (sustain-pedal-interface)) - ) staffSymbolBasicProperties = #`( (molecule-callback . ,Staff_symbol::brew_molecule) (staff-space . 1.0) @@ -692,10 +685,9 @@ ScoreContext = \translator { ) basicTextScriptProperties = #`( (molecule-callback . ,Text_item::brew_molecule) - -: -- don't set, because property-engraver will not override it. -; (no-spacing-rods . #t) + (no-spacing-rods . #t) (interfaces . (text-script-interface text-item-interface)) + (padding . 3.0) ) basicTieProperties = #`( (molecule-callback . ,Tie::brew_molecule) @@ -723,12 +715,26 @@ ScoreContext = \translator { (molecule-callback . ,Tuplet_spanner::brew_molecule) (interfaces . (tuplet-spanner-interface)) ) + basicSostenutoPedalProperties = #`( + (molecule-callback . ,Text_item::brew_molecule) + (style . "italic") + (no-spacing-rods . #t) + (self-alignment-X . 0) + + ) basicStemTremoloProperties = #`( (molecule-callback . ,Stem_tremolo::brew_molecule) (beam-width . 2.0) ; staff-space (beam-thickness . 0.42) ; staff-space ) + basicStemProperties = #`( + (before-line-breaking-callback . ,Stem::before_line_breaking) + (molecule-callback . ,Stem::brew_molecule) + ; if stem is on middle line, choose this direction. + (default-neutral-direction . 1) + (interfaces . (stem-interface)) + ) basicSeparationItemProperties = #`( (interfaces . (separation-item-interface)) ) @@ -736,33 +742,29 @@ ScoreContext = \translator { (interfaces . (separation-spanner-interface)) (spacing-procedure . ,Separating_group_spanner::set_spacing_rods) ) - basicInstrumentNameProperties = #`( - (breakable . #t) - (molecule-callback . ,Text_item::brew_molecule) - (break-align-symbol . Instrument_name) - (visibility-lambda . ,begin-of-line-visible) - ) - basicVerticalAxisGroupProperties = #`( - (axes 1) - (interfaces . (axis-group-interface)) + basicSustainPedalProperties = #`( + (no-spacing-rods . #t) + (molecule-callback . ,Sustain_pedal::brew_molecule) + (self-alignment-X . 0) + (interfaces . (sustain-pedal-interface)) + ) + basicUnaChordaPdealProperties = #`( + (molecule-callback . ,Text_item::brew_molecule) + (style . "italic") + (no-spacing-rods . #t) + (self-alignment-X . 0) ) + basicVoltaSpannerProperties = #`( (molecule-callback . ,Volta_spanner::brew_molecule) (interfaces . (volta-spanner-interface)) + (padding . 5) + (minimum-space . 25) + ) + basicVerticalAxisGroupProperties = #`( + (axes 1) + (interfaces . (axis-group-interface)) ) - - \accepts "Staff"; - \accepts "StaffGroup"; - \accepts "RhythmicStaff"; - \accepts "Lyrics"; - \accepts "ChordNames"; - \accepts "GrandStaff"; - \accepts "ChoirStaff"; - \accepts "PianoStaff"; - \accepts "NoteNames"; - - - markVisibilityFunction = #end-of-line-invisible }; \translator { \ScoreContext } @@ -770,10 +772,6 @@ ScoreContext = \translator { OrchestralScoreContext= \translator { \ScoreContext - barScriptPadding = #2.0 % dimension \pt - markScriptPadding = #4.0 - - \consists "Mark_engraver"; }; \translator { @@ -781,4 +779,5 @@ OrchestralScoreContext= \translator { \name NoteNames; \consistsend "Axis_group_engraver"; \consists "Note_name_engraver"; + \consists "Separating_line_group_engraver"; } diff --git a/make/out/lilypond.lsm b/make/out/lilypond.lsm index 4281407c22..951fe62c35 100644 --- a/make/out/lilypond.lsm +++ b/make/out/lilypond.lsm @@ -1,15 +1,15 @@ Begin3 Title: LilyPond -Version: 1.3.81 -Entered-date: 28AUG00 +Version: 1.3.82 +Entered-date: 31AUG00 Description: Keywords: music notation typesetting midi fonts engraving Author: hanwen@cs.uu.nl (Han-Wen Nienhuys) janneke@gnu.org (Jan Nieuwenhuizen) Maintained-by: hanwen@stack.nl (Han-Wen Nienhuys) Primary-site: sunsite.unc.edu /pub/Linux/apps/sound/convert - 1000k lilypond-1.3.81.tar.gz + 1000k lilypond-1.3.82.tar.gz Original-site: ftp.cs.uu.nl /pub/GNU/LilyPond/development/ - 1000k lilypond-1.3.81.tar.gz + 1000k lilypond-1.3.82.tar.gz Copying-policy: GPL End diff --git a/make/out/lilypond.spec b/make/out/lilypond.spec index 6741ab896e..d6ee4e0161 100644 --- a/make/out/lilypond.spec +++ b/make/out/lilypond.spec @@ -1,9 +1,9 @@ Name: lilypond -Version: 1.3.81 +Version: 1.3.82 Release: 1 Copyright: GPL Group: Applications/Publishing -Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.3.81.tar.gz +Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.3.82.tar.gz Summary: A program for printing sheet music. URL: http://www.cs.uu.nl/~hanwen/lilypond # Icon: lilypond-icon.gif diff --git a/mutopia/Coriolan/coriolan-paper.ly b/mutopia/Coriolan/coriolan-paper.ly index 9a277e310c..9d33209b23 100644 --- a/mutopia/Coriolan/coriolan-paper.ly +++ b/mutopia/Coriolan/coriolan-paper.ly @@ -94,7 +94,7 @@ \consists "Script_engraver"; \consists "Script_column_engraver"; \consists "Rhythmic_column_engraver"; -%% \consists "Slur_engraver"; + \consists "Slur_engraver"; \consists "Tie_engraver"; } \translator { diff --git a/mutopia/Coriolan/coriolan-part-combine-paper.ly b/mutopia/Coriolan/coriolan-part-combine-paper.ly index dd045ff0e4..c23c88937a 100644 --- a/mutopia/Coriolan/coriolan-part-combine-paper.ly +++ b/mutopia/Coriolan/coriolan-part-combine-paper.ly @@ -94,7 +94,7 @@ \consists "Script_engraver"; \consists "Script_column_engraver"; \consists "Rhythmic_column_engraver"; -%% \consists "Slur_engraver"; + \consists "Slur_engraver"; \consists "Tie_engraver"; } \translator { diff --git a/scm/generic-property.scm b/scm/generic-property.scm index a786acd0a1..befcda71bc 100644 --- a/scm/generic-property.scm +++ b/scm/generic-property.scm @@ -144,7 +144,7 @@ (define generic-All-properties (cons 'all - (list (list 'fontSize number? 'fontsize)))) + (list (list 'fontSize number? 'font-size)))) (define generic-notehead-properties diff --git a/scripts/abc2ly.py b/scripts/abc2ly.py index e592f9f38f..cc0d03c07e 100644 --- a/scripts/abc2ly.py +++ b/scripts/abc2ly.py @@ -1049,12 +1049,15 @@ def help (): print r""" Convert ABC to Mudela. -Usage: abc2ly [OPTION]... ABC-FILE +Usage: abc2ly [OPTIONS]... ABC-FILE Options: -h, --help this help -o, --output=FILE set output filename to FILE -v, --version version information + +This program converts ABC music files (see +http://www.gre.ac.uk/~c.walshaw/abc2mtex/abc.txt) To LilyPond input. """ def print_version (): diff --git a/scripts/etf2ly.py b/scripts/etf2ly.py index 292e983fb8..b194f28561 100644 --- a/scripts/etf2ly.py +++ b/scripts/etf2ly.py @@ -14,10 +14,12 @@ # # todo: +# * automatic PC/mac/unix conversion # * slur/stem directions # * voices (2nd half of frame?) # * more intelligent lyrics # * beams (better use autobeam?) +# * more robust: try entertainer.etf (freenote), schubert ave maria (gmd) program_name = 'etf2ly' version = '@TOPLEVEL_VERSION@' @@ -151,11 +153,19 @@ class Slur: def calculate (self, chords): startnote = self.finale[0][5] endnote = self.finale[3][2] + try: + cs = chords[startnote] + ce = chords[endnote] - cs = chords[startnote] - cs.note_suffix = '(' + cs.note_suffix - ce = chords[endnote] - ce.prefix = ce.prefix + ')' + if not cs or not ce: + raise IndexError + + cs.note_suffix = '(' + cs.note_suffix + ce.note_prefix = ce.note_prefix + ')' + except IndexError: + sys.stderr.write ("""\nHuh? Incorrect slur start/endpoint +len(list) is %d, start/end is (%d,%d)\n""" % (len (chords), startnote, endnote)) + class Global_measure: def __init__ (self, number): @@ -166,6 +176,9 @@ class Global_measure: self.finale = [] + def __str__ (self): + return `self.finale ` + def set_timesig (self, finale): (beats, fdur) = finale (log, dots) = EDU_to_duration (fdur) @@ -248,17 +261,23 @@ class Verse: class Measure: def __init__(self, no): self.number = no - self.frames = [] + self.frames = [0] * 4 self.flags = 0 self.clef = 0 self.finale = [] self.global_measure = None + self.staff = None def add_finale_entry (self, entry): self.finale.append (entry) def calculate (self): - f0 = self.finale[0] + if len (self.finale) < 2: + sys.stderr.write ("Measure %d in staff %d has incomplete information.\n" % (self.number, self.staff.number)) + + return + + f0 = self.finale[0] f1 = self.finale[1] self.clef = string.atoi (f0[0]) @@ -286,11 +305,12 @@ class Frame: for c in self.chords: str = str + c.ly_string () + ' ' left = rat_subtract (left, c.length ()) + if left[0] < 0: - print self.number - print self.start, self.end - print left - raise 'bla' + sys.stderr.write ("""Huh? Going backwards. +Frame no %d, start/end (%d,%d) +""" % (self.number, self.start, self.end)) + left = (0,1) if left[0]: str = str + 's*%d/%d' % left @@ -310,7 +330,10 @@ class Staff: self.measures = self.measures + [None]* (1 + no - len (self.measures)) if self.measures[no] == None: - self.measures [no] = Measure (no) + m = Measure (no) + self.measures [no] =m + m.staff = self + return self.measures[no] def staffid (self): @@ -325,6 +348,9 @@ class Staff: last_clef = None gap = (0,1) for m in self.measures[1:]: + if not m : + continue # ugh. + g = m.global_measure e = '' if last_key <> g.keysignature: @@ -359,6 +385,10 @@ class Staff: first_frame = None gap = (0,1) for m in self.measures[1:]: + if not m: + continue + + fr = m.frames[x] if fr: first_frame = fr @@ -596,7 +626,12 @@ class Etf_file: = tuple (map (string.atoi, [no,prev,next,dur,pos,extended,follow])) entryflag = string.atol (entryflag,16) - assert (no==len (self.entries)) + if no > len (self.entries): + sys.stderr.write ("Huh? Entry number to large,\nexpected %d got %d. Filling with void entries.\n" % (len(self.entries), no )) + while len (self.entries) <> no: + c = ((len (self.entries), 0, 0, 0, 0, 0L, 0, 0), []) + self.entries.append (c) + current_entry = ((no, prev, next, dur, pos, entryflag, extended, follow), []) self.entries.append (current_entry) return m @@ -632,6 +667,11 @@ class Etf_file: if m: (frameno, startnote, endnote, foo, bar) = m.groups () (frameno, startnote, endnote) = tuple (map (string.atoi, [frameno, startnote, endnote])) + if frameno > len (self.frames): + sys.stderr.write ("Frame no %d missing, filling up to %d\n" % (len(self.frames), frameno)) + while frameno <> len (self.frames): + self.frames.append (Frame ((len (self.frames), 0,0) )) + self.frames.append (Frame ((frameno, startnote, endnote))) return m @@ -660,8 +700,12 @@ class Etf_file: def parse (self, name): sys.stderr.write ('parsing ...') sys.stderr.flush () + + gulp = open (name).read () + + gulp = re.sub ('[\n\r]+', '\n', gulp) + ls = string.split (gulp, '\n') - ls = open (name).readlines () for l in ls: m = None if not m: @@ -691,6 +735,9 @@ class Etf_file: continue mno = 1 for m in st.measures[1:]: + if not m: + continue + m.global_measure = self.measures[mno] m.calculate() @@ -756,7 +803,7 @@ class Etf_file: def __str__ (self): - return self.dump () + return 'ETF FILE %s %s' % (self.measures, self.entries) def unthread_entries (self): self.chords = [None] @@ -827,7 +874,7 @@ for f in files: sys.stderr.write ('Processing `%s\'\n' % f) e = Etf_file(f) if not out_filename: - out_filename = os.path.basename (re.sub ('.etf$', '.ly', f)) + out_filename = os.path.basename (re.sub ('(?i).etf$', '.ly', f)) if out_filename == f: out_filename = os.path.basename (f + '.ly') diff --git a/scripts/mudela-book.py b/scripts/mudela-book.py index 03b479bfb2..610c29e709 100644 --- a/scripts/mudela-book.py +++ b/scripts/mudela-book.py @@ -1,7 +1,43 @@ #!@PYTHON@ # vim: set noexpandtab: +import time +t1 = time.clock() + +# support bruk av convert-mudela +# +# option: +# 11pt, 13pt, 16pt, 20pt, 26pt +# singleline +# multiline +# fragment (used when a comment containg \score confuses mudela-book) +# nonfragment (probably not needed) +# verbatim + +# latex only options: +# eps +# + +# command line options +# --defalt-mudela-fontsize +# --force-mudela-fontsize +# --outname +# --force-verbatim make all mudela verbatim. Maybe not that useful +# --dependencies +# --dep-prefix +# --no-pictures +# --no-lily # TODO: Figure out clean set of options. -# add support for .lilyrc + +# BUG: does not handle \verb|\begin{verbatim}\end{verbatim}| correctly. +# Should make a joint RE for \verb and \begin, \end{verbatim} + +# TODO: add an option to read the .ly files from a previous run and dump +# the .tex file, so you can do +# +# * mudela-book file.tex +# * convert-mudela *.ly +# * mudela-book --read-lys *.ly +# import os import stat @@ -12,7 +48,12 @@ import sys import __main__ +initfile = '' + + program_version = '@TOPLEVEL_VERSION@' +if program_version == '@' + 'TOPLEVEL_VERSION' + '@': + program_version = '1.3.69-very-unstable' include_path = [os.getcwd()] @@ -24,6 +65,7 @@ g_do_pictures = 1 g_num_cols = 1 format = '' g_run_lilypond = 1 +g_use_hash = 1 no_match = 'a\ba' default_music_fontsize = 16 @@ -62,20 +104,22 @@ def get_linewidth(cols, paper, fontsize): option_definitions = [ ('EXT', 'f', 'format', 'set format. EXT is one of texi and latex.'), - ('DIM', '', 'default-music-fontsize', 'default fontsize for music. DIM is assumed to be in points'), + ('DIM', '', 'default-music-fontsize', 'default fontsize for music. DIM is assumed to in points'), ('DIM', '', 'default-mudela-fontsize', 'deprecated, use --default-music-fontsize'), - ('DIM', '', 'force-music-fontsize', 'force fontsize for all inline mudela. DIM is assumed be to in points'), - ('DIM', '', 'force-mudela-fontsize', 'deprecated, use --force-music-fontsize'), + ('', 'h', 'help', 'print help'), ('DIR', 'I', 'include', 'include path'), + ('', '', 'init', 'mudela-book initfile'), + ('DIM', '', 'force-music-fontsize', 'force fontsize for all inline mudela. DIM is assumed to in points'), + ('DIM', '', 'force-mudela-fontsize', 'deprecated, use --force-music-fontsize'), + ('', '', 'force-verbatim', 'make all mudela verbatim'), ('', 'M', 'dependencies', 'write dependencies'), - ('PREF', '', 'dep-prefix', 'prepend PREF before each -M dependency'), ('', 'n', 'no-lily', 'don\'t run lilypond'), ('', '', 'no-pictures', "don\'t generate pictures"), ('', '', 'read-lys', "don't write ly files."), - ('FILE', 'o', 'outname', 'filename main output file'), - ('FILE', '', 'outdir', "where to place generated files"), + ('FILE', 'o', 'outname', 'prefix for filenames'), ('', 'v', 'version', 'print version information' ), - ('', 'h', 'help', 'print help'), + ('PREF', '', 'dep-prefix', 'prepend PREF before each -M dependency'), + ('FILE', '', 'outdir', "where to place generated files"), ] # format specific strings, ie. regex-es for input, and % strings for output @@ -150,16 +194,16 @@ re_dict = { 'option-sep' : ', *', 'header': r"""\\documentclass(\[.*?\])?""", 'preamble-end': '\\\\begin{document}', - 'verbatim': r"""(?s)(?P\\begin{verbatim}.*?\\end{verbatim})""", - 'verb': r"""(?P\\verb(?P.).*?(?P=del))""", + 'verbatim': r"""(?s)\\begin{verbatim}(?P.*?)\\end{verbatim}""", + 'verb': r"""\\verb(.)(?P.*?)\1""", 'mudela-file': r'\\mudelafile(\[(?P.*?)\])?\{(?P.+)}', - 'mudela' : '(?m)\\\\mudela(\[(?P.*?)\])?{(?P.*?)}', - #'mudela-block': r"""(?m)^[^%]*?\\begin(\[(?P.*?)\])?{mudela}(?P.*?)\\end{mudela}""", + 'mudela' : '\\\\mudela(\[(?P.*?)\])?{(?P.*?)}', 'mudela-block': r"""(?s)\\begin(\[(?P.*?)\])?{mudela}(?P.*?)\\end{mudela}""", + 'interesting-cs': '\\\\(chapter|section|twocolumn|onecolumn)', 'def-post-re': r"""\\def\\postMudelaExample""", 'def-pre-re': r"""\\def\\preMudelaExample""", 'intertext': r',?\s*intertext=\".*?\"', - 'ignore': r"(?m)(?P%.*?^)", + 'ignore': no_match, 'numcols': r"(?P\\(?Pone|two)column)", }, @@ -169,13 +213,14 @@ re_dict = { 'header': no_match, 'preamble-end': no_match, 'verbatim': r"""(?s)(?P@example\s.*?@end example\s)""", - 'verb': r"""(?P@code{.*?})""", + 'verb': r"""@code{(?P.*?)}""", 'mudela-file': '@mudelafile(\[(?P.*?)\])?{(?P[^}]+)}', 'mudela' : '@mudela(\[(?P.*?)\])?{(?P.*?)}', 'mudela-block': r"""(?s)@mudela(\[(?P.*?)\])?\s(?P.*?)@end mudela\s""", + 'interesting-cs': r"""[\\@](chapter|section)""", 'option-sep' : ', *', 'intertext': r',?\s*intertext=\".*?\"', - 'ignore': r"(?s)(?P@ignore\s.*?@end ignore)\s", + 'ignore': r"(?s)@ignore\s(.*?)@end ignore\s", 'numcols': no_match, } } @@ -351,7 +396,7 @@ def find_file (name): return '' def do_ignore(match_object): - return [('ignore', match_object.group('code'))] + return [] def make_verbatim(match_object): return [('verbatim', match_object.group('code'))] @@ -423,9 +468,7 @@ def chop_chunks(chunks, re_name, func): str = '' else: newchunks.append (('input', str[:m.start (0)])) - #newchunks.extend(func(m)) - # python 1.5 compatible: - newchunks = newchunks + func(m) + newchunks.extend(func(m)) str = str [m.end(0):] else: newchunks.append(c) @@ -450,6 +493,7 @@ def read_doc_file (filename): # we have to check for verbatim before doing include, # because we don't want to include files that are mentioned # inside a verbatim environment + chunks = chop_chunks(chunks, 'ignore', do_ignore) chunks = chop_chunks(chunks, 'verbatim', make_verbatim) chunks = chop_chunks(chunks, 'verb', make_verb) #ugh fix input @@ -458,8 +502,25 @@ def read_doc_file (filename): return chunks -taken_file_names = {} -def schedule_mudela_block (chunk, extra_opts): +def advance_counters (counter, str): + """Advance chap/sect counters, + Return the new counter tuple + """ + (chapter, section, count) = counter + while str: + m = get_re ('interesting-cs').search(str) + if not m: + break + str = str[m.end(0):] + g = m.group (1) + if g == 'chapter':#ugh use dict + (chapter, section, count) = (chapter + 1, 0, 0) + elif g == 'section': + (section, count) = (section + 1, 0) + return (chapter, section, count) + +taken_file_names = [] +def schedule_mudela_block (basename, chunk, extra_opts): """Take the body and options from CHUNK, figure out how the real .ly should look, and what should be left MAIN_STR (meant for the main file). The .ly is written, and scheduled in @@ -478,16 +539,15 @@ def schedule_mudela_block (chunk, extra_opts): assert type == 'mudela' opts = opts + extra_opts file_body = compose_full_body (body, opts) - basename = `abs(hash (file_body))` + if __main__.g_use_hash: + basename = `abs(hash (file_body))` for o in opts: m = re.search ('filename="(.*?)"', o) if m: - basename = m.group (1) - if not taken_file_names.has_key(basename): - taken_file_names[basename] = 0 - else: - taken_file_names[basename] = taken_file_names[basename] + 1 - basename = basename + "-%i" % taken_file_names[basename] + basename = m.group (1)#ugh add check if more than + #one file has the same name + assert basename not in taken_file_names + taken_file_names.append(basename) # writes the file if necessary, returns true if it was written if not g_read_lys: update_file(file_body, os.path.join(g_outdir, basename) + '.ly') @@ -527,11 +587,16 @@ def schedule_mudela_block (chunk, extra_opts): return ('mudela', newbody, opts, todo, basename) def process_mudela_blocks(outname, chunks, global_options):#ugh rename + (chap,sect,count) = (0,0,0) newchunks = [] # Count sections/chapters. for c in chunks: - if c[0] == 'mudela': - c = schedule_mudela_block (c, global_options) + if c[0] == 'input': + (chap,sect,count) = advance_counters((chap,sect,count), c[1]) + elif c[0] == 'mudela': + base = '%s-%d.%d.%d' % (outname, chap, sect, count) + count = count + 1 + c = schedule_mudela_block (base, c, global_options) elif c[0] == 'numcols': __main__.g_num_cols = c[2] newchunks.append (c) @@ -716,9 +781,8 @@ def do_file(input_filename): chunks = chop_chunks(chunks, 'mudela', make_mudela) chunks = chop_chunks(chunks, 'mudela-file', make_mudela_file) chunks = chop_chunks(chunks, 'mudela-block', make_mudela_block) - #for c in chunks: print c, "\n" - chunks = chop_chunks(chunks, 'ignore', do_ignore) chunks = chop_chunks(chunks, 'numcols', do_columns) + #for c in chunks: print c, "\n" global_options = scan_preamble(chunks[0][1]) chunks = process_mudela_blocks(my_outname, chunks, global_options) # Do It. @@ -741,7 +805,8 @@ def do_file(input_filename): sys.stderr.write ("Writing `%s'\n" % foutn) fout = open (foutn, 'w') for c in chunks: - fout.write (c[1]) + #if c[1] is not None: + fout.write (c[1]) fout.close () if do_deps: @@ -763,10 +828,11 @@ for opt in options: if o == '--include' or o == '-I': include_path.append (a) - elif o == '--version' or o == '-v': + elif o == '--version': print_version () sys.exit (0) - elif o == '--format' or o == '-f': + + elif o == '--format' or o == '-o': __main__.format = a elif o == '--outname' or o == '-o': if len(files) > 1: @@ -778,7 +844,7 @@ for opt in options: help () elif o == '--no-lily' or o == '-n': __main__.g_run_lilypond = 0 - elif o == '--dependencies' or o == '-M': + elif o == '--dependencies': do_deps = 1 elif o == '--default-music-fontsize': default_music_fontsize = string.atoi (a) @@ -790,6 +856,9 @@ for opt in options: elif o == '--force-mudela-fontsize': print "--force-mudela-fontsize is deprecated, use --default-mudela-fontsize" g_force_mudela_fontsize = string.atoi(a) + + elif o == '--init': + initfile = a elif o == '--dep-prefix': g_dep_prefix = a elif o == '--no-pictures': @@ -808,6 +877,10 @@ if g_outdir: for input_filename in files: do_file(input_filename) + + +t2 = time.clock() +print "Time:", t2-t1 # # Petr, ik zou willen dat ik iets zinvoller deed, # maar wat ik kan ik doen, het verandert toch niets? -- 2.39.5