summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Sandberg <mandolaerik@gmail.com>2006-06-26 22:11:39 +0000
committerErik Sandberg <mandolaerik@gmail.com>2006-06-26 22:11:39 +0000
commitb3cf2199183a184c7eef9a9f8f3c9a691db1f0ad (patch)
treee80dc80156881e0367a723cd91c85d5807873270
parentffb9d71ab52ad8d9a891f8070525d949789e5058 (diff)
* 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.
-rw-r--r--ChangeLog14
-rw-r--r--Documentation/topdocs/NEWS.tely5
-rw-r--r--Documentation/user/advanced-notation.itely8
-rw-r--r--THANKS5
-rw-r--r--lily/auto-change-iterator.cc7
-rw-r--r--lily/change-iterator.cc4
-rw-r--r--lily/context-def.cc88
-rw-r--r--lily/context.cc234
-rw-r--r--lily/dispatcher.cc24
-rw-r--r--lily/engraver-group.cc49
-rw-r--r--lily/global-context-scheme.cc34
-rw-r--r--lily/global-context.cc62
-rw-r--r--lily/include/context-def.hh3
-rw-r--r--lily/include/context.hh35
-rw-r--r--lily/include/engraver-group.hh5
-rw-r--r--lily/include/global-context.hh9
-rw-r--r--lily/include/score-engraver.hh9
-rw-r--r--lily/include/score-performer.hh11
-rw-r--r--lily/include/score-translator.hh3
-rw-r--r--lily/include/stream-event.hh6
-rw-r--r--lily/include/translator-group.hh4
-rw-r--r--lily/include/translator.hh3
-rw-r--r--lily/music.cc2
-rw-r--r--lily/paper-column-engraver.cc13
-rw-r--r--lily/part-combine-iterator.cc5
-rw-r--r--lily/property-iterator.cc53
-rw-r--r--lily/score-context.cc13
-rw-r--r--lily/score-engraver.cc35
-rw-r--r--lily/score-performer.cc46
-rw-r--r--lily/score-translator.cc15
-rw-r--r--lily/stream-event.cc30
-rw-r--r--lily/translator-group.cc114
-rw-r--r--make/lilypond-vars.make2
-rw-r--r--make/lysdoc-targets.make3
-rw-r--r--scm/define-event-classes.scm2
35 files changed, 614 insertions, 341 deletions
diff --git a/ChangeLog b/ChangeLog
index a3400ca1f3..e41a15cb29 100644
--- 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.
diff --git a/Documentation/topdocs/NEWS.tely b/Documentation/topdocs/NEWS.tely
index e67e068f73..925246b4dc 100644
--- a/Documentation/topdocs/NEWS.tely
+++ b/Documentation/topdocs/NEWS.tely
@@ -198,10 +198,13 @@ support for feathered beaming,
\override Beam #'grow-direction = #LEFT
c16[
c 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
diff --git a/Documentation/user/advanced-notation.itely b/Documentation/user/advanced-notation.itely
index 1bb72ecc82..f446039c5c 100644
--- a/Documentation/user/advanced-notation.itely
+++ b/Documentation/user/advanced-notation.itely
@@ -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 40be0a2918..cf2c2e3361 100644
--- 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
diff --git a/lily/auto-change-iterator.cc b/lily/auto-change-iterator.cc
index f5c54f224c..ade8303e0d 100644
--- a/lily/auto-change-iterator.cc
+++ b/lily/auto-change-iterator.cc
@@ -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_))
{
diff --git a/lily/change-iterator.cc b/lily/change-iterator.cc
index aef7567be0..55099a855e 100644
--- a/lily/change-iterator.cc
+++ b/lily/change-iterator.cc
@@ -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. */
diff --git a/lily/context-def.cc b/lily/context-def.cc
index fee67b661d..f4ee43b160 100644
--- a/lily/context-def.cc
+++ b/lily/context-def.cc
@@ -11,14 +11,10 @@
#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 ()
@@ -144,12 +140,6 @@ Context_def::add_context_mod (SCM mod)
}
SCM
-Context_def::get_context_name () const
-{
- return context_name_;
-}
-
-SCM
Context_def::get_accepted (SCM user_mod) const
{
SCM mods = scm_reverse_x (scm_list_copy (accept_mods_), user_mod);
@@ -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;
diff --git a/lily/context.cc b/lily/context.cc
index 5e97a6171d..f39fb5e1c2 100644
--- a/lily/context.cc
+++ b/lily/context.cc
@@ -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
{
diff --git a/lily/dispatcher.cc b/lily/dispatcher.cc
index e66f0952cb..ce6f2b7101 100644
--- a/lily/dispatcher.cc
+++ b/lily/dispatcher.cc
@@ -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));
}
}
diff --git a/lily/engraver-group.cc b/lily/engraver-group.cc
index 71533cd116..6271d93979 100644
--- a/lily/engraver-group.cc
+++ b/lily/engraver-group.cc
@@ -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)
diff --git a/lily/global-context-scheme.cc b/lily/global-context-scheme.cc
index 7eb5fb224a..9229a8a0d9 100644
--- a/lily/global-context-scheme.cc
+++ b/lily/global-context-scheme.cc
@@ -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 ();
}
diff --git a/lily/global-context.cc b/lily/global-context.cc
index 6e2d26a58a..94f3547630 100644
--- a/lily/global-context.cc
+++ b/lily/global-context.cc
@@ -12,24 +12,33 @@
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_;
-}
diff --git a/lily/include/context-def.hh b/lily/include/context-def.hh
index 8f5ba8686d..df69f257dd 100644
--- a/lily/include/context-def.hh
+++ b/lily/include/context-def.hh
@@ -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,
diff --git a/lily/include/context.hh b/lily/include/context.hh
index 5a7eb92687..eaa280ff58 100644
--- a/lily/include/context.hh
+++ b/lily/include/context.hh
@@ -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 */
diff --git a/lily/include/engraver-group.hh b/lily/include/engraver-group.hh
index d1df4cffb3..938fde0492 100644
--- a/lily/include/engraver-group.hh
+++ b/lily/include/engraver-group.hh
@@ -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:
diff --git a/lily/include/global-context.hh b/lily/include/global-context.hh
index cc87ff3c9b..0ff225c50d 100644
--- a/lily/include/global-context.hh
+++ b/lily/include/global-context.hh
@@ -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_;
};
diff --git a/lily/include/score-engraver.hh b/lily/include/score-engraver.hh
index 7657114536..b3127f8977 100644
--- a/lily/include/score-engraver.hh
+++ b/lily/include/score-engraver.hh
@@ -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 ();
diff --git a/lily/include/score-performer.hh b/lily/include/score-performer.hh
index e38f430c62..f98dd18dd5 100644
--- a/lily/include/score-performer.hh
+++ b/lily/include/score-performer.hh
@@ -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;
diff --git a/lily/include/score-translator.hh b/lily/include/score-translator.hh
index b74fb0fe22..01ee9e3ad0 100644
--- a/lily/include/score-translator.hh
+++ b/lily/include/score-translator.hh
@@ -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 */
diff --git a/lily/include/stream-event.hh b/lily/include/stream-event.hh
index 13535c73f6..f2d5a96036 100644
--- a/lily/include/stream-event.hh
+++ b/lily/include/stream-event.hh
@@ -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;
diff --git a/lily/include/translator-group.hh b/lily/include/translator-group.hh
index 3bb6b4255f..1c8f91ce45 100644
--- a/lily/include/translator-group.hh
+++ b/lily/include/translator-group.hh
@@ -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);
diff --git a/lily/include/translator.hh b/lily/include/translator.hh
index 398a32ce06..f6b3c88819 100644
--- a/lily/include/translator.hh
+++ b/lily/include/translator.hh
@@ -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);
diff --git a/lily/music.cc b/lily/music.cc
index 02a9876b1c..56b6998820 100644
--- a/lily/music.cc
+++ b/lily/music.cc
@@ -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);
}
diff --git a/lily/paper-column-engraver.cc b/lily/paper-column-engraver.cc
index 7bc7c665ac..cef0f9e5c0 100644
--- a/lily/paper-column-engraver.cc
+++ b/lily/paper-column-engraver.cc
@@ -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];
diff --git a/lily/part-combine-iterator.cc b/lily/part-combine-iterator.cc
index 65c7f1aac9..6f07a67be7 100644
--- a/lily/part-combine-iterator.cc
+++ b/lily/part-combine-iterator.cc
@@ -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_));
diff --git a/lily/property-iterator.cc b/lily/property-iterator.cc
index a4c993b756..cfa6fb6286 100644
--- a/lily/property-iterator.cc
+++ b/lily/property-iterator.cc
@@ -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);
-
diff --git a/lily/score-context.cc b/lily/score-context.cc
index 1191856546..60ef490517 100644
--- a/lily/score-context.cc
+++ b/lily/score-context.cc
@@ -11,29 +11,18 @@
#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
diff --git a/lily/score-engraver.cc b/lily/score-engraver.cc
index ba80e75bb6..b6c79d0158 100644
--- a/lily/score-engraver.cc
+++ b/lily/score-engraver.cc
@@ -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,
@@ -88,6 +90,28 @@ Score_engraver::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 ()
{
Score_translator::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")))
{
diff --git a/lily/score-performer.cc b/lily/score-performer.cc
index 5bff2797da..c71b4c5361 100644
--- a/lily/score-performer.cc
+++ b/lily/score-performer.cc
@@ -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")))
{
diff --git a/lily/score-translator.cc b/lily/score-translator.cc
index 5d2cbc4093..68baba6010 100644
--- a/lily/score-translator.cc
+++ b/lily/score-translator.cc
@@ -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 ()
-{
-}
diff --git a/lily/stream-event.cc b/lily/stream-event.cc
index f8c868c34a..eb530046a0 100644
--- a/lily/stream-event.cc
+++ b/lily/stream-event.cc
@@ -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
diff --git a/lily/translator-group.cc b/lily/translator-group.cc
index e2541996ef..172c5b2a3a 100644
--- a/lily/translator-group.cc
+++ b/lily/translator-group.cc
@@ -12,10 +12,12 @@
#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)
diff --git a/make/lilypond-vars.make b/make/lilypond-vars.make
index 1dd53512b8..1daacd7932 100644
--- a/make/lilypond-vars.make
+++ b/make/lilypond-vars.make
@@ -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
diff --git a/make/lysdoc-targets.make b/make/lysdoc-targets.make
index 090c6c753c..b1712c66d3 100644
--- a/make/lysdoc-targets.make
+++ b/make/lysdoc-targets.make
@@ -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
diff --git a/scm/define-event-classes.scm b/scm/define-event-classes.scm
index 84d6ef57d4..3d8b1b1426 100644
--- a/scm/define-event-classes.scm
+++ b/scm/define-event-classes.scm
@@ -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)