]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 4609/4: Move \once action from iterators to listeners
authorDavid Kastrup <dak@gnu.org>
Tue, 15 Sep 2015 18:50:13 +0000 (20:50 +0200)
committerDavid Kastrup <dak@gnu.org>
Sun, 20 Sep 2015 13:09:38 +0000 (15:09 +0200)
This ends the dependency of the events generated for \once\unset and
\once\set on the current context (bad for recording and replaying events
like with the part combiner and quoted music).  It also implements
\once\revert and makes every \once\override and \once\revert impervious
to any other overrides and reverts that may happen at the same time.

lily/context.cc
lily/engraver-group.cc
lily/include/context.hh
lily/include/property-iterator.hh
lily/property-iterator.cc

index 7e3c646a6f7e2569ea7451213e6ab9fe6b58c10c..ef6fecf4b1aa123e566d858c4a576f2c3f45951e 100644 (file)
@@ -252,7 +252,25 @@ Context::set_property_from_event (SCM sev)
       ok = type_check_assignment (sym, val, ly_symbol2scm ("translation-type?"));
 
       if (ok)
-        set_property (sym, val);
+        {
+          if (to_boolean (ev->get_property ("once")))
+            {
+              if (Global_context *g = get_global_context ())
+                {
+                  SCM old_val = SCM_UNDEFINED;
+                  if (here_defined (sym, &old_val))
+                    g->add_finalization (scm_list_4 (ly_context_set_property_x_proc,
+                                                     self_scm (),
+                                                     sym,
+                                                     old_val));
+                  else
+                    g->add_finalization (scm_list_3 (ly_context_unset_property_proc,
+                                                     self_scm (),
+                                                     sym));
+                }
+            }
+          set_property (sym, val);
+        }
     }
 }
 
@@ -262,8 +280,28 @@ Context::unset_property_from_event (SCM sev)
   Stream_event *ev = unsmob<Stream_event> (sev);
 
   SCM sym = ev->get_property ("symbol");
-  type_check_assignment (sym, SCM_EOL, ly_symbol2scm ("translation-type?"));
-  unset_property (sym);
+  bool ok = type_check_assignment (sym, SCM_EOL, ly_symbol2scm ("translation-type?"));
+
+  if (ok)
+    {
+      if (to_boolean (ev->get_property ("once")))
+        {
+          if (Global_context *g = get_global_context ())
+            {
+              SCM old_val = SCM_UNDEFINED;
+              if (here_defined (sym, &old_val))
+                g->add_finalization (scm_list_4 (ly_context_set_property_x_proc,
+                                                 self_scm (),
+                                                 sym,
+                                                 old_val));
+              else
+                g->add_finalization (scm_list_3 (ly_context_unset_property_proc,
+                                                 self_scm (),
+                                                 sym));
+            }
+        }
+      unset_property (sym);
+    }
 }
 
 /*
index c69b974a69631aba681068aaadf91bae9789fa1a..cf1832fe1fb73dd25f93e621e7a20d077485bbd0 100644 (file)
@@ -20,6 +20,7 @@
 #include "context.hh"
 #include "dispatcher.hh"
 #include "engraver-group.hh"
+#include "global-context.hh"
 #include "grob.hh"
 #include "grob-properties.hh"
 #include "paper-score.hh"
@@ -30,19 +31,48 @@ void
 Engraver_group::override (SCM sev)
 {
   Stream_event *ev = unsmob<Stream_event> (sev);
+  SCM sym = ev->get_property ("symbol");
+  Grob_property_info gpi (context (), sym);
 
-  Grob_property_info (context (), ev->get_property ("symbol"))
-    .push (ev->get_property ("property-path"),
-           ev->get_property ("value"));
+  if (to_boolean (ev->get_property ("once")))
+    {
+      SCM token = gpi.temporary_override (ev->get_property ("property-path"),
+                                          ev->get_property ("value"));
+      if (scm_is_pair (token))
+        if (Global_context *g = context ()->get_global_context ())
+          {
+            g->add_finalization (scm_list_4 (ly_context_matched_pop_property_proc,
+                                             context ()->self_scm (),
+                                             sym,
+                                             token));
+          }
+    }
+  else
+    gpi.push (ev->get_property ("property-path"),
+              ev->get_property ("value"));
 }
 
 void
 Engraver_group::revert (SCM sev)
 {
   Stream_event *ev = unsmob<Stream_event> (sev);
+  SCM sym = ev->get_property ("symbol");
+  Grob_property_info gpi (context (), sym);
 
-  Grob_property_info (context (), ev->get_property ("symbol"))
-    .pop (ev->get_property ("property-path"));
+  if (to_boolean (ev->get_property ("once")))
+    {
+      SCM token = gpi.temporary_revert (ev->get_property ("property-path"));
+      if (scm_is_pair (token))
+        if (Global_context *g = context ()->get_global_context ())
+          {
+            g->add_finalization (scm_list_4 (ly_context_matched_pop_property_proc,
+                                             context ()->self_scm (),
+                                             sym,
+                                             token));
+          }
+    }
+  else
+    gpi.pop (ev->get_property ("property-path"));
 }
 
 void
index 546152035082b302a887667aedc2018ba58f86f7..b9aa6292b67736e07150b18c04d0c8d18e385c33 100644 (file)
@@ -199,5 +199,8 @@ SCM assq_tail (SCM key, SCM alist, SCM alist_end);
 SCM assoc_tail (SCM key, SCM alist, SCM alist_end);
 SCM evict_from_alist (SCM, SCM, SCM);
 SCM nalist_to_alist (SCM nalist, int nested);
+extern SCM ly_context_set_property_x_proc;
+extern SCM ly_context_unset_property_proc;
+extern SCM ly_context_matched_pop_property_proc;
 
 #endif /* CONTEXT_HH */
