Little MidiEvent prettification additions, ifdef'd non-realtime aspects (for future...
authorDavid Robillard <d@drobilla.net>
Thu, 2 Aug 2007 21:08:18 +0000 (21:08 +0000)
committerDavid Robillard <d@drobilla.net>
Thu, 2 Aug 2007 21:08:18 +0000 (21:08 +0000)
Fix MIDI recording crash bug.

git-svn-id: svn://localhost/ardour2/trunk@2228 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/midi_streamview.cc
gtk2_ardour/midi_streamview.h
gtk2_ardour/streamview.cc
libs/ardour/ardour/midi_event.h
libs/ardour/meter.cc
libs/ardour/midi_model.cc
libs/ardour/midi_track.cc

index 30de0090fd30cefea44034b8129fdc5569d5bdc1..a9521a2dd966b98221210b91c895f41387a9c7fd 100644 (file)
@@ -66,8 +66,7 @@ MidiStreamView::MidiStreamView (MidiTimeAxisView& tv)
        canvas_rect->property_fill_color_rgba() = stream_base_color;
        canvas_rect->property_outline_color_rgba() = RGBA_BLACK;
 
-       //use_rec_regions = tv.editor.show_waveforms_recording ();
-       use_rec_regions = true;
+       use_rec_regions = tv.editor.show_waveforms_recording ();
 }
 
 MidiStreamView::~MidiStreamView ()
@@ -94,7 +93,7 @@ MidiStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wfd)
 
                        (*i)->set_valid (true);
                        (*i)->enable_display(wfd);
-                       display_region(dynamic_cast<MidiRegionView*>(*i));
+                       display_region(dynamic_cast<MidiRegionView*>(*i), wfd);
 
                        return NULL;
                }
@@ -114,7 +113,7 @@ MidiStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wfd)
        }
 
        /* display events and find note range */
-       display_region(region_view);
+       display_region(region_view, wfd);
 
        /* always display at least 1 octave range */
        _highest_note = max(_highest_note, static_cast<uint8_t>(_lowest_note + 11));
@@ -128,13 +127,15 @@ MidiStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wfd)
 }
 
 void
