On Saturday 08 July 2006 22:39, Erik Sandberg wrote:
> On Saturday 08 July 2006 12:21, Han-Wen Nienhuys wrote:
> > Erik Sandberg schreef:
> > > B. Create a dummy listener that protects all incoming events, and
> > > unprotects them at the end of each moment. The easiest way is probably
> > > to let Score-level translators take care of this. This is the easiest
> > > and safest solution, but also the most inefficient one.
> > > C. Create some macro trickery in translators, so that incoming events
> > > are remembered and protected automatically between try_music and
> > > stop_translation_timestep.
> >
> > go for either B or C. I'm not sure whether you can make B work, because
> > it sounds as if there still might still be a small time unprotected time
> > interval before the event reaches the protection engraver.
>
> No, the event is still protected by dispatchers (how could it otherwise
> reach the protection engraver?)
>
> Hm, for efficiency reasons, I think I'll go for a hybrid version, and let
> each translator group store a list of events, to which engraver listeners
> automatically store all incoming events.
This is now implemented, see attachment. Events are protected during as long
as the translator-group is connected to the context. Other news:
- I commented out the 'junking event' warning.
- I added support for the grob property "cause" to have stream-event values,
for grob::warning / grob::programming_error. This made me realise that
set_spot and origin are duplicated in Music and Stream_event, and that this
is bad. Do you think it would make sense to either move the set_spot and
origin methods to Prob, or alternatively to introduce a new class
Prob_with_origin? A Prob_with_origin would have the additional methods
warning, programming_error, set_spot and origin. Music, Stream_event and Grob
would all be subclasses of Prob_with_origin. Grob's origin would be set by
make_grob_from_properties.
--
Erik
Index: lily/arpeggio-engraver.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/arpeggio-engraver.cc,v
retrieving revision 1.42
diff -u -r1.42 arpeggio-engraver.cc
--- lily/arpeggio-engraver.cc 6 Jan 2006 09:13:27 -0000 1.42
+++ lily/arpeggio-engraver.cc 9 Jul 2006 12:11:34 -0000
@@ -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 @@
protected:
void process_music ();
void stop_translation_timestep ();
- virtual bool try_music (Music *);
+ DECLARE_TRANSLATOR_LISTENER (Arpeggio_engraver, hear_arpeggio);
private:
Item *arpeggio_;
- Music *arpeggio_event_;
+ Stream_event *arpeggio_event_;
};
Arpeggio_engraver::Arpeggio_engraver ()
@@ -40,12 +41,11 @@
arpeggio_event_ = 0;
}
-bool
-Arpeggio_engraver::try_music (Music *m)
+IMPLEMENT_TRANSLATOR_LISTENER (Arpeggio_engraver, hear_arpeggio, "ArpeggioEvent");
+void Arpeggio_engraver::hear_arpeggio (Stream_event *ev)
{
- if (!arpeggio_event_)
- arpeggio_event_ = m;
- return true;
+ arpeggio_event_ = ev;
+ ev->protect ();
}
void
@@ -84,7 +84,10 @@
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_event_ = 0;
}
-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_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 */ "");
Index: lily/dispatcher.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/dispatcher.cc,v
retrieving revision 1.3
diff -u -r1.3 dispatcher.cc
--- lily/dispatcher.cc 26 Jun 2006 22:11:38 -0000 1.3
+++ lily/dispatcher.cc 9 Jul 2006 12:11:35 -0000
@@ -80,7 +80,8 @@
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;
Index: lily/grob.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/grob.cc,v
retrieving revision 1.171
diff -u -r1.171 grob.cc
--- lily/grob.cc 9 Jun 2006 02:20:22 -0000 1.171
+++ lily/grob.cc 9 Jul 2006 12:11:36 -0000
@@ -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 @@
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 @@
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);
}
Index: lily/listener.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/listener.cc,v
retrieving revision 1.2
diff -u -r1.2 listener.cc
--- lily/listener.cc 16 May 2006 11:30:55 -0000 1.2
+++ lily/listener.cc 9 Jul 2006 12:11:36 -0000
@@ -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,7 +36,8 @@
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;
}
Index: lily/lyric-combine-music-iterator.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/lyric-combine-music-iterator.cc,v
retrieving revision 1.56
diff -u -r1.56 lyric-combine-music-iterator.cc
--- lily/lyric-combine-music-iterator.cc 3 Jun 2006 12:25:27 -0000 1.56
+++ lily/lyric-combine-music-iterator.cc 9 Jul 2006 12:11:38 -0000
@@ -76,13 +76,13 @@
{
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 ());
}
}
Index: lily/music.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/music.cc,v
retrieving revision 1.152
diff -u -r1.152 music.cc
--- lily/music.cc 26 Jun 2006 22:11:38 -0000 1.152
+++ lily/music.cc 9 Jul 2006 12:11:38 -0000
@@ -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,15 @@
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);
+
+ Stream_event *e = new Stream_event (get_property ("name"), mutable_property_alist_);
+ c->event_source ()->broadcast (e);
}
Music *
Index: lily/part-combine-iterator.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/part-combine-iterator.cc,v
retrieving revision 1.32
diff -u -r1.32 part-combine-iterator.cc
--- lily/part-combine-iterator.cc 26 Jun 2006 22:11:38 -0000 1.32
+++ lily/part-combine-iterator.cc 9 Jul 2006 12:11:39 -0000
@@ -373,7 +373,7 @@
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++)
Index: lily/stream-event.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/stream-event.cc,v
retrieving revision 1.2
diff -u -r1.2 stream-event.cc
--- lily/stream-event.cc 26 Jun 2006 22:11:38 -0000 1.2
+++ lily/stream-event.cc 9 Jul 2006 12:11:39 -0000
@@ -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 @@
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 ("#<Stream_event ", port);
- scm_write (dump (s), port);
- 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 *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<Stream_event*> (unsmob_prob (m));
}
Index: lily/translator-group.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/translator-group.cc,v
retrieving revision 1.155
diff -u -r1.155 translator-group.cc
--- lily/translator-group.cc 26 Jun 2006 22:11:38 -0000 1.155
+++ lily/translator-group.cc 9 Jul 2006 12:11:41 -0000
@@ -48,19 +48,25 @@
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 ()
{
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 +129,24 @@
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 +193,12 @@
}
}
- g->simple_trans_list_ = trans_list;
-
/* Filter unwanted translator types. Required to make
\with {\consists "..."} work. */
if (dynamic_cast<Engraver_group *> (g))
- g->simple_trans_list_ = filter_performers (g->simple_trans_list_);
+ g->simple_trans_list_ = filter_performers (trans_list);
else if (dynamic_cast<Performer_group *> (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 +253,12 @@
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 +320,7 @@
{
simple_trans_list_ = SCM_EOL;
accept_hash_table_ = SCM_EOL;
+ protected_events_ = SCM_EOL;
context_ = 0;
smobify_self ();
@@ -376,5 +402,6 @@
me->derived_mark ();
scm_gc_mark (me->accept_hash_table_);
+ scm_gc_mark (me->protected_events_);
return me->simple_trans_list_;
}
Index: lily/translator.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/translator.cc,v
retrieving revision 1.100
diff -u -r1.100 translator.cc
--- lily/translator.cc 11 Feb 2006 11:35:17 -0000 1.100
+++ lily/translator.cc 9 Jul 2006 12:11:41 -0000
@@ -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 @@
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,28 @@
{
}
+void
+Translator::connect_to_context (Context *c)
+{
+ for (translator_listener_record *r = get_listener_list (); r; r=r->next_)
+ {
+ if (!r->event_class_symbol_)
+ r->event_class_symbol_ = ly_symbol2scm (r->event_class_str_);
+ c->events_below ()->add_listener (r->get_listener_ (this), r->event_class_symbol_);
+ }
+}
+
+void
+Translator::disconnect_from_context (Context *c)
+{
+ for (translator_listener_record *r = get_listener_list (); r; r=r->next_)
+ {
+ if (!r->event_class_symbol_)
+ r->event_class_symbol_ = ly_symbol2scm (r->event_class_str_);
+ c->events_below ()->remove_listener (r->get_listener_ (this), r->event_class_symbol_);
+ }
+}
+
/*
SMOBS
*/
Index: lily/include/listener.hh
===================================================================
RCS file: /sources/lilypond/lilypond/lily/include/listener.hh,v
retrieving revision 1.1
diff -u -r1.1 listener.hh
--- lily/include/listener.hh 5 May 2006 15:59:21 -0000 1.1
+++ lily/include/listener.hh 9 Jul 2006 12:11:42 -0000
@@ -63,6 +63,8 @@
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 @@
};
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); \
Index: lily/include/stream-event.hh
===================================================================
RCS file: /sources/lilypond/lilypond/lily/include/stream-event.hh,v
retrieving revision 1.3
diff -u -r1.3 stream-event.hh
--- lily/include/stream-event.hh 26 Jun 2006 22:11:39 -0000 1.3
+++ lily/include/stream-event.hh 9 Jul 2006 12:11:42 -0000
@@ -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 @@
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 */
Index: lily/include/translator-group.hh
===================================================================
RCS file: /sources/lilypond/lilypond/lily/include/translator-group.hh,v
retrieving revision 1.83
diff -u -r1.83 translator-group.hh
--- lily/include/translator-group.hh 26 Jun 2006 22:11:39 -0000 1.83
+++ lily/include/translator-group.hh 9 Jul 2006 12:11:42 -0000
@@ -47,6 +47,8 @@
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 @@
virtual void initialize ();
virtual void finalize ();
+ void protect_event (SCM ev);
+
void stop_translation_timestep ();
void start_translation_timestep ();
Index: lily/include/translator.hh
===================================================================
RCS file: /sources/lilypond/lilypond/lily/include/translator.hh,v
retrieving revision 1.100
diff -u -r1.100 translator.hh
--- lily/include/translator.hh 26 Jun 2006 22:11:39 -0000 1.100
+++ lily/include/translator.hh 9 Jul 2006 12:11:42 -0000
@@ -23,7 +23,22 @@
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 *);
+ const char *event_class_str_;
+ SCM event_class_symbol_;
+ 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 +57,19 @@
} \
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(cl, m) \
+public: \
+inline void m (Stream_event *); \
+static Listener get_ ## m ## _listener (void *); \
+DECLARE_LISTENER (m ## _scm); \
+friend class cl ## _ ## m ## _init;
#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 +110,10 @@
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,6 +127,7 @@
protected: // should be private.
Context *daddy_context_;
+ void protect_event (SCM ev);
virtual void derived_mark () const;
friend class Translator_group;
Index: lily/include/translator.icc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/include/translator.icc,v
retrieving revision 1.13
diff -u -r1.13 translator.icc
--- lily/include/translator.icc 30 May 2006 15:47:16 -0000 1.13
+++ lily/include/translator.icc 9 Jul 2006 12:11:43 -0000
@@ -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,40 @@
} \
ADD_SCM_INIT_FUNC (CLASS ## NAME ## _end_ack_adder_initclass, CLASS ## NAME ## _end_ack_adder);
+/*
+ Implement the method cl::m, and make it hear stream events in class
+ evclass.
+*/
+#define IMPLEMENT_TRANSLATOR_LISTENER(cl, m, evclass) \
+static class cl ## _ ## m ## _init \
+{ \
+public: \
+ cl ## _ ## m ## _init () \
+ { \
+ static translator_listener_record r; \
+ r.get_listener_ = cl::get_ ## m ## _listener; \
+ r.event_class_str_ = evclass; \
+ r.event_class_symbol_ = 0; \
+ r.next_ = cl::listener_list_; \
+ cl::listener_list_ = &r; \
+ } \
+} cl ## _ ## m ## _dummy; \
+ \
+Listener \
+cl :: get_ ## m ## _listener (void *me) \
+{ \
+ cl *obj = (cl *) me; \
+ return obj->GET_LISTENER (m ## _scm); \
+} \
+ \
+IMPLEMENT_LISTENER (cl, m ## _scm) \
+void \
+cl::m ## _scm(SCM sev) \
+{ \
+ Stream_event *ev = unsmob_stream_event (sev); \
+ protect_event (sev); \
+ m (ev); \
+}
#endif /* TRANSLATOR_ICC */
Index: scm/define-event-classes.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/define-event-classes.scm,v
retrieving revision 1.3
diff -u -r1.3 define-event-classes.scm
--- scm/define-event-classes.scm 26 Jun 2006 22:11:39 -0000 1.3
+++ scm/define-event-classes.scm 9 Jul 2006 12:11:43 -0000
@@ -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)
+ ((ArpeggioEvent) . MusicEvent)
((Announcement) . '())
((AnnounceNewContext) . Announcement)
))
_______________________________________________
lilypond-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/lilypond-devel