From 63c78ebceddb9af541afb600e18d6862b2feefa3 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 23 Oct 2022 19:12:31 +0200 Subject: [PATCH] Fix MIDI edit opertaiont (trim, draw) across tempo-changes In the presence of tempo-changes distinguishing between offsets and absolute positions is signficant. It is only valid to convert absolute times using the tempo-map Furthermore since GUI zoom-factor is time-invariant (samples per pixel), all GUI operations must explictly use samples (or timecnt). It is not valid (and problematic) to use use a location dependent timepos. --- gtk2_ardour/automation_region_view.cc | 2 +- gtk2_ardour/editor_drag.cc | 16 ++++++++-------- gtk2_ardour/midi_region_view.cc | 16 ++++++++-------- gtk2_ardour/midi_region_view.h | 4 ++-- gtk2_ardour/region_view.cc | 4 ++-- gtk2_ardour/region_view.h | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/gtk2_ardour/automation_region_view.cc b/gtk2_ardour/automation_region_view.cc index a8a2dac2b4..15e6a48dc6 100644 --- a/gtk2_ardour/automation_region_view.cc +++ b/gtk2_ardour/automation_region_view.cc @@ -192,7 +192,7 @@ AutomationRegionView::add_automation_event (GdkEvent *, timepos_t const & w, dou /* snap time */ - when = snap_region_time_to_region_time (when.earlier (_region->start()), false) + _region->start (); + when = snap_region_time_to_region_time (_region->start().distance (when), false) + _region->start (); /* map using line */ diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 48d3ca6fcd..cc5e2cc040 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -6692,11 +6692,11 @@ NoteCreateDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) * coordinates relative to the region in order to draw it correctly. */ - const timepos_t rrp1 (_region_view->region()->region_relative_position (_note[0])); - const timepos_t rrp2 (_region_view->region()->region_relative_position (_note[1])); + const timecnt_t rrp1 (_region_view->region()->region_relative_position (_note[0])); + const timecnt_t rrp2 (_region_view->region()->region_relative_position (_note[1])); - double const x0 = _editor->time_to_pixel (rrp1); - double const x1 = _editor->time_to_pixel (rrp2); + double const x0 = _editor->sample_to_pixel (rrp1.samples ()); + double const x1 = _editor->sample_to_pixel (rrp2.samples ()); double const y = _region_view->note_to_y (_region_view->y_to_note (y_to_region (event->button.y))); _drag_rect->set (ArdourCanvas::Rect (x0, y, x1, y + floor (_region_view->midi_stream_view()->note_height ()))); @@ -6717,11 +6717,11 @@ NoteCreateDrag::motion (GdkEvent* event, bool) _note[1] = timepos_t (max (Temporal::Beats(), aligned_beats)); - const timepos_t rrp1 (_region_view->region()->region_relative_position (_note[0])); - const timepos_t rrp2 (_region_view->region()->region_relative_position (_note[1])); + const timecnt_t rrp1 (_region_view->region()->region_relative_position (_note[0])); + const timecnt_t rrp2 (_region_view->region()->region_relative_position (_note[1])); - double const x0 = _editor->time_to_pixel (rrp1); - double const x1 = _editor->time_to_pixel (rrp2); + double const x0 = _editor->sample_to_pixel (rrp1.samples()); + double const x1 = _editor->sample_to_pixel (rrp2.samples()); _drag_rect->set_x0 (std::min(x0, x1)); _drag_rect->set_x1 (std::max(x0, x1)); } diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index ce77e9697b..923ed9ab03 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -2527,8 +2527,8 @@ MidiRegionView::update_drag_selection(timepos_t const & start, timepos_t const & // Convert to local coordinates const double y = midi_view()->y_position(); - const double x0 = editor.time_to_pixel (max (timepos_t(), _region->region_relative_position (start))); - const double x1 = editor.time_to_pixel (max (timepos_t(), _region->region_relative_position (end))); + const double x0 = editor.sample_to_pixel (max(0, _region->region_relative_position (start).samples())); + const double x1 = editor.sample_to_pixel (max(0, _region->region_relative_position (end).samples())); const double y0 = max(0.0, gy0 - y); const double y1 = max(0.0, gy1 - y); @@ -2941,11 +2941,11 @@ MidiRegionView::note_dropped(NoteBase *, timecnt_t const & d_qn, int8_t dnote, b * Used for inverting the snap logic with key modifiers and snap delta calculation. * @return Snapped time relative to the region position. */ -timepos_t +timecnt_t MidiRegionView::snap_pixel_to_time (double x, bool ensure_snap) { PublicEditor& editor (trackview.editor()); - return snap_region_time_to_region_time (timepos_t (editor.pixel_to_sample (x)), ensure_snap); + return snap_region_time_to_region_time (timecnt_t (editor.pixel_to_sample (x)), ensure_snap); } /** @param x Pixel relative to the region position. @@ -2955,7 +2955,7 @@ MidiRegionView::snap_pixel_to_time (double x, bool ensure_snap) double MidiRegionView::snap_to_pixel(double x, bool ensure_snap) { - return (double) trackview.editor().time_to_pixel(snap_pixel_to_time(x, ensure_snap)); + return (double) trackview.editor().sample_to_pixel (snap_pixel_to_time(x, ensure_snap).samples()); } double @@ -3188,11 +3188,11 @@ MidiRegionView::finish_resizing (NoteBase* primary, bool at_front, double delta_ } /* Convert the new x position to a position within the source */ - timepos_t current_time; + timecnt_t current_time; if (with_snap) { current_time = snap_pixel_to_time (current_x, ensure_snap); } else { - current_time = timepos_t (trackview.editor().pixel_to_sample (current_x)); + current_time = timecnt_t (trackview.editor().pixel_to_sample (current_x)); } /* and then to beats */ @@ -4124,7 +4124,7 @@ MidiRegionView::update_ghost_note (double x, double y, uint32_t state) _ghost_note->show(); /* calculate time in of a single grid units worth of beats, at the start of source */ - const Temporal::Beats length = get_draw_length_beats (_region->source_position() + timepos_t (snapped_beats)); + const Temporal::Beats length = get_draw_length_beats (_region->source_position() + timecnt_t (snapped_beats)); _ghost_note->note()->set_time (snapped_beats); _ghost_note->note()->set_length (length); diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 323dab196e..e4bbba4d00 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -279,9 +279,9 @@ public: * @param x a pixel coordinate relative to region start * @param ensure_snap ignore SnapOff and magnetic snap. * Required for inverting snap logic with modifier keys and snap delta calculation. - * @return the snapped timepos_t coordinate relative to region start + * @return the snapped timecnt_t coordinate relative to region start */ - Temporal::timepos_t snap_pixel_to_time (double x, bool ensure_snap = false); + Temporal::timecnt_t snap_pixel_to_time (double x, bool ensure_snap = false); void goto_previous_note (bool add_to_selection); void goto_next_note (bool add_to_selection); diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc index 143d49f019..f863c0a62e 100644 --- a/gtk2_ardour/region_view.cc +++ b/gtk2_ardour/region_view.cc @@ -1160,8 +1160,8 @@ RegionView::move_contents (timecnt_t const & distance) * Used when inverting snap mode logic with key modifiers, or snap distance calculation. * @return Snapped time offset from this region's position. */ -timepos_t -RegionView::snap_region_time_to_region_time (timepos_t const & x, bool ensure_snap) const +timecnt_t +RegionView::snap_region_time_to_region_time (timecnt_t const & x, bool ensure_snap) const { PublicEditor& editor = trackview.editor(); /* x is region relative, convert it to global absolute time */ diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h index 5c5aad5cfc..47c43de3b8 100644 --- a/gtk2_ardour/region_view.h +++ b/gtk2_ardour/region_view.h @@ -148,7 +148,7 @@ public: } }; - Temporal::timepos_t snap_region_time_to_region_time (Temporal::timepos_t const &, bool ensure_snap = false) const; + Temporal::timecnt_t snap_region_time_to_region_time (Temporal::timecnt_t const &, bool ensure_snap = false) const; void update_visibility ();