-#include "scommands.hh"
-#include "tstream.hh"
+/*
+ score.cc -- implement Score
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+#include "tex-stream.hh"
#include "score.hh"
-#include "sccol.hh"
+#include "score-column.hh"
#include "pscore.hh"
#include "staff.hh"
#include "debug.hh"
-#include "paper.hh"
+#include "paper-def.hh"
+#include "main.hh"
+#include "source.hh"
+#include "source-file.hh"
+#include "score-walker.hh"
+#include "midi-output.hh"
+#include "midi-def.hh"
+
+extern String default_out_fn;
void
-Score::set(Paperdef*p)
+Score::setup_music()
{
- delete paper_;
- paper_ = p;
+ *mlog << "\nSetting up music ..." << flush;
+ if (last() == Moment(0)) {
+ errorlevel_i_ |= 1;
+ error("Need to have music in a score.", defined_ch_c_l_);
+ }
+
+ for (iter_top(staffs_,i); i.ok(); i++) {
+ i->setup_staffcols();
+ i->OK();
+ }
}
void
-Score::output(String s)
+Score::process_music()
{
- OK();
- if (paper_->outfile=="")
- paper_->outfile = s;
-
- *mlog << "output to " << paper_->outfile << "...\n";
- Tex_stream the_output(paper_->outfile);
- pscore_->output(the_output);
+ *mlog << "Processing music ..." << flush;
+ for (Score_walker w(this); w.ok(); w++) {
+ w.process();
+ }
}
-
void
Score::process()
{
- *mlog << "Processing ... ";
- set(commands_->parse(last()));
- commands_->print();
-
- if (!paper_)
- paper_ = new Paperdef;
-
- commands_->clean(last());
+ setup_music();
+
+ paper();
+ midi();
+}
+
+void
+Score::paper()
+{
+ if (!paper_p_)
+ return;
- /// distribute commands to disciples
- distribute_commands();
+ pscore_p_ = new PScore(paper_p_);
+
+ find_col(0, false)->set_breakable(); // ugh
+ find_col(last(), false)->set_breakable();
+ do_cols();
- pscore_ = new PScore(paper_);
- for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
- sc->set_output(pscore_);
- sc->process();
- }
+ for (iter_top(staffs_,i); i.ok(); i++)
+ i->set_output(pscore_p_);
- // do this after processing, staffs first have to generate PCols.
- do_pcols();
+
+ process_music();
+ clean_cols(); // can't move clean_cols() farther up.
+ print();
calc_idealspacing();
- clean_cols();
- OK();
- // print();
- pscore_->preprocess();
- *mlog << "Calculating ... ";
- pscore_->calc_breaking();
- pscore_->postprocess();
+ // debugging
+ OK();
+ *mlog << endl;
+ pscore_p_->process();
- // TODO: calculate vertical structs
- // TODO: calculate mixed structs.
- *mlog << "\n";
+ // output
+ paper_output();
+
}
-// remove empty cols with no spacing attached.
-/* should rethink ownership of cols
- */
+/**
+ Remove empty cols, preprocess other columns.
+ */
void
Score::clean_cols()
-{
- for (PCursor<Staff * > sc(staffs_); sc.ok(); sc++)
- sc->clean_cols();
-
- for (PCursor<Score_column*> c(cols_); c.ok(); ) {
- if (!c->pcol_->used()) {
- mtor << "removing : ";
- c->print();
- c.del();
- } else
+{
+ for (iter_top(staffs_,i); i.ok(); i++)
+ i->clean_cols();
+
+ for (iter_top(cols_,c); c.ok(); ) {
+ if (!c->pcol_l_->used_b()) {
+ delete c.get_p();
+ } else {
+ c->preprocess();
c++;
+ }
}
-
- pscore_->clean_cols();
}
-/* this sux. We should have Score_column create the appropriate PCol.
- Unfortunately, PCols don't know about their position.
- */
-// todo
+
+/**
+ Create columns at time #w#.
+ this sux. We should have Score_column create the appropriate PCol.
+ Unfortunately, PCols don't know about their position.
+
+ @return cursor pointing to the nonmusical (first) column
+ */
PCursor<Score_column*>
-Score::create_cols(Real w)
+Score::create_cols(Moment w)
{
Score_column* c1 = new Score_column(w);
Score_column* c2 = new Score_column(w);
- c1->musical = false;
- c2->musical = true;
+ c1->musical_b_ = false;
+ c2->musical_b_ = true;
- PCursor<Score_column*> scc(cols_);
+ iter_top(cols_,i);
- for (; scc.ok(); scc++) {
- assert(scc->when != w);
- if (scc->when > w)
+ for (; i.ok(); i++) {
+ assert(i->when() != w);
+ if (i->when() > w)
break;
}
- if (!scc.ok()) {
+ if (!i.ok()) {
cols_.bottom().add(c1);
cols_.bottom().add(c2);
- scc = cols_.bottom();
- scc --;
+ i = cols_.bottom();
+ i --;
} else {
- scc.insert(c1);
- scc.insert(c2);
- scc -= 2;
+ i.insert(c1);
+ i.insert(c2);
+ i -= 2;
}
- return scc;
+ return i;
}
-Score_column*
-Score::find_col(Real w,bool mus)
+PCursor<Score_column*>
+Score::find_col(Moment w, bool mus)
{
- PCursor<Score_column*> scc(cols_);
- for (; scc.ok(); scc++) {
- if (scc->when == w && scc->musical == mus)
- return scc;
- if (scc->when > w)
+ iter_top( cols_,i);
+
+ for (; i.ok(); i++) {
+ if (i->when() == w && i->musical_b_ == mus)
+ return i;
+ if (i->when() > w)
break;
}
- scc = create_cols(w);
+ i = create_cols(w);
if (mus)
- scc++;
- return scc;
+ i++;
+ return i;
}
void
-Score::distribute_commands(void)
+Score::do_cols()
{
- for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
- sc->add_commands(*commands_);
+ iter_top(cols_,i);
+ for (; i.ok(); i++) {
+ pscore_p_->add(i->pcol_l_);
}
}
-void
-Score::add(Staff*s)
-{
- s->score_ = this;
- staffs_.bottom().add(s);
-}
+Moment
+Score::last() const
+{
+ Moment l = 0;
+ for (iter_top(staffs_,i); i.ok(); i++) {
+ l = l>? i->last();
+ }
+ return l;
+}
void
-Score::do_pcols()
+Score::set(Paper_def *pap_p)
{
- PCursor<Score_column*> sc(cols_);
- for (; sc.ok(); sc++) {
- pscore_->add(sc->pcol_);
- }
+ delete paper_p_;
+ paper_p_ = pap_p;
}
-Real
-Score::last() const
+
+void
+Score::set(Midi_def* midi_p)
{
- Real l = 0;
- for (PCursor<Staff*> stc(staffs_); stc.ok(); stc++) {
- l = MAX(l, stc->last());
- }
- return l;
+ delete midi_p_;
+ midi_p_ = midi_p;
}
void
Score::OK() const
{
#ifndef NDEBUG
- for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
- sc->OK();
- assert(sc->score_ == this);
+ for (iter_top(staffs_,i); i.ok(); i++) {
+ i->OK();
+ assert(i->score_l_ == this);
}
staffs_.OK();
cols_.OK();
- for (PCursor<Score_column*> cc(cols_); cc.ok() && (cc+1).ok(); cc++) {
- assert(cc->when <= (cc+1)->when);
+ for (iter_top(cols_,cc); cc.ok() && (cc+1).ok(); cc++) {
+ assert(cc->when() <= (cc+1)->when());
}
- commands_->OK();
#endif
}
{
#ifndef NPRINT
mtor << "score {\n";
- for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
- sc->print();
+ for (iter_top(staffs_,i); i.ok(); i++) {
+ i->print();
}
- for (PCursor<Score_column*> sc(cols_); sc.ok(); sc++) {
- sc->print();
+ for (iter_top(cols_,i); i.ok(); i++) {
+ i->print();
}
- commands_->print();
+ if (pscore_p_)
+ pscore_p_->print();
+ if (midi_p_)
+ midi_p_->print();
+
mtor << "}\n";
#endif
}
Score::Score()
{
- pscore_=0;
- paper_ = 0;
- commands_ = new Score_commands;
+ pscore_p_=0;
+ paper_p_ = 0;
+ midi_p_ = 0;
+ errorlevel_i_ = 0;
+ defined_ch_c_l_ = 0;
}
Score::~Score()
{
- delete pscore_;
- delete commands_;
- delete paper_;
+ delete pscore_p_;
+ delete paper_p_;
+ delete midi_p_;
+}
+
+void
+Score::paper_output()
+{
+ OK();
+ if (paper_p_->outfile=="")
+ paper_p_->outfile = default_out_fn + ".out";
+
+ if ( errorlevel_i_ ) {
+ *mlog << "lilypond: warning: no output to: " << paper_p_->outfile
+ << " (errorlevel=" << errorlevel_i_ << ")" << endl;
+ return;
+ }
+
+ *mlog << "TeX output to " << paper_p_->outfile << " ...\n";
+
+ Tex_stream the_output(paper_p_->outfile);
+
+ the_output << "% outputting Score, defined at: " <<
+ source_l_g->
+ sourcefile_l (defined_ch_c_l_)->file_line_no_str(defined_ch_c_l_) << "\n";
+ pscore_p_->output(the_output);
+}
+
+void
+Score::midi()
+{
+ if (!midi_p_)
+ return;
+
+ if (midi_p_->outfile_str_ == "")
+ midi_p_->outfile_str_ = default_out_fn + ".midi";
+
+ *mlog << "midi output to " << midi_p_->outfile_str_ << " ...\n";
+ Midi_output(this, midi_p_);
}
void
-Score::set(Score_commands*c)
+Score::add(Staff*s)
{
- delete commands_;
- commands_ = c;
+ s->score_l_ = this;
+ staffs_.bottom().add(s);
}