index 3f9577f6f720fbb065860702255f9bb98ffcc833..984d41ef57d5b9acc60a71090ff8ac77d993fbff 100644 (file)
@@ -29,11 +29,9 @@ class Property_iterator : public Simple_music_iterator
 {
 public:
   DECLARE_SCHEME_CALLBACK (constructor, ());
-  DECLARE_SCHEME_CALLBACK (once_finalization, (SCM, SCM, SCM));
   DECLARE_CLASSNAME (Property_iterator);
 
 protected:
-  virtual void do_quit ();
   virtual void process (Moment);
 };
 
@@ -53,11 +51,9 @@ class Push_property_iterator : public Simple_music_iterator
 {
 public:
   DECLARE_SCHEME_CALLBACK (constructor, ());
-  DECLARE_SCHEME_CALLBACK (once_finalization, (SCM, SCM));
   DECLARE_CLASSNAME (Push_property_iterator);
 protected:
   virtual void process (Moment);
-  virtual void do_quit ();
 };
 
 class Pop_property_iterator : public Simple_music_iterator
index bf95ee21eb12182be6b3fec91fa5a6aeb3d15b52..4725406323e46efceef64fb788543788009c6c76 100644 (file)
@@ -35,25 +35,11 @@ Property_iterator::process (Moment mom)
 {
   Context *o = get_outlet ();
   Music *m = get_music ();
-  bool once = to_boolean (m->get_property ("once"));
-  SCM symbol = m->get_property ("symbol");
-  SCM previous_value = SCM_UNDEFINED;
-  if (once)
-    o->here_defined (symbol, &previous_value);
 
   send_stream_event (o, "SetProperty", m->origin (),
-                     ly_symbol2scm ("symbol"), symbol,
-                     ly_symbol2scm ("value"), m->get_property ("value"));
-
-  /* For \once \set install a finalization hook to reset the property to the
-   * previous value after the timestep */
-  if (once)
-    {
-      Global_context *tg = get_outlet ()->get_global_context ();
-      tg->add_finalization (scm_list_4 (once_finalization_proc,
-                                        o->self_scm (), m->self_scm (),
-                                        previous_value));
-    }
+                     ly_symbol2scm ("symbol"), m->get_property ("symbol"),
+                     ly_symbol2scm ("value"), m->get_property ("value"),
+                     ly_symbol2scm ("once"), m->get_property ("once"));
 
   Simple_music_iterator::process (mom);
 }
