Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 /* | 1 /* |
2 This file is part of LilyPond, the GNU music typesetter. | 2 This file is part of LilyPond, the GNU music typesetter. |
3 | 3 |
4 Copyright (C) 1998--2011 Han-Wen Nienhuys <hanwen@xs4all.nl> | 4 Copyright (C) 1998--2011 Han-Wen Nienhuys <hanwen@xs4all.nl> |
5 | 5 |
6 LilyPond is free software: you can redistribute it and/or modify | 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 | 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 | 8 the Free Software Foundation, either version 3 of the License, or |
9 (at your option) any later version. | 9 (at your option) any later version. |
10 | 10 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 tie_definition_ = SCM_EOL; | 60 tie_definition_ = SCM_EOL; |
61 tie_event_ = 0; | 61 tie_event_ = 0; |
62 tie_stream_event_ = 0; | 62 tie_stream_event_ = 0; |
63 tie_from_chord_created = false; | 63 tie_from_chord_created = false; |
64 } | 64 } |
65 }; | 65 }; |
66 | 66 |
67 class Tie_engraver : public Engraver | 67 class Tie_engraver : public Engraver |
68 { | 68 { |
69 Stream_event *event_; | 69 Stream_event *event_; |
70 vector<Grob*> now_heads_; | 70 vector<Grob *> now_heads_; |
71 vector<Head_event_tuple> heads_to_tie_; | 71 vector<Head_event_tuple> heads_to_tie_; |
72 vector<Grob*> ties_; | 72 vector<Grob *> ties_; |
73 | 73 |
74 Spanner *tie_column_; | 74 Spanner *tie_column_; |
75 | 75 |
76 protected: | 76 protected: |
77 void stop_translation_timestep (); | 77 void stop_translation_timestep (); |
78 virtual void derived_mark () const; | 78 virtual void derived_mark () const; |
79 void start_translation_timestep (); | 79 void start_translation_timestep (); |
80 DECLARE_ACKNOWLEDGER (note_head); | 80 DECLARE_ACKNOWLEDGER (note_head); |
81 DECLARE_TRANSLATOR_LISTENER (tie); | 81 DECLARE_TRANSLATOR_LISTENER (tie); |
82 void process_music (); | 82 void process_music (); |
83 void typeset_tie (Grob *); | 83 void typeset_tie (Grob *); |
84 void report_unterminated_tie (Head_event_tuple const &); | 84 void report_unterminated_tie (Head_event_tuple const &); |
85 bool has_autosplit_end (Stream_event* event); | 85 bool has_autosplit_end (Stream_event *event); |
86 public: | 86 public: |
87 TRANSLATOR_DECLARATIONS (Tie_engraver); | 87 TRANSLATOR_DECLARATIONS (Tie_engraver); |
88 }; | 88 }; |
89 | 89 |
90 void | 90 void |
91 Tie_engraver::derived_mark () const | 91 Tie_engraver::derived_mark () const |
92 { | 92 { |
93 Engraver::derived_mark (); | 93 Engraver::derived_mark (); |
94 for (vsize i = 0; i < heads_to_tie_.size (); i++) | 94 for (vsize i = 0; i < heads_to_tie_.size (); i++) |
95 scm_gc_mark (heads_to_tie_[i].tie_definition_); | 95 scm_gc_mark (heads_to_tie_[i].tie_definition_); |
(...skipping 11 matching lines...) Expand all Loading... | |
107 { | 107 { |
108 ASSIGN_EVENT_ONCE (event_, ev); | 108 ASSIGN_EVENT_ONCE (event_, ev); |
109 } | 109 } |
110 | 110 |
111 void Tie_engraver::report_unterminated_tie (Head_event_tuple const &tie_start) | 111 void Tie_engraver::report_unterminated_tie (Head_event_tuple const &tie_start) |
112 { | 112 { |
113 // If tie_from_chord_created is set, we have another note at the same | 113 // If tie_from_chord_created is set, we have another note at the same |
114 // moment that created a tie, so this is not necessarily an unterminated | 114 // moment that created a tie, so this is not necessarily an unterminated |
115 // tie. Happens e.g. for <c e g>~ g | 115 // tie. Happens e.g. for <c e g>~ g |
116 if (!tie_start.tie_from_chord_created) | 116 if (!tie_start.tie_from_chord_created) |
117 tie_start.head_->warning (_("unterminated tie")); | 117 tie_start.head_->warning (_ ("unterminated tie")); |
118 } | 118 } |
119 | 119 |
120 /* | 120 /* |
121 Determines whether the end of an event was created by | 121 Determines whether the end of an event was created by |
122 a split in Completion_heads_engraver or by user input. | 122 a split in Completion_heads_engraver or by user input. |
123 */ | 123 */ |
124 bool | 124 bool |
125 Tie_engraver::has_autosplit_end (Stream_event* event) | 125 Tie_engraver::has_autosplit_end (Stream_event *event) |
126 { | 126 { |
127 if (event) | 127 if (event) |
128 return to_boolean (event->get_property ("autosplit-end")); | 128 return to_boolean (event->get_property ("autosplit-end")); |
129 return false; | 129 return false; |
130 } | 130 } |
131 | 131 |
132 void | 132 void |
133 Tie_engraver::process_music () | 133 Tie_engraver::process_music () |
134 { | 134 { |
135 bool busy = event_; | 135 bool busy = event_; |
136 for (vsize i = 0; !busy && i < heads_to_tie_.size (); i++) | 136 for (vsize i = 0; !busy && i < heads_to_tie_.size (); i++) |
137 busy |= (heads_to_tie_[i].tie_event_ | 137 busy |= (heads_to_tie_[i].tie_event_ |
138 » || heads_to_tie_[i].tie_stream_event_); | 138 » || heads_to_tie_[i].tie_stream_event_); |
139 | 139 |
140 if (busy) | 140 if (busy) |
141 context ()->set_property ("tieMelismaBusy", SCM_BOOL_T); | 141 context ()->set_property ("tieMelismaBusy", SCM_BOOL_T); |
142 } | 142 } |
143 | 143 |
144 void | 144 void |
145 Tie_engraver::acknowledge_note_head (Grob_info i) | 145 Tie_engraver::acknowledge_note_head (Grob_info i) |
146 { | 146 { |
147 Grob *h = i.grob (); | 147 Grob *h = i.grob (); |
148 | 148 |
149 now_heads_.push_back (h); | 149 now_heads_.push_back (h); |
150 for (vsize i = heads_to_tie_.size (); i--;) | 150 for (vsize i = heads_to_tie_.size (); i--;) |
151 { | 151 { |
152 Grob *th = heads_to_tie_[i].head_; | 152 Grob *th = heads_to_tie_[i].head_; |
153 Stream_event *right_ev = unsmob_stream_event (h->get_property ("cause")); | 153 Stream_event *right_ev = unsmob_stream_event (h->get_property ("cause")); |
154 Stream_event *left_ev = unsmob_stream_event (th->get_property ("cause")); | 154 Stream_event *left_ev = unsmob_stream_event (th->get_property ("cause")); |
155 | 155 |
156 /* | 156 /* |
157 » maybe should check positions too. | 157 maybe should check positions too. |
Graham Percival (old account)
2011/06/15 09:29:00
this should be indented with:
1 tab
| |
158 */ | 158 */ |
159 if (!right_ev || !left_ev) | 159 if (!right_ev || !left_ev) |
160 continue; | 160 continue; |
161 | 161 |
162 | 162 /* |
163 /* | 163 Make a tie only if pitches are equal or if event end was not generated b y |
164 Make a tie only if pitches are equal or if event end was not generated by | 164 Completion_heads_engraver. |
165 Completion_heads_engraver. | 165 */ |
166 */ | 166 if (ly_is_equal (right_ev->get_property ("pitch"), left_ev->get_property ( "pitch")) |
167 if (ly_is_equal (right_ev->get_property ("pitch"), left_ev->get_property ("p itch")) | 167 » && (!Tie_engraver::has_autosplit_end (left_ev))) |
168 && (!Tie_engraver::has_autosplit_end (left_ev))) | |
169 { | 168 { |
170 Grob *p = new Spanner (heads_to_tie_[i].tie_definition_); | 169 Grob *p = new Spanner (heads_to_tie_[i].tie_definition_); |
171 Moment end = heads_to_tie_[i].end_moment_; | 170 Moment end = heads_to_tie_[i].end_moment_; |
172 | 171 |
173 SCM cause = heads_to_tie_[i].tie_event_ | 172 SCM cause = heads_to_tie_[i].tie_event_ |
174 ? heads_to_tie_[i].tie_event_->self_scm () | 173 ? heads_to_tie_[i].tie_event_->self_scm () |
175 : heads_to_tie_[i].tie_stream_event_->self_scm (); | 174 : heads_to_tie_[i].tie_stream_event_->self_scm (); |
176 | 175 |
177 announce_grob (p, cause); | 176 announce_grob (p, cause); |
178 Tie::set_head (p, LEFT, th); | 177 Tie::set_head (p, LEFT, th); |
179 Tie::set_head (p, RIGHT, h); | 178 Tie::set_head (p, RIGHT, h); |
180 | 179 |
181 | |
182 if (is_direction (unsmob_stream_event (cause)->get_property ("directio n"))) | 180 if (is_direction (unsmob_stream_event (cause)->get_property ("directio n"))) |
183 { | 181 { |
184 Direction d = to_dir (unsmob_stream_event (cause)->get_property (" direction")); | 182 Direction d = to_dir (unsmob_stream_event (cause)->get_property (" direction")); |
185 p->set_property ("direction", scm_from_int (d)); | 183 p->set_property ("direction", scm_from_int (d)); |
186 } | 184 } |
187 | 185 |
188 ties_.push_back (p); | 186 ties_.push_back (p); |
189 heads_to_tie_.erase (heads_to_tie_.begin () + i); | 187 heads_to_tie_.erase (heads_to_tie_.begin () + i); |
190 | 188 |
191 » // Prevent all other tied notes ending at the same moment (assume | 189 /* |
Graham Percival (old account)
2011/06/15 09:29:00
this should be indented with:
1 tab
| |
192 » // implicitly the notes have also started at the same moment!) | 190 Prevent all other tied notes ending at the same moment (assume |
Graham Percival (old account)
2011/06/15 09:29:00
this should be indented with:
1 tab + 2 spaces
| |
193 » // from triggering an "unterminated tie" warning. Needed e.g. for | 191 implicitly the notes have also started at the same moment!) |
194 » // <c e g>~ g | 192 from triggering an "unterminated tie" warning. Needed e.g. for |
193 <c e g>~ g | |
194 */ | |
195 for (vsize j = heads_to_tie_.size (); j--;) | 195 for (vsize j = heads_to_tie_.size (); j--;) |
196 { | 196 { |
197 if (heads_to_tie_[j].end_moment_ == end) | 197 if (heads_to_tie_[j].end_moment_ == end) |
198 heads_to_tie_[j].tie_from_chord_created = true; | 198 heads_to_tie_[j].tie_from_chord_created = true; |
199 } | 199 } |
200 } | 200 } |
201 } | 201 } |
202 | 202 |
203 if (ties_.size () && ! tie_column_) | 203 if (ties_.size () && !tie_column_) |
204 tie_column_ = make_spanner ("TieColumn", ties_[0]->self_scm ()); | 204 tie_column_ = make_spanner ("TieColumn", ties_[0]->self_scm ()); |
205 | 205 |
206 if (tie_column_) | 206 if (tie_column_) |
207 for (vsize i = ties_.size (); i--;) | 207 for (vsize i = ties_.size (); i--;) |
208 Tie_column::add_tie (tie_column_, ties_[i]); | 208 Tie_column::add_tie (tie_column_, ties_[i]); |
209 } | 209 } |
210 | 210 |
211 void | 211 void |
212 Tie_engraver::start_translation_timestep () | 212 Tie_engraver::start_translation_timestep () |
213 { | 213 { |
214 if (heads_to_tie_.size () && !to_boolean (get_property ("tieWaitForNote"))) | 214 if (heads_to_tie_.size () && !to_boolean (get_property ("tieWaitForNote"))) |
215 { | 215 { |
216 Moment now = now_mom (); | 216 Moment now = now_mom (); |
217 for (vsize i = heads_to_tie_.size (); i--; ) | 217 for (vsize i = heads_to_tie_.size (); i--;) |
218 { | 218 { |
219 if (now > heads_to_tie_[i].end_moment_) | 219 if (now > heads_to_tie_[i].end_moment_) |
220 { | 220 { |
221 report_unterminated_tie (heads_to_tie_[i]); | 221 report_unterminated_tie (heads_to_tie_[i]); |
222 heads_to_tie_.erase (heads_to_tie_.begin () + i); | 222 heads_to_tie_.erase (heads_to_tie_.begin () + i); |
223 } | 223 } |
224 } | 224 } |
225 } | 225 } |
226 | 226 |
227 context ()->set_property ("tieMelismaBusy", | 227 context ()->set_property ("tieMelismaBusy", |
228 ly_bool2scm (heads_to_tie_.size ())); | 228 ly_bool2scm (heads_to_tie_.size ())); |
229 } | 229 } |
230 | 230 |
231 void | 231 void |
232 Tie_engraver::stop_translation_timestep () | 232 Tie_engraver::stop_translation_timestep () |
233 { | 233 { |
234 bool wait = to_boolean (get_property ("tieWaitForNote")); | 234 bool wait = to_boolean (get_property ("tieWaitForNote")); |
235 if (ties_.size ()) | 235 if (ties_.size ()) |
236 { | 236 { |
237 if (!wait) | 237 if (!wait) |
238 { | 238 » { |
Graham Percival (old account)
2011/06/15 09:29:00
heh, wow, the original file was wrong. Go figure.
| |
239 vector<Head_event_tuple>::iterator it = heads_to_tie_.begin (); | 239 vector<Head_event_tuple>::iterator it = heads_to_tie_.begin (); |
240 for (; it < heads_to_tie_.end (); it++) | 240 for (; it < heads_to_tie_.end (); it++) |
241 report_unterminated_tie (*it); | 241 report_unterminated_tie (*it); |
242 heads_to_tie_.clear (); | 242 heads_to_tie_.clear (); |
243 } | 243 » } |
244 | 244 |
245 for (vsize i = 0; i < ties_.size (); i++) | 245 for (vsize i = 0; i < ties_.size (); i++) |
246 » typeset_tie (ties_[i]); | 246 » typeset_tie (ties_[i]); |
247 | 247 |
248 ties_.clear (); | 248 ties_.clear (); |
249 tie_column_ = 0; | 249 tie_column_ = 0; |
250 } | 250 } |
251 | 251 |
252 vector<Head_event_tuple> new_heads_to_tie; | 252 vector<Head_event_tuple> new_heads_to_tie; |
253 | 253 |
254 /* | 254 /* |
255 Whether tie event has been processed and can be deleted or should | 255 Whether tie event has been processed and can be deleted or should |
256 be kept for later portions of a split note. | 256 be kept for later portions of a split note. |
257 */ | 257 */ |
258 bool event_processed = false; | 258 bool event_processed = false; |
259 | 259 |
260 for (vsize i = 0; i < now_heads_.size (); i++) | 260 for (vsize i = 0; i < now_heads_.size (); i++) |
261 { | 261 { |
262 Grob *head = now_heads_[i]; | 262 Grob *head = now_heads_[i]; |
263 Stream_event *left_ev | 263 Stream_event *left_ev |
264 = unsmob_stream_event (head->get_property ("cause")); | 264 = unsmob_stream_event (head->get_property ("cause")); |
265 | 265 |
266 if (!left_ev) | 266 if (!left_ev) |
267 { | 267 { |
268 // may happen for ambitus | 268 // may happen for ambitus |
269 continue; | 269 continue; |
270 } | 270 } |
271 | 271 |
272 | |
273 SCM left_articulations = left_ev->get_property ("articulations"); | 272 SCM left_articulations = left_ev->get_property ("articulations"); |
274 | 273 |
275 Stream_event *tie_event = 0; | 274 Stream_event *tie_event = 0; |
276 Stream_event *tie_stream_event = event_; | 275 Stream_event *tie_stream_event = event_; |
277 for (SCM s = left_articulations; | 276 for (SCM s = left_articulations; |
278 !tie_event && !tie_stream_event && scm_is_pair (s); | 277 !tie_event && !tie_stream_event && scm_is_pair (s); |
279 s = scm_cdr (s)) | 278 s = scm_cdr (s)) |
280 { | 279 { |
281 Stream_event *ev = unsmob_stream_event (scm_car (s)); | 280 Stream_event *ev = unsmob_stream_event (scm_car (s)); |
282 if (!ev) | 281 if (!ev) |
283 continue; | 282 continue; |
284 | 283 |
285 if (ev->in_event_class ("tie-event")) | 284 if (ev->in_event_class ("tie-event")) |
286 tie_event = ev; | 285 tie_event = ev; |
287 } | 286 } |
288 | 287 |
289 if (left_ev && (tie_event || tie_stream_event) | 288 if (left_ev && (tie_event || tie_stream_event) |
290 && (!Tie_engraver::has_autosplit_end (left_ev))) | 289 » && (!Tie_engraver::has_autosplit_end (left_ev))) |
291 { | 290 » { |
292 event_processed = true; | 291 » event_processed = true; |
293 | 292 |
294 Head_event_tuple event_tup; | 293 Head_event_tuple event_tup; |
295 | 294 |
296 SCM start_definition | 295 SCM start_definition |
297 = updated_grob_properties (context (), ly_symbol2scm ("Tie")); | 296 = updated_grob_properties (context (), ly_symbol2scm ("Tie")); |
298 | 297 |
299 event_tup.head_ = head; | 298 event_tup.head_ = head; |
300 event_tup.tie_definition_ = start_definition; | 299 event_tup.tie_definition_ = start_definition; |
301 event_tup.tie_event_ = tie_event; | 300 event_tup.tie_event_ = tie_event; |
302 event_tup.tie_stream_event_ = tie_stream_event; | 301 event_tup.tie_stream_event_ = tie_stream_event; |
303 | 302 |
304 Moment end = now_mom (); | 303 Moment end = now_mom (); |
305 if (end.grace_part_) | 304 if (end.grace_part_) |
306 { | 305 { |
307 end.grace_part_ += get_event_length (left_ev).main_part_; | 306 end.grace_part_ += get_event_length (left_ev).main_part_; |
308 } | 307 } |
309 else | 308 else |
310 { | 309 { |
311 end += get_event_length (left_ev); | 310 end += get_event_length (left_ev); |
312 } | 311 } |
313 event_tup.end_moment_ = end; | 312 event_tup.end_moment_ = end; |
314 | 313 |
315 new_heads_to_tie.push_back (event_tup); | 314 new_heads_to_tie.push_back (event_tup); |
316 } | 315 } |
317 } | 316 } |
318 | 317 |
319 if (!wait && new_heads_to_tie.size ()) | 318 if (!wait && new_heads_to_tie.size ()) |
320 { | 319 { |
321 vector<Head_event_tuple>::iterator it=heads_to_tie_.begin (); | 320 vector<Head_event_tuple>::iterator it = heads_to_tie_.begin (); |
322 for (; it < heads_to_tie_.end (); it++) | 321 for (; it < heads_to_tie_.end (); it++) |
323 report_unterminated_tie (*it); | 322 » report_unterminated_tie (*it); |
324 heads_to_tie_.clear (); | 323 heads_to_tie_.clear (); |
325 } | 324 } |
326 | 325 |
327 // hmmm, how to do with copy () ? | 326 // hmmm, how to do with copy () ? |
328 for (vsize i = 0; i < new_heads_to_tie.size (); i++) | 327 for (vsize i = 0; i < new_heads_to_tie.size (); i++) |
329 heads_to_tie_.push_back (new_heads_to_tie[i]); | 328 heads_to_tie_.push_back (new_heads_to_tie[i]); |
330 | 329 |
331 /* | 330 /* |
332 Discard event only if it has been processed with at least one | 331 Discard event only if it has been processed with at least one |
333 appropriate note. | 332 appropriate note. |
(...skipping 14 matching lines...) Expand all Loading... | |
348 Drul_array<Grob *> new_head_drul; | 347 Drul_array<Grob *> new_head_drul; |
349 new_head_drul[LEFT] = Tie::head (her, LEFT); | 348 new_head_drul[LEFT] = Tie::head (her, LEFT); |
350 new_head_drul[RIGHT] = Tie::head (her, RIGHT); | 349 new_head_drul[RIGHT] = Tie::head (her, RIGHT); |
351 do | 350 do |
352 { | 351 { |
353 if (!Tie::head (her, d)) | 352 if (!Tie::head (her, d)) |
354 new_head_drul[d] = Tie::head (her, (Direction) - d); | 353 new_head_drul[d] = Tie::head (her, (Direction) - d); |
355 } | 354 } |
356 while (flip (&d) != LEFT); | 355 while (flip (&d) != LEFT); |
357 | 356 |
358 Spanner *sp = dynamic_cast<Spanner*> (her); | 357 Spanner *sp = dynamic_cast<Spanner *> (her); |
359 sp->set_bound (LEFT, new_head_drul[LEFT]); | 358 sp->set_bound (LEFT, new_head_drul[LEFT]); |
360 sp->set_bound (RIGHT, new_head_drul[RIGHT]); | 359 sp->set_bound (RIGHT, new_head_drul[RIGHT]); |
361 } | 360 } |
362 | 361 |
363 ADD_ACKNOWLEDGER (Tie_engraver, note_head); | 362 ADD_ACKNOWLEDGER (Tie_engraver, note_head); |
364 ADD_TRANSLATOR (Tie_engraver, | 363 ADD_TRANSLATOR (Tie_engraver, |
365 /* doc */ | 364 /* doc */ |
366 "Generate ties between note heads of equal pitch.", | 365 "Generate ties between note heads of equal pitch.", |
367 | 366 |
368 /* create */ | 367 /* create */ |
369 "Tie " | 368 "Tie " |
370 "TieColumn ", | 369 "TieColumn ", |
371 | 370 |
372 /* read */ | 371 /* read */ |
373 "tieWaitForNote ", | 372 "tieWaitForNote ", |
374 | 373 |
375 /* write */ | 374 /* write */ |
376 "tieMelismaBusy " | 375 "tieMelismaBusy " |
377 ); | 376 ); |
LEFT | RIGHT |