On Monday 10 July 2006 13:42, Erik Sandberg wrote:
> On 7/10/06, Han-Wen Nienhuys <[EMAIL PROTECTED]> wrote:
> > Erik Sandberg schreef:
> > >> Use C++ names in C++, and scheme names in scheme, i.e.
> > >>
> > >>    Foo_bar::bla_bla
> > >>
> > >> for handling a bla-bla-event.
> > >
> > > so do you also think that all stream-event classes should be named
> > > like 'arpeggio-event' rather than 'ArpeggioEvent'?
> > >
> > > Regarding bla_bla for classes, it makes me nervous about namespace
> > > clashes. Why not use Foo_bar::bla_bla_event?
> >
> > maybe
> >
> >    Foo_bar::listen_bla_bla
>
> ok, fair enough.

Attached is an updated version. Notes:
- The Scheme symbol for arpeggio events is arpeggio-event. This naming 
convention is different from previous event classes. We can make it more 
consistent later, when we have agreed on good naming conventions.
- The code that converts music name to event-class 
(ArpeggioEvent->arpeggio-event) is unclean and too C-ish. I'll fix that when 
the translator cleanup is finished and a better music->event conversion 
interface will be designed.

-- 
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	11 Jul 2006 21:13:08 -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);
 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, 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 @@
 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	11 Jul 2006 21:13:10 -0000
@@ -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 @@
   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	11 Jul 2006 21:13:12 -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	11 Jul 2006 21:13:12 -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	11 Jul 2006 21:13:14 -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	11 Jul 2006 21:13:14 -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,31 @@
 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 *
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	11 Jul 2006 21:13:16 -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	11 Jul 2006 21:13:16 -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	11 Jul 2006 21:13:18 -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.101
diff -u -r1.101 translator.cc
--- lily/translator.cc	11 Jul 2006 05:58:00 -0000	1.101
+++ lily/translator.cc	11 Jul 2006 21:13:18 -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,34 @@
 {
 }
 
+void
+Translator::connect_to_context (Context *c)
+{
+  for (translator_listener_record *r = get_listener_list (); r; r=r->next_)
+    {
+      if (!r->event_class_symbol_)
+	{
+	  string name = string (r->event_class_str_);
+	  name = replace_all (name, '_', '-');
+	  name = name + "-event";
+	  r->event_class_symbol_ = ly_symbol2scm (name.c_str ());
+	  scm_display (r->event_class_symbol_, scm_current_output_port ());
+	}
+      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	11 Jul 2006 21:13:20 -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	11 Jul 2006 21:13:20 -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	11 Jul 2006 21:13:20 -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.101
diff -u -r1.101 translator.hh
--- lily/include/translator.hh	11 Jul 2006 05:58:00 -0000	1.101
+++ lily/include/translator.hh	11 Jul 2006 21:13:20 -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,21 @@
   } \
   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 +112,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 +129,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	11 Jul 2006 21:13:25 -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,46 @@
   }									\
   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)		\
+static class cl ## _ ## m ## _init			\
+{							\
+public:							\
+  cl ## _ ## m ## _init ()				\
+  {							\
+    cl::_internal_declare_ ## m (); 			\
+  }							\
+} cl ## _ ## m ## _dummy;				\
+							\
+void							\
+cl :: _internal_declare_ ## m ()			\
+{							\
+  static translator_listener_record r;			\
+  r.get_listener_ = _get_ ## m ## _listener;		\
+  r.event_class_str_ = #m;				\
+  r.event_class_symbol_ = 0;				\
+  r.next_ = listener_list_;				\
+  listener_list_ = &r;					\
+}							\
+							\
+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 */
 
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	11 Jul 2006 21:13:25 -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)
+    ((arpeggio-event) . MusicEvent)
     ((Announcement) . '())
     ((AnnounceNewContext) . Announcement)
     ))
_______________________________________________
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel

Reply via email to