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 DECLARE_ACKNOWLEDGER (note_head);
88 DECLARE_TRANSLATOR_LISTENER (tie);
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;
104 IMPLEMENT_TRANSLATOR_LISTENER (Tie_engraver, tie);
106 Tie_engraver::listen_tie (Stream_event *ev)
108 if (!to_boolean (get_property ("skipTypesetting")))
110 ASSIGN_EVENT_ONCE (event_, ev);
114 void Tie_engraver::report_unterminated_tie (Head_event_tuple const &tie_start)
116 // If tie_from_chord_created is set, we have another note at the same
117 // moment that created a tie, so this is not necessarily an unterminated
118 // tie. Happens e.g. for <c e g>~ g
119 if (!tie_start.tie_from_chord_created)
121 tie_start.tie_->warning (_ ("unterminated tie"));
122 tie_start.tie_->suicide ();
127 Determines whether the end of an event was created by
128 a split in Completion_heads_engraver or by user input.
131 Tie_engraver::has_autosplit_end (Stream_event *event)
134 return to_boolean (event->get_property ("autosplit-end"));
139 Tie_engraver::process_music ()
142 for (vsize i = 0; !busy && i < heads_to_tie_.size (); i++)
143 busy |= (heads_to_tie_[i].tie_event_
144 || heads_to_tie_[i].tie_stream_event_);
147 context ()->set_property ("tieMelismaBusy", SCM_BOOL_T);
151 Tie_engraver::tie_notehead (Grob *h, bool enharmonic)
155 for (vsize i = 0; i < heads_to_tie_.size (); i++)
157 Grob *th = heads_to_tie_[i].head_;
158 Stream_event *right_ev = unsmob<Stream_event> (h->get_property ("cause"));
159 Stream_event *left_ev = unsmob<Stream_event> (th->get_property ("cause"));
162 maybe should check positions too.
164 if (!right_ev || !left_ev)
168 Make a tie only if pitches are equal or if event end was not generated by
169 Completion_heads_engraver.
171 SCM p1 = left_ev->get_property ("pitch");
172 SCM p2 = right_ev->get_property ("pitch");
174 ? (unsmob<Pitch> (p1) && unsmob<Pitch> (p2) &&
175 unsmob<Pitch> (p1)->tone_pitch () == unsmob<Pitch> (p2)->tone_pitch ())
176 : ly_is_equal (p1, p2))
177 && (!Tie_engraver::has_autosplit_end (left_ev)))
179 Spanner *p = heads_to_tie_[i].tie_;
180 Moment end = heads_to_tie_[i].end_moment_;
182 Stream_event *cause = heads_to_tie_[i].tie_event_
183 ? heads_to_tie_[i].tie_event_
184 : heads_to_tie_[i].tie_stream_event_;
186 announce_end_grob (p, cause->self_scm ());
188 Tie::set_head (p, LEFT, th);
189 Tie::set_head (p, RIGHT, h);
191 if (is_direction (cause->get_property ("direction")))
193 Direction d = to_dir (cause->get_property ("direction"));
194 p->set_property ("direction", scm_from_int (d));
198 heads_to_tie_.erase (heads_to_tie_.begin () + i);
202 Prevent all other tied notes ending at the same moment (assume
203 implicitly the notes have also started at the same moment!)
204 from triggering an "unterminated tie" warning. Needed e.g. for
207 for (vsize j = heads_to_tie_.size (); j--;)
209 if (heads_to_tie_[j].end_moment_ == end)
210 heads_to_tie_[j].tie_from_chord_created = true;
219 Tie_engraver::acknowledge_note_head (Grob_info i)
223 now_heads_.push_back (h);
225 if (!tie_notehead (h, false))
226 tie_notehead (h, true);
228 if (ties_.size () && ! tie_column_)
229 tie_column_ = make_spanner ("TieColumn", ties_[0]->self_scm ());
232 for (vsize i = 0; i < ties_.size (); i++)
233 Tie_column::add_tie (tie_column_, ties_[i]);
237 Tie_engraver::start_translation_timestep ()
239 if (heads_to_tie_.size () && !to_boolean (get_property ("tieWaitForNote")))
241 Moment now = now_mom ();
242 for (vsize i = heads_to_tie_.size (); i--;)
244 if (now > heads_to_tie_[i].end_moment_)
246 report_unterminated_tie (heads_to_tie_[i]);
247 heads_to_tie_.erase (heads_to_tie_.begin () + i);
252 context ()->set_property ("tieMelismaBusy",
253 ly_bool2scm (heads_to_tie_.size ()));
257 Tie_engraver::process_acknowledged ()
259 bool wait = to_boolean (get_property ("tieWaitForNote"));
264 vector<Head_event_tuple>::iterator it = heads_to_tie_.begin ();
265 for (; it < heads_to_tie_.end (); it++)
266 report_unterminated_tie (*it);
267 heads_to_tie_.clear ();
270 for (vsize i = 0; i < ties_.size (); i++)
271 typeset_tie (ties_[i]);
277 vector<Head_event_tuple> new_heads_to_tie;
280 for (vsize i = 0; i < now_heads_.size (); i++)
282 Grob *head = now_heads_[i];
283 Stream_event *left_ev
284 = unsmob<Stream_event> (head->get_property ("cause"));
288 // may happen for ambitus
292 // We only want real notes to cause ties, not e.g. pitched trills
293 if (!left_ev->in_event_class ("note-event"))
296 SCM left_articulations = left_ev->get_property ("articulations");
298 Stream_event *tie_event = 0;
299 Stream_event *tie_stream_event = event_;
300 for (SCM s = left_articulations;
301 !tie_event && !tie_stream_event && scm_is_pair (s);
304 Stream_event *ev = unsmob<Stream_event> (scm_car (s));
308 if (ev->in_event_class ("tie-event"))
312 if (left_ev && (tie_event || tie_stream_event)
313 && (!Tie_engraver::has_autosplit_end (left_ev)))
315 event_processed_ = true;
317 Head_event_tuple event_tup;
319 event_tup.head_ = head;
320 event_tup.tie_event_ = tie_event;
321 event_tup.tie_stream_event_ = tie_stream_event;
322 event_tup.tie_ = make_spanner ("Tie", tie_event
323 ? tie_event->self_scm ()
324 : tie_stream_event->self_scm ());
326 Moment end = now_mom ();
329 end.grace_part_ += get_event_length (left_ev).main_part_;
333 end += get_event_length (left_ev);
335 event_tup.end_moment_ = end;
337 new_heads_to_tie.push_back (event_tup);
341 if (!wait && new_heads_to_tie.size ())
343 vector<Head_event_tuple>::iterator it = heads_to_tie_.begin ();
344 for (; it < heads_to_tie_.end (); it++)
345 report_unterminated_tie (*it);
346 heads_to_tie_.clear ();
349 // hmmm, how to do with copy () ?
350 for (vsize i = 0; i < new_heads_to_tie.size (); i++)
351 heads_to_tie_.push_back (new_heads_to_tie[i]);
357 Tie_engraver::stop_translation_timestep ()
360 Discard event only if it has been processed with at least one
363 if (event_processed_)
366 event_processed_ = false;
370 Tie_engraver::typeset_tie (Spanner *her)
372 Grob *left_head = Tie::head (her, LEFT);
373 Grob *right_head = Tie::head (her, RIGHT);
375 if (!left_head || !right_head)
377 warning (_ ("lonely tie"));
379 left_head = right_head;
381 right_head = left_head;
384 her->set_bound (LEFT, left_head);
385 her->set_bound (RIGHT, right_head);
388 ADD_ACKNOWLEDGER (Tie_engraver, note_head);
389 ADD_TRANSLATOR (Tie_engraver,
391 "Generate ties between note heads of equal pitch.",