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