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 */
|
/* 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 */
|
/* 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.
|
* coordinates relative to the region in order to draw it correctly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const timepos_t rrp1 (_region_view->region()->region_relative_position (_note[0]));
|
const timecnt_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 rrp2 (_region_view->region()->region_relative_position (_note[1]));
|
||||||
|
|
||||||
double const x0 = _editor->time_to_pixel (rrp1);
|
double const x0 = _editor->sample_to_pixel (rrp1.samples ());
|
||||||
double const x1 = _editor->time_to_pixel (rrp2);
|
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)));
|
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 ())));
|
_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));
|
_note[1] = timepos_t (max (Temporal::Beats(), aligned_beats));
|
||||||
|
|
||||||
const timepos_t rrp1 (_region_view->region()->region_relative_position (_note[0]));
|
const timecnt_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 rrp2 (_region_view->region()->region_relative_position (_note[1]));
|
||||||
|
|
||||||
double const x0 = _editor->time_to_pixel (rrp1);
|
double const x0 = _editor->sample_to_pixel (rrp1.samples());
|
||||||
double const x1 = _editor->time_to_pixel (rrp2);
|
double const x1 = _editor->sample_to_pixel (rrp2.samples());
|
||||||
_drag_rect->set_x0 (std::min(x0, x1));
|
_drag_rect->set_x0 (std::min(x0, x1));
|
||||||
_drag_rect->set_x1 (std::max(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
|
// Convert to local coordinates
|
||||||
const double y = midi_view()->y_position();
|
const double y = midi_view()->y_position();
|
||||||
const double x0 = editor.time_to_pixel (max (timepos_t(), _region->region_relative_position (start)));
|
const double x0 = editor.sample_to_pixel (max<samplepos_t>(0, _region->region_relative_position (start).samples()));
|
||||||
const double x1 = editor.time_to_pixel (max (timepos_t(), _region->region_relative_position (end)));
|
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 y0 = max(0.0, gy0 - y);
|
||||||
const double y1 = max(0.0, gy1 - 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.
|
* Used for inverting the snap logic with key modifiers and snap delta calculation.
|
||||||
* @return Snapped time relative to the region position.
|
* @return Snapped time relative to the region position.
|
||||||
*/
|
*/
|
||||||
timepos_t
|
timecnt_t
|
||||||
MidiRegionView::snap_pixel_to_time (double x, bool ensure_snap)
|
MidiRegionView::snap_pixel_to_time (double x, bool ensure_snap)
|
||||||
{
|
{
|
||||||
PublicEditor& editor (trackview.editor());
|
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.
|
/** @param x Pixel relative to the region position.
|
||||||
|
|
@ -2955,7 +2955,7 @@ MidiRegionView::snap_pixel_to_time (double x, bool ensure_snap)
|
||||||
double
|
double
|
||||||
MidiRegionView::snap_to_pixel(double x, bool ensure_snap)
|
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
|
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 */
|
/* Convert the new x position to a position within the source */
|
||||||
timepos_t current_time;
|
timecnt_t current_time;
|
||||||
if (with_snap) {
|
if (with_snap) {
|
||||||
current_time = snap_pixel_to_time (current_x, ensure_snap);
|
current_time = snap_pixel_to_time (current_x, ensure_snap);
|
||||||
} else {
|
} 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 */
|
/* and then to beats */
|
||||||
|
|
@ -4124,7 +4124,7 @@ MidiRegionView::update_ghost_note (double x, double y, uint32_t state)
|
||||||
_ghost_note->show();
|
_ghost_note->show();
|
||||||
|
|
||||||
/* calculate time in of a single grid units worth of beats, at the start of source */
|
/* 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_time (snapped_beats);
|
||||||
_ghost_note->note()->set_length (length);
|
_ghost_note->note()->set_length (length);
|
||||||
|
|
|
||||||
|
|
@ -279,9 +279,9 @@ public:
|
||||||
* @param x a pixel coordinate relative to region start
|
* @param x a pixel coordinate relative to region start
|
||||||
* @param ensure_snap ignore SnapOff and magnetic snap.
|
* @param ensure_snap ignore SnapOff and magnetic snap.
|
||||||
* Required for inverting snap logic with modifier keys and snap delta calculation.
|
* 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_previous_note (bool add_to_selection);
|
||||||
void goto_next_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.
|
* Used when inverting snap mode logic with key modifiers, or snap distance calculation.
|
||||||
* @return Snapped time offset from this region's position.
|
* @return Snapped time offset from this region's position.
|
||||||
*/
|
*/
|
||||||
timepos_t
|
timecnt_t
|
||||||
RegionView::snap_region_time_to_region_time (timepos_t const & x, bool ensure_snap) const
|
RegionView::snap_region_time_to_region_time (timecnt_t const & x, bool ensure_snap) const
|
||||||
{
|
{
|
||||||
PublicEditor& editor = trackview.editor();
|
PublicEditor& editor = trackview.editor();
|
||||||
/* x is region relative, convert it to global absolute time */
|
/* 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 ();
|
void update_visibility ();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue