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"
18 #include "translator.icc"
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 PRECOMPUTED_VIRTUAL void stop_translation_timestep ();
33 PRECOMPUTED_VIRTUAL void process_music ();
37 Spanner *end_volta_span_;
41 bool staff_eligible ();
44 Volta_engraver::Volta_engraver ()
52 TODO: this logic should be rewritten, it is buggy.
54 One of the problems is that we can't determine wether or not to
55 print the volta bracket during the first step, since that requires
56 acknowledging the staff.
59 Volta_engraver::staff_eligible ()
61 SCM doit = get_property ("voltaOnThisStaff");
62 if (scm_is_bool (doit))
64 return to_boolean (doit);
67 if (!unsmob_grob (staff_))
71 TODO: this does weird things when you open a piece with a
74 SCM staffs = get_property ("stavesFound");
76 /* Only put a volta on the top staff.
77 Maybe this is a bit convoluted, and we should have a single
78 volta engraver in score context or somesuch. */
79 if (!scm_is_pair (staffs))
81 programming_error ("volta engraver can't find staffs");
84 else if (scm_car (scm_last_pair (staffs)) != staff_)
90 Volta_engraver::process_music ()
92 SCM cs = get_property ("repeatCommands");
94 if (!staff_eligible ())
98 start_string_ = SCM_EOL;
99 while (scm_is_pair (cs))
101 SCM c = scm_car (cs);
104 && scm_car (c) == ly_symbol2scm ("volta")
105 && scm_is_pair (scm_cdr (c)))
107 if (scm_cadr (c) == SCM_BOOL_F)
110 start_string_ = scm_cadr (c);
118 SCM l (get_property ("voltaSpannerDuration"));
119 Moment now = now_mom ();
121 bool early_stop = unsmob_moment (l)
122 && *unsmob_moment (l) <= now - started_mom_;
124 end = end || early_stop;
127 if (end && !volta_span_)
128 /* fixme: be more verbose. */
129 warning (_ ("can't end volta spanner"));
132 end_volta_span_ = volta_span_;
137 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
139 warning (_ ("already have a volta spanner, ending that one prematurely"));
143 warning (_ ("also already have an ended spanner"));
144 warning (_ ("giving up"));
148 end_volta_span_ = volta_span_;
153 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
155 started_mom_ = now_mom ();
157 volta_span_ = make_spanner ("VoltaBracket", SCM_EOL);
159 volta_span_->set_property ("text", start_string_);
164 Volta_engraver::acknowledge_grob (Grob_info i)
166 if (Item *item = dynamic_cast<Item *> (i.grob ()))
168 if (Note_column::has_interface (item))
171 Volta_bracket_interface::add_column (volta_span_, item);
173 if (Bar_line::has_interface (item))
176 Volta_bracket_interface::add_bar (volta_span_, item);
178 Volta_bracket_interface::add_bar (end_volta_span_, item);
181 else if (Staff_symbol::has_interface (i.grob ()))
184 We only want to know about a single staff: then we add to the
186 if (staff_ != SCM_EOL)
187 staff_ = SCM_UNDEFINED;
189 if (staff_ != SCM_UNDEFINED)
190 staff_ = i.grob ()->self_scm ();
195 Volta_engraver::finalize ()
200 Volta_engraver::stop_translation_timestep ()
202 if (volta_span_ && !staff_eligible ())
207 we need to do this here, because STAFF_ is not initialized yet
208 in the 1st call of process_music ()
211 volta_span_->suicide ();
215 if (end_volta_span_ && !end_volta_span_->get_bound (RIGHT))
217 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
218 Item *ci = dynamic_cast<Item *> (cc);
219 end_volta_span_->set_bound (RIGHT, ci);
224 if (volta_span_ && !volta_span_->get_bound (LEFT))
226 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
227 Item *ci = dynamic_cast<Item *> (cc);
228 volta_span_->set_bound (LEFT, ci);
233 TODO: should attach volta to paper-column if no bar is found.
236 ADD_TRANSLATOR (Volta_engraver,
237 /* descr */ "Make volta brackets.",
238 /* creats*/ "VoltaBracket",
240 /* acks */ "bar-line-interface staff-symbol-interface note-column-interface",
241 /* reads */ "repeatCommands voltaSpannerDuration stavesFound",