]> git.donarmstrong.com Git - lilypond.git/blob - lily/include/translator.icc
fa2e2842bb4d62a94169bb3011d648bbe5cb8317
[lilypond.git] / lily / include / translator.icc
1 /*
2   translator.icc -- declare Translator glue wiring.
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2005--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #ifndef TRANSLATOR_ICC
10 #define TRANSLATOR_ICC
11
12 #include "listener.hh"
13 #include "std-vector.hh"
14 #include "translator.hh"
15
16 /**
17    A macro to automate administration of translators.
18 */
19 #define ADD_THIS_TRANSLATOR(T)                                          \
20   translator_listener_record *T::listener_list_;                        \
21   SCM T::static_description_ = SCM_EOL;                                 \
22   static void _ ## T ## _adder ()                                       \
23   {                                                                     \
24     T *t = new T;                                                       \
25     T::static_description_ = t->static_translator_description ();       \
26     scm_permanent_object (T::static_description_);                      \
27     add_translator (t);                                                 \
28   }                                                                     \
29   SCM T::translator_description () const                                \
30   {                                                                     \
31     return static_description_;                                         \
32   }                                                                     \
33   ADD_GLOBAL_CTOR (_ ## T ## _adder);
34
35 #define ADD_TRANSLATOR(classname, desc, grobs, accepted, read, write)   \
36   Drul_array< vector<Acknowledge_information> > classname::acknowledge_static_array_drul_;      \
37   IMPLEMENT_FETCH_PRECOMPUTABLE_METHODS (classname);                    \
38   ADD_THIS_TRANSLATOR (classname);                                      \
39   Engraver_void_function_engraver_grob_info                             \
40   classname::static_get_acknowledger (SCM sym)                          \
41   {                                                                     \
42     return generic_get_acknowledger (sym, &acknowledge_static_array_drul_[START]);      \
43   }                                                                     \
44   Engraver_void_function_engraver_grob_info                             \
45   classname::static_get_end_acknowledger (SCM sym)                              \
46   {                                                                     \
47     return generic_get_acknowledger (sym, &acknowledge_static_array_drul_[STOP]);       \
48   }                                                                     \
49   SCM                                                                   \
50   classname::static_translator_description () const                     \
51   {                                                                     \
52     SCM static_properties = SCM_EOL;                                    \
53     /*  static_properties = acons (name , gh_str02scm (Translator::name (self_scm ())), \
54         static_properties_);                                            \
55     */                                                                  \
56     static_properties = scm_acons (ly_symbol2scm ("grobs-created"),     \
57                                    parse_symbol_list (grobs), static_properties); \
58                                                                         \
59     static_properties = scm_acons (ly_symbol2scm ("description"),       \
60                                    scm_makfrom0str (desc), static_properties); \
61                                                                         \
62     static_properties = scm_acons (ly_symbol2scm ("events-accepted"),   \
63                                    get_listened_class_list (listener_list_), static_properties); \
64                                                                         \
65     static_properties = scm_acons (ly_symbol2scm ("properties-read"),   \
66                                    parse_symbol_list (read), static_properties); \
67                                                                         \
68     static_properties = scm_acons (ly_symbol2scm ("properties-written"), \
69                                    parse_symbol_list (write), static_properties); \
70                                                                         \
71     return static_properties;                                           \
72   }
73
74 #define IMPLEMENT_FETCH_PRECOMPUTABLE_METHODS(T)                        \
75   void                                                                  \
76   T::fetch_precomputable_methods (Translator_void_method_ptr ptrs[])    \
77   {                                                                     \
78     ptrs[START_TRANSLATION_TIMESTEP] =                                  \
79       ((Translator_void_method_ptr) & T::start_translation_timestep ==  \
80        (Translator_void_method_ptr) & Translator::start_translation_timestep) \
81       ? 0                                                               \
82       : (Translator_void_method_ptr) & T::start_translation_timestep;   \
83                                                                         \
84     ptrs[STOP_TRANSLATION_TIMESTEP] =                                   \
85       ((Translator_void_method_ptr) & T::stop_translation_timestep == (Translator_void_method_ptr) & Translator::stop_translation_timestep) \
86       ? 0                                                               \
87       : (Translator_void_method_ptr) & T::stop_translation_timestep;    \
88                                                                         \
89     ptrs[PROCESS_MUSIC] =                                               \
90       ((Translator_void_method_ptr) & T::process_music == (Translator_void_method_ptr) & Translator::process_music) \
91       ? 0                                                               \
92       : (Translator_void_method_ptr) & T::process_music;                \
93                                                                         \
94     ptrs[PROCESS_ACKNOWLEDGED] =                                        \
95       ((Translator_void_method_ptr) & T::process_acknowledged == (Translator_void_method_ptr) & Translator::process_acknowledged) \
96       ? 0                                                               \
97       : (Translator_void_method_ptr) & T::process_acknowledged;         \
98   }
99
100 void add_acknowledger (Engraver_void_function_engraver_grob_info ptr,
101                        char const *func_name,
102                        vector<Acknowledge_information> *ack_array);
103
104 Engraver_void_function_engraver_grob_info
105 generic_get_acknowledger (SCM sym,
106                           vector<Acknowledge_information> const *ack_array);
107
108 #define ADD_ACKNOWLEDGER(CLASS, NAME)                                   \
109   void CLASS ## NAME ## _ack_adder ()                                   \
110   {                                                                     \
111     add_acknowledger ((Engraver_void_function_engraver_grob_info) & CLASS::acknowledge_ ## NAME, #NAME, &CLASS::acknowledge_static_array_drul_[START]); \
112   }                                                                     \
113   ADD_SCM_INIT_FUNC (CLASS ## NAME ## _ack_adder_initclass, CLASS ## NAME ## _ack_adder);
114
115 #define ADD_END_ACKNOWLEDGER(CLASS, NAME)                                       \
116   void CLASS ## NAME ## _end_ack_adder ()                                       \
117   {                                                                     \
118     add_acknowledger ((Engraver_void_function_engraver_grob_info) & CLASS::acknowledge_end_ ## NAME, #NAME, &CLASS::acknowledge_static_array_drul_[STOP]); \
119   }                                                                     \
120   ADD_SCM_INIT_FUNC (CLASS ## NAME ## _end_ack_adder_initclass, CLASS ## NAME ## _end_ack_adder);
121
122 /*
123   Implement the method cl::listen_##m, and make it listen to stream 
124   events of class m.
125  */
126 #define IMPLEMENT_TRANSLATOR_LISTENER(cl, m)            \
127 void                                                    \
128 cl :: _internal_declare_ ## m ()                        \
129 {                                                       \
130   static translator_listener_record r;                  \
131   add_translator_listener (&listener_list_, &r, _get_ ## m ## _listener, #m); \
132 }                                                       \
133                                                         \
134 ADD_SCM_INIT_FUNC (cl ## _declare_event_ ## m, cl::_internal_declare_ ## m);    \
135                                                         \
136 Listener                                                \
137 cl :: _get_ ## m ## _listener (void *me)                \
138 {                                                       \
139   cl *obj = (cl *) me;                                  \
140   return obj->GET_LISTENER (_listen_scm_ ## m);         \
141 }                                                       \
142                                                         \
143 IMPLEMENT_LISTENER (cl, _listen_scm_ ## m)              \
144 void                                                    \
145 cl::_listen_scm_ ## m (SCM sev)                         \
146 {                                                       \
147   Stream_event *ev = unsmob_stream_event (sev);         \
148   protect_event (sev);                                  \
149   listen_ ## m (ev);                                    \
150 }
151
152 /*
153   This helper is only meaningful inside listen_* methods.
154 */
155 extern bool internal_event_assignment (Stream_event **old_ev, Stream_event *new_ev, const char *function);
156 #define ASSIGN_EVENT_ONCE(o,n) internal_event_assignment (&o, n, __FUNCTION__)
157
158 #endif /* TRANSLATOR_ICC */