* lexer-gcc-3.1.sh: Remove.
[lilypond/patrick.git] / lily / volta-engraver.cc
blob9439d6f6d710f0ea6c4ca8cc269b003f877f707b
1 /*
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>
7 */
9 #include "engraver.hh"
11 #include "bar-line.hh"
12 #include "context.hh"
13 #include "international.hh"
14 #include "note-column.hh"
15 #include "side-position-interface.hh"
16 #include "staff-symbol.hh"
17 #include "text-interface.hh"
18 #include "volta-bracket.hh"
19 #include "warn.hh"
21 #include "translator.icc"
24 Create Volta spanners, by reading repeatCommands property, usually
25 set by Volta_repeat_iterator.
27 class Volta_engraver : public Engraver
29 public:
30 TRANSLATOR_DECLARATIONS (Volta_engraver);
31 protected:
33 DECLARE_END_ACKNOWLEDGER (staff_symbol);
34 DECLARE_ACKNOWLEDGER (staff_symbol);
35 DECLARE_ACKNOWLEDGER (note_column);
36 DECLARE_ACKNOWLEDGER (bar_line);
38 virtual void finalize ();
39 virtual void derived_mark () const;
40 void stop_translation_timestep ();
41 void process_music ();
43 Moment started_mom_;
44 Spanner *volta_span_;
45 Spanner *end_volta_span_;
46 SCM staff_;
47 SCM start_string_;
49 bool staff_eligible ();
52 void
53 Volta_engraver::derived_mark () const
55 scm_gc_mark (staff_);
56 scm_gc_mark (start_string_);
59 Volta_engraver::Volta_engraver ()
61 staff_ = SCM_EOL;
62 start_string_ = SCM_EOL;
63 volta_span_ = 0;
64 end_volta_span_ = 0;
68 TODO: this logic should be rewritten, it is buggy.
70 One of the problems is that we can't determine wether or not to
71 print the volta bracket during the first step, since that requires
72 acknowledging the staff.
74 bool
75 Volta_engraver::staff_eligible ()
77 SCM doit = get_property ("voltaOnThisStaff");
78 if (scm_is_bool (doit))
79 return to_boolean (doit);
81 if (!unsmob_grob (staff_))
82 return false;
85 TODO: this does weird things when you open a piece with a
86 volta spanner.
88 SCM staffs = get_property ("stavesFound");
90 /* Only put a volta on the top staff.
91 Maybe this is a bit convoluted, and we should have a single
92 volta engraver in score context or somesuch. */
93 if (!scm_is_pair (staffs))
95 programming_error ("volta engraver can't find staffs");
96 return false;
98 else if (scm_car (scm_last_pair (staffs)) != staff_)
99 return false;
100 return true;
103 void
104 Volta_engraver::process_music ()
106 SCM cs = get_property ("repeatCommands");
108 if (!staff_eligible ())
109 return;
111 bool end = false;
112 start_string_ = SCM_EOL;
113 while (scm_is_pair (cs))
115 SCM c = scm_car (cs);
117 if (scm_is_pair (c)
118 && scm_car (c) == ly_symbol2scm ("volta")
119 && scm_is_pair (scm_cdr (c)))
121 if (scm_cadr (c) == SCM_BOOL_F)
122 end = true;
123 else
124 start_string_ = scm_cadr (c);
127 cs = scm_cdr (cs);
130 if (volta_span_)
132 SCM l (get_property ("voltaSpannerDuration"));
133 Moment now = now_mom ();
135 bool early_stop = unsmob_moment (l)
136 && *unsmob_moment (l) <= now - started_mom_;
138 end = end || early_stop;
141 if (end && !volta_span_)
142 /* fixme: be more verbose. */
143 warning (_ ("can't end volta spanner"));
144 else if (end)
146 end_volta_span_ = volta_span_;
147 volta_span_ = 0;
150 if (volta_span_
151 && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
153 warning (_ ("already have a volta spanner, ending that one prematurely"));
155 if (end_volta_span_)
157 warning (_ ("also already have an ended spanner"));
158 warning (_ ("giving up"));
159 return;
162 end_volta_span_ = volta_span_;
163 volta_span_ = 0;
166 if (!volta_span_
167 && Text_interface::is_markup (start_string_))
169 started_mom_ = now_mom ();
171 volta_span_ = make_spanner ("VoltaBracket", SCM_EOL);
173 volta_span_->set_property ("text", start_string_);
177 void
178 Volta_engraver::acknowledge_note_column (Grob_info i)
180 if (volta_span_)
181 Volta_bracket_interface::add_column (volta_span_, i.grob ());
184 void
185 Volta_engraver::acknowledge_bar_line (Grob_info i)
187 if (volta_span_)
188 Volta_bracket_interface::add_bar (volta_span_, i.item ());
189 if (end_volta_span_)
190 Volta_bracket_interface::add_bar (end_volta_span_, i.item ());
193 void
194 Volta_engraver::acknowledge_end_staff_symbol (Grob_info i)
196 if (i.grob ()->self_scm () == staff_)
197 staff_ = SCM_EOL;
200 void
201 Volta_engraver::acknowledge_staff_symbol (Grob_info i)
204 We only want to know about a single staff: then we add to the
205 support. */
206 if (staff_ != SCM_EOL)
207 staff_ = SCM_UNDEFINED;
209 if (staff_ != SCM_UNDEFINED)
210 staff_ = i.grob ()->self_scm ();
214 void
215 Volta_engraver::finalize ()
219 void
220 Volta_engraver::stop_translation_timestep ()
222 if (volta_span_ && !staff_eligible ())
225 THIS IS A KLUDGE.
227 we need to do this here, because STAFF_ is not initialized yet
228 in the 1st call of process_music ()
231 volta_span_->suicide ();
232 volta_span_ = 0;
235 if (end_volta_span_ && !end_volta_span_->get_bound (RIGHT))
237 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
238 Item *ci = dynamic_cast<Item *> (cc);
239 end_volta_span_->set_bound (RIGHT, ci);
242 end_volta_span_ = 0;
244 if (volta_span_ && !volta_span_->get_bound (LEFT))
246 Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
247 Item *ci = dynamic_cast<Item *> (cc);
248 volta_span_->set_bound (LEFT, ci);
253 TODO: should attach volta to paper-column if no bar is found.
255 ADD_ACKNOWLEDGER (Volta_engraver, staff_symbol);
256 ADD_END_ACKNOWLEDGER (Volta_engraver, staff_symbol);
257 ADD_ACKNOWLEDGER (Volta_engraver, note_column);
258 ADD_ACKNOWLEDGER (Volta_engraver, bar_line);
259 ADD_TRANSLATOR (Volta_engraver,
260 /* doc */ "Make volta brackets.",
261 /* create */ "VoltaBracket",
262 /* accept */ "",
263 /* read */ "repeatCommands voltaSpannerDuration stavesFound",
264 /* write */ "");