]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/quote-iterator.cc
Web-ja: update introduction
[lilypond.git] / lily / quote-iterator.cc
index 4d26ce79f0b8de11903b197c88c0efead01e6906..885e1bd3b658ef593f0418a19b66449a881a0e77 100644 (file)
@@ -1,17 +1,31 @@
-/*   
-  quote-iterator.cc --  implement Quote_iterator
+/*
+  This file is part of LilyPond, the GNU music typesetter.
 
-  source file of the GNU LilyPond music typesetter
+  Copyright (C) 2004--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
-  (c) 2004--2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  LilyPond is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
 
+  LilyPond is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#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-wrapper-iterator.hh"
+#include "music-sequence.hh"
+#include "music.hh"
 #include "warn.hh"
 
 class Quote_iterator : public Music_wrapper_iterator
@@ -19,46 +33,60 @@ class Quote_iterator : public Music_wrapper_iterator
 public:
   Quote_iterator ();
   Moment vector_moment (int idx) const;
-  Interpretation_context_handle quote_outlet_;
+  Context_handle quote_outlet_;
 
   Moment start_moment_;
   Moment stop_moment_;
   SCM event_vector_;
   int event_idx_;
-  int end_idx_ ;
+  int end_idx_;
 
   SCM transposed_musics_;
-  
-  DECLARE_SCHEME_CALLBACK (constructor, ()); 
+
+  DECLARE_SCHEME_CALLBACK (constructor, ());
   bool quote_ok () const;
-  bool accept_music_type (Music*) const;
+  bool accept_music_type (Stream_event *, bool is_cue = true) const;
+
 protected:
   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::do_quit ()
+{
+  Music_wrapper_iterator::do_quit ();
+  quote_outlet_.set_context (0);
+}
+
 bool
-Quote_iterator::accept_music_type (Music *mus) const
+Quote_iterator::accept_music_type (Stream_event *ev, bool is_cue) const
 {
-  SCM accept = get_outlet()->get_property ("quotedEventTypes");
-  for (SCM s =  mus->get_property ("types");
-       scm_is_pair (s);  s = scm_cdr (s))
+  SCM accept = SCM_EOL;
+  // Cue notes use the quotedCueEventTypes property, otherwise (and as fallback
+  // for cue notes if quotedCueEventTypes is not set) use quotedEventTypes
+  if (is_cue)
+    accept = get_outlet ()->get_property ("quotedCueEventTypes");
+  if (scm_is_null (accept))
+    accept = get_outlet ()->get_property ("quotedEventTypes");
+
+  for (; scm_is_pair (accept); accept = scm_cdr (accept))
     {
-      if (scm_memq (scm_car (s), accept) != SCM_BOOL_F)
-       return true;
+      if (ev->internal_in_event_class (scm_car (accept)))
+        return true;
     }
-
   return false;
 }
 
-
 void
 Quote_iterator::derived_mark () const
 {
-  scm_gc_mark (transposed_musics_ );
+  Music_wrapper_iterator::derived_mark ();
+  scm_gc_mark (transposed_musics_);
 }
 
 Quote_iterator::Quote_iterator ()
@@ -69,31 +97,29 @@ Quote_iterator::Quote_iterator ()
   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 = 0;
   int hi = scm_c_vector_length (vec);
 
   /* binary search */
   do
-  {
-    int cmp = (lo + hi) / 2;
+    {
+      int cmp = (lo + hi) / 2;
 
       SCM when = scm_caar (scm_c_vector_ref (vec, cmp));
-      bool result =  (*is_less) (key, when);
+      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 ()
 {
@@ -102,35 +128,32 @@ Quote_iterator::construct_children ()
   SCM name = get_music ()->get_property ("quoted-context-type");
   SCM id = get_music ()->get_property ("quoted-context-id");
 
-  if (scm_is_string (id)
-      && scm_is_symbol (name))
+  if (scm_is_symbol (name))
     {
-      Context *cue_context = get_outlet()->find_create_context (name,
-                                                               ly_scm2string (id), SCM_EOL);
+      Context *cue_context =
+        get_outlet ()->find_create_context (name,
+                                            robust_scm2string (id, ""),
+                                            SCM_EOL);
       quote_outlet_.set_context (cue_context);
     }
   else
-    {
-      quote_outlet_.set_context (get_outlet ());
-    }
-  
+    quote_outlet_.set_context (get_outlet ()->get_default_interpreter ());
 
   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 
+    take starting grace notes into account. Those may offset
     event_idx_.
   */
   event_idx_ = -1;
 }
 
-
 bool
 Quote_iterator::ok () const
 {
   return
-    Music_wrapper_iterator::ok()
+    Music_wrapper_iterator::ok ()
     || quote_ok ();
 }
 
@@ -138,14 +161,13 @@ 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_
-         );
+          && 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
@@ -155,15 +177,15 @@ Quote_iterator::pending_moment () const
   infty.set_infinite (1);
   Moment m (infty);
 
-  if (Music_wrapper_iterator::ok())
-    m = m <? Music_wrapper_iterator::pending_moment();
+  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 = m <? vector_moment (event_idx_) - start_moment_;
+    m = min (m, vector_moment (event_idx_) - start_moment_);
 
   return m;
 }
