]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/quote-iterator.cc
(beam): add function.
[lilypond.git] / lily / quote-iterator.cc
index 3b676a4cd5155f544f60766c6cc20e571be4b31a..4f2e5ab2fc2c4cf357b62f7f9bf44eaae310975d 100644 (file)
 #include "event.hh"
 #include "music-sequence.hh"
 #include "lily-guile.hh"
-#include "music-iterator.hh"
+#include "music-wrapper-iterator.hh"
 #include "music.hh"
 #include "input.hh"
 #include "warn.hh"
+#include "interpretation-context-handle.hh"
 
-
-class Quote_iterator : public Music_iterator
+class Quote_iterator : public Music_wrapper_iterator
 {
 public:
   Quote_iterator ();
   Moment vector_moment (int idx) const;
-  
+  Interpretation_context_handle quote_outlet_;
+
   Moment start_moment_;
+  Moment stop_moment_;
   SCM event_vector_;
   int event_idx_;
   int end_idx_ ;
@@ -31,7 +33,7 @@ public:
   SCM transposed_musics_;
   
   DECLARE_SCHEME_CALLBACK (constructor, ()); 
-
+  bool quote_ok () const;
   bool accept_music_type (Music*) const;
 protected:
   virtual void derived_mark () const;
@@ -70,12 +72,6 @@ Quote_iterator::Quote_iterator ()
   end_idx_ = 0;
 }
 
-bool
-moment_less (SCM a, SCM b)
-{
-  return  *unsmob_moment (a) < *unsmob_moment (b);
-}
-
 
 int
 binsearch_scm_vector (SCM vec, SCM key, bool (*is_less)(SCM a,SCM b))
@@ -104,40 +100,75 @@ binsearch_scm_vector (SCM vec, SCM key, bool (*is_less)(SCM a,SCM b))
 void
 Quote_iterator::construct_children ()
 {
-  SCM dur = get_music ()->get_property ("duration");
-  if (!unsmob_duration (dur))
-    return ;
+  Music_wrapper_iterator::construct_children ();
 
-  set_translator (get_outlet ()->get_default_interpreter ());
-  
-  Moment now = get_outlet ()->now_mom ();
-  Moment stop = now + unsmob_duration (dur)->get_length ();
+  SCM name = get_music ()->get_property ("quoted-context-type");
+  SCM id = get_music ()->get_property ("quoted-context-id");
 
-  start_moment_ = now;
-  event_vector_ = get_music ()->get_property ("quoted-events");
-
-  if (ly_c_vector_p (event_vector_))
+  if (scm_is_string (id)
+      && scm_is_symbol (name))
     {
-      event_idx_ = binsearch_scm_vector (event_vector_, now.smobbed_copy (), &moment_less);
-      end_idx_ = binsearch_scm_vector (event_vector_, stop.smobbed_copy (), &moment_less);
+      Context *cue_context = get_outlet()->find_create_context (name,
+                                                               ly_scm2string (id), SCM_EOL);
+      quote_outlet_.set_context (cue_context);
     }
   else
     {
-      get_music ()->origin()->warning (_("No events found for \\quote"));
+      quote_outlet_.set_context (get_outlet ());
     }
+  
+
+  event_vector_ = get_music ()->get_property ("quoted-events");
+  
+  /*
+    We have to delay initting event_idx_ , since we have to
+    take starting grace notes into account. Those may offset 
+    event_idx_.
+  */
+  event_idx_ = -1;
 }
 
 
 bool
 Quote_iterator::ok () const
 {
-  return ly_c_vector_p (event_vector_) && (event_idx_ <= end_idx_);
+  return
+    Music_wrapper_iterator::ok()
+    || quote_ok ();
+}
+
+bool
+Quote_iterator::quote_ok () const
+{
+  return (event_idx_ >= 0
+         && ly_c_vector_p (event_vector_)
+         && event_idx_ <= end_idx_
+
+         /*
+           Don't quote the grace notes leading to an unquoted note.
+          */
+         && vector_moment (event_idx_).main_part_ < stop_moment_.main_part_
+         );
 }
 
 Moment
 Quote_iterator::pending_moment () const
 {
-  return vector_moment (event_idx_) - start_moment_;
+  Rational infty;
+  infty.set_infinite (1);
+  Moment m (infty);
+
+  if (Music_wrapper_iterator::ok())
+    m = m <? Music_wrapper_iterator::pending_moment();
+
+  /*
+    In case event_idx_ < 0, we're not initted yet, and the wrapped
+    music expression determines the starting moment.
+   */
+  if (quote_ok ())
+    m = m <? vector_moment (event_idx_) - start_moment_;
+
+  return m;
 }
 
 Moment
@@ -146,11 +177,29 @@ Quote_iterator::vector_moment (int idx) const
   SCM entry = SCM_VECTOR_REF (event_vector_, idx);
   return *unsmob_moment (scm_caar (entry));
 }
-  
 
 void
 Quote_iterator::process (Moment m)
 {
+  if (Music_wrapper_iterator::ok())
+    Music_wrapper_iterator::process (m);
+
+  if (!ly_c_vector_p (event_vector_))
+    return ;
+  
+  if (event_idx_ < 0)
+    {
+      event_idx_ = binsearch_scm_vector (event_vector_,
+                                        get_outlet ()->now_mom ().smobbed_copy (),
+                                        &moment_less);
+      start_moment_ = get_outlet ()->now_mom () - music_start_mom();
+      stop_moment_ = start_moment_ + get_music()->get_length ();
+      
+      end_idx_ = binsearch_scm_vector (event_vector_,
+                                      stop_moment_.smobbed_copy (),
+                                      &moment_less);
+    }
+  
   m += start_moment_;
   while (event_idx_ <= end_idx_)
     {
@@ -164,7 +213,7 @@ Quote_iterator::process (Moment m)
       event_idx_++;
     }
 
-  if (event_idx_ <= end_idx_)
+  if (quote_ok ())
     {
       SCM entry = SCM_VECTOR_REF (event_vector_, event_idx_);
       Pitch * quote_pitch = unsmob_pitch (scm_cdar (entry));
@@ -193,23 +242,21 @@ Quote_iterator::process (Moment m)
 
                  Pitch diff = pitch_interval (qp, mp);
 
-                 SCM copy = ly_deep_mus_copy (mus->self_scm ());
+                 SCM copy = ly_music_deep_copy (mus->self_scm ());
                  mus = unsmob_music (copy);
-                 transposed_musics_ = scm_cons (copy, transposed_musics_);
-
                  
+                 transposed_musics_ = scm_cons (copy, transposed_musics_);
                  mus->transpose (diff);
                }
-
              
-             bool b = get_outlet ()->try_music (mus);
-      
+             bool b = quote_outlet_.get_outlet ()->try_music (mus);
              if (!b)
                mus->origin ()->warning (_f ("In quotation: junking event %s", mus->name ()));
            }
        }
+      
+      event_idx_ ++; 
     }
-  event_idx_ ++; 
 }
 
 IMPLEMENT_CTOR_CALLBACK (Quote_iterator);