Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1177)

Delta Between Two Patch Sets: lily/phrasing-slur-engraver.cc

Issue 7424049: Allows slurs to break at barlines.
Left Patch Set: Breaks slurs at repeats by default. Created 12 years, 1 month ago
Right Patch Set: Changes name, harmonizes slur direction Created 12 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « lily/include/slur-proto-engraver.hh ('k') | lily/slur.cc » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl> 4 Copyright (C) 1997--2012 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
11 LilyPond is distributed in the hope that it will be useful, 11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details. 14 GNU General Public License for more details.
15 15
16 You should have received a copy of the GNU General Public License 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/>. 17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
18 */ 18 */
19 19
20 #include "engraver.hh" 20 #include "engraver.hh"
21 21
22 #include "context.hh" 22 #include "context.hh"
23 #include "directional-element-interface.hh" 23 #include "directional-element-interface.hh"
24 #include "international.hh" 24 #include "international.hh"
25 #include "note-column.hh" 25 #include "note-column.hh"
26 #include "slur.hh" 26 #include "slur.hh"
27 #include "slur-proto-engraver.hh"
27 #include "spanner.hh" 28 #include "spanner.hh"
28 #include "stream-event.hh" 29 #include "stream-event.hh"
29 #include "warn.hh" 30 #include "warn.hh"
30 31
31 #include "translator.icc" 32 #include "translator.icc"
32 33
33 /* 34 class Phrasing_slur_engraver : public Slur_proto_engraver
34 NOTE NOTE NOTE
35
36 This is largely similar to Slur_engraver. Check if fixes
37 apply there too.
38
39 (on principle, engravers don't use inheritance for code sharing)
40
41 */
42
43 /*
44 It is possible that a slur starts and ends on the same note. At
45 least, it is for phrasing slurs: a note can be both beginning and
46 ending of a phrase.
47 */
48 class Phrasing_slur_engraver : public Engraver
49 { 35 {
50 vector<Stream_event *> start_events_;
51 vector<Stream_event *> stop_events_;
52 vector<Grob *> slurs_;
53 vector<Grob *> end_slurs_;
54 vector<Grob_info> objects_to_acknowledge_;
55 Stream_event *break_slur_;
56
57 protected: 36 protected:
58 DECLARE_TRANSLATOR_LISTENER (phrasing_slur); 37 DECLARE_TRANSLATOR_LISTENER (phrasing_slur);
59 DECLARE_TRANSLATOR_LISTENER (break_phrasing_slur); 38 DECLARE_TRANSLATOR_LISTENER (break_phrasing_slur);
60 DECLARE_ACKNOWLEDGER (inline_accidental);
61 DECLARE_ACKNOWLEDGER (fingering);
62 DECLARE_ACKNOWLEDGER (note_column);
63 DECLARE_ACKNOWLEDGER (slur); 39 DECLARE_ACKNOWLEDGER (slur);
64 DECLARE_ACKNOWLEDGER (script);
65 DECLARE_ACKNOWLEDGER (dots);
66 DECLARE_ACKNOWLEDGER (text_script);
67 DECLARE_END_ACKNOWLEDGER (tie);
68 DECLARE_ACKNOWLEDGER (tuplet_number);
69
70 void acknowledge_extra_object (Grob_info);
71 void stop_translation_timestep ();
72 void process_music ();
73
74 virtual void finalize ();
75 virtual void derived_mark () const;
76 40
77 public: 41 public:
78 TRANSLATOR_DECLARATIONS (Phrasing_slur_engraver); 42 TRANSLATOR_DECLARATIONS (Phrasing_slur_engraver);
79 }; 43 };
80 44
81 Phrasing_slur_engraver::Phrasing_slur_engraver () 45 Phrasing_slur_engraver::Phrasing_slur_engraver () :
46 Slur_proto_engraver (0, "PhrasingSlur", "phrasing slur", "phrasing-slur-event" )
82 { 47 {
83 } 48 break_slur_ = 0;
84
85 void
86 Phrasing_slur_engraver::derived_mark () const
87 {
88 for (vsize i = start_events_.size (); i--;)
89 scm_gc_mark (start_events_[i]->self_scm ());
90 for (vsize i = stop_events_.size (); i--;)
91 scm_gc_mark (stop_events_[i]->self_scm ());
92 } 49 }
93 50
94 IMPLEMENT_TRANSLATOR_LISTENER (Phrasing_slur_engraver, phrasing_slur); 51 IMPLEMENT_TRANSLATOR_LISTENER (Phrasing_slur_engraver, phrasing_slur);
95 void 52 void
96 Phrasing_slur_engraver::listen_phrasing_slur (Stream_event *ev) 53 Phrasing_slur_engraver::listen_phrasing_slur (Stream_event *ev)
97 { 54 {
98 Direction d = to_dir (ev->get_property ("span-direction")); 55 internal_listen_slur (ev);
99 if (d == START)
100 start_events_.push_back (ev);
101 else if (d == STOP)
102 stop_events_.push_back (ev);
103 else ev->origin ()->warning (_f ("direction of %s invalid: %d",
104 "phrasing-slur-event", int (d)));
105 } 56 }
106 57
107 IMPLEMENT_TRANSLATOR_LISTENER (Phrasing_slur_engraver, break_phrasing_slur); 58 IMPLEMENT_TRANSLATOR_LISTENER (Phrasing_slur_engraver, break_phrasing_slur);
108 void 59 void
109 Phrasing_slur_engraver::listen_break_phrasing_slur (Stream_event *ev) 60 Phrasing_slur_engraver::listen_break_phrasing_slur (Stream_event *ev)
110 { 61 {
111 ASSIGN_EVENT_ONCE (break_slur_, ev); 62 internal_listen_break_slur (ev);
112 }
113
114 void
115 Phrasing_slur_engraver::acknowledge_note_column (Grob_info info)
116 {
117 Grob *e = info.grob ();
118 for (vsize i = slurs_.size (); i--;)
119 Slur::add_column (slurs_[i], e);
120 for (vsize i = end_slurs_.size (); i--;)
121 Slur::add_column (end_slurs_[i], e);
122 }
123
124 void
125 Phrasing_slur_engraver::acknowledge_extra_object (Grob_info info)
126 {
127 objects_to_acknowledge_.push_back (info);
128 }
129
130 void
131 Phrasing_slur_engraver::acknowledge_inline_accidental (Grob_info info)
132 {
133 acknowledge_extra_object (info);
134 }
135
136 void
137 Phrasing_slur_engraver::acknowledge_dots (Grob_info info)
138 {
139 acknowledge_extra_object (info);
140 }
141
142 void
143 Phrasing_slur_engraver::acknowledge_fingering (Grob_info info)
144 {
145 acknowledge_extra_object (info);
146 }
147
148 void
149 Phrasing_slur_engraver::acknowledge_tuplet_number (Grob_info info)
150 {
151 acknowledge_extra_object (info);
152 }
153
154 void
155 Phrasing_slur_engraver::acknowledge_script (Grob_info info)
156 {
157 if (!info.grob ()->internal_has_interface (ly_symbol2scm ("dynamic-interface") ))
158 acknowledge_extra_object (info);
159 }
160
161 void
162 Phrasing_slur_engraver::acknowledge_text_script (Grob_info info)
163 {
164 acknowledge_extra_object (info);
165 }
166
167 void
168 Phrasing_slur_engraver::acknowledge_end_tie (Grob_info info)
169 {
170 acknowledge_extra_object (info);
171 } 63 }
172 64
173 void 65 void
174 Phrasing_slur_engraver::acknowledge_slur (Grob_info info) 66 Phrasing_slur_engraver::acknowledge_slur (Grob_info info)
175 { 67 {
176 acknowledge_extra_object (info); 68 acknowledge_extra_object (info);
177 }
178
179 void
180 Phrasing_slur_engraver::finalize ()
181 {
182 for (vsize i = 0; i < slurs_.size (); i++)
183 {
184 slurs_[i]->warning (_ ("unterminated phrasing slur"));
185 slurs_[i]->suicide ();
186 }
187 slurs_.clear ();
188 }
189
190 void
191 Phrasing_slur_engraver::process_music ()
192 {
193 if (break_slur_
194 && unsmob_grob (get_property ("currentCommandColumn")))
195 {
196 for (vsize i = slurs_.size (); i--;)
197 {
198 Grob *ccc = unsmob_grob (get_property ("currentCommandColumn"));
199 Spanner *s = dynamic_cast<Spanner *> (slurs_[i]);
200 s->set_bound (RIGHT, ccc);
201 announce_end_grob (s, SCM_EOL);
202 slurs_.erase (slurs_.begin () + i);
203 if (robust_scm2dir (break_slur_->get_property ("side-to-junk"), CENTER ) == LEFT)
204 s->suicide ();
205
206 if (robust_scm2dir (break_slur_->get_property ("side-to-junk"), CENTER ) != RIGHT)
207 {
208 SCM spanner_id = s->get_property ("spanner-id");
209 Spanner *slur = make_spanner ("Slur", s->self_scm ());
210 slur->set_property ("spanner-id", spanner_id);
211 if (scm_is_number (s->get_property_data ("direction")))
212 set_grob_direction (slur, robust_scm2dir (s->get_property ("dire ction"), UP));
213 slur->set_bound (LEFT, ccc);
214 slurs_.push_back (slur);
215 }
216 }
217 }
218 else if (to_boolean (get_property ("breakSlurHere")))
219 warning ("no current command column to break slur");
220
221 for (vsize i = 0; i < stop_events_.size (); i++)
222 {
223 Stream_event *ev = stop_events_[i];
224 string id = robust_scm2string (ev->get_property ("spanner-id"), "");
225
226 // Find the slurs that are ended with this event (by checking the spanner- id)
227 bool ended = false;
228 for (vsize j = slurs_.size (); j--;)
229 {
230 if (id == robust_scm2string (slurs_[j]->get_property ("spanner-id"), " "))
231 {
232 ended = true;
233 end_slurs_.push_back (slurs_[j]);
234 slurs_.erase (slurs_.begin () + j);
235 }
236 }
237 if (ended)
238 {
239 // Ignore redundant stop events for this id
240 for (vsize j = stop_events_.size (); --j > i;)
241 {
242 if (id == robust_scm2string (stop_events_[j]->get_property ("spann er-id"), ""))
243 stop_events_.erase (stop_events_.begin () + j);
244 }
245 }
246 else
247 ev->origin ()->warning (_ ("cannot end phrasing slur"));
248 }
249
250 vsize old_slurs = slurs_.size ();
251 for (vsize i = start_events_.size (); i--;)
252 {
253 Stream_event *ev = start_events_[i];
254 string id = robust_scm2string (ev->get_property ("spanner-id"), "");
255 Direction updown = to_dir (ev->get_property ("direction"));
256
257 bool completed;
258 for (vsize j = slurs_.size (); !(completed = (j-- == 0));)
259 {
260 // Check if we already have a slur with the same spanner-id.
261 if (id == robust_scm2string (slurs_[j]->get_property ("spanner-id"), " "))
262 {
263 if (j < old_slurs)
264 {
265 // We already have an old slur, so give a warning
266 // and completely ignore the new slur.
267 ev->origin ()->warning (_ ("already have phrasing slur"));
268 start_events_.erase (start_events_.begin () + i);
269 break;
270 }
271
272 // If this slur event has no direction, it will not
273 // contribute anything new to the existing slur(s), so
274 // we can ignore it.
275
276 if (!updown)
277 break;
278
279 Stream_event *c = unsmob_stream_event (slurs_[j]->get_property ("c ause"));
280
281 if (!c)
282 {
283 slurs_[j]->programming_error ("phrasing slur without a cause") ;
284 continue;
285 }
286
287 Direction slur_dir = to_dir (c->get_property ("direction"));
288
289 // If the existing slur does not have a direction yet,
290 // we'd rather take the new one.
291
292 if (!slur_dir)
293 {
294 slurs_[j]->suicide ();
295 slurs_.erase (slurs_.begin () + j);
296 continue;
297 }
298
299 // If the existing slur has the same direction as ours, drop ours
300
301 if (slur_dir == updown)
302 break;
303 }
304 }
305 // If the loop completed, our slur is new
306 if (completed)
307 {
308 Grob *slur = make_spanner ("PhrasingSlur", ev->self_scm ());
309 slur->set_property ("spanner-id", ly_string2scm (id));
310 if (updown)
311 set_grob_direction (slur, updown);
312 slurs_.push_back (slur);
313 }
314 }
315 }
316
317 void
318 Phrasing_slur_engraver::stop_translation_timestep ()
319 {
320 if (Grob *g = unsmob_grob (get_property ("currentCommandColumn")))
321 {
322 for (vsize i = 0; i < end_slurs_.size (); i++)
323 Slur::add_extra_encompass (end_slurs_[i], g);
324
325 if (!start_events_.size ())
326 for (vsize i = 0; i < slurs_.size (); i++)
327 Slur::add_extra_encompass (slurs_[i], g);
328 }
329
330 for (vsize i = 0; i < end_slurs_.size (); i++)
331 {
332 Spanner *s = dynamic_cast<Spanner *> (end_slurs_[i]);
333 if (!s->get_bound (RIGHT))
334 s->set_bound (RIGHT, unsmob_grob (get_property ("currentMusicalColumn")) );
335 announce_end_grob (s, SCM_EOL);
336 }
337
338 for (vsize i = 0; i < objects_to_acknowledge_.size (); i++)
339 Slur::auxiliary_acknowledge_extra_object (objects_to_acknowledge_[i], slurs_ , end_slurs_);
340
341 objects_to_acknowledge_.clear ();
342 end_slurs_.clear ();
343 start_events_.clear ();
344 stop_events_.clear ();
345 break_slur_ = 0;
346 } 69 }
347 70
348 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, inline_accidental); 71 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, inline_accidental);
349 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, fingering) 72 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, fingering)
350 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, note_column); 73 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, note_column);
351 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, slur); 74 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, slur);
352 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, script); 75 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, script);
353 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, dots); 76 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, dots);
354 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, text_script); 77 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, text_script);
355 ADD_END_ACKNOWLEDGER (Phrasing_slur_engraver, tie); 78 ADD_END_ACKNOWLEDGER (Phrasing_slur_engraver, tie);
356 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, tuplet_number); 79 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, tuplet_number);
357 80
358 ADD_TRANSLATOR (Phrasing_slur_engraver, 81 ADD_TRANSLATOR (Phrasing_slur_engraver,
359 /* doc */ 82 /* doc */
360 "Print phrasing slurs. Similar to @ref{Slur_engraver}.", 83 "Print phrasing slurs. Similar to @ref{Slur_engraver}.",
361 84
362 /* create */ 85 /* create */
363 "PhrasingSlur ", 86 "PhrasingSlur ",
364 87
365 /* read */ 88 /* read */
366 "", 89 "",
367 90
368 /* write */ 91 /* write */
369 "" 92 ""
370 ); 93 );
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b