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 ();
42 Volta_engraver::Volta_engraver ()
50 TODO: this logic should be rewritten, it is buggy.
52 One of the problems is that we can't determine wether or not to
53 print the volta bracket during the first step, since that requires
54 acknowledging the staff.
57 Volta_engraver::staff_eligible ()
59 SCM doit = get_property ("voltaOnThisStaff");
60 if (scm_is_bool (doit))
62 return to_boolean (doit);
65 if (!unsmob_grob (staff_))
69 TODO: this does weird things when you open a piece with a
72 SCM staffs = get_property ("stavesFound");
74 /* Only put a volta on the top staff.
75 Maybe this is a bit convoluted, and we should have a single
76 volta engraver in score context or somesuch. */
77 if (!scm_is_pair (staffs))
79 programming_error ("volta engraver can't find staffs");
82 else if (scm_car (scm_last_pair (staffs)) != staff_)
88 Volta_engraver::process_music ()
90 SCM cs = get_property ("repeatCommands");
92 if (!staff_eligible ())
96 start_string_ = SCM_EOL;
97 while (scm_is_pair (cs))
102 && scm_car (c) == ly_symbol2scm ("volta")
103 && scm_is_pair (scm_cdr (c)))
105 if (scm_cadr (c) == SCM_BOOL_F)
108 start_string_ = scm_cadr (c);
116 SCM l (get_property ("voltaSpannerDuration"));
117 Moment now = now_mom ();
119 bool early_stop = unsmob_moment (l)
120 && *unsmob_moment (l) <= now - started_mom_;
122 end = end || early_stop;
125 if (end && !volta_span_)
126 /* fixme: be more verbose. */
127 warning (_ ("can't end volta spanner"));
130 end_volta_span_ = volta_span_;
135 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
137 warning (_ ("already have a volta spanner, ending that one prematurely"));
141 warning (_ ("also already have an ended spanner"));
142 warning (_ ("giving up"));
146 end_volta_span_ = volta_span_;
151 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
153 started_mom_ = now_mom ();
155 volta_span_ = make_spanner ("VoltaBracket", SCM_EOL);
157 volta_span_->set_property ("text", start_string_);
162 Volta_engraver::acknowledge_grob (Grob_info i)
164 if (Item *item = dynamic_cast<Item *> (i.grob ()))
166 if (Note_column::has_interface (item))
169 Volta_bracket_interface::add_column (volta_span_, item);
171 if (Bar_line::has_interface (item))
174 Volta_bracket_interface::add_bar (volta_span_, item);
176 Volta_bracket_interface::add_bar (end_volta_span_, item);
179 else if (Staff_symbol::has_interface (i.grob ()))
182 We only want to know about a single staff: then we add to the
184 if (staff_ != SCM_EOL)
185 staff_ = SCM_UNDEFINED;
187 if (staff_ != SCM_UNDEFINED)
188 staff_ = i.grob ()->self_scm ();
193 Volta_engraver::finalize ()
198 Volta_engraver::stop_translation_timestep ()
200 if (volta_span_ && !staff_eligible ())
205 we need to do this here, because STAFF_ is not initialized yet
206 in the 1st call of process_music ()
209 volta_span_->suicide ();
213 if (end_volta_span_ && !end_volta_span_->get_bound (RIGHT))
215 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
216 Item *ci = dynamic_cast<Item *> (cc);
217 end_volta_span_->set_bound (RIGHT, ci);
222 if (volta_span_ && !volta_span_->get_bound (LEFT))
224 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
225 Item *ci = dynamic_cast<Item *> (cc);
226 volta_span_->set_bound (LEFT, ci);
231 TODO: should attach volta to paper-column if no bar is found.
234 ADD_TRANSLATOR (Volta_engraver,
235 /* descr */ "Make volta brackets.",
236 /* creats*/ "VoltaBracket",
238 /* acks */ "bar-line-interface staff-symbol-interface note-column-interface",
239 /* reads */ "repeatCommands voltaSpannerDuration stavesFound",