2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2015 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"
48 When we catch the rest, we predict the end of the rest. We keep the
49 events living until we reach the predicted end-time.
51 Every time process_music () is called and there are rest events, we
52 figure out how long the rest to typeset should be. It should be no
53 longer than what's specified, than what is left to do and it should
54 not cross barlines or sub-bar units.
56 We copy the events into scratch rest events, to make sure that we get
57 all durations exactly right.
60 class Completion_rest_engraver : public Engraver
62 vector<Item *> rests_;
63 vector<Stream_event *> rest_events_;
67 Rational do_nothing_until_;
70 Moment next_moment (Rational const &);
71 Item *make_rest (Stream_event *);
74 TRANSLATOR_DECLARATIONS (Completion_rest_engraver);
77 virtual void initialize ();
78 void start_translation_timestep ();
79 void process_music ();
80 void stop_translation_timestep ();
81 DECLARE_TRANSLATOR_LISTENER (rest);
85 Completion_rest_engraver::initialize ()
90 IMPLEMENT_TRANSLATOR_LISTENER (Completion_rest_engraver, rest);
92 Completion_rest_engraver::listen_rest (Stream_event *ev)
94 rest_events_.push_back (ev);
97 Moment now = now_mom ();
98 Moment musiclen = get_event_length (ev, now);
100 rest_end_mom_ = max (rest_end_mom_, (now + musiclen));
101 do_nothing_until_ = Rational (0, 0);
105 The duration _until_ the next barline or completion unit
108 Completion_rest_engraver::next_moment (Rational const ¬e_len)
110 Moment *e = unsmob<Moment> (get_property ("measurePosition"));
111 Moment *l = unsmob<Moment> (get_property ("measureLength"));
112 if (!e || !l || !to_boolean (get_property ("timing")))
114 return Moment (0, 0);
117 Moment result = *l - *e;
118 Moment const *unit = unsmob<Moment> (get_property ("completionUnit"));
122 Rational const now_unit = e->main_part_ / unit->main_part_;
123 if (now_unit.den () > 1)
126 within a unit - go to the end of that
128 result = unit->main_part_
129 * (Rational (1) - (now_unit - now_unit.trunc_rat ()));
134 at the beginning of a unit:
135 take a power-of-two number of units, but not more than required,
136 since then the Duration constructor destroys the unit structure
138 if (note_len < result.main_part_)
139 result.main_part_ = note_len;
140 Rational const step_unit = result.main_part_ / unit->main_part_;
141 if (step_unit.den () < step_unit.num ())
144 = intlog2 (int (step_unit.num () / step_unit.den ()));
145 result.main_part_ = unit->main_part_ * Rational (1 << log2);
154 Completion_rest_engraver::make_rest (Stream_event *ev)
156 Item *rest = make_item ("Rest", ev->self_scm ());
157 if (Pitch *p = unsmob<Pitch> (ev->get_property ("pitch")))
159 int pos = p->steps ();
160 SCM c0 = get_property ("middleCPosition");
161 if (scm_is_number (c0))
162 pos += scm_to_int (c0);
163 rest->set_property ("staff-position", scm_from_int (pos));
170 Completion_rest_engraver::process_music ()
172 if (!is_first_ && !left_to_do_)
177 Moment now = now_mom ();
178 if (do_nothing_until_ > now.main_part_)
186 note that rest_dur may be strictly less than left_to_do_
187 (say, if left_to_do_ == 5/8)
189 rest_dur = Duration (left_to_do_ / factor_, false).compressed (factor_);
193 orig = unsmob<Duration> (rest_events_[0]->get_property ("duration"));
195 SCM factor = get_property ("completionFactor");
196 if (ly_is_procedure (factor))
197 factor = scm_call_2 (factor,
198 context ()->self_scm (),
199 rest_dur.smobbed_copy ());
200 factor_ = robust_scm2rational (factor, rest_dur.factor());
201 left_to_do_ = orig->get_length ();
203 Moment nb = next_moment (rest_dur.get_length ());
204 if (nb.main_part_ && nb < rest_dur.get_length ())
206 rest_dur = Duration (nb.main_part_ / factor_, false).compressed (factor_);
209 do_nothing_until_ = now.main_part_ + rest_dur.get_length ();
211 for (vsize i = 0; left_to_do_ && i < rest_events_.size (); i++)
213 bool need_clone = !orig || *orig != rest_dur;
214 Stream_event *event = rest_events_[i];
217 event = event->clone ();
219 SCM pits = rest_events_[i]->get_property ("pitch");
220 event->set_property ("pitch", pits);
221 event->set_property ("duration", rest_dur.smobbed_copy ());
222 event->set_property ("length", Moment (rest_dur.get_length ()).smobbed_copy ());
223 event->set_property ("duration-log", scm_from_int (rest_dur.duration_log ()));
225 Item *rest = make_rest (event);
228 rests_.push_back (rest);
231 left_to_do_ -= rest_dur.get_length ();
233 get_global_context ()->add_moment_to_process (now.main_part_ + rest_dur.get_length ());
235 don't do complicated arithmetic with grace rests.
237 if (orig && now_mom ().grace_part_)
238 left_to_do_ = Rational (0, 0);
242 Completion_rest_engraver::stop_translation_timestep ()
248 Completion_rest_engraver::start_translation_timestep ()
250 Moment now = now_mom ();
251 if (rest_end_mom_.main_part_ <= now.main_part_)
253 rest_events_.clear ();
255 context ()->set_property ("restCompletionBusy",
256 ly_bool2scm (rest_events_.size ()));
259 Completion_rest_engraver::Completion_rest_engraver ()
263 ADD_TRANSLATOR (Completion_rest_engraver,
265 "This engraver replaces @code{Rest_engraver}. It plays"
266 " some trickery to break long rests into the next measure.",
279 "restCompletionBusy "