2 volta-engraver.cc -- implement Volta_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
11 #include "volta-bracket.hh"
12 #include "note-column.hh"
13 #include "bar-line.hh"
14 #include "side-position-interface.hh"
16 #include "staff-symbol.hh"
19 Create Volta spanners, by reading repeatCommands property, usually
20 set by Unfolded_repeat_iterator.
22 class Volta_engraver : public Engraver
25 TRANSLATOR_DECLARATIONS (Volta_engraver);
28 virtual void acknowledge_grob (Grob_info);
29 virtual void finalize ();
30 virtual void stop_translation_timestep ();
31 virtual void process_music ();
35 Spanner *end_volta_span_;
39 bool staff_eligible ();
43 Volta_engraver::Volta_engraver ()
51 TODO: this logic should be rewritten, it is buggy.
53 One of the problems is that we can't determine wether or not to
54 print the volta bracket during the first step, since that requires
55 acknowledging the staff.
58 Volta_engraver::staff_eligible ()
60 SCM doit = get_property ("voltaOnThisStaff");
61 if (scm_is_bool (doit))
63 return to_boolean (doit);
66 if (!unsmob_grob (staff_))
70 TODO: this does weird things when you open a piece with a
73 SCM staffs = get_property ("stavesFound");
76 only put a volta on the top staff.
78 May be this is a bit convoluted, and we should have a single
79 volta engraver in score context or somesuch.
82 if (!scm_is_pair (staffs))
84 programming_error ("Huh? Volta engraver can't find staffs?");
87 else if (scm_car (scm_last_pair (staffs)) != staff_)
95 Volta_engraver::process_music ()
97 SCM cs = get_property ("repeatCommands");
99 if (!staff_eligible ())
103 start_string_ = SCM_EOL;
104 while (scm_is_pair (cs))
106 SCM c = scm_car (cs);
109 && scm_car (c) == ly_symbol2scm ("volta")
110 && scm_is_pair (scm_cdr (c)))
112 if (scm_cadr (c) == SCM_BOOL_F)
115 start_string_ = scm_cadr (c);
123 SCM l (get_property ("voltaSpannerDuration"));
124 Moment now = now_mom ();
126 bool early_stop = unsmob_moment (l)
127 && *unsmob_moment (l) <= now - started_mom_;
129 end = end || early_stop;
132 if (end && !volta_span_)
134 warning (_ ("No volta spanner to end")); // fixme: be more verbose.
138 end_volta_span_ = volta_span_;
143 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
145 warning (_ ("Already have a volta spanner. Stopping that one prematurely."));
149 warning (_ ("Also have a stopped spanner. Giving up."));
153 end_volta_span_ = volta_span_;
158 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
160 started_mom_ = now_mom ();
162 volta_span_ = make_spanner ("VoltaBracket", SCM_EOL);
164 volta_span_->set_property ("text", start_string_);
169 Volta_engraver::acknowledge_grob (Grob_info i)
171 if (Item *item = dynamic_cast<Item *> (i.grob_))
173 if (Note_column::has_interface (item))
176 Volta_bracket_interface::add_column (volta_span_, item);
178 if (Bar_line::has_interface (item))
181 Volta_bracket_interface::add_bar (volta_span_, item);
183 Volta_bracket_interface::add_bar (end_volta_span_, item);
186 else if (Staff_symbol::has_interface (i.grob_))
189 We only want to know about a single staff: then we add to the
191 if (staff_ != SCM_EOL)
192 staff_ = SCM_UNDEFINED;
194 if (staff_ != SCM_UNDEFINED)
195 staff_ = i.grob_->self_scm ();
200 Volta_engraver::finalize ()
205 Volta_engraver::stop_translation_timestep ()
207 if (volta_span_ && !staff_eligible ())
212 we need to do this here, because STAFF_ is not initialized yet
213 in the 1st call of process_music ()
216 volta_span_->suicide ();
220 if (end_volta_span_ && !end_volta_span_->get_bound (RIGHT))
222 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
223 Item *ci = dynamic_cast<Item *> (cc);
224 end_volta_span_->set_bound (RIGHT, ci);
229 if (volta_span_ && !volta_span_->get_bound (LEFT))
231 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
232 Item *ci = dynamic_cast<Item *> (cc);
233 volta_span_->set_bound (LEFT, ci);
239 TODO: should attach volta to paper-column if no bar is found.
242 ADD_TRANSLATOR (Volta_engraver,
243 /* descr */ "Make volta brackets.",
244 /* creats*/ "VoltaBracket",
246 /* acks */ "bar-line-interface staff-symbol-interface note-column-interface",
247 /* reads */ "repeatCommands voltaSpannerDuration stavesFound",