summaryrefslogtreecommitdiffabout
path: root/lib
Side-by-side diff
Diffstat (limited to 'lib') (more/less context) (show whitespace changes)
-rw-r--r--lib/SMF.cc1
-rw-r--r--lib/message.cc1
2 files changed, 2 insertions, 0 deletions
diff --git a/lib/SMF.cc b/lib/SMF.cc
index ba3179d..2c62b1f 100644
--- a/lib/SMF.cc
+++ b/lib/SMF.cc
@@ -1,62 +1,63 @@
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
+#include <cstring>
#include <midillo/SMF.h>
namespace midillo {
using std::ifstream;
using std::ofstream;
using std::cin;
using std::cout;
using std::copy;
using std::ostream_iterator;
using std::endl;
void SMF_t::load(const char *f,bool stdinable) {
if(stdinable && !strcmp(f,"-")) {
load(cin);
}else{
ifstream s(f,std::ios::in|std::ios::binary);
load(s);
}
}
void SMF_t::load(istream& s) {
mthd.load(s);
tracks.resize(mthd.ntracks);
tracks_t::iterator i = tracks.begin();
for(int t=0;t<mthd.ntracks;++t,++i) {
i->load(s);
}
}
void SMF_t::save(const char *f,bool stdoutable) const {
if(stdoutable && !strcmp(f,"-")) {
save(cout);
}else{
ofstream s(f,std::ios::out|std::ios::trunc|std::ios::binary);
save(s);
}
}
void SMF_t::save(ostream& s) const {
mthd.save(s);
for(tracks_t::const_iterator i=tracks.begin();i!=tracks.end();++i) {
i->save(s);
}
}
void SMF_t::dump(ostream& s) const {
std::ios::fmtflags ff = s.flags();
s.unsetf(std::ios::hex); s.setf(std::ios::dec);
s
<< "SMF with " << tracks.size() << " track(s)" << endl
<< mthd << endl;
copy(
tracks.begin(), tracks.end(),
ostream_iterator<MTrk_t>(s,"\n") );
s.flags(ff);
}
}
diff --git a/lib/message.cc b/lib/message.cc
index 8f9e68a..6a5cfd6 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -1,194 +1,195 @@
#include <algorithm>
#include <iterator>
+#include <cassert>
#include <midillo/message.h>
#include <midillo/util.h>
#include <midillo/exception.h>
namespace midillo {
using std::copy;
using std::ostream_iterator;
unsigned long message_t::calculate_save_size(int& rs) const {
unsigned long rv = 0;
if(status!=rs) {
++rv;
rs = status;
}else if((status&status_event_bits)==status_system) {
rs = -1;
++rv; // XXX: is it really needed?
}
switch(status&status_event_bits) {
case status_note_off:
case status_note_on:
case status_polyphonic_key_pressure: // aka status_aftertouch
case status_control_change:
case status_pitch_wheel_change:
rv += 2; break;
case status_program_change:
case status_channel_pressure:
++rv; break;
case status_system:
switch(status&status_system_bits) {
case status_system_sysex:
case status_system_end_of_sysex:
rv += data.size()+1; break;
case status_system_MTC_quarter_frame:
case status_system_song_select:
++rv; break;
case status_system_song_position_pointer:
rv += 2; break;
case status_system_tune_request:
case status_system_timing_clock: // aka status_system_midi_clock
case status_system_midi_tick:
case status_system_start: // aka status_system_midi_start
case status_system_stop: // aka status_system_midi_stop
case status_system_continue: // aka status_system_midi_continue
case status_system_active_sense:
break; /* XXX: ensure there is no data? */
case status_system_meta: // also reset, but not for the purpose of midi file
++rv;
rv += calcVLsize(data.size());
rv += data.size();
break;
default:
throw exception(CODEPOINT,"Internal error");
break;
}
break;
default:
throw exception(CODEPOINT,"Internal error");
break;
}
return rv;
}
void message_t::save(int& rs,ostream& s) const {
if(status!=rs) {
s.put(status);
if(!s.good())
throw exception_output_error(CODEPOINT,"Error writing midi status byte");
rs = status;
}else if((status&status_event_bits)==status_system) {
rs = -1;
s.put(status); // XXX: is it really needed?
if(!s.good())
throw exception_output_error(CODEPOINT,"Error writing midi system status byte");
}
switch(status&status_event_bits) {
case status_note_off:
case status_note_on:
case status_polyphonic_key_pressure: // aka status_aftertouch
case status_control_change:
case status_pitch_wheel_change:
save_data(s,2); break;
case status_program_change:
case status_channel_pressure:
save_data(s,1); break;
case status_system:
switch(status&status_system_bits) {
case status_system_sysex:
case status_system_end_of_sysex:
save_sysex(s); break;
case status_system_MTC_quarter_frame:
case status_system_song_select:
save_data(s,1); break;
case status_system_song_position_pointer:
save_data(s,2); break;
case status_system_tune_request:
case status_system_timing_clock: // aka status_system_midi_clock
case status_system_midi_tick:
case status_system_start: // aka status_system_midi_start
case status_system_stop: // aka status_system_midi_stop
case status_system_continue: // aka status_system_midi_continue
case status_system_active_sense:
break; /* XXX: ensure there is no data? */
case status_system_meta: // also reset, but not for the purpose of midi file
s.put(meta_status&0xFF);
if(!s.good())
throw exception_output_error(CODEPOINT,"Error writing meta event");
writeVL(s,data.size());
save_data(s);
break;
default:
throw exception(CODEPOINT,"Internal error");
break;
}
break;
default:
throw exception(CODEPOINT,"Internal error");
break;
}
}
void message_t::load(int& rs,istream& s) {
data.clear();
status = s.get();
if(!s.good())
throw exception_input_error(CODEPOINT,"Error reading MIDI event status byte");
if(status&status_bit) {
if((status&status_event_bits)!=status_system)
rs = status;
}else{
if(rs<0)
throw exception_invalid_input(CODEPOINT,"Attempt to rely on the absent running status");
data.push_back(status);
status = rs;
}
switch(status&status_event_bits) {
case status_note_off:
case status_note_on:
case status_polyphonic_key_pressure: // a.k.a. status_aftertouch
case status_control_change:
case status_pitch_wheel_change:
load_data(s,2); break;
case status_program_change:
case status_channel_pressure:
load_data(s,1); break;
case status_system:
switch(status&status_system_bits) {
case status_system_sysex:
case status_system_end_of_sysex:
load_sysex(s); break;
case status_system_MTC_quarter_frame:
case status_system_song_select:
load_data(s,1); break;
case status_system_song_position_pointer:
load_data(s,2); break;
case status_system_tune_request:
case status_system_timing_clock: // a.k.a. status_system_midi_clock
case status_system_midi_tick:
case status_system_start: // a.k.a. status_system_midi_start
case status_system_stop: // a.k.a. status_system_midi_stop
case status_system_continue: // a.k.a. status_system_midi_continue
case status_system_active_sense:
break;
case status_system_meta: // also, reset, but not in midi files
{
meta_status = s.get();
if(!s.good())
throw exception_input_error(CODEPOINT,"Error reading meta event type");
int l = readVL(s);
load_data(s,l);
}
break;
default:
throw exception(CODEPOINT,"Internal error");
break;
}
break;
default:
throw exception(CODEPOINT,"Internal error");
break;
}
}
void message_t::save_data(ostream& s,int c) const {
if(c!=data.size())
throw exception(CODEPOINT,"Writing corrupt data");
save_data(s);
}
void message_t::save_data(ostream& s) const {
for(bytes_t::const_iterator i=data.begin();i!=data.end();++i)
s.put(*i);
if(!s.good())