-MidiStreamView::display_region(MidiRegionView* region_view)
+MidiStreamView::display_region(MidiRegionView* region_view, bool load_model)
 {
        if ( ! region_view)
                return;
 
        boost::shared_ptr<MidiSource> source(region_view->midi_region()->midi_source(0));
-       source->load_model();
+
+       if (load_model)
+               source->load_model();
 
        if (source->model()) {
                // Find our note range
index baaf33d67ddcdb91855f205b8078b313c6336111..ceee4dc4440c8cbeb0846e3e0cf1b27163acb240 100644 (file)
@@ -79,7 +79,7 @@ class MidiStreamView : public StreamView
        void update_rec_regions (boost::shared_ptr<ARDOUR::MidiBuffer> data, jack_nframes_t start, jack_nframes_t dur);
        
        RegionView* add_region_view_internal (boost::shared_ptr<ARDOUR::Region>, bool wait_for_waves);
-       void        display_region(MidiRegionView* region_view);
+       void        display_region(MidiRegionView* region_view, bool load_model);
 
        void color_handler ();
 
index 34c1e4a1c959db18da484e4a312cb23411d71703..1b7e9028f2d63cb246de4aa44e75805fdb7943ed 100644 (file)
@@ -153,7 +153,7 @@ StreamView::set_samples_per_unit (gdouble spp)
 void
 StreamView::add_region_view (boost::shared_ptr<Region> r)
 {
-       add_region_view_internal (r, false);
+       add_region_view_internal (r, true);
 }
 
 void
index a0816d510539bd2a4438785fb0f795f476f87636..3a6b89f198a695581c2d102809b5e457514e6564 100644 (file)
 #ifndef __ardour_midi_event_h__
 #define __ardour_midi_event_h__
 
+#include <ardour/midi_events.h>
+
+/** If this is not defined, all methods of MidiEvent are RT safe
+ * but MidiEvent will never deep copy and (depending on the scenario)
+ * may not be usable in STL containers, signals, etc. */
+#define MIDI_EVENT_ALLOW_ALLOC 1
+
 namespace ARDOUR {
 
 
@@ -30,11 +37,12 @@ namespace ARDOUR {
  * tempo time, used in MidiModel) depending on context.
  */
 struct MidiEvent {
-       MidiEvent(bool owns_buffer=false, double t=0, size_t s=0, Byte* b=NULL)
-               : _owns_buffer(owns_buffer)
-               , _time(t)
+#ifdef MIDI_EVENT_ALLOW_ALLOC
+       MidiEvent(double t=0, size_t s=0, Byte* b=NULL, bool owns_buffer=false)
+               : _time(t)
                , _size(s)
                , _buffer(b)
+               , _owns_buffer(owns_buffer)
        {
                if (owns_buffer) {
                        _buffer = (Byte*)malloc(_size);
@@ -45,11 +53,17 @@ struct MidiEvent {
                }
        }
        
+       /** Copy \a copy.
+        * 
+        * If \a owns_buffer is true, the buffer will be copied and this method
+        * is NOT REALTIME SAFE.  Otherwise both events share a buffer and
+        * memory management semantics are the caller's problem.
+        */
        MidiEvent(const MidiEvent& copy, bool owns_buffer)
-               : _owns_buffer(owns_buffer)
-               , _time(copy._time)
+               : _time(copy._time)
                , _size(copy._size)
                , _buffer(copy._buffer)
+               , _owns_buffer(owns_buffer)
        {
                if (owns_buffer) {
                        _buffer = (Byte*)malloc(_size);
@@ -81,24 +95,37 @@ struct MidiEvent {
                return *this;
        }
 
-       inline bool        owns_buffer() const { return _owns_buffer; }
+       inline bool owns_buffer() const { return _owns_buffer; }
+       inline void set_buffer(Byte* buf) { assert(!_owns_buffer); _buffer = buf; }
+
+#else
+
+       inline void set_buffer(Byte* buf) { _buffer = buf; }
+
+#endif // MIDI_EVENT_ALLOW_ALLOC
+
        inline double      time()        const { return _time; }
        inline double&     time()              { return _time; }
-       inline size_t      size()        const { return _size; }
-       inline size_t&     size()              { return _size; }
+       inline uint32_t    size()        const { return _size; }
+       inline uint32_t&   size()              { return _size; }
        inline uint8_t     type()        const { return (_buffer[0] & 0xF0); }
+       inline uint8_t     channel()     const { return (_buffer[0] & 0x0F); }
+       inline bool        is_note_on()  const { return (type() == MIDI_CMD_NOTE_ON); }
+       inline bool        is_note_off() const { return (type() == MIDI_CMD_NOTE_OFF); }
+       inline bool        is_note()     const { return (is_note_on() || is_note_off()); }
        inline uint8_t     note()        const { return (_buffer[1]); }
        inline uint8_t     velocity()    const { return (_buffer[2]); }
        inline const Byte* buffer()      const { return _buffer; }
        inline Byte*       buffer()            { return _buffer; }
 
-       void set_buffer(Byte* buf) { assert(!_owns_buffer); _buffer = buf; }
-
 private:
-       bool   _owns_buffer; /**< Whether buffer is locally allocated */
-       double _time;         /**< Sample index (or beat time) at which event is valid */
-       size_t _size;         /**< Number of bytes of data in \a buffer */
-       Byte*  _buffer;       /**< Raw MIDI data */
+       double   _time;   /**< Sample index (or beat time) at which event is valid */
+       uint32_t _size;   /**< Number of bytes of data in \a buffer */
+       Byte*    _buffer; /**< Raw MIDI data */
+
+#ifdef MIDI_EVENT_ALLOW_ALLOC
+       bool _owns_buffer; /**< Whether buffer is locally allocated */
+#endif
 };
 
 
index 74a3e61f9a67aa4517d92cb0545c70537459ed5d..6ea5a30920a8ddafc82edba8907e58718644034c 100644 (file)
@@ -23,7 +23,6 @@
 #include <ardour/peak.h>
 #include <ardour/dB.h>
 #include <ardour/session.h>
-#include <ardour/midi_events.h>
 
 namespace ARDOUR {
 
@@ -49,7 +48,7 @@ PeakMeter::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nfr
                // expressed through peaks alone
                for (MidiBuffer::iterator i = bufs.get_midi(n).begin(); i != bufs.get_midi(n).end(); ++i) {
                        const MidiEvent& ev = *i;
-                       if ((ev.buffer()[0] & 0xF0) == MIDI_CMD_NOTE_ON) {
+                       if (ev.is_note_on()) {
                                const float this_vel = log(ev.buffer()[2] / 127.0 * (M_E*M_E-M_E) + M_E) - 1.0;
                                //printf("V %d -> %f\n", (int)((Byte)ev.buffer[2]), this_vel);
                                if (this_vel > val)
index b2d5a8092821f57561536ec51c16aa32f495c27b..7a09804aef85a5f8fb5636dd07294ec65b941815 100644 (file)
@@ -33,8 +33,8 @@ using namespace ARDOUR;
 // Note
 
 MidiModel::Note::Note(double t, double d, uint8_t n, uint8_t v)
-       : _on_event(true, t, 3, NULL)
-       , _off_event(true, t + d, 3, NULL)
+       : _on_event(t, 3, NULL, true)
+       , _off_event(t + d, 3, NULL, true)
 {
        _on_event.buffer()[0] = MIDI_CMD_NOTE_ON;
        _on_event.buffer()[1] = n;
index ae1c8f1a071534f523dbcb8dfe02d7150275f6c9..ac40170e72d644b9ddd624a70bc3bcd3a55bc82c 100644 (file)
@@ -587,7 +587,7 @@ MidiTrack::write_controller_messages(MidiBuffer& output_buf, nframes_t start_fra
        
        Byte buf[3]; // CC = 3 bytes
        buf[0] = MIDI_CMD_CONTROL;
-       MidiEvent ev(false, 0, 3, buf);
+       MidiEvent ev(0, 3, buf, false);
 
        // Write controller automation
        if (_session.transport_rolling()) {