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>
12 #include "bar-engraver.hh"
13 #include "musical-request.hh"
14 #include "multi-measure-rest.hh"
15 #include "command-request.hh"
16 #include "timing-translator.hh"
17 #include "engraver-group-engraver.hh"
18 #include "repeated-music.hh"
19 #include "timing-translator.hh"
20 #include "volta-spanner.hh"
21 #include "note-column.hh"
22 #include "paper-def.hh"
23 #include "music-list.hh"
24 #include "side-position-interface.hh"
26 struct Bar_create_event
33 Bar_create_event (Moment w, String s);
34 Bar_create_event (Moment w, int i, int j);
37 int compare (Bar_create_event const & c1, Bar_create_event const &c2)
39 return (c1.when_ - c2.when_).sign();
43 Generate repeat-bars |: :| for repeated-music
45 class Repeat_engraver : public Engraver
48 VIRTUAL_COPY_CONS(Translator);
51 virtual void acknowledge_element (Score_element_info i);
52 virtual void do_removal_processing ();
53 virtual bool do_try_music (Music *req_l);
54 virtual void do_process_music();
55 virtual void do_pre_move_processing();
56 virtual void do_post_move_processing ();
60 Repeated_music *repeated_music_l_;
61 bool done_this_one_b_;
64 Royal_brackla_create_queue is only two Whiskies away. :-)
66 Cons<Bar_create_event> *create_barmoments_queue_;
68 Spanner * volta_span_p_;
69 Spanner* end_volta_span_p_;
75 ADD_THIS_TRANSLATOR (Repeat_engraver);
78 Repeat_engraver::do_try_music (Music* m)
80 if (Repeated_music* r = dynamic_cast<Repeated_music *> (m))
82 if (repeated_music_l_)
87 repeated_music_l_ = r;
91 We acknowledge other types of unfolded music as well, to
92 get auto context selection right.
94 if (r->type_ == "volta" || r->type_ == "unfolded")
102 Walk through repeat music, and generate events for appropriate times.
104 UGH. Should use Music_iteration for this.
106 Should also queue some event to get timing information reset during
107 2nd and following voltas.
110 Repeat_engraver::queue_events ()
112 Music_sequence* alt = repeated_music_l_->alternatives_p_;
113 Moment walk_mom = now_mom () + repeated_music_l_->repeat_body_p_->length_mom ();
115 SCM novolta = get_property ("noVoltaBraces");
116 bool create_volta = !to_boolean (novolta);
118 Cons_list<Bar_create_event> becel;
119 becel.append (new Bar_create_event (now_mom (), "|:"));
123 becel.append (new Bar_create_event (walk_mom, ":|"));
124 becel.append (new Bar_create_event (walk_mom, "stop"));
129 int volta_number = repeated_music_l_->repeats_i_ - alt->length_i () + 1;
132 all repeat alternatives, and generate events with
133 appropriate timestamps. The volta spanner event (a number string)
134 happens at the begin of the alt. The :| bar event at the ending.
136 for (Cons<Music> *i = alt->music_p_list_p_->head_; i; i = i->next_)
140 some idiot might typeset a repeat not starting on a
141 barline. Make sure there is one.
143 (todo: should try to avoid line breaks?)
145 if (last_number == 0)
147 becel.append (new Bar_create_event (walk_mom, ""));
153 Bar_create_event * c = new Bar_create_event (walk_mom, last_number+ 1,
160 last_number = volta_number;
162 SCM l (get_property ("voltaSpannerDuration"));
163 if (SMOB_IS_TYPE_B (Moment, l))
165 Moment vSD_mom = *SMOB_TO_TYPE (Moment,l);
166 if ( vSD_mom < i->car_->length_mom() ) // terminate volta early ?
170 becel.append (new Bar_create_event (vSD_mom, "stop"));
174 walk_mom += i->car_->length_mom();
177 becel.append (new Bar_create_event (walk_mom, ":|"));
179 becel.append (new Bar_create_event (walk_mom, "stop"));
183 Cons<Bar_create_event> *&tail = create_barmoments_queue_
184 ? last_cons (create_barmoments_queue_)->next_
185 : create_barmoments_queue_;
192 Repeat_engraver::do_process_music ()
194 if (repeated_music_l_ && !done_this_one_b_)
197 done_this_one_b_ = true;
201 Cons<Bar_create_event> * head = create_barmoments_queue_;
205 Bar_engraver* bar_engraver_l = dynamic_cast <Bar_engraver*>
206 (daddy_grav_l ()->get_simple_translator ("Bar_engraver"));
209 Do all the events that need to be done now.
211 while (head && now_mom () == head->car_->when_)
213 create_barmoments_queue_ = create_barmoments_queue_->next_;
217 String t = head->car_->type_;
218 if (head->car_->bar_b_)
220 if (t == "stop" || t == ":|")
222 end_volta_span_p_ = volta_span_p_;
227 bar_engraver_l->request_bar (t);
229 bar_engraver_l->request_bar ("");
233 assert (!volta_span_p_);
234 volta_span_p_ = new Spanner (get_property ("basicVoltaSpannerProperties"));
235 Volta_spanner::set_interface (volta_span_p_);
236 announce_element (Score_element_info (volta_span_p_,0));
237 volta_span_p_->set_elt_property ("text",
238 ly_str02scm (t.ch_C()));
239 volta_span_p_->set_elt_property ("last-volta",
240 gh_bool2scm (head->car_->last_b_));
241 // voltaSpannerDuration stuff here.
242 // other property stuff here.
248 warning (_ ("No bar engraver found. Ignoring repeats."));
254 head = create_barmoments_queue_;
257 assert (!head || head->car_->when_ > now_mom ());
262 Repeat_engraver::acknowledge_element (Score_element_info i)
264 if (Note_column *c = dynamic_cast<Note_column *> (i.elem_l_))
267 Volta_spanner::add_column (volta_span_p_,c);
268 if (end_volta_span_p_)
269 Volta_spanner::add_column (end_volta_span_p_,c);
271 if (Bar *c = dynamic_cast<Bar*> (i.elem_l_))
274 Volta_spanner::add_bar (volta_span_p_,c);
275 if (end_volta_span_p_)
276 Volta_spanner::add_bar(end_volta_span_p_ , c);
282 Repeat_engraver::do_removal_processing ()
286 typeset_element(volta_span_p_);
288 if (end_volta_span_p_)
290 typeset_element (end_volta_span_p_);
292 // todo: the paranoid may also delete create_barmoments_queue_
296 Repeat_engraver::do_post_move_processing ()
298 for (Cons<Bar_create_event> *p = create_barmoments_queue_;
299 p && p->car_->when_ == now_mom (); p = p->next_)
300 if (p->car_->type_ == "stop")
302 repeated_music_l_ = 0;
303 done_this_one_b_ = false;
308 Repeat_engraver::do_pre_move_processing ()
310 if (end_volta_span_p_)
312 Side_position_interface (end_volta_span_p_).add_staff_support ();
314 typeset_element (end_volta_span_p_ );
315 end_volta_span_p_ =0;
321 Repeat_engraver::Repeat_engraver()
323 repeated_music_l_ =0;
324 end_volta_span_p_ =0;
326 done_this_one_b_ = false;
327 create_barmoments_queue_ =0;
331 Bar_create_event::Bar_create_event()
337 Bar_create_event::Bar_create_event (Moment w, String s)
345 Bar_create_event::Bar_create_event (Moment w, int i, int j)
352 type_ = to_str (i) + ".-" ;
354 type_ += to_str(j) + ".";