From 8b500afb9431f5471e385fa2eeb8fde868e4fc49 Mon Sep 17 00:00:00 2001 From: Erik Sandberg Date: Wed, 24 May 2006 07:00:42 +0000 Subject: [PATCH] * lily/chord-tremolo-*.cc: Reworked how \repeat "tremolo" works. More work is done by iterator now, and engraver has been very much simplified. * lily/translator-group.cc: try_music is now invoked through a listener * lily/*-iterator.cc: Massive cleanups. Junked try_music_in_children globally. Renamed try_music to report_event, and made that method descend to a bottom context automatically. * lily/event-iterator.cc: New file. * lily/output-property-iterator.cc, lily/old-lyric-combine-music-iterator.cc: Removed. --- ChangeLog | 27 ++- input/regression/apply-output.ly | 4 +- input/regression/balloon.ly | 4 +- input/regression/generic-output-property.ly | 9 +- input/test/ancient-font.ly | 4 +- input/test/move-specific-text.ly | 4 +- lily/chord-tremolo-engraver.cc | 131 ++++--------- lily/chord-tremolo-iterator.cc | 100 ++++------ lily/context-def.cc | 3 +- lily/context.cc | 13 ++ lily/event-chord-iterator.cc | 18 +- lily/event-iterator.cc | 39 ++++ lily/folded-repeat-iterator.cc | 9 - lily/include/chord-tremolo-iterator.hh | 20 +- lily/include/event-chord-iterator.hh | 16 +- lily/include/event-iterator.hh | 29 +++ lily/include/folded-repeat-iterator.hh | 1 - lily/include/lily-proto.hh | 1 + lily/include/music-iterator.hh | 5 +- lily/include/music-wrapper-iterator.hh | 1 - lily/include/percent-repeat-iterator.hh | 3 - lily/include/sequential-iterator.hh | 1 - lily/include/simultaneous-music-iterator.hh | 1 - lily/include/time-scaled-music-iterator.hh | 3 - lily/include/translator-group.hh | 4 + lily/lyric-combine-music-iterator.cc | 143 ++++++++------ lily/music-iterator.cc | 39 ++-- lily/music-wrapper-iterator.cc | 6 - lily/old-lyric-combine-music-iterator.cc | 207 -------------------- lily/output-property-engraver.cc | 11 +- lily/output-property-music-iterator.cc | 37 ---- lily/part-combine-iterator.cc | 90 ++++++--- lily/percent-repeat-iterator.cc | 38 +--- lily/quote-iterator.cc | 5 +- lily/sequential-iterator.cc | 6 - lily/simple-music-iterator.cc | 2 +- lily/simultaneous-music-iterator.cc | 9 - lily/time-scaled-music-iterator.cc | 22 +-- lily/translator-group.cc | 31 ++- ly/music-functions-init.ly | 10 +- python/convertrules.py | 6 + scm/define-music-properties.scm | 3 +- scm/define-music-types.scm | 34 +--- 43 files changed, 441 insertions(+), 708 deletions(-) create mode 100644 lily/event-iterator.cc create mode 100644 lily/include/event-iterator.hh delete mode 100644 lily/old-lyric-combine-music-iterator.cc delete mode 100644 lily/output-property-music-iterator.cc diff --git a/ChangeLog b/ChangeLog index 77a7204c2e..150ba92618 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,27 @@ +2006-05-24 Erik Sandberg + + * lily/chord-tremolo-*.cc: Reworked how \repeat "tremolo" + works. More work is done by iterator now, and engraver has been + very much simplified. + + * lily/translator-group.cc: try_music is now invoked through a + listener + + * lily/*-iterator.cc: Massive cleanups. Junked + try_music_in_children globally. Renamed try_music to report_event, + and made that method descend to a bottom context automatically. + + * lily/event-iterator.cc: New file. + + * lily/output-property-iterator.cc, + lily/old-lyric-combine-music-iterator.cc: Removed. + + * python/convert-rules.py: Modified the syntax for \applyOutput. + 2006-05-23 Graham Percival - * stepmake/stepmake/texinfo-rules.make: added -E, allows - pdf doc creation. + * stepmake/stepmake/texinfo-rules.make: added -E, allows pdf doc + creation. * Documentation/user/ various: stuff that might have helped to fix the pdf creation, plus some minor doc additions. @@ -184,6 +204,9 @@ * lily/time-scaled-music-iterator.cc, lily/tuplet-engraver.cc: rework tuplets: send start/stop events to engraver + * lily/context.cc, lily/music.cc, lily/context-scheme.cc: Add + dispatchers event-source and events-below to Context + 2006-05-15 Graham Percival * Documentation/user/README.txt: update info for doc writers. diff --git a/input/regression/apply-output.ly b/input/regression/apply-output.ly index 128c07f6f0..56d5155570 100644 --- a/input/regression/apply-output.ly +++ b/input/regression/apply-output.ly @@ -1,5 +1,5 @@ -\version "2.7.39" +\version "2.9.6" \header { texidoc = "The @code{\applyOutput} expression is the most flexible way to @@ -38,7 +38,7 @@ position. \stemUp \set autoBeaming = ##f { 8 - \context Voice \applyOutput #mc-squared + \applyOutput #'Voice #mc-squared } diff --git a/input/regression/balloon.ly b/input/regression/balloon.ly index 1d0c9a7588..8f1ab2b8e9 100644 --- a/input/regression/balloon.ly +++ b/input/regression/balloon.ly @@ -3,7 +3,7 @@ texidoc = "With balloon texts, objects in the output can be marked, with lines and explanatory text added." } -\version "2.7.39" +\version "2.9.6" \layout{ ragged-right = ##t } @@ -21,7 +21,7 @@ with lines and explanatory text added." %% use predefd function. - \context Voice \applyOutput #(add-balloon-text + \applyOutput #'Voice #(add-balloon-text 'NoteHead "heads, or tails?" '(0 . -3)) diff --git a/input/regression/generic-output-property.ly b/input/regression/generic-output-property.ly index 9f94467da6..e3257d2079 100644 --- a/input/regression/generic-output-property.ly +++ b/input/regression/generic-output-property.ly @@ -1,5 +1,5 @@ -\version "2.7.39" +\version "2.9.6" \header{ texidoc=" @@ -12,15 +12,12 @@ setting the @code{extra-offset} of a grob. \relative c''{ - \context Bottom - \applyOutput #(outputproperty-compatibility + \applyOutput #'Bottom #(outputproperty-compatibility (make-type-checker 'note-head-interface) 'extra-offset '(2 . 3)) c2 c - \context Score { - \applyOutput #(outputproperty-compatibility (make-type-checker 'mark-interface) 'extra-offset '(-1 . 4)) - } + \applyOutput #'Score #(outputproperty-compatibility (make-type-checker 'mark-interface) 'extra-offset '(-1 . 4)) \mark A d1 \mark \default diff --git a/input/test/ancient-font.ly b/input/test/ancient-font.ly index cd6ccaa36c..a295c68c37 100644 --- a/input/test/ancient-font.ly +++ b/input/test/ancient-font.ly @@ -1,4 +1,4 @@ -\version "2.7.39" +\version "2.9.6" % TODO: split ancient-font into seperate files; possibly in % different locations. \header { @@ -117,7 +117,7 @@ lowerStaff = \new MensuralStaff = "lowerStaff" << % this is broken until further notice -- see refman % \override Staff.StaffSymbol #'line-count = #5 - \context Staff \applyOutput #(outputproperty-compatibility (make-type-checker 'staff-symbol-interface) 'line-count 5) + \applyOutput #'Staff #(outputproperty-compatibility (make-type-checker 'staff-symbol-interface) 'line-count 5) \transpose c c { \set autoBeaming = ##f diff --git a/input/test/move-specific-text.ly b/input/test/move-specific-text.ly index 51c25f0d57..44db4d861d 100644 --- a/input/test/move-specific-text.ly +++ b/input/test/move-specific-text.ly @@ -1,5 +1,5 @@ -\version "2.7.39" +\version "2.9.6" % possible rename to scheme- or something like that. -gp \header { texidoc = "@cindex Scheme Move Text Objects, like text, can be moved around by using some Scheme code. @@ -11,7 +11,7 @@ Objects, like text, can be moved around by using some Scheme code. \score { \relative c''' { \stemUp - \applyOutput #(outputproperty-compatibility (make-text-checker (make-simple-markup "m.d.")) + \applyOutput #'Voice #(outputproperty-compatibility (make-text-checker (make-simple-markup "m.d.")) 'extra-offset '(-3.5 . -4.5)) a^2^"m.d." } diff --git a/lily/chord-tremolo-engraver.cc b/lily/chord-tremolo-engraver.cc index dd1c040946..60800064c9 100644 --- a/lily/chord-tremolo-engraver.cc +++ b/lily/chord-tremolo-engraver.cc @@ -4,12 +4,12 @@ source file of the GNU LilyPond music typesetter (c) 2000--2006 Han-Wen Nienhuys + Erik Sandberg */ #include "math.h" // ceil #include "beam.hh" -#include "chord-tremolo-iterator.hh" #include "engraver-group.hh" #include "international.hh" #include "item.hh" @@ -39,92 +39,72 @@ create dependencies between engravers, which is bad. */ class Chord_tremolo_engraver : public Engraver { - void typeset_beam (); TRANSLATOR_DECLARATIONS (Chord_tremolo_engraver); protected: Music *repeat_; - /// moment (global time) where beam started. - Moment start_mom_; - Moment stop_mom_; int flags_; - int total_duration_flags_; + // number of beams for short tremolos + int expected_beam_count_; + // current direction of beam (first RIGHT, then LEFT) + Direction beam_dir_; - /// location within measure where beam started. - Moment beam_start_location_; - - bool body_is_sequential_; Spanner *beam_; - Spanner *finished_beam_; - Item *stem_tremolo_; protected: virtual void finalize (); virtual bool try_music (Music *); - void stop_translation_timestep (); - void start_translation_timestep (); void process_music (); DECLARE_ACKNOWLEDGER (stem); }; Chord_tremolo_engraver::Chord_tremolo_engraver () { - beam_ = finished_beam_ = 0; + beam_ = 0; repeat_ = 0; flags_ = 0; - stem_tremolo_ = 0; - body_is_sequential_ = false; + expected_beam_count_ = 0; + beam_dir_ = CENTER; } bool Chord_tremolo_engraver::try_music (Music *m) { - if (m->is_mus_type ("repeated-music") - && m->get_property ("iterator-ctor") == Chord_tremolo_iterator::constructor_proc - && !repeat_) + if (m->is_mus_type ("tremolo-span-event")) { - Moment l = m->get_length (); - repeat_ = m; - start_mom_ = now_mom (); - stop_mom_ = start_mom_ + l; - - Music *body = Repeated_music::body (m); - body_is_sequential_ = body->is_mus_type ("sequential-music"); - - int elt_count = body_is_sequential_ ? scm_ilength (body->get_property ("elements")) : 1; - - if (body_is_sequential_ && elt_count != 2) - m->origin ()->warning (_f ("expect 2 elements for chord tremolo, found %d", elt_count)); - - if (elt_count <= 0) - elt_count = 1; - - Rational total_dur = l.main_part_; - Rational note_dur = total_dur / Rational (elt_count * Repeated_music::repeat_count (repeat_)); - - total_duration_flags_ = max (0, (intlog2 (total_dur.den ()) - 2)); - - flags_ = intlog2 (note_dur.den ()) -2; - + Direction span_dir = to_dir (m->get_property ("span-direction")); + if (span_dir == START) + { + repeat_ = m; + int type = scm_to_int (m->get_property ("tremolo-type")); + /* e.g. 1 for type 8, 2 for type 16 */ + flags_ = intlog2 (type) - 2; + expected_beam_count_ = scm_to_int (m->get_property ("expected-beam-count")); + beam_dir_ = RIGHT; + } + if (span_dir == STOP) + { + repeat_ = 0; + beam_ = 0; + expected_beam_count_ = 0; + beam_dir_ = CENTER; + } return true; } - return false; } void Chord_tremolo_engraver::process_music () { - if (repeat_ && body_is_sequential_ && !beam_) + if (repeat_ && !beam_) { beam_ = make_spanner ("Beam", repeat_->self_scm ()); - beam_start_location_ = robust_scm2moment (get_property ("measurePosition"), Moment (0)); } } void Chord_tremolo_engraver::finalize () { - typeset_beam (); if (beam_) { repeat_->origin ()->warning (_ ("unterminated chord tremolo")); @@ -132,12 +112,6 @@ Chord_tremolo_engraver::finalize () } } -void -Chord_tremolo_engraver::typeset_beam () -{ - finished_beam_ = 0; -} - void Chord_tremolo_engraver::acknowledge_stem (Grob_info info) { @@ -145,13 +119,13 @@ Chord_tremolo_engraver::acknowledge_stem (Grob_info info) { Grob *s = info.grob (); - if (start_mom_ == now_mom ()) - Stem::set_beaming (s, flags_, RIGHT); - else - Stem::set_beaming (s, flags_, LEFT); + Stem::set_beaming (s, flags_, beam_dir_); if (Stem::duration_log (s) != 1) - beam_->set_property ("gap-count", scm_from_int (flags_ - total_duration_flags_)); + beam_->set_property ("gap-count", scm_from_int (flags_ - expected_beam_count_)); + + if (beam_dir_ == RIGHT) + beam_dir_ = LEFT; if (info.ultimate_music_cause ()->is_mus_type ("rhythmic-event")) Beam::add_stem (beam_, s); @@ -164,49 +138,12 @@ Chord_tremolo_engraver::acknowledge_stem (Grob_info info) ::warning (s); } } - else if (repeat_ - && flags_ - && !body_is_sequential_) - { - stem_tremolo_ = make_item ("StemTremolo", repeat_->self_scm ()); - stem_tremolo_->set_property ("flag-count", - scm_from_int (flags_)); - stem_tremolo_->set_object ("stem", - info.grob ()->self_scm ()); - stem_tremolo_->set_parent (info.grob (), X_AXIS); - info.grob ()->set_object ("tremolo-flag", stem_tremolo_->self_scm ()); - } -} - -void -Chord_tremolo_engraver::start_translation_timestep () -{ - if (beam_ && stop_mom_ == now_mom ()) - { - finished_beam_ = beam_; - repeat_ = 0; - beam_ = 0; - } -} - -void -Chord_tremolo_engraver::stop_translation_timestep () -{ - if (stem_tremolo_) - { - repeat_ = 0; - if (beam_) - programming_error ("beam and stem tremolo?"); - stem_tremolo_ = 0; - } - - typeset_beam (); } ADD_ACKNOWLEDGER (Chord_tremolo_engraver, stem); ADD_TRANSLATOR (Chord_tremolo_engraver, - /* doc */ "Generates beams for tremolo repeats.", + /* doc */ "Generates beams for tremolo repeats.", /* create */ "Beam", - /* accept */ "repeated-music", + /* accept */ "tremolo-span-event", /* read */ "", /* write */ ""); diff --git a/lily/chord-tremolo-iterator.cc b/lily/chord-tremolo-iterator.cc index b6f1c4f69a..45ddbc443d 100644 --- a/lily/chord-tremolo-iterator.cc +++ b/lily/chord-tremolo-iterator.cc @@ -4,82 +4,66 @@ source file of the GNU LilyPond music typesetter (c) 2000--2006 Han-Wen Nienhuys + Erik Sandberg */ #include "chord-tremolo-iterator.hh" #include "input.hh" #include "international.hh" +#include "misc.hh" #include "repeated-music.hh" -void -Chord_tremolo_iterator::construct_children () -{ - Music *m = get_music (); - - factor_ = Moment (Rational (1, 1)); - child_iter_ = unsmob_iterator (get_iterator (Repeated_music::body (m))); -} - Chord_tremolo_iterator::Chord_tremolo_iterator () { - factor_ = 1; - child_iter_ = 0; -} - -void -Chord_tremolo_iterator::do_quit () -{ - if (child_iter_) - child_iter_->quit (); -} - -void -Chord_tremolo_iterator::derived_mark () const -{ - if (child_iter_) - scm_gc_mark (child_iter_->self_scm ()); } -void -Chord_tremolo_iterator::derived_substitute (Context *f, Context *t) +SCM +Chord_tremolo_iterator::get_music_list () const { - if (child_iter_) - child_iter_->substitute_outlet (f, t); -} + Music *mus = get_music (); + Input *origin = mus->origin (); + Moment l = mus->get_length (); + Music *body = Repeated_music::body (mus); + bool body_is_sequential = body->is_mus_type ("sequential-music"); -void -Chord_tremolo_iterator::process (Moment m) -{ - if (!m.to_bool ()) - { - Music_iterator *yeah = try_music (get_music ()); - if (yeah) - set_context (yeah->get_outlet ()); - else - get_music ()->origin ()->warning (_ ("no one to print a tremolos")); - } + int elt_count = body_is_sequential ? scm_ilength (body->get_property ("elements")) : 1; - child_iter_->process (factor_ * m); -} + if (body_is_sequential && elt_count != 2) + mus->origin ()->warning (_f ("expect 2 elements for chord tremolo, found %d", elt_count)); -Moment -Chord_tremolo_iterator::pending_moment () const -{ - return child_iter_->pending_moment () / factor_; -} + if (elt_count <= 0) + elt_count = 1; + + Rational total_dur = l.main_part_; + Rational note_dur = total_dur / Rational (elt_count * Repeated_music::repeat_count (mus)); -bool -Chord_tremolo_iterator::ok () const -{ - return child_iter_ && child_iter_->ok (); -} + SCM tremolo_type = scm_int2num (note_dur.den ()); + int expected_beaming_ = max (0, (intlog2 (total_dur.den ()) - 2)); -Music_iterator * -Chord_tremolo_iterator::try_music_in_children (Music *m) const -{ - return child_iter_->try_music (m); + if (elt_count == 1) + { + Music *ev = make_music_by_name (ly_symbol2scm ("TremoloEvent")); + ev->set_spot (*origin); + ev->set_property ("tremolo-type", tremolo_type); + return scm_list_2 (ev->unprotect (), body->self_scm ()); + } + else + { + SCM tremolo_symbol = ly_symbol2scm ("TremoloSpanEvent"); + SCM start_event_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tremolo_symbol, scm_from_int (START)); + unsmob_music (start_event_scm)->set_spot (*origin); + SCM stop_event_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tremolo_symbol, scm_from_int (STOP)); + + Music *start_event = unsmob_music (start_event_scm); + Music *stop_event = unsmob_music (stop_event_scm); + start_event->set_spot (*origin); + stop_event->set_spot (*origin); + start_event->set_property ("tremolo-type", tremolo_type); + start_event->set_property ("expected-beam-count", scm_int2num (expected_beaming_)); + + return scm_list_3 (start_event_scm, body->self_scm (), stop_event_scm); + } } IMPLEMENT_CTOR_CALLBACK (Chord_tremolo_iterator); - diff --git a/lily/context-def.cc b/lily/context-def.cc index 05363e498c..fee67b661d 100644 --- a/lily/context-def.cc +++ b/lily/context-def.cc @@ -344,9 +344,8 @@ Context_def::instantiate (SCM ops, Object_key const *key) else if (dynamic_cast (g)) g->simple_trans_list_ = filter_engravers (g->simple_trans_list_); - g->context_ = context; context->aliases_ = context_aliases_; - + g->connect_to_context (context); g->unprotect (); context->accepts_list_ = get_accepted (ops); diff --git a/lily/context.cc b/lily/context.cc index 010e07798b..5e97a6171d 100644 --- a/lily/context.cc +++ b/lily/context.cc @@ -660,3 +660,16 @@ set_context_property_on_children (Context *trans, SCM sym, SCM val) set_context_property_on_children (trg, sym, ly_deep_copy (val)); } } + +bool +melisma_busy (Context *tr) +{ + SCM melisma_properties = tr->get_property ("melismaBusyProperties"); + bool busy = false; + + for (; scm_is_pair (melisma_properties); + melisma_properties = scm_cdr (melisma_properties)) + busy = busy || to_boolean (tr->internal_get_property (scm_car (melisma_properties))); + + return busy; +} diff --git a/lily/event-chord-iterator.cc b/lily/event-chord-iterator.cc index 2b1441a275..60e7e3081a 100644 --- a/lily/event-chord-iterator.cc +++ b/lily/event-chord-iterator.cc @@ -20,22 +20,11 @@ Event_chord_iterator::Event_chord_iterator () { } -Context * -Event_chord_iterator::get_bottom_context () -{ - assert (get_outlet ()); - if (get_outlet ()->is_bottom_context ()) - return get_outlet (); - - set_context (get_outlet ()->get_default_interpreter ()); - return get_outlet (); -} - void Event_chord_iterator::construct_children () { Simple_music_iterator::construct_children (); - get_bottom_context (); + descend_to_bottom_context (); } void @@ -47,10 +36,7 @@ Event_chord_iterator::process (Moment m) scm_is_pair (s); s = scm_cdr (s)) { Music *mus = unsmob_music (scm_car (s)); - - bool gotcha = try_music (mus); - if (!gotcha) - mus->origin ()->warning (_f ("junking event: `%s'", mus->name ())); + report_event (mus); } } Simple_music_iterator::process (m); diff --git a/lily/event-iterator.cc b/lily/event-iterator.cc new file mode 100644 index 0000000000..8e6d6df26d --- /dev/null +++ b/lily/event-iterator.cc @@ -0,0 +1,39 @@ +/* + event-chord-iterator.cc -- implement Event_chord_iterator + + source file of the GNU LilyPond music typesetter + + (c) 1997--2006 Han-Wen Nienhuys +*/ + +#include "event-iterator.hh" + +#include "context.hh" +#include "duration.hh" +#include "input.hh" +#include "international.hh" +#include "music.hh" +#include "pitch.hh" +#include "warn.hh" + +Event_iterator::Event_iterator () +{ +} + +void +Event_iterator::construct_children () +{ + descend_to_bottom_context (); + Simple_music_iterator::construct_children (); +} + +void +Event_iterator::process (Moment m) +{ + if (last_processed_mom_ < Moment (0)) + report_event (get_music ()); + + Simple_music_iterator::process (m); +} + +IMPLEMENT_CTOR_CALLBACK (Event_iterator); diff --git a/lily/folded-repeat-iterator.cc b/lily/folded-repeat-iterator.cc index 6465f3399a..1a4de7c369 100644 --- a/lily/folded-repeat-iterator.cc +++ b/lily/folded-repeat-iterator.cc @@ -107,15 +107,6 @@ Folded_repeat_iterator::enter_alternative () } } -Music_iterator * -Folded_repeat_iterator::try_music_in_children (Music *m) const -{ - if (main_iter_) - return main_iter_->try_music (m); - if (alternative_iter_) - return alternative_iter_->try_music (m); - return 0; -} void Folded_repeat_iterator::derived_mark () const { diff --git a/lily/include/chord-tremolo-iterator.hh b/lily/include/chord-tremolo-iterator.hh index 12c12607f1..d1d407dd1f 100644 --- a/lily/include/chord-tremolo-iterator.hh +++ b/lily/include/chord-tremolo-iterator.hh @@ -9,28 +9,18 @@ #ifndef CHORD_TREMOLO_ITERATOR_HH #define CHORD_TREMOLO_ITERATOR_HH -#include "music-iterator.hh" +#include "sequential-iterator.hh" -class Chord_tremolo_iterator : public Music_iterator +class Chord_tremolo_iterator : public Sequential_iterator { public: - DECLARE_CLASSNAME(Chord_tremolo_iterator); DECLARE_SCHEME_CALLBACK (constructor, ()); + /* construction */ + DECLARE_CLASSNAME(Chord_tremolo_iterator); Chord_tremolo_iterator (); - Chord_tremolo_iterator (Chord_tremolo_iterator const &); protected: - virtual void derived_substitute (Context *f, Context *t); - - virtual void derived_mark () const; - virtual Moment pending_moment () const; - virtual void do_quit (); - virtual void construct_children (); - virtual bool ok () const; - virtual void process (Moment); - virtual Music_iterator *try_music_in_children (Music *) const; + virtual SCM get_music_list () const; private: - Moment factor_; - Music_iterator *child_iter_; }; #endif /* CHORD_TREMOLO_ITERATOR_HH */ diff --git a/lily/include/event-chord-iterator.hh b/lily/include/event-chord-iterator.hh index 5dd293038f..a252e871fe 100644 --- a/lily/include/event-chord-iterator.hh +++ b/lily/include/event-chord-iterator.hh @@ -1,13 +1,13 @@ /* - event-iter.hh -- declare Event_chord_iterator + event-chord-iterator.hh -- declare Event_chord_iterator source file of the GNU LilyPond music typesetter (c) 1997--2006 Han-Wen Nienhuys */ -#ifndef EVENT_ITER_HH -#define EVENT_ITER_HH +#ifndef EVENT_CHORD_ITERATOR_HH +#define EVENT_CHORD_ITERATOR_HH #include "simple-music-iterator.hh" @@ -19,16 +19,8 @@ class Event_chord_iterator : public Simple_music_iterator /** Find a bottom notation context to deliver events to. */ - virtual Context *get_bottom_context (); DECLARE_CLASSNAME(Event_chord_iterator); - /* - Since Event_chord_iterator has no list-cursor internally, we - must use a status variable to adminstrate where we are */ - - enum { NONE_DONE, START_DONE, END_DONE } - status_; - public: DECLARE_SCHEME_CALLBACK (constructor, ()); Event_chord_iterator (); @@ -39,4 +31,4 @@ protected: virtual void construct_children (); }; -#endif // EVENT_ITER_HH +#endif // EVENT_CHORD_ITERATOR_HH diff --git a/lily/include/event-iterator.hh b/lily/include/event-iterator.hh new file mode 100644 index 0000000000..ce2809c8ea --- /dev/null +++ b/lily/include/event-iterator.hh @@ -0,0 +1,29 @@ +/* + event-iter.hh -- declare Event_chord_iterator + + source file of the GNU LilyPond music typesetter + + (c) 2006 Han-Wen Nienhuys + Erik Sandberg +*/ + +#ifndef EVENT_ITERATOR_HH +#define EVENT_ITERATOR_HH + +#include "simple-music-iterator.hh" + +class Event_iterator : public Simple_music_iterator +{ + DECLARE_CLASSNAME(Event_iterator); + +public: + DECLARE_SCHEME_CALLBACK (constructor, ()); + Event_iterator (); + Event_iterator (Event_iterator const &); + virtual void construct_children (); + +protected: + virtual void process (Moment); +}; + +#endif // EVENT_ITERATOR_HH diff --git a/lily/include/folded-repeat-iterator.hh b/lily/include/folded-repeat-iterator.hh index 2d52a5cc84..239b7941f0 100644 --- a/lily/include/folded-repeat-iterator.hh +++ b/lily/include/folded-repeat-iterator.hh @@ -36,7 +36,6 @@ protected: void leave_body (); virtual void process (Moment); - virtual Music_iterator *try_music_in_children (Music *) const; private: Music_iterator *main_iter_; diff --git a/lily/include/lily-proto.hh b/lily/include/lily-proto.hh index d0410c7ae2..58e7cb4c84 100644 --- a/lily/include/lily-proto.hh +++ b/lily/include/lily-proto.hh @@ -51,6 +51,7 @@ class Engraver_group; class Event; class Event_chord; class Event_chord_iterator; +class Event_iterator; class Folded_repeat_iterator; class Font_metric; class Font_size_engraver; diff --git a/lily/include/music-iterator.hh b/lily/include/music-iterator.hh index 0b738aa0b3..3c62205b90 100644 --- a/lily/include/music-iterator.hh +++ b/lily/include/music-iterator.hh @@ -61,13 +61,14 @@ public: Moment music_get_length () const; Moment music_start_mom () const; Music_iterator (); - Music_iterator *try_music (Music *) const; + void report_event (Music *); Context *get_outlet () const; void set_context (Context *); static SCM get_static_get_iterator (Music *mus); void init_translator (Music *, Context *); void quit (); void substitute_outlet (Context *from, Context *to); + void descend_to_bottom_context (); virtual void derived_substitute (Context *, Context *); virtual Moment pending_moment () const; virtual bool ok () const; @@ -78,8 +79,6 @@ public: DECLARE_SCHEME_CALLBACK (constructor, ()); SCM get_iterator (Music *) const; - virtual Music_iterator *try_music_in_children (Music *) const; - Music *get_music () const; protected: virtual void do_quit (); diff --git a/lily/include/music-wrapper-iterator.hh b/lily/include/music-wrapper-iterator.hh index 41ede2711e..d249428654 100644 --- a/lily/include/music-wrapper-iterator.hh +++ b/lily/include/music-wrapper-iterator.hh @@ -33,7 +33,6 @@ public: virtual bool run_always () const; protected: virtual void process (Moment); - virtual Music_iterator *try_music_in_children (Music *) const; Music_iterator *child_iter_; }; diff --git a/lily/include/percent-repeat-iterator.hh b/lily/include/percent-repeat-iterator.hh index 7c510cd7ad..8637d9f7ae 100644 --- a/lily/include/percent-repeat-iterator.hh +++ b/lily/include/percent-repeat-iterator.hh @@ -19,10 +19,7 @@ public: Percent_repeat_iterator (); protected: virtual SCM get_music_list () const; - virtual void derived_mark () const; - virtual void construct_children (); private: - SCM child_list_; }; #endif /* PERCENT_REPEAT_ITERATOR_HH */ diff --git a/lily/include/sequential-iterator.hh b/lily/include/sequential-iterator.hh index 5015fb9a6a..124461d997 100644 --- a/lily/include/sequential-iterator.hh +++ b/lily/include/sequential-iterator.hh @@ -33,7 +33,6 @@ public: protected: virtual void process (Moment); - virtual Music_iterator *try_music_in_children (Music *) const; virtual bool run_always () const; protected: diff --git a/lily/include/simultaneous-music-iterator.hh b/lily/include/simultaneous-music-iterator.hh index e98bc6feb2..ae318f478b 100644 --- a/lily/include/simultaneous-music-iterator.hh +++ b/lily/include/simultaneous-music-iterator.hh @@ -32,7 +32,6 @@ public: protected: virtual void process (Moment); - virtual Music_iterator *try_music_in_children (Music *) const; private: SCM children_list_; diff --git a/lily/include/time-scaled-music-iterator.hh b/lily/include/time-scaled-music-iterator.hh index 34bd50cf6f..f2b3d0bd18 100644 --- a/lily/include/time-scaled-music-iterator.hh +++ b/lily/include/time-scaled-music-iterator.hh @@ -21,10 +21,7 @@ public: Time_scaled_music_iterator (); protected: virtual SCM get_music_list () const; - virtual void derived_mark () const; - virtual void construct_children (); private: - SCM child_list_; }; #endif /* TIME_SCALED_MUSIC_ITERATOR_HH */ diff --git a/lily/include/translator-group.hh b/lily/include/translator-group.hh index 9a6940ac06..3bb6b4255f 100644 --- a/lily/include/translator-group.hh +++ b/lily/include/translator-group.hh @@ -9,6 +9,7 @@ #ifndef TRANSLATOR_GROUP_HH #define TRANSLATOR_GROUP_HH +#include "listener.hh" #include "translator.hh" #include "std-vector.hh" @@ -46,11 +47,14 @@ private: Translator_group_void_method precomputed_self_method_bindings_[TRANSLATOR_METHOD_PRECOMPUTE_COUNT]; + DECLARE_LISTENER (eat_event); + public: VIRTUAL_COPY_CONSTRUCTOR (Translator_group, Translator_group); DECLARE_SMOBS (Translator_group, dummy); public: + void connect_to_context (Context *c); virtual Translator_group *get_daddy_translator ()const; virtual SCM get_simple_trans_list (); virtual bool try_music (Music *req); diff --git a/lily/lyric-combine-music-iterator.cc b/lily/lyric-combine-music-iterator.cc index f812d1c952..feb18d6559 100644 --- a/lily/lyric-combine-music-iterator.cc +++ b/lily/lyric-combine-music-iterator.cc @@ -7,9 +7,12 @@ */ #include "context.hh" +#include "dispatcher.hh" +#include "global-context.hh" #include "grob.hh" #include "input.hh" #include "international.hh" +#include "listener.hh" #include "music-iterator.hh" #include "music.hh" @@ -24,69 +27,82 @@ protected: virtual Moment pending_moment () const; virtual void do_quit (); virtual void process (Moment); - virtual Music_iterator *try_music_in_children (Music *) const; virtual bool run_always ()const; virtual bool ok () const; virtual void derived_mark () const; virtual void derived_substitute (Context *, Context *); + void set_music_context (Context *to); private: bool start_new_syllable (); - void find_voice (); + Context *find_voice (); + DECLARE_LISTENER (set_busy); + DECLARE_LISTENER (check_new_context); bool pending_grace_lyric_; bool music_found_; - bool made_association_; Context *lyrics_context_; Context *music_context_; SCM lyricsto_voice_name_; + bool busy_; Music_iterator *lyric_iter_; }; -/* - Ugh; this is a hack, let's not export this hack, so static. -*/ -static Music *busy_ev; -static Music *start_ev; -static Music *melisma_playing_ev; - Lyric_combine_music_iterator::Lyric_combine_music_iterator () { music_found_ = false; - made_association_ = false; pending_grace_lyric_ = false; lyric_iter_ = 0; music_context_ = 0; lyrics_context_ = 0; + busy_ = false; +} - /* - Ugh. out of place here. - */ - if (!busy_ev) +IMPLEMENT_LISTENER (Lyric_combine_music_iterator, set_busy) +void +Lyric_combine_music_iterator::set_busy (SCM se) +{ + Stream_event *e = unsmob_stream_event (se); + SCM mus = e->get_property ("music"); + Music *m = unsmob_music (mus); + assert (m); + + if (m->is_mus_type ("note-event") || m->is_mus_type ("cluster-note-event")) + busy_ = true; +} + +void +Lyric_combine_music_iterator::set_music_context (Context *to) +{ + if (music_context_) + { + music_context_->event_source()->remove_listener (GET_LISTENER (set_busy), ly_symbol2scm ("MusicEvent")); + lyrics_context_->unset_property (ly_symbol2scm ("associatedVoiceContext")); + } + music_context_ = to; + if (to) { - busy_ev - = make_music_by_name (ly_symbol2scm ("BusyPlayingEvent")); - start_ev - = make_music_by_name (ly_symbol2scm ("StartPlayingEvent")); - melisma_playing_ev - = make_music_by_name (ly_symbol2scm ("MelismaPlayingEvent")); + to->event_source()->add_listener (GET_LISTENER (set_busy), ly_symbol2scm ("MusicEvent")); + lyrics_context_->set_property ("associatedVoiceContext", to->self_scm ()); } } bool Lyric_combine_music_iterator::start_new_syllable () { - bool b = music_context_->try_music (busy_ev); - - if (!b) + if (!busy_) return false; + busy_ = false; + + scm_display (music_context_->now_mom().smobbed_copy(), scm_current_output_port ()); + if (!lyrics_context_) return false; if (!to_boolean (lyrics_context_->get_property ("ignoreMelismata"))) { - bool m = music_context_->try_music (melisma_playing_ev); + bool m = melisma_busy (music_context_); if (m) return false; } @@ -135,7 +151,7 @@ Lyric_combine_music_iterator::derived_substitute (Context *f, Context *t) if (lyrics_context_ && lyrics_context_ == f) lyrics_context_ = t; if (music_context_ && music_context_ == f) - music_context_ = t; + set_music_context (t); } void @@ -143,14 +159,25 @@ Lyric_combine_music_iterator::construct_children () { Music *m = unsmob_music (get_music ()->get_property ("element")); lyric_iter_ = unsmob_iterator (get_iterator (m)); + if (!lyric_iter_) + return; + lyrics_context_ = find_context_below (lyric_iter_->get_outlet (), + ly_symbol2scm ("Lyrics"), ""); lyricsto_voice_name_ = get_music ()->get_property ("associated-context"); - find_voice (); - - if (lyric_iter_) - lyrics_context_ = find_context_below (lyric_iter_->get_outlet (), - ly_symbol2scm ("Lyrics"), ""); + Context *voice = find_voice (); + if (voice) + set_music_context (voice); + else + { + /* + Wait for a Create_context event. If this isn't done, lyrics can be + delayed when voices are created implicitly. + */ + Global_context *g = lyrics_context_->get_global_context (); + g->events_below ()->add_listener (GET_LISTENER (check_new_context), ly_symbol2scm ("CreateContext")); + } /* We do not create a Lyrics context, because the user might @@ -159,7 +186,27 @@ Lyric_combine_music_iterator::construct_children () */ } +IMPLEMENT_LISTENER (Lyric_combine_music_iterator, check_new_context) void +Lyric_combine_music_iterator::check_new_context (SCM sev) +{ + // TODO: Check first if type=Voice and if id matches + (void)sev; + + Context *voice = find_voice (); + if (voice) + { + set_music_context (voice); + + Global_context *g = voice->get_global_context (); + g->events_below ()->remove_listener (GET_LISTENER (check_new_context), ly_symbol2scm ("CreateContext")); + } +} + +/* +Look for a suitable voice to align lyrics to. +*/ +Context * Lyric_combine_music_iterator::find_voice () { SCM voice_name = lyricsto_voice_name_; @@ -173,40 +220,20 @@ Lyric_combine_music_iterator::find_voice () if (scm_is_string (voice_name) && (!music_context_ || ly_scm2string (voice_name) != music_context_->id_string ())) { - /* - (spaghettini). - - Need to set associatedVoiceContext again - */ - if (music_context_) - made_association_ = false; - Context *t = get_outlet (); while (t && t->get_parent_context ()) t = t->get_parent_context (); string name = ly_scm2string (voice_name); - Context *voice = find_context_below (t, ly_symbol2scm ("Voice"), name); - - if (voice) - music_context_ = voice; + return find_context_below (t, ly_symbol2scm ("Voice"), name); } - if (lyrics_context_ && music_context_) - { - if (!made_association_) - { - made_association_ = true; - lyrics_context_->set_property ("associatedVoiceContext", - music_context_->self_scm ()); - } - } + return 0; } void -Lyric_combine_music_iterator::process (Moment mom) +Lyric_combine_music_iterator::process (Moment) { - (void) mom; find_voice (); if (!music_context_) return; @@ -220,7 +247,7 @@ Lyric_combine_music_iterator::process (Moment mom) if (lyrics_context_) lyrics_context_->unset_property (ly_symbol2scm ("associatedVoiceContext")); lyric_iter_ = 0; - music_context_ = 0; + set_music_context (0); } if (music_context_ @@ -261,10 +288,4 @@ Lyric_combine_music_iterator::do_quit () lyric_iter_->quit (); } -Music_iterator * -Lyric_combine_music_iterator::try_music_in_children (Music *m) const -{ - return lyric_iter_->try_music (m); -} - IMPLEMENT_CTOR_CALLBACK (Lyric_combine_music_iterator); diff --git a/lily/music-iterator.cc b/lily/music-iterator.cc index 528fffb682..fcfd2fc1f4 100644 --- a/lily/music-iterator.cc +++ b/lily/music-iterator.cc @@ -14,6 +14,9 @@ using namespace std; #include "warn.hh" #include "context.hh" +#include "event-iterator.hh" +#include "input.hh" +#include "international.hh" #include "music-wrapper.hh" #include "music-wrapper-iterator.hh" #include "simple-music-iterator.hh" @@ -85,6 +88,8 @@ Music_iterator::get_static_get_iterator (Music *m) { if (dynamic_cast (m)) p = new Music_wrapper_iterator; + else if (m->is_mus_type ("event")) + p = new Event_iterator; else p = new Simple_music_iterator; @@ -146,30 +151,24 @@ Music_iterator::get_iterator (Music *m) const return ip; } -/* - TODO: rename to prevent confusion between Context::try_music and - Iterator::try_music -*/ -Music_iterator * -Music_iterator::try_music (Music *m) const +/* Descend to a bottom context; implicitly create a new one if necessary */ +void +Music_iterator::descend_to_bottom_context () { - bool b = get_outlet ()->try_music ((Music *)m); // ugh - Music_iterator *it = b ? (Music_iterator *) this : 0; // ugh - if (!it) - it = try_music_in_children (m); - else - /* TODO: try_music should only do the following: - - descend iterator to bottom context - - send music to a bottom context. - The function should also be renamed, and it should not return a value. */ - m->send_to_context (get_outlet ()); - return it; + assert (get_outlet ()); + if (!get_outlet ()->is_bottom_context ()) + set_context (get_outlet ()->get_default_interpreter ()); } -Music_iterator * -Music_iterator::try_music_in_children (Music *) const +void +Music_iterator::report_event (Music *m) { - return 0; + descend_to_bottom_context (); + + if (!m->is_mus_type ("event")) + m->origin ()->warning (_f ("Sending non-event to context")); + + m->send_to_context (get_outlet ()); } IMPLEMENT_CTOR_CALLBACK (Music_iterator); diff --git a/lily/music-wrapper-iterator.cc b/lily/music-wrapper-iterator.cc index 643d30f024..c50a64c7c1 100644 --- a/lily/music-wrapper-iterator.cc +++ b/lily/music-wrapper-iterator.cc @@ -60,12 +60,6 @@ Music_wrapper_iterator::pending_moment () const return child_iter_->pending_moment (); } -Music_iterator * -Music_wrapper_iterator::try_music_in_children (Music *m) const -{ - return child_iter_->try_music (m); -} - IMPLEMENT_CTOR_CALLBACK (Music_wrapper_iterator); bool diff --git a/lily/old-lyric-combine-music-iterator.cc b/lily/old-lyric-combine-music-iterator.cc deleted file mode 100644 index d1f68cc508..0000000000 --- a/lily/old-lyric-combine-music-iterator.cc +++ /dev/null @@ -1,207 +0,0 @@ -/* - lyric-combine-music-iterator.cc -- implement Old_lyric_combine_music_iterator - - source file of the GNU LilyPond music typesetter - - (c) 1999--2006 Han-Wen Nienhuys -*/ - -#include "context.hh" -#include "music.hh" -#include "note-head.hh" -#include "grob.hh" -#include "music-iterator.hh" - -class Old_lyric_combine_music_iterator : public Music_iterator -{ -public: - Old_lyric_combine_music_iterator (); - Old_lyric_combine_music_iterator (Old_lyric_combine_music_iterator const &src); - DECLARE_SCHEME_CALLBACK (constructor, ()); -protected: - virtual void construct_children (); - virtual Moment pending_moment () const; - virtual void do_quit (); - virtual void process (Moment); - virtual Music_iterator *try_music_in_children (Music *) const; - - virtual bool ok () const; - virtual void derived_mark () const; - virtual void derived_substitute (Context *, Context *); -private: - bool get_busy_status () const; - bool melisma_busy (); - Music *get_combine_lyrics () const; - Music *get_combine_music () const; - - Music_iterator *music_iter_; - Music_iterator *lyric_iter_; -}; - -bool -melisma_busy (Context *tr) -{ - SCM melisma_properties = tr->get_property ("melismaBusyProperties"); - bool busy = false; - - for (; scm_is_pair (melisma_properties); - melisma_properties = scm_cdr (melisma_properties)) - busy = busy || to_boolean (tr->internal_get_property (scm_car (melisma_properties))); - - return busy; -} - -/* - Ugh, why static? -*/ -Music *busy_req; -Music *melisma_playing_req; - -Old_lyric_combine_music_iterator::Old_lyric_combine_music_iterator () -{ - music_iter_ = 0; - lyric_iter_ = 0; - - if (!busy_req) - { - busy_req - = make_music_by_name (ly_symbol2scm ("BusyPlayingEvent")); - melisma_playing_req - = make_music_by_name (ly_symbol2scm ("MelismaPlayingEvent")); - } -} - -Moment -Old_lyric_combine_music_iterator::pending_moment () const -{ - Moment musnext = music_iter_->pending_moment (); - return musnext; -} - -bool -Old_lyric_combine_music_iterator::ok () const -{ - return music_iter_->ok (); -} - -void -Old_lyric_combine_music_iterator::derived_mark ()const -{ - if (music_iter_) - scm_gc_mark (music_iter_->self_scm ()); - if (lyric_iter_) - scm_gc_mark (lyric_iter_->self_scm ()); -} - -void -Old_lyric_combine_music_iterator::derived_substitute (Context *f, Context *t) -{ - if (music_iter_) - music_iter_->substitute_outlet (f, t); - if (lyric_iter_) - lyric_iter_->substitute_outlet (f, t); -} - -Music * -Old_lyric_combine_music_iterator::get_combine_music () const -{ - SCM l = get_music ()->get_property ("elements"); - if (!scm_is_pair (l)) - return 0; - return unsmob_music (scm_car (l)); -} - -Music * -Old_lyric_combine_music_iterator::get_combine_lyrics () const -{ - SCM l = get_music ()->get_property ("elements"); - if (!scm_is_pair (l)) - return 0; - l = scm_cdr (l); - if (!scm_is_pair (l)) - return 0; - return unsmob_music (scm_car (l)); -} - -void -Old_lyric_combine_music_iterator::construct_children () -{ - music_iter_ = unsmob_iterator (get_iterator (get_combine_music ())); - lyric_iter_ = unsmob_iterator (get_iterator (get_combine_lyrics ())); -} - -bool -Old_lyric_combine_music_iterator::get_busy_status () const -{ - /* - We have to use both the event and the busyGrobs queue. The - busyGrobs queue doesn't contain any notes that have started this - instant. */ - if (try_music (busy_req)) - return true; - - Context *tr = music_iter_->get_outlet (); - - SCM grobs = tr->get_property ("busyGrobs"); - Moment now = tr->now_mom (); - for (; scm_is_pair (grobs); grobs = scm_cdr (grobs)) - { - SCM grob = scm_cdar (grobs); - Moment end = *unsmob_moment (scm_caar (grobs)); - - /* - This is slightly ugh: we are now confunding the frontend - (iterators) and the backend (note heads) */ - if (end > now - && Note_head::has_interface (unsmob_grob (grob))) - return true; - } - - return false; -} - -bool -Old_lyric_combine_music_iterator::melisma_busy () -{ - /* We cannot read the property, since music_iter_->get_outlet () might - not be the context that sets the melisma properties, but rather a - parent context. */ - return music_iter_->try_music (melisma_playing_req); -} - -void -Old_lyric_combine_music_iterator::process (Moment m) -{ - Moment my_next = music_iter_->pending_moment (); - if (my_next > m) - return; - - music_iter_->process (m); - - if (get_busy_status () && !melisma_busy () && lyric_iter_->ok ()) - { - Moment m = lyric_iter_->pending_moment (); - lyric_iter_->process (m); - } -} - -void -Old_lyric_combine_music_iterator::do_quit () -{ - if (music_iter_) - music_iter_->quit (); - if (lyric_iter_) - lyric_iter_->quit (); -} - -Music_iterator * -Old_lyric_combine_music_iterator::try_music_in_children (Music *m) const -{ - Music_iterator *i = music_iter_->try_music (m); - if (i) - return i; - else - return lyric_iter_->try_music (m); -} - -IMPLEMENT_CTOR_CALLBACK (Old_lyric_combine_music_iterator); diff --git a/lily/output-property-engraver.cc b/lily/output-property-engraver.cc index 74ee449411..7f59d44430 100644 --- a/lily/output-property-engraver.cc +++ b/lily/output-property-engraver.cc @@ -31,8 +31,15 @@ Output_property_engraver::try_music (Music* m) { if (m->is_mus_type ("layout-instruction")) { - props_.push_back (m); - return true; + /* + UGH. Only swallow the output property event in the context + it was intended for. This is inelegant but not inefficient. + */ + if (context ()->is_alias (m->get_property ("context-type"))) + { + props_.push_back (m); + return true; + } } return false; } diff --git a/lily/output-property-music-iterator.cc b/lily/output-property-music-iterator.cc deleted file mode 100644 index a08b88413c..0000000000 --- a/lily/output-property-music-iterator.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - output-property-music-iterator.cc -- implement Output_property_music_iterator - - source file of the GNU LilyPond music typesetter - - (c) 2000--2006 Jan Nieuwenhuizen - */ - -#include "simple-music-iterator.hh" - -#include "input.hh" -#include "international.hh" -#include "music.hh" - -class Output_property_music_iterator : public Simple_music_iterator -{ -public: - DECLARE_SCHEME_CALLBACK (constructor, ()); -protected: - virtual void process (Moment); -}; - - -void -Output_property_music_iterator::process (Moment m) -{ - if (last_processed_mom_ < Moment (0)) - { - bool accepted = try_music (get_music ()); - if (!accepted) - get_music ()->origin ()->warning (_f ("junking event: `%s'", - get_music ()->class_name ())); - } - Simple_music_iterator::process (m); -} - -IMPLEMENT_CTOR_CALLBACK (Output_property_music_iterator); diff --git a/lily/part-combine-iterator.cc b/lily/part-combine-iterator.cc index caa6c73aa8..65c7f1aac9 100644 --- a/lily/part-combine-iterator.cc +++ b/lily/part-combine-iterator.cc @@ -7,11 +7,13 @@ */ #include "context.hh" +#include "dispatcher.hh" +#include "lily-guile.hh" +#include "listener.hh" #include "music.hh" +#include "music-iterator.hh" #include "music-sequence.hh" -#include "lily-guile.hh" #include "warn.hh" -#include "music-iterator.hh" class Part_combine_iterator : public Music_iterator { @@ -29,11 +31,16 @@ protected: virtual void do_quit (); virtual void process (Moment); - virtual Music_iterator *try_music_in_children (Music *) const; - virtual bool ok () const; private: + /* used by try_process */ + DECLARE_LISTENER (set_busy); + bool busy_; + bool notice_busy_; + + bool try_process (Music_iterator *i, Moment m); + Music_iterator *first_iter_; Music_iterator *second_iter_; Moment start_moment_; @@ -77,8 +84,6 @@ private: void unisono (bool silent); }; -static Music *busy_playing_event; - void Part_combine_iterator::do_quit () { @@ -101,12 +106,6 @@ Part_combine_iterator::Part_combine_iterator () split_list_ = SCM_EOL; state_ = APART; playing_state_ = APART; - - if (!busy_playing_event) - { - busy_playing_event - = make_music_by_name (ly_symbol2scm ("BusyPlayingEvent")); - } } void @@ -169,7 +168,7 @@ Part_combine_iterator::kill_mmrest (Context *tg) mmrest->set_property ("duration", SCM_EOL); } - tg->try_music (mmrest); + mmrest->send_to_context (tg); } void @@ -192,7 +191,7 @@ Part_combine_iterator::solo1 () if (!event) event = make_music_by_name (ly_symbol2scm ("SoloOneEvent")); - first_iter_->try_music_in_children (event); + event->send_to_context (first_iter_->get_outlet ()); } playing_state_ = SOLO1; } @@ -255,8 +254,9 @@ Part_combine_iterator::unisono (bool silent) if (!event) event = make_music_by_name (ly_symbol2scm ("UnisonoEvent")); - (last_playing_ == SOLO2 ? second_iter_ : first_iter_) - ->try_music_in_children (event); + Context *out = (last_playing_ == SOLO2 ? second_iter_ : first_iter_) + ->get_outlet (); + event->send_to_context (out); playing_state_ = UNISONO; } state_ = newstate; @@ -280,7 +280,7 @@ Part_combine_iterator::solo2 () if (!event) event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent")); - second_iter_->try_music_in_children (event); + event->send_to_context (second_iter_->get_outlet ()); playing_state_ = SOLO2; } } @@ -369,6 +369,13 @@ Part_combine_iterator::construct_children () 0 }; + // Add listeners to all contexts except Devnull. + Context *contexts[] = {one, two, solo_tr, tr, 0}; + for (int i = 0; contexts[i]; i++) + { + contexts[i]->event_source ()->add_listener (GET_LISTENER (set_busy), ly_symbol2scm ("MusicEvent")); + } + for (char const **p = syms; *p; p++) { SCM sym = ly_symbol2scm (*p); @@ -380,6 +387,37 @@ Part_combine_iterator::construct_children () } } +IMPLEMENT_LISTENER (Part_combine_iterator, set_busy); +void +Part_combine_iterator::set_busy (SCM se) +{ + if (!notice_busy_) + return; + + Stream_event *e = unsmob_stream_event (se); + SCM mus = e->get_property ("music"); + Music *m = unsmob_music (mus); + assert (m); + + if (m->is_mus_type ("note-event") || m->is_mus_type ("cluster-note-event")) + busy_ = true; +} + +/* +* Processes a moment in an iterator, and returns whether any new music was reported. +*/ +bool +Part_combine_iterator::try_process (Music_iterator *i, Moment m) +{ + busy_ = false; + notice_busy_ = true; + + i->process (m); + + notice_busy_ = false; + return busy_; +} + void Part_combine_iterator::process (Moment m) { @@ -418,27 +456,15 @@ Part_combine_iterator::process (Moment m) if (first_iter_->ok ()) { - first_iter_->process (m); - if (first_iter_->try_music_in_children (busy_playing_event)) - last_playing_ = SOLO1; + if (try_process (first_iter_, m)) + last_playing_ = SOLO1; } if (second_iter_->ok ()) { - second_iter_->process (m); - if (second_iter_->try_music_in_children (busy_playing_event)) + if (try_process (second_iter_, m)) last_playing_ = SOLO2; } } -Music_iterator * -Part_combine_iterator::try_music_in_children (Music *m) const -{ - Music_iterator *i = first_iter_->try_music (m); - if (i) - return i; - else - return second_iter_->try_music (m); -} - IMPLEMENT_CTOR_CALLBACK (Part_combine_iterator); diff --git a/lily/percent-repeat-iterator.cc b/lily/percent-repeat-iterator.cc index 29021ee396..7ba527da5d 100644 --- a/lily/percent-repeat-iterator.cc +++ b/lily/percent-repeat-iterator.cc @@ -3,13 +3,12 @@ source file of the GNU LilyPond music typesetter - (c) 2001--2006 Han-Wen Nienhuys , Erik Sandberg + (c) 2001--2006 Han-Wen Nienhuys + Erik Sandberg */ #include "percent-repeat-iterator.hh" - #include "input.hh" -#include "international.hh" #include "music.hh" #include "repeated-music.hh" @@ -17,17 +16,16 @@ IMPLEMENT_CTOR_CALLBACK (Percent_repeat_iterator); Percent_repeat_iterator::Percent_repeat_iterator () { - child_list_ = SCM_EOL; } -void -Percent_repeat_iterator::construct_children () +SCM +Percent_repeat_iterator::get_music_list () const { - /* TODO: Distinction between percent and slash */ + /* TODO: Distinction between percent, double-percent and slash */ Music *mus = get_music (); Music *child = Repeated_music::body (mus); SCM length = child->get_length ().smobbed_copy (); - child_list_ = SCM_EOL; + SCM child_list = SCM_EOL; int repeats = scm_to_int (mus->get_property ("repeat-count")); for (int i = repeats; i > 1; i--) @@ -37,27 +35,9 @@ Percent_repeat_iterator::construct_children () percent->set_property ("length", length); if (repeats > 1) percent->set_property ("repeat-count", scm_int2num (i - 1)); - Music *percent_chord = make_music_by_name (ly_symbol2scm ("EventChord")); - percent_chord->set_spot (*mus->origin ()); - percent_chord->set_property ("elements", scm_list_1 (percent->self_scm ())); - child_list_ = scm_cons (percent_chord->self_scm (), child_list_); - percent->unprotect (); - percent_chord->unprotect (); + child_list = scm_cons (percent->unprotect (), child_list); } - child_list_ = scm_cons (child->self_scm (), child_list_); - - Sequential_iterator::construct_children (); -} - -SCM -Percent_repeat_iterator::get_music_list () const -{ - return child_list_; -} + child_list = scm_cons (child->self_scm (), child_list); -void -Percent_repeat_iterator::derived_mark () const -{ - scm_gc_mark (child_list_); - Sequential_iterator::derived_mark (); + return child_list; } diff --git a/lily/quote-iterator.cc b/lily/quote-iterator.cc index 820d0ed158..9ca8fd25b7 100644 --- a/lily/quote-iterator.cc +++ b/lily/quote-iterator.cc @@ -252,10 +252,7 @@ Quote_iterator::process (Moment m) mus->transpose (diff); } - bool b = quote_outlet_.get_outlet ()->try_music (mus); - if (!b) - mus->origin ()->warning (_f ("in quotation: junking event %s", - mus->name ())); + quote_outlet_.get_outlet ()->try_music (mus); } } diff --git a/lily/sequential-iterator.cc b/lily/sequential-iterator.cc index 76b97efc39..86bacecf48 100644 --- a/lily/sequential-iterator.cc +++ b/lily/sequential-iterator.cc @@ -244,12 +244,6 @@ Sequential_iterator::ok () const return iter_; } -Music_iterator * -Sequential_iterator::try_music_in_children (Music *m) const -{ - return iter_ ? iter_->try_music (m) : 0; -} - IMPLEMENT_CTOR_CALLBACK (Sequential_iterator); bool diff --git a/lily/simple-music-iterator.cc b/lily/simple-music-iterator.cc index f2661f4b72..b2d686b32e 100644 --- a/lily/simple-music-iterator.cc +++ b/lily/simple-music-iterator.cc @@ -43,7 +43,7 @@ void Simple_music_iterator::process (Moment m) { /* - don't do try_music (), since it would make the function useless for + don't do report_event (), since it would make the function useless for base classes */ diff --git a/lily/simultaneous-music-iterator.cc b/lily/simultaneous-music-iterator.cc index 16691c3e63..a264d55ba9 100644 --- a/lily/simultaneous-music-iterator.cc +++ b/lily/simultaneous-music-iterator.cc @@ -133,15 +133,6 @@ Simultaneous_music_iterator::run_always () const return false; } -Music_iterator * -Simultaneous_music_iterator::try_music_in_children (Music *m) const -{ - Music_iterator *b = 0; - for (SCM s = children_list_; !b && scm_is_pair (s); s = scm_cdr (s)) - b = unsmob_iterator (scm_car (s))->try_music (m); - return b; -} - void Simultaneous_music_iterator::do_quit () { diff --git a/lily/time-scaled-music-iterator.cc b/lily/time-scaled-music-iterator.cc index db4c616274..7406d88469 100644 --- a/lily/time-scaled-music-iterator.cc +++ b/lily/time-scaled-music-iterator.cc @@ -16,11 +16,10 @@ Time_scaled_music_iterator::Time_scaled_music_iterator () { - child_list_ = SCM_EOL; } -void -Time_scaled_music_iterator::construct_children () +SCM +Time_scaled_music_iterator::get_music_list () const { Music *mus = get_music (); Input *origin = mus->origin (); @@ -41,22 +40,7 @@ Time_scaled_music_iterator::construct_children () stop_event = scm_call_1 (ly_lily_module_constant ("make-event-chord"), scm_list_1 (stop_event)); unsmob_music (stop_event)->set_spot (*origin); - child_list_ = scm_list_3 (start_event, child->self_scm (), stop_event); - - Sequential_iterator::construct_children (); -} - -SCM -Time_scaled_music_iterator::get_music_list () const -{ - return child_list_; -} - -void -Time_scaled_music_iterator::derived_mark () const -{ - scm_gc_mark (child_list_); - Sequential_iterator::derived_mark (); + return scm_list_3 (start_event, child->self_scm (), stop_event); } IMPLEMENT_CTOR_CALLBACK (Time_scaled_music_iterator); diff --git a/lily/translator-group.cc b/lily/translator-group.cc index 529d0f9979..0fd2bc4d21 100644 --- a/lily/translator-group.cc +++ b/lily/translator-group.cc @@ -3,18 +3,21 @@ source file of the GNU LilyPond music typesetter - (c) 1997--2006 Han-Wen Nienhuys + (c) 1997--2006 Han-Wen Nienhuys , + Erik Sandberg */ #include "translator-group.hh" -#include "output-def.hh" -#include "warn.hh" -#include "scm-hash.hh" #include "context-def.hh" #include "context.hh" +#include "dispatcher.hh" #include "main.hh" #include "music.hh" +#include "output-def.hh" +#include "scm-hash.hh" +#include "stream-event.hh" +#include "warn.hh" Translator_group * Translator_group::get_daddy_translator () const @@ -35,6 +38,15 @@ Translator_group::initialize () precompute_method_bindings (); } +void +Translator_group::connect_to_context (Context *c) +{ + if (context_) + programming_error ("already connected to a context"); + context_ = c; + c->event_source ()->add_listener (GET_LISTENER (eat_event), ly_symbol2scm ("MusicEvent")); +} + void Translator_group::finalize () { @@ -67,6 +79,16 @@ find_accept_translators (SCM gravlist, SCM ifaces) return l; } +IMPLEMENT_LISTENER (Translator_group, eat_event); +void +Translator_group::eat_event (SCM sev) +{ + Stream_event *ev = unsmob_stream_event (sev); + SCM sm = ev->get_property ("music"); + Music *m = unsmob_music (sm); + try_music (m); +} + bool Translator_group::try_music (Music *m) { @@ -235,4 +257,3 @@ Translator_group::mark_smob (SCM smob) scm_gc_mark (me->accept_hash_table_); return me->simple_trans_list_; } - diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly index 030426ea1e..b2780027c7 100644 --- a/ly/music-functions-init.ly +++ b/ly/music-functions-init.ly @@ -107,10 +107,11 @@ displayLilyMusic = music) applyOutput = -#(define-music-function (parser location proc) (procedure?) - (make-music 'ApplyOutputEvent +#(define-music-function (parser location ctx proc) (symbol? procedure?) + (make-music 'ApplyOutputEvent 'origin location - 'procedure proc)) + 'procedure proc + 'context-type ctx)) overrideProperty = #(define-music-function (parser location name property value) @@ -140,8 +141,7 @@ or @code{\"GrobName\"}" (if (equal? (cdr (assoc 'name (ly:grob-property grob 'meta))) grob-name) - (set! (ly:grob-property grob property) value) - ))) + (set! (ly:grob-property grob property) value)))) context-name))) diff --git a/python/convertrules.py b/python/convertrules.py index 3bc19ef5f8..d535ae8ce9 100644 --- a/python/convertrules.py +++ b/python/convertrules.py @@ -2789,3 +2789,9 @@ def conv (str): return str conversions.append (((2, 9, 4), conv, """(page-)penalty -> (page-)break-penalty""")) + +def conv (str): + str = re.sub (r'\\context\s+\"?([a-zA-Z]+)\"?\s*\\applyOutput', r"\\applyOutput #'\1", str) + return str + +conversions.append (((2, 9, 6), conv, """\context Foo \applyOutput #bla -> \applyOutput #'Foo #bla """)) diff --git a/scm/define-music-properties.scm b/scm/define-music-properties.scm index b330534d75..13a0da1f4e 100644 --- a/scm/define-music-properties.scm +++ b/scm/define-music-properties.scm @@ -50,6 +50,7 @@ TODO: consider making type into symbol ") (error-found ,boolean? "If true, a parsing error was found in this expression") (element ,ly:music? "The single child of a Music_wrapper music object, or the body of a repeat.") (elements ,ly:music-list? "A list of elements for sequential of simultaneous music, or the alternatives of repeated music. ") + (expected-beam-count ,integer? "Expected number of non-tremolo beams in a tremolo repeat") (force-accidental ,boolean? "If set, a cautionary accidental should always be printed on this note") (grob-property ,symbol? "The symbol of the grob property to set. ") (grob-property-path ,list? "A list of symbols, locating a nested grob property, e.g. (beamed-lengths details). ") @@ -100,7 +101,7 @@ e.g. @code{\\tag #'part ...} could tag a piece of music as only being active in (text ,markup? "markup expression to be printed") (tempo-unit ,ly:duration? "The unit for the metronome count.") (tonic ,ly:pitch? "Base of the scale") - (tremolo-type ,integer? "") + (tremolo-type ,integer? "speed of tremolo, e.g. 16 for c4:16") (trill-pitch ,ly:pitch? "Pitch of other note of the trill.") (type ,symbol? "The type of this music object. Determines iteration in some cases.") (types ,list? "The types of this music object; determines by what diff --git a/scm/define-music-types.scm b/scm/define-music-types.scm index 41d4609d49..69c654b019 100644 --- a/scm/define-music-types.scm +++ b/scm/define-music-types.scm @@ -30,14 +30,13 @@ Call the argument with all current grobs during interpreting phase. Syntax -\\applyoutput FUNC +\\applyOutput #'Context FUNC arguments to func are 1. the grob, 2. the originating context, 3. context where FUNC is called. ") - (iterator-ctor . ,ly:output-property-music-iterator::constructor) - (types . (general-music layout-instruction)) + (types . (general-music event layout-instruction)) )) (ArpeggioEvent . ( @@ -238,17 +237,6 @@ Syntax: @var{note}\\laissezVibrer.") (description . "Allow, forbid or force a line break.") (types . (general-music break-event event)) )) - (OldLyricCombineMusic - . ( - (description . "Align lyrics to the start of notes. - -Syntax @var{\\oldaddlyrics }@var{music} @var{lyrics}.") - - (types . (general-music lyric-combine-music)) - (length-callback . ,ly:lyric-combine-music::length-callback) - (start-callback . ,ly:music-sequence::first-start-callback) - (iterator-ctor . ,ly:old-lyric-combine-music-iterator::constructor) - )) (LyricCombineMusic . ( @@ -331,18 +319,6 @@ Syntax (types . (general-music event note-event rhythmic-event melodic-event)) )) - (OutputPropertySetMusic - . ( - (description . "Set grob properties in objects -individually. - -Syntax @code{\\outputproperty @var{predicate} @var{prop} -= @var{val}}.") - - (iterator-ctor . ,ly:output-property-music-iterator::constructor) - (types . (general-music layout-instruction)) - )) - (OverrideProperty . ( (description . "Extend the definition of a graphical object. @@ -674,6 +650,12 @@ Syntax: @code{\\@var{number}}.") (types . (general-music event tremolo-event)) )) + (TremoloSpanEvent + . ( + (description . "Tremolo over two stems") + (types . (general-music event span-event tremolo-span-event)) + )) + (VoiceSeparator . ( (description . "Separate polyphonic voices in simultaneous music. -- 2.39.5