2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
5 Jan Nieuwenhuizen <janneke@gnu.org>
7 LilyPond is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 LilyPond is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
24 #include "dot-column.hh"
26 #include "duration.hh"
27 #include "global-context.hh"
29 #include "output-def.hh"
32 #include "rhythmic-head.hh"
33 #include "score-engraver.hh"
35 #include "staff-symbol-referencer.hh"
36 #include "stream-event.hh"
41 #include "translator.icc"
46 When we catch the rest, we predict the end of the rest. We keep the
47 events living until we reach the predicted end-time.
49 Every time process_music () is called and there are rest events, we
50 figure out how long the rest to typeset should be. It should be no
51 longer than what's specified, than what is left to do and it should
52 not cross barlines or sub-bar units.
54 We copy the events into scratch rest events, to make sure that we get
55 all durations exactly right.
58 class Completion_rest_engraver : public Engraver
60 vector<Item *> rests_;
61 vector<Stream_event *> rest_events_;
65 Rational do_nothing_until_;
68 Moment next_moment (Rational const &);
69 Item *make_rest (Stream_event *);
72 TRANSLATOR_DECLARATIONS (Completion_rest_engraver);
75 virtual void initialize ();
76 void start_translation_timestep ();
77 void process_music ();
78 void stop_translation_timestep ();
79 DECLARE_TRANSLATOR_LISTENER (rest);
83 Completion_rest_engraver::initialize ()
88 IMPLEMENT_TRANSLATOR_LISTENER (Completion_rest_engraver, rest);
90 Completion_rest_engraver::listen_rest (Stream_event *ev)
92 rest_events_.push_back (ev);
95 Moment now = now_mom ();
96 Moment musiclen = get_event_length (ev, now);
98 rest_end_mom_ = max (rest_end_mom_, (now + musiclen));
99 do_nothing_until_ = Rational (0, 0);
103 The duration _until_ the next barline or completion unit
106 Completion_rest_engraver::next_moment (Rational const ¬e_len)
108 Moment *e = unsmob_moment (get_property ("measurePosition"));
109 Moment *l = unsmob_moment (get_property ("measureLength"));
110 if (!e || !l || !to_boolean (get_property ("timing")))
112 return Moment (0, 0);
115 Moment result = *l - *e;
116 Moment const *unit = unsmob_moment (get_property ("completionUnit"));
120 Rational const now_unit = e->main_part_ / unit->main_part_;
121 if (now_unit.den () > 1)
124 within a unit - go to the end of that
126 result = unit->main_part_
127 * (Rational (1) - (now_unit - now_unit.trunc_rat ()));
132 at the beginning of a unit:
133 take a power-of-two number of units, but not more than required,
134 since then the Duration constructor destroys the unit structure
136 if (note_len < result.main_part_)
137 result.main_part_ = note_len;
138 Rational const step_unit = result.main_part_ / unit->main_part_;
139 if (step_unit.den () < step_unit.num ())
142 = intlog2 (int (step_unit.num () / step_unit.den ()));
143 result.main_part_ = unit->main_part_ * Rational (1 << log2);
152 Completion_rest_engraver::make_rest (Stream_event *ev)
154 Item *rest = make_item ("Rest", ev->self_scm ());
155 if (Pitch *p = unsmob_pitch (ev->get_property ("pitch")))
157 int pos = p->steps ();
158 SCM c0 = get_property ("middleCPosition");
159 if (scm_is_number (c0))
160 pos += scm_to_int (c0);
161 rest->set_property ("staff-position", scm_from_int (pos));
168 Completion_rest_engraver::process_music ()
170 if (!is_first_ && !left_to_do_)
175 Moment now = now_mom ();
176 if (do_nothing_until_ > now.main_part_)
184 note that rest_dur may be strictly less than left_to_do_
185 (say, if left_to_do_ == 5/8)
187 if (factor_.denominator () == 1 && factor_ > Rational (1, 1))
188 rest_dur = Duration (left_to_do_, false);
190 rest_dur = Duration (left_to_do_ / factor_, false).compressed (factor_);
194 orig = unsmob_duration (rest_events_[0]->get_property ("duration"));
196 factor_ = rest_dur.factor ();
197 left_to_do_ = orig->get_length ();
199 Moment nb = next_moment (rest_dur.get_length ());
200 if (nb.main_part_ && nb < rest_dur.get_length ())
202 if (factor_.denominator () == 1 && factor_.numerator () > 1)
203 rest_dur = Duration (nb.main_part_, false);
205 rest_dur = Duration (nb.main_part_ / factor_, false).compressed (factor_);
208 do_nothing_until_ = now.main_part_ + rest_dur.get_length ();
210 for (vsize i = 0; left_to_do_ && i < rest_events_.size (); i++)
212 bool need_clone = !orig || *orig != rest_dur;
213 Stream_event *event = rest_events_[i];
216 event = event->clone ();
218 SCM pits = rest_events_[i]->get_property ("pitch");
219 event->set_property ("pitch", pits);
220 event->set_property ("duration", rest_dur.smobbed_copy ());
221 event->set_property ("length", Moment (rest_dur.get_length ()).smobbed_copy ());
222 event->set_property ("duration-log", scm_from_int (rest_dur.duration_log ()));
224 Item *rest = make_rest (event);
227 rests_.push_back (rest);
230 left_to_do_ -= rest_dur.get_length ();
232 get_global_context ()->add_moment_to_process (now.main_part_ + rest_dur.get_length ());
234 don't do complicated arithmetic with grace rests.
236 if (orig && now_mom ().grace_part_)
237 left_to_do_ = Rational (0, 0);
241 Completion_rest_engraver::stop_translation_timestep ()
247 Completion_rest_engraver::start_translation_timestep ()
249 Moment now = now_mom ();
250 if (rest_end_mom_.main_part_ <= now.main_part_)
252 rest_events_.clear ();
254 context ()->set_property ("restCompletionBusy",
255 ly_bool2scm (rest_events_.size ()));
258 Completion_rest_engraver::Completion_rest_engraver ()
262 ADD_TRANSLATOR (Completion_rest_engraver,
264 "This engraver replaces @code{Rest_engraver}. It plays"
265 " some trickery to break long rests into the next measure.",
277 "restCompletionBusy "