(staff_eligible): new function.
[lilypond.git] / lily / volta-engraver.cc
blob195a258c580dd8591654d1bfd464db890f293e42
1 /*
2 volta-engraver.cc -- implement Volta_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 */
10 #include "engraver.hh"
11 #include "translator-group.hh"
12 #include "volta-bracket.hh"
13 #include "item.hh"
14 #include "note-column.hh"
15 #include "bar-line.hh"
16 #include "side-position-interface.hh"
17 #include "warn.hh"
18 #include "staff-symbol.hh"
21 Create Volta spanners, by reading repeatCommands property, usually
22 set by Unfolded_repeat_iterator.
24 class Volta_engraver : public Engraver
26 public:
27 TRANSLATOR_DECLARATIONS(Volta_engraver);
28 protected:
30 virtual void acknowledge_grob (Grob_info);
31 virtual void finalize ();
32 virtual void stop_translation_timestep ();
33 virtual void process_music ();
35 Moment started_mom_;
36 Spanner *volta_span_;
37 Spanner *end_volta_span_;
38 SCM staff_;
39 SCM start_string_;
41 bool staff_eligible ();
45 Volta_engraver::Volta_engraver ()
47 staff_ = SCM_EOL;
48 volta_span_ = 0;
49 end_volta_span_ = 0;
54 TODO: this logic should be rewritten, it is buggy.
56 One of the problems is that we can't determine wether or not to
57 print the volta bracket during the first step, since that requires
58 acknowledging the staff.
60 bool
61 Volta_engraver::staff_eligible ()
64 UGH.
66 if (!unsmob_grob (staff_))
67 return true;
69 if (!to_boolean (get_property ("voltaOnThisStaff")))
72 TODO: this does weird things when you open a piece with a
73 volta spanner.
76 SCM staffs = get_property ("stavesFound");
79 only put a volta on the top staff.
81 May be this is a bit convoluted, and we should have a single
82 volta engraver in score context or somesuch.
85 if (!gh_pair_p (staffs))
87 programming_error ("Huh? Volta engraver can't find staffs?");
88 return false;
90 else if (ly_car (scm_last_pair (staffs)) != staff_)
92 return false;
95 return true;
98 void
99 Volta_engraver::process_music ()
101 SCM cs = get_property ("repeatCommands");
103 if (!staff_eligible ())
104 return ;
107 bool end = false;
108 start_string_ = SCM_EOL;
109 while (gh_pair_p (cs))
111 SCM c = ly_car (cs);
113 if (gh_pair_p (c)
114 && ly_car (c) == ly_symbol2scm ("volta")
115 && gh_pair_p (ly_cdr (c)))
117 if (ly_cadr (c) == SCM_BOOL_F)
118 end = true;
119 else
120 start_string_ = ly_cadr (c);
123 cs = ly_cdr (cs);
126 if (volta_span_)
128 SCM l (get_property ("voltaSpannerDuration"));
129 Moment now = now_mom ();
131 bool early_stop = unsmob_moment (l)
132 && *unsmob_moment (l) <= now - started_mom_;
134 end = end || early_stop;
138 if (end && !volta_span_)
140 warning (_ ("No volta spanner to end")); // fixme: be more verbose.
142 else if (end)
144 end_volta_span_ = volta_span_;
145 volta_span_ =0;
148 if (volta_span_ &&
149 (gh_string_p (start_string_) || gh_pair_p (start_string_)))
151 warning (_ ("Already have a volta spanner. Stopping that one prematurely."));
153 if (end_volta_span_)
155 warning (_ ("Also have a stopped spanner. Giving up."));
156 return ;
159 end_volta_span_ = volta_span_;
160 volta_span_ = 0;
163 if (!volta_span_ &&
164 (gh_string_p (start_string_) || gh_pair_p (start_string_)))
166 started_mom_ = now_mom () ;
168 volta_span_ = new Spanner (get_property ("VoltaBracket"));
170 announce_grob (volta_span_, SCM_EOL);
171 volta_span_->set_grob_property ("text", start_string_);
176 void
177 Volta_engraver::acknowledge_grob (Grob_info i)
179 if (Item* item = dynamic_cast<Item*> (i.grob_))
181 if (Note_column::has_interface (item))
183 if (volta_span_)
184 Volta_bracket_interface::add_column (volta_span_,item);
186 if (Bar_line::has_interface (item))
188 if (volta_span_)
189 Volta_bracket_interface::add_bar (volta_span_, item);
190 if (end_volta_span_)
191 Volta_bracket_interface::add_bar (end_volta_span_ , item);
194 else if (Staff_symbol::has_interface (i.grob_))
197 We only want to know about a single staff: then we add to the
198 support. */
199 if (staff_ != SCM_EOL)
200 staff_ = SCM_UNDEFINED;
202 if (staff_ != SCM_UNDEFINED)
203 staff_ = i.grob_->self_scm();
207 void
208 Volta_engraver::finalize ()
210 if (volta_span_)
212 typeset_grob (volta_span_);
214 if (end_volta_span_)
216 typeset_grob (end_volta_span_);
222 void
223 Volta_engraver::stop_translation_timestep ()
225 if (volta_span_ && !staff_eligible ())
228 THIS IS A KLUDGE.
230 we need to do this here, because STAFF_ is not initialized yet
231 in the 1st call of process_music()
234 volta_span_->suicide( );
235 volta_span_ = 0;
238 if (end_volta_span_)
240 typeset_grob (end_volta_span_);
241 end_volta_span_ =0;
246 TODO: should attach volta to paper-column if no bar is found.
249 ENTER_DESCRIPTION(Volta_engraver,
250 /* descr */ "Make volta brackets",
251 /* creats*/ "VoltaBracket",
252 /* accepts */ "",
253 /* acks */ "bar-line-interface staff-symbol-interface note-column-interface",
254 /* reads */ "repeatCommands voltaSpannerDuration stavesFound",
255 /* write */ "");