]> git.donarmstrong.com Git - lilypond.git/blob - lily/include/translator.icc
New upstream version 2.19.65
[lilypond.git] / lily / include / translator.icc
1 /* -*- c++ -*-
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2005--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
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 TRANSLATOR_ICC
21 #define TRANSLATOR_ICC
22
23 #include "callback.hh"
24 #include "std-vector.hh"
25 #include "engraver.hh"
26
27 /*
28   TODO: derive "foo-bar-interface" from Foo_bar classname.
29  */
30
31 /**
32    A macro to automate administration of translators.
33 */
34 #define ADD_THIS_TRANSLATOR(T)                                          \
35   static void _ ## T ## _adder ()                                       \
36   {                                                                     \
37     T::boot ();                                                         \
38     add_translator_creator (Translator_creator::alloc<T>()->unprotect (), \
39                             scm_from_ascii_symbol (#T),                 \
40                             T::static_translator_description ());       \
41   }                                                                     \
42   ADD_GLOBAL_CTOR (_ ## T ## _adder);                                   \
43   /* end define */
44
45 #define DEFINE_TRANSLATOR_LISTENER_LIST(T)                              \
46   Protected_scm T::listener_list_ (SCM_EOL);                            \
47   /* end define */
48
49 #define DEFINE_ACKNOWLEDGERS(classname) \
50   Drul_array<Protected_scm> classname::acknowledge_static_array_drul_;  \
51   SCM                                                                   \
52   classname::static_get_acknowledger (SCM sym, Direction start_end)     \
53   {                                                                     \
54     return generic_get_acknowledger                                     \
55       (sym, acknowledge_static_array_drul_[start_end]);                 \
56   }                                                                     \
57   /* end define */
58
59 #define DEFINE_TRANSLATOR_DOC(classname, desc, grobs, read, write)      \
60   SCM                                                                   \
61   classname::static_translator_description ()                           \
62   {                                                                     \
63     return Translator::static_translator_description (grobs, desc, listener_list_, read, write); \
64   }
65
66 #define ADD_TRANSLATOR(classname, desc, grobs, read, write)             \
67   IMPLEMENT_FETCH_PRECOMPUTABLE_METHODS (classname);                    \
68   DEFINE_ACKNOWLEDGERS(classname);                                      \
69   ADD_THIS_TRANSLATOR (classname);                                      \
70   DEFINE_TRANSLATOR_DOC(classname, desc, grobs, read, write);           \
71   DEFINE_TRANSLATOR_LISTENER_LIST(classname);
72
73 #define IMPLEMENT_FETCH_PRECOMPUTABLE_METHODS(T)                        \
74   void                                                                  \
75   T::fetch_precomputable_methods (SCM ptrs[])                           \
76   {                                                                     \
77     ptrs[START_TRANSLATION_TIMESTEP] =                                  \
78       method_finder <&T::start_translation_timestep> ();                \
79                                                                         \
80     ptrs[STOP_TRANSLATION_TIMESTEP] =                                   \
81       method_finder <&T::stop_translation_timestep> ();                 \
82                                                                         \
83     ptrs[PROCESS_MUSIC] =                                               \
84       method_finder <&T::process_music> ();                             \
85                                                                         \
86     ptrs[PROCESS_ACKNOWLEDGED] =                                        \
87       method_finder <&T::process_acknowledged> ();                      \
88   }
89
90 void add_acknowledger (SCM ptr,
91                        char const *func_name,
92                        SCM &ack_hash);
93
94 #define ADD_ACKNOWLEDGER_FOR(CLASS, NAME, GROB)                         \
95   add_acknowledger (method_finder<&CLASS::acknowledge_ ## NAME> (),     \
96                     #GROB, acknowledge_static_array_drul_[START])
97
98 #define ADD_ACKNOWLEDGER(CLASS, NAME) ADD_ACKNOWLEDGER_FOR (CLASS, NAME, NAME)
99
100 // ADD_END_ACKNOWLEDGER_FOR requires your NAME to actually be
101 // end_whatever if you are utilizing acknowledge_end_whatever as a
102 // different end acknowledger.
103 #define ADD_END_ACKNOWLEDGER_FOR(CLASS, NAME, GROB)                     \
104   add_acknowledger (method_finder<&CLASS::acknowledge_ ## NAME> (),     \
105                     #GROB, acknowledge_static_array_drul_[STOP])
106
107 #define ADD_END_ACKNOWLEDGER(CLASS, NAME)               \
108   ADD_END_ACKNOWLEDGER_FOR (CLASS, end_ ## NAME, NAME)
109
110 /*
111   Implement the method cl::listen_##m, and make it listen to stream
112   events of class m.
113
114   At macro call time, neither creator instances (which are anonymous
115   and only accessible via the translator registry) nor translator
116   instances exist, so the only named place where we can store it is in
117   a static member of the translator class.
118  */
119 #define ADD_LISTENER_FOR(cl, m, ev)                                     \
120   listener_list_ = scm_acons                                            \
121     (event_class_symbol (#ev),                                          \
122      method_finder<&cl::listen_ ## m> (),                               \
123      listener_list_)
124
125 #define ADD_LISTENER(cl, m) ADD_LISTENER_FOR (cl, m, m)
126
127 #endif /* TRANSLATOR_ICC */