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<Item *> prev_rests_;
62 vector<Stream_event *> rest_events_;
66 Rational do_nothing_until_;
69 Moment next_moment (Rational const &);
70 Item *make_rest (Stream_event *);
73 TRANSLATOR_DECLARATIONS (Completion_rest_engraver);
76 virtual void initialize ();
77 void start_translation_timestep ();
78 void process_music ();
79 void stop_translation_timestep ();
80 DECLARE_TRANSLATOR_LISTENER (rest);
84 Completion_rest_engraver::initialize ()
89 IMPLEMENT_TRANSLATOR_LISTENER (Completion_rest_engraver, rest);
91 Completion_rest_engraver::listen_rest (Stream_event *ev)
93 rest_events_.push_back (ev);
96 Moment now = now_mom ();
97 Moment musiclen = get_event_length (ev, now);
99 rest_end_mom_ = max (rest_end_mom_, (now + musiclen));
100 do_nothing_until_ = Rational (0, 0);
104 The duration _until_ the next barline or completion unit
107 Completion_rest_engraver::next_moment (Rational const ¬e_len)
109 Moment *e = unsmob_moment (get_property ("measurePosition"));
110 Moment *l = unsmob_moment (get_property ("measureLength"));
111 if (!e || !l || !to_boolean (get_property ("timing")))
113 return Moment (0, 0);
116 Moment result = *l - *e;
117 Moment const *unit = unsmob_moment (get_property ("completionUnit"));
121 Rational const now_unit = e->main_part_ / unit->main_part_;
122 if (now_unit.den() > 1)
125 within a unit - go to the end of that
127 result = unit->main_part_
128 * (Rational (1) - (now_unit - now_unit.trunc_rat ()));
133 at the beginning of a unit:
134 take a power-of-two number of units, but not more than required,
135 since then the Duration constructor destroys the unit structure
137 if (note_len < result.main_part_)
138 result.main_part_ = note_len;
139 Rational const step_unit = result.main_part_ / unit->main_part_;
140 if (step_unit.den () < step_unit.num ())
143 = intlog2 (int (step_unit.num () / step_unit.den ()));
144 result.main_part_ = unit->main_part_ * Rational (1 << log2);
153 Completion_rest_engraver::make_rest (Stream_event *ev)
155 Item *rest = make_item ("Rest", ev->self_scm ());
156 if (Pitch *p = unsmob_pitch (ev->get_property ("pitch")))
158 int pos = p->steps ();
159 SCM c0 = get_property ("middleCPosition");
160 if (scm_is_number (c0))
161 pos += scm_to_int (c0);
162 rest->set_property ("staff-position", scm_from_int (pos));
169 Completion_rest_engraver::process_music ()
171 if (!is_first_ && !left_to_do_)
176 Moment now = now_mom ();
177 if (do_nothing_until_ > now.main_part_)
186 rest that rest_dur may be strictly less than left_to_do_
187 (say, if left_to_do_ == 5/8)
189 if (factor_.denominator () == 1 && factor_ > Rational (1, 1))
190 rest_dur = Duration (left_to_do_, false);
192 rest_dur = Duration (left_to_do_ / factor_, false).compressed (factor_);
193 appearance = Duration (left_to_do_, false);
197 orig = unsmob_duration (rest_events_[0]->get_property ("duration"));
199 factor_ = rest_dur.factor ();
200 left_to_do_ = orig->get_length ();
202 Moment nb = next_moment (rest_dur.get_length ());
203 if (nb.main_part_ && nb < rest_dur.get_length ())
205 if (factor_.denominator () == 1 && factor_.numerator () > 1)
206 rest_dur = Duration (nb.main_part_, false);
208 rest_dur = Duration (nb.main_part_ / factor_, false).compressed (factor_);
211 do_nothing_until_ = now.main_part_ + rest_dur.get_length ();
213 for (vsize i = 0; left_to_do_ && i < rest_events_.size (); i++)
215 bool need_clone = !orig || *orig != rest_dur;
216 Stream_event *event = rest_events_[i];
219 event = event->clone ();
221 SCM pits = rest_events_[i]->get_property ("pitch");
222 event->set_property ("pitch", pits);
223 event->set_property ("duration", rest_dur.smobbed_copy ());
224 event->set_property ("length", Moment (rest_dur.get_length ()).smobbed_copy ());
225 event->set_property ("duration-log", scm_from_int (rest_dur.duration_log ()));
227 Item *rest = make_rest (event);
230 rests_.push_back (rest);
233 left_to_do_ -= rest_dur.get_length ();
235 get_global_context ()->add_moment_to_process (now.main_part_ + rest_dur.get_length ());
237 don't do complicated arithmetic with grace rests.
239 if (orig && now_mom ().grace_part_)
240 left_to_do_ = Rational (0, 0);
244 Completion_rest_engraver::stop_translation_timestep ()
247 prev_rests_ = rests_;
252 Completion_rest_engraver::start_translation_timestep ()
254 Moment now = now_mom ();
255 if (rest_end_mom_.main_part_ <= now.main_part_)
257 rest_events_.clear ();
258 prev_rests_.clear ();
260 context ()->set_property ("restCompletionBusy",
261 ly_bool2scm (rest_events_.size ()));
264 Completion_rest_engraver::Completion_rest_engraver ()
268 ADD_TRANSLATOR (Completion_rest_engraver,
270 "This engraver replaces @code{Rest_engraver}. It plays"
271 " some trickery to break long rests into the next measure.",
283 "restCompletionBusy "