Comment out excessive terminal output.
authorDavid Robillard <d@drobilla.net>
Sat, 3 May 2008 21:55:43 +0000 (21:55 +0000)
committerDavid Robillard <d@drobilla.net>
Sat, 3 May 2008 21:55:43 +0000 (21:55 +0000)
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

gtk2_ardour/automation_time_axis.cc
libs/ardour/ardour/midi_model.h
libs/ardour/ardour/smf_source.h
libs/ardour/ardour/sndfilesource.h
libs/ardour/audioengine.cc
libs/ardour/automation_event.cc
libs/ardour/midi_model.cc
libs/ardour/midi_region.cc
libs/ardour/parameter.cc
libs/ardour/smf_source.cc

index 518f4ed41fa83c9f29b3e79a1937fbdb3e2ae4c1..099a36c8224bb9f59e806ef914119899e4e27f0f 100644 (file)
@@ -623,7 +623,7 @@ AutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEvent
 bool
 AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
 {
-       return cut_copy_clear_one (*_line, selection, op);
+       return (_line ? cut_copy_clear_one (*_line, selection, op) : false);
 }
 
 bool
index ea915d0a45d5971174815d4283ca4125da3e6bfd..39987dfe7ac68f0982051b9474f69bf02408ad11 100644 (file)
@@ -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<const Note> a,
                                                 const boost::shared_ptr<const Note> b) { 
                return a->time() < b->time();
@@ -149,7 +148,8 @@ public:
        void set_edited(bool yn) { _edited = yn; }
        bool write_to(boost::shared_ptr<MidiSource> 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; }
 
index dd8fd6192660850ff31518e6f88cf88d313b4840..9e215bf5a2f28307b727db57ae5bc34db3ac4f38 100644 (file)
@@ -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();
 
index dc83fc6ec146d74e7143491b1c2e17c23265ad98..4ad967c132a2a4e8ce46ad7ccb9b416453be5b6e 100644 (file)
@@ -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 */
index 9f7d67fb6d1ce32f6abf4a01cb27b30e9121e865..8bbed4673346229158aaaf8d7fb98238e2fab53f 100644 (file)
@@ -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<Ports> writer (ports);
                boost::shared_ptr<Ports> 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;
        }
index e47de7510dfb83cbf86c73d0eb5fb7fa6c8deb75..af390953f424aa660b773efa64501a130e2f85f4 100644 (file)
@@ -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"));
index d599e7187c054bff7c879d8a18482e64118589f1..3e009bcb8f8671bfc4ddeda311e64fe496edb577 100644 (file)
@@ -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<AutomationControl> 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> 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<MidiSource> 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<const MIDI::Event*>,
-       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<const Note> 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;
 }
index c3ce6db327c97ad912fa267403b425ee8d03db5d..e29fb1e65979c77f6407f323fd857fb2c077ea1b 100644 (file)
@@ -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 {
index aa480e47a2c5fc371b4c4ed5949d1919931a62eb..528d7e114c6b38ffa37d47b5c296f86996b704a1 100644 (file)
@@ -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;
        }
index 371824b83388eef7999e1ae3a048180116a827ec..dadb919b1749b6f5a0c98738d31b4509b9ac9852 100644 (file)
@@ -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<MidiModel>(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());
 }