Remove non-RT-safe alloc in the MIDI process() call.
authorCarl Hetherington <carl@carlh.net>
Fri, 4 Nov 2011 17:52:12 +0000 (17:52 +0000)
committerCarl Hetherington <carl@carlh.net>
Fri, 4 Nov 2011 17:52:12 +0000 (17:52 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@10441 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/midi_region_view.cc
gtk2_ardour/midi_region_view.h
libs/ardour/ardour/midi_diskstream.h
libs/ardour/ardour/midi_track.h
libs/ardour/midi_diskstream.cc
libs/ardour/midi_track.cc

index fcab48328711f3ad127de3f199dc51c668c2883d..0f30c357330873cb259b25320f0d38dda70068cc 100644 (file)
@@ -305,7 +305,7 @@ MidiRegionView::connect_to_diskstream ()
 {
        midi_view()->midi_track()->DataRecorded.connect(
                *this, invalidator(*this),
-               ui_bind(&MidiRegionView::data_recorded, this, _1, _2),
+               ui_bind(&MidiRegionView::data_recorded, this, _1),
                gui_context());
 }
 
@@ -3525,11 +3525,10 @@ MidiRegionView::set_step_edit_cursor_width (Evoral::MusicalTime beats)
 }
 
 /** Called when a diskstream on our track has received some data.  Update the view, if applicable.
- *  @param buf Data that has been recorded.
- *  @param w Source that this data will end up in.
+ *  @param w Source that the data will end up in.
  */
 void
-MidiRegionView::data_recorded (boost::shared_ptr<MidiBuffer> buf, boost::weak_ptr<MidiSource> w)
+MidiRegionView::data_recorded (boost::weak_ptr<MidiSource> w)
 {
        if (!_active_notes) {
                /* we aren't actively being recorded to */
@@ -3543,6 +3542,9 @@ MidiRegionView::data_recorded (boost::shared_ptr<MidiBuffer> buf, boost::weak_pt
        }
 
        MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (&trackview);
+
+       boost::shared_ptr<MidiBuffer> buf = mtv->midi_track()->get_gui_feed_buffer ();
+
        BeatsFramesConverter converter (trackview.session()->tempo_map(), mtv->midi_track()->get_capture_start_frame (0));
 
        framepos_t back = max_framepos;
index c43c863afef8762ae295eeedbd8ec0214d4d0bc1..70939ac640eadfafb46a64e8aefacb8c60104593 100644 (file)
@@ -456,7 +456,7 @@ private:
        void display_patch_changes_on_channel (uint8_t);
 
        void connect_to_diskstream ();
-       void data_recorded (boost::shared_ptr<ARDOUR::MidiBuffer>, boost::weak_ptr<ARDOUR::MidiSource>);
+       void data_recorded (boost::weak_ptr<ARDOUR::MidiSource>);
 
        void remove_ghost_note ();
        void mouse_mode_changed ();
index 65008714123b2f4be47fdcb546a76c7d1f7dd174..a7695b5ebfff985adecfc1e2fa3065bdb4e6a865 100644 (file)
@@ -110,10 +110,12 @@ class MidiDiskstream : public Diskstream
        }
 
        /** Emitted when some MIDI data has been received for recording.
-        *  First parameter is the data.
-        *  Second parameter is the source that it is destined for.
+        *  Parameter is the source that it is destined for.
+        *  A caller can get a copy of the data with get_gui_feed_buffer ()
         */
-       PBD::Signal2<void, boost::shared_ptr<MidiBuffer>, boost::weak_ptr<MidiSource> > DataRecorded;
+       PBD::Signal1<void, boost::weak_ptr<MidiSource> > DataRecorded;
+
+       boost::shared_ptr<MidiBuffer> get_gui_feed_buffer () const;
 
   protected:
        friend class Session;
@@ -189,6 +191,12 @@ class MidiDiskstream : public Diskstream
        NoteMode                     _note_mode;
        volatile gint                _frames_written_to_ringbuffer;
        volatile gint                _frames_read_from_ringbuffer;
+
+       /** A buffer that we use to put newly-arrived MIDI data in for
+           the GUI to read (so that it can update itself).
+       */
+       MidiBuffer                   _gui_feed_buffer;
+       mutable Glib::Mutex          _gui_feed_buffer_mutex;
 };
 
 }; /* namespace ARDOUR */
index 3d1ef558dc2ae64701f7e04b0d194c68f1b0c096..a70fc4604d72b4a28c4e40166eb6839c52699b32 100644 (file)
@@ -104,7 +104,8 @@ public:
                return false;
        }
 