@@ -63,47 +49,12 @@ Property_unset_iterator::process (Moment mom)
 {
   Context *o = get_outlet ();
   Music *m = get_music ();
-  bool once = to_boolean (m->get_property ("once"));
-  SCM symbol = m->get_property ("symbol");
-  SCM previous_value = SCM_UNDEFINED;
-  if (once)
-    o->here_defined (symbol, &previous_value);
 
   send_stream_event (o, "UnsetProperty", m->origin (),
-                     ly_symbol2scm ("symbol"), symbol);
-
-  /* For \once \unset install a finalization hook to reset the property to the
-   * previous value after the timestep */
-  if (once && !SCM_UNBNDP (previous_value))
-    {
-      Global_context *tg = get_outlet ()->get_global_context ();
-      tg->add_finalization (scm_list_4 (Property_iterator::once_finalization_proc,
-                                        o->self_scm (), m->self_scm (),
-                                        previous_value));
-    }
-
-  Simple_music_iterator::process (mom);
-}
-
-MAKE_SCHEME_CALLBACK (Property_iterator, once_finalization, 3);
-SCM
-Property_iterator::once_finalization (SCM ctx, SCM music, SCM previous_value)
-{
-  Music *m = unsmob<Music> (music);
-  Context *c = unsmob<Context> (ctx);
-
-  // Do not use UnsetProperty, which sets the default, but rather
-  // cache the value before the \once \set command and restore it now
-  send_stream_event (c, "SetProperty", m->origin (),
                      ly_symbol2scm ("symbol"), m->get_property ("symbol"),
-                     ly_symbol2scm ("value"), previous_value);
-
-  return SCM_UNSPECIFIED;
-}
+                     ly_symbol2scm ("once"), m->get_property ("once"));
 
-void
-Property_iterator::do_quit ()
-{
+  Simple_music_iterator::process (mom);
 }
 
 bool
@@ -140,9 +91,10 @@ Push_property_iterator::process (Moment m)
     {
       SCM grob_property_path = get_property_path (get_music ());
       SCM val = get_music ()->get_property ("grob-value");
+      SCM once = get_music ()->get_property ("once");
 
       if (to_boolean (get_music ()->get_property ("pop-first"))
-          && !to_boolean (get_music ()->get_property ("once")))
+          && !to_boolean (once))
         send_stream_event (get_outlet (), "Revert", get_music ()->origin (),
                            ly_symbol2scm ("symbol"), sym,
                            ly_symbol2scm ("property-path"), grob_property_path);
@@ -150,58 +102,28 @@ Push_property_iterator::process (Moment m)
       send_stream_event (get_outlet (), "Override", get_music ()->origin (),
                          ly_symbol2scm ("symbol"), sym,
                          ly_symbol2scm ("property-path"), grob_property_path,
+                         ly_symbol2scm ("once"), once,
                          ly_symbol2scm ("value"), val);
     }
   Simple_music_iterator::process (m);
 }
 
-MAKE_SCHEME_CALLBACK (Push_property_iterator, once_finalization, 2);
-SCM
-Push_property_iterator::once_finalization (SCM ctx, SCM music)
-{
-  Music *mus = unsmob<Music> (music);
-  Context *c = unsmob<Context> (ctx);
-
-  SCM sym = mus->get_property ("symbol");
-  if (check_grob (mus, sym))
-    {
-      SCM grob_property_path = get_property_path (mus);
-
-      send_stream_event (c, "Revert", mus->origin (),
-                         ly_symbol2scm ("symbol"), sym,
-                         ly_symbol2scm ("property-path"), grob_property_path);
-    }
-  return SCM_UNSPECIFIED;
-}
-
 void
-Push_property_iterator::do_quit ()
+Pop_property_iterator::process (Moment mom)
 {
-  if (to_boolean (get_music ()->get_property ("once")))
-    {
-      SCM trans = get_outlet ()->self_scm ();
-      SCM music = get_music ()->self_scm ();
-
-      Global_context *tg = get_outlet ()->get_global_context ();
-      tg->add_finalization (scm_list_3 (once_finalization_proc,
-                                        trans, music));
-    }
-}
-
-void
-Pop_property_iterator::process (Moment m)
-{
-  SCM sym = get_music ()->get_property ("symbol");
+  Music *m = get_music ();
+  SCM sym = m->get_property ("symbol");
 
-  if (check_grob (get_music (), sym))
+  if (check_grob (m, sym))
     {
-      SCM grob_property_path = get_property_path (get_music ());
+      SCM grob_property_path = get_property_path (m);
 
-      send_stream_event (get_outlet (), "Revert", get_music ()->origin (),
+      send_stream_event (get_outlet (), "Revert", m->origin (),
                          ly_symbol2scm ("symbol"), sym,
+                         ly_symbol2scm ("once"), m->get_property ("once"),
                          ly_symbol2scm ("property-path"), grob_property_path);
     }
-  Simple_music_iterator::process (m);
+  Simple_music_iterator::process (mom);
 }
 
 IMPLEMENT_CTOR_CALLBACK (Pop_property_iterator);