From: Han-Wen Nienhuys Date: Thu, 11 Jul 2002 23:07:09 +0000 (+0000) Subject: * input/regression/grace-auto-beam.ly: new file X-Git-Tag: release/1.5.67~10 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=42e20e7c10237378b290cc9d8bcae7a6fda7b076;p=lilypond.git * input/regression/grace-auto-beam.ly: new file * input/regression/grace-unfold-repeat.ly: new file * lily/auto-beam-engraver.cc (test_moment): never start on grace moments. * lily/forbid-break-engraver.cc (start_translation_timestep): skip grace notes for break-forbidding. Breaks during grace notes are handled by Bar_engraver. * lily/unfolded-repeat-iterator.cc: Reimplement Unfolded_repeat_iterator, Volta_repeat_iterator using Sequential_iterator. All grace functionality from {} carries over to repeats as well. * lily/sequential-iterator.cc: new file: form baseclass for sequential music iterator and unfolded/volta repeat iterator. --- diff --git a/ChangeLog b/ChangeLog index 1cab6d4e8a..566160ab81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2002-07-12 Han-Wen + + * input/regression/grace-auto-beam.ly: new file + + * input/regression/grace-unfold-repeat.ly: new file + + * lily/auto-beam-engraver.cc (test_moment): never start on grace moments. + + * lily/forbid-break-engraver.cc (start_translation_timestep): skip + grace notes for break-forbidding. Breaks during grace notes are + handled by Bar_engraver. + + * lily/unfolded-repeat-iterator.cc: Reimplement + Unfolded_repeat_iterator, Volta_repeat_iterator using + Sequential_iterator. All grace functionality from {} carries over + to repeats as well. + + * lily/sequential-iterator.cc: new file: form baseclass for + sequential music iterator and unfolded/volta repeat iterator. + 2002-07-11 Han-Wen Nienhuys * lily/include/debug.hh: deprecate. diff --git a/Documentation/regression-test.tely b/Documentation/regression-test.tely index f469c28c17..b140bdf65f 100644 --- a/Documentation/regression-test.tely +++ b/Documentation/regression-test.tely @@ -145,6 +145,10 @@ Grace note do weird things with timing. Fragile. @lilypondfile[printfilename]{grace-bar-number.ly} +@lilypondfile[printfilename]{grace-auto-beam.ly} + +@lilypondfile[printfilename]{grace-unfold-repeat.ly} + @section Beams diff --git a/input/regression/grace-auto-beam.ly b/input/regression/grace-auto-beam.ly new file mode 100644 index 0000000000..53deb7e5bc --- /dev/null +++ b/input/regression/grace-auto-beam.ly @@ -0,0 +1,12 @@ +\header +{ + texidoc = "The autobeamer is not confusde by grace notes." +} + +\score{ + \notes\context Voice \relative c'{ + + \grace a8 g16 f e f \grace a8 g16 f e f \grace a8 g16 f e f + \grace a8 g16 f e f | + } +} diff --git a/input/regression/grace-unfold-repeat.ly b/input/regression/grace-unfold-repeat.ly new file mode 100644 index 0000000000..9b580ceb31 --- /dev/null +++ b/input/regression/grace-unfold-repeat.ly @@ -0,0 +1,15 @@ +\header { + texidoc = "Grace notes and unfolded repeats. +Line breaks may happen before grace notes. +" +} + + +\score{ + \notes\context Voice \relative c'{ + + % Bug 2: What happens with the grace notes here? + \repeat unfold 10 {\grace d8 c4 d e f} + + } +} diff --git a/lily/auto-beam-engraver.cc b/lily/auto-beam-engraver.cc index 15e931c7cb..14e9604996 100644 --- a/lily/auto-beam-engraver.cc +++ b/lily/auto-beam-engraver.cc @@ -109,6 +109,13 @@ Auto_beam_engraver::Auto_beam_engraver () bool Auto_beam_engraver::test_moment (Direction dir, Moment test_mom) { + Moment now = now_mom(); + if (dir == START + && now.grace_part_) + { + return false; + } + SCM wild = scm_list_n (ly_symbol2scm ("*"), ly_symbol2scm ("*"), SCM_UNDEFINED); SCM function; if (dir == START) @@ -186,6 +193,7 @@ Auto_beam_engraver::test_moment (Direction dir, Moment test_mom) /* but ending is not */ r = 1; } + return !r; } diff --git a/lily/break-algorithm.cc b/lily/break-algorithm.cc index 7dd25936c3..249dcec8fb 100644 --- a/lily/break-algorithm.cc +++ b/lily/break-algorithm.cc @@ -9,7 +9,6 @@ #include "paper-column.hh" #include "break-algorithm.hh" #include "paper-def.hh" -#include "debug.hh" #include "system.hh" #include "paper-score.hh" #include "paper-column.hh" diff --git a/lily/forbid-break-engraver.cc b/lily/forbid-break-engraver.cc index 0ece1306c5..3df1cdc640 100644 --- a/lily/forbid-break-engraver.cc +++ b/lily/forbid-break-engraver.cc @@ -29,7 +29,7 @@ Forbid_line_break_engraver::start_translation_timestep() SCM busy = get_property ("busyGrobs"); Moment now = now_mom(); - while (gh_pair_p (busy) && *unsmob_moment (gh_caar (busy)) == now) + while (gh_pair_p (busy) && unsmob_moment (gh_caar (busy))->main_part_ == now.main_part_) busy = gh_cdr (busy); diff --git a/lily/grob-property.cc b/lily/grob-property.cc index c03e311936..d4a0272734 100644 --- a/lily/grob-property.cc +++ b/lily/grob-property.cc @@ -13,7 +13,7 @@ #include "paper-score.hh" #include "paper-def.hh" #include "grob.hh" -#include "debug.hh" + #include "spanner.hh" #include "item.hh" #include "misc.hh" diff --git a/lily/grob.cc b/lily/grob.cc index 6caceb624a..ff3130c57f 100644 --- a/lily/grob.cc +++ b/lily/grob.cc @@ -12,21 +12,17 @@ #include "main.hh" #include "input-smob.hh" - +#include "warn.hh" #include "group-interface.hh" #include "misc.hh" #include "paper-score.hh" -#include "paper-def.hh" #include "molecule.hh" #include "grob.hh" -#include "debug.hh" #include "spanner.hh" #include "system.hh" #include "item.hh" -#include "paper-column.hh" #include "molecule.hh" #include "misc.hh" -#include "paper-outputter.hh" #include "music.hh" #include "item.hh" diff --git a/lily/include/sequential-iterator.hh b/lily/include/sequential-iterator.hh new file mode 100644 index 0000000000..d56d8ad0a6 --- /dev/null +++ b/lily/include/sequential-iterator.hh @@ -0,0 +1,81 @@ +/* + sequential-iterator.hh -- declare Sequential_iterator + + source file of the GNU LilyPond music typesetter + + (c) 2002 Han-Wen Nienhuys +*/ + +#ifndef SEQUENTIAL_ITERATOR_HH +#define SEQUENTIAL_ITERATOR_HH + +#include "music-iterator.hh" + +/* + + This is a lookahead list for grace notes. + + { ... X \grace Y Z ... } + + normally, the ending of X is the start of Z. In case of a grace + note, we take off a little at the end of X. What is stored: START + (start point of X), LENGTH (length of X), GRACE_START (start_music + of Y), and the next fixup element. + + This is also done for nested musics, i.e. + + voiceA = \notes { \grace b16 c'2 } + voiceB = \notes { c'2 \voiceA } + + the iterator for voiceB will contain a fixup entry with (START=0/1, + LENGTH=2/1, GRACE_START=(0G-1/16) ) + + Graces at the start of a sequential music iterator are handled + by initting here_mom_ with Music::start_music (); no fixups are needed. + +*/ +struct Grace_fixup +{ + Moment start_; + Moment length_; + + Rational grace_start_; + Grace_fixup *next_; +}; + +/** Sequential_music iteration: walk each element in turn, and + construct an iterator for every element. + + */ +class Sequential_iterator : public Music_iterator +{ +public: + Grace_fixup * grace_fixups_; + + VIRTUAL_COPY_CONS (Music_iterator); + static SCM constructor_cxx_function; + Sequential_iterator (); + Sequential_iterator (Sequential_iterator const&); + virtual ~Sequential_iterator (); + + virtual void construct_children (); + virtual Moment pending_moment () const; + virtual bool ok () const; + virtual void skip (Moment); + virtual SCM get_music (Moment)const; + +protected: + virtual void process (Moment); + virtual Music_iterator *try_music_in_children (Music *) const; + +protected: + Moment here_mom_; + Music_iterator * iter_p_; + SCM cursor_; + + virtual void next_element (bool side_effect); + virtual void descend_to_child (); + virtual SCM get_music_list ()const; +}; + +#endif /* SEQUENTIAL_ITERATOR_HH */ diff --git a/lily/include/sequential-music-iterator.hh b/lily/include/sequential-music-iterator.hh index 62a251e22f..31d4220927 100644 --- a/lily/include/sequential-music-iterator.hh +++ b/lily/include/sequential-music-iterator.hh @@ -9,73 +9,20 @@ #ifndef SEQUENTIAL_MUSIC_ITERATOR_HH #define SEQUENTIAL_MUSIC_ITERATOR_HH -#include "music-iterator.hh" - - -/* - - This is a lookahead list for grace notes. - - { ... X \grace Y Z ... } - - normally, the ending of X is the start of Z. In case of a grace - note, we take off a little at the end of X. What is stored: START - (start point of X), LENGTH (length of X), GRACE_START (start_music - of Y), and the next fixup element. - - This is also done for nested musics, i.e. - - voiceA = \notes { \grace b16 c'2 } - voiceB = \notes { c'2 \voiceA } - - the iterator for voiceB will contain a fixup entry with (START=0/1, - LENGTH=2/1, GRACE_START=(0G-1/16) ) - - Graces at the start of a sequential music iterator are handled - by initting here_mom_ with Music::start_music (); no fixups are needed. - -*/ -struct Grace_fixup -{ - Moment start_; - Moment length_; - - Rational grace_start_; - Grace_fixup *next_; -}; +#include "sequential-iterator.hh" /** Sequential_music iteration: walk each element in turn, and construct an iterator for every element. */ -class Sequential_music_iterator : public Music_iterator +class Sequential_music_iterator : public Sequential_iterator { public: - Grace_fixup * grace_fixups_; - VIRTUAL_COPY_CONS (Music_iterator); static SCM constructor_cxx_function; - Sequential_music_iterator (); - Sequential_music_iterator (Sequential_music_iterator const&); - virtual ~Sequential_music_iterator (); - - virtual void construct_children (); - virtual Moment pending_moment () const; - virtual bool ok () const; - virtual void skip (Moment); - virtual SCM get_music (Moment)const; - -protected: - virtual void process (Moment); - virtual Music_iterator *try_music_in_children (Music *) const; - private: - Moment here_mom_; - SCM cursor_; - Music_iterator * iter_p_; - - void next_element (); - void descend_to_child (); + virtual SCM get_music_list()const; + virtual void descend_to_child (); }; #endif // SEQUENTIAL_MUSIC_ITERATOR_HH diff --git a/lily/paper-def.cc b/lily/paper-def.cc index f051844532..3bf736aeff 100644 --- a/lily/paper-def.cc +++ b/lily/paper-def.cc @@ -12,7 +12,7 @@ #include "string.hh" #include "misc.hh" #include "paper-def.hh" -#include "debug.hh" + #include "scaled-font-metric.hh" #include "main.hh" #include "scm-hash.hh" diff --git a/lily/sequential-iterator.cc b/lily/sequential-iterator.cc new file mode 100644 index 0000000000..3e5d8a5dd5 --- /dev/null +++ b/lily/sequential-iterator.cc @@ -0,0 +1,360 @@ +/* + Sequential_iterator.cc -- implement Sequential_iterator + + source file of the GNU LilyPond music typesetter + + (c) 1997--2002 Han-Wen Nienhuys +*/ + +#include "translator-group.hh" + +#include "sequential-iterator.hh" +#include "music-list.hh" + +Grace_fixup *copy_grace_fixups (Grace_fixup* src); +Grace_fixup *get_grace_fixups (SCM cursor); + +/* + + TODO: handling of grace notes is exquisite pain. This handling + should be formally specified and then the implementation verified. + +*/ + +/* + + TODO: the grace note handling hasn't been done for skip() and + get_music(), meaning that staff-switching and partcombining will be + broken with grace notes. + + */ +/* + + TODO: the grace note handling hasn't been done for skip() and + get_music(), meaning that staff-switching and partcombining will be + broken with grace notes. + + */ +/* + Invariant for the data structure. + + + if (gh_pair_p (cursor_)) + iter_p_->music_l_ == unsmob_music (ly_car (cursor_)) + else + iter_p_ == 0; + + The length of musiclist from start to up to cursor_ (cursor_ not + including), is summed + + here_mom_ = sum (length (musiclist [start ... cursor>)) %) + + */ +Sequential_iterator::Sequential_iterator () +{ + here_mom_ = Moment (0); + grace_fixups_ = 0; + iter_p_ =0; +} + +SCM +Sequential_iterator::get_music_list () const +{ + return SCM_EOL; +} + +Sequential_iterator::Sequential_iterator (Sequential_iterator const &src) + : Music_iterator (src) +{ + grace_fixups_ = copy_grace_fixups (src.grace_fixups_); + cursor_ = src.cursor_; + here_mom_ = src.here_mom_; + if (src.iter_p_) + iter_p_ = src.iter_p_->clone (); + else + iter_p_ = 0; +} + +Sequential_iterator::~Sequential_iterator () +{ + delete iter_p_; +} + + +Grace_fixup * +get_grace_fixups (SCM cursor) +{ + Moment here; + Moment last (-1); + Grace_fixup *head = 0; + Grace_fixup **tail = &head; + + for (; gh_pair_p (cursor); cursor = ly_cdr (cursor)) + { + Music * mus = unsmob_music (ly_car (cursor)); + Moment s = mus->start_mom (); + Moment l =mus->length_mom () - s; + + if (s.grace_part_) + { + if (last != Moment (-1)) + { + Grace_fixup *p =new Grace_fixup; + p->start_ = last; + p->length_ = here - last; + p->grace_start_ = s.grace_part_; + p->next_ = 0; + *tail = p; + tail = &(*tail)->next_; + } + + here.grace_part_ = s.grace_part_; + } + + if (l.to_bool()) + { + last = here; + here += l; + } + } + return head; +} + +Grace_fixup * +copy_grace_fixups (Grace_fixup* src) +{ + Grace_fixup * head = 0; + Grace_fixup **dest = &head; + + while (src) + { + *dest = new Grace_fixup (*src); + dest = & (*dest)->next_; + src = src ->next_; + } + + return head; +} + +void +Sequential_iterator::construct_children () +{ + cursor_ = get_music_list (); + + iter_p_ = gh_pair_p (cursor_) ? get_iterator_p (unsmob_music (ly_car (cursor_))) : 0; + while (iter_p_ && !iter_p_->ok ()) + { + next_element (true); + } + + here_mom_ = music_l ()->start_mom (); + grace_fixups_ = get_grace_fixups (cursor_); + + /* + iter_p_->ok () is tautology, but what the heck. + */ + if (iter_p_ && iter_p_->ok ()) + descend_to_child (); +} + + +/* + maintain invariants: change cursor, iter and here_mom_ in one fell + swoop. +*/ +void +Sequential_iterator::next_element (bool side_effect) +{ + Moment len =iter_p_->music_length_mom () - iter_p_->music_start_mom (); + assert (!grace_fixups_ || grace_fixups_->start_ >= here_mom_); + + if (len.main_part_ && grace_fixups_ && + grace_fixups_->start_ == here_mom_) + { + here_mom_ += grace_fixups_->length_; + here_mom_.grace_part_ += grace_fixups_->grace_start_; + + Grace_fixup * n =grace_fixups_->next_; + delete grace_fixups_; + grace_fixups_ = n; + } + else if (len.grace_part_ && !len.main_part_) + { + here_mom_.grace_part_ =0; + } + else + { + /* + !len.grace_part_ || len.main_part_ + + We skip over a big chunk (mainpart != 0). Any starting graces + in that chunk should be in len.grace_part_ + + */ + here_mom_ += len; + } + + delete iter_p_; + cursor_ = ly_cdr (cursor_); + + if (gh_pair_p (cursor_)) + iter_p_ = get_iterator_p (unsmob_music (ly_car (cursor_))); + else + iter_p_ = 0; +} + +/* + move to context of child iterator if it is deeper down in the + hierarchy. + */ +void +Sequential_iterator::descend_to_child () +{ +} + + +/* + Retrieve all music (starting at HERE), until a music with length L > + 0 is found. From the precondition, we know that UNTIL is later than + the earliest event. Hence we know + + L >= (UNTIL - HERE) + + so something that comes after this thing with L > 0 happens after + + HERE + L >= HERE + (UNTIL - HERE) = UNTIL + + Hence all events after the one with L>0 are uninteresting, so we + ignore them. + +*/ + +SCM +Sequential_iterator::get_music (Moment until)const +{ + SCM s = SCM_EOL; + if (until < pending_moment ()) + return s; + + Sequential_iterator * me = + dynamic_cast (clone ()); + while (me->ok ()) + { + SCM nm = me->iter_p_->get_music (until - me->here_mom_); + s = gh_append2 (nm, s); + + Moment m = 0; + for (SCM i = nm; gh_pair_p (i); i = ly_cdr (i)) + { + Music *mus=unsmob_music (ly_car (i)); + m = m >? (mus->length_mom () - mus->start_mom ()); + } + if (m > Moment (0)) + break ; + else + me->next_element (false); + } + delete me; + + return s; +} + + +/* + Skip events till UNTIL. We don't do any other side effects such as + descending to child iterator contexts, because they might depend on + \context specs and \translator changes being executed + + TODO: check support for grace notes here. + */ +void +Sequential_iterator::skip (Moment until) +{ + while (ok ()) + { + if (grace_fixups_ && + grace_fixups_->start_ == here_mom_ + && (grace_fixups_->start_ + grace_fixups_->length_ + + Moment (Rational (0), grace_fixups_->grace_start_) == until)) + { + /* + do the stuff/note/rest preceding a grace. + */ + iter_p_->skip (iter_p_->music_length_mom ()); + } + else if (iter_p_->music_length_mom () >= until - here_mom_) + iter_p_->skip (until - here_mom_ + iter_p_->music_start_mom ()); + + if (iter_p_->ok ()) + return ; + + next_element (false); + } +} + +void +Sequential_iterator::process (Moment until) +{ + while (iter_p_) + { + if (grace_fixups_ && + grace_fixups_->start_ == here_mom_ + && (grace_fixups_->start_ + grace_fixups_->length_ + + Moment (Rational (0), grace_fixups_->grace_start_) == until)) + { + /* + do the stuff/note/rest preceding a grace. + */ + iter_p_->process (iter_p_->music_length_mom ()); + } + else + iter_p_->process (until - here_mom_ + iter_p_->music_start_mom ()); + + /* + if the iter is still OK, there must be events left that have + + TIME > LEFT + + */ + if (iter_p_->ok ()) + return ; + + descend_to_child (); + next_element (true); + } +} + +Moment +Sequential_iterator::pending_moment () const +{ + Moment cp = iter_p_->pending_moment (); + + /* + Fix-up a grace note halfway in the music. + */ + if (grace_fixups_ && here_mom_ == grace_fixups_->start_ + && grace_fixups_->length_ + iter_p_->music_start_mom () == cp) + { + return here_mom_ + grace_fixups_->length_ + Moment (0, grace_fixups_->grace_start_); + } + + /* + Fix-up a grace note at the start of the music. + */ + return cp + here_mom_ - iter_p_->music_start_mom (); +} + + +bool +Sequential_iterator::ok () const +{ + return iter_p_; +} + +Music_iterator* +Sequential_iterator::try_music_in_children (Music *m) const +{ + return iter_p_ ? iter_p_->try_music (m) : 0; +} + +IMPLEMENT_CTOR_CALLBACK (Sequential_iterator); diff --git a/lily/sequential-music-iterator.cc b/lily/sequential-music-iterator.cc index 63f7e072f0..6de624e0eb 100644 --- a/lily/sequential-music-iterator.cc +++ b/lily/sequential-music-iterator.cc @@ -11,194 +11,6 @@ #include "sequential-music-iterator.hh" #include "music-list.hh" -Grace_fixup *copy_grace_fixups (Grace_fixup* src); -Grace_fixup *get_grace_fixups (SCM cursor); - -/* - - TODO: handling of grace notes is exquisite pain. This handling - should be formally specified and then the implementation verified. - -*/ - -/* - - TODO: the grace note handling hasn't been done for skip() and - get_music(), meaning that staff-switching and partcombining will be - broken with grace notes. - - */ -/* - - TODO: the grace note handling hasn't been done for skip() and - get_music(), meaning that staff-switching and partcombining will be - broken with grace notes. - - */ -/* - Invariant for the data structure. - - - if (gh_pair_p (cursor_)) - iter_p_->music_l_ == unsmob_music (ly_car (cursor_)) - else - iter_p_ == 0; - - The length of musiclist from start to up to cursor_ (cursor_ not - including), is summed - - here_mom_ = sum (length (musiclist [start ... cursor>)) %) - - */ -Sequential_music_iterator::Sequential_music_iterator () -{ - cursor_ = SCM_EOL; - here_mom_ = Moment (0); - grace_fixups_ = 0; - iter_p_ =0; -} - -Sequential_music_iterator::Sequential_music_iterator (Sequential_music_iterator const &src) - : Music_iterator (src) -{ - grace_fixups_ = copy_grace_fixups (src.grace_fixups_); - cursor_ = src.cursor_; - here_mom_ = src.here_mom_; - if (src.iter_p_) - iter_p_ = src.iter_p_->clone (); - else - iter_p_ = 0; -} - -Sequential_music_iterator::~Sequential_music_iterator () -{ - delete iter_p_; -} - - -Grace_fixup * -get_grace_fixups (SCM cursor) -{ - Moment here; - Moment last (-1); - Grace_fixup *head = 0; - Grace_fixup **tail = &head; - - for (; gh_pair_p (cursor); cursor = ly_cdr (cursor)) - { - Music * mus = unsmob_music (ly_car (cursor)); - Moment s = mus->start_mom (); - Moment l =mus->length_mom () - s; - - if (s.grace_part_) - { - if (last != Moment (-1)) - { - Grace_fixup *p =new Grace_fixup; - p->start_ = last; - p->length_ = here - last; - p->grace_start_ = s.grace_part_; - p->next_ = 0; - *tail = p; - tail = &(*tail)->next_; - } - - here.grace_part_ = s.grace_part_; - } - - if (l.to_bool()) - { - last = here; - here += l; - } - } - return head; -} - -Grace_fixup * -copy_grace_fixups (Grace_fixup* src) -{ - - Grace_fixup * head = 0; - Grace_fixup **dest = &head; - - while (src) - { - *dest = new Grace_fixup (*src); - dest = & (*dest)->next_; - src = src ->next_; - } - - return head; -} - -void -Sequential_music_iterator::construct_children () -{ - cursor_ = dynamic_cast (music_l ())->music_list (); - - iter_p_ = gh_pair_p (cursor_) ? get_iterator_p (unsmob_music (ly_car (cursor_))) : 0; - while (iter_p_ && !iter_p_->ok ()) - { - next_element (); - } - - here_mom_ = music_l ()->start_mom (); - grace_fixups_ = get_grace_fixups (cursor_); - - /* - iter_p_->ok () is tautology, but what the heck. - */ - if (iter_p_ && iter_p_->ok ()) - descend_to_child (); -} - - -/* - maintain invariants: change cursor, iter and here_mom_ in one fell - swoop. -*/ -void -Sequential_music_iterator::next_element () -{ - Moment len =iter_p_->music_length_mom () - iter_p_->music_start_mom (); - assert (!grace_fixups_ || grace_fixups_->start_ >= here_mom_); - - if (len.main_part_ && grace_fixups_ && - grace_fixups_->start_ == here_mom_) - { - here_mom_ += grace_fixups_->length_; - here_mom_.grace_part_ += grace_fixups_->grace_start_; - - Grace_fixup * n =grace_fixups_->next_; - delete grace_fixups_; - grace_fixups_ = n; - } - else if (len.grace_part_ && !len.main_part_) - { - here_mom_.grace_part_ =0; - } - else - { - /* - !len.grace_part_ || len.main_part_ - - We skip over a big chunk (mainpart != 0). Any starting graces - in that chunk should be in len.grace_part_ - - */ - here_mom_ += len; - } - - delete iter_p_; - cursor_ = ly_cdr (cursor_); - - if (gh_pair_p (cursor_)) - iter_p_ = get_iterator_p (unsmob_music (ly_car (cursor_))); - else - iter_p_ = 0; -} - /* move to context of child iterator if it is deeper down in the hierarchy. @@ -220,147 +32,10 @@ Sequential_music_iterator::descend_to_child () } -/* - Retrieve all music (starting at HERE), until a music with length L > - 0 is found. From the precondition, we know that UNTIL is later than - the earliest event. Hence we know - - L >= (UNTIL - HERE) - - so something that comes after this thing with L > 0 happens after - - HERE + L >= HERE + (UNTIL - HERE) = UNTIL - - Hence all events after the one with L>0 are uninteresting, so we - ignore them. - -*/ +IMPLEMENT_CTOR_CALLBACK (Sequential_music_iterator); SCM -Sequential_music_iterator::get_music (Moment until)const +Sequential_music_iterator::get_music_list()const { - SCM s = SCM_EOL; - if (until < pending_moment ()) - return s; - - Sequential_music_iterator * me = - dynamic_cast (clone ()); - while (me->ok ()) - { - SCM nm = me->iter_p_->get_music (until - me->here_mom_); - s = gh_append2 (nm, s); - - Moment m = 0; - for (SCM i = nm; gh_pair_p (i); i = ly_cdr (i)) - { - Music *mus=unsmob_music (ly_car (i)); - m = m >? (mus->length_mom () - mus->start_mom ()); - } - if (m > Moment (0)) - break ; - else - me->next_element (); - } - delete me; - - return s; + return dynamic_cast (music_l ())->music_list (); } - - -/* - Skip events till UNTIL. We don't do any other side effects such as - descending to child iterator contexts, because they might depend on - \context specs and \translator changes being executed - - TODO: check support for grace notes here. - */ -void -Sequential_music_iterator::skip (Moment until) -{ - while (ok ()) - { - if (grace_fixups_ && - grace_fixups_->start_ == here_mom_ - && (grace_fixups_->start_ + grace_fixups_->length_ - + Moment (Rational (0), grace_fixups_->grace_start_) == until)) - { - /* - do the stuff/note/rest preceding a grace. - */ - iter_p_->skip (iter_p_->music_length_mom ()); - } - else if (iter_p_->music_length_mom () >= until - here_mom_) - iter_p_->skip (until - here_mom_ + iter_p_->music_start_mom ()); - - if (iter_p_->ok ()) - return ; - - next_element (); - } -} - -void -Sequential_music_iterator::process (Moment until) -{ - while (iter_p_) - { - if (grace_fixups_ && - grace_fixups_->start_ == here_mom_ - && (grace_fixups_->start_ + grace_fixups_->length_ - + Moment (Rational (0), grace_fixups_->grace_start_) == until)) - { - /* - do the stuff/note/rest preceding a grace. - */ - iter_p_->process (iter_p_->music_length_mom ()); - } - else - iter_p_->process (until - here_mom_ + iter_p_->music_start_mom ()); - - /* - if the iter is still OK, there must be events left that have - - TIME > LEFT - - */ - if (iter_p_->ok ()) - return ; - - descend_to_child (); - next_element (); - } -} - -Moment -Sequential_music_iterator::pending_moment () const -{ - Moment cp = iter_p_->pending_moment (); - - /* - Fix-up a grace note halfway in the music. - */ - if (grace_fixups_ && here_mom_ == grace_fixups_->start_ - && grace_fixups_->length_ + iter_p_->music_start_mom () == cp) - { - return here_mom_ + grace_fixups_->length_ + Moment (0, grace_fixups_->grace_start_); - } - - /* - Fix-up a grace note at the start of the music. - */ - return cp + here_mom_ - iter_p_->music_start_mom (); -} - - -bool -Sequential_music_iterator::ok () const -{ - return iter_p_; -} - -Music_iterator* -Sequential_music_iterator::try_music_in_children (Music *m) const -{ - return iter_p_ ? iter_p_->try_music (m) : 0; -} -IMPLEMENT_CTOR_CALLBACK (Sequential_music_iterator); diff --git a/lily/unfolded-repeat-iterator.cc b/lily/unfolded-repeat-iterator.cc index 16c21f425b..95e5b04162 100644 --- a/lily/unfolded-repeat-iterator.cc +++ b/lily/unfolded-repeat-iterator.cc @@ -1,294 +1,108 @@ /* - unfolded-repeat-iterator.cc -- implement Unfolded_repeat_iterator - - source file of the GNU LilyPond music typesetter - - (c) 1999--2002 Han-Wen Nienhuys - - */ - -/* - This is too hairy. Maybe split into subclasses for volta and full - unfold? - - */ -#include "music-iterator.hh" -#include "repeated-music.hh" -#include "music-list.hh" -#include "warn.hh" -#include "translator-group.hh" - -/** - Iterate repeats. First do body, then alternatives one by one, - optionally interspersed by the body. - */ -class Unfolded_repeat_iterator : public Music_iterator -{ - void add_repeat_command (SCM); - -public: - VIRTUAL_COPY_CONS (Music_iterator); - /** - How often have we done the body (assuming bodies are interspersed.)? +unfolded-repeat-iterator.cc -- implement Unfolded_repeat_iterator, Volta_repeat_iterator - In volta: the number to print in the bracket. - */ - int done_count_; - static SCM constructor_cxx_function; +source file of the GNU LilyPond music typesetter - /* - are we now busy doing the body? - */ - bool do_main_b_; +(c) 2002 Han-Wen Nienhuys +*/ - /* - are we doing volta's? - */ - bool volta_b_; - /** How far have we progressed into the repeat. - This excludes the elt currently being iterated. - */ - Moment here_mom_; - int alternative_count_i_; - Music_iterator * current_iter_p_; - - /// pointer to the alternative that will be processed next. - SCM alternative_cons_; - ~Unfolded_repeat_iterator (); - Unfolded_repeat_iterator (); - Unfolded_repeat_iterator (Unfolded_repeat_iterator const &); -protected: - virtual void construct_children (); - virtual Moment pending_moment () const; - virtual void process (Moment); - virtual Music_iterator *try_music_in_children (Music *) const; - virtual void skip (Moment); - virtual SCM get_music (Moment) const; - - virtual bool ok () const; - virtual void next_element (bool side_effect); -}; +#include "music.hh" +#include "sequential-iterator.hh" +#include "translator-group.hh" -class Volta_repeat_iterator : public Unfolded_repeat_iterator +class Unfolded_repeat_iterator : public Sequential_iterator { public: - Volta_repeat_iterator (); static SCM constructor_cxx_function; VIRTUAL_COPY_CONS (Music_iterator); +protected: + virtual SCM get_music_list () const; }; - -Unfolded_repeat_iterator::~Unfolded_repeat_iterator () -{ - delete current_iter_p_; -} - -Unfolded_repeat_iterator::Unfolded_repeat_iterator (Unfolded_repeat_iterator const &src) - : Music_iterator (src) -{ - done_count_ = src.done_count_; - current_iter_p_ = (src.current_iter_p_)? src.current_iter_p_->clone () : 0; - do_main_b_ = src.do_main_b_; - volta_b_ = src.volta_b_; - here_mom_ = src.here_mom_; - alternative_count_i_ = src.alternative_count_i_; - alternative_cons_ = src.alternative_cons_; -} - -Unfolded_repeat_iterator::Unfolded_repeat_iterator () -{ - done_count_ =0; - current_iter_p_ =0; - volta_b_ = false; - do_main_b_ = false; - here_mom_ = Moment (0); - alternative_count_i_ =0; - alternative_cons_ = SCM_EOL; -} - -/** - -If we are in the body of the repeat always go to the current alternative. - -If we are not in the body, then we are in an alternative. If we are -fully unfolding, advance the current alternative and go back to main. -If we are semi-unfolding, advance the current alternative, and go to -the alternative just set. - - */ -void -Unfolded_repeat_iterator::next_element (bool side_effect) +SCM +Unfolded_repeat_iterator::get_music_list () const { - Repeated_music * repmus =dynamic_cast (music_l ()); - delete current_iter_p_; - current_iter_p_ =0; - - bool do_repcommands = side_effect && volta_b_; + SCM l = SCM_EOL; + SCM *tail = &l; - if (do_main_b_) - { - /* - we were busy doing the main body, so - - - go to alternative if we're a volta + SCM body = music_l ()->get_mus_property ("element"); + SCM alts = music_l ()->get_mus_property ("elements"); + int alt_count = scm_ilength (alts); + int rep_count = gh_scm2int (music_l ()->get_mus_property ("repeat-count")); - - make a :| if there are no alternatives - - - do something intelligent when we're fully unfolding (fixcomment) - */ - - here_mom_ += repmus->body ()->length_mom (); + for (int i = 0; i < rep_count; i++) + { + if (unsmob_music (body)) + *tail = gh_cons (body, SCM_EOL) ; - if (!volta_b_) - done_count_ ++; - - if (gh_pair_p (alternative_cons_)) - { - current_iter_p_ = get_iterator_p (unsmob_music (ly_car (alternative_cons_))); - do_main_b_ = false; + tail = SCM_CDRLOC (*tail); - if (volta_b_) - { - String repstr = to_str (done_count_ + 1) + "."; - - /* - we're coming in from main, so we're always on the first repeat. - */ - assert (done_count_ == 0); - - if (done_count_ == 0 - && alternative_count_i_ < repmus->repeat_count ()) - { - done_count_ += repmus->repeat_count () - alternative_count_i_; - repstr = "1.--" + to_str (done_count_ + 1) + "."; - } - - if (do_repcommands) - add_repeat_command (scm_list_n (ly_symbol2scm ("volta"), - ly_str02scm (repstr.ch_C ()), SCM_UNDEFINED)); - } - } - else if (volta_b_) - { - add_repeat_command (ly_symbol2scm ("end-repeat")); - } - else if (done_count_ < repmus->repeat_count ()) + if (alt_count) { - current_iter_p_ = get_iterator_p (repmus->body ()); - do_main_b_ = true; - } + *tail = gh_cons (gh_car (alts), SCM_EOL); + tail = SCM_CDRLOC (*tail); + if (i >= rep_count - alt_count) + + alts = gh_cdr (alts); + } } - else - { - /* - we're not in the main part. So we're either in an alternative, or - we just finished. - */ - - /* - we're in the alternatives. We move the pointer to the - next alternative. - */ - if (alternative_cons_) - { - here_mom_ += unsmob_music (ly_car (alternative_cons_))->length_mom (); - - if (volta_b_ || - repmus->repeat_count () - done_count_ < alternative_count_i_) - alternative_cons_ = ly_cdr (alternative_cons_); - - if (do_repcommands) - add_repeat_command (scm_list_n (ly_symbol2scm ("volta"), SCM_BOOL_F, SCM_UNDEFINED)); - - - - /* - we've done the main body as well, but didn't go over the other - increment. */ - if (volta_b_) - done_count_ ++; - } - - /* - We still have alternatives left, so - if we're volta: traverse them + return l; +} - if we're full unfold: go back to main body. - */ - - if (done_count_ < repmus->repeat_count () && gh_pair_p (alternative_cons_)) - { - if (do_repcommands) - { - String repstr = to_str (done_count_ + 1) + "."; - add_repeat_command (scm_list_n (ly_symbol2scm ("volta"), - ly_str02scm (repstr.ch_C ()), SCM_UNDEFINED)); - add_repeat_command (ly_symbol2scm ("end-repeat")); - } +class Volta_repeat_iterator : public Sequential_iterator +{ +public: + static SCM constructor_cxx_function; + VIRTUAL_COPY_CONS (Music_iterator); + Volta_repeat_iterator(); - - if (volta_b_) - current_iter_p_ = get_iterator_p (unsmob_music (ly_car (alternative_cons_))); - else - { - current_iter_p_ = get_iterator_p (repmus->body ()); - do_main_b_ = true; - } - } - } -} + void add_repeat_command (SCM); +protected: + virtual SCM get_music_list () const; + virtual void next_element (bool); + virtual void construct_children(); + virtual void process (Moment); + + int alt_count_; + int rep_count_; + int done_count_; +}; -bool -Unfolded_repeat_iterator::ok () const +Volta_repeat_iterator::Volta_repeat_iterator() { - return current_iter_p_; + done_count_ = alt_count_ = rep_count_= 0; } -Moment -Unfolded_repeat_iterator::pending_moment () const +SCM +Volta_repeat_iterator::get_music_list()const { - return here_mom_ + current_iter_p_->pending_moment (); + return gh_cons (music_l ()->get_mus_property ("element"), + music_l ()->get_mus_property ("elements")); } void -Unfolded_repeat_iterator::construct_children () +Volta_repeat_iterator::construct_children () { - Repeated_music * mus =dynamic_cast (music_l ()); + Sequential_iterator::construct_children(); - alternative_cons_ = (mus->alternatives ()) - ? mus->alternatives () - : SCM_EOL; - - for (SCM p = alternative_cons_; gh_pair_p (p); p = ly_cdr (p)) - alternative_count_i_ ++; + SCM alts = music_l ()->get_mus_property ("elements"); - if (mus->body ()) - { - current_iter_p_ = get_iterator_p (mus->body ()); - do_main_b_ = true; - } - else if (gh_pair_p (alternative_cons_)) - { - current_iter_p_ = get_iterator_p (unsmob_music (ly_car (alternative_cons_))); - do_main_b_ = false; - } - - while (current_iter_p_ && !current_iter_p_-> ok ()) - { - next_element (true); - } + alt_count_ = scm_ilength (alts); + rep_count_ = gh_scm2int (music_l ()->get_mus_property ("repeat-count")); + done_count_ = 0; } + /* TODO: add source information for debugging */ void -Unfolded_repeat_iterator::add_repeat_command (SCM what) +Volta_repeat_iterator::add_repeat_command (SCM what) { SCM reps = ly_symbol2scm ("repeatCommands"); SCM current_reps = report_to_l ()->internal_get_property (reps); @@ -302,91 +116,56 @@ Unfolded_repeat_iterator::add_repeat_command (SCM what) } } -void -Unfolded_repeat_iterator::process (Moment m) -{ - if (!m.to_bool ()) - { - if (volta_b_) - add_repeat_command (ly_symbol2scm ("start-repeat")); - } - while (1) - { - while (!current_iter_p_->ok ()) - { - next_element (true); - - if (!current_iter_p_) - return; - } - - if (m - here_mom_ >= current_iter_p_->pending_moment ()) - current_iter_p_->process (m - here_mom_); - else - return; - } -} void -Unfolded_repeat_iterator::skip (Moment until) +Volta_repeat_iterator::next_element (bool side_effect) { - while (current_iter_p_) - { - Moment l =current_iter_p_->music_length_mom (); - if (l >= until - here_mom_) - current_iter_p_->skip (until - here_mom_); + done_count_ ++; - if (current_iter_p_->ok ()) - return ; - - next_element (false); - } -} + Sequential_iterator::next_element (side_effect); -SCM -Unfolded_repeat_iterator::get_music (Moment until)const -{ - SCM s = SCM_EOL; - if (until < pending_moment ()) - return s; + if (side_effect) + { + if (alt_count_) + { + String repstr = to_str (rep_count_ - alt_count_ + done_count_) + "."; + if (done_count_ > 1) + { + add_repeat_command (scm_list_n (ly_symbol2scm ("volta"), SCM_BOOL_F, SCM_UNDEFINED)); + if (done_count_ - 1 < alt_count_) + add_repeat_command (ly_symbol2scm ("end-repeat")); + } - Unfolded_repeat_iterator * me - = dynamic_cast (this->clone ()); - - while (me->ok ()) - { - SCM nm = me->current_iter_p_->get_music (until - - me->here_mom_); - - s = gh_append2 (nm, s); + - Moment m = 0; - for (SCM i = nm; gh_pair_p (i); i = ly_cdr (i)) - m = m >? unsmob_music (ly_car (i))->length_mom (); + if (done_count_ == 1 && alt_count_ < rep_count_) + { + repstr = "1.--" + to_str (rep_count_ - alt_count_ + done_count_) + "."; + } - if (m > Moment (0)) - break ; + if (done_count_ <= alt_count_) + add_repeat_command (scm_list_n (ly_symbol2scm ("volta"), + ly_str02scm (repstr.ch_C ()), SCM_UNDEFINED)); + } else - me->next_element (false); + { + add_repeat_command (ly_symbol2scm ("end-repeat")); + } } - - delete me; - - return s; } -Music_iterator* -Unfolded_repeat_iterator::try_music_in_children (Music * m) const +void +Volta_repeat_iterator::process (Moment m) { - return current_iter_p_->try_music (m); + if (!m.to_bool ()) + { + add_repeat_command (ly_symbol2scm ("start-repeat")); + } + Sequential_iterator::process(m); } -IMPLEMENT_CTOR_CALLBACK (Unfolded_repeat_iterator); -IMPLEMENT_CTOR_CALLBACK (Volta_repeat_iterator); -Volta_repeat_iterator::Volta_repeat_iterator () -{ - volta_b_ = true; -} +IMPLEMENT_CTOR_CALLBACK(Volta_repeat_iterator); +IMPLEMENT_CTOR_CALLBACK(Unfolded_repeat_iterator); diff --git a/scm/c++.scm b/scm/c++.scm index 31113dc866..1ddeae1137 100644 --- a/scm/c++.scm +++ b/scm/c++.scm @@ -142,6 +142,7 @@ is the first to satisfy CRIT " `(("volta" . ((iterator-ctor . ,Volta_repeat_iterator::constructor) (start-moment-function . ,Repeated_music::first_start) (length . ,Repeated_music::volta_music_length))) + ("unfold" . ((iterator-ctor . ,Unfolded_repeat_iterator::constructor) (start-moment-function . ,Repeated_music::first_start) (length . ,Repeated_music::unfolded_music_length)))