X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Frepeat-engraver.cc;h=b389d92ee5ae258fe7c0ba4943af54039cb5d262;hb=9bc467a994787949def91708bf3bd50d088db982;hp=59f2176b46133a05a8a4caf711dffdcb060c6097;hpb=44d3318feb59f81439c0edc5116ae61fe407c226;p=lilypond.git diff --git a/lily/repeat-engraver.cc b/lily/repeat-engraver.cc index 59f2176b46..b389d92ee5 100644 --- a/lily/repeat-engraver.cc +++ b/lily/repeat-engraver.cc @@ -3,7 +3,7 @@ source file of the GNU LilyPond music typesetter - (c) 1998 Jan Nieuwenhuizen + (c) 1998--1999 Jan Nieuwenhuizen */ #include "repeat-engraver.hh" @@ -12,179 +12,282 @@ #include "musical-request.hh" #include "multi-measure-rest.hh" #include "command-request.hh" -#include "time-description.hh" -#include "engraver-group.hh" +#include "timing-translator.hh" +#include "engraver-group-engraver.hh" #include "repeated-music.hh" -#include "time-description.hh" +#include "timing-translator.hh" #include "volta-spanner.hh" #include "note-column.hh" #include "paper-def.hh" +#include "music-list.hh" ADD_THIS_TRANSLATOR (Repeat_engraver); -Repeat_engraver::Repeat_engraver () -{ -} - bool Repeat_engraver::do_try_music (Music* m) { if (Repeated_music* r = dynamic_cast (m)) { - r->unfold_b_ = get_property ("unfoldRepeats", 0).to_bool (); - if (r->unfold_b_) - return true; - - Music_sequence* alt = r->alternative_p_; - Moment repeat_length_mom = r->repeat_p_->length_mom (); - Moment stop_mom = now_mom () + repeat_length_mom; - Moment alt_mom = now_mom () + repeat_length_mom; - if (repeat_length_mom) + if (repeated_music_l_) + return false; + + if (r->volta_fold_b_) { - for (PCursor i (alt->music_p_list_p_->top ()); i.ok () && (i != alt->music_p_list_p_->bottom ()); i++) - { - stop_mom += i->length_mom (); - if (dynamic_cast (alt)) - break; - } - repeated_music_arr_.push (r); - stop_mom_arr_.push (stop_mom); + repeated_music_l_ = r; } - /* - Counting nested repeats, it seems safest to forbid - two pieces of alternative music to start at the same time. - */ - for (int i = 0; i < alternative_start_mom_arr_.size (); i++) - if (alternative_start_mom_arr_[i] == alt_mom) - return false; - /* - Coda kludge: see input/test/coda-kludge.ly + We acknowledge other types of unfolded music as well, to + get auto context selection right. */ - Moment span_mom; - Scalar prop = get_property ("voltaSpannerDuration", 0); - if (prop.length_i ()) - span_mom = prop.to_rat (); - int alt_i = r->repeats_i_ + 1 - alt->music_p_list_p_->size () >? 1; - for (PCursor i (alt->music_p_list_p_->top ()); i.ok (); i++) - { - alternative_music_arr_.push (i.ptr ()); - alternative_start_mom_arr_.push (alt_mom); - if (span_mom) - alternative_stop_mom_arr_.push (alt_mom + span_mom); - else - alternative_stop_mom_arr_.push (alt_mom + i->length_mom ()); - String str; - if ((alt_i != 1) && (alt_i != r->repeats_i_) && (i == alt->music_p_list_p_->top ())) - str = "1.-"; - str += to_str (alt_i) + "."; - alt_i++; - alternative_str_arr_.push (str); - if (!dynamic_cast (alt)) - alt_mom += i->length_mom (); - } return true; + } return false; } +/** + Walk through repeat music, and generate events for appropriate times. +*/ void -Repeat_engraver::acknowledge_element (Score_element_info i) +Repeat_engraver::queue_events () { - Moment now = now_mom (); - if (Note_column *c = dynamic_cast (i.elem_l_)) + Music_sequence* alt = repeated_music_l_->alternatives_p_; + Moment walk_mom = now_mom () + repeated_music_l_->repeat_body_p_->length_mom (); + + SCM novolta = get_property ("noVoltaBraces",0); + bool create_volta = gh_boolean_p (novolta) && !gh_scm2bool (novolta); + + Cons_list becel; + becel.append (new Bar_create_event (now_mom (), "|:")); + + if (!alt) { - for (int i = 0; i < volta_p_arr_.size (); i++) - if (volta_p_arr_[i] && (now >= alternative_start_mom_arr_[i])) - volta_p_arr_[i]->add_column (c); - } - if (Bar *c = dynamic_cast (i.elem_l_)) + becel.append (new Bar_create_event (walk_mom, ":|")); + becel.append (new Bar_create_event (walk_mom, "stop")); + } + else { - for (int i = 0; i < volta_p_arr_.size (); i++) - if (volta_p_arr_[i] && (now >= alternative_start_mom_arr_[i])) - volta_p_arr_[i]->add_column (c); + int last_number = 0; + int volta_number = repeated_music_l_->repeats_i_ - alt->length_i () + 1; + + /* + all repeat alternatives, and generate events with + appropriate timestamps. The volta spanner event (a number string) + happens at the begin of the alt. The :| bar event at the ending. + */ + for (Cons *i = alt->music_p_list_p_->head_; i; i = i->next_) + { + + /* + some idiot might typeset a repeat not starting on a + barline. Make sure there is one. + + (todo: should try to avoid line breaks?) + */ + if (last_number == 0) + { + becel.append (new Bar_create_event (walk_mom, "")); + } + + + if (create_volta) + { + Bar_create_event * c = new Bar_create_event (walk_mom, last_number+ 1, + volta_number); + + if (!i->next_) + c->last_b_ = true; + + becel.append (c); + last_number = volta_number; + volta_number ++; + SCM l (get_property ("voltaSpannerDuration", 0)); + if (SMOB_IS_TYPE_B (Moment, l)) + { + Moment vSD_mom = *SMOB_TO_TYPE (Moment,l); + if ( vSD_mom < i->car_->length_mom() ) // terminate volta early ? + { + vSD_mom += walk_mom; + c->last_b_ = true; + becel.append (new Bar_create_event (vSD_mom, "stop")); + } + } + } + walk_mom += i->car_->length_mom(); + + if (i->next_) + becel.append (new Bar_create_event (walk_mom, ":|")); + else + becel.append (new Bar_create_event (walk_mom, "stop")); + } } -} -void -Repeat_engraver::do_removal_processing () -{ - for (int i = 0; i < volta_p_arr_.size (); i++) - if (volta_p_arr_[i]) - typeset_element (volta_p_arr_[i]); + Cons *&tail = create_barmoments_queue_ + ? last_cons (create_barmoments_queue_)->next_ + : create_barmoments_queue_; + + tail = becel.head_ ; + becel.head_ = 0; } void Repeat_engraver::do_process_requests () -{ - Moment now = now_mom (); +{ + if (repeated_music_l_ && !done_this_one_b_) + { + queue_events (); + done_this_one_b_ = true; + } + + + Cons * head = create_barmoments_queue_; + if (!head) + return; + Bar_engraver* bar_engraver_l = dynamic_cast (daddy_grav_l ()->get_simple_translator ("Bar_engraver")); - for (int i = bar_b_arr_.size (); i < repeated_music_arr_.size (); i++) + + /* + Do all the events that need to be done now. + */ + while (head && now_mom () == head->car_->when_) { + create_barmoments_queue_ = create_barmoments_queue_->next_; + head->next_ =0; if (bar_engraver_l) - bar_engraver_l->request_bar ("|:"); - bar_b_arr_.push (true); + { + String t = head->car_->type_; + if (head->car_->bar_b_) + { + if (t == "stop" || t == ":|") + { + end_volta_span_p_ = volta_span_p_; + volta_span_p_ =0; + } + + if (t != "stop") + bar_engraver_l->request_bar (t); + else + bar_engraver_l->request_bar (""); + } + else + { + assert (!volta_span_p_); + volta_span_p_ = new Volta_spanner; + announce_element (Score_element_info (volta_span_p_,0)); + volta_span_p_->number_str_ = t; + volta_span_p_->last_b_ = head->car_->last_b_; + // voltaSpannerDuration stuff here. + // other property stuff here. + } + + } + else + { + warning (_ ("No bar engraver found. Ignoring repeats.")); + } + + delete head->car_; + delete head; + + head = create_barmoments_queue_; } - for (int i = 0; i < bar_b_arr_.size (); i++) + + assert (!head || head->car_->when_ > now_mom ()); +} + + +void +Repeat_engraver::acknowledge_element (Score_element_info i) +{ + if (Note_column *c = dynamic_cast (i.elem_l_)) { - if (!bar_b_arr_[i] && (now >= stop_mom_arr_[i])) - { - if (bar_engraver_l) - bar_engraver_l->request_bar (":|"); - } + if (volta_span_p_) + volta_span_p_->add_column (c); + if (end_volta_span_p_) + end_volta_span_p_->add_column (c); } - for (int i = volta_p_arr_.size (); i < alternative_music_arr_.size (); i++) + if (Bar *c = dynamic_cast (i.elem_l_)) { - Volta_spanner* v = new Volta_spanner; - Scalar prop = get_property ("voltaVisibility", 0); - v->visible_b_ = prop.to_bool (); - prop = get_property ("voltaSpannerDuration", 0); - if ((i == alternative_music_arr_.size () - 1) || prop.length_i ()) - v->last_b_ = true; - Text_def* t = new Text_def; - t->text_str_ = alternative_str_arr_[i]; - v->number_p_.set_p (t); - volta_p_arr_.push (v); - announce_element (Score_element_info (v, alternative_music_arr_[i])); + if (volta_span_p_) + volta_span_p_->add_bar (c); + if (end_volta_span_p_) + end_volta_span_p_ ->add_bar(c); } } -void -Repeat_engraver::do_pre_move_processing () + +void +Repeat_engraver::do_removal_processing () { - Moment now = now_mom (); - for (int i = bar_b_arr_.size (); i--; ) + if (volta_span_p_) { - if (bar_b_arr_[i]) - bar_b_arr_[i] = false; - if (now >= stop_mom_arr_[i]) - { - bar_b_arr_.del (i); - stop_mom_arr_.del (i); - repeated_music_arr_.del (i); - } + typeset_element(volta_span_p_); } - for (int i = volta_p_arr_.size (); i--; ) + if (end_volta_span_p_) { - if (volta_p_arr_[i] && (now >= alternative_stop_mom_arr_[i]) - && (volta_p_arr_[i]->column_arr_.size () >= 1)) - { - typeset_element (volta_p_arr_[i]); - volta_p_arr_[i] = 0; - volta_p_arr_.del (i); - alternative_music_arr_[i] = 0; - alternative_music_arr_.del (i); - alternative_start_mom_arr_.del (i); - alternative_stop_mom_arr_.del (i); - alternative_str_arr_.del (i); - } + typeset_element (end_volta_span_p_); } + // todo: the paranoid may also delete create_barmoments_queue_ } -void +void Repeat_engraver::do_post_move_processing () { + for (Cons *p = create_barmoments_queue_; + p && p->car_->when_ == now_mom (); p = p->next_) + if (p->car_->type_ == "stop") + { + repeated_music_l_ = 0; + done_this_one_b_ = false; + } +} + +void +Repeat_engraver::do_pre_move_processing () +{ + if (end_volta_span_p_) + { + typeset_element (end_volta_span_p_ ); + end_volta_span_p_ =0; + } + } + +Repeat_engraver::Repeat_engraver() +{ + repeated_music_l_ =0; + end_volta_span_p_ =0; + volta_span_p_ =0; + done_this_one_b_ = false; + create_barmoments_queue_ =0; +} + +/* ************** */ +Bar_create_event::Bar_create_event() +{ + last_b_ =false; + bar_b_ = true; +} + +Bar_create_event::Bar_create_event (Moment w, String s) +{ + last_b_ =false; + when_ = w; + type_ = s; + bar_b_ = true; +} + +Bar_create_event::Bar_create_event (Moment w, int i, int j) +{ + last_b_ =false; + when_ = w ; + bar_b_ = false; + + if (i!=j) + type_ = to_str (i) + ".-" ; + + type_ += to_str(j) + "."; +}