]> git.donarmstrong.com Git - lilypond.git/blob - src/score.cc
release: 0.0.31
[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 "paperdef.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 /**
43   Remove empty cols, preprocess other columns.
44   */
45 void
46 Score::clean_cols()
47 {
48     for (iter_top(staffs_,i); i.ok(); i++)
49         i->clean_cols();
50
51     for (iter_top(cols_,c); c.ok(); ) {
52         if (!c->pcol_l_->used()) {
53             delete c.get();
54         } else {
55             c->preprocess();
56             c++;
57         }
58     }
59 }
60
61 /**
62   this sux.  We should have Score_column create the appropriate PCol.
63   Unfortunately, PCols don't know about their position.    
64   */
65 PCursor<Score_column*>
66 Score::create_cols(Moment w)
67 {
68     Score_column* c1 = new Score_column(w);
69     Score_column* c2 = new Score_column(w);
70     
71     c1->musical_ = false;
72     c2->musical_ = true;
73     
74     iter_top(cols_,i);
75
76     for (; i.ok(); i++) {
77         assert(i->when() != w);
78         if (i->when() > w)
79             break;
80     }
81
82     if (!i.ok()) {
83         cols_.bottom().add(c1);
84         cols_.bottom().add(c2);
85         i = cols_.bottom();
86         i --;
87     } else {
88         i.insert(c1);
89         i.insert(c2);
90         i -= 2;
91     }
92     return i;
93 }
94
95 PCursor<Score_column*>
96 Score::find_col(Moment w, bool mus)
97 {   iter_top( cols_,i);
98         
99     
100     for (; i.ok(); i++) {
101         if (i->when() == w && i->musical_ == mus)
102             return i;
103         if (i->when() > w)
104             break;
105     }
106     i = create_cols(w);
107     if (mus)
108         i++;
109     return i;
110 }
111
112 void
113 Score::do_cols()
114 {
115     iter_top(cols_,i);
116     for (; i.ok(); i++) {
117         pscore_p_->add(i->pcol_l_);
118     }
119     clean_cols();    // can't move clean_cols() farther up.
120 }
121
122 Moment
123 Score::last() const
124 {    
125     Moment l = 0;
126     for (iter_top(staffs_,i); i.ok(); i++) {
127         l = l>? i->last();
128     }
129     return l;
130 }
131
132 void
133 Score::OK() const
134 {
135 #ifndef NDEBUG
136     for (iter_top(staffs_,i); i.ok(); i++) {
137         i->OK();
138         assert(i->score_l_ == this);
139     }
140     staffs_.OK();
141     cols_.OK();
142     for (iter_top(cols_,cc); cc.ok() && (cc+1).ok(); cc++) {
143         assert(cc->when() <= (cc+1)->when());
144     }
145 #endif    
146 }
147
148
149 void
150 Score::print() const
151 {
152 #ifndef NPRINT
153     mtor << "score {\n"; 
154     for (iter_top(staffs_,i); i.ok(); i++) {
155         i->print();
156     }
157     for (iter_top(cols_,i); i.ok(); i++) {
158         i->print();
159     }
160     if (pscore_p_)
161         pscore_p_->print();
162     
163     mtor << "}\n";
164 #endif
165 }
166
167 Score::Score(Paperdef*paper_p)
168 {
169     pscore_p_=0;
170     paper_p_ = paper_p;
171     errorlevel_i_ = 0;
172     defined_ch_c_l_ = 0;
173 }
174
175 Score::~Score()
176 {
177     delete pscore_p_;
178     delete paper_p_;
179 }
180
181 void
182 Score::output(String s)
183 {
184     OK();
185     if (paper_p_->outfile=="")
186         paper_p_->outfile = s;
187     
188     if ( errorlevel_i_ ) { 
189         *mlog << "lilypond: warning: no output to: " << paper_p_->outfile 
190         << " (errorlevel=" << errorlevel_i_ << ")" << endl;
191         return;
192     }
193
194     *mlog << "output to " << paper_p_->outfile << "...\n";
195     
196     Tex_stream the_output(paper_p_->outfile);
197     
198     the_output << "% outputting Score, defined at: " <<
199         source_global_l->
200         sourcefile_l (defined_ch_c_l_)->file_line_no_str(defined_ch_c_l_) << "\n";
201     pscore_p_->output(the_output);
202 }
203
204
205
206 void
207 Score::add(Staff*s)
208 {
209     s->score_l_ = this;
210     staffs_.bottom().add(s);
211 }
212
213 void
214 Score::add_marks(Array<String> s_arr, Array<Moment> m_arr)
215 {
216     for (int i=0; i < s_arr.size(); i++) {
217         String mark_str (s_arr[i]);
218         if (markers_assoc_.elt_query(mark_str) &&
219             m_arr[i] != markers_assoc_[mark_str])
220             
221             error("Conflicting marker: `" + s_arr[i]+ "\'");
222         else
223             markers_assoc_[s_arr[i]] = m_arr[i];
224     }
225 }