Index: lily/time-scaled-music-iterator.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/time-scaled-music-iterator.cc,v retrieving revision 1.30 diff -u -r1.30 time-scaled-music-iterator.cc --- lily/time-scaled-music-iterator.cc 24 May 2006 07:00:41 -0000 1.30 +++ lily/time-scaled-music-iterator.cc 6 Jun 2006 20:40:33 -0000 @@ -7,15 +7,113 @@ Erik Sandberg */ -#include "time-scaled-music-iterator.hh" - #include "context.hh" #include "input.hh" #include "international.hh" #include "music.hh" +#include "sequential-iterator.hh" + +/* + Iterates \times, by sending TupletEvents at the start/end of each + tuplet bracket. Extra stop/start events are sent at regular + intervals if tupletSpannerDuration is set. +*/ +class Time_scaled_music_iterator : public Sequential_iterator +{ +public: + DECLARE_SCHEME_CALLBACK (constructor, ()); + /* construction */ + DECLARE_CLASSNAME(Time_scaled_music_iterator); + Time_scaled_music_iterator (); +protected: + virtual SCM get_music_list () const; + virtual void process (Moment m); + virtual void construct_children (); + virtual Moment pending_moment () const; +private: + /* tupletSpannerDuration */ + Moment spanner_duration_; + /* next time to add a stop/start pair */ + Moment next_split_mom_; + /* Recycle start/stop events. There is no need for GC methods: The + SCM objects are protected by Sequential_iterator. + */ + Music *start_; + Music *stop_; +}; Time_scaled_music_iterator::Time_scaled_music_iterator () { + spanner_duration_ = next_split_mom_ = 0; +} + + +Moment +Time_scaled_music_iterator::pending_moment () const +{ + Moment next_mom = Sequential_iterator::pending_moment (); + + if (spanner_duration_.to_bool () && + next_mom.main_part_ > next_split_mom_) + { + next_mom = next_split_mom_; + } + + return next_mom; +} + + +void +Time_scaled_music_iterator::process (Moment m) +{ + if (spanner_duration_.to_bool () && + m.main_part_ == next_split_mom_) + { + report_event (stop_); + report_event (start_); + next_split_mom_ += spanner_duration_; + /* avoid sending events twice at the end */ + if (next_split_mom_ == get_music ()->get_length ().main_part_) + next_split_mom_.set_infinite (1); + } + Sequential_iterator::process(m); +} + +void +Time_scaled_music_iterator::construct_children () +{ + /* + Inheritance trickery: + Time_scaled_music_iterator::construct_children initialises start_ + and stop_, and calls Sequential_music::construct_children, which + in turn calls Time_scaled_music_iterator::get_music which reads + start_ and stop_. This trickery has been built for const + correctness reasons. + */ + + Music *mus = get_music (); + Input *origin = mus->origin (); + + SCM tuplet_symbol = ly_symbol2scm ("TupletEvent"); + SCM start_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tuplet_symbol, scm_from_int (START)); + start_ = unsmob_music (start_scm); + start_->set_spot (*origin); + start_->set_property ("numerator", mus->get_property ("numerator")); + start_->set_property ("denominator", mus->get_property ("denominator")); + + SCM stop_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tuplet_symbol, scm_from_int (STOP)); + stop_ = unsmob_music (stop_scm); + stop_->set_spot (*origin); + + Moment *mp = unsmob_moment (get_outlet ()->get_property ("tupletSpannerDuration")); + + if (mp) + { + spanner_duration_ = mp->main_part_; + next_split_mom_ = spanner_duration_; + } + + Sequential_iterator::construct_children (); } SCM @@ -25,22 +123,7 @@ Input *origin = mus->origin (); Music *child = unsmob_music (mus->get_property ("element")); - /* Create tuplet start/stop span events before/after the music */ - SCM tuplet_symbol = ly_symbol2scm ("TupletEvent"); - SCM start_event = scm_call_2 (ly_lily_module_constant ("make-span-event"), tuplet_symbol, scm_from_int (START)); - Music *start = unsmob_music (start_event); - start->set_spot (*origin); - start->set_property ("numerator", mus->get_property ("numerator")); - start->set_property ("denominator", mus->get_property ("denominator")); - start_event = scm_call_1 (ly_lily_module_constant ("make-event-chord"), scm_list_1 (start_event)); - unsmob_music (start_event)->set_spot (*origin); - - SCM stop_event = scm_call_2 (ly_lily_module_constant ("make-span-event"), tuplet_symbol, scm_from_int (STOP)); - unsmob_music (stop_event)->set_spot (*origin); - stop_event = scm_call_1 (ly_lily_module_constant ("make-event-chord"), scm_list_1 (stop_event)); - unsmob_music (stop_event)->set_spot (*origin); - - return scm_list_3 (start_event, child->self_scm (), stop_event); + return scm_list_3 (start_->self_scm (), child->self_scm (), stop_->self_scm ()); } IMPLEMENT_CTOR_CALLBACK (Time_scaled_music_iterator); Index: lily/tuplet-engraver.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/tuplet-engraver.cc,v retrieving revision 1.96 diff -u -r1.96 tuplet-engraver.cc --- lily/tuplet-engraver.cc 26 May 2006 10:42:10 -0000 1.96 +++ lily/tuplet-engraver.cc 6 Jun 2006 20:40:33 -0000 @@ -166,5 +166,5 @@ /* doc */ "Catch TupletSpannerEvent and generate appropriate bracket ", /* create */ "TupletBracket TupletNumber ", /* accept */ "tuplet-spanner-event", - /* read */ "tupletNumberFormatFunction tupletSpannerDuration tupletFullLength ", + /* read */ "tupletNumberFormatFunction tupletFullLength ", /* write */ "");