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