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