X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_mouse.cc;h=b3343c42c33fd8dc79dd312aac96b9b3d04c0309;hb=3a3780249ad4c4e98da317fd18a40890c0cf78b9;hp=430195fc2367773cd57751b641e78e2af83b45f4;hpb=91c9fc2533ba0c3708d545c120ad5353be995aff;p=ardour.git diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 430195fc23..b3343c42c3 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -75,21 +75,21 @@ Editor::mouse_frame (nframes64_t& where, bool& in_track_canvas) const int x, y; double wx, wy; Gdk::ModifierType mask; - Glib::RefPtr canvas_window = const_cast(this)->track_canvas.get_window(); + Glib::RefPtr canvas_window = const_cast(this)->track_canvas->get_window(); Glib::RefPtr pointer_window; pointer_window = canvas_window->get_pointer (x, y, mask); - if (pointer_window == track_canvas.get_bin_window()) { + if (pointer_window == track_canvas->get_bin_window()) { - track_canvas.window_to_world (x, y, wx, wy); + track_canvas->window_to_world (x, y, wx, wy); in_track_canvas = true; } else { in_track_canvas = false; - if (pointer_window == time_canvas.get_bin_window()) { - time_canvas.window_to_world (x, y, wx, wy); + if (pointer_window == time_canvas->get_bin_window()) { + time_canvas->window_to_world (x, y, wx, wy); } else { return false; } @@ -127,18 +127,18 @@ Editor::event_frame (GdkEvent* event, double* pcx, double* pcy) const case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: - track_canvas.w2c(event->button.x, event->button.y, *pcx, *pcy); + track_canvas->w2c(event->button.x, event->button.y, *pcx, *pcy); break; case GDK_MOTION_NOTIFY: - track_canvas.w2c(event->motion.x, event->motion.y, *pcx, *pcy); + track_canvas->w2c(event->motion.x, event->motion.y, *pcx, *pcy); break; case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: - track_canvas.w2c(event->crossing.x, event->crossing.y, *pcx, *pcy); + track_canvas->w2c(event->crossing.x, event->crossing.y, *pcx, *pcy); break; case GDK_KEY_PRESS: case GDK_KEY_RELEASE: - // track_canvas.w2c(event->key.x, event->key.y, *pcx, *pcy); + // track_canvas->w2c(event->key.x, event->key.y, *pcx, *pcy); break; default: warning << string_compose (_("Editor::event_frame() used on unhandled event type %1"), event->type) << endmsg; @@ -245,7 +245,7 @@ Editor::set_canvas_cursor () } if (is_drawable()) { - track_canvas.get_window()->set_cursor(*current_canvas_cursor); + track_canvas->get_window()->set_cursor(*current_canvas_cursor); } } @@ -463,7 +463,7 @@ const static double ZERO_GAIN_FRACTION = gain_to_slider_position(dB_to_coefficie bool Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { - track_canvas.grab_focus(); + track_canvas->grab_focus(); if (session && session->actively_recording()) { return true; @@ -750,7 +750,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp scrub_reverse_distance = 0; last_scrub_x = event->button.x; scrubbing_direction = 0; - track_canvas.get_window()->set_cursor (*transparent_cursor); + track_canvas->get_window()->set_cursor (*transparent_cursor); /* rest handled in motion & release */ break; @@ -1102,7 +1102,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT case MouseAudition: _scrubbing = false; - track_canvas.get_window()->set_cursor (*current_canvas_cursor); + track_canvas->get_window()->set_cursor (*current_canvas_cursor); if (scrubbing_direction == 0) { /* no drag, just a click */ switch (item_type) { @@ -1198,7 +1198,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ fraction = 1.0 - (cp->get_y() / cp->line.height()); if (is_drawable() && !_scrubbing) { - track_canvas.get_window()->set_cursor (*fader_cursor); + track_canvas->get_window()->set_cursor (*fader_cursor); } last_item_entered_n++; @@ -1229,7 +1229,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ show_verbose_canvas_cursor (); if (is_drawable()) { - track_canvas.get_window()->set_cursor (*fader_cursor); + track_canvas->get_window()->set_cursor (*fader_cursor); } } break; @@ -1240,7 +1240,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ if (line) line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EnteredGainLine.get(); if (is_drawable()) { - track_canvas.get_window()->set_cursor (*fader_cursor); + track_canvas->get_window()->set_cursor (*fader_cursor); } } break; @@ -1255,14 +1255,14 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EnteredAutomationLine.get(); } if (is_drawable()) { - track_canvas.get_window()->set_cursor (*fader_cursor); + track_canvas->get_window()->set_cursor (*fader_cursor); } } break; case RegionViewNameHighlight: if (is_drawable() && mouse_mode == MouseObject) { - track_canvas.get_window()->set_cursor (*trimmer_cursor); + track_canvas->get_window()->set_cursor (*trimmer_cursor); } break; @@ -1276,7 +1276,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ /* */ if (is_drawable()) { - track_canvas.get_window()->set_cursor (*trimmer_cursor); + track_canvas->get_window()->set_cursor (*trimmer_cursor); } break; @@ -1284,10 +1284,10 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ if (is_drawable()) { switch (_edit_point) { case EditAtMouse: - track_canvas.get_window()->set_cursor (*grabber_edit_point_cursor); + track_canvas->get_window()->set_cursor (*grabber_edit_point_cursor); break; default: - track_canvas.get_window()->set_cursor (*grabber_cursor); + track_canvas->get_window()->set_cursor (*grabber_cursor); break; } } @@ -1299,7 +1299,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ if (!reinterpret_cast (item->get_data ("regionview"))->name_active()) { if (mouse_mode == MouseObject && is_drawable()) { - track_canvas.get_window()->set_cursor (*trimmer_cursor); + track_canvas->get_window()->set_cursor (*trimmer_cursor); } } break; @@ -1320,7 +1320,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ break; } - track_canvas.get_window()->set_cursor (*cursor); + track_canvas->get_window()->set_cursor (*cursor); AutomationTimeAxisView* atv; if ((atv = static_cast(item->get_data ("trackview"))) != 0) { @@ -1337,7 +1337,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case MeterBarItem: case TempoBarItem: if (is_drawable()) { - time_canvas.get_window()->set_cursor (*timebar_cursor); + time_canvas->get_window()->set_cursor (*timebar_cursor); } break; @@ -1351,7 +1351,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case MeterMarkerItem: case TempoMarkerItem: if (is_drawable()) { - time_canvas.get_window()->set_cursor (*timebar_cursor); + time_canvas->get_window()->set_cursor (*timebar_cursor); } break; case FadeInHandleItem: @@ -1420,7 +1420,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ } if (is_drawable()) { - track_canvas.get_window()->set_cursor (*current_canvas_cursor); + track_canvas->get_window()->set_cursor (*current_canvas_cursor); } hide_verbose_canvas_cursor (); @@ -1437,7 +1437,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case MarkerViewHandleEndItem: /* */ if (is_drawable()) { - track_canvas.get_window()->set_cursor (*current_canvas_cursor); + track_canvas->get_window()->set_cursor (*current_canvas_cursor); } break; @@ -1452,7 +1452,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ line->property_fill_color_rgba() = al->get_line_color(); } if (is_drawable()) { - track_canvas.get_window()->set_cursor (*current_canvas_cursor); + track_canvas->get_window()->set_cursor (*current_canvas_cursor); } break; @@ -1460,7 +1460,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ /* see enter_handler() for notes */ if (!reinterpret_cast (item->get_data ("regionview"))->name_active()) { if (is_drawable() && mouse_mode == MouseObject) { - track_canvas.get_window()->set_cursor (*current_canvas_cursor); + track_canvas->get_window()->set_cursor (*current_canvas_cursor); } } break; @@ -1472,7 +1472,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case TempoBarItem: case MarkerBarItem: if (is_drawable()) { - time_canvas.get_window()->set_cursor (*timebar_cursor); + time_canvas->get_window()->set_cursor (*timebar_cursor); } break; @@ -1489,7 +1489,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case TempoMarkerItem: if (is_drawable()) { - time_canvas.get_window()->set_cursor (*timebar_cursor); + time_canvas->get_window()->set_cursor (*timebar_cursor); } break; @@ -1508,7 +1508,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case AutomationTrackItem: if (is_drawable()) { - track_canvas.get_window()->set_cursor (*current_canvas_cursor); + track_canvas->get_window()->set_cursor (*current_canvas_cursor); clear_entered_track = true; Glib::signal_idle().connect (mem_fun(*this, &Editor::left_automation_track)); } @@ -1531,6 +1531,85 @@ Editor::left_automation_track () return false; } +void +Editor::scrub () +{ + double delta; + + if (scrubbing_direction == 0) { + /* first move */ + session->request_locate (drag_info.current_pointer_frame, false); + session->request_transport_speed (0.1); + scrubbing_direction = 1; + + } else { + + if (last_scrub_x > drag_info.current_pointer_x) { + + /* pointer moved to the left */ + + if (scrubbing_direction > 0) { + + /* we reversed direction to go backwards */ + + scrub_reversals++; + scrub_reverse_distance += (int) (last_scrub_x - drag_info.current_pointer_x); + + } else { + + /* still moving to the left (backwards) */ + + scrub_reversals = 0; + scrub_reverse_distance = 0; + + delta = 0.01 * (last_scrub_x - drag_info.current_pointer_x); + session->request_transport_speed (session->transport_speed() - delta); + } + + } else { + /* pointer moved to the right */ + + if (scrubbing_direction < 0) { + /* we reversed direction to go forward */ + + scrub_reversals++; + scrub_reverse_distance += (int) (drag_info.current_pointer_x - last_scrub_x); + + } else { + /* still moving to the right */ + + scrub_reversals = 0; + scrub_reverse_distance = 0; + + delta = 0.01 * (drag_info.current_pointer_x - last_scrub_x); + session->request_transport_speed (session->transport_speed() + delta); + } + } + + /* if there have been more than 2 opposite motion moves detected, or one that moves + back more than 10 pixels, reverse direction + */ + + if (scrub_reversals >= 2 || scrub_reverse_distance > 10) { + + if (scrubbing_direction > 0) { + /* was forwards, go backwards */ + session->request_transport_speed (-0.1); + scrubbing_direction = -1; + } else { + /* was backwards, go forwards */ + session->request_transport_speed (0.1); + scrubbing_direction = 1; + } + + scrub_reverse_distance = 0; + scrub_reversals = 0; + } + } + + last_scrub_x = drag_info.current_pointer_x; +} + bool Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type, bool from_autoscroll) { @@ -1546,8 +1625,8 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item event might do, its a good tradeoff. */ - track_canvas.get_pointer (x, y); - } + track_canvas->get_pointer (x, y); + } if (current_stepping_trackview) { /* don't keep the persistent stepped trackview if the mouse moves */ @@ -1566,85 +1645,13 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item drag_info.current_pointer_frame = event_frame (event, &drag_info.current_pointer_x, &drag_info.current_pointer_y); + switch (mouse_mode) { case MouseAudition: if (_scrubbing) { - - double delta; - - if (scrubbing_direction == 0) { - /* first move */ - session->request_locate (drag_info.current_pointer_frame, false); - session->request_transport_speed (0.1); - scrubbing_direction = 1; - - } else { - - if (last_scrub_x > drag_info.current_pointer_x) { - - /* pointer moved to the left */ - - if (scrubbing_direction > 0) { - - /* we reversed direction to go backwards */ - - scrub_reversals++; - scrub_reverse_distance += (int) (last_scrub_x - drag_info.current_pointer_x); - - } else { - - /* still moving to the left (backwards) */ - - scrub_reversals = 0; - scrub_reverse_distance = 0; - - delta = 0.01 * (last_scrub_x - drag_info.current_pointer_x); - session->request_transport_speed (session->transport_speed() - delta); - } - - } else { - /* pointer moved to the right */ - - if (scrubbing_direction < 0) { - /* we reversed direction to go forward */ - - scrub_reversals++; - scrub_reverse_distance += (int) (drag_info.current_pointer_x - last_scrub_x); - - } else { - /* still moving to the right */ - - scrub_reversals = 0; - scrub_reverse_distance = 0; - - delta = 0.01 * (drag_info.current_pointer_x - last_scrub_x); - session->request_transport_speed (session->transport_speed() + delta); - } - } - - /* if there have been more than 2 opposite motion moves detected, or one that moves - back more than 10 pixels, reverse direction - */ - - if (scrub_reversals >= 2 || scrub_reverse_distance > 10) { - - if (scrubbing_direction > 0) { - /* was forwards, go backwards */ - session->request_transport_speed (-0.1); - scrubbing_direction = -1; - } else { - /* was backwards, go forwards */ - session->request_transport_speed (0.1); - scrubbing_direction = 1; - } - - scrub_reverse_distance = 0; - scrub_reversals = 0; - } - } - - last_scrub_x = drag_info.current_pointer_x; + scrub (); } + break; default: break; @@ -1700,7 +1707,7 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item if (drag_info.item && (event->motion.state & Gdk::BUTTON1_MASK || (event->motion.state & Gdk::BUTTON2_MASK))) { if (!from_autoscroll) { - maybe_autoscroll (event); + maybe_autoscroll (&event->motion); } (this->*(drag_info.motion_callback)) (item, event); goto handled; @@ -1719,7 +1726,7 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item if (drag_info.item && (event->motion.state & GDK_BUTTON1_MASK || (event->motion.state & GDK_BUTTON2_MASK))) { if (!from_autoscroll) { - maybe_autoscroll (event); + maybe_autoscroll (&event->motion); } (this->*(drag_info.motion_callback)) (item, event); goto handled; @@ -1740,6 +1747,48 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item return false; } +void +Editor::break_drag () +{ + stop_canvas_autoscroll (); + hide_verbose_canvas_cursor (); + + if (drag_info.item) { + drag_info.item->ungrab (0); + + /* put it back where it came from */ + + double cxw, cyw; + cxw = 0; + cyw = 0; + drag_info.item->i2w (cxw, cyw); + drag_info.item->move (drag_info.original_x - cxw, drag_info.original_y - cyw); + } + + finalize_drag (); +} + +void +Editor::finalize_drag () +{ + drag_info.item = 0; + drag_info.copy = false; + drag_info.motion_callback = 0; + drag_info.finished_callback = 0; + drag_info.dest_trackview = 0; + drag_info.source_trackview = 0; + drag_info.last_frame_position = 0; + drag_info.grab_frame = 0; + drag_info.last_pointer_frame = 0; + drag_info.current_pointer_frame = 0; + drag_info.brushing = false; + + if (drag_info.copied_location) { + delete drag_info.copied_location; + drag_info.copied_location = 0; + } +} + void Editor::start_grab (GdkEvent* event, Gdk::Cursor *cursor) { @@ -1784,6 +1833,10 @@ Editor::start_grab (GdkEvent* event, Gdk::Cursor *cursor) drag_info.brushing = false; drag_info.copied_location = 0; + drag_info.original_x = 0; + drag_info.original_y = 0; + drag_info.item->i2w (drag_info.original_x, drag_info.original_y); + drag_info.item->grab (Gdk::POINTER_MOTION_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK, *cursor, event->button.time); @@ -1842,21 +1895,7 @@ Editor::end_grab (ArdourCanvas::Item* item, GdkEvent* event) hide_verbose_canvas_cursor(); - drag_info.item = 0; - drag_info.copy = false; - drag_info.motion_callback = 0; - drag_info.finished_callback = 0; - drag_info.last_trackview = 0; - drag_info.last_frame_position = 0; - drag_info.grab_frame = 0; - drag_info.last_pointer_frame = 0; - drag_info.current_pointer_frame = 0; - drag_info.brushing = false; - - if (drag_info.copied_location) { - delete drag_info.copied_location; - drag_info.copied_location = 0; - } + finalize_drag (); return did_drag; } @@ -2342,8 +2381,8 @@ void Editor::marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { if (drag_info.first_move) { - marker_drag_motion_callback (item, event); - + /* just a click, do nothing but whatever selection occured */ + return; } _dragging_edit_point = false; @@ -2691,7 +2730,7 @@ Editor::start_control_point_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.grab_x = control_point->get_x(); drag_info.grab_y = control_point->get_y(); control_point->line.parent_group().i2w(drag_info.grab_x, drag_info.grab_y); - track_canvas.w2c(drag_info.grab_x, drag_info.grab_y, + track_canvas->w2c(drag_info.grab_x, drag_info.grab_y, drag_info.grab_x, drag_info.grab_y); drag_info.grab_frame = pixel_to_frame(drag_info.grab_x); @@ -2944,7 +2983,8 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; - drag_info.last_trackview = &clicked_regionview->get_time_axis_view(); + drag_info.source_trackview = &clicked_regionview->get_time_axis_view(); + drag_info.dest_trackview = drag_info.source_trackview; // we want a move threshold drag_info.want_move_threshold = true; @@ -2974,7 +3014,8 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) speed = atv->get_diskstream()->speed(); } - drag_info.last_trackview = &clicked_regionview->get_time_axis_view(); + drag_info.source_trackview = &clicked_regionview->get_time_axis_view(); + drag_info.dest_trackview = drag_info.source_trackview; drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; // we want a move threshold @@ -3009,7 +3050,8 @@ Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; - drag_info.last_trackview = &clicked_regionview->get_time_axis_view(); + drag_info.source_trackview = &clicked_regionview->get_time_axis_view(); + drag_info.dest_trackview = drag_info.source_trackview; // we want a move threshold drag_info.want_move_threshold = true; drag_info.brushing = true; @@ -3024,7 +3066,7 @@ Editor::possibly_copy_regions_during_grab (GdkEvent* event) drag_info.want_move_threshold = false; // don't copy again - /* duplicate the region(s) */ + /* duplicate the regionview(s) and region(s) */ vector new_regionviews; @@ -3032,7 +3074,7 @@ Editor::possibly_copy_regions_during_grab (GdkEvent* event) RegionView* rv; RegionView* nrv; AudioRegionView* arv; - + rv = (*i); @@ -3040,8 +3082,12 @@ Editor::possibly_copy_regions_during_grab (GdkEvent* event) /* XXX handle MIDI here */ continue; } + + const boost::shared_ptr original = arv->region(); + boost::shared_ptr region_copy = RegionFactory::create (original); + boost::shared_ptr ar = boost::dynamic_pointer_cast (region_copy); - nrv = new AudioRegionView (*arv); + nrv = new AudioRegionView (*arv, ar); nrv->get_canvas_group()->show (); new_regionviews.push_back (nrv); @@ -3051,10 +3097,16 @@ Editor::possibly_copy_regions_during_grab (GdkEvent* event) return; } - /* reset selection to new regionviews */ + /* reset selection to new regionviews. This will not set selection visual status for + these regionviews since they don't belong to a track, so do that by hand too. + */ selection->set (new_regionviews); + for (vector::iterator i = new_regionviews.begin(); i != new_regionviews.end(); ++i) { + (*i)->set_selected (true); + } + /* reset drag_info data to reflect the fact that we are dragging the copies */ drag_info.data = new_regionviews.front(); @@ -3178,7 +3230,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) return; } - original_pointer_order = drag_info.last_trackview->order; + original_pointer_order = drag_info.dest_trackview->order; /************************************************************ Y-Delta Computation @@ -3190,7 +3242,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) goto y_axis_done; } - if ((pointer_y_span = (drag_info.last_trackview->order - tv->order)) != 0) { + if ((pointer_y_span = (drag_info.dest_trackview->order - tv->order)) != 0) { int32_t children = 0, numtracks = 0; // XXX hard coding track limit, oh my, so very very bad @@ -3234,16 +3286,16 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) /* find the actual span according to the canvas */ canvas_pointer_y_span = pointer_y_span; - if (drag_info.last_trackview->order >= tv->order) { + if (drag_info.dest_trackview->order >= tv->order) { int32_t y; - for (y = tv->order; y < drag_info.last_trackview->order; y++) { + for (y = tv->order; y < drag_info.dest_trackview->order; y++) { if (height_list[y] == 0 ) { canvas_pointer_y_span--; } } } else { int32_t y; - for (y = drag_info.last_trackview->order;y <= tv->order; y++) { + for (y = drag_info.dest_trackview->order;y <= tv->order; y++) { if ( height_list[y] == 0 ) { canvas_pointer_y_span++; } @@ -3255,6 +3307,10 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) double ix1, ix2, iy1, iy2; int32_t n = 0; + if (rv2->region()->locked()) { + continue; + } + rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); rv2->get_canvas_group()->i2w (ix1, iy1); TimeAxisView* tvp2 = trackview_by_y_position (iy1); @@ -3326,13 +3382,13 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) } } - } else if (drag_info.last_trackview == tv) { + } else if (drag_info.dest_trackview == tv) { clamp_y_axis = true; } y_axis_done: if (!clamp_y_axis) { - drag_info.last_trackview = tv; + drag_info.dest_trackview = tv; } /************************************************************ @@ -3343,7 +3399,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) the region would be if we moved it by that much. */ - if (drag_info.move_threshold_passed) { + if ( drag_info.move_threshold_passed ) { if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { @@ -3382,8 +3438,21 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) } // printf ("3: pending_region_position= %lu %lu\n", pending_region_position, drag_info.last_frame_position ); - - if (pending_region_position != drag_info.last_frame_position && !drag_info.x_constrained) { + + bool x_move_allowed; + + if (Config->get_edit_mode() == Lock) { + if (drag_info.copy) { + x_move_allowed = !drag_info.x_constrained; + } else { + /* in locked edit mode, reverse the usual meaning of x_constrained */ + x_move_allowed = drag_info.x_constrained; + } + } else { + x_move_allowed = !drag_info.x_constrained; + } + + if ( pending_region_position != drag_info.last_frame_position && x_move_allowed ) { /* now compute the canvas unit distance we need to move the regionview to make it appear at the new location. @@ -3406,7 +3475,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) x_delta = 0; } - + /************************************************************* PREPARE TO MOVE ************************************************************/ @@ -3464,6 +3533,10 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) double ix1, ix2, iy1, iy2; int32_t temp_pointer_y_span = pointer_y_span; + if (rv->region()->locked()) { + continue; + } + /* get item BBox, which will be relative to parent. so we have to query on a child, then convert to world coordinates using the parent. @@ -3501,6 +3574,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) y_delta -= (*j); temp_pointer_y_span--; } + while (temp_pointer_y_span < 0) { y_delta += (*j); if (x != original_pointer_order) { @@ -3531,7 +3605,8 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) x++; } } - + + /* prevent the regionview from being moved to before the zero position on the canvas. */ @@ -3587,15 +3662,12 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) void Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { - nframes_t where; - RegionView* rv = reinterpret_cast (drag_info.data); - pair >::iterator,bool> insert_result; bool nocommit = true; - double speed; - RouteTimeAxisView* atv; - bool regionview_y_movement; - bool regionview_x_movement; vector copies; + RouteTimeAxisView* source_tv; + boost::shared_ptr ds; + boost::shared_ptr from_playlist; + vector new_selection; /* first_move is set to false if the regionview has been moved in the motion handler. @@ -3631,20 +3703,6 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event goto out; } - /* adjust for track speed */ - speed = 1.0; - - atv = dynamic_cast (drag_info.last_trackview); - if (atv && atv->get_diskstream()) { - speed = atv->get_diskstream()->speed(); - } - - regionview_x_movement = (drag_info.last_frame_position != (nframes_t) (rv->region()->position()/speed)); - regionview_y_movement = (drag_info.last_trackview != &rv->get_time_axis_view()); - - //printf ("last_frame: %s position is %lu %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed); - //printf ("last_rackview: %s \n", drag_info.last_trackview->name().c_str()); - char* op_string; if (drag_info.copy) { @@ -3663,71 +3721,110 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event begin_reversible_command (op_string); - if (regionview_y_movement) { - - /* moved to a different audio track. */ - - vector new_selection; - - for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) { + for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) { - RegionView* rv = (*i); + RegionView* rv = (*i); + double ix1, ix2, iy1, iy2; + rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); + rv->get_canvas_group()->i2w (ix1, iy1); + TimeAxisView* dest_tv = trackview_by_y_position (iy1); + AudioTimeAxisView* dest_atv = dynamic_cast(dest_tv); + double speed; + bool changed_tracks; + bool changed_position; + nframes_t where; + + if (rv->region()->locked()) { + ++i; + continue; + } - double ix1, ix2, iy1, iy2; - - rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); - rv->get_canvas_group()->i2w (ix1, iy1); - TimeAxisView* tvp2 = trackview_by_y_position (iy1); - AudioTimeAxisView* atv2 = dynamic_cast(tvp2); + /* adjust for track speed */ - boost::shared_ptr from_playlist = rv->region()->playlist(); - boost::shared_ptr to_playlist = atv2->playlist(); + speed = 1.0; + + if (dest_atv && dest_atv->get_diskstream()) { + speed = dest_atv->get_diskstream()->speed(); + } + + changed_position = (drag_info.last_frame_position != (nframes_t) (rv->region()->position()/speed)); + changed_tracks = (dest_tv != &rv->get_time_axis_view()); + if (changed_position && !drag_info.x_constrained) { where = (nframes_t) (unit_to_frame (ix1) * speed); - boost::shared_ptr new_region (RegionFactory::create (rv->region())); - - /* undo the previous hide_dependent_views so that xfades don't - disappear on copying regions - */ - - rv->get_time_axis_view().reveal_dependent_views (*rv); - - if (!drag_info.copy) { - - /* the region that used to be in the old playlist is not - moved to the new one - we make a copy of it. as a result, - any existing editor for the region should no longer be - visible. - */ - - rv->hide_region_editor(); - rv->fake_set_opaque (false); + } else { + where = rv->region()->position(); + } + + /* undo the previous hide_dependent_views so that xfades don't + disappear on copying regions + */ + + rv->get_time_axis_view().reveal_dependent_views (*rv); + + boost::shared_ptr new_region; - session->add_command (new MementoCommand(*from_playlist, &from_playlist->get_state(), 0)); - from_playlist->remove_region ((rv->region())); - session->add_command (new MementoCommand(*from_playlist, 0, &from_playlist->get_state())); + if (drag_info.copy) { + /* we already made a copy */ + new_region = rv->region(); + } else { + new_region = RegionFactory::create (rv->region()); + } - } else { + if (changed_tracks || drag_info.copy) { - /* the regionview we dragged around is a temporary copy, queue it for deletion */ - - copies.push_back (rv); - } + boost::shared_ptr to_playlist = dest_atv->playlist(); latest_regionviews.clear (); - - sigc::connection c = atv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); + + sigc::connection c = dest_atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); session->add_command (new MementoCommand(*to_playlist, &to_playlist->get_state(), 0)); to_playlist->add_region (new_region, where); session->add_command (new MementoCommand(*to_playlist, 0, &to_playlist->get_state())); c.disconnect (); if (!latest_regionviews.empty()) { - new_selection.insert (new_selection.end(), latest_regionviews.begin(), latest_regionviews.end()); + // XXX why just the first one ? we only expect one + dest_atv->reveal_dependent_views (*latest_regionviews.front()); + new_selection.push_back (latest_regionviews.front()); } + } else { + + /* just change the model */ + + rv->region()->set_position (where, (void*) this); + } + + if (changed_tracks && !drag_info.copy) { + + /* get the playlist where this drag started. we can't use rv->region()->playlist() + because we may have copied the region and it has not been attached to a playlist. + */ + + assert ((source_tv = dynamic_cast (&rv->get_time_axis_view()))); + assert ((ds = source_tv->get_diskstream())); + assert ((from_playlist = ds->playlist())); + + /* moved to a different audio track, without copying */ + + /* the region that used to be in the old playlist is not + moved to the new one - we use a copy of it. as a result, + any existing editor for the region should no longer be + visible. + */ + + rv->hide_region_editor(); + rv->fake_set_opaque (false); + + /* remove the region from the old playlist */ + + session->add_command (new MementoCommand(*from_playlist, &from_playlist->get_state(), 0)); + from_playlist->remove_region ((rv->region())); + session->add_command (new MementoCommand(*from_playlist, 0, &from_playlist->get_state())); + /* 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 the playlist will have removed all + was selected in all of them, then removing it from a playlist will have removed all trace of it from the selection (i.e. there were N regions selected, we removed 1, but since its the same playlist for N tracks, all N tracks updated themselves, removed the corresponding regionview, and the selection is now empty). @@ -3743,116 +3840,37 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event we can just iterate. */ - if (drag_info.copy) { - ++i; - } else { - if (selection->regions.empty()) { - break; - } else { - i = selection->regions.by_layer().begin(); - } + if (selection->regions.empty()) { + break; + } else { + i = selection->regions.by_layer().begin(); } - } - - selection->set (new_selection); - - } else { - /* motion within a single track */ - - list regions = selection->regions.by_layer(); - - if (drag_info.copy) { - selection->clear_regions(); + } else { + ++i; } - for (list::iterator i = regions.begin(); i != regions.end(); ++i) { - - rv = (*i); - - if (rv->region()->locked()) { - continue; - } - - - if (regionview_x_movement) { - double ownspeed = 1.0; - atv = dynamic_cast (&(rv->get_time_axis_view())); - - if (atv && atv->get_diskstream()) { - ownspeed = atv->get_diskstream()->speed(); - } - - /* base the new region position on the current position of the regionview.*/ - - double ix1, ix2, iy1, iy2; - - rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); - rv->get_canvas_group()->i2w (ix1, iy1); - where = (nframes_t) (unit_to_frame (ix1) * ownspeed); - - } else { - - where = rv->region()->position(); - } - - boost::shared_ptr to_playlist = rv->region()->playlist(); - - assert (to_playlist); - - /* add the undo */ - - session->add_command (new MementoCommand(*to_playlist, &to_playlist->get_state(), 0)); - - if (drag_info.copy) { - - boost::shared_ptr newregion; - boost::shared_ptr ar; - - if ((ar = boost::dynamic_pointer_cast(rv->region())) != 0) { - newregion = RegionFactory::create (ar); - } else { - /* XXX MIDI HERE drobilla */ - continue; - } - - /* add it */ - - latest_regionviews.clear (); - sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); - to_playlist->add_region (newregion, (nframes_t) (where * atv->get_diskstream()->speed())); - c.disconnect (); - - if (!latest_regionviews.empty()) { - // XXX why just the first one ? we only expect one - atv->reveal_dependent_views (*latest_regionviews.front()); - selection->add (latest_regionviews); - } - - /* if the original region was locked, we don't care for the new one */ - - newregion->set_locked (false); - - } else { - - /* just change the model */ - - rv->region()->set_position (where, (void*) this); - - } - - /* add the redo */ - - session->add_command (new MementoCommand(*to_playlist, 0, &to_playlist->get_state())); - - if (drag_info.copy) { - copies.push_back (rv); - } + if (drag_info.copy) { + copies.push_back (rv); } } - - out: + if (new_selection.empty()) { + if (drag_info.copy) { + /* the region(view)s that are selected and being dragged around + are copies and do not belong to any track. remove them + from the selection right here. + */ + selection->clear_regions(); + } + } else { + /* this will clear any existing selection that would have been + cleared in the other clause above + */ + selection->set (new_selection); + } + + out: if (!nocommit) { commit_reversible_command (); } @@ -3911,7 +3929,15 @@ Editor::show_verbose_time_cursor (nframes_t frame, double offset, double xpos, d return; } - switch (Profile->get_small_screen() ? ARDOUR_UI::instance()->primary_clock.mode () : ARDOUR_UI::instance()->secondary_clock.mode ()) { + AudioClock::Mode m; + + if (Profile->get_sae() || Profile->get_small_screen()) { + m = ARDOUR_UI::instance()->primary_clock.mode(); + } else { + m = ARDOUR_UI::instance()->secondary_clock.mode(); + } + + switch (m) { case AudioClock::BBT: session->bbt_time (frame, bbt); snprintf (buf, sizeof (buf), "%02" PRIu32 "|%02" PRIu32 "|%02" PRIu32, bbt.bars, bbt.beats, bbt.ticks); @@ -3963,7 +3989,15 @@ Editor::show_verbose_duration_cursor (nframes_t start, nframes_t end, double off return; } - switch (ARDOUR_UI::instance()->secondary_clock.mode ()) { + AudioClock::Mode m; + + if (Profile->get_sae() || Profile->get_small_screen()) { + m = ARDOUR_UI::instance()->primary_clock.mode (); + } else { + m = ARDOUR_UI::instance()->secondary_clock.mode (); + } + + switch (m) { case AudioClock::BBT: session->bbt_time (start, sbbt); session->bbt_time (end, ebbt); @@ -4018,6 +4052,7 @@ Editor::show_verbose_duration_cursor (nframes_t start, nframes_t end, double off else { set_verbose_canvas_cursor (buf, drag_info.current_pointer_x + offset, drag_info.current_pointer_y + offset); } + show_verbose_canvas_cursor (); } @@ -4091,7 +4126,8 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event) start_grab (event); - drag_info.last_trackview = clicked_trackview; + drag_info.source_trackview = clicked_trackview; + drag_info.dest_trackview = drag_info.source_trackview; drag_info.last_frame_position = latest_regionviews.front()->region()->position(); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; @@ -4277,7 +4313,7 @@ Editor::drag_selection (ArdourCanvas::Item* item, GdkEvent* event) } if (event->button.x >= horizontal_adjustment.get_value() + canvas_width) { - start_canvas_autoscroll (1); + start_canvas_autoscroll (1, 0); } if (start != end) { @@ -4852,7 +4888,7 @@ Editor::drag_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event) } if (event->button.x >= horizontal_adjustment.get_value() + canvas_width) { - start_canvas_autoscroll (1); + start_canvas_autoscroll (1, 0); } if (start != end) { @@ -5069,7 +5105,7 @@ Editor::drag_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event) return; } - if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()) && Config->get_rubberbanding_snaps_to_grid()) { if (drag_info.first_move) { snap_to (drag_info.grab_frame); }