--- /dev/null
+//
+// midiitem.cc
+//
+// source file of the LilyPond music typesetter
+//
+// (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#include <limits.h>
+#include "proto.hh"
+#include "plist.hh"
+#include "pcol.hh"
+#include "debug.hh"
+#include "misc.hh"
+#include "string.hh"
+#include "string-convert.hh"
+#include "request.hh"
+#include "musicalrequest.hh"
+#include "voice.hh"
+#include "midi-item.hh"
+#include "midi-stream.hh"
+
+Midi_chunk::Midi_chunk()
+{
+}
+
+void
+Midi_chunk::add( String str )
+{
+ data_str_ += str;
+}
+
+void
+Midi_chunk::set( String header_str, String data_str, String footer_str )
+{
+ data_str_ = data_str;
+ footer_str_ = footer_str;
+ header_str_ = header_str;
+}
+
+String
+Midi_chunk::str() const
+{
+ String str = header_str_;
+ String length_str = String_convert::i2hex_str( data_str_.length_i() + footer_str_.length_i(), 8, '0' );
+ length_str = String_convert::hex2bin_str( length_str );
+ str += length_str;
+ str += data_str_;
+ str += footer_str_;
+ return str;
+}
+
+Midi_duration::Midi_duration( Real seconds_f )
+{
+ seconds_f_ = seconds_f;
+}
+
+String
+Midi_duration::str() const
+{
+ return String( "<duration: " ) + String( seconds_f_ ) + ">";
+}
+
+Midi_header::Midi_header( int format_i, int tracks_i, int clocks_per_4_i )
+{
+ String str;
+
+ String format_str = String_convert::i2hex_str( format_i, 4, '0' );
+ str += String_convert::hex2bin_str( format_str );
+
+ String tracks_str = String_convert::i2hex_str( tracks_i, 4, '0' );
+ str += String_convert::hex2bin_str( tracks_str );
+
+ String tempo_str = String_convert::i2hex_str( clocks_per_4_i, 4, '0' );
+ str += String_convert::hex2bin_str( tempo_str );
+
+ set( "MThd", str, "" );
+}
+
+String
+Midi_item::i2varint_str( int i )
+{
+ int buffer_i = i & 0x7f;
+ while ( (i >>= 7) > 0 ) {
+ buffer_i <<= 8;
+ buffer_i |= 0x80;
+ buffer_i += (i & 0x7f);
+ }
+
+ String str;
+ while ( 1 ) {
+ str += (char)buffer_i;
+ if ( buffer_i & 0x80 )
+ buffer_i >>= 8;
+ else
+ break;
+ }
+ return str;
+}
+
+void
+Midi_item::output_midi( Midi_stream& midi_stream_r ) const
+{
+ midi_stream_r << str();
+}
+
+Midi_key::Midi_key( int accidentals_i, int minor_i )
+{
+ accidentals_i_ = accidentals_i;
+ minor_i_ = minor_i;
+}
+
+String
+Midi_key::str() const
+{
+ String str = "ff5902";
+ str += String_convert::i2hex_str( accidentals_i_, 2, '0' );
+ str += String_convert::i2hex_str( minor_i_, 2, '0' );
+ return String_convert::hex2bin_str( str );
+}
+
+Midi_note::Midi_note( Melodic_req* melreq_l, int channel_i, bool on_bo )
+{
+ assert(melreq_l);
+ pitch_i_ = melreq_l->pitch() + c0_pitch_i_c_;
+ channel_i_ = channel_i;
+
+ // poor man-s staff dynamics:
+ dynamic_byte_ = (melreq_l)? 0x64 - 0x10 * channel_i_:0;
+ on_b_ = on_bo;
+}
+
+String
+Midi_note::str() const
+{
+ if ( pitch_i_ != INT_MAX ) {
+ Byte status_byte = ( on_b_ ? 0x90 : 0x80 ) + channel_i_;
+ String str = String( (char)status_byte );
+ str += (char)pitch_i_;
+ // poor man-s staff dynamics:
+ str += (char)dynamic_byte_;
+ return str;
+ }
+ return String( "" );
+}
+
+Midi_tempo::Midi_tempo( int per_minute_4_i )
+{
+ per_minute_4_i_ = per_minute_4_i;
+}
+
+String
+Midi_tempo::str() const
+{
+ int useconds_per_4_i = 60 * (int)1e6 / per_minute_4_i_;
+ String str = "ff5103";
+ str += String_convert::i2hex_str( useconds_per_4_i, 6, '0' );
+ return String_convert::hex2bin_str( str );
+}
+
+Midi_text::Midi_text( Midi_text::Type type, String text_str )
+{
+ type_ = type;
+ text_str_ = text_str;
+}
+
+String
+Midi_text::str() const
+{
+ String str = "ff" + String_convert::i2hex_str( type_, 2, '0' );
+ str = String_convert::hex2bin_str( str );
+ str += i2varint_str( text_str_.length_i() );
+ str += text_str_;
+ return str;
+}
+
+Midi_track::Midi_track( int number_i )
+{
+// 4D 54 72 6B MTrk
+// 00 00 00 3B chunk length (59)
+// 00 FF 58 04 04 02 18 08 time signature
+// 00 FF 51 03 07 A1 20 tempo
+
+// FF 59 02 sf mi Key Signature
+// sf = -7: 7 flats
+// sf = -1: 1 flat
+// sf = 0: key of C
+// sf = 1: 1 sharp
+// sf = 7: 7 sharps
+// mi = 0: major key
+// mi = 1: minor key
+
+ number_i_ = number_i;
+
+ char const* data_ch_c_l = "00" "ff58" "0404" "0218" "08"
+// "00" "ff51" "0307" "a120"
+// why a key at all, in midi?
+// key: C
+// "00" "ff59" "02" "00" "00"
+// key: F (scsii-menuetto)
+// "00" "ff59" "02" "ff" "00"
+ ;
+
+ String data_str;
+ // only for format 0 (currently using format 1)?
+ data_str += String_convert::hex2bin_str( data_ch_c_l );
+
+ char const* footer_ch_c_l = "00" "ff2f" "00";
+ String footer_str = String_convert::hex2bin_str( footer_ch_c_l );
+
+ set( "MTrk", data_str, footer_str );
+}
+
+void
+Midi_track::add( int delta_time_i, String event_str )
+{
+ assert(delta_time_i >= 0);
+ Midi_chunk::add( i2varint_str( delta_time_i ) + event_str );
+}
+
+void
+Midi_track::add( Moment delta_time_moment, Midi_item* mitem_l )
+{
+ // use convention of 384 clocks per 4
+ // use Duration_convert
+ int delta_time_i = delta_time_moment * Moment( 384 ) / Moment( 1, 4 );
+ add( delta_time_i, mitem_l->str() );
+}
+
--- /dev/null
+/*
+ score-walker.cc -- implement Score_walker
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+#include "proto.hh"
+#include "plist.hh"
+#include "debug.hh"
+#include "score-walker.hh"
+#include "score.hh"
+#include "staff-walker.hh"
+#include "staff.hh"
+#include "score-column.hh"
+
+Score_walker::Score_walker(Score *s)
+ :PCursor<Score_column *> (s->cols_)
+{
+ score_l_ = s;
+ for (iter_top(s->staffs_,i); i.ok(); i++) {
+ Staff_walker* w_p=i->get_walker_p();
+ w_p->score_walk_l_ =this;
+ walker_p_arr_.push(w_p);
+ }
+
+ if(ok()) {
+ s->find_col(0, false)->set_breakable();
+ s->find_col(s->last(), false)->set_breakable();
+ }
+ reinit();
+}
+
+
+void
+Score_walker::reinit()
+{
+ disallow_break_walk_l_arr = walker_p_arr_;
+ disallow_break_count_ = disallow_break_walk_l_arr.size();
+}
+
+
+/** Advance the cursor, and all Staff_walkers contained in this. Reset
+ runtime fields */
+void
+Score_walker::operator ++(int )
+{
+ Moment last = ptr()->when();
+
+ PCursor<Score_column *>::operator++(0);
+ if (ok() && ptr()->when() == last)
+ PCursor<Score_column *>::operator++(0);
+ reinit();
+ if (!ok())
+ return;
+ for (int i=0; i< walker_p_arr_.size(); i++) {
+ if (walker_p_arr_[i]->ok() &&
+ walker_p_arr_[i]->when() < when()) {
+
+ walker_p_arr_[i]->operator++(0);
+ }
+ }
+}
+
+/** Allow the command_column to be breakable for one staff. If all
+ staffs allow, then allow a break here. */
+void
+Score_walker::allow_break(Staff_walker*w)
+{
+ for (int i=0; i < disallow_break_walk_l_arr.size(); i++) {
+ if (w == disallow_break_walk_l_arr[i]) {
+ disallow_break_count_ --;
+ disallow_break_walk_l_arr[i] =0;
+
+ if (!disallow_break_count_) {
+ PCursor<Score_column*> col_cursor = *this;
+ if (ptr()->musical_b())
+ col_cursor --;
+ col_cursor->set_breakable();
+ }
+ }
+ }
+}
+
+Moment
+Score_walker::when()
+{
+ return ptr()->when();
+}
+
+void
+Score_walker::process()
+{
+ for (int i=0; i < walker_p_arr_.size(); i++) {
+ Staff_walker *w = walker_p_arr_[i];
+ if ( w->ok() && w->when() == when() ) {
+ walker_p_arr_[i]->process();
+ }
+ }
+ if (when().denominator() == 1) {
+ *mlog << "." <<flush;
+ }
+}
+
+Score_walker::~Score_walker()
+{
+ for (int i=0; i < walker_p_arr_.size(); i++)
+ delete walker_p_arr_[i];
+ assert( !score_l_->find_col(score_l_->last(), true)->used_b());
+}
+
+
--- /dev/null
+/*
+ slur-reg.cc -- implement Slur_register
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "proto.hh"
+#include "plist.hh"
+#include "musicalrequest.hh"
+#include "complex-walker.hh"
+#include "slur-reg.hh"
+#include "slur.hh"
+#include "debug.hh"
+#include "notehead.hh"
+
+void
+Slur_register::set_feature(Features i)
+{
+ dir_i_ = i.direction_i_;
+}
+
+Slur_register::Slur_register()
+{
+ set_feature(Features::dir(0));
+}
+
+bool
+Slur_register::try_request(Request *req_l)
+{
+ if(!req_l->slur())
+ return false;
+
+ new_slur_req_l_arr_.push(req_l->slur());
+ return true;
+}
+
+void
+Slur_register::acknowledge_element(Staff_elem_info info)
+{
+ if (info.elem_p_->name() == Notehead::static_name()) {
+ Notehead *head_p =(Notehead*) info.elem_p_ ;// ugh
+ for (int i = 0; i < slur_l_stack_.size(); i++)
+ slur_l_stack_[i]->add(head_p );
+ for (int i = 0; i < end_slur_l_arr_.size(); i++)
+ end_slur_l_arr_[i]->add(head_p);
+ }
+}
+/*
+ abracadabra
+ */
+void
+Slur_register::process_requests()
+{
+ Array<Slur*> start_slur_l_arr_;
+ for (int i=0; i< new_slur_req_l_arr_.size(); i++) {
+ Slur_req* slur_req_l = new_slur_req_l_arr_[i];
+ // end slur: move the slur to other array
+ if (slur_req_l->spantype == Span_req::STOP) {
+ if (slur_l_stack_.empty())
+ warning("can't find slur to end",
+ slur_req_l->defined_ch_c_l_);
+ else {
+ end_slur_l_arr_.push(slur_l_stack_.pop());
+ requests_arr_.pop();
+ }
+ } else if (slur_req_l->spantype == Span_req::START) {
+ // push a new slur onto stack.
+ //(use temp. array to wait for all slur STOPs)
+ Slur * s_p =new Slur;
+ requests_arr_.push(slur_req_l);
+ start_slur_l_arr_.push(s_p);
+ announce_element(Staff_elem_info(s_p, slur_req_l));
+ }
+ }
+ for (int i=0; i < start_slur_l_arr_.size(); i++)
+ slur_l_stack_.push(start_slur_l_arr_[i]);
+}
+
+void
+Slur_register::pre_move_processing()
+{
+ for (int i = 0; i < end_slur_l_arr_.size(); i++) {
+ if (dir_i_)
+ end_slur_l_arr_[i]->dir_i_ = dir_i_;
+ typeset_element(end_slur_l_arr_[i]);
+ }
+ end_slur_l_arr_.set_size(0);
+}
+
+void
+Slur_register::post_move_processing()
+{
+ new_slur_req_l_arr_.set_size(0);
+}
+Slur_register::~Slur_register()
+{
+ for (int i=0; i < requests_arr_.size(); i++) {
+ warning("unterminated slur", requests_arr_[i]->defined_ch_c_l_);
+ }
+}
--- /dev/null
+#include "proto.hh"
+#include "idealspacing.hh"
+#include "plist.hh"
+#include "pcol.hh"
+#include "item.hh"
+#include "musicalrequest.hh"
+#include "spanner.hh"
+#include "scoreline.hh"
+#include "staffline.hh"
+
+#include "pcursor.tcc"
+#include "plist.tcc"
+
+
+#define IPLC_instantiate(a) IPL_instantiate(a); PL_instantiate(const a)
+
+
+IPLC_instantiate(Line_of_score);
+IPLC_instantiate(Line_of_staff);
+IPLC_instantiate(Item);
+IPLC_instantiate(Spanner);
+IPLC_instantiate(PStaff);
+IPLC_instantiate(Idealspacing);
+IPLC_instantiate(PCol);
+
--- /dev/null
+#include "proto.hh"
+#include "plist.hh"
+#include "debug.hh"
+#include "lexer.hh"
+#include "moment.hh"
+#include "time-description.hh"
+#include "source-file.hh"
+#include "source.hh"
+#include "main.hh"
+
+ostream &warnout (cerr);
+ostream *mlog(&cerr);
+/*
+void
+warning(String s)
+{
+ WARN << s;
+}
+*/
+
+void
+error(String s)
+{
+ if (busy_parsing())
+ yyerror(s);
+ else
+ cerr << "error: " << s << "\n";
+
+ exit(1);
+}
+
+void
+error_t(const String& s, const Moment& r)
+{
+ String t_mom = String(trunc(r)) + String(r - Moment(trunc(r)));
+ String e=s+ " (t = " + t_mom + ")";
+ error(e);
+}
+
+void
+error_t(const String& s, Time_description const &t_tdes)
+{
+ String e=s+ " (at t=" + String(t_tdes.bars_i_) + ": " + String(t_tdes.whole_in_measure_) + ")\n";
+ error(e);
+}
+
+void
+message( String message_str, char const* context_ch_c_l )
+{
+ String str = "lilypond: ";
+ Source_file* sourcefile_l = source_l_g->sourcefile_l( context_ch_c_l );
+ if ( sourcefile_l ) {
+ str += sourcefile_l->file_line_no_str(context_ch_c_l) + String(": ");
+ }
+ str += message_str;
+ if ( sourcefile_l ) {
+ str += ":\n";
+ str += sourcefile_l->error_str( context_ch_c_l );
+ }
+ if ( busy_parsing() )
+ cerr << endl;
+ cerr << str << endl;
+}
+
+void
+warning( String message_str, char const* context_ch_c_l )
+{
+ message( "warning: " + message_str, context_ch_c_l );
+}
+
+void
+error( String message_str, char const* context_ch_c_l )
+{
+ message( message_str, context_ch_c_l );
+ // since when exits error again?
+ // i-d say: error: errorlevel |= 1; -> no output upon error
+ // warning: recovery -> output (possibly wrong)
+ if ( lexer )
+ lexer->errorlevel_i_ |= 1;
+// exit( 1 );
+}