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