From 8e58d9bf219537b7c6655319d7e57e417b435d51 Mon Sep 17 00:00:00 2001 From: Erik Sandberg Date: Fri, 14 Jul 2006 06:58:29 +0000 Subject: [PATCH] Added new system for how translators listen to events. --- ChangeLog | 18 ++++++- THANKS | 4 +- lily/arpeggio-engraver.cc | 37 +++++++------- lily/dispatcher.cc | 7 +-- lily/grob.cc | 5 ++ lily/include/listener.hh | 44 +++++++++-------- lily/include/stream-event.hh | 15 ++---- lily/include/translator-group.hh | 4 ++ lily/include/translator.hh | 33 +++++++++++++ lily/include/translator.icc | 32 +++++++++++- lily/listener.cc | 11 ++++- lily/lyric-combine-music-iterator.cc | 4 +- lily/music.cc | 31 ++++++++++-- lily/part-combine-iterator.cc | 2 +- lily/stream-event.cc | 74 ++++++++-------------------- lily/translator-group.cc | 44 ++++++++++++++--- lily/translator.cc | 47 ++++++++++++++++++ scm/define-event-classes.scm | 6 ++- 18 files changed, 288 insertions(+), 130 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2d08233975..20bf175d99 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2006-07-14 Erik Sandberg + + * lily/music.cc: Revised MusicEvent event class. It now contains + event data directly instead of encapsulating it in music. The + previously used class is renamed to OldMusicEvent. + + * lily/stream-event.cc: Stream events are now probs. + + * lily/translator-group.cc, lily/translator.cc: Translators can + now listen directly to stream events, by using macros + [DECLARE,IMPLEMENT]_TRANSLATOR_LISTENER. + + * lily/arpeggio-engraver.cc: Converted to use new event system + + * THANKS: Corrected spelling mistake. + 2006-07-12 Graham Percival * Documentation/user/SConscript, make/lilypond-vars.make, @@ -14,7 +30,7 @@ 2006-07-12 Han-Wen Nienhuys - * Documentation/topdocs/NEWS.tely (Top): update prop value + * Documentation/topdocs/NEWS.tely (Top): update prop value * Documentation/user/basic-notation.itely (Tuplets): new property value. diff --git a/THANKS b/THANKS index 1d36a3f31c..4ca18523bd 100644 --- a/THANKS +++ b/THANKS @@ -173,7 +173,7 @@ Patrick K Welton Paul Scott Ralph Little Richard Schoeller -Robert Vlatasy +Robert Vlasaty Roman Kurakin Russell Lang Scott Russell @@ -407,7 +407,7 @@ Pawel D Pedro Kroger Ray McKinney Reuben Thomas -Robert Vlatasy +Robert Vlasaty Stef Epardaud Thomas Willhalm Thomas Scharkowski diff --git a/lily/arpeggio-engraver.cc b/lily/arpeggio-engraver.cc index fd28a41e1f..d67d9da120 100644 --- a/lily/arpeggio-engraver.cc +++ b/lily/arpeggio-engraver.cc @@ -13,6 +13,7 @@ #include "stem.hh" #include "rhythmic-head.hh" #include "side-position-interface.hh" +#include "stream-event.hh" #include "note-column.hh" #include "translator.icc" @@ -28,10 +29,10 @@ public: protected: void process_music (); void stop_translation_timestep (); - virtual bool try_music (Music *); + DECLARE_TRANSLATOR_LISTENER (arpeggio); private: Item *arpeggio_; - Music *arpeggio_event_; + Stream_event *arpeggio_event_; }; Arpeggio_engraver::Arpeggio_engraver () @@ -40,12 +41,11 @@ Arpeggio_engraver::Arpeggio_engraver () arpeggio_event_ = 0; } -bool -Arpeggio_engraver::try_music (Music *m) +IMPLEMENT_TRANSLATOR_LISTENER (Arpeggio_engraver, arpeggio); +void Arpeggio_engraver::listen_arpeggio (Stream_event *ev) { - if (!arpeggio_event_) - arpeggio_event_ = m; - return true; + arpeggio_event_ = ev; + ev->protect (); } void @@ -84,7 +84,10 @@ void Arpeggio_engraver::process_music () { if (arpeggio_event_) - arpeggio_ = make_item ("Arpeggio", arpeggio_event_->self_scm ()); + { + arpeggio_ = make_item ("Arpeggio", arpeggio_event_->self_scm ()); + arpeggio_event_->unprotect (); + } } void @@ -94,13 +97,13 @@ Arpeggio_engraver::stop_translation_timestep () arpeggio_event_ = 0; } -ADD_ACKNOWLEDGER (Arpeggio_engraver, stem) - ADD_ACKNOWLEDGER (Arpeggio_engraver, rhythmic_head) - ADD_ACKNOWLEDGER (Arpeggio_engraver, note_column) +ADD_ACKNOWLEDGER (Arpeggio_engraver, stem); +ADD_ACKNOWLEDGER (Arpeggio_engraver, rhythmic_head); +ADD_ACKNOWLEDGER (Arpeggio_engraver, note_column); - ADD_TRANSLATOR (Arpeggio_engraver, - /* doc */ "Generate an Arpeggio symbol", - /* create */ "Arpeggio", - /* accept */ "arpeggio-event", - /* read */ "", - /* write */ ""); +ADD_TRANSLATOR (Arpeggio_engraver, + /* doc */ "Generate an Arpeggio symbol", + /* create */ "Arpeggio", + /* accept */ "arpeggio-event", + /* read */ "", + /* write */ ""); diff --git a/lily/dispatcher.cc b/lily/dispatcher.cc index ce6f2b7101..9ba5fc2fc7 100644 --- a/lily/dispatcher.cc +++ b/lily/dispatcher.cc @@ -13,10 +13,6 @@ #include "stream-event.hh" #include "warn.hh" -// ES todo: move to lily-guile.hh -SCM appendable_list (); -void appendable_list_append (SCM l, SCM elt); - IMPLEMENT_SMOBS (Dispatcher); IMPLEMENT_TYPE_P (Dispatcher, "dispatcher"); IMPLEMENT_DEFAULT_EQUAL_P (Dispatcher); @@ -80,7 +76,8 @@ Dispatcher::dispatch (SCM sev) 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 ())); + // TODO: Re-enable this warning when the translator cleanup is finished + //ev->origin ()->warning (_f ("Unknown event class %s", ly_symbol2string (class_symbol).c_str ())); return; } bool sent = false; diff --git a/lily/grob.cc b/lily/grob.cc index f79b266b08..c1545de824 100644 --- a/lily/grob.cc +++ b/lily/grob.cc @@ -20,6 +20,7 @@ #include "output-def.hh" #include "pointer-group-interface.hh" #include "stencil.hh" +#include "stream-event.hh" #include "system.hh" #include "warn.hh" @@ -515,6 +516,8 @@ Grob::warning (string s) const if (Music *m = unsmob_music (cause)) m->origin ()->warning (s); + else if (Stream_event *ev = unsmob_stream_event (cause)) + ev->origin ()->warning (s); else ::warning (s); } @@ -540,6 +543,8 @@ Grob::programming_error (string s) const if (Music *m = unsmob_music (cause)) m->origin ()->message (s); + else if (Stream_event *ev = unsmob_stream_event (cause)) + ev->origin ()->warning (s); else ::message (s); } diff --git a/lily/include/listener.hh b/lily/include/listener.hh index fd7a7e2adf..562380c576 100644 --- a/lily/include/listener.hh +++ b/lily/include/listener.hh @@ -63,6 +63,8 @@ class Listener { public: Listener (const void *target, Listener_function_table *type); Listener (Listener const &other); + Listener (); + void listen (SCM ev) const; bool operator == (Listener const &other) const @@ -72,29 +74,29 @@ public: }; DECLARE_UNSMOB (Listener, listener); -#define IMPLEMENT_LISTENER(cl, method) \ -void \ -cl :: method ## _callback (void *self, SCM ev) \ -{ \ - cl *s = (cl *)self; \ - s->method (ev); \ -} \ -void \ -cl :: method ## _mark (void *self) \ -{ \ - cl *s = (cl *)self; \ - scm_gc_mark (s->self_scm ()); \ -} \ -Listener \ -cl :: method ## _listener () const \ -{ \ - static Listener_function_table callbacks; \ - callbacks.listen_callback = &cl::method ## _callback; \ - callbacks.mark_callback = &cl::method ## _mark; \ - return Listener (this, &callbacks); \ +#define IMPLEMENT_LISTENER(cl, method) \ +void \ +cl :: method ## _callback (void *self, SCM ev) \ +{ \ + cl *s = (cl *)self; \ + s->method (ev); \ +} \ +void \ +cl :: method ## _mark (void *self) \ +{ \ + cl *s = (cl *)self; \ + scm_gc_mark (s->self_scm ()); \ +} \ +Listener \ +cl :: method ## _listener () const \ +{ \ + static Listener_function_table callbacks; \ + callbacks.listen_callback = &cl::method ## _callback; \ + callbacks.mark_callback = &cl::method ## _mark; \ + return Listener (this, &callbacks); \ } -#define GET_LISTENER(proc) ( proc ## _listener ()) +#define GET_LISTENER(proc) proc ## _listener () #define DECLARE_LISTENER(name) \ inline void name (SCM); \ diff --git a/lily/include/stream-event.hh b/lily/include/stream-event.hh index f2d5a96036..0ac1b4712f 100644 --- a/lily/include/stream-event.hh +++ b/lily/include/stream-event.hh @@ -13,12 +13,8 @@ #include "smobs.hh" #include "prob.hh" -class Stream_event +class Stream_event : public Prob { - void init (); - SCM property_alist_; - Input *origin_; - public: Stream_event (); Input *origin () const; @@ -28,18 +24,13 @@ public: DECLARE_SCHEME_CALLBACK (dump, (SCM)); // todo: remove unneeded constructors + Stream_event (SCM event_class, SCM mutable_props); Stream_event (SCM property_alist); Stream_event (SCM class_name, Input *); Stream_event (Stream_event *ev); - - SCM internal_get_property (SCM) const; - void internal_set_property (SCM prop, SCM val); - -protected: - DECLARE_SMOBS (Stream_event,); }; -DECLARE_UNSMOB (Stream_event, stream_event); +Stream_event *unsmob_stream_event (SCM); DECLARE_TYPE_P (Stream_event); #endif /* STREAM_EVENT_HH */ diff --git a/lily/include/translator-group.hh b/lily/include/translator-group.hh index 1c8f91ce45..2552fb4186 100644 --- a/lily/include/translator-group.hh +++ b/lily/include/translator-group.hh @@ -47,6 +47,8 @@ private: Translator_group_void_method precomputed_self_method_bindings_[TRANSLATOR_METHOD_PRECOMPUTE_COUNT]; + SCM protected_events_; + DECLARE_LISTENER (create_child_translator); DECLARE_LISTENER (eat_event); @@ -63,6 +65,8 @@ public: virtual void initialize (); virtual void finalize (); + void protect_event (SCM ev); + void stop_translation_timestep (); void start_translation_timestep (); diff --git a/lily/include/translator.hh b/lily/include/translator.hh index 4429429321..eba2d6def4 100644 --- a/lily/include/translator.hh +++ b/lily/include/translator.hh @@ -23,7 +23,21 @@ struct Acknowledge_information Engraver_void_function_engraver_grob_info function_; }; + +/* + Each translator class has a static list of listener records. Each + record makes one explains how to register one of the class's stream event + listeners to a context. +*/ +typedef struct translator_listener_record { + Listener (*get_listener_) (void *); + SCM event_class_; + struct translator_listener_record *next_; +} translator_listener_record; + #define TRANSLATOR_DECLARATIONS(NAME) \ +private: \ + static translator_listener_record *listener_list_; \ public: \ NAME (); \ VIRTUAL_COPY_CONSTRUCTOR (Translator, NAME); \ @@ -42,8 +56,21 @@ struct Acknowledge_information } \ static Engraver_void_function_engraver_grob_info static_get_acknowledger (SCM sym); \ static Engraver_void_function_engraver_grob_info static_get_end_acknowledger(SCM); \ +public: \ + virtual translator_listener_record *get_listener_list () const \ + { \ + return listener_list_; \ + } \ /* end #define */ +#define DECLARE_TRANSLATOR_LISTENER(m) \ +public: \ +inline void listen_ ## m (Stream_event *); \ +/* Should be private */ \ +static void _internal_declare_ ## m (); \ +private: \ +static Listener _get_ ## m ## _listener (void *); \ +DECLARE_LISTENER (_listen_scm_ ## m); #define DECLARE_ACKNOWLEDGER(x) public : void acknowledge_ ## x (Grob_info); protected: #define DECLARE_END_ACKNOWLEDGER(x) public : void acknowledge_end_ ## x (Grob_info); protected: @@ -84,6 +111,10 @@ public: virtual void initialize (); virtual void finalize (); + /*should maybe be virtual*/ + void connect_to_context (Context *c); + void disconnect_from_context (Context *c); + void stop_translation_timestep (); void start_translation_timestep (); void process_music (); @@ -97,7 +128,9 @@ public: protected: // should be private. Context *daddy_context_; + void protect_event (SCM ev); virtual void derived_mark () const; + static void add_translator_listener (translator_listener_record **listener_list, translator_listener_record *r, Listener (*get_listener) (void *), const char *ev_class); friend class Translator_group; }; diff --git a/lily/include/translator.icc b/lily/include/translator.icc index 14ba2b62b6..bff828bcad 100644 --- a/lily/include/translator.icc +++ b/lily/include/translator.icc @@ -9,6 +9,7 @@ #ifndef TRANSLATOR_ICC #define TRANSLATOR_ICC +#include "listener.hh" #include "std-vector.hh" #include "translator.hh" @@ -16,6 +17,7 @@ A macro to automate administration of translators. */ #define ADD_THIS_TRANSLATOR(T) \ + translator_listener_record *T::listener_list_; \ SCM T::static_description_ = SCM_EOL; \ static void _ ## T ## _adder () \ { \ @@ -117,6 +119,34 @@ generic_get_acknowledger (SCM sym, } \ ADD_SCM_INIT_FUNC (CLASS ## NAME ## _end_ack_adder_initclass, CLASS ## NAME ## _end_ack_adder); +/* + Implement the method cl::listen_##m, and make it listen to stream + events of class m. + */ +#define IMPLEMENT_TRANSLATOR_LISTENER(cl, m) \ +void \ +cl :: _internal_declare_ ## m () \ +{ \ + static translator_listener_record r; \ + add_translator_listener (&listener_list_, &r, _get_ ## m ## _listener, #m); \ +} \ + \ +ADD_SCM_INIT_FUNC (cl ## _declare_event_ ## m, cl::_internal_declare_ ## m); \ + \ +Listener \ +cl :: _get_ ## m ## _listener (void *me) \ +{ \ + cl *obj = (cl *) me; \ + return obj->GET_LISTENER (_listen_scm_ ## m); \ +} \ + \ +IMPLEMENT_LISTENER (cl, _listen_scm_ ## m) \ +void \ +cl::_listen_scm_ ## m (SCM sev) \ +{ \ + Stream_event *ev = unsmob_stream_event (sev); \ + protect_event (sev); \ + listen_ ## m (ev); \ +} #endif /* TRANSLATOR_ICC */ - diff --git a/lily/listener.cc b/lily/listener.cc index edc96bdf1c..c8202a9d34 100644 --- a/lily/listener.cc +++ b/lily/listener.cc @@ -10,6 +10,12 @@ #include "ly-smobs.icc" #include "warn.hh" +Listener::Listener () +{ + target_ = 0; + type_ = 0; +} + Listener::Listener (const void *target, Listener_function_table *type) { target_ = (void *)target; @@ -30,12 +36,13 @@ SCM Listener::mark_smob (SCM sm) { Listener *me = (Listener *) SCM_CELL_WORD_1 (sm); - (me->type_->mark_callback) (me->target_); + if (me->type_) + (me->type_->mark_callback) (me->target_); return SCM_EOL; } int -Listener::print_smob (SCM s, SCM p, scm_print_state*) +Listener::print_smob (SCM, SCM p, scm_print_state*) { scm_puts ("#", p); return 1; diff --git a/lily/lyric-combine-music-iterator.cc b/lily/lyric-combine-music-iterator.cc index 8501d3f5b2..aaccf2e210 100644 --- a/lily/lyric-combine-music-iterator.cc +++ b/lily/lyric-combine-music-iterator.cc @@ -76,13 +76,13 @@ Lyric_combine_music_iterator::set_music_context (Context *to) { if (music_context_) { - music_context_->event_source()->remove_listener (GET_LISTENER (set_busy), ly_symbol2scm ("MusicEvent")); + music_context_->event_source()->remove_listener (GET_LISTENER (set_busy), ly_symbol2scm ("OldMusicEvent")); lyrics_context_->unset_property (ly_symbol2scm ("associatedVoiceContext")); } music_context_ = to; if (to) { - to->event_source()->add_listener (GET_LISTENER (set_busy), ly_symbol2scm ("MusicEvent")); + to->event_source()->add_listener (GET_LISTENER (set_busy), ly_symbol2scm ("OldMusicEvent")); lyrics_context_->set_property ("associatedVoiceContext", to->self_scm ()); } } diff --git a/lily/music.cc b/lily/music.cc index 56b6998820..88f38f6a38 100644 --- a/lily/music.cc +++ b/lily/music.cc @@ -21,11 +21,11 @@ #include "warn.hh" /* - Music is anything that has duration and supports both time compression - and transposition. + Music is anything that has (possibly zero) duration and supports + both time compression and transposition. In Lily, everything that can be thought to have a length and a pitch - (which has a duration which can be transposed) is considered "music", + (which has a duration which can be transposed) is considered "music". */ bool Music::internal_is_music_type (SCM k) const @@ -239,8 +239,31 @@ Music::origin () const void Music::send_to_context (Context *c) { - send_stream_event (c, "MusicEvent", origin (), + /* + TODO: This is a work-in-progress solution. Send the event so it + can be read both by old-style translators and the new ones. + */ + send_stream_event (c, "OldMusicEvent", origin (), ly_symbol2scm("music"), self_scm (), 0); + + /* UGH. This is a temp hack for Music->Stream_event transition */ + SCM orig_sym = get_property ("name"); + char out[200]; + string in = ly_symbol2string (orig_sym); + /* don't add '-' before first character */ + out[0] = tolower (in[0]); + size_t outpos = 1; + for (size_t inpos = 1; inpos < in.size () && outpos < 190; inpos++) + { + if (isupper (in[inpos])) + out[outpos++] = '-'; + out[outpos++] = tolower (in[inpos]); + } + out[outpos] = 0; + SCM class_name = ly_symbol2scm (out); + + Stream_event *e = new Stream_event (class_name, mutable_property_alist_); + c->event_source ()->broadcast (e); } Music * diff --git a/lily/part-combine-iterator.cc b/lily/part-combine-iterator.cc index 6f07a67be7..99f36b2b74 100644 --- a/lily/part-combine-iterator.cc +++ b/lily/part-combine-iterator.cc @@ -373,7 +373,7 @@ Part_combine_iterator::construct_children () Context *contexts[] = {one, two, solo_tr, tr, 0}; for (int i = 0; contexts[i]; i++) { - contexts[i]->event_source ()->add_listener (GET_LISTENER (set_busy), ly_symbol2scm ("MusicEvent")); + contexts[i]->event_source ()->add_listener (GET_LISTENER (set_busy), ly_symbol2scm ("OldMusicEvent")); } for (char const **p = syms; *p; p++) diff --git a/lily/stream-event.cc b/lily/stream-event.cc index eb530046a0..e9fe80a22f 100644 --- a/lily/stream-event.cc +++ b/lily/stream-event.cc @@ -13,46 +13,37 @@ #include "input.hh" #include "input-smob.hh" -Stream_event::~Stream_event () +Stream_event::Stream_event () + : Prob (ly_symbol2scm ("Stream_event"), SCM_EOL) { } -void -Stream_event::init () +Stream_event::Stream_event (SCM event_class, SCM mutable_props) + : Prob (ly_symbol2scm ("Stream_event"), + scm_list_1 (scm_cons (ly_symbol2scm ("class"), event_class))) { - self_scm_ = SCM_EOL; - property_alist_ = SCM_EOL; - - smobify_self (); -} - -Stream_event::Stream_event () -{ - init (); + mutable_property_alist_ = mutable_props; } Stream_event::Stream_event (SCM property_alist) + : Prob (ly_symbol2scm ("Stream_event"), SCM_EOL) { - init (); - property_alist_ = property_alist; + mutable_property_alist_ = property_alist; } -/* - Hm. Perhaps Stream_event should be a prob, with class_name as an - immutable property? - */ Stream_event::Stream_event (SCM class_name, Input *origin) + : Prob (ly_symbol2scm ("Stream_event"), + scm_list_1 (scm_cons (ly_symbol2scm ("class"), class_name))) { - init (); - set_property ("class", class_name); if (origin) set_spot (origin); } Stream_event::Stream_event (Stream_event *ev) + : Prob (ly_symbol2scm ("Stream_event"), SCM_EOL) { - init (); - property_alist_ = scm_copy_tree (ev->property_alist_); + mutable_property_alist_ = scm_copy_tree (ev->mutable_property_alist_); + immutable_property_alist_ = ev->immutable_property_alist_; } Input * @@ -67,24 +58,6 @@ void Stream_event::set_spot (Input *i) set_property ("origin", make_input (*i)); } -SCM -Stream_event::mark_smob (SCM sm) -{ - Stream_event *me = (Stream_event *) SCM_CELL_WORD_1 (sm); - return me->property_alist_; -} - -int -Stream_event::print_smob (SCM s, SCM port, scm_print_state *) -{ - scm_puts ("#", port); - return 1; -} - -IMPLEMENT_SMOBS (Stream_event); -IMPLEMENT_DEFAULT_EQUAL_P (Stream_event); IMPLEMENT_TYPE_P (Stream_event, "ly:stream-event?"); MAKE_SCHEME_CALLBACK (Stream_event, undump, 1); @@ -95,28 +68,21 @@ Stream_event::dump (SCM self) { Stream_event *ev = unsmob_stream_event (self); // Reversed alists look prettier. - return scm_reverse (ev->property_alist_); + return scm_cons (scm_reverse (ev->immutable_property_alist_), + scm_reverse (ev->mutable_property_alist_)); } SCM Stream_event::undump (SCM data) { Stream_event *obj = new Stream_event (); - obj->property_alist_ = scm_reverse (data); + obj->immutable_property_alist_ = scm_reverse (scm_car (data)); + obj->mutable_property_alist_ = scm_reverse (scm_cdr (data)); return obj->unprotect (); } -SCM -Stream_event::internal_get_property (SCM sym) const -{ - SCM s = scm_sloppy_assq (sym, property_alist_); - if (s != SCM_BOOL_F) - return scm_cdr (s); - return SCM_EOL; -} - -void -Stream_event::internal_set_property (SCM prop, SCM val) +Stream_event * +unsmob_stream_event (SCM m) { - property_alist_ = scm_assq_set_x (property_alist_, prop, val); + return dynamic_cast (unsmob_prob (m)); } diff --git a/lily/translator-group.cc b/lily/translator-group.cc index 172c5b2a3a..701c75ef77 100644 --- a/lily/translator-group.cc +++ b/lily/translator-group.cc @@ -48,19 +48,30 @@ Translator_group::connect_to_context (Context *c) programming_error ("translator group is already connected to a context"); context_ = c; c->event_source ()->add_listener (GET_LISTENER (eat_event), - ly_symbol2scm ("MusicEvent")); + ly_symbol2scm ("OldMusicEvent")); c->event_source ()->add_listener (GET_LISTENER (create_child_translator), ly_symbol2scm ("AnnounceNewContext")); + for (SCM tr_list = simple_trans_list_; scm_is_pair (tr_list); tr_list = scm_cdr (tr_list)) + { + Translator *tr = unsmob_translator (scm_car (tr_list)); + tr->connect_to_context (c); + } } void Translator_group::disconnect_from_context () { + for (SCM tr_list = simple_trans_list_; scm_is_pair (tr_list); tr_list = scm_cdr (tr_list)) + { + Translator *tr = unsmob_translator (scm_car (tr_list)); + tr->disconnect_from_context (context_); + } context_->event_source ()->remove_listener (GET_LISTENER (eat_event), - ly_symbol2scm ("MusicEvent")); + ly_symbol2scm ("OldMusicEvent")); context_->event_source ()->remove_listener (GET_LISTENER (create_child_translator), ly_symbol2scm ("AnnounceNewContext")); context_ = 0; + protected_events_ = SCM_EOL; } void @@ -123,6 +134,24 @@ filter_engravers (SCM ell) return ell; } +/* + Protects the parameter from being garbage collected. The object is + protected until the next disconnect_from_context call. + + Whenever a child translator hears an event, the event is added to + this list. This eliminates the need for derived_mark methods in most + translators; all incoming events are instead protected by the + translator group. + + TODO: Should the list also be flushed at the beginning of each new + moment? + */ +void +Translator_group::protect_event (SCM ev) +{ + protected_events_ = scm_cons (ev, protected_events_); +} + /* Create a new translator for a newly created child context. Triggered by AnnounceNewContext events. @@ -169,14 +198,12 @@ Translator_group::create_child_translator (SCM sev) } } - 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_); + g->simple_trans_list_ = filter_performers (trans_list); else if (dynamic_cast (g)) - g->simple_trans_list_ = filter_engravers (g->simple_trans_list_); + g->simple_trans_list_ = filter_engravers (trans_list); // TODO: scrap Context::implementation new_context->implementation_ = g; @@ -231,9 +258,12 @@ Translator_group::try_music (Music *m) if (p->get_parent_context()) // ES todo: Make Translators listeners directly instead. return p->implementation ()->try_music (m); + // 'junking event' warning is temporarily disabled during translator cleanup + /* else // We have tried all possible contexts. Give up. m->origin ()->warning (_f ("junking event: `%s'", m->name ())); + */ return false; } @@ -295,6 +325,7 @@ Translator_group::Translator_group () { simple_trans_list_ = SCM_EOL; accept_hash_table_ = SCM_EOL; + protected_events_ = SCM_EOL; context_ = 0; smobify_self (); @@ -376,5 +407,6 @@ Translator_group::mark_smob (SCM smob) me->derived_mark (); scm_gc_mark (me->accept_hash_table_); + scm_gc_mark (me->protected_events_); return me->simple_trans_list_; } diff --git a/lily/translator.cc b/lily/translator.cc index 762fdfd2f9..7bd0e6b47e 100644 --- a/lily/translator.cc +++ b/lily/translator.cc @@ -11,6 +11,7 @@ #include "warn.hh" #include "translator-group.hh" #include "context-def.hh" +#include "dispatcher.hh" #include "global-context.hh" #include "translator.icc" @@ -74,6 +75,12 @@ Translator::get_daddy_translator () const return daddy_context_->implementation (); } +void +Translator::protect_event (SCM ev) +{ + get_daddy_translator ()->protect_event (ev); +} + SCM Translator::internal_get_property (SCM sym) const { @@ -108,6 +115,46 @@ Translator::finalize () { } +void +Translator::connect_to_context (Context *c) +{ + for (translator_listener_record *r = get_listener_list (); r; r=r->next_) + c->events_below ()->add_listener (r->get_listener_ (this), r->event_class_); +} + +void +Translator::disconnect_from_context (Context *c) +{ + for (translator_listener_record *r = get_listener_list (); r; r=r->next_) + c->events_below ()->remove_listener (r->get_listener_ (this), r->event_class_); +} + +/* + Internally called once, statically, for each translator + listener. Connects the name of an event class with a procedure that + fetches the corresponding listener. + + The method should only be called from the macro + IMPLEMENT_TRANSLATOR_LISTENER. + */ +void +Translator::add_translator_listener (translator_listener_record **listener_list, + translator_listener_record *r, + Listener (*get_listener) (void *), + const char *ev_class) +{ + /* ev_class is the C++ identifier name. Convert to scm symbol */ + string name = string (ev_class); + name = replace_all (name, '_', '-'); + name = name + "-event"; + /* It's OK to use scm_gc_protect_object for protection, because r is + statically allocated. */ + r->event_class_ = scm_gc_protect_object (scm_str2symbol (name.c_str ())); + r->get_listener_ = get_listener; + r->next_ = *listener_list; + *listener_list = r; +} + /* SMOBS */ diff --git a/scm/define-event-classes.scm b/scm/define-event-classes.scm index 3d8b1b1426..86245efcbb 100644 --- a/scm/define-event-classes.scm +++ b/scm/define-event-classes.scm @@ -10,8 +10,10 @@ ;; Event class hierarchy. Each line is on the form ((List of children) . Parent) (define event-classes '(((StreamEvent) . '()) - ((RemoveContext ChangeParent Override Revert UnsetProperty SetProperty - MusicEvent CreateContext Prepare OneTimeStep Finish) . StreamEvent) + ((RemoveContext ChangeParent Override Revert UnsetProperty + SetProperty MusicEvent OldMusicEvent CreateContext Prepare + OneTimeStep Finish) . StreamEvent) + ((arpeggio-event) . MusicEvent) ((Announcement) . '()) ((AnnounceNewContext) . Announcement) )) -- 2.39.2