]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 4056: Let \partial in mid-piece work via a finalization hook
authorDavid Kastrup <dak@gnu.org>
Sun, 15 Jun 2014 23:01:57 +0000 (01:01 +0200)
committerDavid Kastrup <dak@gnu.org>
Thu, 14 Aug 2014 16:05:13 +0000 (18:05 +0200)
That allows all other processing to complete before measurePosition is
adjusted.  In particular, this avoids problems when multiple parallel
contexts invoke \partial and/or bar checks.

lily/partial-iterator.cc

index 13223297f551c5fa972e1581d94d39595d59b387..723391020913a08dab5785a36ca4acde7759d83e 100644 (file)
@@ -18,6 +18,7 @@
 */
 
 #include "context.hh"
+#include "global-context.hh"
 #include "input.hh"
 #include "international.hh"
 #include "moment.hh"
@@ -28,6 +29,7 @@ class Partial_iterator : public Simple_music_iterator
 {
 public:
   DECLARE_SCHEME_CALLBACK (constructor, ());
+  DECLARE_SCHEME_CALLBACK (finalization, (SCM, SCM));
 protected:
   virtual void process (Moment);
 };
@@ -38,33 +40,41 @@ Partial_iterator::process (Moment m)
   if (Duration * dur
       = Duration::unsmob (get_music ()->get_property ("duration")))
     {
-      // Partial_iterator is an iterator rather than an engraver, so
-      // the active context it is getting called in does not depend on
-      // which context definition the engraver might be defined.
-      //
-      // Using where_defined to find the context where measurePosition
-      // should be overwritten does not actually work since the
-      // Timing_translator does not set measurePosition when
-      // initializing.
-
-      Context *timing = Context::unsmob (scm_call_2 (ly_lily_module_constant ("ly:context-find"),
-                                                    get_outlet ()->self_scm (),
-                                                    ly_symbol2scm ("Timing")));
-
-      if (!timing)
-        programming_error ("missing Timing in \\partial");
+      Moment length = Moment (dur->get_length ());
+      if (get_outlet ()->now_mom () > 0)
+        {
+          Global_context *tg = get_outlet ()->get_global_context ();
+          tg->add_finalization (scm_list_3 (finalization_proc,
+                                            get_outlet ()->self_scm (),
+                                            length.smobbed_copy ()));
+        }
       else
         {
-          Moment mp = robust_scm2moment (timing->get_property ("measurePosition"),
-                                         Rational (0));
+          // Partial_iterator is an iterator rather than an engraver,
+          // so the active context it is getting called in does not
+          // depend on which context definition the engraver might be
+          // defined.
+          //
+          // Using where_defined to find the context where
+          // measurePosition should be overwritten does not actually
+          // work since the Timing_translator does not set
+          // measurePosition when initializing.
 
-          if (get_outlet ()->now_mom () > 0)
-            mp.main_part_ = measure_length (timing);
+          Context *timing = Context::unsmob
+            (scm_call_2 (ly_lily_module_constant ("ly:context-find"),
+                         get_outlet ()->self_scm (),
+                         ly_symbol2scm ("Timing")));
+          if (!timing)
+            programming_error ("missing Timing in \\partial");
           else
-            mp.main_part_ = 0;
-
-          Moment length = Moment (dur->get_length ());
-          timing->set_property ("measurePosition", (mp - length).smobbed_copy ());
+            {
+              Moment mp = robust_scm2moment
+                (timing->get_property ("measurePosition"),
+                 Rational (0));
+              mp.main_part_ = 0;
+              timing->set_property
+                ("measurePosition", (mp - length).smobbed_copy ());
+            }
         }
     }
   else
@@ -74,3 +84,25 @@ Partial_iterator::process (Moment m)
 }
 
 IMPLEMENT_CTOR_CALLBACK (Partial_iterator);
+
+MAKE_SCHEME_CALLBACK (Partial_iterator, finalization, 2);
+SCM
+Partial_iterator::finalization (SCM ctx, SCM length)
+{
+  LY_ASSERT_SMOB (Context, ctx, 1);
+  LY_ASSERT_SMOB (Moment, length, 2);
+  Context *timing = Context::unsmob
+    (scm_call_2 (ly_lily_module_constant ("ly:context-find"),
+                 ctx,
+                 ly_symbol2scm ("Timing")));
+  if (!timing) {
+    programming_error ("missing Timing in \\partial");
+    return SCM_UNSPECIFIED;
+  }
+  Moment mp = robust_scm2moment (timing->get_property ("measurePosition"),
+                                 Rational (0));
+  mp.main_part_ = measure_length (timing);
+  timing->set_property ("measurePosition",
+                        (mp - *Moment::unsmob (length)).smobbed_copy ());
+  return SCM_UNSPECIFIED;
+}