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>
10 #include "engraver.hh"
12 #include "volta-bracket.hh"
13 #include "note-column.hh"
14 #include "bar-line.hh"
15 #include "side-position-interface.hh"
17 #include "staff-symbol.hh"
20 Create Volta spanners, by reading repeatCommands property, usually
21 set by Unfolded_repeat_iterator.
23 class Volta_engraver
: public Engraver
26 TRANSLATOR_DECLARATIONS (Volta_engraver
);
29 virtual void acknowledge_grob (Grob_info
);
30 virtual void finalize ();
31 virtual void stop_translation_timestep ();
32 virtual void process_music ();
34 virtual void derived_mark () const;
37 Spanner
*end_volta_span_
;
41 bool staff_eligible ();
45 Volta_engraver::derived_mark () const
48 scm_gc_mark (start_string_
);
51 Volta_engraver::Volta_engraver ()
53 start_string_
= SCM_EOL
;
60 TODO: this logic should be rewritten, it is buggy.
62 One of the problems is that we can't determine wether or not to
63 print the volta bracket during the first step, since that requires
64 acknowledging the staff.
67 Volta_engraver::staff_eligible ()
69 SCM doit
= get_property ("voltaOnThisStaff");
70 if (scm_is_bool (doit
))
72 return to_boolean (doit
);
75 if (!unsmob_grob (staff_
))
79 TODO: this does weird things when you open a piece with a
82 SCM staffs
= get_property ("stavesFound");
84 /* Only put a volta on the top staff.
85 Maybe this is a bit convoluted, and we should have a single
86 volta engraver in score context or somesuch. */
87 if (!scm_is_pair (staffs
))
89 programming_error ("volta engraver can't find staffs");
92 else if (scm_car (scm_last_pair (staffs
)) != staff_
)
98 Volta_engraver::process_music ()
100 SCM cs
= get_property ("repeatCommands");
102 if (!staff_eligible ())
106 start_string_
= SCM_EOL
;
107 while (scm_is_pair (cs
))
109 SCM c
= scm_car (cs
);
112 && scm_car (c
) == ly_symbol2scm ("volta")
113 && scm_is_pair (scm_cdr (c
)))
115 if (scm_cadr (c
) == SCM_BOOL_F
)
118 start_string_
= scm_cadr (c
);
126 SCM
l (get_property ("voltaSpannerDuration"));
127 Moment now
= now_mom ();
129 bool early_stop
= unsmob_moment (l
)
130 && *unsmob_moment (l
) <= now
- started_mom_
;
132 end
= end
|| early_stop
;
135 if (end
&& !volta_span_
)
136 /* fixme: be more verbose. */
137 warning (_ ("can't end volta spanner"));
140 end_volta_span_
= volta_span_
;
145 && (scm_is_string (start_string_
) || scm_is_pair (start_string_
)))
147 warning (_ ("already have a volta spanner, ending that one prematurely"));
151 warning (_ ("also already have an ended spanner"));
152 warning (_ ("giving up"));
156 end_volta_span_
= volta_span_
;
161 && (scm_is_string (start_string_
) || scm_is_pair (start_string_
)))
163 started_mom_
= now_mom ();
165 volta_span_
= make_spanner ("VoltaBracket", SCM_EOL
);
167 volta_span_
->set_property ("text", start_string_
);
172 Volta_engraver::acknowledge_grob (Grob_info i
)
174 if (Item
*item
= dynamic_cast<Item
*> (i
.grob ()))
176 if (Note_column::has_interface (item
))
179 Volta_bracket_interface::add_column (volta_span_
, item
);
181 if (Bar_line::has_interface (item
))
184 Volta_bracket_interface::add_bar (volta_span_
, item
);
186 Volta_bracket_interface::add_bar (end_volta_span_
, item
);
189 else if (Staff_symbol::has_interface (i
.grob ()))
192 We only want to know about a single staff: then we add to the
194 if (staff_
!= SCM_EOL
)
195 staff_
= SCM_UNDEFINED
;
197 if (staff_
!= SCM_UNDEFINED
)
198 staff_
= i
.grob ()->self_scm ();
203 Volta_engraver::finalize ()
208 Volta_engraver::stop_translation_timestep ()
210 if (volta_span_
&& !staff_eligible ())
215 we need to do this here, because STAFF_ is not initialized yet
216 in the 1st call of process_music ()
219 volta_span_
->suicide ();
223 if (end_volta_span_
&& !end_volta_span_
->get_bound (RIGHT
))
225 Grob
*cc
= unsmob_grob (get_property ("currentCommandColumn"));
226 Item
*ci
= dynamic_cast<Item
*> (cc
);
227 end_volta_span_
->set_bound (RIGHT
, ci
);
232 if (volta_span_
&& !volta_span_
->get_bound (LEFT
))
234 Grob
*cc
= unsmob_grob (get_property ("currentCommandColumn"));
235 Item
*ci
= dynamic_cast<Item
*> (cc
);
236 volta_span_
->set_bound (LEFT
, ci
);
241 TODO: should attach volta to paper-column if no bar is found.
244 ADD_TRANSLATOR (Volta_engraver
,
245 /* descr */ "Make volta brackets.",
246 /* creats*/ "VoltaBracket",
248 /* acks */ "bar-line-interface staff-symbol-interface note-column-interface",
249 /* reads */ "repeatCommands voltaSpannerDuration stavesFound",