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"
16 #include "side-position-interface.hh"
17 #include "staff-symbol.hh"
18 #include "text-interface.hh"
19 #include "volta-bracket.hh"
22 #include "translator.icc"
25 Create Volta spanners, by reading repeatCommands property, usually
26 set by Volta_repeat_iterator.
28 class Volta_engraver : public Engraver
31 TRANSLATOR_DECLARATIONS (Volta_engraver);
34 DECLARE_END_ACKNOWLEDGER (staff_symbol);
35 DECLARE_ACKNOWLEDGER (staff_symbol);
36 DECLARE_ACKNOWLEDGER (note_column);
37 DECLARE_ACKNOWLEDGER (bar_line);
39 virtual void finalize ();
40 virtual void derived_mark () const;
41 void stop_translation_timestep ();
42 void process_music ();
46 Spanner *end_volta_span_;
50 bool staff_eligible ();
54 Volta_engraver::derived_mark () const
57 scm_gc_mark (start_string_);
60 Volta_engraver::Volta_engraver ()
63 start_string_ = SCM_EOL;
69 TODO: this logic should be rewritten, it is buggy.
71 One of the problems is that we can't determine wether or not to
72 print the volta bracket during the first step, since that requires
73 acknowledging the staff.
76 Volta_engraver::staff_eligible ()
78 SCM doit = get_property ("voltaOnThisStaff");
79 if (scm_is_bool (doit))
80 return to_boolean (doit);
82 if (!unsmob_grob (staff_))
86 TODO: this does weird things when you open a piece with a
89 SCM staffs = get_property ("stavesFound");
91 /* Only put a volta on the top staff.
92 Maybe this is a bit convoluted, and we should have a single
93 volta engraver in score context or somesuch. */
94 if (!scm_is_pair (staffs))
96 programming_error ("volta engraver can't find staffs");
99 else if (scm_car (scm_last_pair (staffs)) != staff_)
105 Volta_engraver::process_music ()
107 SCM cs = get_property ("repeatCommands");
109 if (!staff_eligible ())
113 start_string_ = SCM_EOL;
114 while (scm_is_pair (cs))
116 SCM c = scm_car (cs);
119 && scm_car (c) == ly_symbol2scm ("volta")
120 && scm_is_pair (scm_cdr (c)))
122 if (scm_cadr (c) == SCM_BOOL_F)
125 start_string_ = scm_cadr (c);
133 SCM l (get_property ("voltaSpannerDuration"));
134 Moment now = now_mom ();
136 bool early_stop = unsmob_moment (l)
137 && *unsmob_moment (l) <= now - started_mom_;
139 end = end || early_stop;
142 if (end && !volta_span_)
143 /* fixme: be more verbose. */
144 warning (_ ("can't end volta spanner"));
147 end_volta_span_ = volta_span_;
152 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
154 warning (_ ("already have a volta spanner, ending that one prematurely"));
158 warning (_ ("also already have an ended spanner"));
159 warning (_ ("giving up"));
163 end_volta_span_ = volta_span_;
168 && Text_interface::is_markup (start_string_))
170 started_mom_ = now_mom ();
172 volta_span_ = make_spanner ("VoltaBracket", SCM_EOL);
174 volta_span_->set_property ("text", start_string_);
179 Volta_engraver::acknowledge_note_column (Grob_info i)
182 Volta_bracket_interface::add_column (volta_span_, i.grob ());
186 Volta_engraver::acknowledge_bar_line (Grob_info i)
189 Volta_bracket_interface::add_bar (volta_span_, i.item ());
191 Volta_bracket_interface::add_bar (end_volta_span_, i.item ());
195 Volta_engraver::acknowledge_end_staff_symbol (Grob_info i)
197 if (i.grob ()->self_scm () == staff_)
202 Volta_engraver::acknowledge_staff_symbol (Grob_info i)
205 We only want to know about a single staff: then we add to the
207 if (staff_ != SCM_EOL)
208 staff_ = SCM_UNDEFINED;
210 if (staff_ != SCM_UNDEFINED)
211 staff_ = i.grob ()->self_scm ();
216 Volta_engraver::finalize ()
221 Volta_engraver::stop_translation_timestep ()
223 if (volta_span_ && !staff_eligible ())
228 we need to do this here, because STAFF_ is not initialized yet
229 in the 1st call of process_music ()
232 volta_span_->suicide ();
236 if (end_volta_span_ && !end_volta_span_->get_bound (RIGHT))
238 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
239 Item *ci = dynamic_cast<Item *> (cc);
240 end_volta_span_->set_bound (RIGHT, ci);
245 if (volta_span_ && !volta_span_->get_bound (LEFT))
247 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
248 Item *ci = dynamic_cast<Item *> (cc);
249 volta_span_->set_bound (LEFT, ci);
254 TODO: should attach volta to paper-column if no bar is found.
256 ADD_ACKNOWLEDGER (Volta_engraver, staff_symbol);
257 ADD_END_ACKNOWLEDGER (Volta_engraver, staff_symbol);
258 ADD_ACKNOWLEDGER (Volta_engraver, note_column);
259 ADD_ACKNOWLEDGER (Volta_engraver, bar_line);
260 ADD_TRANSLATOR (Volta_engraver,
261 /* doc */ "Make volta brackets.",
262 /* create */ "VoltaBracket",
263 /* read */ "repeatCommands voltaSpannerDuration stavesFound",