2 repeat-engraver.cc -- implement Repeat_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2000 Jan Nieuwenhuizen <janneke@gnu.org>
9 #include "repeat-engraver.hh"
11 #include "bar-engraver.hh"
12 #include "musical-request.hh"
13 #include "multi-measure-rest.hh"
14 #include "command-request.hh"
15 #include "timing-translator.hh"
16 #include "engraver-group-engraver.hh"
17 #include "repeated-music.hh"
18 #include "timing-translator.hh"
19 #include "volta-spanner.hh"
20 #include "note-column.hh"
21 #include "paper-def.hh"
22 #include "music-list.hh"
24 ADD_THIS_TRANSLATOR (Repeat_engraver);
27 Repeat_engraver::do_try_music (Music* m)
29 if (Repeated_music* r = dynamic_cast<Repeated_music *> (m))
31 if (repeated_music_l_)
36 repeated_music_l_ = r;
40 We acknowledge other types of unfolded music as well, to
41 get auto context selection right.
50 Walk through repeat music, and generate events for appropriate times.
52 UGH. Should use Music_iteration for this.
54 Should also queue some event to get timing information reset during
55 2nd and following voltas.
58 Repeat_engraver::queue_events ()
60 Music_sequence* alt = repeated_music_l_->alternatives_p_;
61 Moment walk_mom = now_mom () + repeated_music_l_->repeat_body_p_->length_mom ();
63 SCM novolta = get_property ("noVoltaBraces");
64 bool create_volta = !to_boolean (novolta);
66 Cons_list<Bar_create_event> becel;
67 becel.append (new Bar_create_event (now_mom (), "|:"));
71 becel.append (new Bar_create_event (walk_mom, ":|"));
72 becel.append (new Bar_create_event (walk_mom, "stop"));
77 int volta_number = repeated_music_l_->repeats_i_ - alt->length_i () + 1;
80 all repeat alternatives, and generate events with
81 appropriate timestamps. The volta spanner event (a number string)
82 happens at the begin of the alt. The :| bar event at the ending.
84 for (Cons<Music> *i = alt->music_p_list_p_->head_; i; i = i->next_)
88 some idiot might typeset a repeat not starting on a
89 barline. Make sure there is one.
91 (todo: should try to avoid line breaks?)
95 becel.append (new Bar_create_event (walk_mom, ""));
101 Bar_create_event * c = new Bar_create_event (walk_mom, last_number+ 1,
108 last_number = volta_number;
110 SCM l (get_property ("voltaSpannerDuration"));
111 if (SMOB_IS_TYPE_B (Moment, l))
113 Moment vSD_mom = *SMOB_TO_TYPE (Moment,l);
114 if ( vSD_mom < i->car_->length_mom() ) // terminate volta early ?
118 becel.append (new Bar_create_event (vSD_mom, "stop"));
122 walk_mom += i->car_->length_mom();
125 becel.append (new Bar_create_event (walk_mom, ":|"));
127 becel.append (new Bar_create_event (walk_mom, "stop"));
131 Cons<Bar_create_event> *&tail = create_barmoments_queue_
132 ? last_cons (create_barmoments_queue_)->next_
133 : create_barmoments_queue_;
140 Repeat_engraver::do_process_music ()
142 if (repeated_music_l_ && !done_this_one_b_)
145 done_this_one_b_ = true;
149 Cons<Bar_create_event> * head = create_barmoments_queue_;
153 Bar_engraver* bar_engraver_l = dynamic_cast <Bar_engraver*>
154 (daddy_grav_l ()->get_simple_translator ("Bar_engraver"));
157 Do all the events that need to be done now.
159 while (head && now_mom () == head->car_->when_)
161 create_barmoments_queue_ = create_barmoments_queue_->next_;
165 String t = head->car_->type_;
166 if (head->car_->bar_b_)
168 if (t == "stop" || t == ":|")
170 end_volta_span_p_ = volta_span_p_;
175 bar_engraver_l->request_bar (t);
177 bar_engraver_l->request_bar ("");
181 assert (!volta_span_p_);
182 volta_span_p_ = new Volta_spanner;
183 announce_element (Score_element_info (volta_span_p_,0));
184 volta_span_p_->set_elt_property ("text",
185 ly_str02scm (t.ch_C()));
186 volta_span_p_->set_elt_property ("last-volta",
187 gh_bool2scm (head->car_->last_b_));
188 // voltaSpannerDuration stuff here.
189 // other property stuff here.
195 warning (_ ("No bar engraver found. Ignoring repeats."));
201 head = create_barmoments_queue_;
204 assert (!head || head->car_->when_ > now_mom ());
209 Repeat_engraver::acknowledge_element (Score_element_info i)
211 if (Note_column *c = dynamic_cast<Note_column *> (i.elem_l_))
214 volta_span_p_->add_column (c);
215 if (end_volta_span_p_)
216 end_volta_span_p_->add_column (c);
218 if (Bar *c = dynamic_cast<Bar*> (i.elem_l_))
221 volta_span_p_->add_bar (c);
222 if (end_volta_span_p_)
223 end_volta_span_p_ ->add_bar(c);
229 Repeat_engraver::do_removal_processing ()
233 typeset_element(volta_span_p_);
235 if (end_volta_span_p_)
237 typeset_element (end_volta_span_p_);
239 // todo: the paranoid may also delete create_barmoments_queue_
243 Repeat_engraver::do_post_move_processing ()
245 for (Cons<Bar_create_event> *p = create_barmoments_queue_;
246 p && p->car_->when_ == now_mom (); p = p->next_)
247 if (p->car_->type_ == "stop")
249 repeated_music_l_ = 0;
250 done_this_one_b_ = false;
255 Repeat_engraver::do_pre_move_processing ()
257 if (end_volta_span_p_)
259 typeset_element (end_volta_span_p_ );
260 end_volta_span_p_ =0;
266 Repeat_engraver::Repeat_engraver()
268 repeated_music_l_ =0;
269 end_volta_span_p_ =0;
271 done_this_one_b_ = false;
272 create_barmoments_queue_ =0;
276 Bar_create_event::Bar_create_event()
282 Bar_create_event::Bar_create_event (Moment w, String s)
290 Bar_create_event::Bar_create_event (Moment w, int i, int j)
297 type_ = to_str (i) + ".-" ;
299 type_ += to_str(j) + ".";