do not allow smf_source's reads to stomp on cached read_end position in parent class...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 16 Sep 2009 01:08:51 +0000 (01:08 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 16 Sep 2009 01:08:51 +0000 (01:08 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@5665 d708f5d6-7413-0410-9779-e7cbd77b26cf

12 files changed:
libs/ardour/ardour/midi_ring_buffer.h
libs/ardour/ardour/smf_source.h
libs/ardour/midi_buffer.cc
libs/ardour/midi_diskstream.cc
libs/ardour/midi_playlist.cc
libs/ardour/midi_region.cc
libs/ardour/midi_ring_buffer.cc
libs/ardour/midi_source.cc
libs/ardour/smf_source.cc
libs/evoral/evoral/Event.hpp
libs/evoral/src/SMF.cpp
libs/evoral/src/Sequence.cpp

index 228479067f4c7173467725e7dc73af653794e085..f879aa75341e668fa4c4cd335e2adbfd8a4ca27d 100644 (file)
@@ -51,6 +51,7 @@ public:
        inline bool read_contents(uint32_t size, uint8_t* buf);
 
        size_t read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset=0);
+       void dump(std::ostream& dst);
        
        /** Set the channel filtering mode.
         * @param mask If mode is FilterChannels, each bit represents a midi channel:
index 73bef5480adfe3b4a6ba47778b44a58e6d40ef8e..025f770fc3853c5b73e2b51dea619d29634a545f 100644 (file)
@@ -85,6 +85,7 @@ private:
 
        double    _last_ev_time_beats;
        sframes_t _last_ev_time_frames;
+       mutable sframes_t _smf_last_read_end;
 };
 
 }; /* namespace ARDOUR */
index 12b46e7f04ad70ad33da6c8158a388168742cd06..ae3071a53cd673fed85841a7530b9b8446840f50 100644 (file)
@@ -93,7 +93,6 @@ MidiBuffer::read_from (const Buffer& src, nframes_t nframes, nframes_t dst_offse
                const Evoral::MIDIEvent<TimeType> ev(*i, false);
                if (ev.time() >= src_offset && ev.time() < (nframes+src_offset)) {
                        push_back (ev);
-                       cerr << "got note " << ev << endl;
                }
        }
 
index 9c8c9e8620101683593ec0583b14fc899c7a46be..6e57714ae2e7713f2075eb160de58fbfa994050a 100644 (file)
@@ -858,8 +858,6 @@ MidiDiskstream::can_internal_playback_seek (nframes_t distance)
 int
 MidiDiskstream::internal_playback_seek (nframes_t distance)
 {
-       cerr << "MDS: internal_playback_seek " << distance << endl;
-
        first_recordable_frame += distance;
        playback_sample += distance;
 
@@ -929,8 +927,7 @@ MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed)
                                        _id, this_read, start) << endmsg;
                        return -1;
                }
-               
-               //cout << "MDS this read " << this_read << " start = " << start << endl;
+
                g_atomic_int_add(&_frames_written_to_ringbuffer, this_read);
 
                _read_data_count = _playlist->read_data_count();
@@ -1650,7 +1647,9 @@ MidiDiskstream::get_playback (MidiBuffer& dst, nframes_t start, nframes_t end)
 
        // Translates stamps to be relative to start
 
+
        _playback_buf->read(dst, start, end);
+
 #if 0
        const size_t events_read = _playback_buf->read(dst, start, end);
        cout << _name << ": MDS events read = " << events_read
index 8f8b882d1e99de56a4b964c47d9be3a8f898b008..82f8827f21497e843ca0632aac8ebfb5bed47dce 100644 (file)
@@ -91,7 +91,7 @@ MidiPlaylist::MidiPlaylist (boost::shared_ptr<const MidiPlaylist> other, string
                                        out_o++;
                                        out_n++;
                                }
-                               //                              cerr << "HUH!? second region in the crossfade not found!" << endl;
+                               // cerr << "HUH!? second region in the crossfade not found!" << endl;
                        }
                }
 
