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