]> git.donarmstrong.com Git - lilypond.git/blob - lily/include/listener.hh
Imported Upstream version 2.14.2
[lilypond.git] / lily / include / listener.hh
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2005 Erik Sandberg <mandolaerik@gmail.com>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifndef LISTENER_HH
21 #define LISTENER_HH
22
23 /*
24   Listeners
25
26   Listeners are used for stream event dispatching. If you want to
27   register a method as an event handler in a dispatcher, then you
28   must:
29
30   - declare the method using the DECLARE_LISTENER macro. 
31   class Foo
32   {
33     DECLARE_LISTENER (method);
34     ...
35   };
36   This macro declares the method to take a SCM as parameter, and to
37     return void. It also declares some other stuff that shouldn't be
38     touched.
39
40   - implement the method using IMPLEMENT_LISTENER:
41   IMPLEMENT_LISTENER (Foo, method)
42   void method (SCM e)
43   {
44     write ("Foo hears an event!");
45   }
46
47   - Extract a listener using GET_LISTENER (Foo->method)
48   - Register the method to the dispatcher using Dispatcher::register
49
50   Example:
51
52   Foo *foo = (...);
53   Stream_distributor *d = (...);
54   Listener l = GET_LISTENER (foo->method);
55   d->register_listener (l, "EventClass");
56   
57   Whenever d hears a stream-event ev of class "EventClass",
58   the implemented procedure is called.
59
60   Limitations:
61   - DECLARE_LISTENER currently only works inside smob classes.
62 */
63
64 #include "smobs.hh"
65
66 typedef struct {
67   void (*listen_callback) (void *, SCM);
68   void (*mark_callback) (void *);
69 } Listener_function_table;
70
71 class Listener {
72   void *target_;
73   Listener_function_table *type_;
74 public:
75   Listener (const void *target, Listener_function_table *type);
76   Listener (Listener const &other);
77   Listener ();
78
79   void listen (SCM ev) const;
80
81   bool operator == (Listener const &other) const
82   { return target_ == other.target_ && type_ == other.type_; }
83
84   DECLARE_SIMPLE_SMOBS (Listener);
85 };
86 DECLARE_UNSMOB (Listener, listener);
87
88 #define IMPLEMENT_LISTENER(cl, method)                  \
89 void                                                    \
90 cl :: method ## _callback (void *self, SCM ev)          \
91 {                                                       \
92   cl *s = (cl *)self;                                   \
93   s->method (ev);                                       \
94 }                                                       \
95 void                                                    \
96 cl :: method ## _mark (void *self)                      \
97 {                                                       \
98   cl *s = (cl *)self;                                   \
99   scm_gc_mark (s->self_scm ());                         \
100 }                                                       \
101 Listener                                                \
102 cl :: method ## _listener () const                      \
103 {                                                       \
104   static Listener_function_table callbacks;             \
105   callbacks.listen_callback = &cl::method ## _callback; \
106   callbacks.mark_callback = &cl::method ## _mark;       \
107   return Listener (this, &callbacks);                   \
108 }
109
110 #define GET_LISTENER(proc) proc ## _listener ()
111
112 #define DECLARE_LISTENER(name)                          \
113   inline void name (SCM);                               \
114   static void name ## _callback (void *self, SCM ev);   \
115   static void name ## _mark (void *self);               \
116   Listener name ## _listener () const
117
118 #endif /* LISTENER_HH */