]> git.donarmstrong.com Git - lilypond.git/blob - lily/translator.cc
*** empty log message ***
[lilypond.git] / lily / translator.cc
1 /*
2   translator.cc -- implement Translator
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "translator.hh"
10
11 #include "context-def.hh"
12 #include "dispatcher.hh"
13 #include "global-context.hh"
14 #include "international.hh"
15 #include "translator-group.hh"
16 #include "warn.hh"
17
18 #include "translator.icc"
19 #include "ly-smobs.icc"
20
21 Translator::~Translator ()
22 {
23 }
24
25 void
26 Translator::init ()
27 {
28   must_be_last_ = false;
29   self_scm_ = SCM_EOL;
30   daddy_context_ = 0;
31   smobify_self ();
32 }
33
34 void
35 Translator::process_music ()
36 {
37 }
38
39 void
40 Translator::process_acknowledged ()
41 {
42 }
43
44 Translator::Translator ()
45 {
46   init ();
47 }
48
49 Translator::Translator (Translator const &src)
50 {
51   init ();
52   must_be_last_ = src.must_be_last_;
53 }
54
55 bool
56 Translator::try_music (Music *)
57 {
58   return false;
59 }
60
61 Moment
62 Translator::now_mom () const
63 {
64   return daddy_context_->now_mom ();
65 }
66
67 Output_def *
68 Translator::get_output_def () const
69 {
70   return daddy_context_->get_output_def ();
71 }
72
73 Translator_group *
74 Translator::get_daddy_translator () const
75 {
76   return daddy_context_->implementation ();
77 }
78
79 void
80 Translator::protect_event (SCM ev)
81 {
82   get_daddy_translator ()->protect_event (ev);
83 }
84
85 SCM
86 Translator::internal_get_property (SCM sym) const
87 {
88   return daddy_context_->internal_get_property (sym);
89 }
90
91 void
92 Translator::stop_translation_timestep ()
93 {
94 }
95
96 /*
97   this function has 2 properties
98
99   - It is called before try_music ()
100
101   - It is called before any user information enters the translators.
102   (i.e. any \property or event is not processed yet.)
103 */
104 void
105 Translator::start_translation_timestep ()
106 {
107 }
108
109 void
110 Translator::initialize ()
111 {
112 }
113
114 void
115 Translator::finalize ()
116 {
117 }
118
119 void
120 Translator::connect_to_context (Context *c)
121 {
122   for (translator_listener_record *r = get_listener_list (); r; r=r->next_)
123     c->events_below ()->add_listener (r->get_listener_ (this), r->event_class_);
124 }
125
126 void
127 Translator::disconnect_from_context (Context *c)
128 {
129   for (translator_listener_record *r = get_listener_list (); r; r=r->next_)
130     c->events_below ()->remove_listener (r->get_listener_ (this), r->event_class_);
131 }
132
133 static SCM listened_event_classes = SCM_EOL;
134
135 LY_DEFINE (ly_get_listened_event_classes, "ly:get-listened-event-classes",
136            0, 0, 0, (),
137            "Returns a list of all event classes that some translator listens to.")
138 {
139   return listened_event_classes;
140 }
141
142 /*
143   Internally called once, statically, for each translator
144   listener. Connects the name of an event class with a procedure that
145   fetches the corresponding listener.
146
147   The method should only be called from the macro
148   IMPLEMENT_TRANSLATOR_LISTENER.
149  */
150 void
151 Translator::add_translator_listener (translator_listener_record **listener_list,
152                          translator_listener_record *r,
153                          Listener (*get_listener) (void *), 
154                          const char *ev_class)
155 {
156   /* ev_class is the C++ identifier name. Convert to scm symbol */
157   string name = string (ev_class);
158   name = replace_all (name, '_', '-');
159   name = name + "-event";
160   /* It's OK to use scm_gc_protect_object for protection, because r is
161      statically allocated. */
162   SCM class_sym = scm_gc_protect_object (scm_str2symbol (name.c_str ()));
163   listened_event_classes = scm_gc_protect_object (scm_cons (class_sym, listened_event_classes));
164   r->event_class_ = class_sym;
165   r->get_listener_ = get_listener;
166   r->next_ = *listener_list;
167   *listener_list = r;
168 }
169
170 /*
171   SMOBS
172 */
173 SCM
174 Translator::mark_smob (SCM sm)
175 {
176   Translator *me = (Translator *) SCM_CELL_WORD_1 (sm);
177   me->derived_mark ();
178   return SCM_EOL;
179 }
180
181 Global_context *
182 Translator::get_global_context () const
183 {
184   return daddy_context_->get_global_context ();
185 }
186
187 Context *
188 Translator::get_score_context () const
189 {
190   return daddy_context_->get_score_context ();
191 }
192
193 IMPLEMENT_SMOBS (Translator);
194 IMPLEMENT_DEFAULT_EQUAL_P (Translator);
195 IMPLEMENT_TYPE_P (Translator, "ly:translator?");
196
197 bool
198 Translator::must_be_last () const
199 {
200   return must_be_last_;
201 }
202
203 void
204 Translator::derived_mark () const
205 {
206 }
207
208 int
209 Translator::print_smob (SCM s, SCM port, scm_print_state *)
210 {
211   Translator *me = (Translator *) SCM_CELL_WORD_1 (s);
212   scm_puts ("#<Translator ", port);
213   scm_puts (me->class_name (), port);
214   scm_puts (" >", port);
215   return 1;
216 }
217
218 void
219 add_acknowledger (Engraver_void_function_engraver_grob_info ptr,
220                   char const *func_name,
221                   vector<Acknowledge_information> *ack_array)
222 {
223   Acknowledge_information inf;
224   inf.function_ = ptr;
225
226   string interface_name (func_name);
227
228   interface_name = replace_all (interface_name, '_', '-');
229   interface_name += "-interface";
230
231   inf.symbol_ = scm_gc_protect_object (ly_symbol2scm (interface_name.c_str ()));
232   ack_array->push_back (inf);
233 }
234
235 Engraver_void_function_engraver_grob_info
236 generic_get_acknowledger (SCM sym, vector<Acknowledge_information> const *ack_array)
237 {
238   for (vsize i = 0; i < ack_array->size (); i++)
239     {
240       if (ack_array->at (i).symbol_ == sym)
241         return ack_array->at (i).function_;
242     }
243   return 0;
244 }
245
246 Moment
247 get_event_length (Stream_event *e)
248 {
249   Moment *m = unsmob_moment (e->get_property ("length"));
250   if (m)
251     return *m;
252   else
253     return Moment (0);
254 }
255
256 /*
257   Helper, used through ASSIGN_EVENT_ONCE to throw warnings for
258   simultaneous events. The helper is only useful in listen_* methods
259   of translators.
260 */
261 bool
262 internal_event_assignment (Stream_event **old_ev, Stream_event *new_ev, const char *function)
263 {
264   if (*old_ev)
265     {
266       /* extract event class from function name */
267       const char *prefix = "listen_";
268       assert (!strncmp (function, "listen_", strlen (prefix)));
269       function += strlen (prefix);
270       char ev_class[strlen (function) + 1];
271       strcpy (ev_class, function);
272       for (char *c = ev_class; *c; c++)
273         if (*c == '_')
274           *c = '-';
275
276       new_ev->origin ()->warning (_f ("Two simultaneous %s events, junking this one", ev_class));
277       (*old_ev)->origin ()->warning (_f ("Previous %s event here", ev_class));
278       return false;
279     }
280   else
281     {
282       *old_ev = new_ev;
283       return true;
284     }
285 }
286
287 ADD_TRANSLATOR (Translator,
288                 "Base class. Unused",
289                 "",
290                 "",
291                 "",
292                 "");