]> git.donarmstrong.com Git - lilypond.git/commitdiff
Make inherited stream event properties immutable.
authorDavid Kastrup <dak@gnu.org>
Fri, 20 Jan 2012 11:01:03 +0000 (12:01 +0100)
committerDavid Kastrup <dak@gnu.org>
Sat, 21 Jan 2012 08:49:33 +0000 (09:49 +0100)
Previously, the initialization of stream events from the (mutable) part
of music event properties was done by just taking the mutable property list.
That had the effect that any changes to the inherited properties were
reflected in the originating music event, making a mockery of the
mutable/immutable distinction intended to provide copy-on-write
semantics.  As an example, the conversion of the articulations
property to events might or might not already have happened if the music
event got reported more than once, like it is done in \repeat unfold.

The change had the unexpected side effect of making quoted transposed
music fail since the transposition worked exclusively on the mutable
property list part.  This has been fixed by adding a make_transposable
member function to Stream_event that copies affected properties from
the immutable to the mutable part before one attempts transposition.

The source code has not yet been combed through for instances where
stream events have been manually cloned to avoid the bad side effects
of the original code.

lily/include/stream-event.hh
lily/music.cc
lily/quote-iterator.cc
lily/stream-event.cc

index 613b9294fbacdbad6b731d8e8287118de749d8a1..f255ab53531d4833cb3ca24e6d31d2bdfbeb2f1e 100644 (file)
@@ -30,12 +30,13 @@ public:
   Stream_event ();
   VIRTUAL_COPY_CONSTRUCTOR (Stream_event, Stream_event);
 
-  Stream_event (SCM event_class, SCM mutable_props = SCM_EOL);
+  Stream_event (SCM event_class, SCM immutable_props = SCM_EOL);
   Stream_event (SCM class_name, Input *);
 
   Input *origin () const;
   void set_spot (Input *i);
   bool internal_in_event_class (SCM class_name);
+  void make_transposable ();
 
   virtual SCM copy_mutable_properties () const;
 
index d8609ace96e2e6b56af077898edc1b0e7284a859..02dbe41499e644d184c356254933e4c1397fddfa 100644 (file)
@@ -290,8 +290,7 @@ Music::to_event () const
       for (; scm_is_pair (art_mus); art_mus = scm_cdr (art_mus))
         {
           Music *m = unsmob_music (scm_car (art_mus));
-          SCM ev = m ? m->to_event ()->unprotect () : scm_car (art_mus);
-          art_ev = scm_cons (ev, art_ev);
+          art_ev = scm_cons (m->to_event ()->unprotect (), art_ev);
         }
       e->set_property ("articulations", scm_reverse_x (art_ev, SCM_EOL));
     }
index 9c5ea78e229639937026a4303872bee0d205ffca..efb9c132e876b2dad09d6c3d4078d35c447cbb95 100644 (file)
@@ -265,6 +265,7 @@ Quote_iterator::process (Moment m)
 
                   Pitch diff = pitch_interval (qp, mp);
                   ev = ev->clone ();
+                 ev->make_transposable ();
 
                   transpose_mutable (ev->get_property_alist (true), diff);
                   transposed_musics_ = scm_cons (ev->unprotect (), transposed_musics_);
index 4b8ff7fa1e03114075c8884edd184fedf1ab5078..117559b87c52871bca8d5739b22f1dcf122265c6 100644 (file)
@@ -22,7 +22,8 @@
 #include "ly-smobs.icc"
 #include "context.hh"
 #include "input.hh"
-#include "input.hh"
+#include "music.hh"
+#include "pitch.hh"
 
 /* TODO: Rename Stream_event -> Event */
 
@@ -31,11 +32,10 @@ Stream_event::Stream_event ()
 {
 }
 
-Stream_event::Stream_event (SCM event_class, SCM mutable_props)
+Stream_event::Stream_event (SCM event_class, SCM immutable_props)
   : Prob (ly_symbol2scm ("Stream_event"),
-          scm_list_1 (scm_cons (ly_symbol2scm ("class"), event_class)))
+          scm_acons (ly_symbol2scm ("class"), event_class, immutable_props))
 {
-  mutable_property_alist_ = mutable_props;
 }
 
 Stream_event::Stream_event (SCM class_name, Input *origin)
@@ -76,6 +76,29 @@ Stream_event::internal_in_event_class (SCM class_name)
 MAKE_SCHEME_CALLBACK (Stream_event, undump, 1);
 MAKE_SCHEME_CALLBACK (Stream_event, dump, 1);
 
+void
+Stream_event::make_transposable ()
+{
+  /* This is in preparation for transposing stuff
+     that may be defined in the immutable part */
+
+  for (SCM s = immutable_property_alist_; scm_is_pair (s); s = scm_cdr (s))
+    {
+      SCM entry = scm_car (s);
+      SCM prop = scm_car (entry);
+      SCM val = scm_cdr (entry);
+
+      if ((unsmob_pitch (val)
+          || (prop == ly_symbol2scm ("element") && unsmob_music (val))
+          || (prop == ly_symbol2scm ("elements") && scm_is_pair (val))
+          || (prop == ly_symbol2scm ("pitch-alist") && scm_is_pair (val)))
+         && scm_is_false (scm_assq (prop, mutable_property_alist_)))
+       mutable_property_alist_ =
+         scm_acons (prop, ly_music_deep_copy (val), mutable_property_alist_);
+    }
+}
+
+
 SCM
 Stream_event::dump (SCM self)
 {