+2002-07-12 Han-Wen <hanwen@cs.uu.nl>
+
+ * 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 <hanwen@cs.uu.nl>
* lily/include/debug.hh: deprecate.
@lilypondfile[printfilename]{grace-bar-number.ly}
+@lilypondfile[printfilename]{grace-auto-beam.ly}
+
+@lilypondfile[printfilename]{grace-unfold-repeat.ly}
+
@section Beams
--- /dev/null
+\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 |
+ }
+}
--- /dev/null
+\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}
+
+ }
+}
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)
/* but ending is not */
r = 1;
}
+
return !r;
}
#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"
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);
#include "paper-score.hh"
#include "paper-def.hh"
#include "grob.hh"
-#include "debug.hh"
+
#include "spanner.hh"
#include "item.hh"
#include "misc.hh"
#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"
--- /dev/null
+/*
+ sequential-iterator.hh -- declare Sequential_iterator
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+*/
+
+#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 */
#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
#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"
--- /dev/null
+/*
+ Sequential_iterator.cc -- implement Sequential_iterator
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1997--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+*/
+
+#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<Sequential_iterator*> (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);
#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_sequence const*> (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.
}
-/*
- 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<Sequential_music_iterator*> (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_sequence const*> (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);
/*
- unfolded-repeat-iterator.cc -- implement Unfolded_repeat_iterator
-
- source file of the GNU LilyPond music typesetter
-
- (c) 1999--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
-
- */
-
-/*
- 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 <hanwen@cs.uu.nl>
+*/
- /*
- 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<Repeated_music *> (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<Repeated_music *> (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);
}
}
-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<Unfolded_repeat_iterator*> (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);
`(("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)))