]> git.donarmstrong.com Git - lilypond.git/blob - lily/score.cc
release: 0.0.65
[lilypond.git] / lily / score.cc
1 /*
2   score.cc -- implement Score
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8 #include "tex-stream.hh"
9 #include "score.hh"
10 #include "score-column.hh"
11 #include "p-score.hh"
12 #include "staff.hh"
13 #include "debug.hh"
14 #include "paper-def.hh"
15 #include "main.hh"
16 #include "source.hh"
17 #include "source-file.hh"
18 #include "score-walker.hh"
19 #include "midi-output.hh"
20 #include "midi-def.hh"
21 #include "pulk-voices.hh"
22 #include "request-column.hh"
23 #include "p-col.hh"
24
25 extern String default_out_fn;
26
27 void
28 Score::setup_music()
29 {
30     *mlog << "\nSetting up requests..." << flush;
31     
32     Pulk_voices pulk(staffs_); 
33
34     Moment l_mom = pulk.last_;
35     if (l_mom == Moment(0)) {
36         errorlevel_i_ |= 1;
37         input_.error("Need to have music in a score.");
38     }
39     
40     Moment previous_mom = -1;
41     while (pulk.ok()) {
42
43         Moment w= pulk.next_mom();
44         assert(w > previous_mom);
45         Request_column* rcol_p = new Request_column( staffs_ );
46
47         Score_column* c1 = new Score_column(w);
48         Score_column* c2 = new Score_column(w);
49         if (w == Moment(0) || w == l_mom) {
50             c1->set_breakable();
51         }
52                 
53         c1->musical_b_ = false;
54         c2->musical_b_ = true;
55         
56         cols_.bottom().add(c1);
57         cols_.bottom().add(c2);
58         rcol_p->set_score_cols(c1, c2);
59         rcols_.bottom().add(rcol_p);
60         pulk.get_aligned_request( rcol_p );
61         previous_mom =w;
62     }
63
64     errorlevel_i_ |= pulk.time_checks_failed_b(); 
65 }
66
67 void
68 Score::process_music()
69 {
70     *mlog << "Processing requests ..." << flush;
71     for (Score_walker w(this); w.ok(); w++) {
72         w.process();
73    }
74 }
75
76 void
77 Score::process()
78 {
79     setup_music();
80
81     paper();
82     midi();
83 }
84
85 void
86 Score::paper()
87 {
88     if (!paper_p_)
89         return;
90     if( errorlevel_i_){
91         // should we? hampers debugging. 
92         warning("Errors found, /*not processing score*/");
93 //      return;
94     }
95     pscore_p_ = new PScore(paper_p_);
96     do_cols();
97     
98     for (iter_top(staffs_,i); i.ok(); i++) 
99         i->set_output(pscore_p_);
100
101     
102     process_music();
103     clean_cols();    // can't move clean_cols() farther up.
104     print();
105     calc_idealspacing();
106
107     // debugging
108     OK();
109     *mlog << endl;
110     pscore_p_->process();
111
112     // output
113     paper_output();
114     
115 }
116
117 /**
118   Remove empty cols, preprocess other columns.
119   */
120 void
121 Score::clean_cols()
122 {
123 #if 1
124     for (iter_top(staffs_,i); i.ok(); i++)
125         i->clean_cols();
126
127     for (iter_top(rcols_,i); i.ok(); i++) {
128         i->when();              // update cache, ugh
129         if (!i->command_column_l_->used_b()) {
130             i->command_column_l_ = 0;
131         }
132         if (!i->musical_column_l_->used_b())
133             i->musical_column_l_ = 0;
134     }
135     
136     for (iter_top(cols_,c); c.ok(); ) {
137         if (!c->pcol_l_->used_b()) {
138             delete c.remove_p();
139         } else {
140             c->preprocess();
141             c++;
142         }
143     }
144 #endif
145 }
146
147 PCursor<Score_column*>
148 Score::find_col(Moment w, bool mus)
149 {
150     iter_top( cols_,i);
151     
152     for (; i.ok(); i++) {
153         if (i->when() == w && i->musical_b_ == mus)
154             return i;
155         if (i->when() > w)
156             break;
157     }
158     assert(false);
159     return i;
160 }
161
162 void
163 Score::do_cols()    
164 {
165     iter_top(cols_,i);
166     for (; i.ok(); i++) {
167         pscore_p_->add(i->pcol_l_);
168     }
169 }
170
171 Moment
172 Score::last() const
173 {    
174     Moment l = 0;
175     for (iter_top(staffs_,i); i.ok(); i++) {
176         l = l>? i->last();
177     }
178     return l;
179 }
180
181 void
182 Score::set(Paper_def *pap_p)
183 {
184     delete paper_p_;
185     paper_p_ = pap_p;
186 }
187
188 void
189 Score::set(Midi_def* midi_p)
190 {    
191     delete midi_p_;
192     midi_p_ = midi_p;
193 }
194
195 void
196 Score::OK() const
197 {
198 #ifndef NDEBUG
199     for (iter_top(staffs_,i); i.ok(); i++) {
200         i->OK();
201         assert(i->score_l_ == this);
202     }
203     staffs_.OK();
204     cols_.OK();
205     for (iter_top(cols_,cc); cc.ok() && (cc+1).ok(); cc++) {
206         assert(cc->when() <= (cc+1)->when());
207     }
208 #endif    
209 }
210
211
212 void
213 Score::print() const
214 {
215 #ifndef NPRINT
216     mtor << "score {\n"; 
217     for (iter_top(staffs_,i); i.ok(); i++) {
218         i->print();
219     }
220     for (iter_top(cols_,i); i.ok(); i++) {
221         i->print();
222     }
223     if (pscore_p_)
224         pscore_p_->print();
225     if (midi_p_)
226         midi_p_->print();
227     
228     mtor << "}\n";
229 #endif
230 }
231
232 Score::Score()
233 {
234     pscore_p_=0;
235     paper_p_ = 0;
236     midi_p_ = 0;
237     errorlevel_i_ = 0;
238 }
239
240 Score::~Score()
241 {
242     delete pscore_p_;
243     delete paper_p_;
244     delete midi_p_;
245 }
246
247 void
248 Score::paper_output()
249 {
250     if (paper_p_->outfile=="")
251         paper_p_->outfile = default_out_fn + ".out";
252
253     if ( errorlevel_i_ ) { 
254         *mlog << "lilypond: warning: no output to: " << paper_p_->outfile 
255         << " (errorlevel=" << errorlevel_i_ << ")" << endl;
256         return;
257     }
258
259     *mlog << "TeX output to " << paper_p_->outfile << " ...\n";
260     
261     Tex_stream the_output(paper_p_->outfile);
262     
263     the_output << "% outputting Score, defined at: " <<
264         input_.location_str() << "\n";
265     pscore_p_->output(the_output);
266     
267 }
268
269 void
270 Score::midi()
271 {
272     if (!midi_p_)
273         return;
274
275     if (midi_p_->outfile_str_ == "")
276         midi_p_->outfile_str_ = default_out_fn + ".midi";
277     
278     *mlog << "midi output to " << midi_p_->outfile_str_ << " ...\n";    
279     Midi_output(this, midi_p_);
280 }
281
282 void
283 Score::add(Staff*s)
284 {
285     s->score_l_ = this;
286     staffs_.bottom().add(s);
287 }