/* listener.hh -- declare Listener source file of the GNU LilyPond music typesetter (c) 2005 Erik Sandberg */ #ifndef LISTENER_HH #define LISTENER_HH /* Listeners Listeners are used for stream event dispatching. If you want to register a method as an event handler in a dispatcher, then you must: - declare the method using DECLARE_LISTENER: class Foo { DECLARE_LISTENER (method); ... }; - implement the method using IMPLEMENT_LISTENER: IMPLEMENT_LISTENER (Foo, method, (Stream_event *e)) { write ("Foo hears an event!"); } - register the method to the dispatcher using Dispatcher::register Foo *foo = (...); Stream_distributor *d = (...); Listener l = foo->method (); d->register_listener (l, "EventClass"); Whenever d hears a stream-event ev of class "EventClass", the implemented procedure is called. DECLARE_LISTENER currently only works inside smob classes. */ #include "smobs.hh" /*TODO: to lily-proto*/ class Stream_event; typedef struct { void (*listen_callback) (void *, SCM); void (*mark_callback) (void *); } Listener_function_table; class Listener { void *target_; Listener_function_table *type_; public: Listener (const void *target, Listener_function_table *type); Listener (Listener const &other); void listen (SCM ev) const; bool operator == (Listener const &other) const { return target_ == other.target_ && type_ == other.type_; } DECLARE_SIMPLE_SMOBS (Listener,); }; DECLARE_UNSMOB (Listener, listener); #define IMPLEMENT_LISTENER(cl, method, params) \ void \ cl :: method ## _callback (void *self, SCM ev) \ { \ cl *s = (cl *)self; \ s->method ## _proc (ev); \ } \ void \ cl :: method ## _mark (void *self) \ { \ cl *s = (cl *)self; \ scm_gc_mark (s->self_scm ()); \ } \ Listener \ cl :: method () const \ { \ static Listener_function_table callbacks; \ callbacks.listen_callback = &cl::method ## _callback; \ callbacks.mark_callback = &cl::method ## _mark; \ return Listener (this, &callbacks); \ } \ void \ cl :: method ## _proc params #define DECLARE_LISTENER(name) \ inline void name ## _proc (SCM); \ static void name ## _callback (void *self, SCM ev); \ static void name ## _mark (void *self); \ Listener name () const #endif /* LISTENER_HH */