#include "international.hh"
#include "music.hh"
#include "music-wrapper-iterator.hh"
+#include "stream-event.hh"
/*
Iterates \times, by sending TupletSpanEvents at the start/end of each
virtual void construct_children ();
virtual void derived_mark () const;
virtual Moment pending_moment () const;
+
+ Music *create_event (Direction d);
+
private:
/* tupletSpannerDuration */
Moment next_split_mom_;
/* Recycle start/stop events if tupletSpannerDuration is set. */
- Music *start_;
- Music *stop_;
-
- bool done_first_;
+ SCM synthesized_events_;
Context_handle tuplet_handler_;
};
+Music*
+Time_scaled_music_iterator::create_event (Direction d)
+{
+ SCM ev_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"),
+ ly_symbol2scm ("TupletSpanEvent"),
+ scm_from_int (d));
+
+ Music *mus = get_music ();
+
+ Music *ev = unsmob_music (ev_scm);
+ ev->set_spot (*mus->origin ());
+ if (d == START)
+ {
+ ev->set_property ("numerator", mus->get_property ("numerator"));
+ ev->set_property ("denominator", mus->get_property ("denominator"));
+ ev->set_property ("tweaks", mus->get_property ("tweaks"));
+ ev->set_property ("length", spanner_duration_.smobbed_copy ());
+ }
+
+ synthesized_events_ = scm_cons (ev_scm, synthesized_events_);
+ return ev;
+}
+
+
Time_scaled_music_iterator::Time_scaled_music_iterator ()
{
spanner_duration_ = next_split_mom_ = 0;
- done_first_ = 0;
+ synthesized_events_ = SCM_EOL;
}
Moment
Time_scaled_music_iterator::pending_moment () const
{
- if (!done_first_)
- return Moment (0);
-
Moment next_mom = Music_wrapper_iterator::pending_moment ();
-
- if (spanner_duration_.to_bool () &&
- next_mom.main_part_ > next_split_mom_)
- {
- next_mom = next_split_mom_;
- }
+ next_mom = min (next_mom, next_split_mom_);
return next_mom;
}
void
Time_scaled_music_iterator::process (Moment m)
{
- if (!done_first_)
- {
- done_first_ = true;
- descend_to_bottom_context ();
- report_event (start_);
- tuplet_handler_.set_context (get_outlet());
- }
-
if (spanner_duration_.to_bool () &&
m.main_part_ == next_split_mom_)
{
descend_to_bottom_context ();
- stop_->send_to_context (tuplet_handler_.get_outlet ());
-
- tuplet_handler_.set_context (get_outlet ());
- report_event (start_);
+ if (tuplet_handler_.get_outlet())
+ create_event (STOP)->send_to_context (tuplet_handler_.get_outlet ());
+
+ if (m.main_part_ < music_get_length ().main_part_)
+ {
+ tuplet_handler_.set_context (get_outlet ());
+ report_event (create_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);
+ next_split_mom_ += spanner_duration_;
+ }
+ else
+ {
+ tuplet_handler_.set_context (0);
+ }
}
-
Music_wrapper_iterator::process(m);
if (child_iter_ && child_iter_->ok ())
descend_to_child (child_iter_->get_outlet ());
- if (m.main_part_ == music_get_length ().main_part_)
- {
- stop_->send_to_context (tuplet_handler_.get_outlet ());
- tuplet_handler_.set_context (0);
- }
}
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_.
- */
-
- Music *mus = get_music ();
- Input *origin = mus->origin ();
-
- SCM tuplet_symbol = ly_symbol2scm ("TupletSpanEvent");
- 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"));
- start_->set_property ("tweaks", mus->get_property ("tweaks"));
-
-
- 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_;
}
-
+ else
+ {
+ spanner_duration_ = music_get_length ();
+ }
+
Music_wrapper_iterator::construct_children ();
if (child_iter_ && child_iter_->ok ())
void
Time_scaled_music_iterator::derived_mark () const
{
- if (start_)
- scm_gc_mark (start_->self_scm ());
- if (stop_)
- scm_gc_mark (stop_->self_scm ());
-
+ scm_gc_mark (synthesized_events_);
Music_wrapper_iterator::derived_mark ();
}
#include "tuplet-bracket.hh"
#include "warn.hh"
#include "item.hh"
+#include "moment.hh"
#include "translator.icc"
bool full_length_;
bool full_length_note_;
+ Moment stop_moment_;
+ Moment start_moment_;
+ Moment length_;
Tuplet_description ()
{
{
Tuplet_description d;
d.event_ = ev;
+
+ d.length_ = robust_scm2moment (d.event_->get_property ("length"),
+ Moment (0));
+ d.start_moment_ = now_mom ();
+ d.stop_moment_ = now_mom () + d.length_;
+
+ for (vsize i=0; i < new_tuplets_.size (); i++)
+ {
+ /*
+ discard duplicates.
+ */
+ if (new_tuplets_[i].stop_moment_ == d.stop_moment_)
+ return;
+ }
+
new_tuplets_.push_back (d);
}
- else if (dir == STOP && tuplets_.size ())
+ else if (dir == STOP)
+ {
+ if (tuplets_.size ())
{
stopped_tuplets_.push_back (tuplets_.back ());
tuplets_.pop_back ();
}
+ else
+ ev->origin ()->warning (_f ("No tuplet to end"));
+ }
else
- programming_error (_f ("direction of %s invalid: %d",
- "tuplet-span-event", int (dir)));
+ ev->origin ()->programming_error ("direction tuplet-span-event_ invalid.");
}
void
Tuplet_engraver::process_music ()
{
+ /*
+ This may happen if the end of a tuplet is part of a quoted voice.
+ */
+ Moment now = now_mom();
+ for (vsize i = tuplets_.size (); i --; )
+ {
+ stopped_tuplets_.push_back (tuplets_[i]);
+ if (tuplets_[i].stop_moment_ == now)
+ tuplets_.erase (tuplets_.begin () + i);
+ }
+
for (vsize i = 0; i < stopped_tuplets_.size (); i++)
{
Spanner *bracket = stopped_tuplets_[i].bracket_;
number->set_bound (RIGHT,
stopped_tuplets_[i].bracket_->get_bound (LEFT));
}
+
// todo: scrap last_tuplets_, use stopped_tuplets_ only.
// clear stopped_tuplets_ at start_translation_timestep
last_tuplets_.push_back (bracket);
tuplets_[i].event_->self_scm ());
tuplets_[i].number_->set_object ("bracket", tuplets_[i].bracket_->self_scm ());
tuplets_[i].bracket_->set_object ("tuplet-number", tuplets_[i].number_->self_scm ());
+ tuplets_[i].stop_moment_.grace_part_ = 0;
+
if (i < tuplets_.size () - 1 && tuplets_[i + 1].bracket_)
Tuplet_bracket::add_tuplet_bracket (tuplets_[i].bracket_, tuplets_[i + 1].bracket_);