2 piano-pedal-engraver.cc -- implement Piano_pedal_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2009 Jan Nieuwenhuizen <janneke@gnu.org>,
7 Erik Sandberg <mandolaerik@gmail.com>
9 Chris Jackson <chris@fluffhouse.org.uk> - extended to support
13 #include "engraver.hh"
15 #include "axis-group-interface.hh"
17 #include "directional-element-interface.hh"
18 #include "international.hh"
19 #include "lily-guile.hh"
20 #include "note-column.hh"
21 #include "side-position-interface.hh"
22 #include "staff-symbol-referencer.hh"
23 #include "stream-event.hh"
24 #include "string-convert.hh"
29 #include "translator.icc"
36 * Junk hardcoded sustain/sostenuto/una_corda distinction;
37 Softcode using (list (sustain-event SustainPedal PianoPedalBracket) ... )
39 * Try to use same engraver for dynamics.
43 /* Ugh: This declaration is duplicated in piano-pedal-performer */
52 Static precalculated data (symbols and strings) for the different
55 struct Pedal_type_info
62 const char *pedal_c_str_
;
66 event_class_sym_
= SCM_EOL
;
68 strings_sym_
= SCM_EOL
;
73 scm_gc_protect_object (event_class_sym_
);
74 scm_gc_protect_object (style_sym_
);
75 scm_gc_protect_object (strings_sym_
);
81 const Pedal_type_info
*type_
;
84 Event for currently running pedal.
86 Stream_event
*current_bracket_ev_
;
89 Event for currently starting pedal, (necessary?
91 distinct from current_bracket_ev_, since current_bracket_ev_ only
92 necessary for brackets, not for text style.
94 Stream_event
*start_ev_
;
97 Events that were found in this timestep.
99 Drul_array
<Stream_event
*> event_drul_
;
101 Spanner
*bracket_
; // A single portion of a pedal bracket
102 Spanner
*finished_bracket_
;
105 static Pedal_type_info pedal_types_
[NUM_PEDAL_TYPES
];
107 class Piano_pedal_engraver
: public Engraver
110 TRANSLATOR_DECLARATIONS (Piano_pedal_engraver
);
113 virtual void initialize ();
114 virtual void finalize ();
115 DECLARE_TRANSLATOR_LISTENER (sustain
);
116 DECLARE_TRANSLATOR_LISTENER (una_corda
);
117 DECLARE_TRANSLATOR_LISTENER (sostenuto
);
118 DECLARE_ACKNOWLEDGER (note_column
);
119 void stop_translation_timestep ();
120 void process_music ();
123 Pedal_info info_list_
[NUM_PEDAL_TYPES
+ 1];
125 void create_text_grobs (Pedal_info
*p
, bool);
126 void create_bracket_grobs (Pedal_info
*p
, bool);
127 void typeset_all (Pedal_info
*p
);
134 const char *names
[NUM_PEDAL_TYPES
];
135 names
[SOSTENUTO
] = "Sostenuto";
136 names
[SUSTAIN
] = "Sustain";
137 names
[UNA_CORDA
] = "UnaCorda";
139 for (int i
= 0; i
< NUM_PEDAL_TYPES
; i
++)
141 const char *name
= names
[i
];
143 string base_name
= name
;
145 string base_ident
= "";
148 for (cur_pos
= 1; name
[cur_pos
]; cur_pos
++)
149 if (isupper (name
[cur_pos
]))
151 base_ident
= base_ident
+ String_convert::to_lower (string (name
, prev_pos
, cur_pos
- prev_pos
)) + "-";
154 base_ident
+= String_convert::to_lower (string (name
, prev_pos
, cur_pos
- prev_pos
));
157 be careful, as we don't want to loose references to the _sym_ members.
159 Pedal_type_info info
;
160 info
.event_class_sym_
= scm_str2symbol ((base_ident
+ "-event").c_str ());
161 info
.style_sym_
= scm_str2symbol (("pedal" + base_name
+ "Style").c_str ());
162 info
.strings_sym_
= scm_str2symbol (("pedal" + base_name
+ "Strings").c_str ());
164 info
.base_name_
= name
;
165 info
.pedal_c_str_
= strdup ((base_name
+ "Pedal").c_str ());
169 pedal_types_
[i
] = info
;
173 ADD_SCM_INIT_FUNC (Piano_pedal_engraver_init_pedal_types_
, init_pedal_types
);
175 Piano_pedal_engraver::Piano_pedal_engraver ()
180 Piano_pedal_engraver::initialize ()
182 for (int i
= 0; i
< NUM_PEDAL_TYPES
; i
++)
184 Pedal_type_info
*s
= &pedal_types_
[i
];
185 Pedal_info
*info
= &info_list_
[i
];
190 info
->finished_bracket_
= 0;
191 info
->current_bracket_ev_
= 0;
192 info
->event_drul_
[START
] = 0;
193 info
->event_drul_
[STOP
] = 0;
196 info_list_
[NUM_PEDAL_TYPES
].type_
= 0;
205 Piano_pedal_engraver::acknowledge_note_column (Grob_info info
)
207 for (Pedal_info
*p
= info_list_
; p
->type_
; p
++)
210 add_bound_item (p
->bracket_
, info
.grob ());
211 if (p
->finished_bracket_
)
212 add_bound_item (p
->finished_bracket_
, info
.grob ());
216 IMPLEMENT_TRANSLATOR_LISTENER (Piano_pedal_engraver
, sostenuto
);
218 Piano_pedal_engraver::listen_sostenuto (Stream_event
*ev
)
220 Direction d
= to_dir (ev
->get_property ("span-direction"));
221 ASSIGN_EVENT_ONCE (info_list_
[SOSTENUTO
].event_drul_
[d
], ev
);
224 IMPLEMENT_TRANSLATOR_LISTENER (Piano_pedal_engraver
, sustain
);
226 Piano_pedal_engraver::listen_sustain (Stream_event
*ev
)
228 Direction d
= to_dir (ev
->get_property ("span-direction"));
229 ASSIGN_EVENT_ONCE (info_list_
[SUSTAIN
].event_drul_
[d
], ev
);
232 IMPLEMENT_TRANSLATOR_LISTENER (Piano_pedal_engraver
, una_corda
);
234 Piano_pedal_engraver::listen_una_corda (Stream_event
*ev
)
236 Direction d
= to_dir (ev
->get_property ("span-direction"));
237 ASSIGN_EVENT_ONCE (info_list_
[UNA_CORDA
].event_drul_
[d
], ev
);
241 Piano_pedal_engraver::process_music ()
243 for (Pedal_info
*p
= info_list_
; p
->type_
; p
++)
245 if (p
->event_drul_
[STOP
] || p
->event_drul_
[START
])
247 /* Choose the appropriate grobs to add to the line spanner
248 These can be text items or text-spanners
252 ugh, code dup, should read grob to create from other
255 bracket: |_________/\____|
257 mixed: Ped. _____/\____|
260 SCM style
= internal_get_property (p
->type_
->style_sym_
);
262 bool mixed
= style
== ly_symbol2scm ("mixed");
263 bool bracket
= (mixed
264 || style
== ly_symbol2scm ("bracket"));
265 bool text
= (style
== ly_symbol2scm ("text")
268 if (text
&& !p
->item_
)
269 create_text_grobs (p
, mixed
);
271 create_bracket_grobs (p
, mixed
);
277 Piano_pedal_engraver::create_text_grobs (Pedal_info
*p
, bool mixed
)
280 SCM strings
= internal_get_property (p
->type_
->strings_sym_
);
282 if (scm_ilength (strings
) < 3)
284 Stream_event
*m
= p
->event_drul_
[START
];
285 if (!m
) m
= p
->event_drul_
[STOP
];
287 string msg
= _f ("expect 3 strings for piano pedals, found: %ld",
288 scm_ilength (strings
));
290 m
->origin ()->warning (msg
);
297 if (p
->event_drul_
[STOP
] && p
->event_drul_
[START
])
302 p
->event_drul_
[STOP
]->origin ()->warning (_f ("cannot find start of piano pedal: `%s'", p
->type_
->base_name_
.c_str ()));
304 s
= scm_cadr (strings
);
305 p
->start_ev_
= p
->event_drul_
[START
];
308 else if (p
->event_drul_
[STOP
])
313 p
->event_drul_
[STOP
]->origin ()->warning (_f ("cannot find start of piano pedal: `%s'", p
->type_
->base_name_
.c_str ()));
315 s
= scm_caddr (strings
);
319 else if (p
->event_drul_
[START
])
321 p
->start_ev_
= p
->event_drul_
[START
];
322 s
= scm_car (strings
);
325 if (scm_is_string (s
))
327 const char *propname
= p
->type_
->pedal_c_str_
;
329 p
->item_
= make_item (propname
, (p
->event_drul_
[START
]
330 ? p
->event_drul_
[START
]
331 : p
->event_drul_
[STOP
])->self_scm ());
333 p
->item_
->set_property ("text", s
);
338 p
->event_drul_
[START
] = 0;
339 p
->event_drul_
[STOP
] = 0;
344 Piano_pedal_engraver::create_bracket_grobs (Pedal_info
*p
, bool mixed
)
346 if (!p
->bracket_
&& p
->event_drul_
[STOP
])
348 string msg
= _f ("cannot find start of piano pedal bracket: `%s'", p
->type_
->base_name_
.c_str ());
349 p
->event_drul_
[STOP
]->origin ()->warning (msg
);
350 p
->event_drul_
[STOP
] = 0;
353 if (p
->event_drul_
[STOP
])
355 assert (!p
->finished_bracket_
);
357 Grob
*cmc
= unsmob_grob (get_property ("currentMusicalColumn"));
359 if (!p
->bracket_
->get_bound (RIGHT
))
360 p
->bracket_
->set_bound (RIGHT
, cmc
);
363 Set properties so that the stencil-creating function will
364 know whether the right edge should be flared ___/
367 if (!p
->event_drul_
[START
])
369 SCM flare
= p
->bracket_
->get_property ("bracket-flare");
370 if (scm_is_pair (flare
))
371 p
->bracket_
->set_property ("bracket-flare", scm_cons (scm_car (flare
),
372 scm_from_double (0)));
375 p
->finished_bracket_
= p
->bracket_
;
378 announce_end_grob (p
->finished_bracket_
, p
->event_drul_
[STOP
]->self_scm ());
380 p
->current_bracket_ev_
= 0;
383 if (p
->event_drul_
[START
])
385 p
->start_ev_
= p
->event_drul_
[START
];
386 p
->current_bracket_ev_
= p
->event_drul_
[START
];
388 p
->bracket_
= make_spanner ("PianoPedalBracket", p
->event_drul_
[START
]->self_scm ());
391 Set properties so that the stencil-creating function will
392 know whether the left edge should be flared \___
395 if (!p
->finished_bracket_
)
397 SCM flare
= p
->bracket_
->get_property ("bracket-flare");
398 p
->bracket_
->set_property ("bracket-flare", scm_cons (scm_from_double (0), scm_cdr (flare
)));
401 /* Set this property for 'mixed style' pedals, Ped._______/\ ,
402 so the stencil function will shorten the ____ line by the length of the Ped. text.
408 Mixed style: Store a pointer to the preceding text for use in
409 calculating the length of the line
414 WTF is pedal-text not the bound of the object? --hwn
417 p
->bracket_
->set_object ("pedal-text", p
->item_
->self_scm ());
421 p
->event_drul_
[START
] = 0;
422 p
->event_drul_
[STOP
] = 0;
426 Piano_pedal_engraver::finalize ()
428 for (Pedal_info
*p
= info_list_
; p
->type_
; p
++)
431 && !p
->bracket_
->is_live ())
436 SCM cc
= get_property ("currentCommandColumn");
437 Item
*c
= unsmob_item (cc
);
438 p
->bracket_
->set_bound (RIGHT
, c
);
440 p
->finished_bracket_
= p
->bracket_
;
449 Piano_pedal_engraver::stop_translation_timestep ()
451 for (Pedal_info
*p
= info_list_
; p
->type_
; p
++)
455 if (p
->bracket_
&& !p
->bracket_
->get_bound (LEFT
))
457 Grob
*cmc
= unsmob_grob (get_property ("currentMusicalColumn"));
459 if (!p
->bracket_
->get_bound (LEFT
))
460 p
->bracket_
->set_bound (LEFT
, cmc
);
464 for (Pedal_info
*p
= info_list_
; p
->type_
; p
++)
466 p
->event_drul_
[STOP
] = 0;
467 p
->event_drul_
[START
] = 0;
472 Piano_pedal_engraver::typeset_all (Pedal_info
*p
)
477 if (p
->finished_bracket_
478 && !p
->finished_bracket_
->is_live ())
479 p
->finished_bracket_
= 0;
484 if (p
->finished_bracket_
)
486 Grob
*r
= p
->finished_bracket_
->get_bound (RIGHT
);
488 p
->finished_bracket_
->set_bound (RIGHT
, unsmob_grob (get_property ("currentMusicalColumn")));
490 p
->finished_bracket_
= 0;
494 ADD_ACKNOWLEDGER (Piano_pedal_engraver
, note_column
);
496 ADD_TRANSLATOR (Piano_pedal_engraver
,
498 "Engrave piano pedal symbols and brackets.",
507 "currentCommandColumn "
508 "pedalSostenutoStrings "
509 "pedalSostenutoStyle "
510 "pedalSustainStrings "
512 "pedalUnaCordaStrings "
513 "pedalUnaCordaStyle ",