From: Erik Sandberg Date: Tue, 16 May 2006 11:30:55 +0000 (+0000) Subject: * lily/context.cc, lily/music.cc, lily/context-scheme.cc: Add X-Git-Tag: release/2.9.5~10 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=c83f8abe0c27faabcad658ff3a9691158c62c3a3;p=lilypond.git * lily/context.cc, lily/music.cc, lily/context-scheme.cc: Add dispatchers event-source and events-below to Context --- diff --git a/lily/context-def.cc b/lily/context-def.cc index d77b075322..05363e498c 100644 --- a/lily/context-def.cc +++ b/lily/context-def.cc @@ -298,6 +298,7 @@ Context_def::instantiate (SCM ops, Object_key const *key) context = new Context (key); context->definition_ = self_scm (); + context->definition_mods_ = ops; SCM trans_names = get_translator_names (ops); diff --git a/lily/context-scheme.cc b/lily/context-scheme.cc index 51b49b7d8f..92240a9b1d 100644 --- a/lily/context-scheme.cc +++ b/lily/context-scheme.cc @@ -9,6 +9,7 @@ #include "context.hh" #include "context-def.hh" +#include "dispatcher.hh" LY_DEFINE (ly_context_id, "ly:context-id", 1, 0, 0, (SCM context), @@ -159,3 +160,22 @@ LY_DEFINE (ly_context_now, "ly:context-now", SCM_ASSERT_TYPE (ctx, context, SCM_ARG1, __FUNCTION__, "Context"); return ctx->now_mom ().smobbed_copy (); } + +LY_DEFINE (ly_context_event_source, "ly:context-event-source", + 1, 0, 0, (SCM context), + "Return event-source of context CONTEXT") +{ + Context *ctx = unsmob_context (context); + SCM_ASSERT_TYPE (ctx, context, SCM_ARG1, __FUNCTION__, "Context"); + return ctx->event_source ()->self_scm (); +} + +LY_DEFINE (ly_context_events_below, "ly:context-events-below", + 1, 0, 0, (SCM context), + "Return a stream-distributor that distributes all events\n" + " from @var{context} and all its subcontexts.") +{ + Context *ctx = unsmob_context (context); + SCM_ASSERT_TYPE (ctx, context, SCM_ARG1, __FUNCTION__, "Context"); + return ctx->events_below ()->self_scm (); +} diff --git a/lily/context.cc b/lily/context.cc index 9ebdb10695..7ab871b15e 100644 --- a/lily/context.cc +++ b/lily/context.cc @@ -9,6 +9,7 @@ #include "context.hh" #include "context-def.hh" +#include "dispatcher.hh" #include "international.hh" #include "ly-smobs.icc" #include "main.hh" @@ -24,7 +25,7 @@ bool Context::is_removable () const { return context_list_ == SCM_EOL && ! iterator_count_ - && !dynamic_cast (this); + && !dynamic_cast (daddy_context_); } void @@ -96,12 +97,19 @@ Context::Context (Object_key const *key) accepts_list_ = SCM_EOL; context_list_ = SCM_EOL; definition_ = SCM_EOL; + definition_mods_ = SCM_EOL; unique_ = -1; + event_source_ = 0; + events_below_ = 0; smobify_self (); Scheme_hash_table *tab = new Scheme_hash_table; properties_scm_ = tab->unprotect (); + event_source_ = new Dispatcher (); + event_source_->unprotect (); + events_below_ = new Dispatcher (); + events_below_->unprotect (); /* UGH UGH @@ -117,9 +125,9 @@ Context::create_unique_context (SCM name, string id, SCM operations) /* Don't create multiple score contexts. */ - if (dynamic_cast (this) - && dynamic_cast (this)->get_score_context ()) - return get_score_context ()->create_unique_context (name, id, operations); + Global_context *gthis = dynamic_cast (this); + if (gthis && gthis->get_score_context ()) + return gthis->get_score_context ()->create_unique_context (name, id, operations); /* TODO: use accepts_list_. @@ -171,9 +179,9 @@ Context::find_create_context (SCM n, string id, SCM operations) /* Don't create multiple score contexts. */ - if (dynamic_cast (this) - && dynamic_cast (this)->get_score_context ()) - return get_score_context ()->find_create_context (n, id, operations); + Global_context *gthis = dynamic_cast (this); + if (gthis && gthis->get_score_context ()) + return gthis->get_score_context ()->find_create_context (n, id, operations); if (Context *existing = find_context_below (this, n, id)) return existing; @@ -232,15 +240,29 @@ Context::create_context (Context_def *cdef, string id, SCM ops) { + int unique = get_global_context()->new_unique(); + + // TODO: The following should be carried out by a listener. string type = ly_symbol2string (cdef->get_context_name ()); Object_key const *key = key_manager_.get_context_key (now_mom(), type, id); Context *new_context = cdef->instantiate (ops, key); - new_context->unique_ = get_global_context()->new_unique(); new_context->id_string_ = id; + new_context->unique_ = unique; + + new_context->events_below_->register_as_listener (new_context->event_source_); + add_context (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), + ly_symbol2scm ("ops"), ops, + ly_symbol2scm ("type"), cdef->get_context_name (), + ly_symbol2scm ("id"), scm_makfrom0str (id.c_str ())); return new_context; } @@ -280,10 +302,7 @@ Context::get_default_interpreter () } Context *tg = create_context (t, "", SCM_EOL); - if (!tg->is_bottom_context ()) - return tg->get_default_interpreter (); - else - return tg; + return tg->get_default_interpreter (); } return this; } @@ -326,6 +345,19 @@ Context::internal_get_property (SCM sym) const return val; } +void +Context::internal_send_stream_event (SCM type, SCM props[]) +{ + Stream_event *e = new Stream_event (this, type); + for (int i = 0; props[i]; i++) + { + assert(props[i+1]); + e->internal_set_property (props[i], props[i+1]); + } + event_source_->broadcast (e); + e->unprotect (); +} + bool Context::is_alias (SCM sym) const { @@ -377,6 +409,7 @@ Context::remove_context (Context *trans) return trans; } + /* ID == "" means accept any ID. */ @@ -402,6 +435,25 @@ 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 { @@ -500,10 +552,13 @@ Context::mark_smob (SCM sm) scm_gc_mark (me->context_list_); scm_gc_mark (me->aliases_); scm_gc_mark (me->definition_); + scm_gc_mark (me->definition_mods_); scm_gc_mark (me->properties_scm_); scm_gc_mark (me->accepts_list_); if (me->implementation_) scm_gc_mark (me->implementation_->self_scm ()); + if (me->event_source_) scm_gc_mark (me->event_source_->self_scm ()); + if (me->events_below_) scm_gc_mark (me->events_below_->self_scm ()); return me->properties_scm_; } diff --git a/lily/dispatcher.cc b/lily/dispatcher.cc index c6fedb2374..e66f0952cb 100644 --- a/lily/dispatcher.cc +++ b/lily/dispatcher.cc @@ -31,7 +31,9 @@ Dispatcher::Dispatcher () dispatchers_ = SCM_EOL; listen_classes_ = SCM_EOL; smobify_self (); - listeners_ = scm_c_make_hash_table (0); +// TODO: use resizable hash (guile 1.8) +// listeners_ = scm_c_make_hash_table (0); + listeners_ = scm_c_make_hash_table (17); priority_count_ = 0; } @@ -147,8 +149,10 @@ Dispatcher::dispatch (SCM sev) lists[i].list = next; } +/* TODO: Uncomment. if (!sent) warning (_f ("Junking event: %s", ly_symbol2string (class_symbol).c_str ())); +*/ } void diff --git a/lily/include/context.hh b/lily/include/context.hh index 4b85bd31cd..5a7eb92687 100644 --- a/lily/include/context.hh +++ b/lily/include/context.hh @@ -33,7 +33,10 @@ private: protected: int unique_; Context *daddy_context_; + /* The used Context_def */ SCM definition_; + /* Additions to the Context_def, given by \with */ + SCM definition_mods_; Context_key_manager key_manager_; SCM properties_scm_; @@ -42,6 +45,13 @@ protected: SCM aliases_; Translator_group *implementation_; string id_string_; + + /* Events reported in the context is sent to this dispatcher. */ + Dispatcher *event_source_; + + /* Events reported to this context or recursively in any of its + children, are sent to this dispatcher. */ + Dispatcher *events_below_; friend class Context_def; void clear_key_disambiguations (); @@ -57,6 +67,13 @@ public: 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[]); + + SCM get_definition () const { return definition_; } + SCM get_definition_mods () const { return definition_mods_; } + Translator_group *implementation () const { return implementation_; } Context *get_parent_context () const; Context (Object_key const *); @@ -116,5 +133,12 @@ Moment measure_position (Context const *context); 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, ...) \ +{ \ + SCM props[] = { __VA_ARGS__, 0 }; \ + ctx->internal_send_stream_event (ly_symbol2scm (type), props); \ +} + #endif /* CONTEXT_HH */ diff --git a/lily/include/music.hh b/lily/include/music.hh index f278786847..3c43209b47 100644 --- a/lily/include/music.hh +++ b/lily/include/music.hh @@ -41,6 +41,9 @@ public: /// Scale the music in time by #factor#. void compress (Moment factor); + + // Broadcast the event in a context's event-source. + void send_to_context (Context *c); DECLARE_SCHEME_CALLBACK (duration_length_callback, (SCM)); diff --git a/lily/include/stream-event.hh b/lily/include/stream-event.hh index 9966a35eb9..13535c73f6 100644 --- a/lily/include/stream-event.hh +++ b/lily/include/stream-event.hh @@ -42,15 +42,4 @@ protected: DECLARE_UNSMOB (Stream_event, stream_event); DECLARE_TYPE_P (Stream_event); -#define SEND_EVENT_TO_CONTEXT(ctx, cl, ...) \ - { \ - Stream_event *_e_ = new Stream_event (ctx, ly_symbol2scm (cl)); \ - __VA_ARGS__; \ - ctx->event_source ()->distribute (_e_); \ - scm_gc_unprotect_object (_e_->self_scm ()); \ - } - -#define EVENT_PROPERTY(prop, val) \ - (_e_->set_property (prop, val)) - #endif /* STREAM_EVENT_HH */ diff --git a/lily/listener.cc b/lily/listener.cc index 8b9f3ad9ac..edc96bdf1c 100644 --- a/lily/listener.cc +++ b/lily/listener.cc @@ -10,12 +10,6 @@ #include "ly-smobs.icc" #include "warn.hh" -/* -Listener_target::~Listener_target () -{ -} -*/ - Listener::Listener (const void *target, Listener_function_table *type) { target_ = (void *)target; diff --git a/lily/music-iterator.cc b/lily/music-iterator.cc index 326b975028..528fffb682 100644 --- a/lily/music-iterator.cc +++ b/lily/music-iterator.cc @@ -157,6 +157,12 @@ Music_iterator::try_music (Music *m) const Music_iterator *it = b ? (Music_iterator *) this : 0; // ugh if (!it) it = try_music_in_children (m); + else + /* TODO: try_music should only do the following: + - descend iterator to bottom context + - send music to a bottom context. + The function should also be renamed, and it should not return a value. */ + m->send_to_context (get_outlet ()); return it; } diff --git a/lily/music.cc b/lily/music.cc index 191f42a1b7..5bd573dab0 100644 --- a/lily/music.cc +++ b/lily/music.cc @@ -8,6 +8,8 @@ #include "music.hh" +#include "context.hh" +#include "dispatcher.hh" #include "duration.hh" #include "input-smob.hh" #include "international.hh" @@ -234,6 +236,13 @@ Music::origin () const return ip ? ip : &dummy_input_global; } +void +Music::send_to_context (Context *c) +{ + send_stream_event (c, "MusicEvent", + ly_symbol2scm("music"), self_scm ()); +} + Music * make_music_by_name (SCM sym) { diff --git a/scm/define-event-classes.scm b/scm/define-event-classes.scm index 80bf8a4fa8..84d6ef57d4 100644 --- a/scm/define-event-classes.scm +++ b/scm/define-event-classes.scm @@ -14,6 +14,10 @@ MusicEvent CreateContext Prepare OneTimeStep Finish) . StreamEvent) )) +;; Maps event-class to a list of ancestors (inclusive) +;; TODO: use resizable hash +(define ancestor-lookup (make-hash-table 1)) + ;; Each class will be defined as ;; (class parent grandparent .. ) ;; so that (eq? (cdr class) parent) holds. @@ -21,13 +25,14 @@ (lambda (rel) (for-each (lambda (type) - (primitive-eval `(define ,type (cons ',type ,(cdr rel))))) + (hashq-set! ancestor-lookup type (cons type (hashq-ref ancestor-lookup (cdr rel) '())))) ;; `(define ,type (cons ',type ,(cdr rel))))) (car rel))) event-classes) ;; TODO: Allow entering more complex classes, by taking unions. (define-public (ly:make-event-class leaf) - (primitive-eval leaf)) + (hashq-ref ancestor-lookup leaf)) +;; (primitive-eval leaf)) (defmacro-public make-stream-event (expr) (Stream_event::undump (primitive-eval (list 'quasiquote expr)))) diff --git a/scm/lily.scm b/scm/lily.scm index 701c70ea6a..f0cda6749e 100644 --- a/scm/lily.scm +++ b/scm/lily.scm @@ -228,7 +228,7 @@ The syntax is the same as `define*-public'." ;; load-from-path '("lily-library.scm" "file-cache.scm" -; "define-event-classes.scm" + "define-event-classes.scm" "define-music-types.scm" "output-lib.scm" "c++.scm"