lilypond-1.3.18
[lilypond.git] / lily / repeat-engraver.cc
blob86b202972eac9e4d49e15c29498ff600b4de830f
1 /*
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>
7 */
9 #include "repeat-engraver.hh"
10 #include "bar.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);
26 bool
27 Repeat_engraver::do_try_music (Music* m)
29 if (Repeated_music* r = dynamic_cast<Repeated_music *> (m))
31 if (repeated_music_l_)
32 return false;
34 if (r->volta_fold_b_)
36 repeated_music_l_ = r;
40 We acknowledge other types of unfolded music as well, to
41 get auto context selection right.
43 return true;
46 return false;
49 /**
50 Walk through repeat music, and generate events for appropriate times.
52 UGH. Should use Music_iteration for this.
54 void
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 (), "|:"));
66 if (!alt)
68 becel.append (new Bar_create_event (walk_mom, ":|"));
69 becel.append (new Bar_create_event (walk_mom, "stop"));
71 else
73 int last_number = 0;
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?)
90 if (last_number == 0)
92 becel.append (new Bar_create_event (walk_mom, ""));
96 if (create_volta)
98 Bar_create_event * c = new Bar_create_event (walk_mom, last_number+ 1,
99 volta_number);
101 if (!i->next_)
102 c->last_b_ = true;
104 becel.append (c);
105 last_number = volta_number;
106 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 ?
113 vSD_mom += walk_mom;
114 c->last_b_ = true;
115 becel.append (new Bar_create_event (vSD_mom, "stop"));
119 walk_mom += i->car_->length_mom();
121 if (i->next_)
122 becel.append (new Bar_create_event (walk_mom, ":|"));
123 else
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_;
132 tail = becel.head_ ;
133 becel.head_ = 0;
136 void
137 Repeat_engraver::do_process_requests ()
139 if (repeated_music_l_ && !done_this_one_b_)
141 queue_events ();
142 done_this_one_b_ = true;
146 Cons<Bar_create_event> * head = create_barmoments_queue_;
147 if (!head)
148 return;
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_;
159 head->next_ =0;
160 if (bar_engraver_l)
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_;
168 volta_span_p_ =0;
171 if (t != "stop")
172 bar_engraver_l->request_bar (t);
173 else
174 bar_engraver_l->request_bar ("");
176 else
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.
190 else
192 warning (_ ("No bar engraver found. Ignoring repeats."));
195 delete head->car_;
196 delete head;
198 head = create_barmoments_queue_;
201 assert (!head || head->car_->when_ > now_mom ());
205 void
206 Repeat_engraver::acknowledge_element (Score_element_info i)
208 if (Note_column *c = dynamic_cast<Note_column *> (i.elem_l_))
210 if (volta_span_p_)
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_))
217 if (volta_span_p_)
218 volta_span_p_->add_bar (c);
219 if (end_volta_span_p_)
220 end_volta_span_p_ ->add_bar(c);
225 void
226 Repeat_engraver::do_removal_processing ()
228 if (volta_span_p_)
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_
239 void
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;
251 void
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;
267 volta_span_p_ =0;
268 done_this_one_b_ = false;
269 create_barmoments_queue_ =0;
272 /* ************** */
273 Bar_create_event::Bar_create_event()
275 last_b_ =false;
276 bar_b_ = true;
279 Bar_create_event::Bar_create_event (Moment w, String s)
281 last_b_ =false;
282 when_ = w;
283 type_ = s;
284 bar_b_ = true;
287 Bar_create_event::Bar_create_event (Moment w, int i, int j)
289 last_b_ =false;
290 when_ = w ;
291 bar_b_ = false;
293 if (i!=j)
294 type_ = to_str (i) + ".-" ;
296 type_ += to_str(j) + ".";