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"
19 Create Volta spanners, by reading repeatCommands property, usually
20 set by Unfolded_repeat_iterator.
22 class Volta_engraver : public Engraver
25 TRANSLATOR_DECLARATIONS (Volta_engraver);
28 virtual void acknowledge_grob (Grob_info);
29 virtual void finalize ();
30 virtual void stop_translation_timestep ();
31 virtual void process_music ();
33 virtual void derived_mark () const;
36 Spanner *end_volta_span_;
40 bool staff_eligible ();
44 Volta_engraver::derived_mark () const
47 scm_gc_mark (start_string_);
50 Volta_engraver::Volta_engraver ()
52 start_string_ = SCM_EOL;
59 TODO: this logic should be rewritten, it is buggy.
61 One of the problems is that we can't determine wether or not to
62 print the volta bracket during the first step, since that requires
63 acknowledging the staff.
66 Volta_engraver::staff_eligible ()
68 SCM doit = get_property ("voltaOnThisStaff");
69 if (scm_is_bool (doit))
71 return to_boolean (doit);
74 if (!unsmob_grob (staff_))
78 TODO: this does weird things when you open a piece with a
81 SCM staffs = get_property ("stavesFound");
83 /* Only put a volta on the top staff.
84 Maybe this is a bit convoluted, and we should have a single
85 volta engraver in score context or somesuch. */
86 if (!scm_is_pair (staffs))
88 programming_error ("volta engraver can't find staffs");
91 else if (scm_car (scm_last_pair (staffs)) != staff_)
97 Volta_engraver::process_music ()
99 SCM cs = get_property ("repeatCommands");
101 if (!staff_eligible ())
105 start_string_ = SCM_EOL;
106 while (scm_is_pair (cs))
108 SCM c = scm_car (cs);
111 && scm_car (c) == ly_symbol2scm ("volta")
112 && scm_is_pair (scm_cdr (c)))
114 if (scm_cadr (c) == SCM_BOOL_F)
117 start_string_ = scm_cadr (c);
125 SCM l (get_property ("voltaSpannerDuration"));
126 Moment now = now_mom ();
128 bool early_stop = unsmob_moment (l)
129 && *unsmob_moment (l) <= now - started_mom_;
131 end = end || early_stop;
134 if (end && !volta_span_)
135 /* fixme: be more verbose. */
136 warning (_ ("can't end volta spanner"));
139 end_volta_span_ = volta_span_;
144 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
146 warning (_ ("already have a volta spanner, ending that one prematurely"));
150 warning (_ ("also already have an ended spanner"));
151 warning (_ ("giving up"));
155 end_volta_span_ = volta_span_;
160 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
162 started_mom_ = now_mom ();
164 volta_span_ = make_spanner ("VoltaBracket", SCM_EOL);
166 volta_span_->set_property ("text", start_string_);
171 Volta_engraver::acknowledge_grob (Grob_info i)
173 if (Item *item = dynamic_cast<Item *> (i.grob ()))
175 if (Note_column::has_interface (item))
178 Volta_bracket_interface::add_column (volta_span_, item);
180 if (Bar_line::has_interface (item))
183 Volta_bracket_interface::add_bar (volta_span_, item);
185 Volta_bracket_interface::add_bar (end_volta_span_, item);
188 else if (Staff_symbol::has_interface (i.grob ()))
191 We only want to know about a single staff: then we add to the
193 if (staff_ != SCM_EOL)
194 staff_ = SCM_UNDEFINED;
196 if (staff_ != SCM_UNDEFINED)
197 staff_ = i.grob ()->self_scm ();
202 Volta_engraver::finalize ()
207 Volta_engraver::stop_translation_timestep ()
209 if (volta_span_ && !staff_eligible ())
214 we need to do this here, because STAFF_ is not initialized yet
215 in the 1st call of process_music ()
218 volta_span_->suicide ();
222 if (end_volta_span_ && !end_volta_span_->get_bound (RIGHT))
224 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
225 Item *ci = dynamic_cast<Item *> (cc);
226 end_volta_span_->set_bound (RIGHT, ci);
231 if (volta_span_ && !volta_span_->get_bound (LEFT))
233 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
234 Item *ci = dynamic_cast<Item *> (cc);
235 volta_span_->set_bound (LEFT, ci);
240 TODO: should attach volta to paper-column if no bar is found.
243 ADD_TRANSLATOR (Volta_engraver,
244 /* descr */ "Make volta brackets.",
245 /* creats*/ "VoltaBracket",
247 /* acks */ "bar-line-interface staff-symbol-interface note-column-interface",
248 /* reads */ "repeatCommands voltaSpannerDuration stavesFound",