]> git.donarmstrong.com Git - lilypond.git/blob - lily/translator-group.cc
* lily/chord-tremolo-*.cc: Reworked how \repeat "tremolo"
[lilypond.git] / lily / translator-group.cc
1 /*
2   translator-group.cc -- implement Translator_group
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>,
7                  Erik Sandberg <mandolaerik@gmail.com>
8 */
9
10 #include "translator-group.hh"
11
12 #include "context-def.hh"
13 #include "context.hh"
14 #include "dispatcher.hh"
15 #include "main.hh"
16 #include "music.hh"
17 #include "output-def.hh"
18 #include "scm-hash.hh"
19 #include "stream-event.hh"
20 #include "warn.hh"
21
22 Translator_group *
23 Translator_group::get_daddy_translator () const
24 {
25   return context ()->get_parent_context ()->implementation ();
26 }
27
28 void
29 translator_each (SCM list, Translator_method method)
30 {
31   for (SCM p = list; scm_is_pair (p); p = scm_cdr (p))
32     (unsmob_translator (scm_car (p))->*method) ();
33 }
34
35 void
36 Translator_group::initialize ()
37 {
38   precompute_method_bindings ();
39 }
40
41 void
42 Translator_group::connect_to_context (Context *c)
43 {
44   if (context_)
45     programming_error ("already connected to a context");
46   context_ = c;
47   c->event_source ()->add_listener (GET_LISTENER (eat_event), ly_symbol2scm ("MusicEvent"));
48 }
49
50 void
51 Translator_group::finalize ()
52 {
53 }
54
55 bool
56 translator_accepts_any_of (Translator *tr, SCM ifaces)
57 {
58   SCM ack_ifs = scm_assoc (ly_symbol2scm ("events-accepted"),
59                            tr->translator_description ());
60   ack_ifs = scm_cdr (ack_ifs);
61   for (SCM s = ifaces; scm_is_pair (s); s = scm_cdr (s))
62     if (scm_c_memq (scm_car (s), ack_ifs) != SCM_BOOL_F)
63       return true;
64   return false;
65 }
66
67 SCM
68 find_accept_translators (SCM gravlist, SCM ifaces)
69 {
70   SCM l = SCM_EOL;
71   for (SCM s = gravlist; scm_is_pair (s); s = scm_cdr (s))
72     {
73       Translator *tr = unsmob_translator (scm_car (s));
74       if (translator_accepts_any_of (tr, ifaces))
75         l = scm_cons (tr->self_scm (), l);
76     }
77   l = scm_reverse_x (l, SCM_EOL);
78
79   return l;
80 }
81
82 IMPLEMENT_LISTENER (Translator_group, eat_event);
83 void
84 Translator_group::eat_event (SCM sev)
85 {
86   Stream_event *ev = unsmob_stream_event (sev);
87   SCM sm = ev->get_property ("music");
88   Music *m = unsmob_music (sm);
89   try_music (m);
90 }
91
92 bool
93 Translator_group::try_music (Music *m)
94 {
95   SCM name = scm_sloppy_assq (ly_symbol2scm ("name"),
96                               m->get_property_alist (false));
97
98   if (!scm_is_pair (name))
99     return false;
100
101   name = scm_cdr (name);
102   SCM accept_list = scm_hashq_ref (accept_hash_table_, name, SCM_UNDEFINED);
103   if (accept_list == SCM_BOOL_F)
104     {
105       accept_list = find_accept_translators (get_simple_trans_list (),
106                                              m->get_property ("types"));
107       scm_hashq_set_x (accept_hash_table_, name, accept_list);
108     }
109
110   for (SCM p = accept_list; scm_is_pair (p); p = scm_cdr (p))
111     {
112       Translator *t = unsmob_translator (scm_car (p));
113       if (t && t->try_music (m))
114         return true;
115     }
116   return false;
117 }
118
119 SCM
120 Translator_group::get_simple_trans_list ()
121 {
122   return simple_trans_list_;
123 }
124
125 void
126 precomputed_recurse_over_translators (Context *c, Translator_precompute_index idx, Direction dir)
127 {
128   Translator_group *tg
129     = dynamic_cast<Translator_group *> (c->implementation ());
130
131   if (dir == DOWN)
132     {
133       tg->precomputed_translator_foreach (idx);
134       tg->call_precomputed_self_method (idx);
135     }
136
137   for (SCM s = c->children_contexts (); scm_is_pair (s);
138        s = scm_cdr (s))
139     precomputed_recurse_over_translators (unsmob_context (scm_car (s)), idx, dir);
140
141   if (dir == UP)
142     {
143       tg->precomputed_translator_foreach (idx);
144       tg->call_precomputed_self_method (idx);
145     }
146 }
147
148 void
149 recurse_over_translators (Context *c, Translator_method ptr, Translator_group_method tg_ptr, Direction dir)
150 {
151   Translator_group *tg
152     = dynamic_cast<Translator_group *> (c->implementation ());
153
154   if (dir == DOWN)
155     {
156       (tg->*tg_ptr) ();
157       translator_each (tg->get_simple_trans_list (), ptr);
158     }
159
160   for (SCM s = c->children_contexts (); scm_is_pair (s);
161        s = scm_cdr (s))
162     recurse_over_translators (unsmob_context (scm_car (s)), ptr, tg_ptr, dir);
163
164   if (dir == UP)
165     {
166       translator_each (tg->get_simple_trans_list (),
167                        ptr);
168
169       (tg->*tg_ptr) ();
170     }
171 }
172
173 Translator_group::Translator_group ()
174 {
175   simple_trans_list_ = SCM_EOL;
176   accept_hash_table_ = SCM_EOL;
177   context_ = 0;
178   smobify_self ();
179
180   accept_hash_table_ = scm_c_make_hash_table (19);
181 }
182
183 void
184 Translator_group::derived_mark () const
185 {
186 }
187
188 void
189 Translator_group::precompute_method_bindings ()
190 {
191   for (SCM s = simple_trans_list_; scm_is_pair (s); s = scm_cdr (s))
192     {
193       Translator *tr = unsmob_translator (scm_car (s));
194       Translator_void_method_ptr ptrs[TRANSLATOR_METHOD_PRECOMPUTE_COUNT];
195       tr->fetch_precomputable_methods (ptrs);
196
197       assert (tr);
198       for (int i = 0; i < TRANSLATOR_METHOD_PRECOMPUTE_COUNT; i++)
199         {
200           if (ptrs[i])
201             precomputed_method_bindings_[i].push_back (Translator_method_binding (tr, ptrs[i]));
202         }
203     }
204
205   fetch_precomputable_methods (precomputed_self_method_bindings_);
206 }
207
208 void
209 Translator_group::precomputed_translator_foreach (Translator_precompute_index idx)
210 {
211   vector<Translator_method_binding> &bindings (precomputed_method_bindings_[idx]);
212   for (vsize i = 0; i < bindings.size (); i++)
213     bindings[i].invoke ();
214 }
215
216 void
217 Translator_group::fetch_precomputable_methods (Translator_group_void_method ptrs[])
218 {
219   for (int i = 0; i < TRANSLATOR_METHOD_PRECOMPUTE_COUNT; i++)
220     ptrs[i] = 0;
221 }
222
223 void
224 Translator_group::call_precomputed_self_method (Translator_precompute_index idx)
225 {
226   if (precomputed_self_method_bindings_[idx])
227     (*precomputed_self_method_bindings_[idx]) (this);
228 }
229
230 Translator_group::~Translator_group ()
231 {
232 }
233
234 #include "ly-smobs.icc"
235
236 IMPLEMENT_SMOBS (Translator_group);
237 IMPLEMENT_DEFAULT_EQUAL_P (Translator_group);
238 IMPLEMENT_TYPE_P (Translator_group, "ly:translator-group?");
239
240 int
241 Translator_group::print_smob (SCM s, SCM port, scm_print_state *)
242 {
243   Translator_group *me = (Translator_group *) SCM_CELL_WORD_1 (s);
244   scm_puts ("#<Translator_group ", port);
245   scm_puts (me->class_name (), port);
246   scm_display (me->simple_trans_list_, port);
247   scm_puts (" >", port);
248   return 1;
249 }
250
251 SCM
252 Translator_group::mark_smob (SCM smob)
253 {
254   Translator_group *me = (Translator_group *)SCM_CELL_WORD_1 (smob);
255
256   me->derived_mark ();
257   scm_gc_mark (me->accept_hash_table_);
258   return me->simple_trans_list_;
259 }