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 ()
66 if (!unsmob_grob (staff_))
69 if (!to_boolean (get_property ("voltaOnThisStaff")))
72 TODO: this does weird things when you open a piece with a
76 SCM staffs = get_property ("stavesFound");
79 only put a volta on the top staff.
81 May be this is a bit convoluted, and we should have a single
82 volta engraver in score context or somesuch.
85 if (!is_pair (staffs))
87 programming_error ("Huh? Volta engraver can't find staffs?");
90 else if (ly_car (scm_last_pair (staffs)) != staff_)
99 Volta_engraver::process_music ()
101 SCM cs = get_property ("repeatCommands");
103 if (!staff_eligible ())
108 start_string_ = SCM_EOL;
114 && ly_car (c) == ly_symbol2scm ("volta")
115 && is_pair (ly_cdr (c)))
117 if (ly_cadr (c) == SCM_BOOL_F)
120 start_string_ = ly_cadr (c);
128 SCM l (get_property ("voltaSpannerDuration"));
129 Moment now = now_mom ();
131 bool early_stop = unsmob_moment (l)
132 && *unsmob_moment (l) <= now - started_mom_;
134 end = end || early_stop;
138 if (end && !volta_span_)
140 warning (_ ("No volta spanner to end")); // fixme: be more verbose.
144 end_volta_span_ = volta_span_;
149 (is_string (start_string_) || is_pair (start_string_)))
151 warning (_ ("Already have a volta spanner. Stopping that one prematurely."));
155 warning (_ ("Also have a stopped spanner. Giving up."));
159 end_volta_span_ = volta_span_;
164 (is_string (start_string_) || is_pair (start_string_)))
166 started_mom_ = now_mom () ;
168 volta_span_ = make_spanner ("VoltaBracket");
170 announce_grob (volta_span_, SCM_EOL);
171 volta_span_->set_property ("text", start_string_);
177 Volta_engraver::acknowledge_grob (Grob_info i)
179 if (Item* item = dynamic_cast<Item*> (i.grob_))
181 if (Note_column::has_interface (item))
184 Volta_bracket_interface::add_column (volta_span_,item);
186 if (Bar_line::has_interface (item))
189 Volta_bracket_interface::add_bar (volta_span_, item);
191 Volta_bracket_interface::add_bar (end_volta_span_ , item);
194 else if (Staff_symbol::has_interface (i.grob_))
197 We only want to know about a single staff: then we add to the
199 if (staff_ != SCM_EOL)
200 staff_ = SCM_UNDEFINED;
202 if (staff_ != SCM_UNDEFINED)
203 staff_ = i.grob_->self_scm ();
208 Volta_engraver::finalize ()
212 typeset_grob (volta_span_);
216 typeset_grob (end_volta_span_);
223 Volta_engraver::stop_translation_timestep ()
225 if (volta_span_ && !staff_eligible ())
230 we need to do this here, because STAFF_ is not initialized yet
231 in the 1st call of process_music ()
234 volta_span_->suicide ( );
240 typeset_grob (end_volta_span_);
246 TODO: should attach volta to paper-column if no bar is found.
249 ENTER_DESCRIPTION (Volta_engraver,
250 /* descr */ "Make volta brackets",
251 /* creats*/ "VoltaBracket",
253 /* acks */ "bar-line-interface staff-symbol-interface note-column-interface",
254 /* reads */ "repeatCommands voltaSpannerDuration stavesFound",