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_);
147 add_bound_item (p->line_spanner_,info.grob_);
150 add_bound_item (p->bracket_,info.grob_);
157 Piano_pedal_engraver::try_music (Music *m)
159 if (m->is_mus_type ("abort-event"))
161 for (Pedal_info*p = info_list_; p->name_; p ++)
163 p->event_drul_[START] = 0;
164 p->event_drul_[STOP] = 0;
167 p->bracket_->suicide ();
171 else if (m->is_mus_type ("pedal-event"))
173 for (Pedal_info*p = info_list_; p->name_; p ++)
175 String nm = p->name_ + String ("Event");
176 if (gh_equal_p (m->get_mus_property ("name") ,
177 gh_symbol2scm (nm.to_str0())))
179 Direction d = to_dir (m->get_mus_property ("span-direction"));
180 p->event_drul_[d] = m;
189 Piano_pedal_engraver::process_music ()
191 for (Pedal_info*p = info_list_; p && p->name_; p ++)
193 if (p->event_drul_[STOP] || p->event_drul_[START])
195 if (!p->line_spanner_)
197 String name = String (p->name_) + "PedalLineSpanner";
198 p->line_spanner_ = new Spanner (get_property (name.to_str0 ()));
201 Music * rq = (p->event_drul_[START] ? p->event_drul_[START] : p->event_drul_[STOP]);
202 announce_grob (p->line_spanner_, rq->self_scm ());
205 /* Choose the appropriate grobs to add to the line spanner
206 These can be text items or text-spanners
210 ugh, code dup, should read grob to create from other
213 bracket: |_________/\____|
215 mixed: Ped. _____/\____|
219 String prop = String ("pedal") + p->name_ + "Style";
220 SCM style = get_property (prop.to_str0 ());
221 bool mixed = style == ly_symbol2scm ("mixed");
222 if (style == ly_symbol2scm ("text") ||
226 create_text_grobs (p, mixed);
228 if (style == ly_symbol2scm ("bracket") ||
231 create_bracket_grobs (p, mixed);
238 Piano_pedal_engraver::create_text_grobs (Pedal_info *p, bool mixed)
241 SCM strings = get_property ( ("pedal" + String (p->name_) + "Strings").to_str0 ());
243 if (scm_ilength (strings) < 3)
245 Music * m = p->event_drul_[START];
246 if (!m) m = p->event_drul_ [STOP];
248 String msg = _ ("Need 3 strings for piano pedals. No pedal made. ");
250 m->origin()->warning (msg);
257 if (p->event_drul_[STOP] && p->event_drul_[START])
263 p->event_drul_[STOP]->origin ()->warning (_f ("can't find start of piano pedal: `%s'", p->name_));
267 s = ly_cadr (strings);
269 p->start_ev_ = p->event_drul_[START];
272 else if (p->event_drul_[STOP])
278 p->event_drul_[STOP]->origin ()->warning (_f ("can't find start of piano pedal: `%s'", p->name_));
282 s = ly_caddr (strings);
283 if (previous_.size ())
289 else if (p->event_drul_[START])
291 p->start_ev_ = p->event_drul_[START];
292 s = ly_car (strings);
296 Code dup?! see below.
298 if (previous_.size ())
299 // add extra space below the previous already-occuring pedal
300 Side_position_interface::add_support (p->line_spanner_,
302 previous_.push ( p->line_spanner_);
308 String propname = String (p->name_) + "Pedal";
310 SCM b = get_property (propname.to_str0 ());
311 p->item_ = new Item (b);
312 p->item_->set_grob_property ("text", s);
313 Axis_group_interface::add_element (p->line_spanner_, p->item_);
315 announce_grob (p->item_,
316 (p->event_drul_[START]
317 ? p->event_drul_[START]
318 : p->event_drul_[STOP])->self_scm ());
323 p->event_drul_[START] = 0;
324 p->event_drul_[STOP] = 0;
329 Piano_pedal_engraver::create_bracket_grobs (Pedal_info *p, bool mixed)
331 if (!p->bracket_ && p->event_drul_[STOP])
333 String msg =_f ("can't find start of piano pedal bracket: `%s'", p->name_);
334 p->event_drul_[STOP]->origin ()->warning (msg);
335 p->event_drul_[STOP] = 0;
338 if (p->event_drul_[STOP])
340 if (!p->event_drul_[START])
342 if (previous_.size())
346 assert (!p->finished_bracket_);
348 Grob *cmc = unsmob_grob (get_property ("currentMusicalColumn"));
349 p->bracket_->set_bound (RIGHT, cmc);
352 Set properties so that the molecule-creating function will
353 know whether the right edge should be flared ___/
356 if (!p->event_drul_[START])
358 SCM flare = p->bracket_->get_grob_property ("bracket-flare");
359 p->bracket_->set_grob_property ("bracket-flare", scm_cons (gh_car (flare),
363 p->finished_bracket_ = p->bracket_;
365 p->current_bracket_ev_ = 0;
368 if (p->event_drul_[START])
370 p->start_ev_ = p->event_drul_[START];
371 p->current_bracket_ev_ = p->event_drul_[START];
373 p->bracket_ = new Spanner (get_property ("PianoPedalBracket"));
376 Set properties so that the molecule-creating function will
377 know whether the left edge should be flared \___
380 if (!p->finished_bracket_)
382 SCM flare = p->bracket_->get_grob_property ("bracket-flare");
383 p->bracket_->set_grob_property ("bracket-flare", scm_cons (gh_double2scm (0),gh_cdr (flare)));
387 /* Set this property for 'mixed style' pedals, Ped._______/\ ,
388 so the molecule function will shorten the ____ line by the length of the Ped. text.
394 Mixed style: Store a pointer to the preceding text for use in
395 calculating the length of the line
400 WTF is pedal-text not the bound of the object? --hwn
403 p->bracket_->set_grob_property ("pedal-text", p->item_->self_scm ());
408 We do not use currentMusicalColumn for the left span-point.
409 If the column as accidentals (eg on a different stave), the
410 currentMusicalColumn is too wide, making the bracket too big.
414 Hmm. What do we do when there are no notes when the spanner starts?
418 what about the right span point?
421 Axis_group_interface::add_element (p->line_spanner_, p->bracket_);
422 announce_grob (p->bracket_, p->event_drul_[START]->self_scm ());
424 if (!p->event_drul_[STOP])
430 // position new pedal spanner below the current one
432 if (previous_.size())
433 Side_position_interface::add_support (p->line_spanner_, previous_.top());
435 previous_.push (p->line_spanner_);
439 p->event_drul_[START] = 0;
440 p->event_drul_[STOP] = 0;
444 Piano_pedal_engraver::finalize ()
446 for (Pedal_info*p = info_list_; p && p->name_; p ++)
452 && !p->line_spanner_->live())
453 p->line_spanner_ = 0;
455 if (p->line_spanner_)
457 p->finished_line_spanner_ = p->line_spanner_;
461 && !p->bracket_->live())
466 p->current_bracket_ev_->origin ()->warning (_ ("unterminated pedal bracket"));
467 p->bracket_->suicide ();
475 Piano_pedal_engraver::stop_translation_timestep ()
477 for (Pedal_info*p = info_list_; p && p->name_; p ++)
481 p->finished_line_spanner_ = p->line_spanner_;
482 p->line_spanner_ = 0;
491 Piano_pedal_engraver::typeset_all ()
494 for (Pedal_info*p = info_list_; p->name_; p ++)
499 if (p->finished_line_spanner_
500 && !p->finished_line_spanner_->live ())
501 p->finished_line_spanner_ = 0;
502 if (p->finished_bracket_
503 && !p->finished_bracket_->live())
504 p->finished_bracket_ = 0;
507 if (p->name_ == String ("Sustain"))
515 if (p->name_ != String ("Sustain"))
519 Side_position_interface::add_support (p->item_,sustain);
522 typeset_grob (p->item_);
526 if (p->finished_bracket_)
528 Grob * r = p->finished_bracket_->get_bound (RIGHT);
531 p->finished_bracket_->set_bound (RIGHT, unsmob_grob (get_property ("currentMusicalColumn")));
534 typeset_grob (p->finished_bracket_);
535 p->finished_bracket_ =0;
538 if (p->finished_line_spanner_)
540 Side_position_interface::add_staff_support (p->finished_line_spanner_);
541 Grob * l = p->finished_line_spanner_->get_bound (LEFT);
542 Grob * r = p->finished_line_spanner_->get_bound (RIGHT);
544 p->finished_line_spanner_->set_bound (RIGHT, l);
546 p->finished_line_spanner_->set_bound (LEFT, r);
549 Grob * cc = unsmob_grob (get_property ("currentMusicalColumn"));
550 Item * ci = dynamic_cast<Item*> (cc);
551 p->finished_line_spanner_->set_bound (RIGHT, ci);
552 p->finished_line_spanner_->set_bound (LEFT, ci);
554 typeset_grob (p->finished_line_spanner_);
555 p->finished_line_spanner_ = 0;
561 Piano_pedal_engraver::start_translation_timestep ()
563 for (Pedal_info*p = info_list_; p->name_; p ++)
565 p->event_drul_[STOP] = 0;
566 p->event_drul_[START] = 0;
570 ENTER_DESCRIPTION (Piano_pedal_engraver,
571 /* descr */ "Engrave piano pedal symbols and brackets.",
572 /* creats*/ "SostenutoPedal SustainPedal UnaCordaPedal SostenutoPedalLineSpanner SustainPedalLineSpanner UnaCordaPedalLineSpanner",
573 /* accepts */ "pedal-event abort-event",
574 /* acks */ "note-column-interface",
575 /* reads */ "pedalSostenutoStrings pedalSustainStrings pedalUnaCordaStrings pedalSostenutoStyle pedalSustainStyle pedalUnaCordaStyle",