lilypond-0.0.4
[lilypond.git] / score.cc
blobf5e357ecdbab7bfa3b13794d3154a6691d96870d
2 #include "tstream.hh"
3 #include "score.hh"
4 #include "pscore.hh"
5 #include "staff.hh"
6 #include "misc.hh"
7 #include "debug.hh"
9 void
10 Score::add_command_seq(svec<Command *> com)
12 if (!com.sz())
13 return;
14 Real when = com[0]->when;
16 PCursor<Command*> pc(commands_);
17 while (pc.ok()&&pc->when <= when)
18 pc++;
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]);
30 void
31 Score::add(Command *c)
33 svec<Command*> seq;
34 if (c->code == TYPESET && c->args[0] == "BAR") {
35 /* should be encapsulated in BREAKs
37 THIS SUX.
41 Command k;
43 k.when = c->when;
44 k.code = BREAK_PRE;
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));
56 else
57 seq.add(new Command(*c));
59 add_command_seq(seq);
62 void
63 Score::add(Staff*s)
65 s->score_ = this;
66 staffs_.bottom().add(s);
70 void
71 Score::do_pcols()
73 PCursor<Score_column*> sc(cols_);
74 for (;sc.ok(); sc++) {
75 pscore_->add(sc->pcol);
79 this sux. Really makeshift.
81 first and last column should be breakable.
82 Remove any command past the last musical column.
84 void
85 Score::do_miscs()
87 Command c;
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);
98 PCursor<Command*> bot(commands_.bottom());
99 Real l = last();
100 while (bot.ok() && bot->when > l) {
102 mtor <<"removing "<< bot->code <<" at " << bot->when<<'\n';
103 bot.del();
104 bot = commands_.bottom();
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);
115 commands_.OK();
118 Mtime
119 Score::last() const
121 Mtime l = 0;
122 for (PCursor<Staff*> stc(staffs_); stc.ok(); stc++) {
123 l = MAX(l, stc->last());
125 return l;
127 void
128 Score::clean_commands()
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++;
139 void
140 Score::process()
142 do_miscs();
144 /// distribute commands to disciples
145 distribute_commands();
147 pscore_ = new PScore;
148 for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
149 sc->set_output(pscore_);
150 sc->process();
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.
164 // remove empty cols with no spacing attached.
165 /* should rethink ownership of cols
167 void
168 Score::clean_cols()
170 for (PCursor<Staff * > sc(staffs_); sc.ok(); sc++)
171 sc->clean_cols();
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++;
182 pscore_->clean_cols();
184 /* this sux. We should have Score_column create the appropriate PCol.
185 Unfortunately, PCols don't know about their position.
187 // todo
188 PCursor<Score_column*>
189 Score::create_cols(Mtime w)
191 Score_column* c1 = new Score_column(w);
192 Score_column* c2 = new Score_column(w);
194 c1->musical = false;
195 c2->musical = true;
197 PCursor<Score_column*> scc(cols_);
199 for (; scc.ok(); scc++) {
200 assert(scc->when != w);
201 if (scc->when > w)
202 break;
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;
215 return scc;
218 Score_column*
219 Score::find_col(Mtime w,bool mus)
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;
228 scc = create_cols(w);
229 if (mus)
230 scc++;
231 return scc;
234 void
235 Score::distribute_commands(void)
237 for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
238 sc->add_commands(commands_);
243 void
244 Score::output(String s)
246 OK();
247 if (outfile=="")
248 outfile = s;
250 *mlog << "output to " << outfile << "...\n";
251 Tex_stream the_output(outfile);
252 pscore_->output(the_output);
255 void
256 Score::OK() const
258 #ifndef NDEBUG
259 for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
260 sc->OK();
261 assert(sc->score_ == this);
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);
268 for (PCursor<Command*> cc(commands_); cc.ok() && (cc+1).ok(); cc++) {
269 assert(cc->when <= (cc+1)->when);
271 #endif
274 void
275 Score::print() const
277 #ifndef NPRINT
278 mtor << "score {\n";
279 for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
280 sc->print();
282 for (PCursor<Score_column*> sc(cols_); sc.ok(); sc++) {
283 sc->print();
285 mtor << "}\n";
286 #endif
288 Score::Score()
290 pscore_=0;
292 /****************************************************************/
294 Score_column::Score_column(Mtime w)
296 when = w;
297 pcol = new PCol(0);
298 musical = false;
301 bool
302 Score_column::used() {
303 return pcol->used;
306 void
307 Score_column::print() const
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