@@ -172,40 +194,40 @@ Moment
 Quote_iterator::vector_moment (int idx) const
 {
   SCM entry = scm_c_vector_ref (event_vector_, idx);
-  return *unsmob_moment (scm_caar (entry));
+  return *unsmob<Moment> (scm_caar (entry));
 }
 
 void
 Quote_iterator::process (Moment m)
 {
-  if (Music_wrapper_iterator::ok())
+  if (Music_wrapper_iterator::ok ())
     Music_wrapper_iterator::process (m);
 
   if (!scm_is_vector (event_vector_))
-    return ;
-  
+    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 ();
-      
+                                         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);
+                                       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_++;
     }
@@ -213,46 +235,56 @@ Quote_iterator::process (Moment m)
   if (quote_ok ())
     {
       SCM entry = scm_c_vector_ref (event_vector_, event_idx_);
-      Pitch * quote_pitch = unsmob_pitch (scm_cdar (entry));
+      Pitch *quote_pitch = unsmob<Pitch> (scm_cdar (entry));
 
       /*
-       The pitch that sounds like central C
-       */
-      Pitch * me_pitch = unsmob_pitch (get_outlet ()->get_property ("instrumentTransposition"));
-      
+        The pitch that sounds when written central C is played.
+      */
+      Pitch temp_pitch;
+      Pitch *me_pitch = unsmob<Pitch> (get_music ()->get_property ("quoted-transposition"));
+      if (!me_pitch)
+        me_pitch = unsmob<Pitch> (get_outlet ()->get_property ("instrumentTransposition"));
+      else
+        {
+          // We are not going to win a beauty contest with this one,
+          // but it is slated for replacement and touches little code.
+          // quoted-transposition currently has a different sign
+          // convention than instrumentTransposition
+          temp_pitch = me_pitch->negated ();
+          me_pitch = &temp_pitch;
+        }
+      SCM cid = get_music ()->get_property ("quoted-context-id");
+      bool is_cue = scm_is_string (cid) && (ly_scm2string (cid) == "cue");
+
       for (SCM s = scm_cdr (entry); scm_is_pair (s); s = scm_cdr (s))
-       {
-         SCM ev_acc = scm_car (s);
-
-         Music * mus = unsmob_music (scm_car (ev_acc));
-         if (!mus)
-           programming_error ("need music in quote.");
-         else if (accept_music_type (mus))
-           {
-             if (quote_pitch || me_pitch)
-               {
-                 Pitch qp, mp;
-                 if (quote_pitch)
-                   qp = *quote_pitch;
-                 if (me_pitch)
-                   mp = *me_pitch;
-
-                 Pitch diff = pitch_interval (qp, mp);
-
-                 SCM copy = ly_music_deep_copy (mus->self_scm ());
-                 mus = unsmob_music (copy);
-                 
-                 transposed_musics_ = scm_cons (copy, transposed_musics_);
-                 mus->transpose (diff);
-               }
-             
-             bool b = quote_outlet_.get_outlet ()->try_music (mus);
-             if (!b)
-               mus->origin ()->warning (_f ("In quotation: junking event %s", mus->name ()));
-           }
-       }
-      
-      event_idx_ ++; 
+        {
+          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, is_cue))
+            {
+              /* create a transposed copy if necessary */
+              if (quote_pitch || me_pitch)
+                {
+                  Pitch qp, mp;
+                  if (quote_pitch)
+                    qp = *quote_pitch;
+                  if (me_pitch)
+                    mp = *me_pitch;
+
+                  Pitch diff = pitch_interval (mp, qp);
+                  ev = ev->clone ();
+                  ev->make_transposable ();
+                  ev->transpose (diff);
+                  transposed_musics_ = scm_cons (ev->unprotect (), transposed_musics_);
+                }
+              quote_outlet_.get_context ()->event_source ()->broadcast (ev);
+            }
+        }
+
+      event_idx_++;
     }
 }