diff options
author | Han-Wen Nienhuys <hanwen@xs4all.nl> | 2004-02-24 22:14:32 +0000 |
---|---|---|
committer | Han-Wen Nienhuys <hanwen@xs4all.nl> | 2004-02-24 22:14:32 +0000 |
commit | f12ef1c68506b5d8a9ae4d8b5d894109ce8fe17a (patch) | |
tree | 3f4e8988dea987c4715dc1fe845dab786c70aae8 | |
parent | 4759b19bf2a9d3baa0f0ff4c66213cc125c301e4 (diff) |
* lily/lyric-phrasing-engraver.cc: remove
* lily/lyric-engraver.cc: rewrite so lyric-phrasing-engraver no
longer necessary.
* lily/extender-engraver.cc (stop_translation_timestep): rewrite
so lyric-phrasing-engraver is no longer necessary.
* ly/engraver-init.ly: move Break_forbid_engraver to Voice, remove
Grob_pq_engraver from Staff.
* lily/grob-pq-engraver.cc: remove current_grobs array, read/write
busyGrobs directly.
34 files changed, 513 insertions, 518 deletions
@@ -17,6 +17,37 @@ 2004-02-24 Han-Wen Nienhuys <hanwen@xs4all.nl> + * lily/lyric-phrasing-engraver.cc: remove + + * lily/lyric-engraver.cc: rewrite so lyric-phrasing-engraver no + longer necessary. + + * lily/extender-engraver.cc (stop_translation_timestep): rewrite + so lyric-phrasing-engraver is no longer necessary. + + * ly/engraver-init.ly: move Break_forbid_engraver to Voice, remove + Grob_pq_engraver from Staff. + + * lily/grob-pq-engraver.cc: remove current_grobs array, read/write + busyGrobs directly. + + * input/regression/quote-transposition.ly: new file. + + * lily/recording-group-engraver.cc (stop_translation_timestep): + store instrumentTuning too. + + * lily/quote-iterator.cc (process): transpose events using + instrumentTuning. + + * scripts/convert-ly.py (FatalConversionError.subst): \set transposing + -> \tuning <pitch> + + * lily/parser.yy (command_req): add \tuning command for setting + instrument tuning of staff. + + * Documentation/user/GNUmakefile + ($(outdir)/lilypond/lilypond.html): ugh: use perl iso. sed. + * Documentation/user/refman.itely (Customized accidental rules): typo. diff --git a/Documentation/topdocs/NEWS.texi b/Documentation/topdocs/NEWS.texi index 32d53d7fbf..a5fce91ffd 100644 --- a/Documentation/topdocs/NEWS.texi +++ b/Documentation/topdocs/NEWS.texi @@ -18,11 +18,16 @@ Version 2.1.13 @itemize @bullet + @item Cue notes can now be quoted directly from the parts that -contain them. For example, +contain them. This will take into account tunings of source and target +instrument. For example, @verbatim -\addquote oboe \notes\relative c' { fis4 fis fis fis } +\addquote clarinet \notes\relative c' { + \tuning bes + fis4 fis fis fis +} \score { \notes \relative c'' { @@ -31,7 +36,13 @@ contain them. For example, } @end verbatim +@item The transposition of an instrument can be specified using the +@code{\tuning} command. The following command specifies an E-flat alto +saxophone: +@example + \tuning es' +@end example @item The naming of exported Scheme functions now follows Scheme conventions. Changes be applied to Scheme files with convert-ly: diff --git a/Documentation/user/GNUmakefile b/Documentation/user/GNUmakefile index a9a3c97fa2..038605846a 100644 --- a/Documentation/user/GNUmakefile +++ b/Documentation/user/GNUmakefile @@ -68,7 +68,7 @@ $(outdir)/lilypond/lilypond.html: $(outdir)/lilypond.texi mkdir -p $(dir $@) $(MAKEINFO) -I$(outdir) --output=$(outdir)/lilypond --html $< $(MAKEINFO) -I$(outdir) --output=$@ --html --no-split --no-headers $< - sed -i 's!../lilypond-internals!lilypond-internals/!g' $(outdir)/lilypond.html + perl -i~ -pe 's!../lilypond-internals!lilypond-internals/!g' $(outdir)/lilypond.html rm -f $(outdir)/lilypond/*.png $(outdir)/lilypond/*.ly -ln -f $(outdir)/*.png $(outdir)/*.ly $(outdir)/lilypond/ diff --git a/Documentation/user/introduction.itely b/Documentation/user/introduction.itely index a05bf1f00c..d0618c72d9 100644 --- a/Documentation/user/introduction.itely +++ b/Documentation/user/introduction.itely @@ -5,7 +5,7 @@ @chapter Introduction There are a lot of programs that let you print sheet music with a -computer, but most of them do not do good job. Most computer +computer, but most of them do not do a good job. Most computer printouts have a bland, mechanical look, and are unpleasant to play from. If you agree with us on that, then you will like LilyPond: we have tried to capture the original look of hand-engraved music. We @@ -54,10 +54,10 @@ question is considered ``engraving'' (i.e. typography). For tackling the first problem, notation, we have broken up the problem into digestible (and programmable) chunks: every type of symbol is handled by a separate program module, a so-called plug-in. -Each plug-in are completely modular and independent, so each can be +Each plug-in is completely modular and independent, so each can be developed and improved separately. When put together, the plug-ins -can solve the music notation program in cooperation. People that put -graphics to musical ideas are called copyists or engravers, so by +can solve the music notation problem in cooperation. People that translate +musical ideas to graphic symbols are called copyists or engravers, so by analogy, each plug-in is also called @code{engraver}. In the following example, we see how we start out with a note head @@ -196,7 +196,7 @@ polyphony? In polyphonic notation, many voices can share a staff. In this situation, the accidentals and staff are shared, but the stems, slurs, beams, etc. are private to each voice. Hence, engravers -should be grouped. The engravers for note head, stems, slurs, etc. go +should be grouped. The engravers for note heads, stems, slurs, etc. go into a group called ``Voice context,'' while the engravers for key, accidental, bar, etc. go into a group called ``Staff context.'' In the case of polyphony, a single Staff context contains more than one Voice @@ -223,7 +223,7 @@ printing. Only a few decades ago, sheet music was made by cutting and stamping the music into zinc or pewter plates, in mirror image. The plate would be inked, and the depressions caused by the cutting and stamping would hold ink. An image was formed by pressing paper to the -plate. The stamping and cutting was completely done by hand. Making +plate. The stamping and cutting was done completely by hand. Making corrections was cumbersome, so engraving had to be done correctly in one go. Of course, this was a highly specialized skill, much more so than the traditional process of printing books. @@ -239,7 +239,7 @@ is acceptable for publication. Sheet music is performance material: everything is done to aid the -musician in letting him perform better. Music often is far away from +musician in letting him perform better. Music is often far away from its reader---it might be on a music stand. To make it clearly readable, traditionally printed sheet music always uses bold symbols, on heavy staff lines, and is printed on large sheets of paper. This @@ -338,7 +338,7 @@ combination should be put farther apart, and the notes of a down-up combination should be put closer together, all depending on the combined vertical positions of the notes. The first two measures are printed with this correction, the last two measures without. The notes -in the last two measures form down-stem/up-stems clumps of notes. +in the last two measures form down-stem/up-stem clumps of notes. @node Typography and program architecture @section Typography and program architecture @@ -352,9 +352,9 @@ become a master. As an engraver gets older and wiser, he will be able to produce better and more complex pieces. A similar situation is present when putting typographical knowledge into a computer program. It is not possible to come up with a definitive solution for a problem -at the first try. Instead, we start out with simple solution that +on the first try. Instead, we start out with a simple solution that might cover 75% of the cases, and gradually refine that solution over -the course of months or years, so 90 or 95 % of the cases are +the course of months or years, so that 90 or 95 % of the cases are handled. This has an important implication for the design of the program: at @@ -372,7 +372,7 @@ Until that time, users must have a way to deal with imperfections: these 25%, 10% or 5% of the cases that are not handled automatically. In these cases, a user must be able to override formatting decisions. To accomplish this we store decisions in generic -variables, and let the user manipulate thosed. For example, consider +variables, and let the user manipulate those. For example, consider the following fragment of notation: @lilypond @@ -405,7 +405,7 @@ This was achieved with the following input statement: \once \override DynamicLineSpanner #'padding = #4.0 @end example It increases the amount of space (@code{padding}) between the note and -the dynamic symbol to 4.0 (which is measured in staff space, so 4.0 +the dynamic symbol to 4.0 (which is measured in staff spaces, so 4.0 equals the height of a staff). The keyword @code{\once} indicates that this is a tweak: it is only done one time. @@ -416,12 +416,13 @@ Scheme objects, and attached to graphical objects such as note heads and stems. The variables are a means to adjust formatting details in individual cases, but they are used in a more general manner. -Consider the case of a publisher that is not satisfied with the in the +Consider the case of a publisher that is not satisfied with the default layout, and wants heavier stems. Normally, they are @code{1.3} times the thickness of staff lines, but suppose that their editions require them to be twice the thickness of the staff lines. The same mechanism can be used to adjust a setting globally. By issuing the -following command, the entire piece is now formatted with thicker stems: +following command, the entire piece is now formatted with thicker +stems: @example \override Score.Stem #'thickness = #3.0 @end example @@ -462,7 +463,7 @@ The full scope of this functionality certainly is intimidating, but there is no need to fear: normally, it is not necessary to define style-sheets or rewrite formatting functions. In fact, LilyPond gets a lot of formatting right automatically, so adjusting individual layout -situations is not needed often at all. +situations is often not needed at all. @node Music representation diff --git a/Documentation/user/refman.itely b/Documentation/user/refman.itely index 8224465a7d..f1c7160a5c 100644 --- a/Documentation/user/refman.itely +++ b/Documentation/user/refman.itely @@ -4065,12 +4065,12 @@ some common problems in orchestral music. * Bar numbers:: * Instrument names:: * Transpose:: +* Instrument transpositions:: * Multi measure rests:: * Automatic part combining:: * Hiding staves:: * Different editions from one source:: * Quoting other voices:: -* Sound output for transposing instruments:: @end menu @node Multiple staff contexts @@ -4325,7 +4325,27 @@ you must put @code{\transpose} outside of @code{\relative}, since @code{\relative} will have no effect music that appears inside a @code{\transpose}. +@node Instrument transpositions +@subsection Instrument transpositions +The key of a transposing instrument can also be specified. This +applies to many wind instruments, for example, clarinets (B-flat, A and +E-flat), horn (F) and trumpet (B-flat, C, D and E-flat). + +@syntax + +The transposition is entered after the keyword @code{\transposition}: + +@example + \transposition bes %% B-flat clarinet +@end example + +This command sets the property @code{instrumentTuning}. The value of +this property is used for MIDI output and quotations. It does not +affect how notes are printed in the current staff. + +@cindex transposition, MIDI +@cindex transposition, instrument @node Multi measure rests @@ -4606,27 +4626,70 @@ Examples: @inputfileref{input/regression,tag-filter.ly}. @node Quoting other voices @subsection Quoting other voices -TODO: document! +With quotations, fragments of other parts can be inserted into a part +directly. Before a part can be quoted, it must be marked especially as +quotable. This is done with code @code{\addquote} command. The +quotation may then be done with @code{\quote} +@example + \addquote @var{name} @var{music} + \quote @var{name} @var{duration} +@end example +@noindent +Here, @var{name} is an identifying string. The @var{music} is any kind +of music. This is an example of @code{\addquote}: +@verbatim +\addquote clarinet \notes\relative c' { + f4 fis g gis +} +@end verbatim -@node Sound output for transposing instruments -@subsection Sound output for transposing instruments +During a part, a piece of music can be quoted with the @code{\quote} +command. + +@verbatim + \quote clarinet 2. +@end verbatim + +This would cite 3 quarter notes (a dotted half note) of the previously +added clarinet voice. + +Quotations take into account the transposition both source and target +instruments, if they are specified using the @code{\transposition} command. + +@lilypond[verbatim fragment] +\addquote clarinet \notes\relative c' { + \transposition bes + f4 fis g gis +} +\score { + \notes { + e'8 f'8 \quote clarinet 2 +} } +@end lilypond + +@refbugs + +Only the contents of the first @internalsref{Voice} occurring in an +@code{\addquote} command will be considered for quotation, so +@var{music} can not contain @code{\new} and @code{\context Voice} +statements that would switch to a different Voice. + + +@seealso + +In this manual: @ref{Instrument transpositions}. + +Examples: @inputfileref{input/regression,quote.ly} +@inputfileref{input/regression,quote-transposition.ly} + +Internals: @internalsref{QuoteMusic}. -When you want to make a MIDI file from a score containing transposed -and untransposed instruments, you have to instruct LilyPond the pitch -offset (in semitones) for the transposed instruments. This is done -using the @code{transposing} property. It does not affect printed -output: -@cindex @code{transposing} -@example - \set Staff.instrument = #"Cl. in B-flat" - \set Staff.transposing = #-2 -@end example @node Ancient notation diff --git a/input/regression/lyric-extender.ly b/input/regression/lyric-extender.ly index 09b7758264..635b7a52aa 100644 --- a/input/regression/lyric-extender.ly +++ b/input/regression/lyric-extender.ly @@ -2,13 +2,13 @@ \header { texidoc= "In lyric extenders, a syllable may be extended over several notes. "} - \paper { raggedright= ##t } +\paper { raggedright= ##t } \score{ \notes \relative c' << - \context Staff { + \context Voice = melody { c8[ ( d] ) r4 f4 } - \context Lyrics \lyrics { xxx __ \skip 4 x } + \lyricsto melody \context Lyrics \lyrics { ah __ ha } >> } diff --git a/input/regression/lyric-phrasing-new.ly b/input/regression/lyric-phrasing-new.ly deleted file mode 100644 index 881e190452..0000000000 --- a/input/regression/lyric-phrasing-new.ly +++ /dev/null @@ -1,25 +0,0 @@ -\version "2.1.26" -\header { - -texidoc = " - Normally, the lyric is centered on the note head. However, on - melismata, the text is left aligned on the left-side of the note head. - -" -} - - -\score{ -<< \notes \relative c' \context Voice = "bla" { - \autoBeamOff - c4( c16 d c b) c4 - d16[ e f g] - - } - \lyrics \lyricsto "bla" \context Lyrics { - al tijd - izzz - } >> - - \paper { raggedright = ##t } -} diff --git a/input/regression/lyric-phrasing.ly b/input/regression/lyric-phrasing.ly index 915791596a..eef50b280e 100644 --- a/input/regression/lyric-phrasing.ly +++ b/input/regression/lyric-phrasing.ly @@ -1,40 +1,25 @@ - \version "2.1.26" -\header{ - texidoc=" - The multiple stanzas of lyric phrasing are aligned according to the start - and end of a phrase. - - By default, lyrics are centered with respect to the corresponding notes. - -@example - | | | | | - x| x| x| x| x| +\header { - 1: Start sentence melisma end. - 2: x x x______ x -@end example +texidoc = " + Normally, the lyric is centered on the note head. However, on + melismata, the text is left aligned on the left-side of the note head. - While there is a melisma, lyrics are followed by '__' and they - are left-aligned, in this case the third x." +" } -\paper { raggedright = ##t} -\score { - \addlyrics - \context Voice = "v" \notes \relative c'' { - \autoBeamOff - a a a8 ( a) a4 - } - << - \new Lyrics \lyricsto "v" \lyrics { - \set stanza = "1:" - Start sentence melisma end. - } - \new Lyrics \lyricsto "v" \lyrics { - \set stanza = "2:" - x x x __ x. - } - >> -} +\score{ +<< \notes \relative c' \context Voice = "bla" { + \autoBeamOff + c4( c16 d c b) c4 + d16[ e f g] + + } + \lyrics \lyricsto "bla" \context Lyrics { + alllll __ tijd + izzz + } >> + + \paper { raggedright = ##t } +} diff --git a/input/regression/quote-transposition.ly b/input/regression/quote-transposition.ly new file mode 100644 index 0000000000..66fdbab12d --- /dev/null +++ b/input/regression/quote-transposition.ly @@ -0,0 +1,33 @@ + +\header +{ + + texidoc = "Quotations take into account the transposition of both source and target. +In this example, all instruments play sounding central C, the target is a instrument in F." + +} +\version "2.1.26" + + +\addquote clarinet \notes { + \transposition bes + d'16 d'16 d'8 + d'16 d'16 d'8 + d'16 d'16 d'8 + d'16 d'16 d'8 + } +\addquote sax \notes { + \transposition es' + a8 a a a a a a a + } + +\score { + \notes{ + \transposition f % french horn + + g'4 + << \quote clarinet 4 s4^"clar" >> + << \quote sax 4 s4^"sax" >> + } +} + diff --git a/input/regression/quote.ly b/input/regression/quote.ly index a1f4daf191..567119a847 100644 --- a/input/regression/quote.ly +++ b/input/regression/quote.ly @@ -7,11 +7,12 @@ music may be quoted. " } \version "2.1.26" -\addquote bla \notes\relative c' { fis4 g a b } +\addquote bla \notes\relative c' { + fis4 g a b } \score { \notes \relative c'' { - c8 d8 \quote 2 bla es8 gis + c8 d8 \quote bla 2 es8 gis } } diff --git a/input/regression/stanza-number.ly b/input/regression/stanza-number.ly index 227402d2fb..7c38a47a60 100644 --- a/input/regression/stanza-number.ly +++ b/input/regression/stanza-number.ly @@ -1,21 +1,25 @@ \version "2.1.26" \header { -texidoc = "Stanza numbers are put left of their lyric." +texidoc = "Stanza numbers are put left of their lyric. Theyr are aligned in a column." } \score { << - \notes { r4 r4 c4 c4 } - \context Lyrics - \lyrics { + \context Voice = "A" \notes \relative c'' { r4 r4 c4 c4 } + \lyricsto A \new Lyrics \lyrics { \skip 2 \set stanza = "1." - Foo8 Bar8 + Foo8 + } + \lyricsto A \new Lyrics \lyrics { + \skip 2 + \set stanza = "2." + FFFooooo8 } >> \paper { raggedright = ##t } -} +} diff --git a/lily/extender-engraver.cc b/lily/extender-engraver.cc index 2bf4c70870..10f677105e 100644 --- a/lily/extender-engraver.cc +++ b/lily/extender-engraver.cc @@ -12,12 +12,14 @@ #include "lyric-extender.hh" #include "item.hh" #include "engraver.hh" +#include "context.hh" +#include "group-interface.hh" class Extender_engraver : public Engraver { Music* ev_; Spanner* extender_; - Spanner * finished_extender_; + Spanner * pending_extender_; public: TRANSLATOR_DECLARATIONS(Extender_engraver); @@ -37,34 +39,80 @@ private: Extender_engraver::Extender_engraver () { extender_ = 0; - finished_extender_ = 0; + pending_extender_ = 0; ev_ = 0; } +bool +Extender_engraver::try_music (Music* r) +{ + if (ev_) + return false; + + ev_ = r; + return true; +} + + +void +Extender_engraver::process_music () +{ + if (ev_) + { + extender_ = make_spanner ("LyricExtender"); + announce_grob (extender_, ev_->self_scm()); + } +} + + void Extender_engraver::acknowledge_grob (Grob_info i) { Item * item = dynamic_cast<Item*> (i.grob_); - // -> text_item - if (item && item->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface"))) + + if (item + && item->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface"))) { if (extender_) extender_->set_bound (LEFT, item); - if (finished_extender_) - finished_extender_->set_bound (RIGHT, item); + if (pending_extender_) + pending_extender_->set_bound (RIGHT, item); } } - -bool -Extender_engraver::try_music (Music* r) +void +Extender_engraver::stop_translation_timestep () { - if (ev_) - return false; + if (pending_extender_ && pending_extender_->get_bound (RIGHT)) + { + typeset_grob (pending_extender_); + pending_extender_ = 0; + } - ev_ = r; - return true; + if (extender_ || pending_extender_) + { + Context *voice = get_voice_to_lyrics (daddy_context_); + Grob* h = (voice) ? get_current_note_head (voice) : 0; + + if (h) + { + if (extender_) + Pointer_group_interface::add_grob (extender_, + ly_symbol2scm ("heads"), h); + if (pending_extender_) + Pointer_group_interface::add_grob (pending_extender_, + ly_symbol2scm ("heads"), h); + } + + if (extender_) + { + pending_extender_ = extender_; + extender_ = 0; + } + } + + ev_ = 0; } void @@ -97,50 +145,18 @@ Extender_engraver::finalize () extender_ = 0; } - if (finished_extender_) + if (pending_extender_) { - completize_extender (finished_extender_); - - if (!finished_extender_->get_bound (RIGHT)) - finished_extender_->warning (_("unterminated extender")); - typeset_grob (finished_extender_); - finished_extender_ =0; - } -} + completize_extender (pending_extender_); -void -Extender_engraver::process_music () -{ - if (ev_) - { - extender_ = make_spanner ("LyricExtender"); - announce_grob (extender_, ev_->self_scm()); + if (!pending_extender_->get_bound (RIGHT)) + pending_extender_->warning (_("unterminated extender")); + typeset_grob (pending_extender_); + pending_extender_ =0; } } -void -Extender_engraver::stop_translation_timestep () -{ - if (finished_extender_ && finished_extender_->get_bound (RIGHT)) - { - typeset_grob (finished_extender_); - finished_extender_ = 0; - } - - if (finished_extender_ && extender_) - { - programming_error ("Haven't finished extender yet."); - typeset_grob (finished_extender_); - finished_extender_ =0; - } - - if (extender_) - finished_extender_ = extender_; - extender_ = 0; - - ev_ = 0; -} diff --git a/lily/forbid-break-engraver.cc b/lily/forbid-break-engraver.cc index dbaad08568..b2a5d802c5 100644 --- a/lily/forbid-break-engraver.cc +++ b/lily/forbid-break-engraver.cc @@ -12,14 +12,6 @@ public: Forbid_line_break_engraver::Forbid_line_break_engraver(){} -ENTER_DESCRIPTION(Forbid_line_break_engraver, -/* descr */ "Forbid line breaks when note heads are still playing at some point.", -/* creats*/ "", -/* accepts */ "", -/* acks */ "", -/* reads */ "busyGrobs", -/* write */ ""); - void Forbid_line_break_engraver::start_translation_timestep() { @@ -43,3 +35,12 @@ Forbid_line_break_engraver::start_translation_timestep() busy = gh_cdr(busy); } } + + +ENTER_DESCRIPTION(Forbid_line_break_engraver, +/* descr */ "Forbid line breaks when note heads are still playing at some point.", +/* creats*/ "", +/* accepts */ "", +/* acks */ "", +/* reads */ "busyGrobs", +/* write */ ""); diff --git a/lily/grob-pq-engraver.cc b/lily/grob-pq-engraver.cc index 4fdf5d2b4f..96d93ceec2 100644 --- a/lily/grob-pq-engraver.cc +++ b/lily/grob-pq-engraver.cc @@ -11,35 +11,10 @@ #include "grob.hh" #include "warn.hh" -/* - TODO: should junk this engraver. - */ - -struct Grob_mom -{ - Grob * grob_ ; - Moment end_; - Grob_mom () {} - Grob_mom (Grob*gr, Moment e) - { - grob_ = gr; - end_ = e; - } -}; - -int compare (Grob_mom const &a, Grob_mom const &b) -{ - return Moment::compare (a.end_, b.end_); -} - -/****************/ - class Grob_pq_engraver: public Engraver { public: TRANSLATOR_DECLARATIONS(Grob_pq_engraver); - - Array<Grob_mom> current_grobs_; protected: virtual void initialize (); virtual void acknowledge_grob (Grob_info); @@ -52,13 +27,23 @@ Grob_pq_engraver::Grob_pq_engraver() { } - void Grob_pq_engraver::initialize () { daddy_context_->set_property ("busyGrobs", SCM_EOL); } +LY_DEFINE(ly_grob_pq_less_p, + "ly:grob-pq-less?", 2 , 0 ,0, (SCM a, SCM b), + "Compare 2 Grob PQ entries. Internal") +{ + if (Moment::compare (*unsmob_moment (gh_car (a)), + *unsmob_moment (gh_car (b))) < 0) + return SCM_BOOL_T; + else + return SCM_BOOL_F; +} + void Grob_pq_engraver::acknowledge_grob (Grob_info gi) { @@ -79,45 +64,31 @@ Grob_pq_engraver::acknowledge_grob (Grob_info gi) l.main_part_ = 0; } - current_grobs_.push (Grob_mom (gi.grob_, n + l)); + Moment end = n + l; + SCM lst = scm_acons (end.smobbed_copy (), + gi.grob_->self_scm(), + SCM_EOL); + + SCM busy= get_property ("busyGrobs"); + busy = scm_merge_x (lst, busy, ly_grob_pq_less_p_proc); + daddy_context_->set_property ("busyGrobs", busy); } } -LY_DEFINE(ly_grob_pq_less_p, - "ly:grob-pq-less?", 2 , 0 ,0, (SCM a, SCM b), - "Compare 2 Grob PQ entries. Internal") -{ - if ( Moment::compare (*unsmob_moment (gh_car (a)), - *unsmob_moment (gh_car (b))) < 0) - return SCM_BOOL_T; - else - return SCM_BOOL_F; -} - void Grob_pq_engraver::stop_translation_timestep () { - Moment now = now_mom(); - - current_grobs_.sort (&compare); - SCM current_list = SCM_EOL; - for (int i = current_grobs_.size(); i--;) - current_list = scm_cons (scm_cons (current_grobs_[i].end_.smobbed_copy(), - current_grobs_[i].grob_->self_scm ()), current_list); - - /* - We generate some garbage here. - */ - SCM busy = get_property ("busyGrobs"); + Moment now = now_mom (); + SCM start_busy = get_property ("busyGrobs"); + SCM busy = start_busy; while (gh_pair_p (busy) && *unsmob_moment (gh_caar (busy)) == now) { busy = gh_cdr (busy); } - - busy = scm_merge_x (current_list, busy, ly_grob_pq_less_p_proc); - current_grobs_.clear (); - daddy_context_->set_property ("busyGrobs", busy); + + if (start_busy != busy) + daddy_context_->set_property ("busyGrobs", busy); } void @@ -133,7 +104,9 @@ Grob_pq_engraver::start_translation_timestep () Todo: do something sensible. The grob-pq-engraver is not water tight, and stuff like tupletSpannerDuration confuses it. */ - programming_error (_f("Skipped something?\nGrob %s ended before I expected it to end.", unsmob_grob (gh_cdar (busy))->name().to_str0())); + programming_error (_f("Skipped something?\nGrob %s ended before " + "I expected it to end.", + unsmob_grob (gh_cdar (busy))->name().to_str0())); busy = gh_cdr (busy); } diff --git a/lily/hyphen-engraver.cc b/lily/hyphen-engraver.cc index dbf70c7414..16b79b915f 100644 --- a/lily/hyphen-engraver.cc +++ b/lily/hyphen-engraver.cc @@ -92,7 +92,11 @@ Hyphen_engraver::finalize () completize_hyphen (hyphen_); if (!hyphen_->get_bound (RIGHT)) - hyphen_->warning (_ ("unterminated hyphen")); + { + hyphen_->warning (_ ("unterminated hyphen; removing")); + hyphen_->suicide (); + } + typeset_grob (hyphen_); hyphen_ = 0; } diff --git a/lily/include/context.hh b/lily/include/context.hh index aadc76bc67..a47237fb03 100644 --- a/lily/include/context.hh +++ b/lily/include/context.hh @@ -76,8 +76,11 @@ void execute_pushpop_property (Context * trg, SCM prop, SCM eltprop, SCM val); SCM updated_grob_properties (Context* tg, SCM sym); Context * find_context_below (Context * where, String type, String id); +bool melisma_busy (Context*); -Context * unsmob_context (SCM); +Context *get_voice_to_lyrics (Context *lyrics); +Grob *get_current_note_head (Context * voice); +Context *unsmob_context (SCM); DECLARE_UNSMOB(Context,context); diff --git a/lily/include/music.hh b/lily/include/music.hh index 8d96b195c6..78d1be7bde 100644 --- a/lily/include/music.hh +++ b/lily/include/music.hh @@ -72,5 +72,6 @@ protected: DECLARE_UNSMOB(Music,music); Music* make_music_by_name (SCM sym); +SCM ly_deep_mus_copy (SCM); #endif // MUSIC_HH diff --git a/lily/include/pitch.hh b/lily/include/pitch.hh index d0891569c5..8a7f276aba 100644 --- a/lily/include/pitch.hh +++ b/lily/include/pitch.hh @@ -78,6 +78,7 @@ enum { DOUBLE_SHARP, }; +SCM ly_pitch_diff (SCM pitch, SCM root); SCM ly_pitch_transpose (SCM p, SCM delta); DECLARE_UNSMOB(Pitch,pitch); diff --git a/lily/include/translator.hh b/lily/include/translator.hh index de406a3db4..57e3257a2f 100644 --- a/lily/include/translator.hh +++ b/lily/include/translator.hh @@ -123,5 +123,4 @@ void add_translator (Translator*trans); Translator*get_translator (SCM s); DECLARE_UNSMOB(Translator,translator); -bool melisma_busy (Translator*); #endif // TRANSLATOR_HH diff --git a/lily/lyric-combine-music-iterator.cc b/lily/lyric-combine-music-iterator.cc index 1783677b82..4c176aacf2 100644 --- a/lily/lyric-combine-music-iterator.cc +++ b/lily/lyric-combine-music-iterator.cc @@ -39,12 +39,10 @@ private: }; -#include "translator.hh" - bool -melisma_busy (Translator* tr) +melisma_busy (Context* tr) { - SCM melisma_properties = tr->daddy_context_->get_property ("melismaBusyProperties"); + SCM melisma_properties = tr->get_property ("melismaBusyProperties"); bool busy = false; for (; gh_pair_p (melisma_properties); diff --git a/lily/lyric-engraver.cc b/lily/lyric-engraver.cc index 6c7c2697dc..20cf201bdc 100644 --- a/lily/lyric-engraver.cc +++ b/lily/lyric-engraver.cc @@ -10,9 +10,9 @@ #include "engraver.hh" #include "event.hh" #include "item.hh" -#include "paper-def.hh" +#include "context.hh" #include "font-metric.hh" -#include "side-position-interface.hh" +#include "note-head.hh" /** Generate texts for lyric syllables. We only do one lyric at a time. @@ -28,17 +28,16 @@ protected: public: TRANSLATOR_DECLARATIONS(Lyric_engraver); private: - Music * req_; + Music * event_; Item* text_; -}; - - + Context* get_voice_context (); +}; Lyric_engraver::Lyric_engraver () { text_ =0; - req_ =0; + event_ =0; } bool @@ -46,9 +45,9 @@ Lyric_engraver::try_music (Music*r) { if (r->is_mus_type ("lyric-event")) { - if (req_) + if (event_) return false; - req_ =r; + event_ =r; return true; } return false; @@ -57,24 +56,82 @@ Lyric_engraver::try_music (Music*r) void Lyric_engraver::process_music () { - if (req_) + if (event_) { text_= make_item ("LyricText"); - text_->set_property ("text", req_->get_property ("text")); - announce_grob (text_, req_->self_scm()); + text_->set_property ("text", event_->get_property ("text")); + announce_grob (text_, event_->self_scm()); } } + +Context* +get_voice_to_lyrics (Context *lyrics) +{ + SCM avc = lyrics->get_property ("associatedVoiceContext"); + if (Context *c = unsmob_context (avc)) + return c; + + SCM voice = lyrics->get_property ("associatedVoice"); + String nm = lyrics->id_string_; + + if (gh_string_p (voice)) + nm = ly_scm2string (voice); + else + { + int idx = nm.index_last ('-'); + if (idx >= 0) + nm = nm.left_string (idx); + } + + Context *c = lyrics->find_existing_context (ly_symbol2scm ("Voice"), nm); + + if (c) + return c; + + return lyrics->find_existing_context (ly_symbol2scm ("Voice"), ""); +} + +Grob * +get_current_note_head (Context * voice) +{ + for (SCM s = voice->get_property ("busyGrobs"); + gh_pair_p (s); s = gh_cdr (s)) + { + Item*g = dynamic_cast<Item*> (unsmob_grob (gh_cdar (s))); + + if (g && !g->get_column () + && Note_head::has_interface (g)) + return g; + } + + return 0; +} + void Lyric_engraver::stop_translation_timestep () { if (text_) { + Context * voice = get_voice_to_lyrics (daddy_context_); + + if (voice) + { + Grob *head = get_current_note_head (voice); + + if (head) + { + text_->set_parent (head, X_AXIS); + if (melisma_busy (voice)) + text_->set_property ("self-alignment-X", gh_int2scm (LEFT)); + } + } + typeset_grob (text_); text_ =0; } - req_ =0; + event_ =0; } diff --git a/lily/lyric-hyphen.cc b/lily/lyric-hyphen.cc index 93f20bca4c..f7a7221afd 100644 --- a/lily/lyric-hyphen.cc +++ b/lily/lyric-hyphen.cc @@ -104,11 +104,15 @@ Hyphen_spanner::set_spacing_rods (SCM smob) do { r.item_l_drul_[d] = sp->get_bound (d); - r.distance_ += r.item_l_drul_[d]->extent (r.item_l_drul_[d], X_AXIS)[-d]; + if (r.item_l_drul_[d]) + r.distance_ += r.item_l_drul_[d]->extent (r.item_l_drul_[d], X_AXIS)[-d]; } while (flip (&d) != LEFT); - r.add_to_cols (); + if (r.item_l_drul_[LEFT] + && r.item_l_drul_[RIGHT]) + r.add_to_cols (); + return SCM_UNSPECIFIED; } diff --git a/lily/lyric-phrasing-engraver.cc b/lily/lyric-phrasing-engraver.cc deleted file mode 100644 index fb94dded75..0000000000 --- a/lily/lyric-phrasing-engraver.cc +++ /dev/null @@ -1,253 +0,0 @@ -/* - new-phrasing-engraver.cc -- implement New_phrasing_engraver - -source file of the GNU LilyPond music typesetter - -(c) 2003--2004 Han-Wen Nienhuys <hanwen@xs4all.nl> - - */ - - -#include "context.hh" -#include "engraver.hh" -#include "note-head.hh" -#include "lyric-extender.hh" -#include "item.hh" -#include "group-interface.hh" -#include "side-position-interface.hh" - -struct Phrasing_association -{ - String name_; - Link_array<Grob> lyrics_; - Link_array<Grob> heads_; - Link_array<Spanner> past_extenders_; - Link_array<Spanner> new_extenders_; - Link_array<Grob> stanza_numbers_; - - - bool melisma_; - - Phrasing_association() - { - melisma_ = false; - } -}; - -class Lyric_phrasing_engraver : public Engraver -{ -public: - ~Lyric_phrasing_engraver (); - TRANSLATOR_DECLARATIONS(Lyric_phrasing_engraver); -protected: - virtual void acknowledge_grob (Grob_info); - virtual void process_acknowledged_grobs (); - virtual void stop_translation_timestep (); - -private: - void add_lyric_phrasing (Grob_info); - void add_voice_phrasing (Grob_info); - void add_lyric_extender (Grob_info); - void add_stanza_number (Grob_info); - Phrasing_association *get_phrasing_assoc (String nm); - String get_voice_name_for_lyric (Context *tr); - Link_array<Phrasing_association> assocs_; -}; - -Lyric_phrasing_engraver::Lyric_phrasing_engraver() -{ -} - -void -Lyric_phrasing_engraver::acknowledge_grob (Grob_info i) -{ - Grob *h = i.grob_; - - if (Note_head::has_interface (h)) - add_voice_phrasing (i); - else if (h->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface"))) - add_lyric_phrasing (i); - else if (Lyric_extender::has_interface (h)) - add_lyric_extender (i); - else if (h->internal_has_interface (ly_symbol2scm ("stanza-number-interface"))) - add_stanza_number (i); -} - -Phrasing_association * -Lyric_phrasing_engraver::get_phrasing_assoc (String nm) -{ - Phrasing_association * a=0; - for (int i=0 ; !a && i < assocs_.size (); i++) - { - if (assocs_[i]->name_ == nm) - a = assocs_[i]; - } - - if (!a) - { - a = new Phrasing_association ; - a->name_ = nm; - assocs_.push (a); - } - return a; -} - - - -String -Lyric_phrasing_engraver::get_voice_name_for_lyric (Context *tr) -{ - SCM voice_context = tr->get_property ("associatedVoiceContext"); - if (Context *vc = unsmob_context (voice_context)) - { - return vc->id_string_; - } - - SCM voice = tr->get_property ("associatedVoice"); - String nm = tr->id_string_; - if (gh_string_p (voice)) - nm = ly_scm2string (voice); - else - { - int idx = nm.index_last ('-'); - if (idx >= 0) - nm = nm.left_string (idx); - } - - return nm; -} - - -void -Lyric_phrasing_engraver::add_lyric_extender (Grob_info inf) -{ - Context * tr = inf.origin_trans_->daddy_context_; - while (tr && !tr->is_alias (ly_symbol2scm ("Lyrics"))) - tr = tr->daddy_context_; - - if (!tr) - return; - - - Phrasing_association *a = get_phrasing_assoc (get_voice_name_for_lyric (tr)); - a->new_extenders_.push (dynamic_cast<Spanner*> (inf.grob_)); -} - -void -Lyric_phrasing_engraver::add_stanza_number (Grob_info inf) -{ - Context * tr = inf.origin_trans_->daddy_context_; - while (tr && !tr->is_alias (ly_symbol2scm ("Lyrics"))) - tr = tr->daddy_context_; - - if (!tr) - return; - - Phrasing_association *a = get_phrasing_assoc (get_voice_name_for_lyric (tr)); - a->stanza_numbers_.push (inf.grob_); -} - -void -Lyric_phrasing_engraver::add_voice_phrasing (Grob_info inf) -{ - Context * tr = inf.origin_trans_->daddy_context_; - while (tr && !tr->is_alias (ly_symbol2scm ("Voice"))) - tr = tr->daddy_context_; - - if (!tr) - return; - - Phrasing_association *a = get_phrasing_assoc (tr->id_string_); - a->heads_.push (inf.grob_); - a->melisma_ = melisma_busy (inf.origin_trans_); -} - -void -Lyric_phrasing_engraver::add_lyric_phrasing (Grob_info inf) -{ - Context * tr = inf.origin_trans_->daddy_context_; - while (tr && !tr->is_alias (ly_symbol2scm ("Lyrics"))) - tr = tr->daddy_context_; - - if (!tr) - return; - - - Phrasing_association *a = get_phrasing_assoc (get_voice_name_for_lyric (tr)); - a->lyrics_.push (inf.grob_); - a->past_extenders_.clear (); -} - -void -Lyric_phrasing_engraver::stop_translation_timestep () -{ - Link_array<Grob> stzs; - Link_array<Grob> lyrs; - for (int i = assocs_.size (); i--; ) - { - Phrasing_association * a = assocs_[i]; - stzs.concat (a->stanza_numbers_); - lyrs.concat (a->lyrics_); - } - - for(int i= lyrs.size(); i--;) - for (int j = stzs.size (); j--;) - Side_position_interface::add_support (stzs[j], lyrs[i]); - - for (int i = assocs_.size (); i--; ) - { - Phrasing_association * a = assocs_[i]; - - a->stanza_numbers_.clear (); - a->heads_.clear (); - a->lyrics_.clear (); - a->past_extenders_.concat (assocs_[i]->new_extenders_) ; - a->new_extenders_.clear (); - } -} - -void -Lyric_phrasing_engraver::process_acknowledged_grobs () -{ - for (int i = 0; i < assocs_.size (); i++) - { - Phrasing_association * a = assocs_[i]; - if (! (a->heads_.size() && (a->lyrics_.size () || a->past_extenders_.size ()))) - continue; - - Grob *h = a->heads_[0]; - Direction alignment = CENTER; - if (a->melisma_) - alignment = LEFT; - - for (int j = 0; j < a->lyrics_.size (); j++) - { - Grob *l = a->lyrics_[j]; - if (!l->get_parent (X_AXIS)) - { - l->set_parent (h, X_AXIS); - if (alignment) - l->set_property ("self-alignment-X", gh_int2scm (alignment)); - } - } - - for (int j = a->past_extenders_.size(); j--;) - Pointer_group_interface::add_grob (a->past_extenders_[j],ly_symbol2scm ("heads"), h); - } -} - -Lyric_phrasing_engraver::~Lyric_phrasing_engraver () -{ - for (int i =assocs_.size(); i--;) - delete assocs_[i]; -} - -ENTER_DESCRIPTION(Lyric_phrasing_engraver, - "This engraver combines note heads and lyrics for alignment. ", - "", - "", - "stanza-number-interface lyric-syllable-interface " - "note-head-interface lyric-extender-interface", - "associatedVoice", - ""); - diff --git a/lily/melisma-translator.cc b/lily/melisma-translator.cc index ce14a2909e..1ac8032102 100644 --- a/lily/melisma-translator.cc +++ b/lily/melisma-translator.cc @@ -36,7 +36,7 @@ Melisma_translator::try_music (Music *m) { if (m->is_mus_type ("melisma-playing-event")) { - return melisma_busy (this); + return melisma_busy (daddy_context_); } else if (m->is_mus_type ("melisma-span-event")) { diff --git a/lily/music.cc b/lily/music.cc index cafb9a365a..bcc942e095 100644 --- a/lily/music.cc +++ b/lily/music.cc @@ -15,7 +15,6 @@ #include "ly-smobs.icc" -SCM ly_deep_mus_copy (SCM); bool Music::internal_is_music_type (SCM k)const diff --git a/lily/my-lily-lexer.cc b/lily/my-lily-lexer.cc index 53acda5cdd..007aa9d1ee 100644 --- a/lily/my-lily-lexer.cc +++ b/lily/my-lily-lexer.cc @@ -85,6 +85,7 @@ static Keyword_ent the_key_tab[]={ {"times", TIMES}, {"translator", TRANSLATOR}, {"transpose", TRANSPOSE}, + {"transposition", TRANSPOSITION}, {"type", TYPE}, {"unset", UNSET}, {"with", WITH}, diff --git a/lily/note-performer.cc b/lily/note-performer.cc index 046e6935ac..ab6f6a1887 100644 --- a/lily/note-performer.cc +++ b/lily/note-performer.cc @@ -37,11 +37,11 @@ Note_performer::create_audio_elements () { if (note_evs_.size ()) { - int transposing_i = 0; - //urg - SCM prop = get_property ("transposing"); - if (gh_number_p (prop)) - transposing_i = gh_scm2int (prop); + int transposing = 0; + + SCM prop = get_property ("instrumentTransposition"); + if (unsmob_pitch (prop)) + transposing = unsmob_pitch (prop)->semitone_pitch (); while (note_evs_.size ()) { @@ -50,7 +50,7 @@ Note_performer::create_audio_elements () if (Pitch * pitp = unsmob_pitch (pit)) { - Audio_note* p = new Audio_note (*pitp, n->get_length (), transposing_i); + Audio_note* p = new Audio_note (*pitp, n->get_length (), transposing); Audio_element_info info (p, n); announce_element (info); notes_.push (p); diff --git a/lily/parser.yy b/lily/parser.yy index 666963b1f7..1af8d75138 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -301,6 +301,7 @@ yylex (YYSTYPE *s, void * v) %token TIME_T %token TRANSLATOR %token TRANSPOSE +%token TRANSPOSITION %token TYPE %token UNSET %token WITH @@ -1363,19 +1364,19 @@ command_element: $$ = skip; } - | QUOTE duration_length STRING { + | QUOTE STRING duration_length { SCM tab = THIS->lexer_->lookup_identifier ("musicQuotes"); SCM evs = SCM_EOL; if (scm_hash_table_p (tab) == SCM_BOOL_T) { - SCM key = $3; // use symbol? + SCM key = $2; // use symbol? evs = scm_hash_ref (tab, key, SCM_BOOL_F); } Music * quote = 0; - if (scm_vector_p (evs) == SCM_BOOL_T) + if (gh_vector_p (evs)) { quote = MY_MAKE_MUSIC("QuoteMusic"); - quote->set_property ("duration", $2); + quote->set_property ("duration", $3); quote->set_property ("quoted-events", evs); } else { THIS->here_input ().warning (_f ("Can\'t find music")); @@ -1420,6 +1421,13 @@ command_element: $$ = MY_MAKE_MUSIC("BarCheck"); $$->set_spot (THIS->here_input ()); } + | TRANSPOSITION pitch { + $$ = set_property_music (ly_symbol2scm ("instrumentTransposition"), + $2); + $$->set_spot (THIS-> here_input ()); + $$ = context_spec_music (ly_symbol2scm ("Staff"), SCM_UNDEFINED, + $$ , SCM_EOL); + } | BAR STRING { Music *t = set_property_music (ly_symbol2scm ("whichBar"), $2); diff --git a/lily/quote-iterator.cc b/lily/quote-iterator.cc index 266ca9ed1a..8b4a7d59ec 100644 --- a/lily/quote-iterator.cc +++ b/lily/quote-iterator.cc @@ -27,15 +27,24 @@ public: int event_idx_; int end_idx_ ; + SCM transposed_musics_; + DECLARE_SCHEME_CALLBACK(constructor, ()); protected: + virtual void derived_mark (); virtual void construct_children (); virtual Moment pending_moment () const; virtual void process (Moment); virtual bool ok () const; }; +void +Quote_iterator::derived_mark () +{ + scm_gc_mark (transposed_musics_ ); +} + Quote_iterator::Quote_iterator () { event_vector_ = SCM_EOL; @@ -63,7 +72,7 @@ binsearch_scm_vector (SCM vec, SCM key, bool (*is_less)(SCM a,SCM b)) { int cmp = (lo + hi) / 2; - SCM when = gh_car (SCM_VECTOR_REF(vec, cmp)); + SCM when = gh_caar (SCM_VECTOR_REF(vec, cmp)); bool result = (*is_less) (key, when); if (result) hi = cmp; @@ -91,7 +100,7 @@ Quote_iterator::construct_children () start_moment_ = now; event_vector_ = get_music ()->get_property ("quoted-events"); - if (scm_vector_p (event_vector_) == SCM_BOOL_T) + if (gh_vector_p (event_vector_)) { event_idx_ = binsearch_scm_vector (event_vector_, now.smobbed_copy (), &moment_less); end_idx_ = binsearch_scm_vector (event_vector_, stop.smobbed_copy (), &moment_less); @@ -110,7 +119,7 @@ Moment Quote_iterator::pending_moment () const { SCM entry = SCM_VECTOR_REF (event_vector_, event_idx_); - return *unsmob_moment (gh_car (entry)) - start_moment_; + return *unsmob_moment (gh_caar (entry)) - start_moment_; } @@ -124,7 +133,7 @@ Quote_iterator::process (Moment m) { entry = SCM_VECTOR_REF (event_vector_, event_idx_); - Moment em = *unsmob_moment (gh_car (entry)); + Moment em = *unsmob_moment (gh_caar (entry)); if (em > m) return ; @@ -137,6 +146,9 @@ Quote_iterator::process (Moment m) if (gh_pair_p (entry)) { + Pitch * quote_pitch = unsmob_pitch (gh_cdar (entry)); + Pitch * me_pitch = unsmob_pitch (get_outlet ()->get_property ("instrumentTransposition")); + for (SCM s = gh_cdr (entry); gh_pair_p (s); s = gh_cdr (s)) { SCM ev_acc = gh_car (s); @@ -145,6 +157,24 @@ Quote_iterator::process (Moment m) Music * mus = unsmob_music (gh_car (ev_acc)); if (mus) { + if (quote_pitch || me_pitch) + { + Pitch qp, mp; + if (quote_pitch) + qp = *quote_pitch; + if (me_pitch) + mp = *me_pitch; + + Pitch diff = interval (mp, qp); + + SCM copy = ly_deep_mus_copy (mus->self_scm ()); + mus = unsmob_music (copy); + transposed_musics_ = gh_cons (copy, transposed_musics_); + + mus->transpose (diff); + } + + bool b = get_outlet ()->try_music (mus); if (!b) diff --git a/lily/recording-group-engraver.cc b/lily/recording-group-engraver.cc index c314bb736f..0b8b87da00 100644 --- a/lily/recording-group-engraver.cc +++ b/lily/recording-group-engraver.cc @@ -13,6 +13,7 @@ class Recording_group_engraver : public Engraver_group_engraver { + void start (); public: TRANSLATOR_DECLARATIONS(Recording_group_engraver); virtual bool try_music (Music *m); @@ -27,8 +28,7 @@ void Recording_group_engraver::initialize () { Engraver_group_engraver::initialize (); - accumulator_ = gh_cons (gh_cons (now_mom (). smobbed_copy (), SCM_EOL), - SCM_EOL); + start (); } Recording_group_engraver::Recording_group_engraver() @@ -46,8 +46,23 @@ Recording_group_engraver::start_translation_timestep () start_translation_timestep(), since start_translation_timestep() isn't called on the first time-step. */ + start () ; +} + +void +Recording_group_engraver::start () +{ + if (!gh_pair_p (accumulator_)) + accumulator_ = gh_cons (SCM_EOL, SCM_EOL); if (!gh_pair_p (gh_car (accumulator_))) - scm_set_car_x (accumulator_, gh_cons (now_mom ().smobbed_copy (), SCM_EOL)); + { + /* + Need to store transposition for every moment; transposition changes during pieces. + */ + scm_set_car_x (accumulator_, gh_cons (gh_cons (now_mom ().smobbed_copy (), + get_property ("instrumentTransposition")), + SCM_EOL)); + } } void diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index 39aebe4274..8f6de86a97 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -21,9 +21,9 @@ \consists "Bar_engraver" % Bar_engraver must be first so default bars aren't overwritten % with empty ones. + \consists "Font_size_engraver" -% \consists "Repeat_engraver" \consists "Volta_engraver" \consists "Separating_line_group_engraver" \consists "Dot_column_engraver" @@ -39,8 +39,6 @@ \consists "Accidental_engraver" \consists "Piano_pedal_engraver" \consists "Instrument_name_engraver" - \consists "Grob_pq_engraver" - \consists "Forbid_line_break_engraver" \consists "String_number_engraver" \consistsend "Axis_group_engraver" @@ -171,6 +169,7 @@ \consists "Multi_measure_rest_engraver" \consists "Text_spanner_engraver" \consists "Grob_pq_engraver" + \consists "Forbid_line_break_engraver" \consists "Note_head_line_engraver" \consists "Glissando_engraver" @@ -420,7 +419,7 @@ AncientRemoveEmptyStaffContext = \translator { \consists "Break_align_engraver" \consists "Spacing_engraver" \consists "Vertical_align_engraver" - \consists "Lyric_phrasing_engraver" + \consists "Stanza_number_align_engraver" \consists "Bar_number_engraver" \consists "Span_arpeggio_engraver" diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm index 22c2b77848..1fece80f4d 100644 --- a/scm/define-context-properties.scm +++ b/scm/define-context-properties.scm @@ -187,6 +187,7 @@ selector for tab notation.") @code{instrument} property labels the staff in the first system, and the @code{instr} property labels following lines.") (instrumentEqualizer ,procedure? "[DOCUMENT-ME]") + (instrumentTransposition ,ly:pitch? "Define the transposition of the instrument. This is used to transpose the MIDI output, and @code{\\quote}s.") (instrumentSupport ,list? "list of grobs to attach instrument name to.") @@ -315,7 +316,6 @@ is a 4/4 time signature.") Switch off for cadenzas.") (tonic ,ly:pitch? "The tonic of the current scale") - (transposing ,integer? "Transpose the MIDI output. Set this property to the number of half-steps to transpose by.") (tremoloFlags ,integer? "Number of tremolo flags to add if none is specified.") diff --git a/scm/part-combiner.scm b/scm/part-combiner.scm index fcca7a56b8..a4c21b7767 100644 --- a/scm/part-combiner.scm +++ b/scm/part-combiner.scm @@ -10,6 +10,7 @@ (define-class <Voice-state> () (event-list #:init-value '() #:accessor events #:init-keyword #:events) (when-moment #:accessor when #:init-keyword #:when) + (tuning #:accessor tuning #:init-keyword #:tuning) (split-index #:accessor split-index) (vector-index) (state-vector) @@ -81,7 +82,8 @@ (map (lambda (v) (make <Voice-state> - #:when (car v) + #:when (caar v) + #:tuning (cdar v) #:events (map car (cdr v)) )) evl)))) @@ -580,8 +582,9 @@ the mark when there are no spanners active." (if (null? event-list) acc (let* - ((evs (map car (cdar event-list))) - (now (caar event-list)) + ((now-tun (caar event-list)) + (evs (map car (cdar event-list))) + (now (car now-tun)) (notes (filter (lambda (x) (equal? (ly:music-property x 'name) 'NoteEvent)) evs)) diff --git a/scripts/convert-ly.py b/scripts/convert-ly.py index 9d93613efb..f873382662 100644 --- a/scripts/convert-ly.py +++ b/scripts/convert-ly.py @@ -1938,6 +1938,38 @@ def conv (str): return str conversions.append (((2,1,26), conv, """More Scheme function renaming""")) + +def conv (str): + def subst (m): + g = string.atoi (m.group (2)) + o = g / 12 + g -= o * 12 + if g < 0: + g += 12 + o -= 1 + + + lower_pitches = filter (lambda x : x <= g, [0, 2, 4, 5, 7, 9, 11, 12]) + s = len (lower_pitches) -1 + a = g - lower_pitches [-1] + + + print s , lower_pitches, g, a, s + str = 'cdefgab' [s] + str += ['eses', 'es', '', 'is', 'isis'][a + 2] + if o < 0: + str += ',' * (-o - 1) + elif o >= 0: + str += "'" * (o + 1) + + return '\\tuning %s ' % str + + + str = re.sub (r"\\set ([A-Za-z]+\s*\.\s*)?transposing\s*=\s*#([-0-9]+)", + subst, str) + return str + +conversions.append (((2,1,26), conv, """property transposing -> tuning""")) ################################ # END OF CONVERSIONS ################################ |