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"
17 #include "text-interface.hh"
19 #include "translator.icc"
22 Create Volta spanners, by reading repeatCommands property, usually
23 set by Unfolded_repeat_iterator.
25 class Volta_engraver : public Engraver
28 TRANSLATOR_DECLARATIONS (Volta_engraver);
31 DECLARE_ACKNOWLEDGER (staff_symbol);
32 DECLARE_ACKNOWLEDGER (note_column);
33 DECLARE_ACKNOWLEDGER (bar_line);
35 virtual void finalize ();
36 virtual void derived_mark () const;
37 void stop_translation_timestep ();
38 void process_music ();
42 Spanner *end_volta_span_;
46 bool staff_eligible ();
50 Volta_engraver::derived_mark () const
53 scm_gc_mark (start_string_);
56 Volta_engraver::Volta_engraver ()
59 start_string_ = SCM_EOL;
65 TODO: this logic should be rewritten, it is buggy.
67 One of the problems is that we can't determine wether or not to
68 print the volta bracket during the first step, since that requires
69 acknowledging the staff.
72 Volta_engraver::staff_eligible ()
74 SCM doit = get_property ("voltaOnThisStaff");
75 if (scm_is_bool (doit))
76 return to_boolean (doit);
78 if (!unsmob_grob (staff_))
82 TODO: this does weird things when you open a piece with a
85 SCM staffs = get_property ("stavesFound");
87 /* Only put a volta on the top staff.
88 Maybe this is a bit convoluted, and we should have a single
89 volta engraver in score context or somesuch. */
90 if (!scm_is_pair (staffs))
92 programming_error ("volta engraver can't find staffs");
95 else if (scm_car (scm_last_pair (staffs)) != staff_)
101 Volta_engraver::process_music ()
103 SCM cs = get_property ("repeatCommands");
105 if (!staff_eligible ())
109 start_string_ = SCM_EOL;
110 while (scm_is_pair (cs))
112 SCM c = scm_car (cs);
115 && scm_car (c) == ly_symbol2scm ("volta")
116 && scm_is_pair (scm_cdr (c)))
118 if (scm_cadr (c) == SCM_BOOL_F)
121 start_string_ = scm_cadr (c);
129 SCM l (get_property ("voltaSpannerDuration"));
130 Moment now = now_mom ();
132 bool early_stop = unsmob_moment (l)
133 && *unsmob_moment (l) <= now - started_mom_;
135 end = end || early_stop;
138 if (end && !volta_span_)
139 /* fixme: be more verbose. */
140 warning (_ ("can't end volta spanner"));
143 end_volta_span_ = volta_span_;
148 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
150 warning (_ ("already have a volta spanner, ending that one prematurely"));
154 warning (_ ("also already have an ended spanner"));
155 warning (_ ("giving up"));
159 end_volta_span_ = volta_span_;
164 && Text_interface::is_markup (start_string_))
166 started_mom_ = now_mom ();
168 volta_span_ = make_spanner ("VoltaBracket", SCM_EOL);
170 volta_span_->set_property ("text", start_string_);
175 Volta_engraver::acknowledge_note_column (Grob_info i)
178 Volta_bracket_interface::add_column (volta_span_, i.grob ());
182 Volta_engraver::acknowledge_bar_line (Grob_info i)
185 Volta_bracket_interface::add_bar (volta_span_, i.item ());
187 Volta_bracket_interface::add_bar (end_volta_span_, i.item ());
191 Volta_engraver::acknowledge_staff_symbol (Grob_info i)
194 We only want to know about a single staff: then we add to the
196 if (staff_ != SCM_EOL)
197 staff_ = SCM_UNDEFINED;
199 if (staff_ != SCM_UNDEFINED)
200 staff_ = i.grob ()->self_scm ();
204 Volta_engraver::finalize ()
209 Volta_engraver::stop_translation_timestep ()
211 if (volta_span_ && !staff_eligible ())
216 we need to do this here, because STAFF_ is not initialized yet
217 in the 1st call of process_music ()
220 volta_span_->suicide ();
224 if (end_volta_span_ && !end_volta_span_->get_bound (RIGHT))
226 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
227 Item *ci = dynamic_cast<Item *> (cc);
228 end_volta_span_->set_bound (RIGHT, ci);
233 if (volta_span_ && !volta_span_->get_bound (LEFT))
235 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
236 Item *ci = dynamic_cast<Item *> (cc);
237 volta_span_->set_bound (LEFT, ci);
242 TODO: should attach volta to paper-column if no bar is found.
244 ADD_ACKNOWLEDGER (Volta_engraver, staff_symbol);
245 ADD_ACKNOWLEDGER (Volta_engraver, note_column);
246 ADD_ACKNOWLEDGER (Volta_engraver, bar_line);
247 ADD_TRANSLATOR (Volta_engraver,
248 /* doc */ "Make volta brackets.",
249 /* create */ "VoltaBracket",
251 /* read */ "repeatCommands voltaSpannerDuration stavesFound",