]> git.donarmstrong.com Git - lilypond.git/commitdiff
* input/regression/grace-auto-beam.ly: new file
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Thu, 11 Jul 2002 23:07:09 +0000 (23:07 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Thu, 11 Jul 2002 23:07:09 +0000 (23:07 +0000)
* 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.

16 files changed:
ChangeLog
Documentation/regression-test.tely
input/regression/grace-auto-beam.ly [new file with mode: 0644]
input/regression/grace-unfold-repeat.ly [new file with mode: 0644]
lily/auto-beam-engraver.cc
lily/break-algorithm.cc
lily/forbid-break-engraver.cc
lily/grob-property.cc
lily/grob.cc
lily/include/sequential-iterator.hh [new file with mode: 0644]
lily/include/sequential-music-iterator.hh
lily/paper-def.cc
lily/sequential-iterator.cc [new file with mode: 0644]
lily/sequential-music-iterator.cc
lily/unfolded-repeat-iterator.cc
scm/c++.scm

index 1cab6d4e8a092492a37cc135595f515091cdbd7a..566160ab812459b1b56f89913b5f43fb94a7f92f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+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.
index f469c28c1703cf14b197431cffe5016d6b66f82e..b140bdf65fd3c292b9bd140dd2495b3e196c0cfa 100644 (file)
@@ -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 (file)
index 0000000..53deb7e
--- /dev/null
@@ -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 (file)
index 0000000..9b580ce
--- /dev/null
@@ -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}
+
+  }
+}
index 15e931c7cb6a69550bde20959dff22d3f22d2889..14e9604996e49daffbd7b689e9b0a28d4acbd5d3 100644 (file)
@@ -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;
 }
 
index 7dd25936c3c5a80f5d252851de39ab571d8db0a2..249dcec8fb673b3d9fb118776c0c6a9718ec3fa4 100644 (file)
@@ -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"
index 0ece1306c58a8a8d5d6bffdd106e6c247d8b9b0b..3df1cdc6402098f0d31bc9a4456ecae313096953 100644 (file)
@@ -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);
 
   
index c03e3119368c46f3570776047bf685d27fa56bde..d4a0272734ed28d82d8ed4534034ffeed32b87e1 100644 (file)
@@ -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"
index 6caceb624a462042c883099a369177b7db877c61..ff3130c57fa39506f03026dd7083fb65c6e469b3 100644 (file)
 
 #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 (file)
index 0000000..d56d8ad
--- /dev/null
@@ -0,0 +1,81 @@
+/*   
+  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 */
index 62a251e22f4dc278abac992628be283dce8174c1..31d4220927a1b8c2277ef4c0afe46891b3d0dd8b 100644 (file)
@@ -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
index f0518445324f6782a737c5c8fa0eb700b96cd670..3bf736aeff80bf1cb9cbb31abe900a6f4ae87447 100644 (file)
@@ -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 (file)
index 0000000..3e5d8a5
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+  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);
index 63f7e072f0cc901b25cfeb8b549364a67a598fb1..6de624e0eb5122a102b666aa5e84f0fc8e042274 100644 (file)
 #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.
@@ -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<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);
index 16c21f425b5551af555c024a377496c2eac0c208..95e5b041627a46f949c12ba31468e8751895e6f1 100644 (file)
 /*   
-  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);
@@ -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<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);
index 31113dc8663bd43f0bda71a1a6da58d20d63417a..1ddeae1137130cfacdd87e1666b546e023a30a98 100644 (file)
@@ -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)))