From 9038be49d821f89824c83cf505d51366eb2828c6 Mon Sep 17 00:00:00 2001 From: nick_m Date: Tue, 20 Dec 2016 21:31:54 +1100 Subject: [PATCH] improve midi zoom/scroom performance with lots of notes. - mostly due to searching a multiset rather than a list of canvas events. --- gtk2_ardour/midi_region_view.cc | 96 ++++++++++++++++----------------- 1 file changed, 45 insertions(+), 51 deletions(-) diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 376ae0197f..ecc39dde6b 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -1186,61 +1186,15 @@ MidiRegionView::redisplay_model() return; } - for (Events::iterator i = _events.begin(); i != _events.end(); ++i) { - (*i)->invalidate (); - } - - MidiModel::ReadLock lock(_model->read_lock()); - - MidiModel::Notes& notes (_model->notes()); - _optimization_iterator = _events.begin(); - bool empty_when_starting = _events.empty(); - NoteBase* cne; - - for (MidiModel::Notes::iterator n = notes.begin(); n != notes.end(); ++n) { - - boost::shared_ptr note (*n); - bool visible; - - if (note_in_region_range (note, visible)) { - - if (!empty_when_starting && (cne = find_canvas_note (note)) != 0) { - - if (visible) { - cne->validate (); - update_note (cne); - cne->show (); - } else { - cne->hide (); - } - - } else { - - cne = add_note (note, visible); - } - - set::iterator it; - for (it = _pending_note_selection.begin(); it != _pending_note_selection.end(); ++it) { - if ((*it) == note->id()) { - add_to_selection (cne); - } - } - - } else { - - if (!empty_when_starting && (cne = find_canvas_note (note)) != 0) { - cne->validate (); - cne->hide (); - } - } - } - - /* remove note items that are no longer valid */ + MidiModel::ReadLock lock(_model->read_lock()); + MidiModel::Notes missing_notes = _model->notes(); // copy if (!empty_when_starting) { for (Events::iterator i = _events.begin(); i != _events.end(); ) { - if (!(*i)->valid ()) { + boost::shared_ptr note ((*i)->note()); + /* remove note items that are no longer valid */ + if (!(*i)->valid () || !_model->find_note (note)) { for (vector::iterator j = ghosts.begin(); j != ghosts.end(); ++j) { MidiGhostRegion* gr = dynamic_cast (*j); @@ -1253,8 +1207,48 @@ MidiRegionView::redisplay_model() i = _events.erase (i); } else { + MidiModel::Notes::iterator f; + NoteBase* cne = (*i); + bool visible; + + if (note_in_region_range (note, visible)) { + if (visible) { + update_note (cne); + cne->show (); + } else { + cne->hide (); + } + } else { + cne->hide (); + } + + if ((f = missing_notes.find (note)) != missing_notes.end()) { + missing_notes.erase (f); + } + ++i; } + + } + } + + NoteBase* cne; + + for (MidiModel::Notes::iterator n = missing_notes.begin(); n != missing_notes.end(); ++n) { + boost::shared_ptr note (*n); + bool visible; + + if (note_in_region_range (note, visible)) { + if (visible) { + cne = add_note (note, true); + set::iterator it; + + for (it = _pending_note_selection.begin(); it != _pending_note_selection.end(); ++it) { + if ((*it) == note->id()) { + add_to_selection (cne); + } + } + } } }