2 volta-engraver.cc -- implement Volta_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
10 #include "engraver.hh"
12 #include "volta-bracket.hh"
14 #include "note-column.hh"
15 #include "bar-line.hh"
16 #include "side-position-interface.hh"
18 #include "staff-symbol.hh"
21 Create Volta spanners, by reading repeatCommands property, usually
22 set by Unfolded_repeat_iterator.
24 class Volta_engraver : public Engraver
27 TRANSLATOR_DECLARATIONS (Volta_engraver);
30 virtual void acknowledge_grob (Grob_info);
31 virtual void finalize ();
32 virtual void stop_translation_timestep ();
33 virtual void process_music ();
37 Spanner *end_volta_span_;
41 bool staff_eligible ();
45 Volta_engraver::Volta_engraver ()
54 TODO: this logic should be rewritten, it is buggy.
56 One of the problems is that we can't determine wether or not to
57 print the volta bracket during the first step, since that requires
58 acknowledging the staff.
61 Volta_engraver::staff_eligible ()
63 SCM doit =get_property ("voltaOnThisStaff");
64 if (ly_c_boolean_p (doit))
66 return to_boolean (doit);
70 if (!unsmob_grob (staff_))
74 TODO: this does weird things when you open a piece with a
77 SCM staffs = get_property ("stavesFound");
80 only put a volta on the top staff.
82 May be this is a bit convoluted, and we should have a single
83 volta engraver in score context or somesuch.
86 if (!ly_c_pair_p (staffs))
88 programming_error ("Huh? Volta engraver can't find staffs?");
91 else if (ly_car (scm_last_pair (staffs)) != staff_)
100 Volta_engraver::process_music ()
102 SCM cs = get_property ("repeatCommands");
104 if (!staff_eligible ())
109 start_string_ = SCM_EOL;
110 while (ly_c_pair_p (cs))
115 && ly_car (c) == ly_symbol2scm ("volta")
116 && ly_c_pair_p (ly_cdr (c)))
118 if (ly_cadr (c) == SCM_BOOL_F)
121 start_string_ = ly_cadr (c);
129 SCM l (get_property ("voltaSpannerDuration"));
130 Moment now = now_mom ();
132 bool early_stop = unsmob_moment (l)
133 && *unsmob_moment (l) <= now - started_mom_;
135 end = end || early_stop;
139 if (end && !volta_span_)
141 warning (_ ("No volta spanner to end")); // fixme: be more verbose.
145 end_volta_span_ = volta_span_;
150 (ly_c_string_p (start_string_) || ly_c_pair_p (start_string_)))
152 warning (_ ("Already have a volta spanner. Stopping that one prematurely."));
156 warning (_ ("Also have a stopped spanner. Giving up."));
160 end_volta_span_ = volta_span_;
165 (ly_c_string_p (start_string_) || ly_c_pair_p (start_string_)))
167 started_mom_ = now_mom () ;
169 volta_span_ = make_spanner ("VoltaBracket", SCM_EOL);
172 volta_span_->set_property ("text", start_string_);
178 Volta_engraver::acknowledge_grob (Grob_info i)
180 if (Item* item = dynamic_cast<Item*> (i.grob_))
182 if (Note_column::has_interface (item))
185 Volta_bracket_interface::add_column (volta_span_,item);
187 if (Bar_line::has_interface (item))
190 Volta_bracket_interface::add_bar (volta_span_, item);
192 Volta_bracket_interface::add_bar (end_volta_span_ , item);
195 else if (Staff_symbol::has_interface (i.grob_))
198 We only want to know about a single staff: then we add to the
200 if (staff_ != SCM_EOL)
201 staff_ = SCM_UNDEFINED;
203 if (staff_ != SCM_UNDEFINED)
204 staff_ = i.grob_->self_scm ();
209 Volta_engraver::finalize ()
216 Volta_engraver::stop_translation_timestep ()
218 if (volta_span_ && !staff_eligible ())
223 we need to do this here, because STAFF_ is not initialized yet
224 in the 1st call of process_music ()
227 volta_span_->suicide ( );
231 if (end_volta_span_ && !end_volta_span_->get_bound (RIGHT))
233 Grob * cc = unsmob_grob (get_property ("currentCommandColumn"));
234 Item * ci = dynamic_cast<Item*> (cc);
235 end_volta_span_->set_bound (RIGHT, ci);
240 if (volta_span_ && !volta_span_->get_bound (LEFT))
242 Grob * cc = unsmob_grob (get_property ("currentCommandColumn"));
243 Item * ci = dynamic_cast<Item*> (cc);
244 volta_span_->set_bound (LEFT, ci);
250 TODO: should attach volta to paper-column if no bar is found.
253 ENTER_DESCRIPTION (Volta_engraver,
254 /* descr */ "Make volta brackets.",
255 /* creats*/ "VoltaBracket",
257 /* acks */ "bar-line-interface staff-symbol-interface note-column-interface",
258 /* reads */ "repeatCommands voltaSpannerDuration stavesFound",