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"
38 Manufacture ties. Acknowledge note heads, and put them into a
39 priority queue. If we have a TieEvent, connect the notes that finish
40 just at this time, and note that start at this time.
42 TODO: Remove the dependency on musical info. We should tie on the
43 basis of position and duration-log of the heads (not of the events).
46 struct Head_event_tuple
50 Stream_event *tie_stream_event_;
51 Stream_event *tie_event_;
53 // Indicate whether a tie from the same moment has been processed successfully
54 // This is needed for tied chords, e.g. <c e g>~ g, because otherwise the c
55 // and e will trigger a warning for an unterminated tie!
56 bool tie_from_chord_created;
62 tie_stream_event_ = 0;
63 tie_from_chord_created = false;
68 class Tie_engraver : public Engraver
71 Whether tie event has been processed and can be deleted or should
72 be kept for later portions of a split note.
74 bool event_processed_;
76 vector<Grob *> now_heads_;
77 vector<Head_event_tuple> heads_to_tie_;
78 vector<Spanner *> ties_;
81 bool tie_notehead (Grob *h, bool enharmonic);
84 void process_acknowledged ();
85 void stop_translation_timestep ();
86 void start_translation_timestep ();
87 void acknowledge_note_head (Grob_info);
88 void listen_tie (Stream_event *);
89 void process_music ();
90 void typeset_tie (Spanner *);
91 void report_unterminated_tie (Head_event_tuple const &);
92 bool has_autosplit_end (Stream_event *event);
94 TRANSLATOR_DECLARATIONS (Tie_engraver);
97 Tie_engraver::Tie_engraver ()
101 event_processed_ = false;
105 Tie_engraver::listen_tie (Stream_event *ev)
107 if (!to_boolean (get_property ("skipTypesetting")))
109 ASSIGN_EVENT_ONCE (event_, ev);
113 void Tie_engraver::report_unterminated_tie (Head_event_tuple const &tie_start)
115 // If tie_from_chord_created is set, we have another note at the same
116 // moment that created a tie, so this is not necessarily an unterminated
117 // tie. Happens e.g. for <c e g>~ g
118 if (!tie_start.tie_from_chord_created)
120 tie_start.tie_->warning (_ ("unterminated tie"));
121 tie_start.tie_->suicide ();
126 Determines whether the end of an event was created by
127 a split in Completion_heads_engraver or by user input.
130 Tie_engraver::has_autosplit_end (Stream_event *event)
133 return to_boolean (event->get_property ("autosplit-end"));
138 Tie_engraver::process_music ()
141 for (vsize i = 0; !busy && i < heads_to_tie_.size (); i++)
142 busy |= (heads_to_tie_[i].tie_event_
143 || heads_to_tie_[i].tie_stream_event_);
146 context ()->set_property ("tieMelismaBusy", SCM_BOOL_T);
150 Tie_engraver::tie_notehead (Grob *h, bool enharmonic)
154 for (vsize i = 0; i < heads_to_tie_.size (); i++)
156 Grob *th = heads_to_tie_[i].head_;
157 Stream_event *right_ev = unsmob<Stream_event> (h->get_property ("cause"));
158 Stream_event *left_ev = unsmob<Stream_event> (th->get_property ("cause"));
161 maybe should check positions too.
163 if (!right_ev || !left_ev)
167 Make a tie only if pitches are equal or if event end was not generated by
168 Completion_heads_engraver.
170 SCM p1 = left_ev->get_property ("pitch");
171 SCM p2 = right_ev->get_property ("pitch");
173 ? (unsmob<Pitch> (p1) && unsmob<Pitch> (p2) &&
174 unsmob<Pitch> (p1)->tone_pitch () == unsmob<Pitch> (p2)->tone_pitch ())
175 : ly_is_equal (p1, p2))
176 && (!Tie_engraver::has_autosplit_end (left_ev)))
178 Spanner *p = heads_to_tie_[i].tie_;
179 Moment end = heads_to_tie_[i].end_moment_;
181 Stream_event *cause = heads_to_tie_[i].tie_event_
182 ? heads_to_tie_[i].tie_event_
183 : heads_to_tie_[i].tie_stream_event_;
185 announce_end_grob (p, cause->self_scm ());
187 Tie::set_head (p, LEFT, th);
188 Tie::set_head (p, RIGHT, h);
190 if (is_direction (cause->get_property ("direction")))
192 Direction d = to_dir (cause->get_property ("direction"));
193 p->set_property ("direction", scm_from_int (d));
197 heads_to_tie_.erase (heads_to_tie_.begin () + i);
201 Prevent all other tied notes ending at the same moment (assume
202 implicitly the notes have also started at the same moment!)
203 from triggering an "unterminated tie" warning. Needed e.g. for
206 for (vsize j = heads_to_tie_.size (); j--;)
208 if (heads_to_tie_[j].end_moment_ == end)
209 heads_to_tie_[j].tie_from_chord_created = true;
218 Tie_engraver::acknowledge_note_head (Grob_info i)
222 now_heads_.push_back (h);
224 if (!tie_notehead (h, false))
225 tie_notehead (h, true);
227 if (ties_.size () && ! tie_column_)
228 tie_column_ = make_spanner ("TieColumn", ties_[0]->self_scm ());
231 for (vsize i = 0; i < ties_.size (); i++)
232 Tie_column::add_tie (tie_column_, ties_[i]);
236 Tie_engraver::start_translation_timestep ()
238 if (heads_to_tie_.size () && !to_boolean (get_property ("tieWaitForNote")))
240 Moment now = now_mom ();
241 for (vsize i = heads_to_tie_.size (); i--;)
243 if (now > heads_to_tie_[i].end_moment_)
245 report_unterminated_tie (heads_to_tie_[i]);
246 heads_to_tie_.erase (heads_to_tie_.begin () + i);
251 context ()->set_property ("tieMelismaBusy",
252 ly_bool2scm (heads_to_tie_.size ()));
256 Tie_engraver::process_acknowledged ()
258 bool wait = to_boolean (get_property ("tieWaitForNote"));
263 vector<Head_event_tuple>::iterator it = heads_to_tie_.begin ();
264 for (; it < heads_to_tie_.end (); it++)
265 report_unterminated_tie (*it);
266 heads_to_tie_.clear ();
269 for (vsize i = 0; i < ties_.size (); i++)
270 typeset_tie (ties_[i]);
276 vector<Head_event_tuple> new_heads_to_tie;
279 for (vsize i = 0; i < now_heads_.size (); i++)
281 Grob *head = now_heads_[i];
282 Stream_event *left_ev
283 = unsmob<Stream_event> (head->get_property ("cause"));
287 // may happen for ambitus
291 // We only want real notes to cause ties, not e.g. pitched trills
292 if (!left_ev->in_event_class ("note-event"))
295 SCM left_articulations = left_ev->get_property ("articulations");
297 Stream_event *tie_event = 0;
298 Stream_event *tie_stream_event = event_;
299 for (SCM s = left_articulations;
300 !tie_event && !tie_stream_event && scm_is_pair (s);
303 Stream_event *ev = unsmob<Stream_event> (scm_car (s));
307 if (ev->in_event_class ("tie-event"))
311 if (left_ev && (tie_event || tie_stream_event)
312 && (!Tie_engraver::has_autosplit_end (left_ev)))
314 event_processed_ = true;
316 Head_event_tuple event_tup;
318 event_tup.head_ = head;
319 event_tup.tie_event_ = tie_event;
320 event_tup.tie_stream_event_ = tie_stream_event;
321 event_tup.tie_ = make_spanner ("Tie", tie_event
322 ? tie_event->self_scm ()
323 : tie_stream_event->self_scm ());
325 Moment end = now_mom ();
328 end.grace_part_ += get_event_length (left_ev).main_part_;
332 end += get_event_length (left_ev);
334 event_tup.end_moment_ = end;
336 new_heads_to_tie.push_back (event_tup);
340 if (!wait && new_heads_to_tie.size ())
342 vector<Head_event_tuple>::iterator it = heads_to_tie_.begin ();
343 for (; it < heads_to_tie_.end (); it++)
344 report_unterminated_tie (*it);
345 heads_to_tie_.clear ();
348 // hmmm, how to do with copy () ?
349 for (vsize i = 0; i < new_heads_to_tie.size (); i++)
350 heads_to_tie_.push_back (new_heads_to_tie[i]);
356 Tie_engraver::stop_translation_timestep ()
359 Discard event only if it has been processed with at least one
362 if (event_processed_)
365 event_processed_ = false;
369 Tie_engraver::typeset_tie (Spanner *her)
371 Grob *left_head = Tie::head (her, LEFT);
372 Grob *right_head = Tie::head (her, RIGHT);
374 if (!left_head || !right_head)
376 warning (_ ("lonely tie"));
378 left_head = right_head;
380 right_head = left_head;
383 her->set_bound (LEFT, left_head);
384 her->set_bound (RIGHT, right_head);
388 Tie_engraver::boot ()
390 ADD_LISTENER (Tie_engraver, tie);
391 ADD_ACKNOWLEDGER (Tie_engraver, note_head);
394 ADD_TRANSLATOR (Tie_engraver,
396 "Generate ties between note heads of equal pitch.",