diff --git a/gtk2_ardour/audio_region_view.h b/gtk2_ardour/audio_region_view.h index b670fa7a43..0e932f69c2 100644 --- a/gtk2_ardour/audio_region_view.h +++ b/gtk2_ardour/audio_region_view.h @@ -144,8 +144,6 @@ public: return _end_xfade_visible; } - void redisplay () {} - protected: /* this constructor allows derived types @@ -210,6 +208,7 @@ protected: void transients_changed(); AutomationLine::VisibleAspects automation_line_visibility () const; + void _redisplay (bool) {} private: void setup_fade_handle_positions (); diff --git a/gtk2_ardour/automation_region_view.h b/gtk2_ardour/automation_region_view.h index 6c98b0f8a2..a79e298d57 100644 --- a/gtk2_ardour/automation_region_view.h +++ b/gtk2_ardour/automation_region_view.h @@ -67,7 +67,6 @@ public: void set_height (double); void reset_width_dependent_items(double pixel_width); - void redisplay () {} protected: void create_line(boost::shared_ptr list); @@ -78,6 +77,7 @@ protected: void mouse_mode_changed (); void entered(); void exited(); + void _redisplay (bool) {} private: Evoral::Parameter _parameter; diff --git a/gtk2_ardour/ghostregion.cc b/gtk2_ardour/ghostregion.cc index 53c3f7eb73..d028e59586 100644 --- a/gtk2_ardour/ghostregion.cc +++ b/gtk2_ardour/ghostregion.cc @@ -442,8 +442,15 @@ MidiGhostRegion::remove_note (NoteBase* note) _optimization_iterator = events.end (); } + void -MidiGhostRegion::redisplay_model () +MidiGhostRegion::view_changed () +{ + model_changed(); +} + +void +MidiGhostRegion::model_changed () { /* we rely on the parent MRV having removed notes not in the model */ for (EventList::iterator i = events.begin(); i != events.end(); ) { diff --git a/gtk2_ardour/ghostregion.h b/gtk2_ardour/ghostregion.h index 30ebd662a7..6fbd7258be 100644 --- a/gtk2_ardour/ghostregion.h +++ b/gtk2_ardour/ghostregion.h @@ -122,7 +122,8 @@ public: void update_hit (GhostEvent* hit); void remove_note (NoteBase*); - void redisplay_model(); + void model_changed(); + void view_changed(); void clear_events(); private: diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index e6de9ac131..7932e5946d 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -191,7 +191,7 @@ MidiRegionView::parameter_changed (std::string const & p) RegionView::parameter_changed (p); if (p == "display-first-midi-bank-as-zero") { if (display_enabled()) { - redisplay_model(); + view_changed (); } } else if (p == "color-regions-using-track-color") { set_colors (); @@ -277,8 +277,6 @@ MidiRegionView::init (bool /*wfd*/) set_colors (); reset_width_dependent_items (_pixel_width); - display_model (_model); - group->raise_to_top(); midi_view()->midi_track()->playback_filter().ChannelModeChanged.connect (_channel_mode_changed_connection, invalidator (*this), @@ -896,16 +894,17 @@ MidiRegionView::clear_events () } void -MidiRegionView::display_model(boost::shared_ptr model) +MidiRegionView::display_model (boost::shared_ptr model) { _model = model; content_connection.disconnect (); - _model->ContentsChanged.connect (content_connection, invalidator (*this), boost::bind (&MidiRegionView::redisplay_model, this), gui_context()); + _model->ContentsChanged.connect (content_connection, invalidator (*this), boost::bind (&MidiRegionView::model_changed, this), gui_context()); /* Don't signal as nobody else needs to know until selection has been altered. */ clear_events(); + // PBD::stacktrace (std::cerr, 8); - redisplay_model (); + model_changed (); } void @@ -1080,13 +1079,17 @@ MidiRegionView::get_events (Events& e, Evoral::Sequence::NoteOp } void -MidiRegionView::redisplay () +MidiRegionView::_redisplay (bool view_only) { - redisplay_model (); + if (view_only) { + view_changed (); + } else { + model_changed (); + } } void -MidiRegionView::redisplay_model() +MidiRegionView::model_changed() { if (!display_enabled()) { return; @@ -1118,7 +1121,7 @@ MidiRegionView::redisplay_model() } for (_optimization_iterator = _events.begin(); _optimization_iterator != _events.end(); ++_optimization_iterator) { - _optimization_iterator->second->invalidate(); + // _optimization_iterator->second->invalidate(); } bool empty_when_starting = _events.empty(); @@ -1131,6 +1134,8 @@ MidiRegionView::redisplay_model() MidiModel::Notes& notes (_model->notes()); NoteBase* cne; + + if (empty_when_starting) { for (MidiModel::Notes::iterator n = notes.begin(); n != notes.end(); ++n) { boost::shared_ptr note (*n); @@ -1149,6 +1154,7 @@ MidiRegionView::redisplay_model() } } } + } if (!empty_when_starting) { MidiModel::Notes::iterator f; @@ -1190,6 +1196,8 @@ MidiRegionView::redisplay_model() } } + std::cerr << this << " Adding " << missing_notes.size() << " missing notes\n"; + for (MidiModel::Notes::iterator n = missing_notes.begin(); n != missing_notes.end(); ++n) { boost::shared_ptr note (*n); NoteBase* cne; @@ -1215,7 +1223,7 @@ MidiRegionView::redisplay_model() for (vector::iterator j = ghosts.begin(); j != ghosts.end(); ++j) { MidiGhostRegion* gr = dynamic_cast (*j); if (gr && !gr->trackview.hidden()) { - gr->redisplay_model (); + gr->model_changed (); } } @@ -1230,6 +1238,78 @@ MidiRegionView::redisplay_model() std::cerr << "REDISPLAY of " << region()->name() << " complete after " << t.elapsed_msecs() << std::endl; } +void +MidiRegionView::view_changed() +{ + if (!display_enabled()) { + return; + } + + // PBD::stacktrace (std::cerr, 8); + + Timing t; + + if (_active_notes) { + // Currently recording + const samplecnt_t zoom = trackview.editor().get_current_zoom(); + if (zoom != _last_display_zoom) { + /* Update resolved canvas notes to reflect changes in zoom without + touching model. Leave active notes (with length max) alone since + they are being extended. */ + for (Events::iterator i = _events.begin(); i != _events.end(); ++i) { + if (i->second->note()->end_time() != std::numeric_limits::max()) { + update_note(i->second); + } + } + _last_display_zoom = zoom; + } + return; + } + + if (!_model) { + return; + } + + Note* sus = NULL; + Hit* hit = NULL; + + for (Events::iterator i = _events.begin(); i != _events.end(); ) { + + NoteBase* cne = i->second; + + bool visible = cne->item()->visible(); + + if ((sus = dynamic_cast(cne))) { + + if (visible) { + update_sustained (sus); + } + + } else if ((hit = dynamic_cast(cne))) { + + if (visible) { + update_hit (hit); + } + + } + + ++i; + } + + for (vector::iterator j = ghosts.begin(); j != ghosts.end(); ++j) { + MidiGhostRegion* gr = dynamic_cast (*j); + if (gr && !gr->trackview.hidden()) { + gr->view_changed (); + } + } + + update_sysexes(); + update_patch_changes (); + + t.update (); + std::cerr << "REDISPLAY of " << region()->name() << " complete after " << t.elapsed_msecs() << std::endl; +} + void MidiRegionView::display_patch_changes () { @@ -1277,6 +1357,30 @@ MidiRegionView::display_patch_changes_on_channel (uint8_t channel, bool active_c } } +void +MidiRegionView::update_patch_changes () +{ + for (PatchChanges::iterator p = _patch_changes.begin(); p != _patch_changes.end(); ++p) { + + boost::shared_ptr pc (p->second); + + const timepos_t region_time = _region->source_beats_to_region_time (p->first->time()); + + if (region_time < timepos_t() || region_time >= _region->length()) { + pc->hide(); + } else { + const timepos_t flag_time = _region->source_beats_to_absolute_time (p->first->time()); + const double flag_x = trackview.editor().time_to_pixel (flag_time); + + const double region_x = trackview.editor().time_to_pixel (_region->position()); + + pc->canvas_item()->set_position (ArdourCanvas::Duple (flag_x-region_x, 1.0)); + pc->update_name (); + pc->show(); + } + } +} + void MidiRegionView::display_sysexes() { @@ -1360,6 +1464,31 @@ MidiRegionView::display_sysexes() } } +void +MidiRegionView::update_sysexes () +{ + double height = midi_stream_view()->contents_height(); + + for (SysExes::iterator s = _sys_exes.begin(); s != _sys_exes.end(); ++s) { + + const timepos_t time (s->first->time()); + boost::shared_ptr sysex (s->second); + + // Show unless message is beyond the region bounds + if (_region->source_relative_position (time) >= _region->length() || time < _region->start()) { + sysex->hide(); + continue; + } else { + sysex->show(); + } + + const double x = trackview.editor().time_to_pixel (_region->source_beats_to_region_time (time.beats())); + + sysex->set_height (height); + sysex->item().set_position (ArdourCanvas::Duple (x, 1.0)); + } +} + MidiRegionView::~MidiRegionView () { in_destructor = true; @@ -1392,9 +1521,7 @@ MidiRegionView::reset_width_dependent_items (double pixel_width) { RegionView::reset_width_dependent_items(pixel_width); - if (display_enabled()) { - redisplay_model(); - } + view_changed (); bool hide_all = false; PatchChanges::iterator x = _patch_changes.begin(); @@ -1449,7 +1576,7 @@ MidiRegionView::apply_note_range (uint8_t min, uint8_t max, bool force) _current_range_min = min; _current_range_max = max; - redisplay_model (); + view_changed (); } GhostRegion* @@ -3569,8 +3696,6 @@ MidiRegionView::midi_channel_mode_changed () void MidiRegionView::instrument_settings_changed () { - redisplay_model(); - for (PatchChanges::iterator x = _patch_changes.begin(); x != _patch_changes.end(); ++x) { (*x).second->update_name (); } diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 4e99621298..42f62cc4d4 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -120,9 +120,6 @@ public: void hide_step_edit_cursor (); void set_step_edit_cursor_width (Temporal::Beats beats); - virtual void redisplay (); - void redisplay_model(); - GhostRegion* add_ghost (TimeAxisView&); NoteBase* add_note(const boost::shared_ptr note, bool visible); @@ -333,6 +330,7 @@ public: void reset_width_dependent_items (double pixel_width); void parameter_changed (std::string const & p); + void _redisplay (bool view_only); protected: friend class Editor; @@ -564,6 +562,11 @@ public: double note_to_y (uint8_t note) const; uint8_t y_to_note (double y) const; + + void update_patch_changes (); + void update_sysexes (); + void view_changed (); + void model_changed (); }; diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc index f5f7c66ba8..2024a6e7df 100644 --- a/gtk2_ardour/region_view.cc +++ b/gtk2_ardour/region_view.cc @@ -1260,7 +1260,7 @@ RegionView::enable_display () if (_disable_display) { _disable_display--; if (_disable_display == 0) { - redisplay (); + redisplay (false); } } } diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h index 4cd0fd73d6..3b2576a7f3 100644 --- a/gtk2_ardour/region_view.h +++ b/gtk2_ardour/region_view.h @@ -102,7 +102,9 @@ public: virtual void exited () {} bool display_enabled() const; - virtual void redisplay() = 0; + void redisplay (bool view_only = true) { + _redisplay (view_only); + } struct DisplaySuspender { DisplaySuspender (RegionView& rv) : region_view (rv) { @@ -243,11 +245,13 @@ private: typedef std::list ViewCueMarkers; ViewCueMarkers _cue_markers; bool _cue_markers_visible; + virtual void _redisplay (bool) = 0; private: friend class DisplaySuspender; void enable_display(); void disable_display(); + }; #endif /* __gtk_ardour_region_view_h__ */