mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
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.
This commit is contained in:
parent
0504db2a67
commit
63c78ebced
6 changed files with 22 additions and 22 deletions
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<samplepos_t>(0, _region->region_relative_position (start).samples()));
|
||||
const double x1 = editor.sample_to_pixel (max<samplepos_t>(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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue