]> git.donarmstrong.com Git - lilypond.git/commitdiff
* lily/ various: Introduce stream events of types Prepare,
authorErik Sandberg <mandolaerik@gmail.com>
Mon, 26 Jun 2006 22:11:38 +0000 (22:11 +0000)
committerErik Sandberg <mandolaerik@gmail.com>
Mon, 26 Jun 2006 22:11:38 +0000 (22:11 +0000)
OneTimeStep, CreateContext, AnnounceNewContext, RemoveContext,
ChangeContext, SetProperty, RevertProperty, Override and Revert.

* lily/global-context*.cc: Time is now -inf before iteration
starts.

* lily/include/context.hh: Removed unique_, init_

* Documentation/topdocs/NEWS: Make the feathered beam example
avoid triggering a bug.

35 files changed:
ChangeLog
Documentation/topdocs/NEWS.tely
Documentation/user/advanced-notation.itely
THANKS
lily/auto-change-iterator.cc
lily/change-iterator.cc
lily/context-def.cc
lily/context.cc
lily/dispatcher.cc
lily/engraver-group.cc
lily/global-context-scheme.cc
lily/global-context.cc
lily/include/context-def.hh
lily/include/context.hh
lily/include/engraver-group.hh
lily/include/global-context.hh
lily/include/score-engraver.hh
lily/include/score-performer.hh
lily/include/score-translator.hh
lily/include/stream-event.hh
lily/include/translator-group.hh
lily/include/translator.hh
lily/music.cc
lily/paper-column-engraver.cc
lily/part-combine-iterator.cc
lily/property-iterator.cc
lily/score-context.cc
lily/score-engraver.cc
lily/score-performer.cc
lily/score-translator.cc
lily/stream-event.cc
lily/translator-group.cc
make/lilypond-vars.make
make/lysdoc-targets.make
scm/define-event-classes.scm

index a3400ca1f3ebdb889e3f30a0f0fa09bde836a9c0..e41a15cb299cf8b2ad6d36b4dbc81e379c9766e6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2006-06-26  Erik Sandberg  <mandolaerik@gmail.com>
+
+       * lily/ various: Introduce stream events of types Prepare,
+       OneTimeStep, CreateContext, AnnounceNewContext, RemoveContext,
+       ChangeContext, SetProperty, RevertProperty, Override and Revert.
+
+       * lily/global-context*.cc: Time is now -inf before iteration
+       starts.
+
+       * lily/include/context.hh: Removed unique_, init_
+
+       * Documentation/topdocs/NEWS: Make the feathered beam example
+       avoid triggering a bug.
+
 2006-06-24  Graham Percival  <gpermus@gmail.com>
 
        * Documentation/user/ various: small additions from mailist.
index e67e068f73976f354ff6024e985f941896980b8e..925246b4dce76b4d0e02809fdac5032d396e8d3d 100644 (file)
@@ -198,10 +198,13 @@ support for feathered beaming,
   \override Beam #'grow-direction = #LEFT
   c16[
     c c c
-    c c c ]
+    c c c ]
 }
 @end lilypond 
 
+Known bug: the \featherDuration command only works with very short music
+snippets.
+
 This feature was sponsored by Jamie Bullock.
 
 @item
index 1bb72ecc824cdc5168a0464218708319090b6ac3..f446039c5c397acecf61dd1d3533424642264e0f 100644 (file)
@@ -493,12 +493,12 @@ then set the
 
 @lilypond[fragment,verbatim]
 {
-  \override Staff.TimeSignature #'font-name = #"Charter"
-  \override Staff.TimeSignature #'font-size = #2
+%  \override Staff.TimeSignature #'font-name = #"Charter"
+%  \override Staff.TimeSignature #'font-size = #2
   \time 3/4
   c'1_\markup {
-    \override #'(font-name . "Vera Bold")
-      { This text is in Vera Bold }
+%    \override #'(font-name . "Vera Bold")
+%      { This text is in Vera Bold }
   }
 }
 @end lilypond
diff --git a/THANKS b/THANKS
index 40be0a2918a7213ea3758eb8982653a17dbfa9f3..cf2c2e3361bd12c0314bf80728e677edbb88c3ef 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -54,6 +54,11 @@ David Rogers
 Francisco Vila
 Harald Wellmann
 J. Leung
+<<<<<<< THANKS
+Harald Wellmann
+Karim Haddad
+=======
+>>>>>>> 1.238
 Karl Hammar
 Keith Packard
 Mark Dewey
index f5c54f224ce37f508faa70e3a905c7d87a592b70..ade8303e0d75a5cdc639799fa58bcee6d617b541 100644 (file)
@@ -68,8 +68,9 @@ Auto_change_iterator::change_to (Music_iterator *it, SCM to_type_sym,
        {
          Context *dest
            = it->get_outlet ()->find_create_context (to_type_sym, to_id, SCM_EOL);
-         current->remove_context (last);
-         dest->add_context (last);
+         
+         send_stream_event (last, "ChangeParent", get_music ()->origin (),
+                              ly_symbol2scm ("context"), dest->self_scm ());
        }
       else
        {
@@ -90,6 +91,8 @@ Auto_change_iterator::process (Moment m)
 
   Moment now = get_outlet ()->now_mom ();
   Moment *splitm = 0;
+  if (start_moment_.main_part_.is_infinity () && start_moment_ < 0)
+    start_moment_ = now;
 
   for (; scm_is_pair (split_list_); split_list_ = scm_cdr (split_list_))
     {
index aef7567be0f74e1390b96c55e3b0438b6525b3ba..55099a855e4552cdeec205cad488e6ce86c33125 100644 (file)
@@ -74,8 +74,8 @@ Change_iterator::process (Moment m)
 
        if (dest)
          {
-           current->remove_context (last);
-           dest->add_context (last);
+           send_stream_event (last, "ChangeParent", get_music ()->origin (),
+                              ly_symbol2scm ("context"), dest->self_scm ());
          }
        else
          /* FIXME: constant error message.  */
index fee67b661d043ad86a7777039fd84c7fabc53bb4..f4ee43b1608fbfda98e673b9f648601ada5d3795 100644 (file)
 
 #include "context-def.hh"
 
-#include "engraver-group.hh"
-#include "engraver.hh"
 #include "international.hh"
 #include "output-def.hh"
-#include "performer-group.hh"
-#include "performer.hh"
 #include "score-context.hh"
-#include "translator-group.hh"
+#include "translator.hh"
 #include "warn.hh"
 
 Context_def::Context_def ()
@@ -143,12 +139,6 @@ Context_def::add_context_mod (SCM mod)
     programming_error ("unknown context mod tag");
 }
 
-SCM
-Context_def::get_context_name () const
-{
-  return context_name_;
-}
-
 SCM
 Context_def::get_accepted (SCM user_mod) const
 {
@@ -259,34 +249,6 @@ Context_def::get_translator_names (SCM user_mod) const
   return l1;
 }
 
-SCM
-filter_performers (SCM ell)
-{
-  SCM *tail = &ell;
-  for (SCM p = ell; scm_is_pair (p); p = scm_cdr (p))
-    {
-      if (dynamic_cast<Performer *> (unsmob_translator (scm_car (*tail))))
-       *tail = scm_cdr (*tail);
-      else
-       tail = SCM_CDRLOC (*tail);
-    }
-  return ell;
-}
-
-SCM
-filter_engravers (SCM ell)
-{
-  SCM *tail = &ell;
-  for (SCM p = ell; scm_is_pair (p); p = scm_cdr (p))
-    {
-      if (dynamic_cast<Engraver *> (unsmob_translator (scm_car (*tail))))
-       *tail = scm_cdr (*tail);
-      else
-       tail = SCM_CDRLOC (*tail);
-    }
-  return ell;
-}
-
 Context *
 Context_def::instantiate (SCM ops, Object_key const *key)
 {
@@ -299,55 +261,7 @@ Context_def::instantiate (SCM ops, Object_key const *key)
 
   context->definition_ = self_scm ();
   context->definition_mods_ = ops;
-
-  SCM trans_names = get_translator_names (ops);
-
-  Translator_group *g = get_translator_group (translator_group_type_);
-  SCM trans_list = SCM_EOL;
-
-  for (SCM s = trans_names; scm_is_pair (s); s = scm_cdr (s))
-    {
-      Translator *t = get_translator (scm_car (s));
-      if (!t)
-       warning (_f ("can't find: `%s'", ly_symbol2string (scm_car (s)).c_str ()));
-      else
-       {
-         Translator *tr = t->clone ();
-         SCM str = tr->self_scm ();
-
-         if (tr->must_be_last ())
-           {
-             SCM cons = scm_cons (str, SCM_EOL);
-             if (scm_is_pair (trans_list))
-               scm_set_cdr_x (scm_last_pair (trans_list), cons);
-             else
-               trans_list = cons;
-           }
-         else
-           trans_list = scm_cons (str, trans_list);
-
-         tr->daddy_context_ = context;
-         tr->unprotect ();
-       }
-    }
-
-  /*
-    Ugh,  todo: should just make a private
-    copy of Context_def with the user mods.
-  */
-
-  g->simple_trans_list_ = trans_list;
-
-  context->implementation_ = g;
-  if (dynamic_cast<Engraver_group *> (g))
-    g->simple_trans_list_ = filter_performers (g->simple_trans_list_);
-  else if (dynamic_cast<Performer_group *> (g))
-    g->simple_trans_list_ = filter_engravers (g->simple_trans_list_);
-
   context->aliases_ = context_aliases_;
-  g->connect_to_context (context);
-  g->unprotect ();
-
   context->accepts_list_ = get_accepted (ops);
 
   return context;
index 5e97a6171de24c24830548e4c141ed763d587dac..f39fb5e1c29e4e9e7e3e298dfecce272015887ef 100644 (file)
@@ -33,15 +33,15 @@ Context::check_removal ()
 {
   for (SCM p = context_list_; scm_is_pair (p); p = scm_cdr (p))
     {
-      Context *trg = unsmob_context (scm_car (p));
+      Context *ctx = unsmob_context (scm_car (p));
 
-      trg->check_removal ();
-      if (trg->is_removable ())
+      ctx->check_removal ();
+      if (ctx->is_removable ())
        {
-         recurse_over_translators (trg, &Translator::finalize,
+         recurse_over_translators (ctx, &Translator::finalize,
                                    &Translator_group::finalize,
                                    UP);
-         remove_context (trg);
+         send_stream_event (ctx, "RemoveContext", 0, 0);
        }
     }
 }
@@ -59,29 +59,13 @@ Context::properties_dict () const
 }
 
 void
-Context::add_context (Context *t)
+Context::add_context (Context *child)
 {
-  SCM ts = t->self_scm ();
   context_list_ = ly_append2 (context_list_,
-                             scm_cons (ts, SCM_EOL));
-
-  t->daddy_context_ = this;
-  if (!t->init_)
-    {
-      t->init_ = true;
-
-      t->unprotect ();
-      Context_def *td = unsmob_context_def (t->definition_);
-
-      /* This cannot move before add_context (), because \override
-        operations require that we are in the hierarchy.  */
-      td->apply_default_property_operations (t);
+                             scm_cons (child->self_scm (), SCM_EOL));
 
-      recurse_over_translators (t,
-                               &Translator::initialize,
-                               &Translator_group::initialize,
-                               DOWN);
-    }
+  child->daddy_context_ = this;
+  this->events_below_->register_as_listener (child->events_below_);
 }
 
 
@@ -89,7 +73,6 @@ Context::Context (Object_key const *key)
   : key_manager_ (key)
 {
   daddy_context_ = 0;
-  init_ = false;
   aliases_ = SCM_EOL;
   iterator_count_ = 0;
   implementation_ = 0;
@@ -98,7 +81,6 @@ Context::Context (Object_key const *key)
   context_list_ = SCM_EOL;
   definition_ = SCM_EOL;
   definition_mods_ = SCM_EOL;
-  unique_ = -1;
   event_source_ = 0;
   events_below_ = 0;
 
@@ -235,36 +217,142 @@ Context::find_create_context (SCM n, string id, SCM operations)
   return ret;
 }
 
-Context *
-Context::create_context (Context_def *cdef,
-                        string id,
-                        SCM ops)
+IMPLEMENT_LISTENER (Context, acknowledge_infant);
+void
+Context::acknowledge_infant (SCM sev)
+{
+  infant_event_ = unsmob_stream_event (sev);
+}
+
+IMPLEMENT_LISTENER (Context, set_property_from_event);
+void
+Context::set_property_from_event (SCM sev)
 {
-  int unique = get_global_context()->new_unique();
+  Stream_event *ev = unsmob_stream_event (sev);
+  
+  SCM sym = ev->get_property ("symbol");
+  if (scm_is_symbol (sym))
+    {
+      SCM val = ev->get_property ("value");
+      bool ok = true;
+      if (val != SCM_EOL)
+       ok = type_check_assignment (sym, val, ly_symbol2scm ("translation-type?"));
+      if (ok)
+       internal_set_property (sym, val);
+    }
+}
 
-  // TODO: The following should be carried out by a listener.
-  string type = ly_symbol2string (cdef->get_context_name ());
+IMPLEMENT_LISTENER (Context, unset_property_from_event);
+void
+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);
+}
+
+/*
+  Creates a new context from a CreateContext event, and sends an
+  AnnounceNewContext event to this context.
+*/
+IMPLEMENT_LISTENER (Context, create_context_from_event);
+void
+Context::create_context_from_event (SCM sev)
+{
+  Stream_event *ev = unsmob_stream_event (sev);
+  
+  string id = ly_scm2string (ev->get_property ("id"));
+  SCM ops = ev->get_property ("ops");
+  SCM type_scm = ev->get_property ("type");
+  string type = ly_symbol2string (type_scm);
   Object_key const *key = key_manager_.get_context_key (now_mom(), type, id);
-  Context *new_context
-    = cdef->instantiate (ops, key);
+  
+  vector<Context_def*> path
+    = unsmob_context_def (definition_)->path_to_acceptable_context (type_scm, get_output_def ());
+  if (path.size () != 1)
+    {
+      programming_error (_f ("Invalid CreateContext event: Cannot create %s context", type.c_str ()));
+      return;
+    }
+  Context_def *cdef = path[0];
+  
+  Context *new_context = cdef->instantiate (ops, key);
 
   new_context->id_string_ = id;
-  new_context->unique_ = unique;
   
+  /* Register various listeners:
+      - Make the new context hear events that universally affect contexts
+      - connect events_below etc. properly */
+  /* We want to be the first ones to hear our own events. Therefore, wait
+     before registering events_below_ */
+  new_context->event_source ()->
+    add_listener (GET_LISTENER (new_context->create_context_from_event),
+                  ly_symbol2scm ("CreateContext"));
+  new_context->event_source ()->
+    add_listener (GET_LISTENER (new_context->remove_context),
+                  ly_symbol2scm ("RemoveContext"));
+  new_context->event_source ()->
+    add_listener (GET_LISTENER (new_context->change_parent),
+                  ly_symbol2scm ("ChangeParent"));
+  new_context->event_source ()->
+    add_listener (GET_LISTENER (new_context->set_property_from_event),
+                  ly_symbol2scm ("SetProperty"));
+  new_context->event_source ()->
+    add_listener (GET_LISTENER (new_context->unset_property_from_event),
+                  ly_symbol2scm ("UnsetProperty"));
+
   new_context->events_below_->register_as_listener (new_context->event_source_);
-  
-  add_context (new_context);
+  this->add_context (new_context);
+
+  new_context->unprotect ();
+
+  Context_def *td = unsmob_context_def (new_context->definition_);
+
+  /* This cannot move before add_context (), because \override
+     operations require that we are in the hierarchy.  */
+  td->apply_default_property_operations (new_context);
   apply_property_operations (new_context, ops);
-  events_below_->register_as_listener (new_context->events_below_);
 
-  // TODO: The above operations should be performed by a listener to the following event.
-  send_stream_event (this, "CreateContext",
-                     ly_symbol2scm ("unique"), scm_int2num (unique),
+  send_stream_event (this, "AnnounceNewContext", 0,
+                    ly_symbol2scm ("context"), new_context->self_scm (),
+                    ly_symbol2scm ("creator"), sev);
+}
+
+Context *
+Context::create_context (Context_def *cdef,
+                        string id,
+                        SCM ops)
+{
+  infant_event_ = 0;
+  /* TODO: This is fairly misplaced. We can fix this when we have taken out all
+     iterator specific stuff from the Context class */
+  event_source_->
+    add_listener (GET_LISTENER (acknowledge_infant),
+                  ly_symbol2scm ("AnnounceNewContext"));
+  /* The CreateContext creates a new context, and sends an announcement of the
+     new context through another event. That event will be stored in
+     infant_event_ to create a return value. */
+  send_stream_event (this, "CreateContext", 0,
                      ly_symbol2scm ("ops"), ops,
                      ly_symbol2scm ("type"), cdef->get_context_name (),
                      ly_symbol2scm ("id"), scm_makfrom0str (id.c_str ()));
+  event_source_->
+    remove_listener (GET_LISTENER (acknowledge_infant),
+                     ly_symbol2scm ("AnnounceNewContext"));
+
+  assert (infant_event_);
+  SCM infant_scm = infant_event_->get_property ("context");
+  Context *infant = unsmob_context (infant_scm);
 
-  return new_context;
+  if (!infant || infant->get_parent_context () != this)
+    {
+      programming_error ("create_context: can't locate newly created context");
+      return 0;
+    }
+
+  return infant;
 }
 
 /*
@@ -351,9 +439,9 @@ properties and corresponding values, interleaved. This method should not
 be called from any other place than the send_stream_event macro.
 */
 void
-Context::internal_send_stream_event (SCM type, SCM props[])
+Context::internal_send_stream_event (SCM type, Input *origin, SCM props[])
 {
-  Stream_event *e = new Stream_event (this, type);
+  Stream_event *e = new Stream_event (type, origin);
   for (int i = 0; props[i]; i += 2)
     {
       e->internal_set_property (props[i], props[i+1]);
@@ -400,19 +488,36 @@ Context::unset_property (SCM sym)
   properties_dict ()->remove (sym);
 }
 
-/**
-   Remove a context from the hierarchy.
-*/
-Context *
-Context::remove_context (Context *trans)
+IMPLEMENT_LISTENER (Context, change_parent);
+void
+Context::change_parent (SCM sev)
 {
-  assert (trans);
+  Stream_event *ev = unsmob_stream_event (sev);
+  Context *to = unsmob_context (ev->get_property ("context"));
 
-  context_list_ = scm_delq_x (trans->self_scm (), context_list_);
-  trans->daddy_context_ = 0;
-  return trans;
+  disconnect_from_parent ();
+  to->add_context (this);
+}
+
+/*
+  Die. The next GC sweep should take care of the actual death.
+ */
+IMPLEMENT_LISTENER (Context, remove_context);
+void
+Context::remove_context (SCM)
+{
+  /* ugh, the translator group should listen to RemoveContext events by itself */
+  implementation ()->disconnect_from_context ();
+  disconnect_from_parent ();
 }
 
+void
+Context::disconnect_from_parent ()
+{
+  daddy_context_->events_below_->unregister_as_listener (this->events_below_);
+  daddy_context_->context_list_ = scm_delq_x (this->self_scm (), daddy_context_->context_list_);
+  daddy_context_ = 0;
+}
 
 /*
   ID == "" means accept any ID.
@@ -439,25 +544,6 @@ find_context_below (Context *where,
   return found;
 }
 
-Context *
-find_context_below (Context *where,
-                    int unique)
-{
-  if (where->get_unique () == unique)
-    return where;
-
-  Context *found = 0;
-  for (SCM s = where->children_contexts ();
-       !found && scm_is_pair (s); s = scm_cdr (s))
-    {
-      Context *tr = unsmob_context (scm_car (s));
-
-      found = find_context_below (tr, unique);
-    }
-
-  return found;
-}
-
 SCM
 Context::properties_as_alist () const
 {
index e66f0952cb69456cbf2e61b328cc8e474cf6fcb3..ce6f2b71018c00fd05000365ccca3efd8adab187 100644 (file)
@@ -7,6 +7,7 @@
 */
 
 #include "dispatcher.hh"
+#include "input.hh"
 #include "international.hh"
 #include "ly-smobs.icc"
 #include "stream-event.hh"
@@ -72,11 +73,16 @@ Dispatcher::dispatch (SCM sev)
   SCM class_symbol = ev->get_property ("class");
   if (!scm_symbol_p (class_symbol))
     {
-      warning (_f ("Unknown event class %s", ly_symbol2string (class_symbol).c_str ()));
+      warning (_f ("Event class should be a symbol"));
       return;
     }
 
   SCM class_list = scm_call_1 (ly_lily_module_constant ("ly:make-event-class"), class_symbol);
+  if (!scm_is_pair (class_list))
+    {
+      ev->origin ()->warning (_f ("Unknown event class %s", ly_symbol2string (class_symbol).c_str ()));
+      return;
+    }
   bool sent = false;
   int num_classes = scm_ilength (class_list);
 
@@ -171,9 +177,10 @@ inline void
 Dispatcher::internal_add_listener (Listener l, SCM ev_class, int priority)
 {
   SCM list = scm_hashq_ref (listeners_, ev_class, SCM_EOL);
-  if (list == SCM_EOL)
+  if (!scm_is_pair (list))
     {
-      /* Register with all dispatchers. */
+      /* Tell all dispatchers that we listen to, that we want to hear ev_class 
+         events */
       for (SCM disp = dispatchers_; scm_is_pair(disp); disp = scm_cdr (disp))
        {
          int priority = scm_to_int (scm_cdar (disp));
@@ -183,7 +190,7 @@ Dispatcher::internal_add_listener (Listener l, SCM ev_class, int priority)
       listen_classes_ = scm_cons (ev_class, listen_classes_);
     }
   SCM entry = scm_cons (scm_int2num (priority), l.smobbed_copy ());
-  list = scm_merge_x (list, scm_list_1 (entry), ly_lily_module_constant ("car<"));
+  list = scm_merge (list, scm_list_1 (entry), ly_lily_module_constant ("car<"));
   scm_hashq_set_x (listeners_, ev_class, list);
 }
 
@@ -213,10 +220,11 @@ Dispatcher::remove_listener (Listener l, SCM ev_class)
     else
       e = scm_cdr (e);
   list = scm_cdr (dummy);
+  scm_hashq_set_x (listeners_, ev_class, list);
 
   if (first)
     warning ("Attempting to remove nonexisting listener.");
-  else if (list == SCM_EOL)
+  else if (!scm_is_pair (list))
     {
       /* Unregister with all dispatchers. */
       for (SCM disp = dispatchers_; disp != SCM_EOL; disp = scm_cdr (disp))
@@ -256,9 +264,9 @@ Dispatcher::unregister_as_listener (Dispatcher *disp)
 {
   dispatchers_ = scm_assq_remove_x (dispatchers_, disp->self_scm ());
 
-  Listener list = GET_LISTENER (dispatch);
-  for (SCM cl = listen_classes_; cl != SCM_EOL; cl = scm_cdr (cl))
+  Listener listener = GET_LISTENER (dispatch);
+  for (SCM cl = listen_classes_; scm_is_pair (cl); cl = scm_cdr (cl))
     {
-      disp->remove_listener (list, scm_car (cl));
+      disp->remove_listener (listener, scm_car (cl));
     }
 }
index 71533cd116cd8e353d853285578ed287fc3344c6..6271d93979b729b97fea32db94b7e96df56d5ba9 100644 (file)
@@ -6,13 +6,54 @@
   (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
 */
 
+#include "context.hh"
+#include "dispatcher.hh"
 #include "engraver-group.hh"
-
-#include "warn.hh"
-#include "paper-score.hh"
 #include "grob.hh"
-#include "context.hh"
+#include "paper-score.hh"
+#include "stream-event.hh"
 #include "translator-dispatch-list.hh"
+#include "warn.hh"
+
+IMPLEMENT_LISTENER (Engraver_group, override);
+void
+Engraver_group::override (SCM sev)
+{
+  Stream_event *ev = unsmob_stream_event (sev);
+  
+  execute_general_pushpop_property (context (),
+                                   ev->get_property ("symbol"),
+                                   ev->get_property ("property-path"),
+                                   ev->get_property ("value"));
+}
+
+IMPLEMENT_LISTENER (Engraver_group, revert);
+void
+Engraver_group::revert (SCM sev)
+{
+  Stream_event *ev = unsmob_stream_event (sev);
+  
+  execute_general_pushpop_property (context (),
+                                   ev->get_property ("symbol"),
+                                   ev->get_property ("property-path"),
+                                   SCM_UNDEFINED);
+}
+
+void
+Engraver_group::connect_to_context (Context *c)
+{
+  Translator_group::connect_to_context (c);
+  c->event_source ()->add_listener (GET_LISTENER (override), ly_symbol2scm ("Override"));
+  c->event_source ()->add_listener (GET_LISTENER (revert), ly_symbol2scm ("Revert"));
+}
+
+void
+Engraver_group::disconnect_from_context ()
+{
+  context ()->event_source ()->remove_listener (GET_LISTENER (override), ly_symbol2scm ("Override"));
+  context ()->event_source ()->remove_listener (GET_LISTENER (revert), ly_symbol2scm ("Revert"));
+  Translator_group::disconnect_from_context ();
+}
 
 void
 Engraver_group::announce_grob (Grob_info info)
index 7eb5fb224aa67003a08b06fed3d10c588c58958e..9229a8a0d956d8124cfd83aa671cbfb185f08d7a 100644 (file)
@@ -15,6 +15,7 @@
 #include "music.hh"
 #include "object-key.hh"
 #include "output-def.hh"
+#include "translator-group.hh"
 #include "warn.hh"
 
 LY_DEFINE (ly_format_output, "ly:format-output",
@@ -31,6 +32,21 @@ LY_DEFINE (ly_format_output, "ly:format-output",
   return output;
 }
 
+LY_DEFINE (ly_make_global_translator, "ly:make-global-translator",
+          1, 0, 0, (SCM global),
+          "Create a translator group and connect it to the global context\n"
+          "@var{global}. The translator group is returned.")
+{
+  Global_context *g = dynamic_cast<Global_context *> (unsmob_context (global));
+  SCM_ASSERT_TYPE (g, global, SCM_ARG1, __FUNCTION__, "Global context");
+
+  Translator_group *tg = new Translator_group ();
+  tg->connect_to_context (g);
+  g->implementation_ = tg;
+
+  return tg->unprotect ();
+}
+
 LY_DEFINE (ly_run_translator, "ly:run-translator",
           2, 1, 0, (SCM mus, SCM output_def, SCM key),
           "Process @var{mus} according to @var{output_def}. \n"
@@ -57,19 +73,21 @@ LY_DEFINE (ly_run_translator, "ly:run-translator",
 
   Cpu_timer timer;
 
-  Global_context *trans = new Global_context (odef, music->get_length (),
-                                             unsmob_key (key));
-  if (!trans)
+  Global_context *glob = new Global_context (odef, unsmob_key (key));
+  if (!glob)
     {
-      programming_error ("no toplevel translator");
+      programming_error ("Couldn't create Global context");
       return SCM_BOOL_F;
     }
 
+  SCM tgs = ly_make_global_translator (glob->self_scm ());
+  Translator_group *tg = unsmob_translator_group (tgs);
+
   message (_ ("Interpreting music... "));
 
   SCM protected_iter = Music_iterator::get_static_get_iterator (music);
   Music_iterator *iter = unsmob_iterator (protected_iter);
-  iter->init_translator (music, trans);
+  iter->init_translator (music, glob);
   iter->construct_children ();
 
   if (!iter->ok ())
@@ -79,13 +97,13 @@ LY_DEFINE (ly_run_translator, "ly:run-translator",
       return SCM_BOOL_F;
     }
 
-  trans->run_iterator_on_me (iter);
+  glob->run_iterator_on_me (iter);
   iter->quit ();
   scm_remember_upto_here_1 (protected_iter);
-  trans->finish ();
+  send_stream_event (glob, "Finish", 0, 0);
 
   if (be_verbose_global)
     message (_f ("elapsed time: %.2f seconds", timer.read ()));
 
-  return trans->unprotect ();
+  return glob->unprotect ();
 }
index 6e2d26a58a2fceb00cafeb3cb767b5c16f88395f..94f354763071d3d8700d5c432ef55f1ba2d9c18d 100644 (file)
 using namespace std;
 
 #include "context-def.hh"
+#include "dispatcher.hh"
 #include "international.hh"
 #include "lilypond-key.hh"
 #include "music-iterator.hh"
 #include "music.hh"
 #include "output-def.hh"
 #include "score-context.hh"
+#include "stream-event.hh"
 #include "warn.hh"
 
-Global_context::Global_context (Output_def *o, Moment final, Object_key *key)
+Global_context::Global_context (Output_def *o, Object_key *key)
   : Context (new Lilypond_context_key (key,
                                       Moment (0),
                                       "Global", "", 0))
 {
   output_def_ = o;
-  final_mom_ = final;
   definition_ = find_context_def (o, ly_symbol2scm ("Global"));
-  unique_count_ = 0;
-  unique_ = 0;
+
+  now_mom_.set_infinite (-1);
+  prev_mom_.set_infinite (-1);
+
+  /* We only need the most basic stuff to bootstrap the context tree */
+  event_source ()->add_listener (GET_LISTENER (create_context_from_event),
+                                ly_symbol2scm ("CreateContext"));
+  event_source ()->add_listener (GET_LISTENER (prepare),
+                                ly_symbol2scm ("Prepare"));
+  events_below ()->register_as_listener (event_source_);
 
   Context_def *globaldef = unsmob_context_def (definition_);
   if (!globaldef)
@@ -48,9 +57,6 @@ Global_context::get_output_def () const
 void
 Global_context::add_moment_to_process (Moment m)
 {
-  if (m > final_mom_)
-    return;
-
   if (m < now_mom_)
     programming_error ("trying to freeze in time");
 
@@ -74,15 +80,26 @@ Global_context::get_moments_left () const
   return extra_mom_pq_.size ();
 }
 
+IMPLEMENT_LISTENER (Global_context, prepare);
 void
-Global_context::prepare (Moment m)
+Global_context::prepare (SCM sev)
 {
-  prev_mom_ = now_mom_;
-  now_mom_ = m;
+  Stream_event *ev = unsmob_stream_event (sev);
+  Moment *mom = unsmob_moment (ev->get_property ("moment"));
 
+  assert (mom);
+
+  if (prev_mom_.main_part_.is_infinity () && prev_mom_ < 0)
+    prev_mom_ = *mom;
+  else
+    prev_mom_ = now_mom_;
+  now_mom_ = *mom;
+  
   clear_key_disambiguations ();
+
+  // should do nothing now
   if (get_score_context ())
-    get_score_context ()->prepare (m);
+    get_score_context ()->prepare (now_mom_);
 }
 
 Moment
@@ -109,8 +126,6 @@ void
 Global_context::one_time_step ()
 {
   get_score_context ()->one_time_step ();
-  apply_finalizations ();
-  check_removal ();
 }
 
 void
@@ -123,8 +138,9 @@ Global_context::finish ()
 void
 Global_context::run_iterator_on_me (Music_iterator *iter)
 {
-  if (iter->ok ())
-    prev_mom_ = now_mom_ = iter->pending_moment ();
+  prev_mom_.set_infinite (-1);
+  now_mom_.set_infinite (-1);
+  Moment final_mom = iter->get_music ()->get_length ();
 
   bool first = true;
   while (iter->ok () || get_moments_left ())
@@ -135,7 +151,7 @@ Global_context::run_iterator_on_me (Music_iterator *iter)
        w = iter->pending_moment ();
 
       w = sneaky_insert_extra_moment (w);
-      if (w.main_part_.is_infinity ())
+      if (w.main_part_.is_infinity () || w > final_mom)
        break;
 
       if (first)
@@ -147,13 +163,15 @@ Global_context::run_iterator_on_me (Music_iterator *iter)
          set_property ("measurePosition", w.smobbed_copy ());
        }
 
-      prepare (w);
+      send_stream_event (this, "Prepare", 0,
+                        ly_symbol2scm ("moment"), w.smobbed_copy ());
 
       if (iter->ok ())
        iter->process (w);
 
       if (!get_score_context ())
        {
+         error ("ES TODO: no score context, this shouldn't happen");
          SCM sym = ly_symbol2scm ("Score");
          Context_def *t = unsmob_context_def (find_context_def (get_output_def (),
                                                                 sym));
@@ -168,7 +186,9 @@ Global_context::run_iterator_on_me (Music_iterator *iter)
          sc->prepare (w);
        }
 
-      one_time_step ();
+      send_stream_event (this, "OneTimeStep", 0, 0);
+      apply_finalizations ();
+      check_removal ();
     }
 }
 
@@ -206,9 +226,3 @@ Global_context::get_default_interpreter ()
   else
     return Context::get_default_interpreter ();
 }
-
-int
-Global_context::new_unique ()
-{
-  return ++unique_count_;
-}
index 8f5ba8686d02f8a56d98126a6c724c43cd39d397..df69f257dd6f1a62bfec6ab46a2901bc22cbb087 100644 (file)
@@ -36,10 +36,11 @@ private:
 public:
   void add_context_mod (SCM);
   SCM get_default_child (SCM user_mods) const;
-  SCM get_context_name () const;
+  SCM get_context_name () const { return context_name_; }
   SCM get_accepted (SCM user_mods) const;
   SCM get_property_ops () const { return property_ops_; }
   SCM get_translator_names (SCM) const;
+  SCM get_translator_group_type () const { return translator_group_type_; }
   void set_acceptor (SCM accepts, bool add);
 
   vector<Context_def*> path_to_acceptable_context (SCM type_string,
index 5a7eb92687a522dd0f1f7043f0edf6cabd223341..eaa280ff588d8e63315675a4030d89735516f69b 100644 (file)
@@ -9,12 +9,12 @@
 #ifndef CONTEXT_HH
 #define CONTEXT_HH
 
-
-#include "std-vector.hh"
-#include "moment.hh"
+#include "context-key-manager.hh"
 #include "lily-proto.hh"
+#include "listener.hh"
+#include "moment.hh"
+#include "std-vector.hh"
 #include "virtual-methods.hh"
-#include "context-key-manager.hh"
 
 class Context
 {
@@ -28,10 +28,11 @@ class Context
 private:
   friend class Context_handle;
   int iterator_count_;
-  bool init_;
+  
+  /* Used internally by create_context */
+  Stream_event *infant_event_;
 
 protected:
-  int unique_;
   Context *daddy_context_;
   /* The used Context_def */
   SCM definition_;
@@ -53,23 +54,28 @@ protected:
      children, are sent to this dispatcher. */
   Dispatcher *events_below_;
 
+  // Translator_group is allowed to set implementation_.
+  friend class Translator_group;
+  // Context_def::instantiate initialises some protected members.
   friend class Context_def;
+  // UGH! initialises implementation_
+  friend SCM ly_make_global_translator (SCM);
   void clear_key_disambiguations ();
 
+  DECLARE_LISTENER (set_property_from_event);
+  DECLARE_LISTENER (unset_property_from_event);
   
 public:
   Object_key const *get_grob_key (string name);
   Object_key const *get_context_key (string name, string id);
 
-  Context *create_context (Context_def *, string, SCM);
   string id_string () const { return id_string_; }
   SCM children_contexts () const { return context_list_; }
   SCM default_child_context_name () const;
-  int get_unique() { return unique_; }
 
   Dispatcher *event_source () const { return event_source_; }
   Dispatcher *events_below () const { return events_below_; }
-  void internal_send_stream_event (SCM type, SCM props[]);
+  void internal_send_stream_event (SCM type, Input *origin, SCM props[]);
 
   SCM get_definition () const { return definition_; }
   SCM get_definition_mods () const { return definition_mods_; }
@@ -85,7 +91,12 @@ public:
   Context *where_defined (SCM name_sym, SCM *value) const;
   void unset_property (SCM var_sym);
 
-  Context *remove_context (Context *trans);
+  Context *create_context (Context_def *, string, SCM);
+  DECLARE_LISTENER (create_context_from_event);
+  DECLARE_LISTENER (acknowledge_infant);
+  DECLARE_LISTENER (remove_context);
+  DECLARE_LISTENER (change_parent);
+  void disconnect_from_parent ();
   void check_removal ();
   string context_name () const;
   SCM context_name_symbol () const;
@@ -134,10 +145,10 @@ Rational measure_length (Context const *context);
 void set_context_property_on_children (Context *trans, SCM sym, SCM val);
 
 /* Shorthand for creating and broadcasting stream events. */
-#define send_stream_event(ctx, type, ...)                              \
+#define send_stream_event(ctx, type, origin, ...)                              \
 {                                                                      \
   SCM props[] = { __VA_ARGS__, 0 };                                    \
-  ctx->internal_send_stream_event (ly_symbol2scm (type), props);       \
+  ctx->internal_send_stream_event (ly_symbol2scm (type), origin, props);       \
 }
 
 #endif /* CONTEXT_HH */
index d1df4cffb37c39008cb27d295c8289768ecbab72..938fde04923ed41ed11e9ee70f54433f384cff3f 100644 (file)
@@ -17,12 +17,15 @@ class Engraver_group : public virtual Translator_group
 protected:
   vector<Grob_info> announce_infos_;
   Drul_array<SCM> acknowledge_hash_table_drul_;
-
+  DECLARE_LISTENER (override);
+  DECLARE_LISTENER (revert);
 public:
   VIRTUAL_COPY_CONSTRUCTOR (Translator_group, Engraver_group);
   Engraver_group ();
   virtual void derived_mark () const;
   void do_announces ();
+  virtual void connect_to_context (Context *c);
+  virtual void disconnect_from_context ();
   virtual void announce_grob (Grob_info);
   int pending_grob_count () const;
 private:
index cc87ff3c9bb3e18fcca49c55144355962f219119..0ff225c50d38ec96e5385de723a09d6e9e0d5091 100644 (file)
@@ -16,13 +16,12 @@ class Global_context : public virtual Context
 {
   PQueue<Moment> extra_mom_pq_;
   Output_def *output_def_;
-  int unique_count_;
 
   DECLARE_CLASSNAME(Global_context);
 
   friend class Output_def;
 public:
-  Global_context (Output_def *, Moment final, Object_key *key);
+  Global_context (Output_def *, Object_key *key);
   int get_moments_left () const;
   Moment sneaky_insert_extra_moment (Moment);
   void add_moment_to_process (Moment);
@@ -32,18 +31,16 @@ public:
   void apply_finalizations ();
   void add_finalization (SCM);
 
-  virtual SCM get_output ();
-  virtual void prepare (Moment);
+  DECLARE_LISTENER (prepare);
   virtual void one_time_step ();
   virtual void finish ();
+  virtual SCM get_output ();
   virtual Output_def *get_output_def () const;
   virtual Moment now_mom () const;
   virtual Context *get_default_interpreter ();
 
-  int new_unique ();
   Moment previous_moment () const;
 protected:
-  Moment final_mom_;
   Moment prev_mom_;
   Moment now_mom_;
 };
index 76571145367474c2e03ba6d68168656967222f8c..b3127f8977784a8ea111b942d9a6a048a9d838cc 100644 (file)
@@ -23,12 +23,13 @@ class Score_engraver : public virtual Score_translator,
   void typeset_all ();
 
 protected:
-  /* Score_translator */
-  virtual void finish ();
-  virtual void prepare (Moment);
-  virtual void one_time_step ();
+  DECLARE_LISTENER (finish);
+  DECLARE_LISTENER (prepare);
+  DECLARE_LISTENER (one_time_step);
 
   /* Engraver_group_engraver interface */
+  virtual void connect_to_context (Context *);
+  virtual void disconnect_from_context ();
   virtual bool try_music (Music *);
   virtual void initialize ();
   virtual void finalize ();
index e38f430c62ed679415addf4cb6f5020876d1225f..f98dd18dd549be2ceb72a436db41361838f4bf97 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef SCORE_PERFORMER_HH
 #define SCORE_PERFORMER_HH
 
+#include "moment.hh"
 #include "performer-group.hh"
 #include "score-translator.hh"
 
@@ -24,9 +25,13 @@ public:
 
   Score_performer ();
 protected:
-  virtual void prepare (Moment mom);
-  virtual void finish ();
-  virtual void one_time_step ();
+  DECLARE_LISTENER (finish);
+  DECLARE_LISTENER (prepare);
+  DECLARE_LISTENER (one_time_step);
+
+  /* Engraver_group_engraver interface */
+  virtual void connect_to_context (Context *);
+  virtual void disconnect_from_context ();
   virtual void initialize ();
   virtual void announce_element (Audio_element_info);
   virtual int get_tempo () const;
index b74fb0fe22a565218b5aa0f3ee169ff8440501a9..01ee9e3ad057a44578ff8cfab99e1b5b60465d8f 100644 (file)
@@ -16,9 +16,6 @@ class Score_translator : public virtual Translator_group
   friend class Score_context;
 protected:
   virtual SCM get_output ();
-  virtual void prepare (Moment);
-  virtual void finish ();
-  virtual void one_time_step ();
 };
 
 #endif /* SCORE_TRANSLATOR_HH */
index 13535c73f6ecd1826db46bf0e23eb2b4b5ed9569..f2d5a960363e5ffeaadce96bc6fa5fe39c45d248 100644 (file)
@@ -22,14 +22,14 @@ class Stream_event
 public:
   Stream_event ();
   Input *origin () const;
+  void set_spot (Input *i);
 
   DECLARE_SCHEME_CALLBACK (undump, (SCM));
   DECLARE_SCHEME_CALLBACK (dump, (SCM));
 
-  // todo: make Input mandatory.
+  // todo: remove unneeded constructors
   Stream_event (SCM property_alist);
-  Stream_event (Context *c, SCM class_name);
-  Stream_event (Context *c, Input *);
+  Stream_event (SCM class_name, Input *);
   Stream_event (Stream_event *ev);
 
   SCM internal_get_property (SCM) const;
index 3bb6b4255f8787cb0d2493a7890dc9e6c09199eb..1c8f91ce454370eeb92377949dec337b986d74f6 100644 (file)
@@ -47,6 +47,7 @@ private:
   Translator_group_void_method
   precomputed_self_method_bindings_[TRANSLATOR_METHOD_PRECOMPUTE_COUNT];
 
+  DECLARE_LISTENER (create_child_translator);
   DECLARE_LISTENER (eat_event);
 
 public:
@@ -54,7 +55,8 @@ public:
   DECLARE_SMOBS (Translator_group, dummy);
 
 public:
-  void connect_to_context (Context *c);
+  virtual void connect_to_context (Context *c);
+  virtual void disconnect_from_context ();
   virtual Translator_group *get_daddy_translator ()const;
   virtual SCM get_simple_trans_list ();
   virtual bool try_music (Music *req);
index 398a32ce063bc76593d0b49518dc12b3d5b257d3..f6b3c8881936de24e34292e515a69ae2fc3154e5 100644 (file)
@@ -99,8 +99,7 @@ protected:                    // should be private.
   Context *daddy_context_;
   virtual void derived_mark () const;
 
-  friend class Context_def;
-  friend class Context;
+  friend class Translator_group;
 };
 void add_translator (Translator *trans);
 
index 02a9876b1c2f6779f1df43b5ff11b63170bf4293..56b6998820c821c2a4a2917a5090cd60aca92a44 100644 (file)
@@ -239,7 +239,7 @@ Music::origin () const
 void
 Music::send_to_context (Context *c)
 {
-  send_stream_event (c, "MusicEvent",
+  send_stream_event (c, "MusicEvent", origin (),
                     ly_symbol2scm("music"), self_scm (), 0);
 }
 
index 7bc7c665ac1798d978ee09c17e248965c2bf4952..cef0f9e5c055659010f63a2d3afaba9953f4d770 100644 (file)
@@ -53,10 +53,11 @@ Paper_column_engraver::make_columns ()
   */
   Paper_column *p1 = make_paper_column ("NonMusicalPaperColumn");
   Paper_column *p2 = make_paper_column ("PaperColumn");
-
-  SCM m = now_mom ().smobbed_copy ();
-  p1->set_property ("when", m);
-  p2->set_property ("when", m);
+  /* 
+     The columns are timestamped with now_mom () in
+     stop_translation_timestep. Cannot happen now, because the
+     first column is sometimes created before now_mom is initialised.
+  */
 
   set_columns (p1, p2);
 }
@@ -172,6 +173,10 @@ Paper_column_engraver::process_music ()
 void
 Paper_column_engraver::stop_translation_timestep ()
 {
+  SCM m = now_mom ().smobbed_copy ();
+  command_column_->set_property ("when", m);
+  musical_column_->set_property ("when", m);
+
   for (vsize i = 0; i < items_.size (); i++)
     {
       Item *elem = items_[i];
index 65c7f1aac987a682b4873b37cda8463b00867f48..6f07a67be78ecdc5d256da172d980b5f03fe1629 100644 (file)
@@ -424,6 +424,11 @@ Part_combine_iterator::process (Moment m)
   Moment now = get_outlet ()->now_mom ();
   Moment *splitm = 0;
 
+  /* This is needed if construct_children was called before iteration
+     started */
+  if (start_moment_.main_part_.is_infinity () && start_moment_ < 0)
+    start_moment_ = now;
+
   for (; scm_is_pair (split_list_); split_list_ = scm_cdr (split_list_))
     {
       splitm = unsmob_moment (scm_caar (split_list_));
index a4c993b75644a943fa5ce77255385bf71793c367..cfa6fb62861cf66f3e641e386e71100cea0fe3a6 100644 (file)
@@ -22,16 +22,10 @@ bool check_grob (Music *mus, SCM sym);
 void
 Property_iterator::process (Moment m)
 {
-  SCM sym = get_music ()->get_property ("symbol");
-  if (scm_is_symbol (sym))
-    {
-      SCM val = get_music ()->get_property ("value");
-      bool ok = true;
-      if (val != SCM_EOL)
-       ok = type_check_assignment (sym, val, ly_symbol2scm ("translation-type?"));
-      if (ok)
-       get_outlet ()->internal_set_property (sym, val);
-    }
+  send_stream_event (get_outlet (), "SetProperty", get_music ()->origin (),
+                    ly_symbol2scm ("symbol"), get_music ()->get_property ("symbol"),
+                    ly_symbol2scm ("value"), get_music ()->get_property ("value"));
+  
   Simple_music_iterator::process (m);
 }
 
@@ -39,22 +33,21 @@ void
 Property_unset_iterator::process (Moment m)
 {
   SCM sym = get_music ()->get_property ("symbol");
-  type_check_assignment (sym, SCM_EOL, ly_symbol2scm ("translation-type?"));
-  get_outlet ()->unset_property (sym);
+  send_stream_event (get_outlet (), "UnsetProperty", get_music ()->origin (),
+                    ly_symbol2scm ("symbol"), sym);
 
   Simple_music_iterator::process (m);
 }
 
 MAKE_SCHEME_CALLBACK (Property_iterator, once_finalization, 2);
 SCM
-Property_iterator::once_finalization (SCM translator, SCM music)
+Property_iterator::once_finalization (SCM ctx, SCM music)
 {
   Music *m = unsmob_music (music);
-  Context *tg
-    = dynamic_cast<Context *> (unsmob_context (translator));
-  SCM sym = m->get_property ("symbol");
+  Context *c = unsmob_context (ctx);
 
-  tg->unset_property (sym);
+  send_stream_event (c, "UnsetProperty", m->origin (),
+                    ly_symbol2scm ("symbol"), m->get_property ("symbol"));
   return SCM_UNSPECIFIED;
 }
 
@@ -109,27 +102,33 @@ Push_property_iterator::process (Moment m)
 
       if (to_boolean (get_music ()->get_property ("pop-first"))
          && !to_boolean (get_music ()->get_property ("once")))
-       
-       execute_general_pushpop_property (get_outlet (), sym, grob_property_path, SCM_UNDEFINED);
-
-      execute_general_pushpop_property (get_outlet (), sym, grob_property_path, val);
+       send_stream_event (get_outlet (), "Revert", get_music ()->origin (),
+                          ly_symbol2scm ("symbol"), sym,
+                          ly_symbol2scm ("property-path"), grob_property_path);
+                       
+      send_stream_event (get_outlet (), "Override", get_music ()->origin (),
+                        ly_symbol2scm ("symbol"), sym,
+                        ly_symbol2scm ("property-path"), grob_property_path,
+                        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 trans, SCM music)
+Push_property_iterator::once_finalization (SCM ctx, SCM music)
 {
   Music *mus = unsmob_music (music);
-  Context *tg = dynamic_cast<Context *> (unsmob_context (trans));
+  Context *c = unsmob_context (ctx);
 
   SCM sym = mus->get_property ("symbol");
   if (check_grob (mus, sym))
     {
       SCM grob_property_path = get_property_path (mus);
 
-      execute_general_pushpop_property (tg, sym, grob_property_path, SCM_UNDEFINED);
+      send_stream_event (c, "Revert", mus->origin (),
+                        ly_symbol2scm ("symbol"), sym,
+                        ly_symbol2scm ("property-path"), grob_property_path);
     }
   return SCM_UNSPECIFIED;
 }
@@ -156,7 +155,10 @@ Pop_property_iterator::process (Moment m)
   if (check_grob (get_music (), sym))
     {
       SCM grob_property_path = get_property_path (get_music ());
-      execute_general_pushpop_property (get_outlet (), sym, grob_property_path, SCM_UNDEFINED);
+
+      send_stream_event (get_outlet (), "Revert", get_music ()->origin (),
+                        ly_symbol2scm ("symbol"), sym,
+                        ly_symbol2scm ("property-path"), grob_property_path);
     }
   Simple_music_iterator::process (m);
 }
@@ -165,4 +167,3 @@ IMPLEMENT_CTOR_CALLBACK (Pop_property_iterator);
 IMPLEMENT_CTOR_CALLBACK (Push_property_iterator);
 IMPLEMENT_CTOR_CALLBACK (Property_iterator);
 IMPLEMENT_CTOR_CALLBACK (Property_unset_iterator);
-
index 11918565463a2ec0aaeefccdc1b6401e80df4a2d..60ef4905170671bd29c94b3d9595afa8dd78fa12 100644 (file)
 #include "score-translator.hh"
 
 void
-Score_context::prepare (Moment w)
+Score_context::prepare (Moment)
 {
-  Translator_group *t = implementation ();
-  Score_translator *s = dynamic_cast<Score_translator *> (t);
-
-  s->prepare (w);
 }
 
 void
 Score_context::finish ()
 {
-  Translator_group *t = implementation ();
-  Score_translator *s = dynamic_cast<Score_translator *> (t);
-
-  s->finish ();
 }
 
 void
 Score_context::one_time_step ()
 {
-  Translator_group *t = implementation ();
-  Score_translator *s = dynamic_cast<Score_translator *> (t);
-  s->one_time_step ();
 }
 
 SCM
index ba80e75bb6ac6052cecd38c0e3b465ba4e47e51a..b6c79d01588f57eeff3980742f534a1c8253d2fb 100644 (file)
@@ -11,6 +11,7 @@
 #include "all-font-metrics.hh"
 #include "axis-group-interface.hh"
 #include "context-def.hh"
+#include "dispatcher.hh"
 #include "global-context.hh"
 #include "international.hh"
 #include "main.hh"
@@ -19,6 +20,7 @@
 #include "paper-column-engraver.hh"
 #include "paper-column.hh"
 #include "paper-score.hh"
+#include "stream-event.hh"
 #include "system.hh"
 #include "warn.hh"
 
@@ -37,16 +39,16 @@ Score_engraver::derived_mark () const
   Engraver_group::derived_mark ();
 }
 
+IMPLEMENT_LISTENER (Score_engraver, prepare);
 void
-Score_engraver::prepare (Moment m)
+Score_engraver::prepare (SCM)
 {
-  (void) m;
-
   precomputed_recurse_over_translators (context (), START_TRANSLATION_TIMESTEP, DOWN);
 }
 
+IMPLEMENT_LISTENER (Score_engraver, finish);
 void
-Score_engraver::finish ()
+Score_engraver::finish (SCM)
 {
   recurse_over_translators (context (), &Translator::finalize,
                            &Translator_group::finalize,
@@ -87,6 +89,28 @@ Score_engraver::initialize ()
   Engraver_group::initialize ();
 }
 
+void
+Score_engraver::connect_to_context (Context *c)
+{
+  Engraver_group::connect_to_context (c);
+  
+  Dispatcher *d = c->get_global_context ()->event_source ();
+  d->add_listener (GET_LISTENER (one_time_step), ly_symbol2scm ("OneTimeStep"));
+  d->add_listener (GET_LISTENER (prepare), ly_symbol2scm ("Prepare"));
+  d->add_listener (GET_LISTENER (finish), ly_symbol2scm ("Finish"));
+}
+
+void
+Score_engraver::disconnect_from_context ()
+{
+  Dispatcher *d = context ()->get_global_context ()->event_source ();
+  d->remove_listener (GET_LISTENER (one_time_step), ly_symbol2scm ("OneTimeStep"));
+  d->remove_listener (GET_LISTENER (prepare), ly_symbol2scm ("Prepare"));
+  d->remove_listener (GET_LISTENER (finish), ly_symbol2scm ("Finish"));
+
+  Engraver_group::disconnect_from_context ();
+}
+
 void
 Score_engraver::finalize ()
 {
@@ -95,8 +119,9 @@ Score_engraver::finalize ()
   typeset_all ();
 }
 
+IMPLEMENT_LISTENER(Score_engraver, one_time_step);
 void
-Score_engraver::one_time_step ()
+Score_engraver::one_time_step (SCM)
 {
   if (!to_boolean (context ()->get_property ("skipTypesetting")))
     {
index 5bff2797dac2ded126f08553acd8e2a15e166544..c71b4c53616f565940346e78e4997e8832d925c1 100644 (file)
@@ -6,18 +6,20 @@
   (c) 1996--2006 Jan Nieuwenhuizen <janneke@gnu.org>
 */
 
-#include "moment.hh"
 #include "score-performer.hh"
 
 #include "audio-column.hh"
 #include "audio-item.hh"
+#include "context-def.hh"
+#include "context.hh"
+#include "dispatcher.hh"
+#include "global-context.hh"
 #include "performance.hh"
 #include "midi-stream.hh"
+#include "moment.hh"
+#include "output-def.hh"
 #include "string-convert.hh"
 #include "warn.hh"
-#include "context-def.hh"
-#include "output-def.hh"
-#include "context.hh"
 
 ADD_TRANSLATOR_GROUP (Score_performer,
                      /* doc */ "",
@@ -51,15 +53,42 @@ Score_performer::announce_element (Audio_element_info info)
 }
 
 void
-Score_performer::prepare (Moment m)
+Score_performer::connect_to_context (Context *c)
+{
+  Performer_group::connect_to_context (c);
+  
+  Dispatcher *d = c->get_global_context ()->event_source ();
+  d->add_listener (GET_LISTENER (one_time_step), ly_symbol2scm ("OneTimeStep"));
+  d->add_listener (GET_LISTENER (prepare), ly_symbol2scm ("Prepare"));
+  d->add_listener (GET_LISTENER (finish), ly_symbol2scm ("Finish"));
+}
+
+void
+Score_performer::disconnect_from_context ()
+{
+  Dispatcher *d = context ()->get_global_context ()->event_source ();
+  d->remove_listener (GET_LISTENER (one_time_step), ly_symbol2scm ("OneTimeStep"));
+  d->remove_listener (GET_LISTENER (prepare), ly_symbol2scm ("Prepare"));
+  d->remove_listener (GET_LISTENER (finish), ly_symbol2scm ("Finish"));
+
+  Performer_group::disconnect_from_context ();
+}
+
+IMPLEMENT_LISTENER (Score_performer, prepare);
+void
+Score_performer::prepare (SCM sev)
 {
-  audio_column_ = new Audio_column (m);
+  Stream_event *ev = unsmob_stream_event (sev);
+  SCM sm = ev->get_property ("moment");
+  Moment *m = unsmob_moment (sm);
+  audio_column_ = new Audio_column (*m);
   play_element (audio_column_);
   precomputed_recurse_over_translators (context (), START_TRANSLATION_TIMESTEP, UP);
 }
 
+IMPLEMENT_LISTENER (Score_performer, finish);
 void
-Score_performer::finish ()
+Score_performer::finish (SCM)
 {
   recurse_over_translators (context (),
                            &Translator::finalize,
@@ -67,8 +96,9 @@ Score_performer::finish ()
                            UP);
 }
 
+IMPLEMENT_LISTENER (Score_performer, one_time_step);
 void
-Score_performer::one_time_step ()
+Score_performer::one_time_step (SCM)
 {
   if (to_boolean (context ()->get_property ("skipTypesetting")))
     {
index 5d2cbc4093da74eba889edb2ac6fb2dffa2f70b5..68baba6010acfbcb19c89987ffaebfe20d2d74f3 100644 (file)
@@ -9,23 +9,8 @@
 #include "score-translator.hh"
 #include "moment.hh"
 
-void
-Score_translator::prepare (Moment)
-{
-}
-
 SCM
 Score_translator::get_output ()
 {
   return SCM_EOL;
 }
-
-void
-Score_translator::finish ()
-{
-}
-
-void
-Score_translator::one_time_step ()
-{
-}
index f8c868c34ae9cc0f162df809c0da5b74638052a5..eb530046a0fa5fd8548484be070861f486ca9c6c 100644 (file)
@@ -13,8 +13,6 @@
 #include "input.hh"
 #include "input-smob.hh"
 
-// ES todo: Add stuff to lily-proto.hh: Stream_event and its subclasses, Stream_creator, etc.
-
 Stream_event::~Stream_event ()
 {
 }
@@ -24,7 +22,6 @@ Stream_event::init ()
 {
   self_scm_ = SCM_EOL;
   property_alist_ = SCM_EOL;
-  origin_ = 0;
 
   smobify_self ();
 }
@@ -34,39 +31,40 @@ Stream_event::Stream_event ()
   init ();
 }
 
-Stream_event::Stream_event (Context *c, Input *origin)
-{
-  init ();
-  set_property ("context", scm_int2num (c->get_unique()));
-  origin_ = origin;
-}
-
 Stream_event::Stream_event (SCM property_alist)
 {
   init ();
   property_alist_ = property_alist;
-  origin_ = &dummy_input_global;
 }
 
-Stream_event::Stream_event (Context *c, SCM class_name)
+/*
+   Hm. Perhaps Stream_event should be a prob, with class_name as an
+   immutable property?
+ */
+Stream_event::Stream_event (SCM class_name, Input *origin)
 {
   init ();
-  set_property ("context", scm_int2num (c->get_unique()));
   set_property ("class", class_name);
-  origin_ = &dummy_input_global;
+  if (origin)
+    set_spot (origin);
 }
 
 Stream_event::Stream_event (Stream_event *ev)
 {
   init ();
   property_alist_ = scm_copy_tree (ev->property_alist_);
-  origin_ = ev->origin_;
 }
 
 Input *
 Stream_event::origin () const
 {
-  return origin_;
+  Input *i = unsmob_input (get_property ("origin"));
+  return i ? i : &dummy_input_global;
+}
+
+void Stream_event::set_spot (Input *i)
+{
+  set_property ("origin", make_input (*i));
 }
 
 SCM
index e2541996efcbc998c88a11da8a16ee9a22cb8979..172c5b2a3aed958b36c6508d89901270b0b60422 100644 (file)
 #include "context-def.hh"
 #include "context.hh"
 #include "dispatcher.hh"
+#include "engraver-group.hh"
 #include "international.hh"
 #include "main.hh"
 #include "music.hh"
 #include "output-def.hh"
+#include "performer-group.hh"
 #include "scm-hash.hh"
 #include "stream-event.hh"
 #include "warn.hh"
@@ -43,9 +45,22 @@ void
 Translator_group::connect_to_context (Context *c)
 {
   if (context_)
-    programming_error ("already connected to a context");
+    programming_error ("translator group is already connected to a context");
   context_ = c;
-  c->event_source ()->add_listener (GET_LISTENER (eat_event), ly_symbol2scm ("MusicEvent"));
+  c->event_source ()->add_listener (GET_LISTENER (eat_event),
+                                   ly_symbol2scm ("MusicEvent"));
+  c->event_source ()->add_listener (GET_LISTENER (create_child_translator),
+                                   ly_symbol2scm ("AnnounceNewContext"));
+}
+
+void
+Translator_group::disconnect_from_context ()
+{
+  context_->event_source ()->remove_listener (GET_LISTENER (eat_event),
+                                             ly_symbol2scm ("MusicEvent"));
+  context_->event_source ()->remove_listener (GET_LISTENER (create_child_translator),
+                                             ly_symbol2scm ("AnnounceNewContext"));
+  context_ = 0;
 }
 
 void
@@ -80,6 +95,101 @@ find_accept_translators (SCM gravlist, SCM ifaces)
   return l;
 }
 
+SCM
+filter_performers (SCM ell)
+{
+  SCM *tail = &ell;
+  for (SCM p = ell; scm_is_pair (p); p = scm_cdr (p))
+    {
+      if (dynamic_cast<Performer *> (unsmob_translator (scm_car (*tail))))
+       *tail = scm_cdr (*tail);
+      else
+       tail = SCM_CDRLOC (*tail);
+    }
+  return ell;
+}
+
+SCM
+filter_engravers (SCM ell)
+{
+  SCM *tail = &ell;
+  for (SCM p = ell; scm_is_pair (p); p = scm_cdr (p))
+    {
+      if (dynamic_cast<Engraver *> (unsmob_translator (scm_car (*tail))))
+       *tail = scm_cdr (*tail);
+      else
+       tail = SCM_CDRLOC (*tail);
+    }
+  return ell;
+}
+
+/*
+  Create a new translator for a newly created child context. Triggered
+  by AnnounceNewContext events.
+ */
+IMPLEMENT_LISTENER (Translator_group, create_child_translator);
+void
+Translator_group::create_child_translator (SCM sev)
+{
+  Stream_event *ev = unsmob_stream_event (sev);
+  // get from AnnounceNewContext
+  SCM cs = ev->get_property ("context");
+  Context *new_context = unsmob_context (cs);
+  Context_def *def = unsmob_context_def (new_context->get_definition ());
+  SCM ops = new_context->get_definition_mods ();
+  
+  SCM trans_names = def->get_translator_names (ops);
+
+  Translator_group *g = get_translator_group (def->get_translator_group_type ());
+  SCM trans_list = SCM_EOL;
+
+  for (SCM s = trans_names; scm_is_pair (s); s = scm_cdr (s))
+    {
+      Translator *type = get_translator (scm_car (s));
+      if (!type)
+       warning (_f ("can't find: `%s'", ly_symbol2string (scm_car (s)).c_str ()));
+      else
+       {
+         Translator *tr = type->clone ();
+         SCM str = tr->self_scm ();
+
+         if (tr->must_be_last ())
+           {
+             SCM cons = scm_cons (str, SCM_EOL);
+             if (scm_is_pair (trans_list))
+               scm_set_cdr_x (scm_last_pair (trans_list), cons);
+             else
+               trans_list = cons;
+           }
+         else
+           trans_list = scm_cons (str, trans_list);
+
+         tr->daddy_context_ = new_context;
+         tr->unprotect ();
+       }
+    }
+
+  g->simple_trans_list_ = trans_list;
+
+  /* Filter unwanted translator types. Required to make
+     \with {\consists "..."} work. */
+  if (dynamic_cast<Engraver_group *> (g))
+    g->simple_trans_list_ = filter_performers (g->simple_trans_list_);
+  else if (dynamic_cast<Performer_group *> (g))
+    g->simple_trans_list_ = filter_engravers (g->simple_trans_list_);
+
+  // TODO: scrap Context::implementation
+  new_context->implementation_ = g;
+
+  g->connect_to_context (new_context);
+  g->unprotect ();
+
+  recurse_over_translators (new_context,
+                           &Translator::initialize,
+                           &Translator_group::initialize,
+                           DOWN);
+}
+
 IMPLEMENT_LISTENER (Translator_group, eat_event);
 void
 Translator_group::eat_event (SCM sev)
index 1dd53512b89e31d624b98b4fb1fdf4290da82911..1daacd7932ba0cadc4f856099b8bdb08d92bf761 100644 (file)
@@ -24,7 +24,7 @@ ABC2LY = $(script-dir)/abc2ly.py
 CONVERT_LY = $(script-dir)/convert-ly.py
 LILYPOND_BOOK = $(script-dir)/lilypond-book.py
 LILYPOND_BOOK_INCLUDES = -I $(src-dir)/ -I $(outdir) -I $(input-dir) -I $(input-dir)/regression/ -I $(input-dir)/test/ -I $(input-dir)/tutorial/ -I $(top-build-dir)/mf/$(outconfbase)/  -I $(top-build-dir)/mf/out/
-LILYPOND_BOOK_LILYPOND_FLAGS=-dgs-font-load
+#LILYPOND_BOOK_LILYPOND_FLAGS=-dgs-font-load
 LILYPOND_BOOK_FLAGS = --process="$(LILYPOND_BINARY) --backend=eps --formats=ps,png --header=texidoc -I $(top-src-dir)/input/test -dinternal-type-checking -ddump-signatures -danti-alias-factor=2 $(LILYPOND_BOOK_LILYPOND_FLAGS)"
 TEXINPUTS=$(top-src-dir)/tex/::
 export TEXINPUTS
index 090c6c753c450501073fc9c266a8c16d2d317831..b1712c66d37f96555aaf69a146c07ea67dc11ec8 100644 (file)
@@ -1,5 +1,6 @@
 
 
-local-WWW: $(outdir)/$(NAME).html $(outdir)/$(NAME).pdf
+#local-WWW: $(outdir)/$(NAME).html $(outdir)/$(NAME).pdf
+local-WWW: $(outdir)/$(NAME).html
 
 #.PRECIOUS: $(outdir)/$(NAME).texi
index 84d6ef57d4001d978b463b946f5ebf763ff0b573..3d8b1b14261d4879e756c1e9cc9af244d013760f 100644 (file)
@@ -12,6 +12,8 @@
   '(((StreamEvent) . '())
     ((RemoveContext ChangeParent Override Revert UnsetProperty SetProperty 
       MusicEvent CreateContext Prepare OneTimeStep Finish) . StreamEvent)
+    ((Announcement) . '())
+    ((AnnounceNewContext) . Announcement)
     ))
 
 ;; Maps event-class to a list of ancestors (inclusive)