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 Unfolded_repeat_iterator.
27 class Volta_engraver : public Engraver
30 TRANSLATOR_DECLARATIONS (Volta_engraver);
33 DECLARE_ACKNOWLEDGER (staff_symbol);
34 DECLARE_ACKNOWLEDGER (note_column);
35 DECLARE_ACKNOWLEDGER (bar_line);
37 virtual void finalize ();
38 virtual void derived_mark () const;
39 void stop_translation_timestep ();
40 void process_music ();
44 Spanner *end_volta_span_;
48 bool staff_eligible ();
52 Volta_engraver::derived_mark () const
55 scm_gc_mark (start_string_);
58 Volta_engraver::Volta_engraver ()
61 start_string_ = SCM_EOL;
67 TODO: this logic should be rewritten, it is buggy.
69 One of the problems is that we can't determine wether or not to
70 print the volta bracket during the first step, since that requires
71 acknowledging the staff.
74 Volta_engraver::staff_eligible ()
76 SCM doit = get_property ("voltaOnThisStaff");
77 if (scm_is_bool (doit))
78 return to_boolean (doit);
80 if (!unsmob_grob (staff_))
84 TODO: this does weird things when you open a piece with a
87 SCM staffs = get_property ("stavesFound");
89 /* Only put a volta on the top staff.
90 Maybe this is a bit convoluted, and we should have a single
91 volta engraver in score context or somesuch. */
92 if (!scm_is_pair (staffs))
94 programming_error ("volta engraver can't find staffs");
97 else if (scm_car (scm_last_pair (staffs)) != staff_)
103 Volta_engraver::process_music ()
105 SCM cs = get_property ("repeatCommands");
107 if (!staff_eligible ())
111 start_string_ = SCM_EOL;
112 while (scm_is_pair (cs))
114 SCM c = scm_car (cs);
117 && scm_car (c) == ly_symbol2scm ("volta")
118 && scm_is_pair (scm_cdr (c)))
120 if (scm_cadr (c) == SCM_BOOL_F)
123 start_string_ = scm_cadr (c);
131 SCM l (get_property ("voltaSpannerDuration"));
132 Moment now = now_mom ();
134 bool early_stop = unsmob_moment (l)
135 && *unsmob_moment (l) <= now - started_mom_;
137 end = end || early_stop;
140 if (end && !volta_span_)
141 /* fixme: be more verbose. */
142 warning (_ ("can't end volta spanner"));
145 end_volta_span_ = volta_span_;
150 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
152 warning (_ ("already have a volta spanner, ending that one prematurely"));
156 warning (_ ("also already have an ended spanner"));
157 warning (_ ("giving up"));
161 end_volta_span_ = volta_span_;
166 && Text_interface::is_markup (start_string_))
168 started_mom_ = now_mom ();
170 volta_span_ = make_spanner ("VoltaBracket", SCM_EOL);
172 volta_span_->set_property ("text", start_string_);
177 Volta_engraver::acknowledge_note_column (Grob_info i)
180 Volta_bracket_interface::add_column (volta_span_, i.grob ());
184 Volta_engraver::acknowledge_bar_line (Grob_info i)
187 Volta_bracket_interface::add_bar (volta_span_, i.item ());
189 Volta_bracket_interface::add_bar (end_volta_span_, i.item ());
193 Volta_engraver::acknowledge_staff_symbol (Grob_info i)
196 We only want to know about a single staff: then we add to the
198 if (staff_ != SCM_EOL)
199 staff_ = SCM_UNDEFINED;
201 if (staff_ != SCM_UNDEFINED)
202 staff_ = i.grob ()->self_scm ();
206 Volta_engraver::finalize ()
211 Volta_engraver::stop_translation_timestep ()
213 if (volta_span_ && !staff_eligible ())
218 we need to do this here, because STAFF_ is not initialized yet
219 in the 1st call of process_music ()
222 volta_span_->suicide ();
226 if (end_volta_span_ && !end_volta_span_->get_bound (RIGHT))
228 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
229 Item *ci = dynamic_cast<Item *> (cc);
230 end_volta_span_->set_bound (RIGHT, ci);
235 if (volta_span_ && !volta_span_->get_bound (LEFT))
237 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
238 Item *ci = dynamic_cast<Item *> (cc);
239 volta_span_->set_bound (LEFT, ci);
244 TODO: should attach volta to paper-column if no bar is found.
246 ADD_ACKNOWLEDGER (Volta_engraver, staff_symbol);
247 ADD_ACKNOWLEDGER (Volta_engraver, note_column);
248 ADD_ACKNOWLEDGER (Volta_engraver, bar_line);
249 ADD_TRANSLATOR (Volta_engraver,
250 /* doc */ "Make volta brackets.",
251 /* create */ "VoltaBracket",
253 /* read */ "repeatCommands voltaSpannerDuration stavesFound",