From b3cf2199183a184c7eef9a9f8f3c9a691db1f0ad Mon Sep 17 00:00:00 2001 From: Erik Sandberg Date: Mon, 26 Jun 2006 22:11:39 +0000 Subject: [PATCH] * 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. --- ChangeLog | 14 ++ Documentation/topdocs/NEWS.tely | 5 +- Documentation/user/advanced-notation.itely | 8 +- THANKS | 5 + lily/auto-change-iterator.cc | 7 +- lily/change-iterator.cc | 4 +- lily/context-def.cc | 88 +------- lily/context.cc | 234 ++++++++++++++------- lily/dispatcher.cc | 24 ++- lily/engraver-group.cc | 49 ++++- lily/global-context-scheme.cc | 34 ++- lily/global-context.cc | 62 +++--- lily/include/context-def.hh | 3 +- lily/include/context.hh | 35 +-- lily/include/engraver-group.hh | 5 +- lily/include/global-context.hh | 9 +- lily/include/score-engraver.hh | 9 +- lily/include/score-performer.hh | 11 +- lily/include/score-translator.hh | 3 - lily/include/stream-event.hh | 6 +- lily/include/translator-group.hh | 4 +- lily/include/translator.hh | 3 +- lily/music.cc | 2 +- lily/paper-column-engraver.cc | 13 +- lily/part-combine-iterator.cc | 5 + lily/property-iterator.cc | 53 ++--- lily/score-context.cc | 13 +- lily/score-engraver.cc | 35 ++- lily/score-performer.cc | 46 +++- lily/score-translator.cc | 15 -- lily/stream-event.cc | 30 ++- lily/translator-group.cc | 114 +++++++++- make/lilypond-vars.make | 2 +- make/lysdoc-targets.make | 3 +- scm/define-event-classes.scm | 2 + 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 + + * 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 * 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 () @@ -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 = ℓ - for (SCM p = ell; scm_is_pair (p); p = scm_cdr (p)) - { - if (dynamic_cast (unsmob_translator (scm_car (*tail)))) - *tail = scm_cdr (*tail); - else - tail = SCM_CDRLOC (*tail); - } - return ell; -} - -SCM -filter_engravers (SCM ell) -{ - SCM *tail = ℓ - for (SCM p = ell; scm_is_pair (p); p = scm_cdr (p)) - { - if (dynamic_cast (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 (g)) - g->simple_trans_list_ = filter_performers (g->simple_trans_list_); - else if (dynamic_cast (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 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 */ +#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 (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 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 announce_infos_; Drul_array 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 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 (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 (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 (t); - - s->prepare (w); } void Score_context::finish () { - Translator_group *t = implementation (); - Score_translator *s = dynamic_cast (t); - - s->finish (); } void Score_context::one_time_step () { - Translator_group *t = implementation (); - Score_translator *s = dynamic_cast (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, @@ -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"))) { 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 */ -#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 = ℓ + for (SCM p = ell; scm_is_pair (p); p = scm_cdr (p)) + { + if (dynamic_cast (unsmob_translator (scm_car (*tail)))) + *tail = scm_cdr (*tail); + else + tail = SCM_CDRLOC (*tail); + } + return ell; +} + +SCM +filter_engravers (SCM ell) +{ + SCM *tail = ℓ + for (SCM p = ell; scm_is_pair (p); p = scm_cdr (p)) + { + if (dynamic_cast (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 (g)) + g->simple_trans_list_ = filter_performers (g->simple_trans_list_); + else if (dynamic_cast (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) -- 2.39.2