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 DECLARE_ACKNOWLEDGER (staff_symbol);
31 DECLARE_ACKNOWLEDGER (note_column);
32 DECLARE_ACKNOWLEDGER (bar_line);
34 virtual void finalize ();
35 virtual void derived_mark () const;
36 void stop_translation_timestep ();
37 void process_music ();
41 Spanner *end_volta_span_;
45 bool staff_eligible ();
49 Volta_engraver::derived_mark () const
52 scm_gc_mark (start_string_);
55 Volta_engraver::Volta_engraver ()
58 start_string_ = SCM_EOL;
64 TODO: this logic should be rewritten, it is buggy.
66 One of the problems is that we can't determine wether or not to
67 print the volta bracket during the first step, since that requires
68 acknowledging the staff.
71 Volta_engraver::staff_eligible ()
73 SCM doit = get_property ("voltaOnThisStaff");
74 if (scm_is_bool (doit))
75 return to_boolean (doit);
77 if (!unsmob_grob (staff_))
81 TODO: this does weird things when you open a piece with a
84 SCM staffs = get_property ("stavesFound");
86 /* Only put a volta on the top staff.
87 Maybe this is a bit convoluted, and we should have a single
88 volta engraver in score context or somesuch. */
89 if (!scm_is_pair (staffs))
91 programming_error ("volta engraver can't find staffs");
94 else if (scm_car (scm_last_pair (staffs)) != staff_)
100 Volta_engraver::process_music ()
102 SCM cs = get_property ("repeatCommands");
104 if (!staff_eligible ())
108 start_string_ = SCM_EOL;
109 while (scm_is_pair (cs))
111 SCM c = scm_car (cs);
114 && scm_car (c) == ly_symbol2scm ("volta")
115 && scm_is_pair (scm_cdr (c)))
117 if (scm_cadr (c) == SCM_BOOL_F)
120 start_string_ = scm_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;
137 if (end && !volta_span_)
138 /* fixme: be more verbose. */
139 warning (_ ("can't end volta spanner"));
142 end_volta_span_ = volta_span_;
147 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
149 warning (_ ("already have a volta spanner, ending that one prematurely"));
153 warning (_ ("also already have an ended spanner"));
154 warning (_ ("giving up"));
158 end_volta_span_ = volta_span_;
163 && Text_interface::is_markup (start_string_))
165 started_mom_ = now_mom ();
167 volta_span_ = make_spanner ("VoltaBracket", SCM_EOL);
169 volta_span_->set_property ("text", start_string_);
174 Volta_engraver::acknowledge_note_column (Grob_info i)
177 Volta_bracket_interface::add_column (volta_span_, i.grob ());
181 Volta_engraver::acknowledge_bar_line (Grob_info i)
184 Volta_bracket_interface::add_bar (volta_span_, i.item ());
186 Volta_bracket_interface::add_bar (end_volta_span_, i.item ());
190 Volta_engraver::acknowledge_staff_symbol (Grob_info i)
193 We only want to know about a single staff: then we add to the
195 if (staff_ != SCM_EOL)
196 staff_ = SCM_UNDEFINED;
198 if (staff_ != SCM_UNDEFINED)
199 staff_ = i.grob ()->self_scm ();
203 Volta_engraver::finalize ()
208 Volta_engraver::stop_translation_timestep ()
210 if (volta_span_ && !staff_eligible ())
215 we need to do this here, because STAFF_ is not initialized yet
216 in the 1st call of process_music ()
219 volta_span_->suicide ();
223 if (end_volta_span_ && !end_volta_span_->get_bound (RIGHT))
225 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
226 Item *ci = dynamic_cast<Item *> (cc);
227 end_volta_span_->set_bound (RIGHT, ci);
232 if (volta_span_ && !volta_span_->get_bound (LEFT))
234 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
235 Item *ci = dynamic_cast<Item *> (cc);
236 volta_span_->set_bound (LEFT, ci);
241 TODO: should attach volta to paper-column if no bar is found.
243 ADD_ACKNOWLEDGER (Volta_engraver, staff_symbol);
244 ADD_ACKNOWLEDGER (Volta_engraver, note_column);
245 ADD_ACKNOWLEDGER (Volta_engraver, bar_line);
246 ADD_TRANSLATOR (Volta_engraver,
247 /* doc */ "Make volta brackets.",
248 /* create */ "VoltaBracket",
250 /* read */ "repeatCommands voltaSpannerDuration stavesFound",