]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/quote-iterator.cc
Run `make grand-replace'.
[lilypond.git] / lily / quote-iterator.cc
index 582ba6bac95f0e2d708c4d03af99de802ef4f451..3eaf002c0b9557d1705e777cf8f077fb2e73931f 100644 (file)
-/*   
-  quote-iterator.cc --  implement Quote_iterator
+/*
+  quote-iterator.cc -- implement Quote_iterator
 
   source file of the GNU LilyPond music typesetter
 
-  (c) 2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
-
+  (c) 2004--2008 Han-Wen Nienhuys <hanwen@xs4all.nl>
 */
 
+#include "music-wrapper-iterator.hh"
+
 #include "context.hh"
-#include "event.hh"
-#include "music-sequence.hh"
+#include "dispatcher.hh"
+#include "input.hh"
+#include "international.hh"
 #include "lily-guile.hh"
-#include "music-iterator.hh"
+#include "music-sequence.hh"
 #include "music.hh"
-#include "input.hh"
 #include "warn.hh"
 
-
-class Quote_iterator : public Music_iterator
+class Quote_iterator : public Music_wrapper_iterator
 {
 public:
   Quote_iterator ();
-  
+  Moment vector_moment (int idx) const;
+  Context_handle quote_outlet_;
+
   Moment start_moment_;
+  Moment stop_moment_;
   SCM event_vector_;
   int event_idx_;
-  int end_idx_ ;
-
-  SCM transposed_musics_;
+  int end_idx_;
   
-  DECLARE_SCHEME_CALLBACK (constructor, ()); 
+  SCM transposed_musics_;
+
+  DECLARE_SCHEME_CALLBACK (constructor, ());
+  bool quote_ok () const;
+  bool accept_music_type (Stream_event *) const;
 
 protected:
-  virtual void derived_mark ();
+  virtual void derived_mark () const;
   virtual void construct_children ();
   virtual Moment pending_moment () const;
   virtual void process (Moment);
+  virtual void do_quit ();
   virtual bool ok () const;
 };
 
 void
-Quote_iterator::derived_mark ()
+Quote_iterator::do_quit ()
 {
-  scm_gc_mark (transposed_musics_ );
+  Music_wrapper_iterator::do_quit ();
+  quote_outlet_.set_context (0);
 }
 
-Quote_iterator::Quote_iterator ()
+bool
+Quote_iterator::accept_music_type (Stream_event *ev) const
 {
-  event_vector_ = SCM_EOL;
-  event_idx_ = 0;
-  end_idx_ = 0;
+  for (SCM accept = get_outlet ()->get_property ("quotedEventTypes");
+       scm_is_pair (accept); accept = scm_cdr (accept))
+    {
+      if (ev->internal_in_event_class (scm_car (accept)))
+       return true;
+    }
+  return false;
 }
 
-bool
-moment_less (SCM a, SCM b)
+void
+Quote_iterator::derived_mark () const
 {
-  return  *unsmob_moment (a) < *unsmob_moment (b);
+  Music_wrapper_iterator::derived_mark ();
+  scm_gc_mark (transposed_musics_);
 }
 
+Quote_iterator::Quote_iterator ()
+{
+  transposed_musics_ = SCM_EOL;
+  event_vector_ = SCM_EOL;
+  event_idx_ = 0;
+  end_idx_ = 0;
+}
 
 int
-binsearch_scm_vector (SCM vec, SCM key, bool (*is_less)(SCM a,SCM b))
+binsearch_scm_vector (SCM vec, SCM key, bool (*is_less) (SCM a, SCM b))
 {
-  int lo;
-  int hi;
-  lo = 0;
-  hi = SCM_VECTOR_LENGTH (vec);
+  int lo = 0;
+  int hi = scm_c_vector_length (vec);
 
   /* binary search */
   do
-  {
-    int cmp = (lo + hi) / 2;
+    {
+      int cmp = (lo + hi) / 2;
 
-      SCM when = ly_caar (SCM_VECTOR_REF (vec, cmp));
-      bool result =  (*is_less) (key, when);
+      SCM when = scm_caar (scm_c_vector_ref (vec, cmp));
+      bool result = (*is_less) (key, when);
       if (result)
-          hi = cmp;
+       hi = cmp;
       else
-          lo = cmp;
+       lo = cmp;
     }
   while (hi - lo > 1);
 
   return lo;
 }
 
-
 void
 Quote_iterator::construct_children ()
 {
-  SCM dur = get_music ()->get_property ("duration");
-  if (!unsmob_duration (dur))
-    return ;
+  Music_wrapper_iterator::construct_children ();
+      
+  SCM name = get_music ()->get_property ("quoted-context-type");
+  SCM id = get_music ()->get_property ("quoted-context-id");
 
-  set_translator (get_outlet ()->get_default_interpreter ());
-  
-  Moment now = get_outlet ()->now_mom ();
-  Moment stop = now + unsmob_duration (dur)->get_length ();
+  if (scm_is_string (id)
+      && scm_is_symbol (name))
+    {
+      Context *cue_context = get_outlet ()->find_create_context (name,
+                                                                ly_scm2string (id), SCM_EOL);
+      quote_outlet_.set_context (cue_context);
+    }
+  else
+    quote_outlet_.set_context (get_outlet ());
 
-  start_moment_ = now;
   event_vector_ = get_music ()->get_property ("quoted-events");
 
-  if (is_vector (event_vector_))
-    {
-      event_idx_ = binsearch_scm_vector (event_vector_, now.smobbed_copy (), &moment_less);
-      end_idx_ = binsearch_scm_vector (event_vector_, stop.smobbed_copy (), &moment_less);
-    }
+  /*
+    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 (event_idx_ <= end_idx_);
+  return
+    Music_wrapper_iterator::ok ()
+    || quote_ok ();
 }
 
+bool
+Quote_iterator::quote_ok () const
+{
+  return (event_idx_ >= 0
+         && scm_is_vector (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
 {
-  SCM entry = SCM_VECTOR_REF (event_vector_, event_idx_);
-  return *unsmob_moment (ly_caar (entry)) - start_moment_;
+  Rational infty;
+  infty.set_infinite (1);
+  Moment m (infty);
+
+  if (Music_wrapper_iterator::ok ())
+    m = min (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 = min (m, vector_moment (event_idx_) - start_moment_);
+
+  return m;
 }
 
+Moment
+Quote_iterator::vector_moment (int idx) const
+{
+  SCM entry = scm_c_vector_ref (event_vector_, idx);
+  return *unsmob_moment (scm_caar (entry));
+}
 
 void
 Quote_iterator::process (Moment m)
 {
-  SCM entry = SCM_EOL;
+  if (Music_wrapper_iterator::ok ())
+    Music_wrapper_iterator::process (m);
 
-  m += start_moment_;
-  while (event_idx_ < end_idx_)
-    {
-      entry = SCM_VECTOR_REF (event_vector_, event_idx_);
+  if (!scm_is_vector (event_vector_))
+    return;
 
-      Moment em = *unsmob_moment (ly_caar (entry));
+  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_)
+    {
+      Moment em = vector_moment (event_idx_);
       if (em > m)
-       return ;
+       return;
 
       if (em == m)
-       break ;
+       break;
 
       event_idx_++;
     }
 
-  if (ly_c_pair_p (entry))
+  if (quote_ok ())
     {
-      Pitch * quote_pitch = unsmob_pitch (ly_cdar (entry));
-      Pitch * me_pitch = unsmob_pitch (get_outlet ()->get_property ("instrumentTransposition"));
-      
-      for (SCM s = ly_cdr (entry); ly_c_pair_p (s); s = ly_cdr (s))
-       {
-         SCM ev_acc = ly_car (s);
+      SCM entry = scm_c_vector_ref (event_vector_, event_idx_);
+      Pitch *quote_pitch = unsmob_pitch (scm_cdar (entry));
 
+      /*
+       The pitch that sounds like central C
+      */
+      Pitch *me_pitch = unsmob_pitch (get_music ()->get_property ("quoted-transposition"));
+      if (!me_pitch)
+       me_pitch = unsmob_pitch (get_outlet ()->get_property ("instrumentTransposition"));
 
-         Music * mus = unsmob_music (ly_car (ev_acc));
-         if (mus)
+      for (SCM s = scm_cdr (entry); scm_is_pair (s); s = scm_cdr (s))
+       {
+         SCM ev_acc = scm_car (s);
+
+         Stream_event *ev = unsmob_stream_event (scm_car (ev_acc));
+         if (!ev)
+           programming_error ("no music found in quote");
+         else if (accept_music_type (ev))
            {
+             /* create a transposed copy if necessary */
              if (quote_pitch || me_pitch)
                {
                  Pitch qp, mp;
@@ -165,26 +243,18 @@ Quote_iterator::process (Moment m)
                  if (me_pitch)
                    mp = *me_pitch;
 
-                 Pitch diff = interval (mp, qp);
-
-                 SCM copy = ly_deep_mus_copy (mus->self_scm ());
-                 mus = unsmob_music (copy);
-                 transposed_musics_ = scm_cons (copy, transposed_musics_);
+                 Pitch diff = pitch_interval (qp, mp);
+                 ev = ev->clone ();
                  
-                 mus->transpose (diff);
+                 transpose_mutable (ev->get_property_alist (true), diff);
+                 transposed_musics_ = scm_cons (ev->unprotect (), transposed_musics_);
                }
-
-             
-             bool b = get_outlet ()->try_music (mus);
-      
-             if (!b)
-               mus->origin ()->warning (_f ("In quotation: junking event %s", mus->name ()));
+             quote_outlet_.get_outlet ()->event_source ()->broadcast (ev);
            }
-         else
-           programming_error ("need music in quote.");
        }
+
+      event_idx_++;
     }
-  event_idx_ ++; 
 }
 
 IMPLEMENT_CTOR_CALLBACK (Quote_iterator);