]> git.donarmstrong.com Git - lilypond.git/blob - src/complexwalker.cc
release: 0.0.30
[lilypond.git] / src / complexwalker.cc
1 #include "associter.hh"
2 #include "script.hh"
3 #include "request.hh"
4 #include "voice.hh"
5 #include "clef.hh"
6 #include "pscore.hh"
7 #include "complexstaff.hh"
8 #include "debug.hh"
9 #include "keyitem.hh"
10 #include "clefitem.hh"
11 #include "voicegroup.hh"
12 #include "localkeyreg.hh"
13 #include "complexwalker.hh"
14 #include "misc.hh"
15
16 Rhythmic_grouping
17 parse_grouping(Array<Scalar> const &a)
18 {
19     Array<int> r;
20     Array<Moment> grouplen_arr;
21     for (int i= 0 ; i < a.size()/2; ) {
22         r.push(a[i++]);
23         grouplen_arr.push(Moment(1,(int) a[i++]));
24     }
25     Moment here =0;
26
27     Array<Rhythmic_grouping*> children;
28     for (int i=0; i < r.size(); i++) {
29         
30         Moment last = here;
31         here += grouplen_arr[i] * Rational(r[i]);
32         children.push(
33             new Rhythmic_grouping(MInterval(last, here), r[i] ));
34     }
35     return Rhythmic_grouping(children);
36 }
37
38 void
39 Complex_walker::do_INTERPRET_command(Command*com_l)
40 {
41     Array<Scalar> args(com_l->args);
42     args.del(0);
43     String com = com_l->args[0];
44     
45     if (com == "GROUPING") {    
46         default_grouping = parse_grouping(args);
47     }else if (com == "NEWMEASURE") {
48         local_key_.reset(key_);
49
50     } else if (com == "KEY") {
51         
52         if (col()->when() > Moment(0)) {
53             assert(!oldkey_undo);
54             oldkey_undo = new Array<int>( key_.oldkey_undo(args));
55         }
56         
57         typesetkey = key_.read(args);
58         local_key_.reset(key_); 
59     } else if (com == "CLEF") {
60         clef_.set_type(args[0]);
61     } else {
62         WARN << " ignoring INTERPRET command: " << com<< "\n";
63     }
64 }
65
66 void
67 Complex_walker::do_TYPESET_command(Command*com)
68 {
69     /* ignore these commands if non-default versions have been
70       processed.  */
71     if (com->args[0] == "CURRENTKEY") 
72         if (processed_key) 
73             return;
74         else
75             com->args[0] = "KEY"; // urgh
76     
77     if (com->args[0] == "CURRENTCLEF") {
78         if (processed_clef) 
79             return;
80     }
81     if (com->args[0] == "BAR") {
82         
83         if (processed_bar_priority > com->priority)
84             return;
85         else
86             processed_bar_priority = com->priority;
87     }
88
89     Item* i = staff()->get_TYPESET_item(com);
90     if (!i)
91         return;
92
93     if (com->args[0] == "KEY") {
94         ((Keyitem*) i)->read(clef_);
95         if (oldkey_undo) {
96             ((Keyitem*) i)->read(*oldkey_undo);
97             delete oldkey_undo;
98             oldkey_undo = 0;
99         }
100         processed_key = true;
101         
102         ((Keyitem*) i)->read(typesetkey); // ugh        
103     }
104
105     if (com->args[0] == "CLEF"||com->args[0] == "CURRENTCLEF") {
106         processed_clef =true;
107         Clef_item*c=(Clef_item*)i;
108         c->read(clef_);
109         c->change = (break_status != BREAK_POST - BREAK_PRE);
110     }
111     col()->typeset_item_directional(i, 1, break_status);
112 }
113
114 void
115 Complex_walker::announce_element(Staff_elem_info info)
116 {
117     info.group_regs_l_ = find_voice_group((Voice*)info.voice_l_);
118     announce_info_arr_.push(info);
119 }
120
121 void
122 Complex_walker::do_announces()
123 {
124     for (int i = 0; i < announce_info_arr_.size(); i++){
125         Staff_elem_info info = announce_info_arr_[i];
126         for (iter_top(voice_reg_list_,j); j.ok(); j++) {
127             j->acknowledge_element(info);
128         }
129         for (iter_top ( group_reg_list_, j); j.ok(); j++) {
130             j->acknowledge_element(info);
131         }
132         local_key_reg_.acknowledge_element(info);
133     }
134 }
135
136 Voice_registers *
137 Complex_walker::find_voice_reg(Voice*v_l)const
138 {
139    for (iter_top(voice_reg_list_, i); i.ok(); i++) {
140         if (i->voice_l_ == v_l)
141             return i;
142    }
143    return 0;
144 }
145
146 Voice_registers*
147 Complex_walker::get_voice_reg(Voice*v_l)
148 {
149     Voice_registers *regs_p=find_voice_reg(v_l);
150     if (regs_p)
151         return regs_p;
152     
153     regs_p = new Voice_registers(this,v_l);
154     voice_reg_list_.bottom().add (regs_p);
155     return regs_p;
156 }
157
158 Voice_group_registers *
159 Complex_walker::find_voice_group(Voice* v_l)const
160 {
161     if (!voice_group_map_.elt_query(v_l))
162         return 0;
163     else return voice_group_map_[v_l];
164 }
165
166 Voice_group_registers *
167 Complex_walker::find_voice_group(const char *id)const
168 {
169     for (iter_top(group_reg_list_, i); i.ok(); i++)
170         if (i->group_id_str_ == id)
171             return i;
172     return 0;
173 }
174
175
176 Voice_group_registers *
177 Complex_walker::get_voice_group(Voice *v_l)
178 {
179     Voice_group_registers *group_p = find_voice_group(v_l);
180     if (group_p)
181         return group_p;
182     
183     group_p = new Voice_group_registers(this);
184     group_reg_list_.bottom().add(group_p);
185     voice_group_map_[v_l] = group_p;
186     return group_p;
187 }
188
189
190 Voice_group_registers *
191 Complex_walker::get_voice_group(const char* id)
192 {
193     Voice_group_registers *group_p = find_voice_group(id);
194     if (group_p)
195         return group_p;
196     group_p = new Voice_group_registers(this,id);
197     group_reg_list_.bottom().add(group_p);
198     return group_p;
199 }
200
201 void 
202 Complex_walker::do_change_group(Voice * v, String group_id_str)
203 {
204     voice_group_map_[v] = get_voice_group(group_id_str);
205 }
206
207 void
208 Complex_walker::try_request(Request*req)
209 {
210     bool b=false;
211     Voice *voice_l = req->elt_l_->voice_l_;
212
213     if (req->groupchange()) {
214         do_change_group(voice_l, req->groupchange()->newgroup_str_);
215         b = true;
216     } else if (Voice_registers::acceptable_request(req)) {
217         Voice_registers *vregs_l = get_voice_reg(voice_l);
218         b = vregs_l->try_request(req);
219     } else if (Voice_group_registers::acceptable_request(req)){
220         Voice_group_registers* reg_l = get_voice_group(voice_l);
221         b = reg_l->try_request(req);
222     } 
223
224     if (!b)
225         warning("junking request: "  + String(req->name()), req->defined_ch_c_l_m);
226 }
227
228 void
229 Complex_walker::process_requests()
230 {
231     Complex_column*c = col();
232
233     for (int i=0; i < c->first_l_arr_.size(); i++) {
234         try_request(c->first_l_arr_[i]);
235     }
236
237     for (int i=0; i < c->second_l_arr_.size(); i++) {
238         try_request(c->second_l_arr_[i]);
239     }
240
241     regs_process_requests();
242     do_announces();
243 }
244
245 void
246 Complex_walker::regs_process_requests()
247 {
248     for (iter_top(voice_reg_list_, j); j.ok(); j++) {
249         j->process_requests();
250     }
251     for (iter_top(group_reg_list_, j); j.ok(); j++) 
252         j->process_requests();
253     
254     local_key_reg_.process_request();
255 }
256
257 void
258 Complex_walker::typeset_element(Staff_elem *elem_p)
259 {
260     if (!elem_p)
261         return;
262     if (elem_p->spanner())
263         pscore_l_->typeset_spanner(elem_p->spanner(), staff()->pstaff_l_);
264     else
265         col()->typeset_item(elem_p->item()); 
266 }
267
268 Complex_walker::Complex_walker(Complex_staff*s)
269     : Staff_walker(s, s->pstaff_l_->pscore_l_),
270       local_key_reg_(this)      
271 {
272     oldkey_undo = 0;
273     do_post_move();
274 }
275
276 Complex_staff*
277 Complex_walker::staff()
278 {
279     return (Complex_staff*) staff_l_;
280 }
281
282 Complex_column*
283 Complex_walker::col()
284 {
285     return (Complex_column*) *(*this);
286 }
287
288 void
289 Complex_walker::do_pre_move()
290 {
291     for (iter_top(voice_reg_list_,i); i.ok(); i++) {
292         i->pre_move_processing();   
293     }
294     for (iter_top (group_reg_list_, j); j.ok(); j++) 
295         j->pre_move_processing();
296     local_key_reg_.pre_move_processing();
297 }
298
299 void
300 Complex_walker::do_post_move()
301 {
302     processed_clef = false;    
303     processed_key = false;
304     processed_bar_priority = 0;
305     
306     for (iter_top(voice_reg_list_,i); i.ok(); i++) {
307         i->post_move_processing();   
308     }
309     announce_info_arr_.set_size(0);
310     for (iter_top (group_reg_list_, j); j.ok(); j++) 
311         j->post_move_processing();
312     local_key_reg_.post_move_processing();
313 }
314
315 Array<Voice_registers*>
316 Complex_walker::get_voice_regs(Voice_group_registers* group_regs_l) const
317     return l_arr;
318 {
319     for (Assoc_iter<Voice*,Voice_group_registers*> i(voice_group_map_); i.ok(); i++) {
320         if (i.val() == group_regs_l)
321             l_arr.push(find_voice_reg(i.key()));
322     }
323 }