2 piano-pedal-engraver.cc -- implement Piano_pedal_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2003 Jan Nieuwenhuizen <janneke@gnu.org>
8 Chris Jackson <chris@fluffhouse.org.uk> - extended to support
12 #include "engraver.hh"
16 #include "lily-guile.hh"
17 #include "side-position-interface.hh"
18 #include "staff-symbol-referencer.hh"
20 #include "axis-group-interface.hh"
21 #include "translator-group.hh"
22 #include "directional-element-interface.hh"
23 #include "note-column.hh"
31 Event for currently running pedal.
33 Music
* current_bracket_ev_
;
35 Event for currently starting pedal, (necessary?
37 distinct from current_bracket_ev_, since current_bracket_ev_ only
38 necessary for brackets, not for text style.
45 Events that were found in this timestep.
47 Drul_array
<Music
*> event_drul_
;
49 Spanner
* bracket_
; // A single portion of a pedal bracket
50 Spanner
* finished_bracket_
;
53 This grob contains all the pedals of the same type on the same staff
55 Spanner
* line_spanner_
;
56 Spanner
* finished_line_spanner_
;
60 class Piano_pedal_engraver
: public Engraver
63 TRANSLATOR_DECLARATIONS (Piano_pedal_engraver
);
64 ~Piano_pedal_engraver ();
66 virtual void initialize ();
67 virtual void finalize ();
68 virtual bool try_music (Music
*);
69 virtual void stop_translation_timestep ();
70 virtual void start_translation_timestep ();
71 virtual void acknowledge_grob (Grob_info
);
72 virtual void process_music ();
76 Pedal_info
*info_list_
;
79 Record a stack of the current pedal spanners, so if more than one pedal
80 occurs simultaneously then extra space can be added between them.
83 Link_array
<Spanner
> previous_
;
87 void create_text_grobs (Pedal_info
*p
, bool);
88 void create_bracket_grobs (Pedal_info
*p
, bool);
93 Piano_pedal_engraver::Piano_pedal_engraver ()
99 Piano_pedal_engraver::initialize ()
104 char * names
[] = { "Sostenuto", "Sustain", "UnaCorda", 0 };
106 info_list_
= new Pedal_info
[sizeof (names
)/ sizeof (const char*)];
107 Pedal_info
*p
= info_list_
;
115 p
->finished_bracket_
= 0;
116 p
->line_spanner_
= 0;
117 p
->finished_line_spanner_
= 0;
118 p
->current_bracket_ev_
= 0;
119 p
->event_drul_
[START
] = 0;
120 p
->event_drul_
[STOP
] = 0;
128 Piano_pedal_engraver::~Piano_pedal_engraver ()
138 Piano_pedal_engraver::acknowledge_grob (Grob_info info
)
140 for (Pedal_info
*p
= info_list_
; p
&& p
->name_
; p
++)
142 if (Note_column::has_interface (info
.grob_
))
144 if (p
->line_spanner_
)
146 Side_position_interface::add_support (p
->line_spanner_
, info
.grob_
);
148 add_bound_item (p
->line_spanner_
,info
.grob_
);
151 add_bound_item (p
->bracket_
,info
.grob_
);
158 Piano_pedal_engraver::try_music (Music
*m
)
160 if (m
->is_mus_type ("abort-event"))
162 for (Pedal_info
*p
= info_list_
; p
->name_
; p
++)
164 p
->event_drul_
[START
] = 0;
165 p
->event_drul_
[STOP
] = 0;
168 p
->bracket_
->suicide ();
172 else if (m
->is_mus_type ("pedal-event"))
174 for (Pedal_info
*p
= info_list_
; p
->name_
; p
++)
176 String nm
= p
->name_
+ String ("Event");
177 if (gh_equal_p (m
->get_mus_property ("name") ,
178 gh_symbol2scm (nm
.to_str0())))
180 Direction d
= to_dir (m
->get_mus_property ("span-direction"));
181 p
->event_drul_
[d
] = m
;
190 Piano_pedal_engraver::process_music ()
192 for (Pedal_info
*p
= info_list_
; p
&& p
->name_
; p
++)
194 if (p
->event_drul_
[STOP
] || p
->event_drul_
[START
])
196 if (!p
->line_spanner_
)
198 String name
= String (p
->name_
) + "PedalLineSpanner";
199 p
->line_spanner_
= new Spanner (get_property (name
.to_str0 ()));
202 Music
* rq
= (p
->event_drul_
[START
] ? p
->event_drul_
[START
] : p
->event_drul_
[STOP
]);
203 announce_grob (p
->line_spanner_
, rq
->self_scm ());
206 /* Choose the appropriate grobs to add to the line spanner
207 These can be text items or text-spanners
211 ugh, code dup, should read grob to create from other
214 bracket: |_________/\____|
216 mixed: Ped. _____/\____|
220 String prop
= String ("pedal") + p
->name_
+ "Style";
221 SCM style
= get_property (prop
.to_str0 ());
222 bool mixed
= style
== ly_symbol2scm ("mixed");
223 if (style
== ly_symbol2scm ("text") ||
227 create_text_grobs (p
, mixed
);
229 if (style
== ly_symbol2scm ("bracket") ||
232 create_bracket_grobs (p
, mixed
);
239 Piano_pedal_engraver::create_text_grobs (Pedal_info
*p
, bool mixed
)
242 SCM strings
= get_property ( ("pedal" + String (p
->name_
) + "Strings").to_str0 ());
244 if (scm_ilength (strings
) < 3)
246 Music
* m
= p
->event_drul_
[START
];
247 if (!m
) m
= p
->event_drul_
[STOP
];
249 String msg
= _ ("Need 3 strings for piano pedals. No pedal made. ");
251 m
->origin()->warning (msg
);
258 if (p
->event_drul_
[STOP
] && p
->event_drul_
[START
])
264 p
->event_drul_
[STOP
]->origin ()->warning (_f ("can't find start of piano pedal: `%s'", p
->name_
));
268 s
= ly_cadr (strings
);
270 p
->start_ev_
= p
->event_drul_
[START
];
273 else if (p
->event_drul_
[STOP
])
279 p
->event_drul_
[STOP
]->origin ()->warning (_f ("can't find start of piano pedal: `%s'", p
->name_
));
283 s
= ly_caddr (strings
);
284 if (previous_
.size ())
290 else if (p
->event_drul_
[START
])
292 p
->start_ev_
= p
->event_drul_
[START
];
293 s
= ly_car (strings
);
297 Code dup?! see below.
299 if (previous_
.size ())
300 // add extra space below the previous already-occuring pedal
301 Side_position_interface::add_support (p
->line_spanner_
,
303 previous_
.push ( p
->line_spanner_
);
309 String propname
= String (p
->name_
) + "Pedal";
311 SCM b
= get_property (propname
.to_str0 ());
312 p
->item_
= new Item (b
);
313 p
->item_
->set_grob_property ("text", s
);
314 Axis_group_interface::add_element (p
->line_spanner_
, p
->item_
);
316 announce_grob (p
->item_
,
317 (p
->event_drul_
[START
]
318 ? p
->event_drul_
[START
]
319 : p
->event_drul_
[STOP
])->self_scm ());
324 p
->event_drul_
[START
] = 0;
325 p
->event_drul_
[STOP
] = 0;
330 Piano_pedal_engraver::create_bracket_grobs (Pedal_info
*p
, bool mixed
)
332 if (!p
->bracket_
&& p
->event_drul_
[STOP
])
334 String msg
=_f ("can't find start of piano pedal bracket: `%s'", p
->name_
);
335 p
->event_drul_
[STOP
]->origin ()->warning (msg
);
336 p
->event_drul_
[STOP
] = 0;
339 if (p
->event_drul_
[STOP
])
341 if (!p
->event_drul_
[START
])
343 if (previous_
.size())
347 assert (!p
->finished_bracket_
);
349 Grob
*cmc
= unsmob_grob (get_property ("currentMusicalColumn"));
350 p
->bracket_
->set_bound (RIGHT
, cmc
);
353 Set properties so that the molecule-creating function will
354 know whether the right edge should be flared ___/
357 if (!p
->event_drul_
[START
])
359 SCM flare
= p
->bracket_
->get_grob_property ("bracket-flare");
360 p
->bracket_
->set_grob_property ("bracket-flare", scm_cons (gh_car (flare
),
364 p
->finished_bracket_
= p
->bracket_
;
366 p
->current_bracket_ev_
= 0;
369 if (p
->event_drul_
[START
])
371 p
->start_ev_
= p
->event_drul_
[START
];
372 p
->current_bracket_ev_
= p
->event_drul_
[START
];
374 p
->bracket_
= new Spanner (get_property ("PianoPedalBracket"));
377 Set properties so that the molecule-creating function will
378 know whether the left edge should be flared \___
381 if (!p
->finished_bracket_
)
383 SCM flare
= p
->bracket_
->get_grob_property ("bracket-flare");
384 p
->bracket_
->set_grob_property ("bracket-flare", scm_cons (gh_double2scm (0),gh_cdr (flare
)));
388 /* Set this property for 'mixed style' pedals, Ped._______/\ ,
389 so the molecule function will shorten the ____ line by the length of the Ped. text.
395 Mixed style: Store a pointer to the preceding text for use in
396 calculating the length of the line
401 WTF is pedal-text not the bound of the object? --hwn
404 p
->bracket_
->set_grob_property ("pedal-text", p
->item_
->self_scm ());
407 p
->bracket_
->set_bound (LEFT
, unsmob_grob (get_property ("currentMusicalColumn")));
408 Axis_group_interface::add_element (p
->line_spanner_
, p
->bracket_
);
410 add_bound_item (p
->line_spanner_
, p
->bracket_
->get_bound (LEFT
));
411 announce_grob (p
->bracket_
, p
->event_drul_
[START
]->self_scm ());
413 if (!p
->event_drul_
[STOP
])
419 // position new pedal spanner below the current one
421 if (previous_
.size())
422 Side_position_interface::add_support (p
->line_spanner_
, previous_
.top());
424 previous_
.push (p
->line_spanner_
);
428 p
->event_drul_
[START
] = 0;
429 p
->event_drul_
[STOP
] = 0;
433 Piano_pedal_engraver::finalize ()
435 for (Pedal_info
*p
= info_list_
; p
&& p
->name_
; p
++)
441 && !p
->line_spanner_
->live())
442 p
->line_spanner_
= 0;
444 if (p
->line_spanner_
)
446 p
->finished_line_spanner_
= p
->line_spanner_
;
450 && !p
->bracket_
->live())
455 p
->current_bracket_ev_
->origin ()->warning (_ ("unterminated pedal bracket"));
456 p
->bracket_
->suicide ();
464 Piano_pedal_engraver::stop_translation_timestep ()
466 for (Pedal_info
*p
= info_list_
; p
&& p
->name_
; p
++)
470 p
->finished_line_spanner_
= p
->line_spanner_
;
471 p
->line_spanner_
= 0;
480 Piano_pedal_engraver::typeset_all ()
483 for (Pedal_info
*p
= info_list_
; p
->name_
; p
++)
488 if (p
->finished_line_spanner_
489 && !p
->finished_line_spanner_
->live ())
490 p
->finished_line_spanner_
= 0;
491 if (p
->finished_bracket_
492 && !p
->finished_bracket_
->live())
493 p
->finished_bracket_
= 0;
496 if (p
->name_
== String ("Sustain"))
504 if (p
->name_
!= String ("Sustain"))
508 Side_position_interface::add_support (p
->item_
,sustain
);
511 typeset_grob (p
->item_
);
515 if (p
->finished_bracket_
)
517 Grob
* r
= p
->finished_bracket_
->get_bound (RIGHT
);
520 p
->finished_bracket_
->set_bound (RIGHT
, unsmob_grob (get_property ("currentMusicalColumn")));
523 typeset_grob (p
->finished_bracket_
);
524 p
->finished_bracket_
=0;
527 if (p
->finished_line_spanner_
)
529 Side_position_interface::add_staff_support (p
->finished_line_spanner_
);
530 Grob
* l
= p
->finished_line_spanner_
->get_bound (LEFT
);
531 Grob
* r
= p
->finished_line_spanner_
->get_bound (RIGHT
);
533 p
->finished_line_spanner_
->set_bound (RIGHT
, l
);
535 p
->finished_line_spanner_
->set_bound (LEFT
, r
);
538 Grob
* cc
= unsmob_grob (get_property ("currentMusicalColumn"));
539 Item
* ci
= dynamic_cast<Item
*> (cc
);
540 p
->finished_line_spanner_
->set_bound (RIGHT
, ci
);
541 p
->finished_line_spanner_
->set_bound (LEFT
, ci
);
543 typeset_grob (p
->finished_line_spanner_
);
544 p
->finished_line_spanner_
= 0;
550 Piano_pedal_engraver::start_translation_timestep ()
552 for (Pedal_info
*p
= info_list_
; p
->name_
; p
++)
554 p
->event_drul_
[STOP
] = 0;
555 p
->event_drul_
[START
] = 0;
559 ENTER_DESCRIPTION (Piano_pedal_engraver
,
560 /* descr */ "Engrave piano pedal symbols and brackets.",
561 /* creats*/ "SostenutoPedal SustainPedal UnaCordaPedal SostenutoPedalLineSpanner SustainPedalLineSpanner UnaCordaPedalLineSpanner",
562 /* accepts */ "pedal-event abort-event",
563 /* acks */ "note-column-interface",
564 /* reads */ "pedalSostenutoStrings pedalSustainStrings pedalUnaCordaStrings pedalSostenutoStyle pedalSustainStyle pedalUnaCordaStyle",