]> git.donarmstrong.com Git - lilypond.git/blob - score.cc
release: 0.0.3
[lilypond.git] / score.cc
1
2 #include "tstream.hh"
3 #include "score.hh"
4 #include "pscore.hh"
5 #include "staff.hh"
6 #include "misc.hh"
7 #include "debug.hh"
8
9 void
10 Score::add_command_seq(svec<Command *> com)
11 {
12     if (!com.sz())
13         return;
14     Real when = com[0]->when;
15
16     PCursor<Command*> pc(commands_);    
17     while (pc.ok()&&pc->when <= when)
18         pc++;
19     
20     for (int i = 0; i < com.sz(); i++) {
21         assert(com[i]->when == when);
22         if (!pc.ok())
23             pc.add(com[i]);
24         else
25             pc.insert(com[i]);
26     }
27     
28 }
29
30 void
31 Score::add(Command *c)
32 {
33     svec<Command*> seq;    
34     if (c->code == TYPESET && c->args[0] == "BAR") {
35         /* should be encapsulated in BREAKs
36
37            THIS SUX.
38
39          */
40
41         Command k;
42         
43         k.when = c->when;
44         k.code = BREAK_PRE;
45         
46         seq.add(new Command(k));
47         seq.add(new Command(*c));
48         k.code = BREAK_MIDDLE;
49         seq.add(new Command(k));
50         seq.add(new Command(*c));
51         k.code = BREAK_POST;
52         seq.add(new Command(k));
53         k.code = BREAK_END;
54         seq.add(new Command(k));
55     }
56     else
57         seq.add(new Command(*c));
58     
59     add_command_seq(seq);
60 }
61
62 void
63 Score::add(Staff*s)
64 {
65     s->score_ = this;
66     staffs_.bottom().add(s);    
67 }
68
69
70 void
71 Score::do_pcols()
72 {
73     PCursor<Score_column*> sc(cols_);
74     for (;sc.ok(); sc++) {
75         pscore_->add(sc->pcol);
76     }
77 }
78 /*
79     this sux. Really makeshift.
80
81     first and last column should be breakable.
82     Remove any command past the last musical column.
83     */
84 void
85 Score::do_miscs()
86 {
87     Command c;
88
89     {
90         Command c;
91         c.when = 0.0;
92         c.code = TYPESET;
93         c.args.add("BAR");
94         c.args.add("empty");
95         add(&c);
96     }
97     
98     PCursor<Command*> bot(commands_.bottom());
99     Real l = last();    
100     while (bot.ok() && bot->when > l) {
101
102         mtor <<"removing "<< bot->code <<" at " << bot->when<<'\n';
103         bot.del();
104         bot = commands_.bottom();
105     }
106
107     if (bot->when != l || bot->code != BREAK_END) {
108         Command c;
109         c.code = TYPESET;
110         c.when = l;
111         c.args.add("BAR");
112         c.args.add("||");
113         add(&c);
114     }
115    commands_.OK();
116 }
117
118 Mtime
119 Score::last() const
120 {    
121     Mtime l = 0;
122     for (PCursor<Staff*> stc(staffs_); stc.ok(); stc++) {
123         l = MAX(l, stc->last());
124     }
125     return l;
126 }
127 void
128 Score::clean_commands() 
129 {
130     Mtime l= last();
131     for (PCursor<Command*> cc(commands_); cc.ok(); ) {
132         if (cc->when > l){
133             mtor << "remming \n";
134             cc.del();
135         } else
136             cc++;
137     }
138 }
139 void
140 Score::process()
141 {
142      do_miscs();
143     
144     /// distribute commands to disciples
145     distribute_commands();
146     
147     pscore_ = new PScore;
148     for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
149         sc->set_output(pscore_);
150         sc->process();
151     }
152
153     // do this after processing, staffs first have to generate PCols.
154     do_pcols();
155     calc_idealspacing();
156     clean_cols();
157     OK();
158     //    print();
159     pscore_->calc_breaking();
160     // TODO: calculate vertical structs
161     // TODO: calculate mixed structs.
162 }
163
164 // remove empty cols with no spacing attached.
165 /* should rethink ownership of cols
166     */
167 void
168 Score::clean_cols()
169 {    
170     for (PCursor<Staff * > sc(staffs_); sc.ok(); sc++)
171         sc->clean_cols();
172     
173     for (PCursor<Score_column*> c(cols_); c.ok(); ) {
174         if (!c->pcol->used) {
175             mtor << "removing : ";
176             c->print();
177             c.del();
178         } else
179             c++;
180     }
181     
182     pscore_->clean_cols();
183 }
184 /* this sux.  We should have Score_column create the appropriate PCol.
185     Unfortunately, PCols don't know about their position.    
186     */
187 // todo
188 PCursor<Score_column*>
189 Score::create_cols(Mtime w)
190 {
191     Score_column* c1 = new Score_column(w);
192     Score_column* c2 = new Score_column(w);
193     
194     c1->musical = false;
195     c2->musical = true;
196     
197     PCursor<Score_column*> scc(cols_);
198
199     for (; scc.ok(); scc++) {
200         assert(scc->when != w);
201         if (scc->when > w)
202             break;
203     }
204
205     if (!scc.ok()) {
206         cols_.bottom().add(c1);
207         cols_.bottom().add(c2);
208         scc = cols_.bottom();
209         scc --;
210     } else {
211         scc.insert(c1);
212         scc.insert(c2);
213         scc -= 2;
214     }
215     return scc;
216 }
217
218 Score_column*
219 Score::find_col(Mtime w,bool mus)
220 {
221     PCursor<Score_column*> scc(cols_);
222     for (; scc.ok(); scc++) {
223         if (scc->when == w && scc->musical == mus)
224             return scc;
225         if (scc->when > w)
226             break;
227     }
228     scc = create_cols(w);
229     if (mus)
230         scc++;
231     return scc;
232 }
233
234 void
235 Score::distribute_commands(void)
236 {
237     for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
238         sc->add_commands(commands_);
239     }
240 }
241
242
243 void
244 Score::output(String s)
245 {
246     OK();
247     if (outfile=="")
248         outfile = s;
249     
250     *mlog << "output to " << outfile << "...\n";
251     Tex_stream the_output(outfile);    
252     pscore_->output(the_output);
253 }
254
255 void
256 Score::OK() const
257 {
258 #ifndef NDEBUG
259     for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
260         sc->OK();
261         assert(sc->score_ == this);
262     }
263     staffs_.OK();
264     cols_.OK();
265     for (PCursor<Score_column*> cc(cols_); cc.ok() && (cc+1).ok(); cc++) {
266         assert(cc->when <= (cc+1)->when);
267     }
268     for (PCursor<Command*> cc(commands_); cc.ok() && (cc+1).ok(); cc++) {
269         assert(cc->when <= (cc+1)->when);
270     }
271 #endif    
272 }
273
274 void
275 Score::print() const
276 {
277 #ifndef NPRINT
278     mtor << "score {\n"; 
279     for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
280         sc->print();
281     }
282     for (PCursor<Score_column*> sc(cols_); sc.ok(); sc++) {
283         sc->print();
284     }
285     mtor << "}\n";
286 #endif
287 }
288 Score::Score()
289 {
290     pscore_=0;
291 }
292 /****************************************************************/
293
294 Score_column::Score_column(Mtime w)
295 {
296     when = w;
297     pcol = new PCol(0);
298     musical = false;
299 }
300
301 bool
302 Score_column::used() {
303     return pcol->used;
304 }
305
306 void
307 Score_column::print() const
308 {
309     #ifndef NPRINT
310     mtor << "Score_column { mus "<< musical <<" at " <<  when<<'\n';
311     mtor << " # symbols: " << pcol->its.size() << "\n";
312     mtor << "durations: [" ;
313     for (int i=0; i < durations.sz(); i++)
314         mtor << durations[i] << " ";
315     mtor << "]\n}\n";
316     #endif
317 }
318
319