2 tuplet-engraver.cc -- implement Tuplet_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include "tuplet-bracket.hh"
10 #include "note-column.hh"
12 #include "engraver.hh"
15 #include "translator.icc"
17 struct Tuplet_description
29 static int compare (Tuplet_description const &a, Tuplet_description const &b)
31 return ::compare (a.length_, b.length_);
36 class Tuplet_engraver : public Engraver
39 TRANSLATOR_DECLARATIONS (Tuplet_engraver);
42 Array<Tuplet_description> tuplets_;
43 Link_array<Spanner> last_tuplets_;
44 DECLARE_ACKNOWLEDGER (note_column);
45 virtual bool try_music (Music *r);
46 virtual void finalize ();
47 void start_translation_timestep ();
48 void process_music ();
52 Tuplet_engraver::try_music (Music *music)
54 if (music->is_mus_type ("time-scaled-music"))
56 Music *el = unsmob_music (music->get_property ("element"));
57 if (el && !el->is_mus_type ("event-chord"))
61 d.length_ = music->get_length ().main_part_;
62 d.stop_ = now_mom ().main_part_ + d.length_;
63 d.span_stop_ = d.stop_;
65 SCM s = get_property ("tupletSpannerDuration");
66 if (unsmob_moment (s))
67 d.span_stop_ = min (d.span_stop_, (now_mom () + *unsmob_moment (s)).main_part_);
77 Tuplet_engraver::process_music ()
79 if (!tuplets_.size ())
82 tuplets_.sort (&Tuplet_description::compare);
83 for (int i = 0; i < tuplets_.size (); i++)
85 if (tuplets_[i].spanner_)
88 Spanner *spanner = make_spanner ("TupletBracket",
89 tuplets_[i].music_->self_scm ());
90 tuplets_[i].spanner_ = spanner;
92 if (i > 0 && tuplets_[i - 1].spanner_)
93 Tuplet_bracket::add_tuplet_bracket (tuplets_[i].spanner_, tuplets_[i - 1].spanner_);
94 if (i < tuplets_.size () - 1 && tuplets_[i + 1].spanner_)
95 Tuplet_bracket::add_tuplet_bracket (tuplets_[i + 1].spanner_, tuplets_[i].spanner_);
97 SCM proc = get_property ("tupletNumberFormatFunction");
98 if (ly_is_procedure (proc))
100 SCM t = scm_apply_0 (proc, scm_list_1 (tuplets_[i].music_->self_scm ()));
101 spanner->set_property ("text", t);
107 Tuplet_engraver::acknowledge_note_column (Grob_info i)
109 for (int j = 0; j < tuplets_.size (); j++)
110 if (tuplets_[j].spanner_)
111 Tuplet_bracket::add_column (tuplets_[j].spanner_,
112 dynamic_cast<Item *> (i.grob ()));
116 Tuplet_engraver::start_translation_timestep ()
118 Moment now = now_mom ();
120 last_tuplets_.clear ();
121 if (tuplets_.is_empty ())
124 Moment tsdmom = robust_scm2moment (get_property ("tupletSpannerDuration"), Moment (0));
125 bool full_length = to_boolean (get_property ("tupletFullLength"));
127 for (int i = tuplets_.size (); i--;)
129 Rational tsd = tsdmom.main_part_;
131 if (now.main_part_ >= tuplets_[i].span_stop_)
133 if (tuplets_[i].spanner_)
137 Item *col = unsmob_item (get_property ("currentMusicalColumn"));
139 tuplets_[i].spanner_->set_bound (RIGHT, col);
141 else if (!tuplets_[i].spanner_->get_bound (RIGHT))
142 tuplets_[i].spanner_->set_bound (RIGHT,
143 tuplets_[i].spanner_->get_bound (LEFT));
145 last_tuplets_.push (tuplets_[i].spanner_);
146 tuplets_[i].spanner_ = 0;
150 tuplets_[i].span_stop_ += tsd;
153 if (now.main_part_ >= tuplets_[i].stop_)
159 Tuplet_engraver::finalize ()
161 if (to_boolean (get_property ("tupletFullLength")))
163 for (int i = 0; i < last_tuplets_.size (); i++)
165 Item *col = unsmob_item (get_property ("currentCommandColumn"));
166 last_tuplets_[i]->set_bound (RIGHT, col);
171 Tuplet_engraver::Tuplet_engraver ()
175 ADD_ACKNOWLEDGER (Tuplet_engraver, note_column);
176 ADD_TRANSLATOR (Tuplet_engraver,
177 /* doc */ "Catch Time_scaled_music and generate appropriate bracket ",
178 /* create */ "TupletBracket",
179 /* accept */ "time-scaled-music",
180 /* read */ "tupletNumberFormatFunction tupletSpannerDuration tupletFullLength",