From d4e71555e7e093a4da32d92378f8f475fa0d6aaa Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Sat, 24 Mar 2001 16:20:14 +0100 Subject: [PATCH] patch::: 1.3.141.jcn3 1.3.141.jcn3 ============ * some mup2ly progress. * Bugfix: ly2dvi: don't include empty set fo latexheaders, don't use python-1.5.2 abspath func. --- CHANGES | 25 +- Documentation/regression-test.tely | 2 + Documentation/topdocs/INSTALL.texi | 28 ++ Documentation/user/lilypond.tely | 5 +- Documentation/user/refman.itely | 144 +++------ Documentation/user/tutorial.itely | 37 +++ VERSION | 2 +- input/bugs/crescendo-squash.ly | 9 + input/regression/dynamics-broken-hairpin.ly | 12 + input/regression/dynamics-line.ly | 3 +- input/regression/percent-repeat.ly | 18 ++ input/star-spangled-banner.ly | 6 +- input/test/test-german-chords.ly | 14 + input/tricks/follow-thread.ly | 4 +- lily/hairpin.cc | 35 ++- lily/include/lookup.hh | 3 +- lily/include/percent-repeat-item.hh | 25 ++ lily/lookup.cc | 18 ++ lily/multi-measure-rest.cc | 5 +- lily/percent-repeat-engraver.cc | 87 ++++-- lily/percent-repeat-item.cc | 85 ++++++ lily/system-start-delimiter-engraver.cc | 8 + lily/system-start-delimiter.cc | 19 ++ lily/tuplet-engraver.cc | 10 + ly/german-chords.ly | 39 +++ mf/feta-schrift.mf | 19 -- ps/lily.ps | 66 ++--- scm/chord-name.scm | 18 +- scm/grob-description.scm | 88 +++--- scm/interface-description.scm | 47 +-- scm/ps.scm | 29 +- scm/tex.scm | 17 +- scripts/ly2dvi.py | 28 +- scripts/mup2ly.py | 312 ++++++++++++++------ scripts/pmx2ly.py | 4 +- 35 files changed, 880 insertions(+), 391 deletions(-) create mode 100644 input/bugs/crescendo-squash.ly create mode 100644 input/regression/dynamics-broken-hairpin.ly create mode 100644 input/regression/percent-repeat.ly create mode 100644 input/test/test-german-chords.ly create mode 100644 lily/include/percent-repeat-item.hh create mode 100644 lily/percent-repeat-item.cc create mode 100644 ly/german-chords.ly diff --git a/CHANGES b/CHANGES index 2bb1994a46..9996f1fa38 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,11 @@ +1.3.141.jcn3 +============ + +* some mup2ly progress. + +* Bugfix: ly2dvi: don't include empty set fo latexheaders, don't use +python-1.5.2 abspath func. + 1.3.141.jcn2 ============ @@ -5,17 +13,26 @@ * Bugfix: lilypond-book: accept \documentclass{article}. -1.3.141.jcn1 -============ - * scripts/update-lily.py: fancy source rebuild update tool that we're probably not going to use on www.lilypond.org. Check it out! * Bugfix: building of topdocs. -1.3.140.jcn6 +1.3.141.hwn1 ============ +* doco fixes. + +* Beat repeats, double measure repeats; removed repeat sign character +from the font (WARNING: FONT CHANGED). + +* cleanups in (de)crescendo code, fixed continued (de)crescendi. + +* German chords (Rune Zedler) + +1.3.141 +======= + * po update. * Renamed remaining mudela -> lilypond (except for old change logs). diff --git a/Documentation/regression-test.tely b/Documentation/regression-test.tely index 53d356514c..2b89bd8ab7 100644 --- a/Documentation/regression-test.tely +++ b/Documentation/regression-test.tely @@ -57,6 +57,8 @@ and documenting bugfixes. @lilypondfile[printfilename]{dynamics-line.ly} +@lilypondfile[printfilename]{dynamics-broken-hairpin.ly} + @lilypondfile[printfilename]{arpeggio.ly} @lilypondfile[printfilename]{glissando.ly} diff --git a/Documentation/topdocs/INSTALL.texi b/Documentation/topdocs/INSTALL.texi index 9d7e01ad9d..66141d6c21 100644 --- a/Documentation/topdocs/INSTALL.texi +++ b/Documentation/topdocs/INSTALL.texi @@ -257,6 +257,27 @@ everything will be compiled, but nothing will be installed. The resulting binaries can be found in the subdirectories @file{out/} (which contain all files generated during compilation). + +@section Emacs mode + + +An emacs mode for LilyPond is included with the source archive as +@file{lilypond-mode.el} and @file{lilypond-font-lock.el}. If you have +an RPM, it is in @file{/usr/share/doc/lilypond-X/}. You have to install +it yourself. + +Add this to your ~/.emacs or ~/.emacs.el: +@example + (load-library "lilypond-mode.el") + (setq auto-mode-alist + (cons '("\\.ly$" . LilyPond-mode) auto-mode-alist)) + (add-hook 'LilyPond-mode-hook (lambda () (turn-on-font-lock))) +@end example + +If you have the latest LilyPond-1.3.x Debian package, LilyPond-mode +is automatically loaded, so you need not modify your ~/.emacs file. + + @section Configuring for multiple platforms If you want to build multiple versions of LilyPond with different @@ -330,6 +351,13 @@ in addition to the those needed for running: @item tetex-devel @end itemize +@section SuSE + +[TODO: document this] + +Install @code{tetex}, @code{te_mpost}, @code{te_kpath}. + + @section Debian GNU/Linux A Debian package is also available. You may install it easily by using diff --git a/Documentation/user/lilypond.tely b/Documentation/user/lilypond.tely index 25830f909d..d0034f88a7 100644 --- a/Documentation/user/lilypond.tely +++ b/Documentation/user/lilypond.tely @@ -15,7 +15,7 @@ @titlepage @title GNU LilyPond @subtitle The music typesetter -@author Han-Wen Nienhuys, Jan Nieuwenhuizen, Adrian Mariano, Tom Cato Amundsen +@author Copyright @copyright{} 1999--2001 by the authors @@ -33,7 +33,8 @@ Copyright @copyright{} 1999--2001 by the authors @ifinfo This file documents GNU LilyPond. -Copyright 1999 Han-Wen Nienhuys, Jan Nieuwenhuizen and Adrian Mariano +Copyright 1999 Han-Wen Nienhuys, Jan Nieuwenhuizen, Adrian Mariano +Tom Cato Amundsen. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 diff --git a/Documentation/user/refman.itely b/Documentation/user/refman.itely index 3ec6395039..ee400db07a 100644 --- a/Documentation/user/refman.itely +++ b/Documentation/user/refman.itely @@ -41,7 +41,6 @@ revision of this document was for LilyPond 1.3.141. * Page layout:: * Sound:: * Music entry:: -* Using LilyPond:: * Interpretation context:: * Syntactic details:: * Lexical details:: @@ -1367,11 +1366,9 @@ want to get several marks during one note, you must use spacer notes. @lilypond[fragment,verbatim,center] c'' \< \! c'' d'' \decr e'' \rced - < f''1 { s4 \< \! s2 \> \! s4 } > + < f''1 { s4 s4 \< \! s4 \> \! s4 } > @end lilypond -[BUG in \> ! ] - You can also use a text saying @emph{cresc.} instead of hairpins. Here is an example how to do it: @@ -1384,7 +1381,11 @@ is an example how to do it: @end lilypond +@refbugs +When using spacer notes to subdivide note dynamics and @code{linewidth = +-1}, starting a hairpin on the first spacer note (the one coinciding +with the real note) exposes an embarassing bug. @@ -1583,10 +1584,15 @@ In the @code{percent} style, a note pattern can be repeated. It is printed once, and then the pattern is replaced with a special sign. @lilypond[verbatim,singleline] - \context Voice { \repeat "percent" 5 { c'1 } } + \context Voice { \repeat "percent" 4 { c'4 } + \repeat "percent" 2 { c'2 es'2 f'4 fis'4 g'4 c''4 } +} @end lilypond -At present, only repeats of whole measures are supported. +@refbugs + +You can not nest percent repeats, filling in the first measure with +slashes, and repeating that measure with percents. @node Rhythmic music @section Rhythmic music @@ -2169,7 +2175,7 @@ scheme = \notes { \score { < - \context ChordNamesVoice \scheme + \context ChordNames \scheme \context Staff \scheme > } @@ -2611,6 +2617,29 @@ Formally the syntax for these constructions is Here @var{symbol} is a Scheme expression of symbol type, @var{context} and @var{grobname} are strings and @var{value} is a Scheme expression. +If you want to be +Correct nesting of @code{\override}, @code{\set}, @code{\revert} is as +follows + +@example +\override \set \set \set \set +\revert +@end example + +This is always correct, but if you know the default value, you can also use +@example +\set \set \set \set +\set @var{to default value} +@end example + +If there is no default (i.e. by default, the grob property is unset), +then you can use +@example +\set \set \set \set \set +\revert +@end example + + @refbugs LilyPond will hang or crash if @var{value} contains cyclic references. @@ -3338,107 +3367,6 @@ will complain about not finding @code{src:X:Y} files. Those complaints are harmless, and can be ignored. -@c . {Using LilyPond} -@node Using LilyPond -@section Using LilyPond -@cindex Using LilyPond -@cindex Generating output - -@c slaat dit ergens op? - -@c direct postscript? - -@table @code -@item plain lilypond -@example -lilypond foo.ly -@end example -For more information on how to use lilypond see -@ifnottex -@ref{Invoking LilyPond}. -@end ifnottex -@iftex -the online manual. -@end iftex - -@item ly2dvi -Ly2dvi produces titling from @code{\header} fields. -@example -ly2dvi foo.ly -@end example -For more information on how to use ly2dvi see -@ifnottex -@ref{ly2dvi}. -@end ifnottex -@iftex -the online manual. -@end iftex - -@item lilypond-book -Lilypond-book supports interleaving text and music. -@example -lilypond-book foo.doc -@end example -For more information on how to use lilypond-book see -@ifnottex -@ref{lilypond-book}. -@end ifnottex -@iftex -the online manual. -@end iftex -@end table - - -An emacs mode for LilyPond is included with the source archive as -@file{lilypond-mode.el} and @file{lilypond-font-lock.el}. If you have -an RPM, it is in @file{/usr/share/doc/lilypond-X/}. You have to install -it yourself. - -Add this to your ~/.emacs or ~/.emacs.el: -@example - (load-library "lilypond-mode.el") - (setq auto-mode-alist - (cons '("\\.ly$" . LilyPond-mode) auto-mode-alist)) - (add-hook 'LilyPond-mode-hook (lambda () (turn-on-font-lock))) -@end example - -If you have the latest LilyPond-1.3.x Debian package, LilyPond-mode -is automatically loaded, so you need not modify your ~/.emacs file. - -@menu -* Pre-cooked makefile:: -@end menu - -@node Pre-cooked makefile -@subsection Pre-cooked makefile - -@c waar deze info? is uiteindelijk wel handig, schat ik. -[TODO: cut blabla] -If you have a big music project, or just a lot of LilyPond input files, -all generated output from LilyPond, @TeX{} and metafont will clutter -your working directory. LilyPond comes with a one-size-fits-all -pre-cooked makefile that helps you manage producing ouptut. It will -produce all output in @file{out}, generate and track dependencies. -Also, it helps in preparing your submission to the @ref{Mutopia -project}. - -@file{make/ly.make} -@example -mkdir my-project -cd my-project -cp /usr/share/lilypond/make/ly.make GNUmakefile -cp /usr/share/doc/lilypond/examples/input/tutorial/menuet.ly . -make menuet -[..] -Generated out/menuet.ps for target menuet. -@end example - -Type @samp{make help} to see possible targets. - -[TODO] -@file{/usr/share/lilypond/doc/lilypond/examples/input/mutopia-header.ly} - - @node Interpretation context @section Interpretation context diff --git a/Documentation/user/tutorial.itely b/Documentation/user/tutorial.itely index 04265373c0..415d95ac8c 100644 --- a/Documentation/user/tutorial.itely +++ b/Documentation/user/tutorial.itely @@ -1827,3 +1827,40 @@ files in @file{input} and @file{input/test}. You can also look at Real Music (TM), have a look at the @ref{Mutopia project}. + +[TODO figure out what to do with this: ] + +@menu +* Pre-cooked makefile:: +@end menu + +@node Pre-cooked makefile +@subsection Pre-cooked makefile + +@c waar deze info? is uiteindelijk wel handig, schat ik. +[TODO: cut blabla] + +If you have a big music project, or just a lot of LilyPond input files, +all generated output from LilyPond, @TeX{} and metafont will clutter +your working directory. LilyPond comes with a one-size-fits-all +pre-cooked makefile that helps you manage producing ouptut. It will +produce all output in @file{out}, generate and track dependencies. +Also, it helps in preparing your submission to the @ref{Mutopia +project}. + +@file{make/ly.make} +@example +mkdir my-project +cd my-project +cp /usr/share/lilypond/make/ly.make GNUmakefile +cp /usr/share/doc/lilypond/examples/input/tutorial/menuet.ly . +make menuet +[..] +Generated out/menuet.ps for target menuet. +@end example + +Type @samp{make help} to see possible targets. + +[TODO] +@file{/usr/share/lilypond/doc/lilypond/examples/input/mutopia-header.ly} + diff --git a/VERSION b/VERSION index 1eeef491e1..959790eb7e 100644 --- a/VERSION +++ b/VERSION @@ -2,7 +2,7 @@ PACKAGE_NAME=LilyPond MAJOR_VERSION=1 MINOR_VERSION=3 PATCH_LEVEL=141 -MY_PATCH_LEVEL=jcn2 +MY_PATCH_LEVEL=jcn3 # use the above to send patches: MY_PATCH_LEVEL is always empty for a # released version. diff --git a/input/bugs/crescendo-squash.ly b/input/bugs/crescendo-squash.ly new file mode 100644 index 0000000000..b143968366 --- /dev/null +++ b/input/bugs/crescendo-squash.ly @@ -0,0 +1,9 @@ + + + % < becomes | +\score {\notes { \context Staff < f''1 + { s4 \< \! s4 } > } + + \paper { linewidth = -1.; } + } + diff --git a/input/regression/dynamics-broken-hairpin.ly b/input/regression/dynamics-broken-hairpin.ly new file mode 100644 index 0000000000..2aef2493fe --- /dev/null +++ b/input/regression/dynamics-broken-hairpin.ly @@ -0,0 +1,12 @@ +\header{ +texidoc = "Broken crescendi should look be open on one side."; +} + +\score { \notes \relative c'' { + c1 \< \break \! c1 \> \break \! c1 + } + \paper { + linewidth = 10.\cm; + } +} + diff --git a/input/regression/dynamics-line.ly b/input/regression/dynamics-line.ly index 95f6b6068c..9ab480cb62 100644 --- a/input/regression/dynamics-line.ly +++ b/input/regression/dynamics-line.ly @@ -1,7 +1,8 @@ \header{ texidoc=" Dynamics appear below or above the staff. If multiple dynamics are linked with (de)crescendi, they should be on the same -line. Isolated dynamics may be forced up or down. "; +line. Isolated dynamics may be forced up or down. + "; } diff --git a/input/regression/percent-repeat.ly b/input/regression/percent-repeat.ly new file mode 100644 index 0000000000..2080187b99 --- /dev/null +++ b/input/regression/percent-repeat.ly @@ -0,0 +1,18 @@ +\header { +texidoc = "Measure and beat repeats are supported."; +} + +\score { \notes \relative c' \context Voice { \time 4/4; + \repeat "percent" 2 { c2 } + + % the chairman dances + \repeat "percent" 2 { g'8 g c, c } + \repeat "percent" 4 { b8 b8 } + \repeat "percent" 2 { c8 d es f g4 r4 } + + % riff + \repeat "percent" 2 { r8. a16 g8. a16 bes8. a16 f8 d | a c8 ~ c8 d8 ~ d8 r8 r4 } + + + + }} diff --git a/input/star-spangled-banner.ly b/input/star-spangled-banner.ly index c72646beff..4f79f9dafb 100644 --- a/input/star-spangled-banner.ly +++ b/input/star-spangled-banner.ly @@ -1,7 +1,7 @@ %{ -Converted from star.mup with the aid of mup2ly.py -http://www.Arkkra.com/doc/star.html -http://www.Arkkra.com/doc/star.ps +Converted from star.mup with the aid of the old mup2ly.py +http://www.arkkra.com/doc/star.html +http://www.arkkra.com/doc/star.ps %} diff --git a/input/test/test-german-chords.ly b/input/test/test-german-chords.ly new file mode 100644 index 0000000000..0df2a1a39d --- /dev/null +++ b/input/test/test-german-chords.ly @@ -0,0 +1,14 @@ +\include "german-chords.ly" +% #(set! german-Bb #t) + +ch = \chords { beses1/+beses bes/+bes b/+b bis/+bis ases/+ases as/+as a/+a ais/+ais fisis/+fisis} + + +\score { + < + \context ChordNames=ch {\ch} + \context Staff=st \chords {\ch} + > + \paper {} +} + diff --git a/input/tricks/follow-thread.ly b/input/tricks/follow-thread.ly index 30dfa9d1fc..c09efe2075 100644 --- a/input/tricks/follow-thread.ly +++ b/input/tricks/follow-thread.ly @@ -2,14 +2,14 @@ \header{ texidoc=" Theads can be traced automagically when they switch staffs by setting -property @code{followThread}. +property @code{followVoice}. "; } % followThread: connect note heads with line when thread switches staff fragment = \notes { \context PianoStaff < - \property PianoStaff.followThread = ##t + \property PianoStaff.followVoice = ##t \context Staff \context Voice { c'1 \translator Staff=two diff --git a/lily/hairpin.cc b/lily/hairpin.cc index 23de3362d4..4fc4bce8d3 100644 --- a/lily/hairpin.cc +++ b/lily/hairpin.cc @@ -76,16 +76,33 @@ Hairpin::brew_molecule (SCM smob) bool continued = broken[Direction (-grow_dir)]; Real height = gh_scm2double (me->get_grob_property ("height")); Real thick = line * gh_scm2double (me->get_grob_property ("thickness")); + + Real starth, endh; + if (grow_dir < 0) + { + starth = height; + endh = continued ? height/2 : 0.0; + } + else + { + starth = continued ? height/2 : 0.0; + endh = height; + } - const char* type = (grow_dir < 0) ? "decrescendo" : "crescendo"; - SCM hairpin = gh_list (ly_symbol2scm (type), - gh_double2scm (thick), - gh_double2scm (width), - gh_double2scm (height), - gh_double2scm (continued ? height/2 : 0.0), - SCM_UNDEFINED); - - Box b (Interval (0, width), Interval (-2*height, 2*height)); + /* + TODO: junk this and, make a general + + Lookup::line (XY1, XY2). + */ + SCM hairpin = gh_list (ly_symbol2scm ("hairpin"), + gh_double2scm (thick), + gh_double2scm (width), + gh_double2scm (starth), + gh_double2scm (endh), + SCM_UNDEFINED); + + Interval yext = 2* height * Interval (-1,1); + Box b (Interval (0, width), yext); Molecule mol (b, hairpin); mol.translate_axis (broken_left + extra_off[LEFT], X_AXIS); diff --git a/lily/include/lookup.hh b/lily/include/lookup.hh index 4a3dea7e0f..8f954757df 100644 --- a/lily/include/lookup.hh +++ b/lily/include/lookup.hh @@ -24,7 +24,8 @@ struct Lookup static Molecule beam (Real, Real, Real) ; static Molecule dashed_slur (Bezier, Real thick, Real dash) ; static Molecule blank (Box b) ; - static Molecule filledbox (Box b) ; + static Molecule filledbox (Box b) ; + static Molecule repeat_slash( Real w, Real slope, Real th); }; #endif // LOOKUP_HH diff --git a/lily/include/percent-repeat-item.hh b/lily/include/percent-repeat-item.hh new file mode 100644 index 0000000000..057144c5d7 --- /dev/null +++ b/lily/include/percent-repeat-item.hh @@ -0,0 +1,25 @@ +/* + percent-repeat-item.hh -- declare Percent_repeat_item_interface + + source file of the GNU LilyPond music typesetter + + (c) 2001 Han-Wen Nienhuys + + */ + +#ifndef PERCENT_REPEAT_ITEM_HH +#define PERCENT_REPEAT_ITEM_HH + +#include "grob.hh" + +class Percent_repeat_item_interface +{ +public: + DECLARE_SCHEME_CALLBACK (beat_slash, (SCM )); + DECLARE_SCHEME_CALLBACK (double_percent, (SCM )); + static Molecule x_percent (Grob*,int,Real,Real ); + static Molecule brew_slash (Grob*); +}; + +#endif /* PERCENT_REPEAT_ITEM_HH */ + diff --git a/lily/lookup.cc b/lily/lookup.cc index f2e89466b6..b01db45413 100644 --- a/lily/lookup.cc +++ b/lily/lookup.cc @@ -355,3 +355,21 @@ Lookup::accordion (SCM s, Real staff_space, Font_metric *fm) return m; } +/* + TODO: should use slope instead? Angle gives nasty rad <-> degree + conversions. +*/ +Molecule +Lookup::repeat_slash (Real w, Real s, Real t) +{ + SCM wid = gh_double2scm (w); + SCM sl = gh_double2scm (s); + SCM thick = gh_double2scm (t); + SCM slashnodot = gh_list (ly_symbol2scm ("repeat-slash"), + wid, sl, thick, SCM_UNDEFINED); + + Box b (Interval (0, w + sqrt (sqr(t/s) + sqr (t))), + Interval (0, w * s)); + + return Molecule (b, slashnodot); +} diff --git a/lily/multi-measure-rest.cc b/lily/multi-measure-rest.cc index f216aeac8a..890c0d1562 100644 --- a/lily/multi-measure-rest.cc +++ b/lily/multi-measure-rest.cc @@ -19,6 +19,8 @@ #include "spanner.hh" #include "staff-symbol-referencer.hh" #include "text-item.hh" +#include "percent-repeat-item.hh" + void Multi_measure_rest::set_interface (Grob*me) @@ -36,12 +38,13 @@ MAKE_SCHEME_CALLBACK (Multi_measure_rest,percent,1); SCM Multi_measure_rest::percent (SCM smob) { + Grob *me = unsmob_grob (smob); Spanner *sp = dynamic_cast (me); Font_metric *musfont = Font_interface::get_default_font (me); - Molecule r (musfont->find_by_name ("scripts-repeatsign")); + Molecule r = Percent_repeat_item_interface::x_percent (me, 1, 0.75, 1.6); // ugh copy & paste. diff --git a/lily/percent-repeat-engraver.cc b/lily/percent-repeat-engraver.cc index b063ad4660..994288da64 100644 --- a/lily/percent-repeat-engraver.cc +++ b/lily/percent-repeat-engraver.cc @@ -16,6 +16,10 @@ #include "spanner.hh" #include "item.hh" #include "percent-repeat-iterator.hh" +#include "bar.hh" + +#include "score-engraver.hh" +#include "translator-group.hh" /** This acknowledges repeated music with "percent" style. It typesets @@ -52,7 +56,9 @@ protected: MEASURE, DOUBLE_MEASURE, } repeat_sign_type_ ; - + + Item * beat_slash_; + Item * double_percent_; Spanner * perc_p_; Spanner * finished_perc_p_; Item * stem_tremolo_; @@ -70,6 +76,9 @@ Percent_repeat_engraver::Percent_repeat_engraver () perc_p_ = finished_perc_p_ = 0; repeat_ =0; stem_tremolo_ = 0; + + beat_slash_ = 0; + double_percent_ = 0; } bool @@ -89,25 +98,25 @@ Percent_repeat_engraver::try_music (Music * m) stop_mom_ = start_mom_ + Moment (count) * body_length_; next_moment_ = start_mom_ + body_length_; - SCM m = get_property ("timeSignatureFraction"); - Moment mlen (1, - gh_scm2int (gh_cdr (m))); + SCM m = get_property ("measureLength"); + Moment meas_len; + if (unsmob_moment (m)) + meas_len = *unsmob_moment (m); - if (mlen == body_length_) + if (body_length_ < meas_len && + meas_len.mod_rat (body_length_) == Moment (0,0)) repeat_sign_type_ = BEAT; + else if (meas_len == body_length_) + repeat_sign_type_ = MEASURE; + else if (Moment (2)* meas_len == body_length_) + { + repeat_sign_type_ = DOUBLE_MEASURE; + next_moment_ += meas_len ; + } else { - mlen *= gh_scm2int (gh_car (m)); - if (mlen == body_length_) - repeat_sign_type_ = MEASURE; - else if (Moment (2)* mlen == body_length_) - repeat_sign_type_ = DOUBLE_MEASURE; - - if (repeat_sign_type_ != MEASURE) - { - warning (_ ("Don't know yet how to handle this percent repeat.")); - return false; - } + warning (_ ("Don't know how to handle a percent repeat of this length.")); + return false; } repeat_ = rp; @@ -138,7 +147,8 @@ Percent_repeat_engraver::process_music () { if (repeat_sign_type_ == BEAT) { - ; + beat_slash_ = new Item (get_property ("RepeatSlash")); + announce_grob (beat_slash_, repeat_); } else if (repeat_sign_type_ == MEASURE) { @@ -149,10 +159,31 @@ Percent_repeat_engraver::process_music () perc_p_->set_bound (LEFT, unsmob_grob (col)); announce_grob (perc_p_, repeat_); } + else if (repeat_sign_type_ == DOUBLE_MEASURE) + + { + double_percent_ = new Item (get_property ("DoublePercentRepeat")); + announce_grob (double_percent_, repeat_); + + /* + forbid breaks on a % line. Should forbid all breaks, really. + */ + Score_engraver * e = 0; + Translator * t = daddy_grav_l (); + for (; !e && t; t = t->daddy_trans_l_) + { + e = dynamic_cast (t); + } + if (!e) + programming_error ("No score engraver!"); + else + e->forbid_breaks (); // guh. Use properties! + } next_moment_ = next_moment_ + body_length_; } } + void Percent_repeat_engraver::finalize () { @@ -174,22 +205,38 @@ Percent_repeat_engraver::typeset_perc () typeset_grob (finished_perc_p_); finished_perc_p_ = 0; } + + if (beat_slash_) + { + typeset_grob (beat_slash_); + beat_slash_ = 0; + } + + if (double_percent_) + { + typeset_grob (double_percent_); + double_percent_ = 0; + } } void Percent_repeat_engraver::acknowledge_grob (Grob_info info) { + } void Percent_repeat_engraver::start_translation_timestep () { - if (perc_p_ && stop_mom_ == now_mom ()) + if (stop_mom_ == now_mom ()) { - finished_perc_p_ = perc_p_; - typeset_perc (); + if (perc_p_) + { + finished_perc_p_ = perc_p_; + typeset_perc (); + } repeat_ = 0; perc_p_ = 0; repeat_sign_type_ = UNKNOWN; diff --git a/lily/percent-repeat-item.cc b/lily/percent-repeat-item.cc new file mode 100644 index 0000000000..373404428d --- /dev/null +++ b/lily/percent-repeat-item.cc @@ -0,0 +1,85 @@ +/* + percent-repeat-item.cc -- implement Percent_repeat_item_interface + + source file of the GNU LilyPond music typesetter + + (c) 2001 Han-Wen Nienhuys + + */ +#include + +#include "grob.hh" +#include "lookup.hh" +#include "molecule.hh" +#include "font-interface.hh" +#include "font-metric.hh" +#include "percent-repeat-item.hh" + + +Molecule +Percent_repeat_item_interface::brew_slash ( Grob *me) +{ + Real slope = gh_scm2double (me->get_grob_property ("slope")); + Real wid = 2.0 / slope; + + /* + todo: check out if in staff-rule thickness normally. + */ + Real thick = gh_scm2double (me->get_grob_property ("thickness")); + Molecule m = Lookup::repeat_slash (wid, slope, thick); + m.translate_axis (-m.extent (Y_AXIS).center (), Y_AXIS); + return m; +} + +/* + todo: use grob props for dot_neg_kern, slash_neg_kern? + */ +Molecule +Percent_repeat_item_interface::x_percent (Grob *me, int count, + Real dot_neg_kern, + Real slash_neg_kern) +{ + Molecule m ; + Molecule s = brew_slash (me); + + for (int i = count; i--;) + { + m.add_at_edge (X_AXIS, RIGHT, s, -slash_neg_kern); + } + Molecule d1 = Font_interface::get_default_font (me)->find_by_name ("dots-dot"); + Molecule d2 = d1; + d1.translate_axis (0.5, Y_AXIS ); + d2.translate_axis (-0.5, Y_AXIS); + + m.add_at_edge (X_AXIS, LEFT, d1, -dot_neg_kern); + m.add_at_edge (X_AXIS, RIGHT, d2, -dot_neg_kern); + + return m; +} + +MAKE_SCHEME_CALLBACK(Percent_repeat_item_interface,double_percent,1); +SCM +Percent_repeat_item_interface::double_percent (SCM grob) +{ + Grob *me = unsmob_grob (grob); + Molecule m = x_percent (me, 2, 0.75, 1.6); + m.translate_axis (- m.extent (X_AXIS).center (), X_AXIS); + return m.smobbed_copy (); +} + +MAKE_SCHEME_CALLBACK(Percent_repeat_item_interface,beat_slash,1); +SCM +Percent_repeat_item_interface::beat_slash (SCM grob) +{ + Grob *me = unsmob_grob (grob); + Molecule m = brew_slash (me); + + return m.smobbed_copy (); +} + + + + + + + diff --git a/lily/system-start-delimiter-engraver.cc b/lily/system-start-delimiter-engraver.cc index 1f4504a733..27ee99dc86 100644 --- a/lily/system-start-delimiter-engraver.cc +++ b/lily/system-start-delimiter-engraver.cc @@ -53,6 +53,14 @@ System_start_delimiter_engraver::acknowledge_grob (Grob_info inf) if (gh_symbol_p (gl) && gl == ly_symbol2scm ("brace") && gh_symbol_p (my_gl) && my_gl == ly_symbol2scm ("bracket")) inf.elem_l_->translate_axis (-1.0, X_AXIS); // ugh + else if (gh_symbol_p (gl) && gl == ly_symbol2scm ("bracket") + && gh_symbol_p (my_gl) && my_gl == ly_symbol2scm ("bracket")) + { + inf.elem_l_->translate_axis ( -0.8, X_AXIS); // ugh + inf.elem_l_->set_grob_property ("arch-height", + gh_double2scm(gh_scm2double(inf.elem_l_->get_grob_property + ("arch-height"))+0.5)); + } } } diff --git a/lily/system-start-delimiter.cc b/lily/system-start-delimiter.cc index 39bd68040e..5d4cb3d67a 100644 --- a/lily/system-start-delimiter.cc +++ b/lily/system-start-delimiter.cc @@ -32,6 +32,25 @@ System_start_delimiter::staff_bracket (Grob*me,Real height) me->get_grob_property ("bracket-thick"), SCM_UNDEFINED); + /* +TODO: sort this out. + +Another thing: +In system-start-delimiter.cc I see the line + + Real h = height + 2 * arc_height; + +But I really think that you mean + + Real h = height + 2 * arc_width; + +(arc_height changes the x-axis-size of arc ; arc_width changes the +y-axis-size) +Will not fix it since I'm not sure. + +-Rune + + */ Real h = height + 2 * arc_height; Box b (Interval (0, 1.5), Interval (-h/2, h/2)); Molecule mol (b, at); diff --git a/lily/tuplet-engraver.cc b/lily/tuplet-engraver.cc index 7568a08679..0e7d238247 100644 --- a/lily/tuplet-engraver.cc +++ b/lily/tuplet-engraver.cc @@ -110,6 +110,16 @@ Tuplet_engraver::acknowledge_grob (Grob_info i) } else if (Beam::has_interface (i.elem_l_)) { + /* + TODO: + + ugh, superfluous. Should look at + + tuplet -> note-column -> stem -> beam + + to find the beam(s) of a tuplet + */ + for (int j = 0; j < started_span_p_arr_.size (); j++) if (started_span_p_arr_[j]) Tuplet_bracket::add_beam (started_span_p_arr_[j],i.elem_l_); diff --git a/ly/german-chords.ly b/ly/german-chords.ly new file mode 100644 index 0000000000..e158592b34 --- /dev/null +++ b/ly/german-chords.ly @@ -0,0 +1,39 @@ + +% german-chords.ly: +% german/norwegian/danish? + +% To get Bb instead of B, use +% \include "german-chords.ly" +% #(set! german-Bb #t) + +#(define german-Bb #f) + +#(define (pitch->chord-name-text-banter pitch) + (if (equal? (cdr pitch) '(6 -1)) + (if german-Bb + (cons "B" (accidental->text -1)) + '("B") + ) + (cons + (list-ref '("C" "D" "E" "F" "G" "A" "H") (cadr pitch)) + (accidental->text (caddr pitch)) + ) + ) + ) + + +#(define (pitch->note-name-text-banter pitch) + (if (equal? (cdr pitch) '(6 -1)) + '("b") + (cons + (string-append + (list-ref '("c" "d" "e" "f" "g" "a" "h") (cadr pitch)) + (if (or (equal? (cadr pitch) 2) (equal? (cadr pitch) 5)) + (list-ref '( "ses" "s" "" "is" "isis") (+ 2 (caddr pitch))) + (list-ref '("eses" "es" "" "is" "isis") (+ 2 (caddr pitch))) + ) + ) + '() + ) + ) + ) diff --git a/mf/feta-schrift.mf b/mf/feta-schrift.mf index f4fc744a27..8ddcc5d1d6 100644 --- a/mf/feta-schrift.mf +++ b/mf/feta-schrift.mf @@ -585,25 +585,6 @@ fet_beginchar("Flageolet", "flageolet", "flageolet") draw z1..z2..z3..z4..cycle; fet_endchar; -fet_beginchar("Repeatsign", "repeatsign", "repeatsign") - set_char_box(staff_space#, staff_space#, staff_space#, staff_space#); - - save dot_diam; - 2 dot_diam# = staff_space# - stafflinethickness#; - define_pixels(dot_diam); - - penpos1(dot_diam,0); - z1l=(-b,-d); - penpos2(dot_diam,0); - z2r=(w,h); - filldraw z1l--z2l{right}--z2r{down}--z1r{right}--cycle; - penlabels (1,2); - - pickup pencircle scaled dot_diam; - draw (-staff_space/2, staff_space/2); - draw (staff_space/2, -staff_space/2); -fet_endchar; - fet_beginchar("Segno", "segno", "segno") save thin, thick, ball_diam, darkness, pointheight; save wd, ht, thick_nibangle, ball_nib_thick; diff --git a/ps/lily.ps b/ps/lily.ps index de0f845dd0..b5406ca0ac 100644 --- a/ps/lily.ps +++ b/ps/lily.ps @@ -5,6 +5,11 @@ % round cappings 1 setlinecap +/euclidean_length +{ + 1 copy mul exch 1 copy mul add sqrt +} bind def + /draw_beam % width slope thick { 2 div /beam_thick exch def @@ -18,40 +23,34 @@ closepath fill } bind def -/draw_decrescendo % width height cons thick -{ - setlinewidth - /cresc_cont exch def - /cresc_ht exch def - /cresc_wd exch def - - cresc_wd cresc_cont moveto - 0 cresc_ht lineto - stroke - cresc_wd cresc_cont neg moveto - 0 cresc_ht neg lineto - stroke -} bind def - -/draw_crescendo % width height cons thick -{ - setlinewidth - /cresc_cont exch def - /cresc_ht exch def - /cresc_wd exch def - - 0 cresc_cont moveto - cresc_wd cresc_ht lineto - stroke - 0 cresc_cont neg moveto - cresc_wd cresc_ht neg lineto - stroke -} bind def +/draw_repeat_slash % width slope thick +{ + /beamthick exch def + /slope exch def + /width exch def + beamthick beamthick slope div euclidean_length + /xwid exch def + 0 0 moveto + xwid 0 rlineto + width slope width mul rlineto + xwid neg 0 rlineto +% width neg width angle sin mul neg rlineto + closepath fill +} bind def -/lily_distance -{ - 1 copy mul exch 1 copy mul add sqrt -} bind def +/draw_hairpin % width start_h end_h thick +{ + setlinewidth + /end_h exch def + /start_h exch def + /wid exch def + 0 start_h moveto + wid end_h lineto + stroke + 0 start_h neg moveto + wid end_h neg lineto + stroke +} bind def /draw_tuplet % height gap dx dy thick dir { @@ -101,6 +100,7 @@ } bind def % simple, but does it work everywhere? +% explain ? --hwn /draw_ez_ball % ch letter_col ball_col font { % font diff --git a/scm/chord-name.scm b/scm/chord-name.scm index bcdf7aaa1f..5bbb2017e4 100644 --- a/scm/chord-name.scm +++ b/scm/chord-name.scm @@ -253,11 +253,9 @@ (define (pitch->note-name pitch) (cons (cadr pitch) (caddr pitch))) - -(define (pitch->text pitch) - (cons - (make-string 1 (integer->char (+ (modulo (+ (cadr pitch) 2) 7) 65))) - (if (= (caddr pitch) 0) + +(define (accidental->text acc) + (if (= acc 0) '() (list (append '(music) @@ -268,7 +266,15 @@ (list (append '((raise . 0.6)) (list (string-append "accidentals-" - (number->string (caddr pitch))))))))))))))) + (number->string acc)))))))))))) +) + +(define (pitch->text pitch) + (cons + (make-string 1 (integer->char (+ (modulo (+ (cadr pitch) 2) 7) 65))) + (accidental->text (caddr pitch)) + ) +) ;;; Hooks to override chord names and note names, ;;; see input/tricks/german-chords.ly diff --git a/scm/grob-description.scm b/scm/grob-description.scm index d12715908c..a1fdc784cf 100644 --- a/scm/grob-description.scm +++ b/scm/grob-description.scm @@ -9,7 +9,18 @@ ; staffspace (distances) (define all-grob-descriptions - `((Arpeggio . ( + `( + (Accidentals . ( + (molecule-callback . ,Local_key_item::brew_molecule) + (X-offset-callbacks . (,Side_position_interface::aligned_side)) + (after-line-breaking-callback . ,Local_key_item::after_line_breaking) + (direction . -1) + (left-padding . 0.2) + (right-padding . 0.4) + (meta . ,(grob-description "Accidentals" accidentals-interface font-interface side-position-interface)) + )) + + (Arpeggio . ( (X-extent-callback . ,Arpeggio::width_callback) (Y-extent-callback . #f) (molecule-callback . ,Arpeggio::brew_molecule) @@ -139,21 +150,6 @@ (meta . ,(grob-description "Custos" custos-interface staff-symbol-referencer-interface break-aligned-interface) ) )) - (Hairpin . ( - (molecule-callback . ,Hairpin::brew_molecule) - (thickness . 1.0) - (height . 0.6666) - (spacing-procedure . ,Spanner::set_spacing_rods) - (minimum-length . 2.0) - (if-text-padding . 1.0) - (width-correct . -1.0) - - (dash-thickness . 1.2) - (dash-length . 4.0) - (self-alignment-Y . 0) - (Y-offset-callbacks . (,Side_position_interface::aligned_on_self)) - (meta . ,(grob-description "Hairpin" hairpin-interface dynamic-interface)) - )) (DotColumn . ( (axes 0 ) @@ -167,6 +163,17 @@ (Y-offset-callbacks . (,Dots::quantised_position_callback ,Staff_symbol_referencer::callback)) (meta . ,(grob-description "Dots" font-interface dots-interface )) )) + (DoublePercentRepeat + . ((molecule-callback . ,Percent_repeat_item_interface::double_percent) + (breakable . #t) + (slope . 1.0) + (font-family . music) + (width . 2.0) + (thickness . 0.48) + (break-align-symbol . Staff_bar) + (visibility-lambda . ,begin-of-line-invisible) + (meta . ,(grob-description "DoublePercentRepeat" font-interface percent-repeat-interface)) + )) (DynamicText . ( (Y-offset-callbacks . (,Side_position_interface::aligned_on_self)) @@ -220,14 +227,20 @@ (axes 1) (meta . ,(grob-description "HaraKiriVerticalGroup" axis-group-interface hara-kiri-group-interface)) )) - - (LyricHyphen . ( + (Hairpin . ( + (molecule-callback . ,Hairpin::brew_molecule) (thickness . 1.0) - (height . 0.4) - (minimum-length . 0.5) - (molecule-callback . ,Hyphen_spanner::brew_molecule) - (Y-extent-callback . ,Grob::point_dimension_callback) - (meta . ,(grob-description "LyricHyphen" lyric-hyphen-interface )) + (height . 0.6666) + (spacing-procedure . ,Spanner::set_spacing_rods) + (minimum-length . 2.0) + (if-text-padding . 1.0) + (width-correct . -1.0) + + (dash-thickness . 1.2) + (dash-length . 4.0) + (self-alignment-Y . 0) + (Y-offset-callbacks . (,Side_position_interface::aligned_on_self)) + (meta . ,(grob-description "Hairpin" hairpin-interface dynamic-interface)) )) (InstrumentName . ( @@ -253,14 +266,14 @@ (meta . ,(grob-description "KeySignature" key-signature-interface font-interface break-aligned-interface)) )) - (Accidentals . ( - (molecule-callback . ,Local_key_item::brew_molecule) - (X-offset-callbacks . (,Side_position_interface::aligned_side)) - (after-line-breaking-callback . ,Local_key_item::after_line_breaking) - (direction . -1) - (left-padding . 0.2) - (right-padding . 0.4) - (meta . ,(grob-description "Accidentals" accidentals-interface font-interface side-position-interface)) + + (LyricHyphen . ( + (thickness . 1.0) + (height . 0.4) + (minimum-length . 0.5) + (molecule-callback . ,Hyphen_spanner::brew_molecule) + (Y-extent-callback . ,Grob::point_dimension_callback) + (meta . ,(grob-description "LyricHyphen" lyric-hyphen-interface )) )) (LineOfScore . ( @@ -415,15 +428,20 @@ (PercentRepeat . ( (spacing-procedure . ,Multi_measure_rest::set_spacing_rods) (molecule-callback . ,Multi_measure_rest::percent) - (staff-position . 0) - (expand-limit . 10) - (padding . 2.0) ; staffspace + (slope . 1.0) + (thickness . 0.48) (minimum-width . 12.5) ; staffspace (font-family . music) - (meta . ,(grob-description "PercentRepeat" multi-measure-rest-interface font-interface)) + (meta . ,(grob-description "PercentRepeat" multi-measure-rest-interface font-interface percent-repeat-interface)) )) + (RepeatSlash . ( + (molecule-callback . , Percent_repeat_item_interface::beat_slash) + (thickness . 0.48) + (slope . 1.7) + (meta . ,(grob-description "RepeatSlash" percent-repeat-interface)) + )) (Rest . ( (after-line-breaking-callback . ,Rest::after_line_breaking) (X-extent-callback . ,Rest::extent_callback) diff --git a/scm/interface-description.scm b/scm/interface-description.scm index 3116029953..61f746d6f0 100644 --- a/scm/interface-description.scm +++ b/scm/interface-description.scm @@ -6,7 +6,7 @@ ;;;; Jan Nieuwenhuizen -; should include default value? + ; should include default value? ;;; FIXME: naming. @@ -27,18 +27,18 @@ (define (grob-description name . interfaces) (let* ((ifs (cons general-grob-interface interfaces)) (props (map caddr ifs)) -; (prop-typep-pairs (map (lambda (x) (cons (car x) (cadr x))) -; (apply append props))) + ; (prop-typep-pairs (map (lambda (x) (cons (car x) (cadr x))) + ; (apply append props))) (syms (map car ifs)) - ) + ) (list (cons 'separator "\n\n\n") ;easy printing. (cons 'name name) (cons 'interfaces syms) (cons 'interface-descriptions ifs) - ; (cons 'interface-descriptions (cadr merged)) + ; (cons 'interface-descriptions (cadr merged)) ;; description of the grob itself? -; (cons 'properties prop-typep-pairs) - ))) + ; (cons 'properties prop-typep-pairs) + ))) (lily-interface @@ -190,7 +190,7 @@ '( left-padding right-padding - )) + )) @@ -758,22 +758,26 @@ direction = Forced direction for all ties" '(direction )) +(lily-interface + 'percent-repeat-interface + "Repeats that look like percent signs" + '(angle thickness)) - (lily-interface - 'volta-bracket-interface - "Volta bracket with number" - '( - bars - thickness - height - )) +(lily-interface + 'volta-bracket-interface + "Volta bracket with number" + '( + bars + thickness + height + )) - (lily-interface - 'span-bar-interface - "A bar line that spans other barlines (typically used to get cross-staff barlines." - '( - )) +(lily-interface + 'span-bar-interface + "A bar line that spans other barlines (typically used to get cross-staff barlines." + '( + )) (eval (cons @@ -784,3 +788,4 @@ direction = Forced direction for all ties" (define (interface-names) (map (lambda (x) (symbol->string (car x))) all-interfaces)) + diff --git a/scm/ps.scm b/scm/ps.scm index d17843731e..0f8011bf6d 100644 --- a/scm/ps.scm +++ b/scm/ps.scm @@ -67,11 +67,12 @@ (define (char i) (invoke-char " show" i)) - (define (crescendo thick w h cont ) - (string-append - (numbers->string (list w h (inexact->exact cont) thick)) - " draw_crescendo")) + (define (hairpin thick width starth endh ) + (string-append + (numbers->string (list width starth endh thick)) + " draw_hairpin")) + ;; what the heck is this interface ? (define (dashed-slur thick dash l) (string-append @@ -95,13 +96,11 @@ " " (ly-number->string off) " ] 0 draw_dashed_line")) - - (define (decrescendo thick w h cont) - (string-append - (numbers->string (list w h (inexact->exact cont) thick)) - " draw_decrescendo")) - - + + (define (repeat-slash wid slope thick) + (string-append (numbers->string (list wid slope thick)) + " draw_repeat_slash")) + (define (end-output) "\nshowpage\n") @@ -208,12 +207,11 @@ lilypondpaperoutputscale lilypondpaperoutputscale scale (define tuplet ,tuplet) (define bracket ,bracket) (define char ,char) - (define crescendo ,crescendo) + (define hairpin ,hairpin) (define volta ,volta) (define bezier-sandwich ,bezier-sandwich) (define dashed-line ,dashed-line) (define dashed-slur ,dashed-slur) - (define decrescendo ,decrescendo) (define end-output ,end-output) (define experimental-on ,experimental-on) (define filledbox ,filledbox) @@ -231,20 +229,21 @@ lilypondpaperoutputscale lilypondpaperoutputscale scale (define stem ,stem) (define stop-line ,stop-line) (define stop-last-line ,stop-line) + (define repeat-slash ,repeat-slash) (define text ,text) (define no-origin ,no-origin) (define define-origin ,define-origin) (define ez-ball ,ez-ball) )) + ((eq? action-name 'repeat-slash) repeat-slash) ((eq? action-name 'tuplet) tuplet) ((eq? action-name 'beam) beam) ((eq? action-name 'bezier-sandwich) bezier-sandwich) ((eq? action-name 'bracket) bracket) ((eq? action-name 'char) char) - ((eq? action-name 'crescendo) crescendo) ((eq? action-name 'dashed-line) dashed-line) ((eq? action-name 'dashed-slur) dashed-slur) - ((eq? action-name 'decrescendo) decrescendo) + ((eq? action-name 'hairpin) hairpin) ((eq? action-name 'experimental-on) experimental-on) ((eq? action-name 'filledbox) filledbox) ((eq? action-name 'ez-ball) ez-ball) diff --git a/scm/tex.scm b/scm/tex.scm index 6f0e0e69f6..5e358449f9 100644 --- a/scm/tex.scm +++ b/scm/tex.scm @@ -47,8 +47,8 @@ (define (dashed-slur thick dash l) (embedded-ps ((ps-scm 'dashed-slur) thick dash l))) - (define (crescendo thick w h cont) - (embedded-ps ((ps-scm 'crescendo) thick w h cont))) + (define (hairpin thick w sh eh) + (embedded-ps ((ps-scm 'hairpin) thick w sh eh))) (define (char i) (string-append "\\char" (inexact->string i 10) " ")) @@ -56,9 +56,6 @@ (define (dashed-line thick on off dx dy) (embedded-ps ((ps-scm 'dashed-line) thick on off dx dy))) - (define (decrescendo thick w h cont) - (embedded-ps ((ps-scm 'decrescendo) thick w h cont))) - (define (font-load-command name-mag command) (string-append "\\font\\" command "=" @@ -86,6 +83,9 @@ (define (experimental-on) "") + (define (repeat-slash w a t) + (embedded-ps ((ps-scm 'repeat-slash) w a t))) + (define (font-switch i) (string-append "\\" (font i) "\n")) @@ -201,10 +201,9 @@ (define bezier-sandwich ,bezier-sandwich) (define bracket ,bracket) (define char ,char) - (define crescendo ,crescendo) (define dashed-line ,dashed-line) (define dashed-slur ,dashed-slur) - (define decrescendo ,decrescendo) + (define hairpin ,hairpin) (define end-output ,end-output) (define experimental-on ,experimental-on) (define filledbox ,filledbox) @@ -226,15 +225,15 @@ (define volta ,volta) (define define-origin ,define-origin) (define no-origin ,no-origin) + (define repeat-slash ,repeat-slash) )) ((eq? action-name 'beam) beam) ((eq? action-name 'tuplet) tuplet) ((eq? action-name 'bracket) bracket) - ((eq? action-name 'crescendo) crescendo) + ((eq? action-name 'hairpin) hairpin) ((eq? action-name 'dashed-line) dashed-line) ((eq? action-name 'dashed-slur) dashed-slur) - ((eq? action-name 'decrescendo) decrescendo) ((eq? action-name 'end-output) end-output) ((eq? action-name 'experimental-on) experimental-on) ((eq? action-name 'font-def) font-def) diff --git a/scripts/ly2dvi.py b/scripts/ly2dvi.py index a29429947b..bb9d97188c 100644 --- a/scripts/ly2dvi.py +++ b/scripts/ly2dvi.py @@ -21,6 +21,8 @@ TODO: * dvi from lilypond .tex output? This is hairy, because we create dvi from lilypond .tex *and* header output. + * windows compatibility: rm -rf, cp file... dir + ''' @@ -200,8 +202,9 @@ def setup_temp (): os.mkdir (temp_dir, 0777) except OSError: pass - - + os.chdir (temp_dir) + + def system (cmd, ignore_error = 0): if verbose_p: progress (_ ("Invoking `%s\'") % cmd) @@ -241,6 +244,7 @@ def set_setting (dict, key, val): option_definitions = [ ('', 'h', 'help', _ ("this help")), ('KEY=VAL', 's', 'set', _ ("change global setting KEY to VAL")), + ('DIR', 'I', 'include', _ ("add DIR to LilyPond\'s search path")), ('', 'P', 'postscript', _ ("generate PostScript output")), ('', 'k', 'keep', _ ("keep all output, and name the directory ly2dvi.dir")), ('', '', 'no-lily', _ ("don't run LilyPond")), @@ -364,8 +368,10 @@ def global_latex_definition (tfiles, extra): s = s + '\\usepackage{%s}\n' \ % string.join (extra['latexpackages'], ',') - - s = s + string.join (extra['latexheaders'], ' ') + + if extra['latexheaders']: + s = s + '\\include{%s}\n' \ + % string.join (extra['latexheaders'], '}\n\\include{') textheight = '' if extra['textheight']: @@ -505,11 +511,15 @@ for opt in options: elif o == '--warranty' or o == '-w': warranty () sys.exit (0) - - -include_path = map (os.path.abspath, include_path) -files = map (os.path.abspath, files) -outdir = os.path.abspath (outdir) + +# On most platforms, this is equivalent to +#`normpath(join(os.getcwd()), PATH)'. *Added in Python version 1.5.2* +def compat_abspath (path): + return os.path.normpath (os.path.join (os.getcwd (), path)) + +include_path = map (compat_abspath, include_path) +files = map (compat_abspath, files) +outdir = compat_abspath (outdir) def strip_ly_suffix (f): (p, e) =os.path.splitext (f) diff --git a/scripts/mup2ly.py b/scripts/mup2ly.py index 7011a7b1e4..2808dc1b65 100644 --- a/scripts/mup2ly.py +++ b/scripts/mup2ly.py @@ -7,6 +7,9 @@ ''' TODO: + + WIP:lots of stuff + ''' import os @@ -66,7 +69,9 @@ NO WARRANTY.''')) sys.stdout.write ('\n') def progress (s): - sys.stderr.write (s + '\n') + if s[-1] != '\n': + s = s + '\n' + sys.stderr.write (s) def warning (s): sys.stderr.write (_ ("warning: ") + s) @@ -199,7 +204,7 @@ def set_setting (dict, key, val): # def encodeint (i): - return chr ( i + ord ('A')) + return chr (i + ord ('A')) actab = {-2: 'eses', -1: 'es', 0 : '', 1: 'is', 2:'isis'} @@ -207,7 +212,7 @@ actab = {-2: 'eses', -1: 'es', 0 : '', 1: 'is', 2:'isis'} def pitch_to_lily_string (tup): (o,n,a) = tup - nm = chr((n + 2) % 7 + ord ('a')) + nm = chr((n + 2) % 7 + ord ('a')) nm = nm + actab[a] if o > 0: nm = nm + "'" * o @@ -321,12 +326,14 @@ class Slur: sys.stderr.write ("\nOrphaned slur") class Voice: - def __init__ (self): + def __init__ (self, n): + self.number = n self.entries = [] self.chords = [] self.staff = None self.current_slurs = [] self.slurs = [] + def toggle_slur (self, id): for s in self.current_slurs: @@ -340,36 +347,56 @@ class Voice: self.slurs.append (s) def last_chord (self): - return self.chords[-1] + if len (self.chords): + return self.chords[-1] + else: + ch = Chord () + ch.basic_duration = 4 + return ch + def add_chord (self, ch): self.chords.append (ch) self.entries.append (ch) + def add_nonchord (self, nch): self.entries.append (nch) def idstring (self): return 'staff%svoice%s ' % (encodeint (self.staff.number) , encodeint(self.number)) + def dump (self): str = '' - ln = '' + if not self.entries: + #return '\n' + #ugh ugh + return '\n%s = {}\n\n' % self.idstring () + ln = ' ' + one_two = ("One", "Two") + if self.staff.voices [1 - self.number].entries: + ln = ln + '\\voice%s\n ' % one_two[self.number] for e in self.entries: - next = ' ' + e.dump () + next = e.dump () if next[-1] == '\n': - str = str + ln + next - ln = '' + str = str + ln + next + ' ' + ln = ' ' continue if len (ln) +len (next) > 72: str = str+ ln + '\n' - ln = '' - ln = ln + next + ln = ' ' + ln = ln + next + ' ' str = str + ln id = self.idstring () - str = '%s = \\notes { \n %s }\n '% (id, str) + str = '''%s = \\notes { +%s +} + +'''% (id, str) return str + def calculate_graces (self): lastgr = 0 lastc = None @@ -380,6 +407,7 @@ class Voice: lastc.chord_suffix = lastc.chord_suffix + ' } ' lastgr = c.grace lastc = c + def calculate (self): self.calculate_graces () for s in self.slurs: @@ -400,43 +428,54 @@ clef_table = { 's':'soprano', 't':'treble', 'f':'frenchviolin', - } + } + class Staff: - def __init__ (self): - self.voices = (Voice (), Voice()) + def __init__ (self, n): + # ugh + self.voices = (Voice (0), Voice (1)) + + # self.voice_idx = 0 self.clef = None self.instrument = 0 - self.voice_idx = 0 - self.number = None + self.number = n i = 0 - for v in self.voices: + for v in self.voices: v.staff = self v.number = i i = i+1 + def set_clef (self, letter): clstr = clef_table[letter] self.voices[0].add_nonchord (Clef (clstr)) - def current_voice (self): - return self.voices[self.voice_idx] - def next_voice (self): - self.voice_idx = (self.voice_idx + 1)%len (self.voices) + #def current_voice (self): + # return self.voices[self.voice_idx] + # + #def next_voice (self): + # self.voice_idx = (self.voice_idx + 1)%len (self.voices) def calculate (self): for v in self.voices: v.calculate () + def idstring (self): return 'staff%s' % encodeint (self.number) + def dump (self): str = '' refs = '' for v in self.voices: str = str + v.dump() - refs = refs + '\\' + v.idstring ()+ ' ' + refs = refs + '\n \\' + v.idstring () - str = str + '\n\n%s = \\context Staff = %s \n < \n %s >\n\n\n'% (self.idstring (), self.idstring (), refs) + str = str + ''' +%s = \context Staff = %s <%s +> + +''' % (self.idstring (), self.idstring (), refs) return str class Tuplet: @@ -564,6 +603,7 @@ class Parser: def __init__ (self, filename): self.parse_function = self.parse_context_music self.staffs = [] + self.current_voices = [] self.forced_duration = None self.last_name = 0 self.last_oct = 0 @@ -573,68 +613,140 @@ class Parser: self.parse (filename) - def set_staffs (self, number): - self.staffs = map (lambda x: Staff (), range (0, number)) + #def set_staffs (self, number): + # self.staffs = map (lambda x: Staff (x), range (0, number)) - self.staff_idx = 0 - - i =0 - for s in self.staffs: - s.number = i - i = i+1 - - def current_staff (self): - return self.staffs[self.staff_idx] + #def current_staff (self): + # return self.staffs[self.staff_idx] - def current_voice (self): - return self.current_staff ().current_voice () + #def current_voice (self): + # return self.current_staff ().current_voice () - def next_staff (self): - self.staff_idx = (self.staff_idx + 1)% len (self.staffs) + #def next_staff (self): + # self.staff_idx = (self.staff_idx + 1)% len (self.staffs) + def parse_compound_location (self, line): + colon = string.index (line, ':') + s = line[:colon] + debug (s) + line = line[colon + 1:] + debug (line) + self.current_voices = [] + ##self.current_staffs = [] + map (self.parse_location, string.split (s, '&')) + return line + + def parse_location (self, line): + m = re.match ('^([-,0-9]+) *([-,0-9]*)', string.lstrip (line)) + + def range_list_to_idxs (s): + + # duh + def flatten (l): + f = [] + for i in l: + for j in i: + f.append (j) + return f + + def range_to_list (s): + if string.find (s, '-') >= 0: + debug ('s: ' + s) + l = map (string.lstrip, + string.split (s, '-')) + r = range (string.atoi (l[0]) - 1, + string.atoi (l[1])) + else: + r = (string.atoi (s) - 1,) + return r + + ranges = string.split (s, ',') + l = flatten (map (range_to_list, ranges)) + l.sort () + return l + + staff_idxs = range_list_to_idxs (m.group (1)) + if m.group (2): + voice_idxs = range_list_to_idxs (m.group (2)) + else: + voice_idxs = [0] + for s in staff_idxs: + while s > len (self.staffs) - 1: + self.staffs.append (Staff (s)) + for v in voice_idxs: + self.current_voices.append (self.staffs[s].voices[v]) + def parse_note (self, line): - name = line[0] + # FIXME: 1? + oct = 1 + name = (ord (line[0]) - ord ('a') + 5) % 7 + # FIXME: does key play any role in this? alteration = 0 - line = line[1:] + line = string.lstrip (line[1:]) while line: - if line[0] == '#': + if len (line) > 1 and line[:2] == '//': + line = 0 + break + elif line[0] == '#': alteration = alteration + 1 elif line[0] == '&': alteration = alteration - 1 - line = line[1:] - # shortcut - line = 0 + elif line[0] == '+': + oct = oct + 1 + elif line[0] == '-': + oct = oct - 1 + else: + skipping (_ ("%s") % line[0]) + line = string.lstrip (line[1:]) return (oct, name, alteration) - def parse_chord (self, line): - line = string.strip (line) + line = string.lstrip (line) ch = Chord () if not line: - ch = self.current_voice ().last_chord () + ch = self.current_voices[0].last_chord () else: - m = re.match ('([0-9]+)([.]*)', line) + m = re.match ('^([0-9]+)([.]*)', line) if m: ch.basic_duration = string.atoi (m.group (1)) - line = line[len (m.group (1))-1:] + line = line[len (m.group (1)):] if m.group (2): ch.basic_duration = len (m.group (2)) - line = line[len (m.group (1))-1:] - line = string.strip (line) - m = re.match ('([0-9]+)([.]*)', line) + line = line[len (m.group (1)):] + else: + ch.basic_duration = self.current_voices[0].last_chord ().basic_duration + + line = string.lstrip (line) + if len (line) > 1 and line[:2] == '//': + line = 0 + #ugh + if not line: + duration = ch.basic_duration + ch = self.current_voices[0].last_chord () + ch.basic_duration = duration + while line: - c = line[0] - if line[:1] == 'mr': + if len (line) > 1 and line[:2] == '//': + line = 0 + break + elif line[:1] == 'mr': + ch.multimeasure = 1 + line = line[1:] + elif line[:1] == 'ms': ch.multimeasure = 1 - line = 0 - elif c in 'abcdefgrs': - pitch = parse_note (line) - ch.add_pitches (pitch) - line = 0 + line = line[1:] + elif line[0] in 'rs': + pass + elif line[0] in 'abcdefg': + pitch = self.parse_note (line) + debug ('PITCH: ' + `pitch`) + ch.pitches.append (pitch) + line = 0 + break else: - progress ( _("skipping: %s") % line) - line = 0 - self.current_voice ().add_chord (ch) + skipping (_ ("%s") % line[0]) + line = string.lstrip (line[1:]) + map (lambda x, ch=ch: x.add_chord (ch), self.current_voices) def parse_voice (self, line): chords = string.split (line, ';') @@ -644,81 +756,80 @@ class Parser: self.parse_function = self.parse_context_header def parse_context_header (self, line): - sys.stderr.write ('header: ' + line) + debug ('header: ' + line) def init_context_footer (self, line): self.parse_function = self.parse_context_footer def parse_context_footer (self, line): - sys.stderr.write ('footer: ' + line) + debug ('footer: ' + line) def init_context_header2 (self, line): self.parse_function = self.parse_context_header2 def parse_context_header2 (self, line): - sys.stderr.write ('header2: ' + line) + debug ('header2: ' + line) def init_context_footer2 (self, line): self.parse_function = self.parse_context_footer2 def parse_context_footer2 (self, line): - sys.stderr.write ('footer2: ' + line) + debug ('footer2: ' + line) def init_context_score (self, line): self.parse_function = self.parse_context_score def parse_context_score (self, line): - sys.stderr.write ('score: ' + line) + debug ('score: ' + line) def init_context_staff (self, line): self.parse_function = self.parse_context_staff def parse_context_staff (self, line): - sys.stderr.write ('staff: ' + line) + debug ('staff: ' + line) def init_context_voice (self, line): self.parse_function = self.parse_context_voice def parse_context_voice (self, line): - sys.stderr.write ('voice: ' + line) + debug ('voice: ' + line) def init_context_grids (self, line): self.parse_function = self.parse_context_line def parse_context_grids (self, line): - sys.stderr.write ('grids: ' + line) + debug ('grids: ' + line) def init_context_music (self, line): self.parse_function = self.parse_context_music def parse_context_music (self, line): - sys.stderr.write ('music: ' + line) - m = re.match ('^([0-9]+):([0-9]*) ', line) - if m: - self.staff_idx = string.atoi (m.group (1)) - line = line[len (m.group (1)):] - if m.group (2): - self.current_staff ().voice_idx = string.atoi (m.group (2)) - 1 - line = line[len (m.group (2))-1:] - else: - self.current_staff ().voice_idx = 0 - self.parse_voice (line) + debug ('music: ' + line) + line = string.lstrip (line) + if line and line[0] in '0123456789': + line = string.lstrip (self.parse_compound_location (line)) + self.parse_voice (line) else: - progress ( _("skipping: %s") % line) + skipping (_ ("%s") % line) def parse (self, file): # shortcut: set to official mup maximum (duh) # self.set_staffs (40) lines = open (file).readlines () for line in lines: - m = re.match ('^([a-z2]+)', line) + debug ('LINE: ' + line) + m = re.match ('^([a-z]+2?)', line) if m: word = m.group (1) if word in contexts: eval ('self.init_context_%s (line)' % word) continue + else: + warning (_ ("no such context: %s") % word) + skipping (line) else: + debug ('FUNC: ' + `self.parse_function`) self.parse_function (line) for c in self.staffs: @@ -730,13 +841,20 @@ class Parser: refs = '' for s in self.staffs: str = str + s.dump () - refs = '\\' + s.idstring() + refs + refs = refs + '\n \\' + s.idstring () + + str = str + ''' - str = str + "\n\n\\score { <\n %s\n > }" % refs +\score { + <%s + > +} +''' % refs return str option_definitions = [ + ('', 'd', 'debug', _ ("debug")), ('', 'h', 'help', _ ("this help")), ('FILE', 'o', 'output', _ ("write output to FILE")), ('', 'V', 'verbose', _ ("verbose")), @@ -744,7 +862,13 @@ option_definitions = [ ('', 'w', 'warranty', _ ("show warranty and copyright")), ] - +debug_p = 0 +def debug (s): + if debug_p: + progress ('DEBUG: ' + s) +def skipping (s): + if debug_p: + progress ('SKIPPING: ' + s) (sh, long) = getopt_args (__main__.option_definitions) try: @@ -757,13 +881,19 @@ except: for opt in options: o = opt[0] a = opt[1] - if o== '--help' or o == '-h': + if 0: + pass + elif o== '--debug' or o == '-d': + debug_p = 1 + elif o== '--help' or o == '-h': help () sys.exit (0) - if o == '--version' or o == '-v': + elif o== '--verbose' or o == '-V': + verbose_p = 1 + elif o == '--version' or o == '-v': identify () sys.exit (0) - if o == '--output' or o == '-o': + elif o == '--output' or o == '-o': output = a else: print o @@ -793,7 +923,7 @@ for f in files: progress (_ ("Writing %s...") % output) tag = '%% Lily was here -- automatically converted by %s from %s' % ( program_name, f) - ly = tag + e.dump () + ly = tag + '\n' + e.dump () o = open (output, 'w') o.write (ly) diff --git a/scripts/pmx2ly.py b/scripts/pmx2ly.py index b8d289b861..c260b06819 100644 --- a/scripts/pmx2ly.py +++ b/scripts/pmx2ly.py @@ -407,7 +407,9 @@ class Parser: str = str[1:] else: ch = Chord () - self.current_voice().add_chord (ch) + self.current_voice().add_chord (ch) + + # what about 's'? if str[0] <> 'r': name = (ord (str[0]) - ord('a') + 5) % 7 -- 2.39.2