-       PBD::Signal2<void, boost::shared_ptr<MidiBuffer>, boost::weak_ptr<MidiSource> > DataRecorded;
+       PBD::Signal1<void, boost::weak_ptr<MidiSource> > DataRecorded;
+       boost::shared_ptr<MidiBuffer> get_gui_feed_buffer () const;
 
        void set_input_active (bool);
        bool input_active () const;
@@ -138,7 +139,7 @@ protected:
        int no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing);
        void push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes);
 
-       void diskstream_data_recorded (boost::shared_ptr<MidiBuffer>, boost::weak_ptr<MidiSource>);
+       void diskstream_data_recorded (boost::weak_ptr<MidiSource>);
        PBD::ScopedConnection _diskstream_data_recorded_connection;
 
        void track_input_active (IOChange, void*);
index 7ab8c46c306297073891a96357f970235d463e1c..81217b179acea4a185242a28649547fa58f629db 100644 (file)
@@ -77,6 +77,7 @@ MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::F
        , _note_mode(Sustained)
        , _frames_written_to_ringbuffer(0)
        , _frames_read_from_ringbuffer(0)
+       , _gui_feed_buffer(AudioEngine::instance()->raw_buffer_size (DataType::MIDI))
 {
        in_set_state = true;
 
@@ -96,6 +97,7 @@ MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node)
        , _note_mode(Sustained)
        , _frames_written_to_ringbuffer(0)
        , _frames_read_from_ringbuffer(0)
+       , _gui_feed_buffer(AudioEngine::instance()->raw_buffer_size (DataType::MIDI))
 {
        in_set_state = true;
 
@@ -549,17 +551,23 @@ MidiDiskstream::process (framepos_t transport_frame, pframes_t nframes, framecnt
                }
 
                if (buf.size() != 0) {
-                       /* XXX this needs fixing - realtime new() call for
-                          every time we get MIDI data in a process callback!
-                       */
-
-                       /* Make a copy of this data and emit it for the GUI to see */
-                       boost::shared_ptr<MidiBuffer> copy (new MidiBuffer (buf.capacity ()));
-                       for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
-                               copy->push_back ((*i).time() + transport_frame, (*i).size(), (*i).buffer());
+                       Glib::Mutex::Lock lm (_gui_feed_buffer_mutex, Glib::TRY_LOCK);
+
+                       if (lm.locked ()) {
+                               /* Copy this data into our GUI feed buffer and tell the GUI
+                                  that it can read it if it likes.
+                               */
+                               _gui_feed_buffer.clear ();
+                               
+                               for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
+                                       /* This may fail if buf is larger than _gui_feed_buffer, but it's not really
+                                          the end of the world if it does.
+                                       */
+                                       _gui_feed_buffer.push_back ((*i).time() + transport_frame, (*i).size(), (*i).buffer());
+                               }
                        }
 
-                       DataRecorded (copy, _write_source); /* EMIT SIGNAL */
+                       DataRecorded (_write_source); /* EMIT SIGNAL */
                }
 
        } else {
@@ -1450,3 +1458,12 @@ MidiDiskstream::set_name (string const & name)
        return true;
 }
 
+boost::shared_ptr<MidiBuffer>
+MidiDiskstream::get_gui_feed_buffer () const
+{
+       boost::shared_ptr<MidiBuffer> b (new MidiBuffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI)));
+       
+       Glib::Mutex::Lock lm (_gui_feed_buffer_mutex);
+       b->copy (_gui_feed_buffer);
+       return b;
+}
index 9114311ac9e0b1e24d622c1d5cf95bdf843f7bda..3253485412a181e9d0bb3d5aa3d9ab63365a65d8 100644 (file)
@@ -122,7 +122,7 @@ MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
        boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
        mds->DataRecorded.connect_same_thread (
                _diskstream_data_recorded_connection,
-               boost::bind (&MidiTrack::diskstream_data_recorded, this, _1, _2));
+               boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
 
        DiskstreamChanged (); /* EMIT SIGNAL */
 }
@@ -654,9 +654,9 @@ MidiTrack::midi_playlist ()
 }
 
 void
-MidiTrack::diskstream_data_recorded (boost::shared_ptr<MidiBuffer> buf, boost::weak_ptr<MidiSource> src)
+MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
 {
-       DataRecorded (buf, src); /* EMIT SIGNAL */
+       DataRecorded (src); /* EMIT SIGNAL */
 }
 
 bool
@@ -717,3 +717,9 @@ MidiTrack::diskstream_factory (XMLNode const & node)
 {
        return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
 }
+
+boost::shared_ptr<MidiBuffer>
+MidiTrack::get_gui_feed_buffer () const
+{
+       return midi_diskstream()->get_gui_feed_buffer ();
+}