X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_drag.cc;h=c889921db774b7ed5ac9f29edd9c1859d2f4e0c1;hb=cd17e05e3a22614387050736c89a4727c4da0d61;hp=f8e810232d1f0a0f53ffa451f78aa4ce4bad3ff2;hpb=3409f591dbd7247a664f6a3b3eada930811132a3;p=ardour.git diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index f8e810232d..c889921db7 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -54,6 +54,7 @@ #include "debug.h" #include "editor_cursors.h" #include "mouse_cursors.h" +#include "verbose_cursor.h" using namespace std; using namespace ARDOUR; @@ -65,14 +66,13 @@ using namespace ArdourCanvas; using Gtkmm2ext::Keyboard; -double const ControlPointDrag::_zero_gain_fraction = gain_to_slider_position (dB_to_coefficient (0.0)); +double ControlPointDrag::_zero_gain_fraction = -1.0; DragManager::DragManager (Editor* e) : _editor (e) , _ending (false) , _current_pointer_frame (0) { - } DragManager::~DragManager () @@ -85,16 +85,18 @@ void DragManager::abort () { _ending = true; - + for (list::const_iterator i = _drags.begin(); i != _drags.end(); ++i) { (*i)->abort (); delete *i; } + if (!_drags.empty ()) { + _editor->set_follow_playhead (_old_follow_playhead, false); + } + _drags.clear (); - _editor->set_follow_playhead (_old_follow_playhead, false); - _ending = false; } @@ -119,9 +121,9 @@ DragManager::start_grab (GdkEvent* e, Gdk::Cursor* c) /* Prevent follow playhead during the drag to be nice to the user */ _old_follow_playhead = _editor->follow_playhead (); _editor->set_follow_playhead (false); - + _current_pointer_frame = _editor->event_frame (e, &_current_pointer_x, &_current_pointer_y); - + for (list::const_iterator i = _drags.begin(); i != _drags.end(); ++i) { (*i)->start_grab (e, c); } @@ -134,7 +136,7 @@ bool DragManager::end_grab (GdkEvent* e) { _ending = true; - + bool r = false; for (list::iterator i = _drags.begin(); i != _drags.end(); ++i) { bool const t = (*i)->end_grab (e); @@ -149,7 +151,7 @@ DragManager::end_grab (GdkEvent* e) _ending = false; _editor->set_follow_playhead (_old_follow_playhead, false); - + return r; } @@ -159,13 +161,13 @@ DragManager::motion_handler (GdkEvent* e, bool from_autoscroll) bool r = false; _current_pointer_frame = _editor->event_frame (e, &_current_pointer_x, &_current_pointer_y); - + for (list::iterator i = _drags.begin(); i != _drags.end(); ++i) { bool const t = (*i)->motion_handler (e, from_autoscroll); if (t) { r = true; } - + } return r; @@ -182,7 +184,7 @@ DragManager::have_item (ArdourCanvas::Item* i) const return j != _drags.end (); } -Drag::Drag (Editor* e, ArdourCanvas::Item* i) +Drag::Drag (Editor* e, ArdourCanvas::Item* i) : _editor (e) , _item (i) , _pointer_frame_offset (0) @@ -273,7 +275,7 @@ Drag::end_grab (GdkEvent* event) finished (event, _move_threshold_passed); - _editor->hide_verbose_canvas_cursor(); + _editor->verbose_cursor()->hide (); return _move_threshold_passed; } @@ -316,7 +318,7 @@ Drag::motion_handler (GdkEvent* event, bool from_autoscroll) if (!from_autoscroll && !_move_threshold_passed) { - bool const xp = (::llabs (_drags->current_pointer_frame () - _grab_frame) >= threshold.first); + bool const xp = (::llabs (_drags->current_pointer_frame () - _raw_grab_frame) >= threshold.first); bool const yp = (::fabs ((_drags->current_pointer_y () - _grab_y)) >= threshold.second); _move_threshold_passed = ((xp && x_movement_matters()) || (yp && y_movement_matters())); @@ -334,7 +336,7 @@ Drag::motion_handler (GdkEvent* event, bool from_autoscroll) _last_pointer_x = _drags->current_pointer_x (); _last_pointer_y = _drags->current_pointer_y (); _last_pointer_frame = adjusted_current_frame (event); - + return true; } } @@ -352,9 +354,46 @@ Drag::abort () aborted (_move_threshold_passed); _editor->stop_canvas_autoscroll (); - _editor->hide_verbose_canvas_cursor (); + _editor->verbose_cursor()->hide (); } +void +Drag::show_verbose_cursor_time (framepos_t frame) +{ + _editor->verbose_cursor()->set_time ( + frame, + _drags->current_pointer_x() + 10 - _editor->horizontal_position(), + _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value() + _editor->canvas_timebars_vsize + ); + + _editor->verbose_cursor()->show (); +} + +void +Drag::show_verbose_cursor_duration (framepos_t start, framepos_t end, double xoffset) +{ + _editor->verbose_cursor()->show (xoffset); + + _editor->verbose_cursor()->set_duration ( + start, end, + _drags->current_pointer_x() + 10 - _editor->horizontal_position(), + _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value() + _editor->canvas_timebars_vsize + ); +} + +void +Drag::show_verbose_cursor_text (string const & text) +{ + _editor->verbose_cursor()->show (); + + _editor->verbose_cursor()->set ( + text, + _drags->current_pointer_x() + 10 - _editor->horizontal_position(), + _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value() + _editor->canvas_timebars_vsize + ); +} + + struct EditorOrderTimeAxisViewSorter { bool operator() (TimeAxisView* a, TimeAxisView* b) { RouteTimeAxisView* ra = dynamic_cast (a); @@ -377,7 +416,7 @@ RegionDrag::RegionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, listhidden()) { - + _time_axis_views.push_back (*i); TimeAxisView::Children children_list = (*i)->get_child_list (); @@ -389,11 +428,11 @@ RegionDrag::RegionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list::const_iterator i = v.begin(); i != v.end(); ++i) { _views.push_back (DraggingView (*i, this)); } - + RegionView::RegionViewGoingAway.connect (death_connection, invalidator (*this), ui_bind (&RegionDrag::region_going_away, this, _1), gui_context()); } @@ -423,7 +462,7 @@ RegionDrag::find_time_axis_view (TimeAxisView* t) const if (i == N) { return -1; } - + return i; } @@ -441,7 +480,7 @@ RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) { Drag::start_grab (event, cursor); - _editor->show_verbose_time_cursor (_last_frame_position, 10); + show_verbose_cursor_time (_last_frame_position); pair const tv = _editor->trackview_by_y_position (_drags->current_pointer_y ()); _last_pointer_time_axis_view = find_time_axis_view (tv.first); @@ -459,19 +498,19 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r framepos_t sync_frame; framecnt_t sync_offset; int32_t sync_dir; - + sync_offset = _primary->region()->sync_offset (sync_dir); - + /* we don't handle a sync point that lies before zero. */ if (sync_dir >= 0 || (sync_dir < 0 && *pending_region_position >= sync_offset)) { - + sync_frame = *pending_region_position + (sync_dir*sync_offset); - + _editor->snap_to_with_modifier (sync_frame, event); - + *pending_region_position = _primary->region()->adjust_to_sync (sync_frame); - + } else { *pending_region_position = _last_frame_position; } @@ -487,13 +526,13 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r if ((*pending_region_position != _last_frame_position) && x_move_allowed) { - /* x movement since last time */ + /* x movement since last time (in pixels) */ dx = (static_cast (*pending_region_position) - _last_frame_position) / _editor->frames_per_unit; /* total x movement */ framecnt_t total_dx = *pending_region_position; if (regions_came_from_canvas()) { - total_dx = total_dx - grab_frame () + _pointer_frame_offset; + total_dx = total_dx - grab_frame (); } /* check that no regions have gone off the start of the session */ @@ -526,7 +565,7 @@ RegionMotionDrag::y_movement_allowed (int delta_track, layer_t delta_layer) cons /* not a track, or the wrong type */ return false; } - + int const l = i->layer + delta_layer; if (delta_track == 0 && (l < 0 || l >= int (to->view()->layers()))) { /* Off the top or bottom layer; note that we only refuse if the track hasn't changed. @@ -551,7 +590,7 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move) /* Bail early if we're not over a track */ RouteTimeAxisView* rtv = dynamic_cast (tv.first); if (!rtv || !rtv->is_track()) { - _editor->hide_verbose_canvas_cursor (); + _editor->verbose_cursor()->hide (); return; } @@ -597,39 +636,39 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move) /* here we are calculating the y distance from the top of the first track view to the top of the region area of the track view that we're working on */ - + /* this x value is just a dummy value so that we have something to pass to i2w () */ - + double ix1 = 0; - + /* distance from the top of this track view to the region area of our track view is always 1 */ - + double iy1 = 1; - + /* convert to world coordinates, ie distance from the top of the ruler section */ - + rv->get_canvas_frame()->i2w (ix1, iy1); - + /* compensate for the ruler section and the vertical scrollbar position */ iy1 += _editor->get_trackview_group_vertical_offset (); - + // hide any dependent views - + rv->get_time_axis_view().hide_dependent_views (*rv); - + /* reparent to a non scrolling group so that we can keep the region selection above all time axis views. reparenting means we have to move the rv as the two parent groups have different coordinates. */ - + rv->get_canvas_group()->property_y() = iy1 - 1; rv->get_canvas_group()->reparent (*(_editor->_region_motion_group)); - + rv->fake_set_opaque (true); } @@ -687,13 +726,13 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move) } /* foreach region */ _total_x_delta += x_delta; - + if (first_move) { _editor->cursor_group->raise_to_top(); } if (x_delta != 0 && !_brushing) { - _editor->show_verbose_time_cursor (_last_frame_position, 10); + show_verbose_cursor_time (_last_frame_position); } _last_pointer_time_axis_view += delta_time_axis_view; @@ -710,20 +749,20 @@ RegionMoveDrag::motion (GdkEvent* event, bool first_move) list new_regionviews; for (list::const_iterator i = _views.begin(); i != _views.end(); ++i) { - + RegionView* rv = i->view; AudioRegionView* arv = dynamic_cast(rv); MidiRegionView* mrv = dynamic_cast(rv); const boost::shared_ptr original = rv->region(); boost::shared_ptr region_copy = RegionFactory::create (original, true); - region_copy->set_position (original->position(), this); - + region_copy->set_position (original->position()); + RegionView* nrv; if (arv) { boost::shared_ptr audioregion_copy = boost::dynamic_pointer_cast(region_copy); - + nrv = new AudioRegionView (*arv, audioregion_copy); } else if (mrv) { boost::shared_ptr midiregion_copy @@ -732,29 +771,29 @@ RegionMoveDrag::motion (GdkEvent* event, bool first_move) } else { continue; } - + nrv->get_canvas_group()->show (); new_regionviews.push_back (DraggingView (nrv, this)); - + /* swap _primary to the copy */ - + if (rv == _primary) { _primary = nrv; } - + /* ..and deselect the one we copied */ - + rv->set_selected (false); } - + if (!new_regionviews.empty()) { - + /* reflect the fact that we are dragging the copies */ - + _views = new_regionviews; - + swap_grab (new_regionviews.front().view->get_canvas_group (), 0, event ? event->motion.time : 0); - + /* sync the canvas to what we think is its current state without it, the canvas seems to @@ -792,23 +831,23 @@ RegionMoveDrag::finished (GdkEvent *, bool movement_occurred) framecnt_t const drag_delta = _primary->region()->position() - _last_frame_position; _editor->update_canvas_now (); - + if (_copy) { - + finished_copy ( changed_position, changed_tracks, drag_delta ); - + } else { - + finished_no_copy ( changed_position, changed_tracks, drag_delta ); - + } } @@ -831,9 +870,9 @@ RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed } if (_x_constrained) { - _editor->begin_reversible_command (_("fixed time region copy")); + _editor->begin_reversible_command (Operations::fixed_time_region_copy); } else { - _editor->begin_reversible_command (_("region copy")); + _editor->begin_reversible_command (Operations::region_copy); } /* insert the regions into their new playlists */ @@ -854,13 +893,13 @@ RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed RegionView* new_view = insert_region_into_playlist ( i->view->region(), dynamic_cast (_time_axis_views[i->time_axis_view]), i->layer, where, modified_playlists ); - + if (new_view == 0) { continue; } new_views.push_back (new_view); - + /* we don't need the copied RegionView any more */ views_to_delete.push_back (i->view); } @@ -873,8 +912,8 @@ RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed delete *i; } - /* If we've created new regions either by copying or moving - to a new track, we want to replace the old selection with the new ones + /* If we've created new regions either by copying or moving + to a new track, we want to replace the old selection with the new ones */ if (new_views.size() > 0) { @@ -958,7 +997,7 @@ RegionMoveDrag::finished_no_copy ( remove_region_from_playlist (rv->region(), i->initial_playlist, modified_playlists); } else { - + rv->region()->clear_changes (); /* @@ -974,12 +1013,12 @@ RegionMoveDrag::finished_no_copy ( /* just change the model */ boost::shared_ptr playlist = dest_rtv->playlist(); - + if (dest_rtv->view()->layer_display() == Stacked) { rv->region()->set_layer (dest_layer); rv->region()->set_pending_explicit_relayer (true); } - + /* freeze playlist to avoid lots of relayering in the case of a multi-region drag */ pair r = frozen_playlists.insert (playlist); @@ -991,19 +1030,19 @@ RegionMoveDrag::finished_no_copy ( /* this movement may result in a crossfade being modified, so we need to get undo data from the playlist as well as the region. */ - + r = modified_playlists.insert (playlist); if (r.second) { playlist->clear_changes (); } - rv->region()->set_position (where, (void*) this); + rv->region()->set_position (where); _editor->session()->add_command (new StatefulDiffCommand (rv->region())); } if (changed_tracks) { - + /* OK, this is where it gets tricky. If the playlist was being used by >1 tracks, and the region was selected in all of them, then removing it from a playlist will have removed all trace of it from _views (i.e. there were N regions selected, we removed 1, @@ -1021,7 +1060,7 @@ RegionMoveDrag::finished_no_copy ( we can just iterate. */ - + if (_views.empty()) { break; } else { @@ -1033,8 +1072,8 @@ RegionMoveDrag::finished_no_copy ( } } - /* If we've created new regions either by copying or moving - to a new track, we want to replace the old selection with the new ones + /* If we've created new regions either by copying or moving + to a new track, we want to replace the old selection with the new ones */ if (new_views.size() > 0) { @@ -1072,7 +1111,7 @@ RegionMoveDrag::remove_region_from_playlist ( playlist->remove_region (region); } - + /** Insert a region into a playlist, handling the recovery of the resulting new RegionView, and * clearing the playlist's diff history first if necessary. @@ -1081,7 +1120,7 @@ RegionMoveDrag::remove_region_from_playlist ( * @param dest_layer Destination layer. * @param where Destination position. * @param modified_playlists The playlist will be added to this if it is not there already; used to ensure - * that clear_changes () is only called once per playlist. + * that clear_changes () is only called once per playlist. * @return New RegionView, or 0 if no insert was performed. */ RegionView * @@ -1102,7 +1141,7 @@ RegionMoveDrag::insert_region_into_playlist ( _new_region_view = 0; sigc::connection c = dest_rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &RegionMoveDrag::collect_new_region_view)); - /* clear history for the playlist we are about to insert to, provided we haven't already done so */ + /* clear history for the playlist we are about to insert to, provided we haven't already done so */ pair r = modified_playlists.insert (dest_playlist); if (r.second) { dest_playlist->clear_changes (); @@ -1185,7 +1224,7 @@ RegionMoveDrag::RegionMoveDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, _copy (c) { DEBUG_TRACE (DEBUG::Drags, "New RegionMoveDrag\n"); - + double speed = 1; RouteTimeAxisView* rtv = dynamic_cast (&_primary->get_time_axis_view ()); if (rtv && rtv->is_track()) { @@ -1205,7 +1244,7 @@ RegionInsertDrag::RegionInsertDrag (Editor* e, boost::shared_ptr r, Rout : RegionMotionDrag (e, 0, 0, list (), false) { DEBUG_TRACE (DEBUG::Drags, "New RegionInsertDrag\n"); - + assert ((boost::dynamic_pointer_cast (r) && dynamic_cast (v)) || (boost::dynamic_pointer_cast (r) && dynamic_cast (v))); @@ -1270,11 +1309,6 @@ RegionSpliceDrag::motion (GdkEvent* event, bool) pair const tvp = _editor->trackview_by_y_position (_drags->current_pointer_y ()); RouteTimeAxisView* tv = dynamic_cast (tvp.first); - layer_t layer = tvp.second; - - if (tv && tv->layer_display() == Overlaid) { - layer = 0; - } /* The region motion is only processed if the pointer is over an audio track. @@ -1284,7 +1318,7 @@ RegionSpliceDrag::motion (GdkEvent* event, bool) /* To make sure we hide the verbose canvas cursor when the mouse is not held over and audiotrack. */ - _editor->hide_verbose_canvas_cursor (); + _editor->verbose_cursor()->hide (); return; } @@ -1353,7 +1387,7 @@ RegionCreateDrag::RegionCreateDrag (Editor* e, ArdourCanvas::Item* i, TimeAxisVi _view (dynamic_cast (v)) { DEBUG_TRACE (DEBUG::Drags, "New RegionCreateDrag\n"); - + assert (_view); } @@ -1367,12 +1401,18 @@ RegionCreateDrag::motion (GdkEvent* event, bool first_move) if (_region) { framepos_t const f = adjusted_current_frame (event); if (f < grab_frame()) { - _region->set_position (f, this); + _region->set_position (f); } - - /* again, don't use a zero-length region (see above) */ - framecnt_t const len = abs (f - grab_frame ()); - _region->set_length (len < 1 ? 1 : len, this); + + /* Don't use a zero-length region, and subtract 1 frame from the snapped length + so that if this region is duplicated, its duplicate starts on + a snap point rather than 1 frame after a snap point. Otherwise things get + a bit confusing as if a region starts 1 frame after a snap point, one cannot + place snapped notes at the start of the region. + */ + + framecnt_t const len = abs (f - grab_frame () - 1); + _region->set_length (len < 1 ? 1 : len); } } } @@ -1570,16 +1610,16 @@ TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor*) switch (_operation) { case StartTrim: - _editor->show_verbose_time_cursor (region_start, 10); + show_verbose_cursor_time (region_start); for (list::iterator i = _views.begin(); i != _views.end(); ++i) { i->view->trim_front_starting (); } break; case EndTrim: - _editor->show_verbose_time_cursor (region_end, 10); + show_verbose_cursor_time (region_end); break; case ContentsTrim: - _editor->show_verbose_time_cursor (pf, 10); + show_verbose_cursor_time (pf); break; } @@ -1671,7 +1711,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move) } framecnt_t frame_delta = 0; - + bool left_direction = false; if (last_pointer_frame() > adjusted_current_frame(event)) { left_direction = true; @@ -1692,13 +1732,13 @@ TrimDrag::motion (GdkEvent* event, bool first_move) switch (_operation) { case StartTrim: - _editor->show_verbose_time_cursor ((framepos_t) (rv->region()->position() / speed), 10); + show_verbose_cursor_time ((framepos_t) (rv->region()->position() / speed)); break; case EndTrim: - _editor->show_verbose_time_cursor ((framepos_t) (rv->region()->last_frame() / speed), 10); + show_verbose_cursor_time ((framepos_t) (rv->region()->last_frame() / speed)); break; case ContentsTrim: - _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10); + show_verbose_cursor_time (adjusted_current_frame (event)); break; } } @@ -1719,7 +1759,7 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred) i->view->trim_front_ending (); } } - + if (!_editor->selection->selected (_primary)) { _primary->thaw_after_trim (); } else { @@ -1761,7 +1801,7 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred) if (_operation == StartTrim) { i->view->trim_front_ending (); } - + i->view->region()->resume_property_changes (); } } @@ -1775,7 +1815,7 @@ TrimDrag::aborted (bool movement_occurred) */ finished (0, true); - + if (movement_occurred) { _editor->undo (); } @@ -1814,7 +1854,7 @@ MeterMarkerDrag::MeterMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c) _copy (c) { DEBUG_TRACE (DEBUG::Drags, "New MeterMarkerDrag\n"); - + _marker = reinterpret_cast (_item->get_data ("marker")); assert (_marker); } @@ -1851,7 +1891,7 @@ MeterMarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) Drag::start_grab (event, cursor); - _editor->show_verbose_time_cursor (adjusted_current_frame(event), 10); + show_verbose_cursor_time (adjusted_current_frame(event)); } void @@ -1866,8 +1906,8 @@ MeterMarkerDrag::motion (GdkEvent* event, bool) framepos_t const pf = adjusted_current_frame (event); _marker->set_position (pf); - - _editor->show_verbose_time_cursor (pf, 10); + + show_verbose_cursor_time (pf); } void @@ -1916,7 +1956,7 @@ TempoMarkerDrag::TempoMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c) _copy (c) { DEBUG_TRACE (DEBUG::Drags, "New TempoMarkerDrag\n"); - + _marker = reinterpret_cast (_item->get_data ("marker")); assert (_marker); } @@ -1946,21 +1986,21 @@ TempoMarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) Drag::start_grab (event, cursor); - _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10); + show_verbose_cursor_time (adjusted_current_frame (event)); } void TempoMarkerDrag::setup_pointer_frame_offset () { _pointer_frame_offset = raw_grab_frame() - _marker->tempo().frame(); -} +} void TempoMarkerDrag::motion (GdkEvent* event, bool) { framepos_t const pf = adjusted_current_frame (event); _marker->set_position (pf); - _editor->show_verbose_time_cursor (pf, 10); + show_verbose_cursor_time (pf); } void @@ -2019,7 +2059,7 @@ void CursorDrag::fake_locate (framepos_t t) { _editor->playhead_cursor->set_position (t); - + Session* s = _editor->session (); if (s->timecode_transmission_suspended ()) { framepos_t const f = _editor->playhead_cursor->current_frame; @@ -2027,7 +2067,7 @@ CursorDrag::fake_locate (framepos_t t) s->send_full_time_code (f); } - _editor->show_verbose_time_cursor (t, 10); + show_verbose_cursor_time (t); _editor->UpdateAllTransportClocks (t); } @@ -2036,45 +2076,76 @@ CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c) { Drag::start_grab (event, c); + _grab_zoom = _editor->frames_per_unit; + framepos_t where = _editor->event_frame (event, 0, 0); _editor->snap_to_with_modifier (where, event); _editor->_dragging_playhead = true; - + Session* s = _editor->session (); - + if (s) { if (_was_rolling && _stop) { s->request_stop (); } - + if (s->is_auditioning()) { s->cancel_audition (); } - + s->request_suspend_timecode_transmission (); while (!s->timecode_transmission_suspended ()) { /* twiddle our thumbs */ } } - + fake_locate (where); } void CursorDrag::motion (GdkEvent* event, bool) { - framepos_t const adjusted_frame = adjusted_current_frame (event); + if (_drags->current_pointer_y() != last_pointer_y()) { - if (adjusted_frame == last_pointer_frame()) { - return; + /* zoom when we move the pointer up and down */ + + /* y range to operate over (pixels) */ + double const y_range = 512; + /* we will multiply the grab zoom by a factor between scale_range and scale_range^-1 */ + double const scale_range = 4; + /* dead zone around the grab point in which to do no zooming (pixels) */ + double const dead_zone = 100; + + /* current dy */ + double dy = _drags->current_pointer_y() - grab_y(); + + if (dy < -dead_zone || dy > dead_zone) { + /* we are outside the dead zone; remove it from our calculation */ + if (dy < 0) { + dy += dead_zone; + } else { + dy -= dead_zone; + } + + /* get a number from -1 to 1 as dy ranges from -y_range to y_range */ + double udy = max (min (dy / y_range, 1.0), -1.0); + + /* and zoom, using playhead focus temporarily */ + Editing::ZoomFocus const zf = _editor->get_zoom_focus (); + _editor->set_zoom_focus (Editing::ZoomFocusPlayhead); + _editor->temporal_zoom (_grab_zoom * pow (scale_range, -udy)); + _editor->set_zoom_focus (zf); + } } - fake_locate (adjusted_frame); - + framepos_t const adjusted_frame = adjusted_current_frame (event); + if (adjusted_frame != last_pointer_frame()) { + fake_locate (adjusted_frame); #ifdef GTKOSX - _editor->update_canvas_now (); + _editor->update_canvas_now (); #endif + } } void @@ -2103,7 +2174,7 @@ CursorDrag::aborted (bool) _editor->session()->request_resume_timecode_transmission (); _editor->_dragging_playhead = false; } - + _editor->playhead_cursor->set_position (adjusted_frame (grab_frame (), 0, false)); } @@ -2121,8 +2192,8 @@ FadeInDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) AudioRegionView* arv = dynamic_cast (_primary); boost::shared_ptr const r = arv->audio_region (); - _editor->show_verbose_duration_cursor (r->position(), r->position() + r->fade_in()->back()->when, 10); - + show_verbose_cursor_duration (r->position(), r->position() + r->fade_in()->back()->when, 32); + arv->show_fade_line((framepos_t) r->fade_in()->back()->when); } @@ -2163,7 +2234,7 @@ FadeInDrag::motion (GdkEvent* event, bool) tmp->show_fade_line((framecnt_t) fade_length); } - _editor->show_verbose_duration_cursor (region->position(), region->position() + fade_length, 10); + show_verbose_cursor_duration (region->position(), region->position() + fade_length, 32); } void @@ -2240,8 +2311,8 @@ FadeOutDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) AudioRegionView* arv = dynamic_cast (_primary); boost::shared_ptr r = arv->audio_region (); - _editor->show_verbose_duration_cursor (r->last_frame() - r->fade_out()->back()->when, r->last_frame(), 10); - + show_verbose_cursor_duration (r->last_frame() - r->fade_out()->back()->when, r->last_frame()); + arv->show_fade_line(r->length() - r->fade_out()->back()->when); } @@ -2251,7 +2322,7 @@ FadeOutDrag::setup_pointer_frame_offset () AudioRegionView* arv = dynamic_cast (_primary); boost::shared_ptr r = arv->audio_region (); _pointer_frame_offset = raw_grab_frame() - (r->length() - (framecnt_t) r->fade_out()->back()->when + r->position()); -} +} void FadeOutDrag::motion (GdkEvent* event, bool) @@ -2284,7 +2355,7 @@ FadeOutDrag::motion (GdkEvent* event, bool) tmp->show_fade_line(region->length() - fade_length); } - _editor->show_verbose_duration_cursor (region->last_frame() - fade_length, region->last_frame(), 10); + show_verbose_cursor_duration (region->last_frame() - fade_length, region->last_frame()); } void @@ -2353,7 +2424,7 @@ MarkerDrag::MarkerDrag (Editor* e, ArdourCanvas::Item* i) : Drag (e, i) { DEBUG_TRACE (DEBUG::Drags, "New MarkerDrag\n"); - + _marker = reinterpret_cast (_item->get_data ("marker")); assert (_marker); @@ -2384,9 +2455,9 @@ MarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) // _line->raise_to_top(); if (is_start) { - _editor->show_verbose_time_cursor (location->start(), 10); + show_verbose_cursor_time (location->start()); } else { - _editor->show_verbose_time_cursor (location->end(), 10); + show_verbose_cursor_time (location->end()); } Selection::Operation op = ArdourKeyboard::selection_type (event->button.state); @@ -2465,10 +2536,6 @@ MarkerDrag::motion (GdkEvent* event, bool) framepos_t next = newframe; - if (newframe == last_pointer_frame()) { - return; - } - if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) { move_both = true; } @@ -2594,7 +2661,7 @@ MarkerDrag::motion (GdkEvent* event, bool) assert (!_copied_locations.empty()); - _editor->show_verbose_time_cursor (newframe, 10); + show_verbose_cursor_time (newframe); #ifdef GTKOSX _editor->update_canvas_now (); @@ -2679,8 +2746,12 @@ ControlPointDrag::ControlPointDrag (Editor* e, ArdourCanvas::Item* i) _cumulative_x_drag (0), _cumulative_y_drag (0) { + if (_zero_gain_fraction < 0.0) { + _zero_gain_fraction = gain_to_slider_position_with_max (dB_to_coefficient (0.0), Config->get_max_gain()); + } + DEBUG_TRACE (DEBUG::Drags, "New ControlPointDrag\n"); - + _point = reinterpret_cast (_item->get_data ("control_point")); assert (_point); } @@ -2700,10 +2771,10 @@ ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) _point->line().start_drag_single (_point, _fixed_grab_x, fraction); - _editor->set_verbose_canvas_cursor (_point->line().get_verbose_cursor_string (fraction), - event->button.x + 10, event->button.y + 10); + _editor->verbose_cursor()->set (_point->line().get_verbose_cursor_string (fraction), + event->button.x + 10, event->button.y + 10); - _editor->show_verbose_canvas_cursor (); + _editor->verbose_cursor()->show (); } void @@ -2746,7 +2817,7 @@ ControlPointDrag::motion (GdkEvent* event, bool) cy = min ((double) _point->line().height(), cy); framepos_t cx_frames = _editor->unit_to_frame (cx); - + if (!_x_constrained) { _editor->snap_to_with_modifier (cx_frames, event); } @@ -2759,7 +2830,7 @@ ControlPointDrag::motion (GdkEvent* event, bool) _point->line().drag_motion (_editor->frame_to_unit (cx_frames), fraction, false, push); - _editor->set_verbose_canvas_cursor_text (_point->line().get_verbose_cursor_string (fraction)); + _editor->verbose_cursor()->set_text (_point->line().get_verbose_cursor_string (fraction)); } void @@ -2776,7 +2847,7 @@ ControlPointDrag::finished (GdkEvent* event, bool movement_occurred) } else { motion (event, false); } - + _point->line().end_drag (); _editor->session()->commit_reversible_command (); } @@ -2828,7 +2899,7 @@ LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) uint32_t before; uint32_t after; - + if (!_line->control_points_adjacent (frame_within_region, before, after)) { /* no adjacent points */ return; @@ -2845,10 +2916,10 @@ LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) _line->start_drag_line (before, after, fraction); - _editor->set_verbose_canvas_cursor (_line->get_verbose_cursor_string (fraction), - event->button.x + 10, event->button.y + 10); + _editor->verbose_cursor()->set (_line->get_verbose_cursor_string (fraction), + event->button.x + 10, event->button.y + 10); - _editor->show_verbose_canvas_cursor (); + _editor->verbose_cursor()->show (); } void @@ -2880,7 +2951,7 @@ LineDrag::motion (GdkEvent* event, bool) /* we are ignoring x position for this drag, so we can just pass in anything */ _line->drag_motion (0, fraction, true, push); - _editor->set_verbose_canvas_cursor_text (_line->get_verbose_cursor_string (fraction)); + _editor->verbose_cursor()->set_text (_line->get_verbose_cursor_string (fraction)); } void @@ -2909,7 +2980,7 @@ void FeatureLineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) { Drag::start_grab (event); - + _line = reinterpret_cast (_item); assert (_line); @@ -2922,9 +2993,9 @@ FeatureLineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) /* store grab start in parent frame */ _region_view_grab_x = cx; - + _before = *(float*) _item->get_data ("position"); - + _arv = reinterpret_cast (_item->get_data ("regionview")); _max_x = _editor->frame_to_pixel(_arv->get_duration()); @@ -2934,34 +3005,34 @@ void FeatureLineDrag::motion (GdkEvent*, bool) { double dx = _drags->current_pointer_x() - last_pointer_x(); - + double cx = _region_view_grab_x + _cumulative_x_drag + dx; - + _cumulative_x_drag += dx; - + /* Clamp the min and max extent of the drag to keep it within the region view bounds */ - + if (cx > _max_x){ cx = _max_x; } else if(cx < 0){ cx = 0; } - + ArdourCanvas::Points points; - + double x1 = 0, x2 = 0, y1 = 0, y2 = 0; _line->get_bounds(x1, y2, x2, y2); - + points.push_back(Gnome::Art::Point(cx, 2.0)); // first x-coord needs to be a non-normal value points.push_back(Gnome::Art::Point(cx, y2 - y1)); _line->property_points() = points; - + float *pos = new float; *pos = cx; - + _line->set_data ("position", pos); _before = cx; @@ -2990,7 +3061,7 @@ void RubberbandSelectDrag::start_grab (GdkEvent* event, Gdk::Cursor *) { Drag::start_grab (event); - _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10); + show_verbose_cursor_time (adjusted_current_frame (event)); } void @@ -3040,7 +3111,7 @@ RubberbandSelectDrag::motion (GdkEvent* event, bool) _editor->rubberband_rect->show(); _editor->rubberband_rect->raise_to_top(); - _editor->show_verbose_time_cursor (pf, 10); + show_verbose_cursor_time (pf); } } @@ -3102,7 +3173,7 @@ TimeFXDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) { Drag::start_grab (event, cursor); - _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10); + show_verbose_cursor_time (adjusted_current_frame (event)); } void @@ -3116,7 +3187,7 @@ TimeFXDrag::motion (GdkEvent* event, bool) rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf); } - _editor->show_verbose_time_cursor (pf, 10); + show_verbose_cursor_time (pf); } void @@ -3144,8 +3215,6 @@ TimeFXDrag::finished (GdkEvent* /*event*/, bool movement_occurred) } #endif - _editor->begin_reversible_command (_("timestretch")); - // XXX how do timeFX on multiple regions ? RegionSelection rs; @@ -3245,9 +3314,9 @@ SelectionDrag::start_grab (GdkEvent* event, Gdk::Cursor*) } if (_operation == SelectionMove) { - _editor->show_verbose_time_cursor (_editor->selection->time[_editor->clicked_selection].start, 10); + show_verbose_cursor_time (_editor->selection->time[_editor->clicked_selection].start); } else { - _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10); + show_verbose_cursor_time (adjusted_current_frame (event)); } _original_pointer_time_axis = _editor->trackview_by_y_position (_drags->current_pointer_y ()).first->order (); @@ -3283,7 +3352,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move) if (pending_time_axis.first == 0) { return; } - + framepos_t const pending_position = adjusted_current_frame (event); /* only alter selection if things have changed */ @@ -3328,7 +3397,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move) //_editor->selection->set (_editor->clicked_axisview); _editor->set_selected_track_as_side_effect (Selection::Set); } - + _editor->clicked_selection = _editor->selection->set (start, end); } } @@ -3343,7 +3412,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move) /* deselect any tracks that this drag no longer includes, being careful to only deselect tracks that we selected in the first place. */ - + int min_order = min (_original_pointer_time_axis, pending_time_axis.first->order()); int max_order = max (_original_pointer_time_axis, pending_time_axis.first->order()); @@ -3352,7 +3421,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move) list::iterator tmp = i; ++tmp; - + if ((*i)->order() < min_order || (*i)->order() > max_order) { _editor->selection->remove (*i); _added_time_axes.remove (*i); @@ -3413,9 +3482,9 @@ SelectionDrag::motion (GdkEvent* event, bool first_move) } if (_operation == SelectionMove) { - _editor->show_verbose_time_cursor(start, 10); + show_verbose_cursor_time(start); } else { - _editor->show_verbose_time_cursor(pending_position, 10); + show_verbose_cursor_time(pending_position); } } @@ -3447,7 +3516,7 @@ SelectionDrag::finished (GdkEvent* event, bool movement_occurred) if (_editor->clicked_axisview && !_editor->selection->selected (_editor->clicked_axisview)) { _editor->selection->set (_editor->clicked_axisview); } - + if (s && s->get_play_range () && s->transport_rolling()) { s->request_stop (false, false); } @@ -3469,8 +3538,8 @@ RangeMarkerBarDrag::RangeMarkerBarDrag (Editor* e, ArdourCanvas::Item* i, Operat _copy (false) { DEBUG_TRACE (DEBUG::Drags, "New RangeMarkerBarDrag\n"); - - _drag_rect = new ArdourCanvas::SimpleRect (*_editor->time_line_group, 0.0, 0.0, 0.0, + + _drag_rect = new ArdourCanvas::SimpleRect (*_editor->time_line_group, 0.0, 0.0, 0.0, physical_screen_height (_editor->get_window())); _drag_rect->hide (); @@ -3507,7 +3576,7 @@ RangeMarkerBarDrag::start_grab (GdkEvent* event, Gdk::Cursor *) Drag::start_grab (event, cursor); - _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10); + show_verbose_cursor_time (adjusted_current_frame (event)); } void @@ -3538,7 +3607,7 @@ RangeMarkerBarDrag::motion (GdkEvent* event, bool first_move) if (_operation == CreateRangeMarker || _operation == CreateTransportMarker || _operation == CreateCDMarker) { framepos_t grab = grab_frame (); _editor->snap_to (grab); - + if (pf < grab_frame()) { start = pf; end = grab; @@ -3579,7 +3648,7 @@ RangeMarkerBarDrag::motion (GdkEvent* event, bool first_move) update_item (_editor->temp_location); } - _editor->show_verbose_time_cursor (pf, 10); + show_verbose_cursor_time (pf); } @@ -3612,7 +3681,7 @@ RangeMarkerBarDrag::finished (GdkEvent* event, bool movement_occurred) newloc = new Location ( *_editor->session(), _editor->temp_location->start(), _editor->temp_location->end(), rangename, (Location::Flags) flags ); - + _editor->session()->locations()->add (newloc, true); XMLNode &after = _editor->session()->locations()->get_state(); _editor->session()->add_command(new MementoCommand(*(_editor->session()->locations()), &before, &after)); @@ -3696,8 +3765,8 @@ MouseZoomDrag::start_grab (GdkEvent* event, Gdk::Cursor *) Drag::start_grab (event, _editor->cursors()->zoom_in); _zoom_out = false; } - - _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10); + + show_verbose_cursor_time (adjusted_current_frame (event)); } void @@ -3729,7 +3798,7 @@ MouseZoomDrag::motion (GdkEvent* event, bool first_move) _editor->reposition_zoom_rect(start, end); - _editor->show_verbose_time_cursor (pf, 10); + show_verbose_cursor_time (pf); } } @@ -3808,9 +3877,14 @@ NoteDrag::total_dx () const /* primary note time */ frameoffset_t const n = _region->beats_to_frames (_primary->note()->time ()); - + /* new time of the primary note relative to the region position */ - frameoffset_t const st = n + dx; + frameoffset_t st = n + dx; + + /* prevent the note being dragged earlier than the region's position */ + if (st < 0) { + st = 0; + } /* snap and return corresponding delta */ return _region->snap_frame_to_frame (st) - n; @@ -3835,11 +3909,11 @@ NoteDrag::total_dy () const } /* more positive value = higher pitch and higher y-axis position on track, - which is the inverse of the X-centric geometric universe + which is the inverse of the X-centric geometric universe */ - return -ndy; -} + return -ndy; +} void NoteDrag::motion (GdkEvent *, bool) @@ -3863,8 +3937,8 @@ NoteDrag::motion (GdkEvent *, bool) char buf[12]; snprintf (buf, sizeof (buf), "%s (%d)", Evoral::midi_note_name (_primary->note()->note() + note_delta).c_str(), (int) floor (_primary->note()->note() + note_delta)); - - _editor->show_verbose_canvas_cursor_with (buf); + + show_verbose_cursor_text (buf); } } @@ -3909,7 +3983,7 @@ AutomationRangeDrag::AutomationRangeDrag (Editor* editor, ArdourCanvas::Item* it , _nothing_to_drag (false) { DEBUG_TRACE (DEBUG::Drags, "New AutomationRangeDrag\n"); - + _atav = reinterpret_cast (_item->get_data ("trackview")); assert (_atav); @@ -3967,13 +4041,13 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) i->points.push_back (i->line->nth (j)); } } - + } else { for (list::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i) { framecnt_t const half = (i->start + i->end) / 2; - + /* find the line that this audio range starts in */ list::iterator j = _lines.begin(); while (j != _lines.end() && (j->range.first > i->start || j->range.second < i->start)) { @@ -3982,7 +4056,7 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) if (j != _lines.end()) { boost::shared_ptr the_list = j->line->the_list (); - + /* j is the line that this audio range starts in; fade into it; 64 samples length plucked out of thin air. */ @@ -4002,7 +4076,7 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) } /* same thing for the end */ - + j = _lines.begin(); while (j != _lines.end() && (j->range.first > i->end || j->range.second < i->end)) { ++j; @@ -4010,11 +4084,11 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) if (j != _lines.end()) { boost::shared_ptr the_list = j->line->the_list (); - + /* j is the line that this audio range starts in; fade out of it; 64 samples length plucked out of thin air. */ - + framepos_t b = i->end - 64; if (b < half) { b = half; @@ -4022,7 +4096,7 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) double const p = j->line->time_converter().from (b - j->line->time_converter().origin_b ()); double const q = j->line->time_converter().from (i->end - j->line->time_converter().origin_b ()); - + the_list->add (p, the_list->eval (p)); j->line->add_always_in_view (p); the_list->add (q, the_list->eval (q)); @@ -4090,7 +4164,7 @@ AutomationRangeDrag::finished (GdkEvent* event, bool) if (_nothing_to_drag) { return; } - + motion (event, false); for (list::iterator i = _lines.begin(); i != _lines.end(); ++i) { i->line->end_drag (); @@ -4136,7 +4210,7 @@ PatchChangeDrag::motion (GdkEvent* ev, bool) boost::shared_ptr r = _region_view->region (); f = max (f, r->position ()); f = min (f, r->last_frame ()); - + framecnt_t const dxf = f - grab_frame(); double const dxu = _editor->frame_to_unit (dxf); _patch_change->move (dxu - _cumulative_dx, 0); @@ -4151,11 +4225,11 @@ PatchChangeDrag::finished (GdkEvent* ev, bool movement_occurred) } boost::shared_ptr r (_region_view->region ()); - + framepos_t f = adjusted_current_frame (ev); f = max (f, r->position ()); f = min (f, r->last_frame ()); - + _region_view->move_patch_change ( *_patch_change, _region_view->frames_to_beats (f - r->position() - r->start())