index 910789c7fbfa8c62d77f87a0d1306e55329d01ac..aca8d039ad218b01f3268e50a84cc5510439afb5 100644 (file)
@@ -147,7 +147,7 @@ MidiRegion::_read_at (const SourceList& /*srcs*/, MidiRingBuffer<nframes_t>& dst
        nframes_t internal_offset = 0;
        nframes_t src_offset      = 0;
        nframes_t to_read         = 0;
-       
+
        /* precondition: caller has verified that we cover the desired section */
 
        assert(chan_n == 0);
@@ -191,7 +191,16 @@ MidiRegion::_read_at (const SourceList& /*srcs*/, MidiRingBuffer<nframes_t>& dst
                // _start from the note times in the midi source
                negative_output_buffer_position = _start; 
        }
-       
+
+#if 0  
+       cerr << "\t\tsource read from " << _position << " - " << _start << " (" << _position - _start << ") "
+            << " start in source " << _start << " + " << internal_offset << " (" << _start + internal_offset << ") "
+            << " dur = " << to_read 
+            << " offset = " << output_buffer_position 
+            << " negoffset = " << negative_output_buffer_position 
+            << endl;
+#endif
+
        if (src->midi_read (
                        dst, // destination buffer
                        _position - _start, // start position of the source in this read context
index 88064c87986b990a3b468e519ee057009034d5c7..5fcd3e82984bdf4eeb624200647e66a53c009597 100644 (file)
@@ -43,17 +43,15 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
 
        size_t count = 0;
 
-       //cerr << "MRB read " << start << " .. " << end << " + " << offset << endl;
-
        while (this->read_space() >= sizeof(T) + sizeof(Evoral::EventType) + sizeof(uint32_t)) {
 
                this->full_peek(sizeof(T), (uint8_t*)&ev_time);
-
+               
                if (ev_time > end) {
-                       //cerr << "MRB event @ " << ev_time << " past end @ " << end << endl;
+                       // cerr << "MRB event @ " << ev_time << " past end @ " << end << endl;
                        break;
                } else if (ev_time < start) {
-                       //cerr << "MRB event @ " << ev_time << " before start @ " << start << endl;
+                       // cerr << "MRB event @ " << ev_time << " before start @ " << start << endl;
                        break;
                }
 
@@ -67,7 +65,7 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
                if (ev_type == LoopEventType) {
                        /*ev_time -= start;
                          ev_time += offset;*/
-                       cerr << "MRB loop boundary @ " << ev_time << endl;
+                       // cerr << "MRB loop boundary @ " << ev_time << endl;
 
                        // Return without reading data or writing to buffer (loop events have no data)
                        // FIXME: This is not correct, loses events after the loop this cycle
@@ -87,11 +85,7 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
                                continue;
                        }
                }
-
-               /*cerr << "MRB " << this << " - Reading event, time = "
-                       << ev_time << " - " << start << " => " << ev_time - start
-                       << ", size = " << ev_size << endl;*/
-
+               
                assert(ev_time >= start);
                ev_time -= start;
                ev_time += offset;
@@ -126,6 +120,84 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
        
        return count;
 }
+template<typename T>
+void
+MidiRingBuffer<T>::dump(ostream& str) 
+{
+       size_t rspace;
+
+       if ((rspace = this->read_space()) == 0) {
+               str << "MRB::dump: empty\n";
+               return;
+       }
+
+       T                 ev_time;
+       Evoral::EventType ev_type;
+       uint32_t          ev_size;
+       size_t read_ptr = g_atomic_int_get (&this->_read_ptr);
+
+       str << "Dump @ " << read_ptr << endl;
+       
+       while (1) {
+               uint8_t* wp;
+               uint8_t* data;
+               size_t write_ptr;
+
+#define space(r,w) ((w > r) ? (w - r) : ((w - r + this->_size) % this->_size))
+               
+               write_ptr  = g_atomic_int_get (&this->_write_ptr);
+               if (space (read_ptr, write_ptr) < sizeof (T)) {
+                       break;
+               }
+
+               wp = &this->_buf[read_ptr];
+               memcpy (&ev_time, wp, sizeof (T)); 
+               read_ptr = (read_ptr + sizeof (T)) % this->_size;
+               str << "time " << ev_time;
+
+               write_ptr  = g_atomic_int_get (&this->_write_ptr);
+               if (space (read_ptr, write_ptr) < sizeof (ev_type)) {
+                       break;
+               }
+
+               wp = &this->_buf[read_ptr];
+               memcpy (&ev_type, wp, sizeof (ev_type)); 
+               read_ptr = (read_ptr + sizeof (ev_type)) % this->_size;
+               str << " type " << ev_type;
+
+               write_ptr  = g_atomic_int_get (&this->_write_ptr);
+               if (space (read_ptr, write_ptr) < sizeof (ev_size)) {
+                       str << "!OUT!\n";
+                       break;
+               }
+
+               wp = &this->_buf[read_ptr];
+               memcpy (&ev_size, wp, sizeof (ev_size)); 
+               read_ptr = (read_ptr + sizeof (ev_size)) % this->_size;
+               str << " size " << ev_size;
+
+               write_ptr  = g_atomic_int_get (&this->_write_ptr);
+               if (space (read_ptr, write_ptr) < ev_size) {
+                       str << "!OUT!\n";
+                       break;
+               }
+               
+               data = new uint8_t[ev_size];
+               
+               wp = &this->_buf[read_ptr];
+               memcpy (data, wp, ev_size); 
+               read_ptr = (read_ptr + ev_size) % this->_size;
+
+               for (uint32_t i = 0; i != ev_size; ++i) {
+                       str << ' ' << hex << (int) data[i] << dec;
+               }
+
+               str << endl;
+
+               delete [] data;
+       }
+}
+
 
 template class MidiRingBuffer<nframes_t>;
 
index f16ebf186f27ee0cc7366326a15adad3d051f247..4da2dbb8455f4bf6ae932660a6d3e08a31c7ace4 100644 (file)
@@ -137,16 +137,15 @@ MidiSource::midi_read (MidiRingBuffer<nframes_t>& dst, sframes_t source_start,
 #define BEATS_TO_FRAMES(t) (converter.to(t) + stamp_offset - negative_stamp_offset)
 
                Evoral::Sequence<double>::const_iterator& i = _model_iter;
-               
-               if (_last_read_end == 0 || start != _last_read_end) { // || !i.valid()) {
-                       //cerr << "MidiSource seeking to " << start << " from " << _last_read_end << endl;
+
+               if (_last_read_end == 0 || start != _last_read_end || !i.valid()) {
                        for (i = _model->begin(); i != _model->end(); ++i) {
                                if (BEATS_TO_FRAMES(i->time()) >= start) {
                                        break;
                                }
                        }
                }
-               
+
                _last_read_end = start + cnt;
 
                for (; i != _model->end(); ++i) {
@@ -234,7 +233,7 @@ MidiSource::session_saved()
                        stringstream ss(basename.substr(last_dash+1));
                        unsigned write_count = 0;
                        ss >> write_count;
-                       cerr << "WRITE COUNT: " << write_count << endl;
+                       // cerr << "WRITE COUNT: " << write_count << endl;
                        ++write_count; // start at 1
                        ss.clear();
                        ss << basename.substr(0, last_dash) << "-" << write_count;
index 7db027124b8c09c9b15ff368960cf4cdee1ed62a..7fbc8b0287d29296fc5106c292dc8dc03c92e567 100644 (file)
@@ -55,6 +55,7 @@ SMFSource::SMFSource (Session& s, const ustring& path, bool embedded, Source::Fl
        , Evoral::SMF()
        , _last_ev_time_beats(0.0)
        , _last_ev_time_frames(0)
+       , _smf_last_read_end (0)
 {
        if (init(_name, false)) {
                throw failed_constructor ();
@@ -72,6 +73,7 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
        , FileSource(s, node, must_exist)
        , _last_ev_time_beats(0.0)
        , _last_ev_time_frames(0)
+       , _smf_last_read_end (0)
 {
        if (set_state(node)) {
                throw failed_constructor ();
@@ -116,20 +118,20 @@ SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& destination, sframes_t sour
 
        const uint64_t start_ticks = (uint64_t)(converter.from(start) * ppqn());
 
-       if (_last_read_end == 0 || start != _last_read_end) {
+       if (_smf_last_read_end == 0 || start != _smf_last_read_end) {
                //cerr << "SMFSource::read_unlocked seeking to " << start << endl;
                Evoral::SMF::seek_to_start();
                while (time < start_ticks) {
                        ret = read_event(&ev_delta_t, &ev_size, &ev_buffer);
                        if (ret == -1) { // EOF
-                               _last_read_end = start + duration;
+                               _smf_last_read_end = start + duration;
                                return duration;
                        }
                        time += ev_delta_t; // accumulate delta time
                }
        }
        
-       _last_read_end = start + duration;
+       _smf_last_read_end = start + duration;
 
        while (true) {
                ret = read_event(&ev_delta_t, &ev_size, &ev_buffer);
index 3e8e05fa3bf793cc94bc2645db5d566047348590..cc24ac87f70250a80f2d55ce9755ccb39794b7ca 100644 (file)
@@ -199,12 +199,12 @@ protected:
 
 template<typename Time>
 std::ostream& operator<<(std::ostream& o, const Evoral::Event<Time>& ev) {
-       o << "Event type = " << ev.event_type() << " @ " << " @ " << ev.time() << "\n\t";
+       o << "Event type = " << ev.event_type() << " @ " << ev.time();
        o << std::hex;
        for (uint32_t n = 0; n < ev.size(); ++n) {
-               o << (int) ev.buffer()[n] << ' ';
+               o << ' ' << (int) ev.buffer()[n];
        }
-       o << std::dec << std::endl;
+       o << std::dec;
        return o;
 }
 
index 2103ad8eae7afad837e68bd710874db886cea1fd..424b4d46f2c90a3e9106c08c5542d7b83f25bbf0 100644 (file)
@@ -205,10 +205,10 @@ SMF::read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const
        
                assert(midi_event_is_valid(*buf, *size));
 
-               /*printf("SMF::read_event:\n");
+               /* printf("SMF::read_event @ %u: ", *delta_t);
                for (size_t i = 0; i < *size; ++i) {
                        printf("%X ", (*buf)[i]);
-               } printf("\n");*/
+               } printf("\n") */
        
        return event_size;
     } else {
@@ -223,10 +223,10 @@ SMF::append_event_delta(uint32_t delta_t, uint32_t size, const uint8_t* buf)
                return;
        }
        
-       /*printf("SMF::append_event_delta:\n");
+       /* printf("SMF::append_event_delta @ %u:", delta_t);
        for (size_t i = 0; i < size; ++i) {
                printf("%X ", buf[i]);
-       } printf("\n");*/
+               } printf("\n"); */
 
        if (!midi_event_is_valid(buf, size)) {
                cerr << "WARNING: SMF ignoring illegal MIDI event" << endl;
index 3b1729cfe8a19e2b1fd909a4395c8a48d25f5b5d..91943c03a6422f60055f709261e58d0f60985a10 100644 (file)
@@ -33,7 +33,7 @@
 #include "evoral/TypeMap.hpp"
 #include "evoral/midi_util.h"
 
-//#define DEBUG_SEQUENCE 1
+// #define DEBUG_SEQUENCE 1
 #ifdef DEBUG_SEQUENCE
        #include <boost/format.hpp>
        using boost::format;
@@ -209,10 +209,10 @@ Sequence<Time>::const_iterator::const_iterator(const Sequence<Time>& seq, Time t
                _locked = false;
                _seq->read_unlock();
        } else {
-               DUMP(format("New iterator = %1% : %2% @ %3%\n")
-                               % (int)_event->event_type()
-                               % (int)((MIDIEvent<Time>*)_event.get())->type()
-                               % _event->time());
+               DUMP(printf("New iterator = 0x%x : 0x%x @ %f\n",
+                           (int)_event->event_type(),
+                           (int)((MIDIEvent<Time>*)_event.get())->type(),
+                           _event->time()));
                assert(midi_event_is_valid(_event->buffer(), _event->size()));
        }
 }