2 volta-engraver.cc -- implement Volta_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
11 #include "bar-line.hh"
13 #include "international.hh"
14 #include "note-column.hh"
15 #include "side-position-interface.hh"
16 #include "staff-symbol.hh"
17 #include "text-interface.hh"
18 #include "volta-bracket.hh"
21 #include "translator.icc"
24 Create Volta spanners, by reading repeatCommands property, usually
25 set by Volta_repeat_iterator.
27 class Volta_engraver : public Engraver
30 TRANSLATOR_DECLARATIONS (Volta_engraver);
33 DECLARE_END_ACKNOWLEDGER (staff_symbol);
34 DECLARE_ACKNOWLEDGER (staff_symbol);
35 DECLARE_ACKNOWLEDGER (note_column);
36 DECLARE_ACKNOWLEDGER (bar_line);
38 virtual void finalize ();
39 virtual void derived_mark () const;
40 void stop_translation_timestep ();
41 void process_music ();
45 Spanner *end_volta_span_;
49 bool staff_eligible ();
53 Volta_engraver::derived_mark () const
56 scm_gc_mark (start_string_);
59 Volta_engraver::Volta_engraver ()
62 start_string_ = SCM_EOL;
68 TODO: this logic should be rewritten, it is buggy.
70 One of the problems is that we can't determine wether or not to
71 print the volta bracket during the first step, since that requires
72 acknowledging the staff.
75 Volta_engraver::staff_eligible ()
77 SCM doit = get_property ("voltaOnThisStaff");
78 if (scm_is_bool (doit))
79 return to_boolean (doit);
81 if (!unsmob_grob (staff_))
85 TODO: this does weird things when you open a piece with a
88 SCM staffs = get_property ("stavesFound");
90 /* Only put a volta on the top staff.
91 Maybe this is a bit convoluted, and we should have a single
92 volta engraver in score context or somesuch. */
93 if (!scm_is_pair (staffs))
95 programming_error ("volta engraver can't find staffs");
98 else if (scm_car (scm_last_pair (staffs)) != staff_)
104 Volta_engraver::process_music ()
106 SCM cs = get_property ("repeatCommands");
108 if (!staff_eligible ())
112 start_string_ = SCM_EOL;
113 while (scm_is_pair (cs))
115 SCM c = scm_car (cs);
118 && scm_car (c) == ly_symbol2scm ("volta")
119 && scm_is_pair (scm_cdr (c)))
121 if (scm_cadr (c) == SCM_BOOL_F)
124 start_string_ = scm_cadr (c);
132 SCM l (get_property ("voltaSpannerDuration"));
133 Moment now = now_mom ();
135 bool early_stop = unsmob_moment (l)
136 && *unsmob_moment (l) <= now - started_mom_;
138 end = end || early_stop;
141 if (end && !volta_span_)
142 /* fixme: be more verbose. */
143 warning (_ ("can't end volta spanner"));
146 end_volta_span_ = volta_span_;
151 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
153 warning (_ ("already have a volta spanner, ending that one prematurely"));
157 warning (_ ("also already have an ended spanner"));
158 warning (_ ("giving up"));
162 end_volta_span_ = volta_span_;
167 && Text_interface::is_markup (start_string_))
169 started_mom_ = now_mom ();
171 volta_span_ = make_spanner ("VoltaBracket", SCM_EOL);
173 volta_span_->set_property ("text", start_string_);
178 Volta_engraver::acknowledge_note_column (Grob_info i)
181 Volta_bracket_interface::add_column (volta_span_, i.grob ());
185 Volta_engraver::acknowledge_bar_line (Grob_info i)
188 Volta_bracket_interface::add_bar (volta_span_, i.item ());
190 Volta_bracket_interface::add_bar (end_volta_span_, i.item ());
194 Volta_engraver::acknowledge_end_staff_symbol (Grob_info i)
196 if (i.grob ()->self_scm () == staff_)
201 Volta_engraver::acknowledge_staff_symbol (Grob_info i)
204 We only want to know about a single staff: then we add to the
206 if (staff_ != SCM_EOL)
207 staff_ = SCM_UNDEFINED;
209 if (staff_ != SCM_UNDEFINED)
210 staff_ = i.grob ()->self_scm ();
215 Volta_engraver::finalize ()
220 Volta_engraver::stop_translation_timestep ()
222 if (volta_span_ && !staff_eligible ())
227 we need to do this here, because STAFF_ is not initialized yet
228 in the 1st call of process_music ()
231 volta_span_->suicide ();
235 if (end_volta_span_ && !end_volta_span_->get_bound (RIGHT))
237 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
238 Item *ci = dynamic_cast<Item *> (cc);
239 end_volta_span_->set_bound (RIGHT, ci);
244 if (volta_span_ && !volta_span_->get_bound (LEFT))
246 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
247 Item *ci = dynamic_cast<Item *> (cc);
248 volta_span_->set_bound (LEFT, ci);
253 TODO: should attach volta to paper-column if no bar is found.
255 ADD_ACKNOWLEDGER (Volta_engraver, staff_symbol);
256 ADD_END_ACKNOWLEDGER (Volta_engraver, staff_symbol);
257 ADD_ACKNOWLEDGER (Volta_engraver, note_column);
258 ADD_ACKNOWLEDGER (Volta_engraver, bar_line);
259 ADD_TRANSLATOR (Volta_engraver,
260 /* doc */ "Make volta brackets.",
261 /* create */ "VoltaBracket",
263 /* read */ "repeatCommands voltaSpannerDuration stavesFound",