void init_from_scheme (SCM definition);
TRANSLATOR_DECLARATIONS_NO_LISTENER (Scheme_engraver);
- static Listener tlr_get_listener (void *generic_arg, SCM event);
-
protected:
~Scheme_engraver ();
virtual void initialize ();
virtual void finalize ();
virtual void derived_mark () const;
- virtual translator_listener_record *get_listener_list () const;
+ virtual SCM get_listener_list () const;
virtual bool must_be_last () const;
private:
SCM listeners_alist_;
// We dont use this, but need it for the documentation boilerplate.
- static translator_listener_record *listener_list_;
- translator_listener_record *per_instance_listeners_;
+ static Protected_scm listener_list_;
+ SCM per_instance_listeners_;
};
#endif /* SCHEME_ENGRAVER_HH */
#include "std-vector.hh"
#include "protected-scm.hh"
-/*
- 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);
- SCM event_class_;
- struct translator_listener_record *next_;
-
- translator_listener_record ()
- {
- next_ = 0;
- event_class_ = SCM_EOL;
- get_listener_ = 0;
- }
-
-} translator_listener_record;
-
#define TRANSLATOR_DECLARATIONS_NO_LISTENER(NAME) \
public: \
NAME (); \
} \
/* end #define */
+/*
+ Each translator class has a static alist of event class symbols
+ mapping to callbacks that are called with a translator instance and
+ a stream event when an event of the appropriate event class is
+ announced in a context.
+*/
+
#define TRANSLATOR_DECLARATIONS(NAME) \
TRANSLATOR_DECLARATIONS_NO_LISTENER(NAME) \
private: \
- static translator_listener_record *listener_list_; \
+ static Protected_scm listener_list_; \
public: \
- virtual translator_listener_record *get_listener_list () const \
+ virtual SCM get_listener_list () const \
{ \
return listener_list_; \
} \
public: \
inline void listen_ ## m (Stream_event *); \
/* Should be private */ \
-static void _internal_declare_ ## m (); \
-private: \
- static Listener _get_ ## m ## _listener (void *, SCM);
+static void _internal_declare_ ## 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:
void protect_event (SCM ev);
friend class Callback_wrapper;
virtual void derived_mark () const;
- static void add_translator_listener (translator_listener_record **listener_list,
- translator_listener_record *r,
- Listener (*get_listener) (void *, SCM),
- const char *ev_class);
+ static SCM event_class_symbol (const char *ev_class);
SCM static_translator_description (const char *grobs,
const char *desc,
- translator_listener_record *listener_list,
+ SCM listener_list,
const char *read,
const char *write) const;
/* end define */
#define DEFINE_TRANSLATOR_LISTENER_LIST(T) \
- translator_listener_record *T::listener_list_; \
+ Protected_scm T::listener_list_ (SCM_EOL); \
/* end define */
#define DEFINE_ACKNOWLEDGERS(classname) \
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, SCM) \
- { \
- cl *obj = (cl *) me; \
- return obj->get_listener \
- (Callback_wrapper::make_smob<cl, Stream_event *, &cl::listen_ ## m> ()); \
- }
+ listener_list_ = scm_acons \
+ (event_class_symbol (#m), \
+ Callback_wrapper::make_smob<cl, Stream_event *, &cl::listen_ ## m> (), \
+ listener_list_); \
+} \
+ \
+ADD_SCM_INIT_FUNC (cl ## _declare_event_ ## m, cl::_internal_declare_ ## m);
#endif /* TRANSLATOR_ICC */
process_acknowledged_function_ = SCM_EOL;
initialize_function_ = SCM_EOL;
finalize_function_ = SCM_EOL;
- listeners_alist_ = SCM_EOL;
interface_acknowledger_hash_ = SCM_EOL;
interface_end_acknowledger_hash_ = SCM_EOL;
must_be_last_ = false;
- per_instance_listeners_ = 0;
+ per_instance_listeners_ = SCM_EOL;
}
Scheme_engraver::~Scheme_engraver ()
{
- translator_listener_record *next = 0;
- for (translator_listener_record *r = per_instance_listeners_;
- r; r = next)
- {
- next = r->next_;
- delete r;
- }
}
// Extracts the value if callable, if not return #f.
SCM listeners = ly_assoc_get (ly_symbol2scm ("listeners"), definition, SCM_EOL);
- listeners_alist_ = SCM_EOL;
+ per_instance_listeners_ = SCM_EOL;
must_be_last_ = to_boolean (ly_assoc_get (ly_symbol2scm ("must-be-last"),
definition,
SCM_BOOL_F));
- translator_listener_record **tail = &per_instance_listeners_;
for (SCM p = listeners; scm_is_pair (p); p = scm_cdr (p))
{
SCM event_class = scm_caar (p);
// We should check the arity of the function?
// Record for later lookup.
- listeners_alist_ = scm_acons (event_class, proc, listeners_alist_);
-
- translator_listener_record *rec = new translator_listener_record;
- *tail = rec;
- rec->event_class_ = event_class;
- rec->get_listener_ = &Scheme_engraver::tlr_get_listener;
- tail = &rec->next_;
+ per_instance_listeners_ = scm_acons (event_class, proc, per_instance_listeners_);
}
init_acknowledgers (ly_assoc_get (ly_symbol2scm ("acknowledgers"),
}
}
-/* static */
-Listener
-Scheme_engraver::tlr_get_listener (void *arg, SCM name)
-{
- Scheme_engraver *me = (Scheme_engraver *) arg;
- SCM func = ly_assoc_get (name, me->listeners_alist_, SCM_BOOL_F);
- assert (ly_is_procedure (func));
-
- return me->get_listener (func);
-}
-
-translator_listener_record *
+SCM
Scheme_engraver::get_listener_list () const
{
return per_instance_listeners_;
scm_gc_mark (finalize_function_);
scm_gc_mark (process_music_function_);
scm_gc_mark (process_acknowledged_function_);
- scm_gc_mark (listeners_alist_);
+ scm_gc_mark (per_instance_listeners_);
scm_gc_mark (interface_acknowledger_hash_);
scm_gc_mark (interface_end_acknowledger_hash_);
}
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_),
- r->event_class_);
+ for (SCM r = get_listener_list (); scm_is_pair (r); r = scm_cdr (r))
+ {
+ SCM event_class = scm_caar (r);
+ SCM callback = scm_cdar (r);
+
+ c->events_below ()->add_listener (get_listener (callback),
+ 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_),
- r->event_class_);
-}
+ for (SCM r = get_listener_list (); scm_is_pair (r); r = scm_cdr (r))
+ {
+ SCM event_class = scm_caar (r);
+ SCM callback = scm_cdar (r);
-/*
- internally called once, statically, for each translator
- listener. Connects the name of an event class with a procedure that
- fetches the corresponding listener.
+ c->events_below ()->remove_listener (get_listener (callback),
+ event_class);
+ }
+}
- 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 *, SCM),
- const char *ev_class)
+SCM
+Translator::event_class_symbol (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 += "-event";
- // we make the symbol permanent in order not to have to bother about
- // the static translator_listener_record chains while garbage
- // collecting.
-
- SCM class_sym = scm_permanent_object (scm_from_ascii_symbol (name.c_str ()));
-
- r->event_class_ = class_sym;
- r->get_listener_ = get_listener;
- r->next_ = *listener_list;
- *listener_list = r;
+ return scm_from_ascii_symbol (name.c_str ());
}
/*
SCM
Translator::static_translator_description (const char *grobs,
const char *desc,
- translator_listener_record *listener_list,
+ SCM listener_list,
const char *read,
const char *write) const
{
scm_from_utf8_string (desc), static_properties);
SCM list = SCM_EOL;
- for (; listener_list; listener_list = listener_list->next_)
- list = scm_cons (listener_list->event_class_, list);
+ for (; scm_is_pair (listener_list); listener_list = scm_cdr (listener_list))
+ list = scm_cons (scm_caar (listener_list), list);
static_properties = scm_acons (ly_symbol2scm ("events-accepted"),
list, static_properties);