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