improve the performance of MidiRegionView::find_canvas_patch_change().
authornick_m <mainsbridge@gmail.com>
Wed, 28 Dec 2016 17:21:37 +0000 (04:21 +1100)
committernick_m <mainsbridge@gmail.com>
Wed, 28 Dec 2016 17:21:37 +0000 (04:21 +1100)
- also fixes patch changes appearing outside region bounds
  when copied/trimmed.

gtk2_ardour/midi_region_view.cc
gtk2_ardour/midi_region_view.h

index 7b53b72b413e01d808f3065b5a75f2a5d1b792a2..4057ea95c0e5ee92071f62ae003fa500d47fc38d 100644 (file)
@@ -1136,10 +1136,10 @@ MidiRegionView::find_canvas_note (Evoral::event_id_t id)
 boost::shared_ptr<PatchChange>
 MidiRegionView::find_canvas_patch_change (MidiModel::PatchChangePtr p)
 {
-       for (PatchChanges::iterator x = _patch_changes.begin(); x != _patch_changes.end(); ++x) {
-               if ((*x)->patch() == p) {
-                       return (*x);
-               }
+       PatchChanges::const_iterator f = _patch_changes.find (p);
+
+       if (f != _patch_changes.end()) {
+               return (*f).second;
        }
 
        return boost::shared_ptr<PatchChange>();
@@ -1331,11 +1331,20 @@ MidiRegionView::display_patch_changes_on_channel (uint8_t channel, bool active_c
                }
 
                if ((p = find_canvas_patch_change (*i)) != 0) {
-                       framecnt_t region_frames = source_beats_to_region_frames ((*i)->time());
-                       const double x = trackview.editor().sample_to_pixel (region_frames);
-                       const string patch_name = instrument_info().get_patch_name ((*i)->bank(), (*i)->program(), channel);
-                       p->canvas_item()->set_position (ArdourCanvas::Duple (x, 1.0));
-                       p->flag()->set_text (patch_name);
+
+                       const framecnt_t region_frames = source_beats_to_region_frames ((*i)->time());
+
+                       if (region_frames < 0 || region_frames >= _region->length()) {
+                               p->hide();
+                       } else {
+                               const double x = trackview.editor().sample_to_pixel (region_frames);
+                               const string patch_name = instrument_info().get_patch_name ((*i)->bank(), (*i)->program(), channel);
+                               p->canvas_item()->set_position (ArdourCanvas::Duple (x, 1.0));
+                               p->flag()->set_text (patch_name);
+
+                               p->show();
+                       }
+
                } else {
                        const string patch_name = instrument_info().get_patch_name ((*i)->bank(), (*i)->program(), channel);
                        add_canvas_patch_change (*i, patch_name, active_channel);
@@ -1474,11 +1483,15 @@ MidiRegionView::reset_width_dependent_items (double pixel_width)
                redisplay_model();
        }
 
-       for (PatchChanges::iterator x = _patch_changes.begin(); x != _patch_changes.end(); ++x) {
-               if ((*x)->canvas_item()->width() >= _pixel_width) {
-                       (*x)->hide();
-               } else {
-                       (*x)->show();
+       bool hide_all = false;
+       PatchChanges::iterator x = _patch_changes.begin();
+       if (x != _patch_changes.end()) {
+               hide_all = (*x).second->flag()->width() >= _pixel_width;
+       }
+
+       if (hide_all) {
+               for (; x != _patch_changes.end(); ++x) {
+                       (*x).second->hide();
                }
        }
 
@@ -1501,7 +1514,7 @@ MidiRegionView::set_height (double height)
        }
 
        for (PatchChanges::iterator x = _patch_changes.begin(); x != _patch_changes.end(); ++x) {
-               (*x)->set_height (midi_stream_view()->contents_height());
+               (*x).second->set_height (midi_stream_view()->contents_height());
        }
 
        if (_step_edit_cursor) {
@@ -1946,7 +1959,7 @@ MidiRegionView::add_canvas_patch_change (MidiModel::PatchChangePtr patch, const
                patch_change->hide ();
        }
 
-       _patch_changes.push_back (patch_change);
+       _patch_changes.insert (make_pair (patch, patch_change));
 }
 
 void
@@ -1954,7 +1967,7 @@ MidiRegionView::remove_canvas_patch_change (PatchChange* pc)
 {
        /* remove the canvas item */
        for (PatchChanges::iterator x = _patch_changes.begin(); x != _patch_changes.end(); ++x) {
-               if ((*x)->patch() == pc->patch()) {
+               if ((*x).second->patch() == pc->patch()) {
                        _patch_changes.erase (x);
                        break;
                }
@@ -2047,7 +2060,7 @@ MidiRegionView::change_patch_change (MidiModel::PatchChangePtr old_change, const
        trackview.editor().commit_reversible_command ();
 
        for (PatchChanges::iterator x = _patch_changes.begin(); x != _patch_changes.end(); ++x) {
-               if ((*x)->patch() == old_change) {
+               if ((*x).second->patch() == old_change) {
                        _patch_changes.erase (x);
                        break;
                }
index f8cb9c058cc1d0f2c0425b13917a2d2021334176..a608ad810c0a91ef60d8e2e7edc164fedd78f933 100644 (file)
@@ -410,7 +410,7 @@ private:
        uint8_t  _current_range_max;
 
        typedef std::list<NoteBase*>                          Events;
-       typedef std::vector< boost::shared_ptr<PatchChange> > PatchChanges;
+       typedef std::map<ARDOUR::MidiModel::PatchChangePtr, boost::shared_ptr<PatchChange> > PatchChanges;
        typedef std::vector< boost::shared_ptr<SysEx> >       SysExes;
 
        ARDOUR::BeatsFramesConverter _region_relative_time_converter;