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))
76 return to_boolean (doit);
79 if (!unsmob_grob (staff_))
83 TODO: this does weird things when you open a piece with a
86 SCM staffs = get_property ("stavesFound");
88 /* Only put a volta on the top staff.
89 Maybe this is a bit convoluted, and we should have a single
90 volta engraver in score context or somesuch. */
91 if (!scm_is_pair (staffs))
93 programming_error ("volta engraver can't find staffs");
96 else if (scm_car (scm_last_pair (staffs)) != staff_)
102 Volta_engraver::process_music ()
104 SCM cs = get_property ("repeatCommands");
106 if (!staff_eligible ())
110 start_string_ = SCM_EOL;
111 while (scm_is_pair (cs))
113 SCM c = scm_car (cs);
116 && scm_car (c) == ly_symbol2scm ("volta")
117 && scm_is_pair (scm_cdr (c)))
119 if (scm_cadr (c) == SCM_BOOL_F)
122 start_string_ = scm_cadr (c);
130 SCM l (get_property ("voltaSpannerDuration"));
131 Moment now = now_mom ();
133 bool early_stop = unsmob_moment (l)
134 && *unsmob_moment (l) <= now - started_mom_;
136 end = end || early_stop;
139 if (end && !volta_span_)
140 /* fixme: be more verbose. */
141 warning (_ ("can't end volta spanner"));
144 end_volta_span_ = volta_span_;
149 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
151 warning (_ ("already have a volta spanner, ending that one prematurely"));
155 warning (_ ("also already have an ended spanner"));
156 warning (_ ("giving up"));
160 end_volta_span_ = volta_span_;
165 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
167 started_mom_ = now_mom ();
169 volta_span_ = make_spanner ("VoltaBracket", SCM_EOL);
171 volta_span_->set_property ("text", start_string_);
176 Volta_engraver::acknowledge_note_column (Grob_info i)
179 Volta_bracket_interface::add_column (volta_span_, i.grob ());
183 Volta_engraver::acknowledge_bar_line (Grob_info i)
186 Volta_bracket_interface::add_bar (volta_span_, i.item ());
188 Volta_bracket_interface::add_bar (end_volta_span_, i.item ());
192 Volta_engraver::acknowledge_staff_symbol (Grob_info i)
195 We only want to know about a single staff: then we add to the
197 if (staff_ != SCM_EOL)
198 staff_ = SCM_UNDEFINED;
200 if (staff_ != SCM_UNDEFINED)
201 staff_ = i.grob ()->self_scm ();
205 Volta_engraver::finalize ()
210 Volta_engraver::stop_translation_timestep ()
212 if (volta_span_ && !staff_eligible ())
217 we need to do this here, because STAFF_ is not initialized yet
218 in the 1st call of process_music ()
221 volta_span_->suicide ();
225 if (end_volta_span_ && !end_volta_span_->get_bound (RIGHT))
227 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
228 Item *ci = dynamic_cast<Item *> (cc);
229 end_volta_span_->set_bound (RIGHT, ci);
234 if (volta_span_ && !volta_span_->get_bound (LEFT))
236 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
237 Item *ci = dynamic_cast<Item *> (cc);
238 volta_span_->set_bound (LEFT, ci);
243 TODO: should attach volta to paper-column if no bar is found.
245 ADD_ACKNOWLEDGER (Volta_engraver, staff_symbol);
246 ADD_ACKNOWLEDGER (Volta_engraver, note_column);
247 ADD_ACKNOWLEDGER (Volta_engraver, bar_line);
248 ADD_TRANSLATOR (Volta_engraver,
249 /* doc */ "Make volta brackets.",
250 /* create */ "VoltaBracket",
252 /* read */ "repeatCommands voltaSpannerDuration stavesFound",