split midi region view redisplay into two similar methods

::model_changed() is used when the model has changed (eg. new notes or some
notes deleted); ::view_changed() is used when only some view parameter (e.g.
zoom, scroll, track height etc) has been altered.

Not fully functional yet (::view_chanted() ignores scroll)
This commit is contained in:
Paul Davis 2022-04-01 22:24:01 -06:00
parent 1a8b80e56e
commit 4fa97e2c50
8 changed files with 166 additions and 27 deletions

View File

@ -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 ();

View File

@ -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<ARDOUR::AutomationList> list);
@ -78,6 +77,7 @@ protected:
void mouse_mode_changed ();
void entered();
void exited();
void _redisplay (bool) {}
private:
Evoral::Parameter _parameter;

View File

@ -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(); ) {

View File

@ -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:

View File

@ -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<MidiModel> model)
MidiRegionView::display_model (boost::shared_ptr<MidiModel> 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<Temporal::Beats>::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<NoteType> 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<NoteType> note (*n);
NoteBase* cne;
@ -1215,7 +1223,7 @@ MidiRegionView::redisplay_model()
for (vector<GhostRegion*>::iterator j = ghosts.begin(); j != ghosts.end(); ++j) {
MidiGhostRegion* gr = dynamic_cast<MidiGhostRegion*> (*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<Temporal::Beats>::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<Note*>(cne))) {
if (visible) {
update_sustained (sus);
}
} else if ((hit = dynamic_cast<Hit*>(cne))) {
if (visible) {
update_hit (hit);
}
}
++i;
}
for (vector<GhostRegion*>::iterator j = ghosts.begin(); j != ghosts.end(); ++j) {
MidiGhostRegion* gr = dynamic_cast<MidiGhostRegion*> (*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<PatchChange> 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> 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 ();
}

View File

@ -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<NoteType> 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 ();
};

View File

@ -1260,7 +1260,7 @@ RegionView::enable_display ()
if (_disable_display) {
_disable_display--;
if (_disable_display == 0) {
redisplay ();
redisplay (false);
}
}
}

View File

@ -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<ViewCueMarker*> 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__ */