]> git.donarmstrong.com Git - lilypond.git/blob - lily/translator.cc
a277eab16d96f86ffc7e7c2e2188a434f812357c
[lilypond.git] / lily / translator.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--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 #include "translator.hh"
21
22 #include "context-def.hh"
23 #include "dispatcher.hh"
24 #include "global-context.hh"
25 #include "international.hh"
26 #include "translator-group.hh"
27 #include "warn.hh"
28
29 #include "translator.icc"
30
31 using std::string;
32 using std::vector;
33
34 Translator::~Translator ()
35 {
36 }
37
38 void
39 Translator::init ()
40 {
41   daddy_context_ = 0;
42   smobify_self ();
43 }
44
45 void
46 Translator::process_music ()
47 {
48 }
49
50 void
51 Translator::process_acknowledged ()
52 {
53 }
54
55 Translator::Translator ()
56 {
57   init ();
58 }
59
60 Translator::Translator (Translator const &)
61   : Smob<Translator> ()
62 {
63   init ();
64 }
65
66 Moment
67 Translator::now_mom () const
68 {
69   return daddy_context_->now_mom ();
70 }
71
72 Output_def *
73 Translator::get_output_def () const
74 {
75   return daddy_context_->get_output_def ();
76 }
77
78 Translator_group *
79 Translator::get_daddy_translator () const
80 {
81   return daddy_context_->implementation ();
82 }
83
84 void
85 Translator::protect_event (SCM ev)
86 {
87   get_daddy_translator ()->protect_event (ev);
88 }
89
90 SCM
91 Translator::internal_get_property (SCM sym) const
92 {
93   return daddy_context_->internal_get_property (sym);
94 }
95
96 void
97 Translator::stop_translation_timestep ()
98 {
99 }
100
101 /*
102   this function is called once each moment, before any user
103   information enters the translators.  (i.e. no \property or event has
104   been processed yet.)
105 */
106 void
107 Translator::start_translation_timestep ()
108 {
109 }
110
111 void
112 Translator::initialize ()
113 {
114 }
115
116 void
117 Translator::finalize ()
118 {
119 }
120
121 void
122 Translator::connect_to_context (Context *c)
123 {
124   for (SCM r = get_listener_list (); scm_is_pair (r); r = scm_cdr (r))
125     {
126       SCM event_class = scm_caar (r);
127       SCM callback = scm_cdar (r);
128
129       c->events_below ()->add_listener (get_listener (callback),
130                                         event_class);
131     }
132 }
133
134 void
135 Translator::disconnect_from_context (Context *c)
136 {
137   for (SCM r = get_listener_list (); scm_is_pair (r); r = scm_cdr (r))
138     {
139       SCM event_class = scm_caar (r);
140       SCM callback = scm_cdar (r);
141
142       c->events_below ()->remove_listener (get_listener (callback),
143                                            event_class);
144     }
145 }
146
147 SCM
148 Translator::event_class_symbol (const char *ev_class)
149 {
150   /* ev_class is the C++ identifier name. Convert to scm symbol */
151   string name = string (ev_class);
152   name = replace_all (&name, '_', '-');
153   name += "-event";
154
155   return scm_from_ascii_symbol (name.c_str ());
156 }
157
158 /*
159  Helps the individual static_translator_description methods of translators.
160 */
161 SCM
162 Translator::static_translator_description (const char *grobs,
163                                            const char *desc,
164                                            SCM listener_list,
165                                            const char *read,
166                                            const char *write) const
167 {
168   SCM static_properties = SCM_EOL;
169
170   static_properties = scm_acons (ly_symbol2scm ("grobs-created"),
171                                  parse_symbol_list (grobs), static_properties);
172
173   static_properties = scm_acons (ly_symbol2scm ("description"),
174                                  scm_from_utf8_string (desc), static_properties);
175
176   SCM list = SCM_EOL;
177   for (; scm_is_pair (listener_list); listener_list = scm_cdr (listener_list))
178     list = scm_cons (scm_caar (listener_list), list);
179   static_properties = scm_acons (ly_symbol2scm ("events-accepted"),
180                                  list, static_properties);
181
182   static_properties = scm_acons (ly_symbol2scm ("properties-read"),
183                                  parse_symbol_list (read), static_properties);
184
185   static_properties = scm_acons (ly_symbol2scm ("properties-written"),
186                                  parse_symbol_list (write), static_properties);
187
188   return static_properties;
189 }
190
191 /*
192   SMOBS
193 */
194 SCM
195 Translator::mark_smob () const
196 {
197   derived_mark ();
198   return SCM_EOL;
199 }
200
201 Global_context *
202 Translator::get_global_context () const
203 {
204   return daddy_context_->get_global_context ();
205 }
206
207 Context *
208 Translator::get_score_context () const
209 {
210   return daddy_context_->get_score_context ();
211 }
212
213 const char Translator::type_p_name_[] = "ly:translator?";
214
215 bool
216 Translator::must_be_last () const
217 {
218   return false;
219 }
220
221 void
222 Translator::derived_mark () const
223 {
224 }
225
226 int
227 Translator::print_smob (SCM port, scm_print_state *) const
228 {
229   scm_puts ("#<Translator ", port);
230   scm_puts (class_name (), port);
231   scm_puts (" >", port);
232   return 1;
233 }
234
235 void
236 add_acknowledger (Translator::Grob_info_callback ptr,
237                   char const *func_name,
238                   vector<Acknowledge_information> *ack_array)
239 {
240   Acknowledge_information inf;
241   inf.function_ = ptr;
242
243   string interface_name (func_name);
244
245   interface_name = replace_all (&interface_name, '_', '-');
246   interface_name += "-interface";
247
248   /*
249     this is only called during program init, so safe to use scm_gc_protect_object ()
250   */
251   inf.symbol_ = scm_gc_protect_object (ly_symbol2scm (interface_name.c_str ()));
252   ack_array->push_back (inf);
253 }
254
255 Translator::Grob_info_callback
256 generic_get_acknowledger (SCM sym, vector<Acknowledge_information> const *ack_array)
257 {
258   for (vsize i = 0; i < ack_array->size (); i++)
259     {
260       if (ack_array->at (i).symbol_ == sym)
261         return ack_array->at (i).function_;
262     }
263   return 0;
264 }
265
266 Moment
267 get_event_length (Stream_event *e)
268 {
269   Moment *m = unsmob<Moment> (e->get_property ("length"));
270   if (m)
271     return *m;
272   else
273     return Moment (0);
274 }
275
276 Moment
277 get_event_length (Stream_event *e, Moment now)
278 {
279   Moment len = get_event_length (e);
280
281   if (now.grace_part_)
282     {
283       len.grace_part_ = len.main_part_;
284       len.main_part_ = Rational (0);
285     }
286   return len;
287 }
288
289 /*
290   Helper, used through ASSIGN_EVENT_ONCE to throw warnings for
291   simultaneous events. The helper is only useful in listen_* methods
292   of translators.
293 */
294 bool
295 internal_event_assignment (Stream_event **old_ev, Stream_event *new_ev, const char *function)
296 {
297   if (*old_ev
298       && !to_boolean (scm_equal_p ((*old_ev)->self_scm (),
299                                    new_ev->self_scm ())))
300     {
301       /* extract event class from function name */
302       string ev_class = function;
303
304       /* This assertion fails if EVENT_ASSIGNMENT was called outside a
305          translator listener. Don't do that. */
306       const char *prefix = "listen_";
307       assert (0 == ev_class.find (prefix));
308
309       /* "listen_foo_bar" -> "foo-bar" */
310       ev_class.erase (0, strlen (prefix));
311       replace_all (&ev_class, '_', '-');
312
313       new_ev->origin ()->warning (_f ("Two simultaneous %s events, junking this one", ev_class.c_str ()));
314       (*old_ev)->origin ()->warning (_f ("Previous %s event here", ev_class.c_str ()));
315       return false;
316     }
317   else
318     {
319       *old_ev = new_ev;
320       return true;
321     }
322 }
323
324 ADD_TRANSLATOR (Translator,
325                 /* doc */
326                 "Base class.  Not instantiated.",
327
328                 /* create */
329                 "",
330
331                 /* read */
332                 "",
333
334                 /* write */
335                 ""
336                );