]> git.donarmstrong.com Git - lilypond.git/blob - src/score.cc
release: 0.0.32
[lilypond.git] / src / score.cc
1 /*
2   score.cc -- implement Score
3
4   source file of the LilyPond music typesetter
5
6   (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8
9 #include "tstream.hh"
10 #include "score.hh"
11 #include "sccol.hh"
12 #include "pscore.hh"
13 #include "staff.hh"
14 #include "debug.hh"
15 #include "paperdef.hh"
16 #include "main.hh"
17 #include "source.hh"
18 #include "sourcefile.hh"
19 #include "scorewalker.hh"
20
21 void
22 Score::setup_music()
23 {
24     *mlog << "\nSetting up music ..." << flush;
25     if (last() == Moment(0)) {
26         warning("Need to have music in a score.", defined_ch_c_l_);
27     }
28
29     pscore_p_ = new PScore(paper_p_);
30     find_col(0, false)->set_breakable(); // ugh
31     find_col(last(), false)->set_breakable();
32     
33         
34
35     for (iter_top(staffs_,i); i.ok(); i++) {
36         i->set_output(pscore_p_);
37         i->setup_staffcols();
38         i->OK();
39     }
40 }
41
42 void
43 Score::process_music()
44 {
45     *mlog << "Processing music ..." << flush;
46     for (Score_walker w(this); w.ok(); w++) {
47         w.process();
48     }
49 }
50
51 void
52 Score::process()
53 {
54     setup_music();
55     process_music();
56
57     // do this after processing, staffs first have to generate PCols.
58     do_cols();
59     print();
60     calc_idealspacing();
61
62     // debugging
63     OK();
64     *mlog << endl;
65     pscore_p_->process();
66 }
67
68 /**
69   Remove empty cols, preprocess other columns.
70   */
71 void
72 Score::clean_cols()
73 {
74     for (iter_top(staffs_,i); i.ok(); i++)
75         i->clean_cols();
76
77     for (iter_top(cols_,c); c.ok(); ) {
78         if (!c->pcol_l_->used()) {
79             delete c.get();
80         } else {
81             c->preprocess();
82             c++;
83         }
84     }
85 }
86
87 /**
88   Create columns at time #w#.
89   this sux.  We should have Score_column create the appropriate PCol.
90   Unfortunately, PCols don't know about their position.
91
92   @return cursor pointing to the nonmusical (first) column
93   */
94 PCursor<Score_column*>
95 Score::create_cols(Moment w)
96 {
97     Score_column* c1 = new Score_column(w);
98     Score_column* c2 = new Score_column(w);
99     
100     c1->musical_b_ = false;
101     c2->musical_b_ = true;
102     
103     iter_top(cols_,i);
104
105     for (; i.ok(); i++) {
106         assert(i->when() != w);
107         if (i->when() > w)
108             break;
109     }
110
111     if (!i.ok()) {
112         cols_.bottom().add(c1);
113         cols_.bottom().add(c2);
114         i = cols_.bottom();
115         i --;
116     } else {
117         i.insert(c1);
118         i.insert(c2);
119         i -= 2;
120     }
121     return i;
122 }
123
124 PCursor<Score_column*>
125 Score::find_col(Moment w, bool mus)
126 {
127     iter_top( cols_,i);
128     
129     for (; i.ok(); i++) {
130         if (i->when() == w && i->musical_b_ == mus)
131             return i;
132         if (i->when() > w)
133             break;
134     }
135     i = create_cols(w);
136     if (mus)
137         i++;
138     return i;
139 }
140
141 void
142 Score::do_cols()
143 {
144     iter_top(cols_,i);
145     for (; i.ok(); i++) {
146         pscore_p_->add(i->pcol_l_);
147     }
148     clean_cols();    // can't move clean_cols() farther up.
149 }
150
151 Moment
152 Score::last() const
153 {    
154     Moment l = 0;
155     for (iter_top(staffs_,i); i.ok(); i++) {
156         l = l>? i->last();
157     }
158     return l;
159 }
160
161 void
162 Score::OK() const
163 {
164 #ifndef NDEBUG
165     for (iter_top(staffs_,i); i.ok(); i++) {
166         i->OK();
167         assert(i->score_l_ == this);
168     }
169     staffs_.OK();
170     cols_.OK();
171     for (iter_top(cols_,cc); cc.ok() && (cc+1).ok(); cc++) {
172         assert(cc->when() <= (cc+1)->when());
173     }
174 #endif    
175 }
176
177
178 void
179 Score::print() const
180 {
181 #ifndef NPRINT
182     mtor << "score {\n"; 
183     for (iter_top(staffs_,i); i.ok(); i++) {
184         i->print();
185     }
186     for (iter_top(cols_,i); i.ok(); i++) {
187         i->print();
188     }
189     if (pscore_p_)
190         pscore_p_->print();
191     
192     mtor << "}\n";
193 #endif
194 }
195
196 Score::Score(Paperdef*paper_p)
197 {
198     pscore_p_=0;
199     paper_p_ = paper_p;
200     errorlevel_i_ = 0;
201     defined_ch_c_l_ = 0;
202 }
203
204 Score::~Score()
205 {
206     delete pscore_p_;
207     delete paper_p_;
208 }
209
210 void
211 Score::output(String s)
212 {
213     OK();
214     if (paper_p_->outfile=="")
215         paper_p_->outfile = s;
216     
217     if ( errorlevel_i_ ) { 
218         *mlog << "lilypond: warning: no output to: " << paper_p_->outfile 
219         << " (errorlevel=" << errorlevel_i_ << ")" << endl;
220         return;
221     }
222
223     *mlog << "output to " << paper_p_->outfile << "...\n";
224     
225     Tex_stream the_output(paper_p_->outfile);
226     
227     the_output << "% outputting Score, defined at: " <<
228         source_global_l->
229         sourcefile_l (defined_ch_c_l_)->file_line_no_str(defined_ch_c_l_) << "\n";
230     pscore_p_->output(the_output);
231 }
232
233
234
235 void
236 Score::add(Staff*s)
237 {
238     s->score_l_ = this;
239     staffs_.bottom().add(s);
240 }