2 piano-pedal-engraver.cc -- implement Piano_pedal_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2007 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"
35 * Junk hardcoded sustain/sostenuto/una_corda distinction;
36 Softcode using (list (sustain-event SustainPedal PianoPedalBracket) ... )
38 * Try to use same engraver for dynamics.
42 /* Ugh: This declaration is duplicated in piano-pedal-performer */
43 typedef enum Pedal_type
{
51 Static precalculated data (symbols and strings) for the different
54 struct Pedal_type_info
61 const char *pedal_c_str_
;
65 event_class_sym_
= SCM_EOL
;
67 strings_sym_
= SCM_EOL
;
72 scm_gc_protect_object (event_class_sym_
);
73 scm_gc_protect_object (style_sym_
);
74 scm_gc_protect_object (strings_sym_
);
80 const Pedal_type_info
*type_
;
83 Event for currently running pedal.
85 Stream_event
*current_bracket_ev_
;
88 Event for currently starting pedal, (necessary?
90 distinct from current_bracket_ev_, since current_bracket_ev_ only
91 necessary for brackets, not for text style.
93 Stream_event
*start_ev_
;
96 Events that were found in this timestep.
98 Drul_array
<Stream_event
*> event_drul_
;
100 Spanner
*bracket_
; // A single portion of a pedal bracket
101 Spanner
*finished_bracket_
;
104 static Pedal_type_info pedal_types_
[NUM_PEDAL_TYPES
];
106 class Piano_pedal_engraver
: public Engraver
109 TRANSLATOR_DECLARATIONS (Piano_pedal_engraver
);
112 virtual void initialize ();
113 virtual void finalize ();
114 DECLARE_TRANSLATOR_LISTENER (sustain
);
115 DECLARE_TRANSLATOR_LISTENER (una_corda
);
116 DECLARE_TRANSLATOR_LISTENER (sostenuto
);
117 DECLARE_ACKNOWLEDGER (note_column
);
118 void stop_translation_timestep ();
119 void process_music ();
122 Pedal_info info_list_
[NUM_PEDAL_TYPES
+ 1];
124 void create_text_grobs (Pedal_info
*p
, bool);
125 void create_bracket_grobs (Pedal_info
*p
, bool);
126 void typeset_all (Pedal_info
*p
);
133 const char *names
[NUM_PEDAL_TYPES
];
134 names
[SOSTENUTO
] = "Sostenuto";
135 names
[SUSTAIN
] = "Sustain";
136 names
[UNA_CORDA
] = "UnaCorda";
138 for (int i
= 0; i
< NUM_PEDAL_TYPES
; i
++)
140 const char *name
= names
[i
];
142 string base_name
= name
;
144 string base_ident
= "";
147 for (cur_pos
= 1; name
[cur_pos
]; cur_pos
++)
148 if (isupper (name
[cur_pos
]))
150 base_ident
= base_ident
+ String_convert::to_lower (string (name
, prev_pos
, cur_pos
- prev_pos
)) + "-";
153 base_ident
+= String_convert::to_lower (string (name
, prev_pos
, cur_pos
- prev_pos
));
156 be careful, as we don't want to loose references to the _sym_ members.
158 Pedal_type_info info
;
159 info
.event_class_sym_
= scm_str2symbol ((base_ident
+ "-event").c_str ());
160 info
.style_sym_
= scm_str2symbol (("pedal" + base_name
+ "Style").c_str ());
161 info
.strings_sym_
= scm_str2symbol (("pedal" + base_name
+ "Strings").c_str ());
163 info
.base_name_
= name
;
164 info
.pedal_c_str_
= strdup ((base_name
+ "Pedal").c_str ());
168 pedal_types_
[i
] = info
;
172 ADD_SCM_INIT_FUNC (Piano_pedal_engraver_init_pedal_types_
, init_pedal_types
);
174 Piano_pedal_engraver::Piano_pedal_engraver ()
179 Piano_pedal_engraver::initialize ()
181 for (int i
= 0; i
< NUM_PEDAL_TYPES
; i
++)
183 Pedal_type_info
*s
= &pedal_types_
[i
];
184 Pedal_info
*info
= &info_list_
[i
];
189 info
->finished_bracket_
= 0;
190 info
->current_bracket_ev_
= 0;
191 info
->event_drul_
[START
] = 0;
192 info
->event_drul_
[STOP
] = 0;
195 info_list_
[NUM_PEDAL_TYPES
].type_
= 0;
204 Piano_pedal_engraver::acknowledge_note_column (Grob_info info
)
206 for (Pedal_info
*p
= info_list_
; p
->type_
; p
++)
209 add_bound_item (p
->bracket_
, info
.grob ());
210 if (p
->finished_bracket_
)
211 add_bound_item (p
->finished_bracket_
, info
.grob ());
215 IMPLEMENT_TRANSLATOR_LISTENER (Piano_pedal_engraver
, sostenuto
);
217 Piano_pedal_engraver::listen_sostenuto (Stream_event
*ev
)
219 Direction d
= to_dir (ev
->get_property ("span-direction"));
220 ASSIGN_EVENT_ONCE (info_list_
[SOSTENUTO
].event_drul_
[d
], ev
);
223 IMPLEMENT_TRANSLATOR_LISTENER (Piano_pedal_engraver
, sustain
);
225 Piano_pedal_engraver::listen_sustain (Stream_event
*ev
)
227 Direction d
= to_dir (ev
->get_property ("span-direction"));
228 ASSIGN_EVENT_ONCE (info_list_
[SUSTAIN
].event_drul_
[d
], ev
);
231 IMPLEMENT_TRANSLATOR_LISTENER (Piano_pedal_engraver
, una_corda
);
233 Piano_pedal_engraver::listen_una_corda (Stream_event
*ev
)
235 Direction d
= to_dir (ev
->get_property ("span-direction"));
236 ASSIGN_EVENT_ONCE (info_list_
[UNA_CORDA
].event_drul_
[d
], ev
);
240 Piano_pedal_engraver::process_music ()
242 for (Pedal_info
*p
= info_list_
; p
->type_
; p
++)
244 if (p
->event_drul_
[STOP
] || p
->event_drul_
[START
])
246 /* Choose the appropriate grobs to add to the line spanner
247 These can be text items or text-spanners
251 ugh, code dup, should read grob to create from other
254 bracket: |_________/\____|
256 mixed: Ped. _____/\____|
259 SCM style
= internal_get_property (p
->type_
->style_sym_
);
261 bool mixed
= style
== ly_symbol2scm ("mixed");
262 bool bracket
= (mixed
263 || style
== ly_symbol2scm ("bracket"));
264 bool text
= (style
== ly_symbol2scm ("text")
267 if (text
&& !p
->item_
)
268 create_text_grobs (p
, mixed
);
270 create_bracket_grobs (p
, mixed
);
276 Piano_pedal_engraver::create_text_grobs (Pedal_info
*p
, bool mixed
)
279 SCM strings
= internal_get_property (p
->type_
->strings_sym_
);
281 if (scm_ilength (strings
) < 3)
283 Stream_event
*m
= p
->event_drul_
[START
];
284 if (!m
) m
= p
->event_drul_
[STOP
];
286 string msg
= _f ("expect 3 strings for piano pedals, found: %ld",
287 scm_ilength (strings
));
289 m
->origin ()->warning (msg
);
296 if (p
->event_drul_
[STOP
] && p
->event_drul_
[START
])
301 p
->event_drul_
[STOP
]->origin ()->warning (_f ("cannot find start of piano pedal: `%s'", p
->type_
->base_name_
.c_str ()));
303 s
= scm_cadr (strings
);
304 p
->start_ev_
= p
->event_drul_
[START
];
307 else if (p
->event_drul_
[STOP
])
312 p
->event_drul_
[STOP
]->origin ()->warning (_f ("cannot find start of piano pedal: `%s'", p
->type_
->base_name_
.c_str ()));
314 s
= scm_caddr (strings
);
318 else if (p
->event_drul_
[START
])
320 p
->start_ev_
= p
->event_drul_
[START
];
321 s
= scm_car (strings
);
324 if (scm_is_string (s
))
326 const char *propname
= p
->type_
->pedal_c_str_
;
328 p
->item_
= make_item (propname
, (p
->event_drul_
[START
]
329 ? p
->event_drul_
[START
]
330 : p
->event_drul_
[STOP
])->self_scm ());
332 p
->item_
->set_property ("text", s
);
337 p
->event_drul_
[START
] = 0;
338 p
->event_drul_
[STOP
] = 0;
343 Piano_pedal_engraver::create_bracket_grobs (Pedal_info
*p
, bool mixed
)
345 if (!p
->bracket_
&& p
->event_drul_
[STOP
])
347 string msg
= _f ("cannot find start of piano pedal bracket: `%s'", p
->type_
->base_name_
.c_str ());
348 p
->event_drul_
[STOP
]->origin ()->warning (msg
);
349 p
->event_drul_
[STOP
] = 0;
352 if (p
->event_drul_
[STOP
])
354 assert (!p
->finished_bracket_
);
356 Grob
*cmc
= unsmob_grob (get_property ("currentMusicalColumn"));
358 if (!p
->bracket_
->get_bound (RIGHT
))
359 p
->bracket_
->set_bound (RIGHT
, cmc
);
362 Set properties so that the stencil-creating function will
363 know whether the right edge should be flared ___/
366 if (!p
->event_drul_
[START
])
368 SCM flare
= p
->bracket_
->get_property ("bracket-flare");
369 if (scm_is_pair (flare
))
370 p
->bracket_
->set_property ("bracket-flare", scm_cons (scm_car (flare
),
371 scm_from_double (0)));
374 p
->finished_bracket_
= p
->bracket_
;
377 announce_end_grob (p
->finished_bracket_
, p
->event_drul_
[STOP
]->self_scm ());
379 p
->current_bracket_ev_
= 0;
382 if (p
->event_drul_
[START
])
384 p
->start_ev_
= p
->event_drul_
[START
];
385 p
->current_bracket_ev_
= p
->event_drul_
[START
];
387 p
->bracket_
= make_spanner ("PianoPedalBracket", p
->event_drul_
[START
]->self_scm ());
390 Set properties so that the stencil-creating function will
391 know whether the left edge should be flared \___
394 if (!p
->finished_bracket_
)
396 SCM flare
= p
->bracket_
->get_property ("bracket-flare");
397 p
->bracket_
->set_property ("bracket-flare", scm_cons (scm_from_double (0), scm_cdr (flare
)));
400 /* Set this property for 'mixed style' pedals, Ped._______/\ ,
401 so the stencil function will shorten the ____ line by the length of the Ped. text.
407 Mixed style: Store a pointer to the preceding text for use in
408 calculating the length of the line
413 WTF is pedal-text not the bound of the object? --hwn
416 p
->bracket_
->set_object ("pedal-text", p
->item_
->self_scm ());
420 p
->event_drul_
[START
] = 0;
421 p
->event_drul_
[STOP
] = 0;
425 Piano_pedal_engraver::finalize ()
427 for (Pedal_info
*p
= info_list_
; p
->type_
; p
++)
430 && !p
->bracket_
->is_live ())
435 SCM cc
= get_property ("currentCommandColumn");
436 Item
*c
= unsmob_item (cc
);
437 p
->bracket_
->set_bound (RIGHT
, c
);
439 p
->finished_bracket_
= p
->bracket_
;
448 Piano_pedal_engraver::stop_translation_timestep ()
450 for (Pedal_info
*p
= info_list_
; p
->type_
; p
++)
454 if (p
->bracket_
&& !p
->bracket_
->get_bound (LEFT
))
456 Grob
*cmc
= unsmob_grob (get_property ("currentMusicalColumn"));
458 if (!p
->bracket_
->get_bound (LEFT
))
459 p
->bracket_
->set_bound (LEFT
, cmc
);
463 for (Pedal_info
*p
= info_list_
; p
->type_
; p
++)
465 p
->event_drul_
[STOP
] = 0;
466 p
->event_drul_
[START
] = 0;
471 Piano_pedal_engraver::typeset_all (Pedal_info
*p
)
476 if (p
->finished_bracket_
477 && !p
->finished_bracket_
->is_live ())
478 p
->finished_bracket_
= 0;
483 if (p
->finished_bracket_
)
485 Grob
*r
= p
->finished_bracket_
->get_bound (RIGHT
);
487 p
->finished_bracket_
->set_bound (RIGHT
, unsmob_grob (get_property ("currentMusicalColumn")));
489 p
->finished_bracket_
= 0;
493 ADD_ACKNOWLEDGER (Piano_pedal_engraver
, note_column
);
495 ADD_TRANSLATOR (Piano_pedal_engraver
,
498 "Engrave piano pedal symbols and brackets.",
507 "currentCommandColumn "
508 "pedalSostenutoStrings "
509 "pedalSostenutoStyle "
510 "pedalSustainStrings "
512 "pedalUnaCordaStrings "
513 "pedalUnaCordaStyle",