2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1998--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
20 #include "engraver.hh"
23 #include "international.hh"
25 #include "note-head.hh"
27 #include "protected-scm.hh"
29 #include "staff-symbol-referencer.hh"
30 #include "stream-event.hh"
31 #include "tie-column.hh"
35 #include "translator.icc"
40 Manufacture ties. Acknowledge note heads, and put them into a
41 priority queue. If we have a TieEvent, connect the notes that finish
42 just at this time, and note that start at this time.
44 TODO: Remove the dependency on musical info. We should tie on the
45 basis of position and duration-log of the heads (not of the events).
48 struct Head_event_tuple
52 Stream_event *tie_stream_event_;
53 Stream_event *tie_event_;
55 // Indicate whether a tie from the same moment has been processed successfully
56 // This is needed for tied chords, e.g. <c e g>~ g, because otherwise the c
57 // and e will trigger a warning for an unterminated tie!
58 bool tie_from_chord_created;
64 tie_stream_event_ = 0;
65 tie_from_chord_created = false;
70 class Tie_engraver : public Engraver
73 Whether tie event has been processed and can be deleted or should
74 be kept for later portions of a split note.
76 bool event_processed_;
78 vector<Grob *> now_heads_;
79 vector<Head_event_tuple> heads_to_tie_;
80 vector<Spanner *> ties_;
83 bool tie_notehead (Grob *h, bool enharmonic);
86 void process_acknowledged ();
87 void stop_translation_timestep ();
88 void start_translation_timestep ();
89 DECLARE_ACKNOWLEDGER (note_head);
90 DECLARE_TRANSLATOR_LISTENER (tie);
91 void process_music ();
92 void typeset_tie (Spanner *);
93 void report_unterminated_tie (Head_event_tuple const &);
94 bool has_autosplit_end (Stream_event *event);
96 TRANSLATOR_DECLARATIONS (Tie_engraver);
99 Tie_engraver::Tie_engraver ()
103 event_processed_ = false;
106 IMPLEMENT_TRANSLATOR_LISTENER (Tie_engraver, tie);
108 Tie_engraver::listen_tie (Stream_event *ev)
110 if (!to_boolean (get_property ("skipTypesetting")))
112 ASSIGN_EVENT_ONCE (event_, ev);
116 void Tie_engraver::report_unterminated_tie (Head_event_tuple const &tie_start)
118 // If tie_from_chord_created is set, we have another note at the same
119 // moment that created a tie, so this is not necessarily an unterminated
120 // tie. Happens e.g. for <c e g>~ g
121 if (!tie_start.tie_from_chord_created)
123 tie_start.tie_->warning (_ ("unterminated tie"));
124 tie_start.tie_->suicide ();
129 Determines whether the end of an event was created by
130 a split in Completion_heads_engraver or by user input.
133 Tie_engraver::has_autosplit_end (Stream_event *event)
136 return to_boolean (event->get_property ("autosplit-end"));
141 Tie_engraver::process_music ()
144 for (vsize i = 0; !busy && i < heads_to_tie_.size (); i++)
145 busy |= (heads_to_tie_[i].tie_event_
146 || heads_to_tie_[i].tie_stream_event_);
149 context ()->set_property ("tieMelismaBusy", SCM_BOOL_T);
153 Tie_engraver::tie_notehead (Grob *h, bool enharmonic)
157 for (vsize i = 0; i < heads_to_tie_.size (); i++)
159 Grob *th = heads_to_tie_[i].head_;
160 Stream_event *right_ev = unsmob<Stream_event> (h->get_property ("cause"));
161 Stream_event *left_ev = unsmob<Stream_event> (th->get_property ("cause"));
164 maybe should check positions too.
166 if (!right_ev || !left_ev)
170 Make a tie only if pitches are equal or if event end was not generated by
171 Completion_heads_engraver.
173 SCM p1 = left_ev->get_property ("pitch");
174 SCM p2 = right_ev->get_property ("pitch");
176 ? (unsmob<Pitch> (p1) && unsmob<Pitch> (p2) &&
177 unsmob<Pitch> (p1)->tone_pitch () == unsmob<Pitch> (p2)->tone_pitch ())
178 : ly_is_equal (p1, p2))
179 && (!Tie_engraver::has_autosplit_end (left_ev)))
181 Spanner *p = heads_to_tie_[i].tie_;
182 Moment end = heads_to_tie_[i].end_moment_;
184 Stream_event *cause = heads_to_tie_[i].tie_event_
185 ? heads_to_tie_[i].tie_event_
186 : heads_to_tie_[i].tie_stream_event_;
188 announce_end_grob (p, cause->self_scm ());
190 Tie::set_head (p, LEFT, th);
191 Tie::set_head (p, RIGHT, h);
193 if (is_direction (cause->get_property ("direction")))
195 Direction d = to_dir (cause->get_property ("direction"));
196 p->set_property ("direction", scm_from_int (d));
200 heads_to_tie_.erase (heads_to_tie_.begin () + i);
204 Prevent all other tied notes ending at the same moment (assume
205 implicitly the notes have also started at the same moment!)
206 from triggering an "unterminated tie" warning. Needed e.g. for
209 for (vsize j = heads_to_tie_.size (); j--;)
211 if (heads_to_tie_[j].end_moment_ == end)
212 heads_to_tie_[j].tie_from_chord_created = true;
221 Tie_engraver::acknowledge_note_head (Grob_info i)
225 now_heads_.push_back (h);
227 if (!tie_notehead (h, false))
228 tie_notehead (h, true);
230 if (ties_.size () && ! tie_column_)
231 tie_column_ = make_spanner ("TieColumn", ties_[0]->self_scm ());
234 for (vsize i = 0; i < ties_.size (); i++)
235 Tie_column::add_tie (tie_column_, ties_[i]);
239 Tie_engraver::start_translation_timestep ()
241 if (heads_to_tie_.size () && !to_boolean (get_property ("tieWaitForNote")))
243 Moment now = now_mom ();
244 for (vsize i = heads_to_tie_.size (); i--;)
246 if (now > heads_to_tie_[i].end_moment_)
248 report_unterminated_tie (heads_to_tie_[i]);
249 heads_to_tie_.erase (heads_to_tie_.begin () + i);
254 context ()->set_property ("tieMelismaBusy",
255 ly_bool2scm (heads_to_tie_.size ()));
259 Tie_engraver::process_acknowledged ()
261 bool wait = to_boolean (get_property ("tieWaitForNote"));
266 vector<Head_event_tuple>::iterator it = heads_to_tie_.begin ();
267 for (; it < heads_to_tie_.end (); it++)
268 report_unterminated_tie (*it);
269 heads_to_tie_.clear ();
272 for (vsize i = 0; i < ties_.size (); i++)
273 typeset_tie (ties_[i]);
279 vector<Head_event_tuple> new_heads_to_tie;
282 for (vsize i = 0; i < now_heads_.size (); i++)
284 Grob *head = now_heads_[i];
285 Stream_event *left_ev
286 = unsmob<Stream_event> (head->get_property ("cause"));
290 // may happen for ambitus
294 // We only want real notes to cause ties, not e.g. pitched trills
295 if (!left_ev->in_event_class ("note-event"))
298 SCM left_articulations = left_ev->get_property ("articulations");
300 Stream_event *tie_event = 0;
301 Stream_event *tie_stream_event = event_;
302 for (SCM s = left_articulations;
303 !tie_event && !tie_stream_event && scm_is_pair (s);
306 Stream_event *ev = unsmob<Stream_event> (scm_car (s));
310 if (ev->in_event_class ("tie-event"))
314 if (left_ev && (tie_event || tie_stream_event)
315 && (!Tie_engraver::has_autosplit_end (left_ev)))
317 event_processed_ = true;
319 Head_event_tuple event_tup;
321 event_tup.head_ = head;
322 event_tup.tie_event_ = tie_event;
323 event_tup.tie_stream_event_ = tie_stream_event;
324 event_tup.tie_ = make_spanner ("Tie", tie_event
325 ? tie_event->self_scm ()
326 : tie_stream_event->self_scm ());
328 Moment end = now_mom ();
331 end.grace_part_ += get_event_length (left_ev).main_part_;
335 end += get_event_length (left_ev);
337 event_tup.end_moment_ = end;
339 new_heads_to_tie.push_back (event_tup);
343 if (!wait && new_heads_to_tie.size ())
345 vector<Head_event_tuple>::iterator it = heads_to_tie_.begin ();
346 for (; it < heads_to_tie_.end (); it++)
347 report_unterminated_tie (*it);
348 heads_to_tie_.clear ();
351 // hmmm, how to do with copy () ?
352 for (vsize i = 0; i < new_heads_to_tie.size (); i++)
353 heads_to_tie_.push_back (new_heads_to_tie[i]);
359 Tie_engraver::stop_translation_timestep ()
362 Discard event only if it has been processed with at least one
365 if (event_processed_)
368 event_processed_ = false;
372 Tie_engraver::typeset_tie (Spanner *her)
374 Grob *left_head = Tie::head (her, LEFT);
375 Grob *right_head = Tie::head (her, RIGHT);
377 if (!left_head || !right_head)
379 warning (_ ("lonely tie"));
381 left_head = right_head;
383 right_head = left_head;
386 her->set_bound (LEFT, left_head);
387 her->set_bound (RIGHT, right_head);
390 ADD_ACKNOWLEDGER (Tie_engraver, note_head);
391 ADD_TRANSLATOR (Tie_engraver,
393 "Generate ties between note heads of equal pitch.",