X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Frepeat-engraver.cc;h=b389d92ee5ae258fe7c0ba4943af54039cb5d262;hb=9bc467a994787949def91708bf3bd50d088db982;hp=a28a3caedc08c44c1ed4cf5545a0fb99d70258f2;hpb=3f7d85a05bd1504266c0dc03c0b3eb5462d878df;p=lilypond.git diff --git a/lily/repeat-engraver.cc b/lily/repeat-engraver.cc index a28a3caedc..b389d92ee5 100644 --- a/lily/repeat-engraver.cc +++ b/lily/repeat-engraver.cc @@ -3,193 +3,291 @@ source file of the GNU LilyPond music typesetter - (c) 1998 Jan Nieuwenhuizen + (c) 1998--1999 Jan Nieuwenhuizen */ #include "repeat-engraver.hh" #include "bar.hh" +#include "bar-engraver.hh" #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").to_bool (); - if (r->unfold_b_) - return true; - - Moment stop_mom = now_moment () + r->repeat_p_->duration () - + r->alternative_p_->music_p_list_p_->top ()->duration (); - Moment alt_mom = now_moment () + r->repeat_p_->duration (); - /* - TODO: - figure out what we don't want. - - we don't want to print more than one set of - |: :| and volta brackets on one staff. + if (repeated_music_l_) + return false; + + if (r->volta_fold_b_) + { + repeated_music_l_ = r; + } - counting nested repeats, it seems safest to forbid - two pieces of alternative music to start at the same time. + /* + We acknowledge other types of unfolded music as well, to + get auto context selection right. */ - for (int i = 0; i < alternative_start_mom_arr_.size (); i++) - if (alternative_start_mom_arr_[i] == alt_mom) - return false; - repeated_music_arr_.push (r); - stop_mom_arr_.push (stop_mom); - for (PCursor i (r->alternative_p_->music_p_list_p_->top ()); i.ok (); i++) - { - alternative_music_arr_.push (i.ptr ()); - alternative_start_mom_arr_.push (alt_mom); - alt_mom += i->duration (); - alternative_stop_mom_arr_.push (alt_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_moment (); - 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 ((now >= alternative_start_mom_arr_[i]) && volta_p_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 ((now >= alternative_start_mom_arr_[i]) && volta_p_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 < bar_p_arr_.size (); i++) - if (bar_p_arr_[i]) - typeset_element (bar_p_arr_[i]); - 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_moment (); - for (int i = bar_p_arr_.size (); i < repeated_music_arr_.size (); i++) - { - Bar* bar_p = new Bar; - bar_p-> type_str_ = "|:"; - bar_p_arr_.push (bar_p); - if (now > Moment (0)) - announce_element (Score_element_info (bar_p, repeated_music_arr_[i])); +{ + if (repeated_music_l_ && !done_this_one_b_) + { + queue_events (); + done_this_one_b_ = true; } -#if 0 //urg, try pre-ceating and announcing - for (int i = 0; i < bar_p_arr_.size (); i++) + + + Cons * head = create_barmoments_queue_; + if (!head) + return; + + Bar_engraver* bar_engraver_l = dynamic_cast + (daddy_grav_l ()->get_simple_translator ("Bar_engraver")); + + /* + Do all the events that need to be done now. + */ + while (head && now_mom () == head->car_->when_) { - if (!bar_p_arr_[i] && (now >= stop_mom_arr_[i])) - { - Bar* bar_p = new Bar; - bar_p-> type_str_ = ":|"; - bar_p_arr_[i] = bar_p; - announce_element (Score_element_info (bar_p, repeated_music_arr_[i])); + create_barmoments_queue_ = create_barmoments_queue_->next_; + head->next_ =0; + if (bar_engraver_l) + { + 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_; } -#endif - int bees = volta_p_arr_.size (); - for (int i = volta_p_arr_.size (); i < alternative_music_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 (volta_span_p_) + volta_span_p_->add_column (c); + if (end_volta_span_p_) + end_volta_span_p_->add_column (c); + } + if (Bar *c = dynamic_cast (i.elem_l_)) { - Volta_spanner* v = new Volta_spanner; - if (i == alternative_music_arr_.size () - 1) - v->last_b_ = true; - Text_def* t = new Text_def; - t->text_str_ = to_str (i - bees + 1); - 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_moment (); - for (int i = bar_p_arr_.size (); i--; ) + if (volta_span_p_) { - if (bar_p_arr_[i]) - { - if (now > Moment (0)) - typeset_element (bar_p_arr_[i]); - else - delete bar_p_arr_[i]; - bar_p_arr_[i] = 0; - } + typeset_element(volta_span_p_); } - for (int i = volta_p_arr_.size (); i--; ) + if (end_volta_span_p_) { - if (now >= alternative_stop_mom_arr_[i]) - { - if (volta_p_arr_[i]) - { - typeset_element (volta_p_arr_[i]); - volta_p_arr_[i] = 0; - } - } + typeset_element (end_volta_span_p_); } + // todo: the paranoid may also delete create_barmoments_queue_ } -void +void Repeat_engraver::do_post_move_processing () { - Moment now = now_moment (); - for (int i = bar_p_arr_.size (); i--; ) + 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_) { -#if 0 // urg, try with pre-created and annouced :| - if (now >= stop_mom_arr_[i]) - { - if (bar_p_arr_[i]) - { - typeset_element (bar_p_arr_[i]); - bar_p_arr_.del (i); - stop_mom_arr_.del (i); - repeated_music_arr_.del (i); - } - else - { - bar_p_arr_.del (i); - } - } -#else - if (now >= stop_mom_arr_[i]) - { - Bar* bar_p = new Bar; - bar_p-> type_str_ = ":|"; - typeset_element (bar_p); - bar_p_arr_.del (i); - stop_mom_arr_.del (i); - repeated_music_arr_.del (i); - } -#endif + 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) + "."; +}