From e55e3fde7cec89c49e01046a2db276b2d8f30958 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 3 May 2008 21:55:43 +0000 Subject: Comment out excessive terminal output. Write all events (not just notes) to SMF file from MidiModel (just use iterator instead of hand-hacked MidiModel::write_to). Various MIDI bug fixes. git-svn-id: svn://localhost/ardour2/branches/3.0@3312 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/midi_model.h | 6 +-- libs/ardour/ardour/smf_source.h | 1 + libs/ardour/ardour/sndfilesource.h | 1 - libs/ardour/audioengine.cc | 12 ++--- libs/ardour/automation_event.cc | 4 -- libs/ardour/midi_model.cc | 100 ++++++++++--------------------------- libs/ardour/midi_region.cc | 6 +-- libs/ardour/parameter.cc | 2 - libs/ardour/smf_source.cc | 63 +++++++++++++---------- 9 files changed, 75 insertions(+), 120 deletions(-) (limited to 'libs') diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h index ea915d0a45..39987dfe7a 100644 --- a/libs/ardour/ardour/midi_model.h +++ b/libs/ardour/ardour/midi_model.h @@ -63,7 +63,7 @@ public: */ class MidiModel : public boost::noncopyable, public Automatable { public: - MidiModel(MidiSource *s, size_t size=0); + MidiModel(MidiSource* s, size_t size=0); void write_lock(); void write_unlock(); @@ -91,7 +91,6 @@ public: inline size_t n_notes() const { return _notes.size(); } inline bool empty() const { return _notes.size() == 0 && _controls.size() == 0; } - inline static bool note_time_comparator (const boost::shared_ptr a, const boost::shared_ptr b) { return a->time() < b->time(); @@ -149,7 +148,8 @@ public: void set_edited(bool yn) { _edited = yn; } bool write_to(boost::shared_ptr source); - // MidiModel doesn't use the normal AutomationList serialisation code, as CC data is in the .mid + // MidiModel doesn't use the normal AutomationList serialisation code + // since controller data is stored in the .mid XMLNode& get_state(); int set_state(const XMLNode&) { return 0; } diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h index dd8fd61926..9e215bf5a2 100644 --- a/libs/ardour/ardour/smf_source.h +++ b/libs/ardour/ardour/smf_source.h @@ -110,6 +110,7 @@ class SMFSource : public MidiSource { bool writable() const { return _flags & Writable; } int open(); + void close(); void seek_to_end(); void write_footer(); diff --git a/libs/ardour/ardour/sndfilesource.h b/libs/ardour/ardour/sndfilesource.h index dc83fc6ec1..4ad967c132 100644 --- a/libs/ardour/ardour/sndfilesource.h +++ b/libs/ardour/ardour/sndfilesource.h @@ -78,7 +78,6 @@ class SndFileSource : public AudioFileSource { void init (); int open(); - void close(); int setup_broadcast_info (nframes_t when, struct tm&, time_t); /* destructive */ diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 9f7d67fb6d..8bbed46733 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -556,7 +556,7 @@ AudioEngine::register_port (DataType dtype, const string& portname, bool input, { Port* newport = 0; - cerr << "trying to register port with name " << portname << endl; + /*cerr << "trying to register port with name " << portname << endl;*/ try { if (dtype == DataType::AUDIO) { newport = new AudioPort (portname, (input ? Port::IsInput : Port::IsOutput), publish, frames_per_cycle()); @@ -566,16 +566,16 @@ AudioEngine::register_port (DataType dtype, const string& portname, bool input, throw unknown_type(); } - cerr << "successfully got port " << portname << " with address " << newport << endl; + /*cerr << "successfully got port " << portname << " with address " << newport << endl;*/ RCUWriter writer (ports); boost::shared_ptr ps = writer.get_copy (); - cerr << "Address of ports list: " << ps << endl - << "Ports set size before insert: " << ps->size() << endl; + /*cerr << "Address of ports list: " << ps << endl + << "Ports set size before insert: " << ps->size() << endl;*/ ps->insert (ps->begin(), newport); - cerr << "Ports set size after insert: " << ps->size() << endl; - /* writer goes out of scope, forces update */ + /*cerr << "Ports set size after insert: " << ps->size() << endl;*/ + /* writer goes out of scope, forces update */ return newport; } diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc index e47de7510d..af390953f4 100644 --- a/libs/ardour/automation_event.cc +++ b/libs/ardour/automation_event.cc @@ -1436,10 +1436,6 @@ AutomationList::get_state () XMLNode& AutomationList::state (bool full) { - cerr << "getting "; - if(full) - cerr << "full "; - cerr << "state for AutomationList " << _parameter.to_string() << " list size: " << size() << endl; XMLNode* root = new XMLNode (X_("AutomationList")); char buf[64]; LocaleGuard lg (X_("POSIX")); diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index d599e7187c..3e009bcb8f 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -136,7 +136,7 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t) _locked = false; } } else { - printf("MIDI Iterator = %X @ %lf\n", _event.type(), _event.time()); + //printf("New MIDI Iterator = %X @ %lf\n", _event.type(), _event.time()); } } @@ -161,7 +161,7 @@ const MidiModel::const_iterator& MidiModel::const_iterator::operator++() assert((_event.is_note() || _event.is_cc() || _event.is_pgm_change() || _event.is_pitch_bender() || _event.is_channel_aftertouch())); // Increment past current control event - if (_control_iter != _control_iters.end() && _control_iter->automation_list && _event.is_cc()) { + if (!_event.is_note() && _control_iter != _control_iters.end() && _control_iter->automation_list) { double x, y; cerr << "control_iter x:" << _control_iter->x << " y:" << _control_iter->y << endl; const bool ret = _control_iter->automation_list->rt_safe_earliest_event_unlocked( @@ -212,24 +212,24 @@ const MidiModel::const_iterator& MidiModel::const_iterator::operator++() // Use the next earliest controller iff it's earlier than the note event if (_control_iter != _control_iters.end() && _control_iter->x != DBL_MAX - && _control_iter != old_control_iter) + )//&& _control_iter != old_control_iter) if (type == NIL || _control_iter->x < t) type = AUTOMATION; if (type == NOTE_ON) { - cerr << "********** MIDI Iterator = note on" << endl; + //cerr << "********** MIDI Iterator = note on" << endl; _event = MIDI::Event((*_note_iter)->on_event(), false); _active_notes.push(*_note_iter); ++_note_iter; } else if (type == NOTE_OFF) { - cerr << "********** MIDI Iterator = note off" << endl; + //cerr << "********** MIDI Iterator = note off" << endl; _event = MIDI::Event(_active_notes.top()->off_event(), false); _active_notes.pop(); } else if (type == AUTOMATION) { - cerr << "********** MIDI Iterator = AUTOMATION" << endl; + //cerr << "********** MIDI Iterator = Automation" << endl; _model->control_to_midi_event(_event, *_control_iter); } else { - cerr << "********** MIDI Iterator = END" << endl; + //cerr << "********** MIDI Iterator = End" << endl; _is_end = true; } @@ -483,7 +483,8 @@ void MidiModel::append(const MIDI::Event& ev) write_lock(); _edited = true; - cerr << "MidiModel::append event type: " << hex << "0x" << int(ev.type()) << endl; + /*cerr << "MidiModel append event type: " + << hex << "0x" << (int)ev.type() << endl;*/ assert(_notes.empty() || ev.time() >= _notes.back()->time()); assert(_writing); @@ -507,7 +508,7 @@ void MidiModel::append(const MIDI::Event& ev) append_automation_event_unlocked(MidiChannelAftertouchAutomation, ev.channel(), ev.time(), ev.channel_aftertouch(), 0); } else { - printf("MM Unknown event type %X\n", ev.type()); + printf("WARNING: MidiModel: Unknown event type %X\n", ev.type()); } write_unlock(); @@ -607,7 +608,7 @@ void MidiModel::append_automation_event_unlocked(AutomationType type, Parameter param(type, id, chan); boost::shared_ptr control = Automatable::control(param, true); control->list()->fast_simple_add(time, value); - cerr << "control list size after fast simple add: " << control->list()->size() << endl; + /*cerr << "control list size after fast simple add: " << control->list()->size() << endl;*/ } void MidiModel::add_note_unlocked(const boost::shared_ptr note) @@ -877,76 +878,27 @@ struct EventTimeComparator { } }; +/** Write the model to a MidiSource (i.e. save the model). + * This is different from manually using read to write to a source in that + * note off events are written regardless of the track mode. This is so the + * user can switch a recorded track (with note durations from some instrument) + * to percussive, save, reload, then switch it back to sustained without + * destroying the original note durations. + */ bool MidiModel::write_to(boost::shared_ptr source) { - cerr << "Writing model to " << source->name() << endl; - - /* This could be done using a temporary MidiRingBuffer and using - * MidiModel::read and MidiSource::write, but this is more efficient - * and doesn't require any buffer size assumptions (ie it's worth - * the code duplication). - * - * This is also different from read in that note off events are written - * regardless of the track mode. This is so the user can switch a - * recorded track (with note durations from some instrument) to percussive, - * save, reload, then switch it back to sustained preserving the original - * note durations. - */ - read_lock(); - LaterNoteEndComparator cmp; - ActiveNotes active_notes(cmp); - - EventTimeComparator comp; - typedef std::priority_queue< - const MIDI::Event*, - std::deque, - EventTimeComparator> MidiEvents; - - MidiEvents events(comp); - - /* Why sort manually, when a priority queue does the job for us, - * (I am probably wrong here, but I needed that to test program - * change code quickly) ??? - * */ - // Foreach note - for (Notes::const_iterator n = _notes.begin(); n != _notes.end(); ++n) { - - // Write any pending note offs earlier than this note on - while ( !active_notes.empty() ) { - const boost::shared_ptr earliest_off = - active_notes.top(); - const MIDI::Event& off_ev = earliest_off->off_event(); - if (off_ev.time() <= (*n)->time()) { - events.push(&off_ev); - active_notes.pop(); - } else { - break; - } - } - - // Write this note on - events.push(&(*n)->on_event()); - if ((*n)->duration() > 0) - active_notes.push(*n); - } - - // Write any trailing note offs - while ( !active_notes.empty() ) { - events.push(&active_notes.top()->off_event()); - active_notes.pop(); - } - - while (!events.empty()) { - source->append_event_unlocked(Frames, *events.top()); - //cerr << "MidiModel::write_to appending event with time:" << dec << int(events.top()->time()) << hex << " buffer: 0x" << int(events.top()->buffer()[0]) << " 0x" << int(events.top()->buffer()[1]) << " 0x" << int(events.top()->buffer()[2]) << endl; - events.pop(); - } - - _edited = false; + const NoteMode old_note_mode = _note_mode; + _note_mode = Sustained; + for (const_iterator i = begin(); i != end(); ++i) + source->append_event_unlocked(Frames, *i); + + _note_mode = old_note_mode; + read_unlock(); + _edited = false; return true; } diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index c3ce6db327..e29fb1e659 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -131,8 +131,8 @@ MidiRegion::master_read_at (MidiRingBuffer& out, nframes_t position, nframes_t d nframes_t MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const { - cerr << "reading from region " << _name << " position: " << _position << " start: " << _start << endl; - cerr << _name << "._read_at(" << position << ") - " << position << " duration: " << dur << endl; + /*cerr << "MidiRegion " << _name << "._read_at(" << position << ") - " + << position << " duration: " << dur << endl;*/ nframes_t internal_offset = 0; nframes_t src_offset = 0; @@ -174,7 +174,7 @@ MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst, nframes_t pos nframes_t output_buffer_position = 0; nframes_t negative_output_buffer_position = 0; - if(_position >= _start) { + if (_position >= _start) { // handle resizing of beginnings of regions correctly output_buffer_position = _position - _start; } else { diff --git a/libs/ardour/parameter.cc b/libs/ardour/parameter.cc index aa480e47a2..528d7e114c 100644 --- a/libs/ardour/parameter.cc +++ b/libs/ardour/parameter.cc @@ -56,8 +56,6 @@ Parameter::Parameter(const std::string& str) sscanf(str.c_str(), "midicc-%d-%d", &channel, &_id); assert(channel < 16); _channel = channel; - cout << "LOADED PARAMETER " << str << " chan " << _channel << " id " << _id << endl; - //_id = atoi(str.c_str()+7); } else { PBD::warning << "Unknown Parameter '" << str << "'" << endmsg; } diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index 371824b833..dadb919b17 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -133,6 +133,14 @@ SMFSource::init (string pathstr, bool must_exist) return 0; } +/** Attempt to open the SMF file for reading and writing. + * + * Currently SMFSource is always read/write. + * + * \return 0 on success + * -1 if the file can not be opened for reading, + * -2 if the file can not be opened for writing + */ int SMFSource::open() { @@ -153,6 +161,11 @@ SMFSource::open() // We're making a new file } else { _fd = fopen(path().c_str(), "w+"); + if (_fd == NULL) { + cerr << "ERROR: Can not open SMF file " << path() << " for writing: " << + strerror(errno) << endl; + return -2; + } _track_size = 4; // Write a tentative header just to pad things out so writing happens in the right spot @@ -160,10 +173,21 @@ SMFSource::open() write_footer(); seek_to_end(); } - + return (_fd == 0) ? -1 : 0; } +void +SMFSource::close() +{ + if (_fd) { + flush_header(); + flush_footer(); + fclose(_fd); + _fd = NULL; + } +} + void SMFSource::seek_to_end() { @@ -171,7 +195,7 @@ SMFSource::seek_to_end() } int -SMFSource::flush_header () +SMFSource::flush_header() { // FIXME: write timeline position somehow? @@ -211,8 +235,6 @@ SMFSource::flush_footer() void SMFSource::write_footer() { - //cerr << "SMF " << name() << " writing EOT at byte " << ftell(_fd) << endl; - write_var_len(0); char eot[3] = { 0xFF, 0x2F, 0x00 }; // end-of-track meta-event fwrite(eot, 1, 3, _fd); @@ -318,11 +340,11 @@ SMFSource::read_event(uint32_t* delta_t, uint32_t* size, Byte** buf) const if (event_size > 1) fread((*buf) + 1, 1, *size - 1, _fd); - printf("%s read event: delta = %u, size = %u, data = ", _name.c_str(), *delta_t, *size); + /*printf("%s read event: delta = %u, size = %u, data = ", _name.c_str(), *delta_t, *size); for (size_t i=0; i < *size; ++i) { printf("%X ", (*buf)[i]); } - printf("\n"); + printf("\n");*/ return (int)*size; } @@ -451,12 +473,13 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt) void SMFSource::append_event_unlocked(EventTimeUnit unit, const MIDI::Event& ev) { - //printf("%s - append chan = %u, time = %lf, size = %u, data = ", _path.c_str(), (unsigned)ev.channel(), ev.time(), ev.size()); + /*printf("%s - append chan = %u, time = %lf, size = %u, data = ", + name().c_str(), (unsigned)ev.channel(), ev.time(), ev.size()); for (size_t i=0; i < ev.size(); ++i) { printf("%X ", ev.buffer()[i]); } - printf("\n"); - + printf("\n");*/ + assert(ev.time() >= 0); assert(ev.time() >= _last_ev_time); @@ -535,6 +558,7 @@ SMFSource::mark_streaming_midi_write_started (NoteMode mode, nframes_t start_fra { MidiSource::mark_streaming_midi_write_started (mode, start_frame); _last_ev_time = 0; + fseek(_fd, _header_size, 0); } void @@ -546,20 +570,9 @@ SMFSource::mark_streaming_write_completed () return; } + _model->set_edited(false); flush_header(); flush_footer(); - -#if 0 - Glib::Mutex::Lock lm (_lock); - - - next_peak_clear_should_notify = true; - - if (_peaks_built || pending_peak_builds.empty()) { - _peaks_built = true; - PeaksReady (); /* EMIT SIGNAL */ - } -#endif } void @@ -861,13 +874,8 @@ SMFSource::load_model(bool lock, bool force_reload) if (lock) Glib::Mutex::Lock lm (_lock); - if (_model && !force_reload && !_model->empty()) { - //cerr << _name << " NOT reloading model " << _model.get() << " (" << _model->n_notes() - // << " notes)" << endl; + if (_model && !force_reload && !_model->empty()) return; - } else { - cerr << _name << " loading model" << endl; - } if (! _model) { _model = boost::shared_ptr(new MidiModel(this)); @@ -912,6 +920,7 @@ SMFSource::load_model(bool lock, bool force_reload) } _model->end_write(false); + _model->set_edited(false); free(ev.buffer()); } -- cgit v1.2.3