2 repeat-engraver.cc -- implement Repeat_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--1999 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.
55 Repeat_engraver::queue_events ()
57 Music_sequence* alt = repeated_music_l_->alternatives_p_;
58 Moment walk_mom = now_mom () + repeated_music_l_->repeat_body_p_->length_mom ();
60 SCM novolta = get_property ("noVoltaBraces",0);
61 bool create_volta = !to_boolean (novolta);
63 Cons_list<Bar_create_event> becel;
64 becel.append (new Bar_create_event (now_mom (), "|:"));
68 becel.append (new Bar_create_event (walk_mom, ":|"));
69 becel.append (new Bar_create_event (walk_mom, "stop"));
74 int volta_number = repeated_music_l_->repeats_i_ - alt->length_i () + 1;
77 all repeat alternatives, and generate events with
78 appropriate timestamps. The volta spanner event (a number string)
79 happens at the begin of the alt. The :| bar event at the ending.
81 for (Cons<Music> *i = alt->music_p_list_p_->head_; i; i = i->next_)
85 some idiot might typeset a repeat not starting on a
86 barline. Make sure there is one.
88 (todo: should try to avoid line breaks?)
92 becel.append (new Bar_create_event (walk_mom, ""));
98 Bar_create_event * c = new Bar_create_event (walk_mom, last_number+ 1,
105 last_number = volta_number;
107 SCM l (get_property ("voltaSpannerDuration", 0));
108 if (SMOB_IS_TYPE_B (Moment, l))
110 Moment vSD_mom = *SMOB_TO_TYPE (Moment,l);
111 if ( vSD_mom < i->car_->length_mom() ) // terminate volta early ?
115 becel.append (new Bar_create_event (vSD_mom, "stop"));
119 walk_mom += i->car_->length_mom();
122 becel.append (new Bar_create_event (walk_mom, ":|"));
124 becel.append (new Bar_create_event (walk_mom, "stop"));
128 Cons<Bar_create_event> *&tail = create_barmoments_queue_
129 ? last_cons (create_barmoments_queue_)->next_
130 : create_barmoments_queue_;
137 Repeat_engraver::do_process_requests ()
139 if (repeated_music_l_ && !done_this_one_b_)
142 done_this_one_b_ = true;
146 Cons<Bar_create_event> * head = create_barmoments_queue_;
150 Bar_engraver* bar_engraver_l = dynamic_cast <Bar_engraver*>
151 (daddy_grav_l ()->get_simple_translator ("Bar_engraver"));
154 Do all the events that need to be done now.
156 while (head && now_mom () == head->car_->when_)
158 create_barmoments_queue_ = create_barmoments_queue_->next_;
162 String t = head->car_->type_;
163 if (head->car_->bar_b_)
165 if (t == "stop" || t == ":|")
167 end_volta_span_p_ = volta_span_p_;
172 bar_engraver_l->request_bar (t);
174 bar_engraver_l->request_bar ("");
178 assert (!volta_span_p_);
179 volta_span_p_ = new Volta_spanner;
180 announce_element (Score_element_info (volta_span_p_,0));
181 volta_span_p_->set_elt_property ("text",
182 ly_str02scm (t.ch_C()));
183 volta_span_p_->set_elt_property ("last-volta",
184 gh_bool2scm (head->car_->last_b_));
185 // voltaSpannerDuration stuff here.
186 // other property stuff here.
192 warning (_ ("No bar engraver found. Ignoring repeats."));
198 head = create_barmoments_queue_;
201 assert (!head || head->car_->when_ > now_mom ());
206 Repeat_engraver::acknowledge_element (Score_element_info i)
208 if (Note_column *c = dynamic_cast<Note_column *> (i.elem_l_))
211 volta_span_p_->add_column (c);
212 if (end_volta_span_p_)
213 end_volta_span_p_->add_column (c);
215 if (Bar *c = dynamic_cast<Bar*> (i.elem_l_))
218 volta_span_p_->add_bar (c);
219 if (end_volta_span_p_)
220 end_volta_span_p_ ->add_bar(c);
226 Repeat_engraver::do_removal_processing ()
230 typeset_element(volta_span_p_);
232 if (end_volta_span_p_)
234 typeset_element (end_volta_span_p_);
236 // todo: the paranoid may also delete create_barmoments_queue_
240 Repeat_engraver::do_post_move_processing ()
242 for (Cons<Bar_create_event> *p = create_barmoments_queue_;
243 p && p->car_->when_ == now_mom (); p = p->next_)
244 if (p->car_->type_ == "stop")
246 repeated_music_l_ = 0;
247 done_this_one_b_ = false;
252 Repeat_engraver::do_pre_move_processing ()
254 if (end_volta_span_p_)
256 typeset_element (end_volta_span_p_ );
257 end_volta_span_p_ =0;
263 Repeat_engraver::Repeat_engraver()
265 repeated_music_l_ =0;
266 end_volta_span_p_ =0;
268 done_this_one_b_ = false;
269 create_barmoments_queue_ =0;
273 Bar_create_event::Bar_create_event()
279 Bar_create_event::Bar_create_event (Moment w, String s)
287 Bar_create_event::Bar_create_event (Moment w, int i, int j)
294 type_ = to_str (i) + ".-" ;
296 type_ += to_str(j) + ".";