X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_mouse.cc;h=1a03f66f2427935d32794bd4281fd5d4f0f7731e;hb=b1c48972f2914b49d45a7cef2b38a0a125bd731e;hp=35f410eb25590bcba6af10f67b4ff2fbd38be966;hpb=bb457bb960c5bd7ed538f9d31477293415739f68;p=ardour.git diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 35f410eb25..1a03f66f24 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -1,3 +1,4 @@ + /* Copyright (C) 2000-2001 Paul Davis @@ -27,6 +28,7 @@ #include #include +#include #include #include @@ -82,29 +84,25 @@ 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; + + if (!canvas_window) { + return false; + } pointer_window = canvas_window->get_pointer (x, y, mask); - if (pointer_window == track_canvas.get_bin_window()) { - - track_canvas.window_to_world (x, y, wx, wy); + if (pointer_window == track_canvas->get_bin_window()) { + wx = x; + wy = y; 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); - } else { return false; - } } - wx += horizontal_adjustment.get_value(); - wy += vertical_adjustment.get_value(); - GdkEvent event; event.type = GDK_BUTTON_RELEASE; event.button.x = wx; @@ -134,18 +132,24 @@ 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); + + *pcx = event->button.x; + *pcy = event->button.y; + _trackview_group->w2i(*pcx, *pcy); break; case GDK_MOTION_NOTIFY: - track_canvas.w2c(event->motion.x, event->motion.y, *pcx, *pcy); + + *pcx = event->motion.x; + *pcy = event->motion.y; + _trackview_group->w2i(*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; @@ -215,6 +219,57 @@ Editor::mouse_mode_toggled (MouseMode m) } } +Gdk::Cursor* +Editor::which_grabber_cursor () +{ + switch (_edit_point) { + case EditAtMouse: + return grabber_edit_point_cursor; + break; + default: + break; + } + return grabber_cursor; +} + +void +Editor::set_canvas_cursor () +{ + switch (mouse_mode) { + case MouseRange: + current_canvas_cursor = selector_cursor; + break; + + case MouseObject: + current_canvas_cursor = which_grabber_cursor(); + break; + + case MouseGain: + current_canvas_cursor = cross_hair_cursor; + break; + + case MouseZoom: + current_canvas_cursor = zoom_cursor; + break; + + case MouseTimeFX: + current_canvas_cursor = time_fx_cursor; // just use playhead + break; + + case MouseAudition: + current_canvas_cursor = speaker_cursor; + break; + + case MouseNote: + set_midi_edit_cursor (current_midi_edit_mode()); + break; + } + + if (is_drawable()) { + track_canvas->get_window()->set_cursor(*current_canvas_cursor); + } +} + void Editor::set_mouse_mode (MouseMode m, bool force) { @@ -266,36 +321,26 @@ Editor::set_mouse_mode (MouseMode m, bool force) switch (mouse_mode) { case MouseRange: mouse_select_button.set_active (true); - current_canvas_cursor = selector_cursor; break; case MouseObject: mouse_move_button.set_active (true); - if (Profile->get_sae()) { - current_canvas_cursor = timebar_cursor; - } else { - current_canvas_cursor = grabber_cursor; - } break; case MouseGain: mouse_gain_button.set_active (true); - current_canvas_cursor = cross_hair_cursor; break; case MouseZoom: mouse_zoom_button.set_active (true); - current_canvas_cursor = zoom_cursor; break; case MouseTimeFX: mouse_timefx_button.set_active (true); - current_canvas_cursor = time_fx_cursor; // just use playhead break; case MouseAudition: mouse_audition_button.set_active (true); - current_canvas_cursor = speaker_cursor; break; case MouseNote: @@ -304,16 +349,17 @@ Editor::set_mouse_mode (MouseMode m, bool force) break; } - if (mouse_mode == MouseNote) - midi_toolbar_frame.show(); - else - midi_toolbar_frame.hide(); - - ignore_mouse_mode_toggle = false; - - if (is_drawable()) { - track_canvas.get_window()->set_cursor(*current_canvas_cursor); + if (midi_tools_tearoff) { + if (mouse_mode == MouseNote) { + midi_tools_tearoff->show(); + } else { + midi_tools_tearoff->hide(); + } } + + ignore_mouse_mode_toggle = false; + + set_canvas_cursor (); } void @@ -375,6 +421,11 @@ Editor::midi_edit_mode_toggled (MidiEditMode m) set_midi_edit_mode (m); break; + case MidiEditResize: + if (midi_tool_resize_button.get_active()) + set_midi_edit_mode (m); + break; + case MidiEditErase: if (midi_tool_erase_button.get_active()) set_midi_edit_mode (m); @@ -414,6 +465,10 @@ Editor::set_midi_edit_mode (MidiEditMode m, bool force) midi_tool_select_button.set_active (true); break; + case MidiEditResize: + midi_tool_resize_button.set_active (true); + break; + case MidiEditErase: midi_tool_erase_button.set_active (true); break; @@ -424,7 +479,7 @@ Editor::set_midi_edit_mode (MidiEditMode m, bool force) set_midi_edit_cursor (current_midi_edit_mode()); if (is_drawable()) { - track_canvas.get_window()->set_cursor(*current_canvas_cursor); + track_canvas->get_window()->set_cursor(*current_canvas_cursor); } } @@ -440,6 +495,10 @@ Editor::set_midi_edit_cursor (MidiEditMode m) current_canvas_cursor = midi_select_cursor; break; + case MidiEditResize: + current_canvas_cursor = midi_resize_cursor; + break; + case MidiEditErase: current_canvas_cursor = midi_erase_cursor; break; @@ -462,7 +521,7 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it (mouse_mode != MouseTimeFX || item_type != RegionItem) && (mouse_mode != MouseRange)) || - (event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE || event->button.button > 3)) { + ((event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE) || event->button.button > 3)) { return; } @@ -542,7 +601,25 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it bool Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { - track_canvas.grab_focus(); + Glib::RefPtr canvas_window = const_cast(this)->track_canvas->get_window(); + + if (canvas_window) { + Glib::RefPtr pointer_window; + int x, y; + double wx, wy; + Gdk::ModifierType mask; + + pointer_window = canvas_window->get_pointer (x, y, mask); + + if (pointer_window == track_canvas->get_bin_window()) { + track_canvas->window_to_world (x, y, wx, wy); + allow_vertical_scroll = true; + } else { + allow_vertical_scroll = false; + } + } + + track_canvas->grab_focus(); if (session && session->actively_recording()) { return true; @@ -695,8 +772,8 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp case RegionViewName: /* rename happens on edit clicks */ - start_trim (clicked_regionview->get_name_highlight(), event); - return true; + start_trim (clicked_regionview->get_name_highlight(), event); + return true; break; case ControlPointItem: @@ -812,7 +889,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; @@ -903,7 +980,8 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp bool Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { - nframes_t where = event_frame (event, 0, 0); + nframes64_t where = event_frame (event, 0, 0); + AutomationTimeAxisView* atv = 0; /* no action if we're recording */ @@ -967,24 +1045,23 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT case FadeOutHandleItem: popup_fade_context_menu (1, event->button.time, item, item_type); break; - + case StreamItem: - popup_track_context_menu (1, event->button.time, where); + popup_track_context_menu (1, event->button.time, item_type, false, where); break; case RegionItem: case RegionViewNameHighlight: case RegionViewName: - popup_track_context_menu (1, event->button.time, where); + popup_track_context_menu (1, event->button.time, item_type, false, where); break; case SelectionItem: - popup_track_context_menu (1, event->button.time, where); + popup_track_context_menu (1, event->button.time, item_type, true, where); break; case AutomationTrackItem: - case CrossfadeViewItem: - popup_track_context_menu (1, event->button.time, where); + popup_track_context_menu (1, event->button.time, item_type, false, where); break; case MarkerBarItem: @@ -1007,6 +1084,10 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT case MeterMarkerItem: tm_marker_context_menu (&event->button, item); break; + + case CrossfadeViewItem: + popup_track_context_menu (1, event->button.time, item_type, false, where); + break; #ifdef WITH_CMT case ImageFrameItem: @@ -1116,14 +1197,14 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT case MouseObject: switch (item_type) { case AutomationTrackItem: - dynamic_cast(clicked_axisview)->add_automation_event - (item, - event, - where, - event->button.y); + atv = dynamic_cast(clicked_routeview); + if (atv) { + atv->add_automation_event (item, event, where, event->button.y); + } return true; + break; - + default: break; } @@ -1154,7 +1235,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) { @@ -1229,6 +1310,11 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ Marker * marker; double fraction; + if (last_item_entered != item) { + last_item_entered = item; + last_item_entered_n = 0; + } + switch (item_type) { case ControlPointItem: if (mouse_mode == MouseGain || mouse_mode == MouseObject) { @@ -1239,16 +1325,19 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ at_x = cp->get_x(); at_y = cp->get_y (); cp->item()->i2w (at_x, at_y); - at_x += 20.0; - at_y += 20.0; + at_x += 10.0; + at_y += 10.0; fraction = 1.0 - (cp->get_y() / cp->line().height()); - set_verbose_canvas_cursor (cp->line().get_verbose_cursor_string (fraction), at_x, at_y); - show_verbose_canvas_cursor (); - if (is_drawable() && !_scrubbing) { - track_canvas.get_window()->set_cursor (*fader_cursor); + track_canvas->get_window()->set_cursor (*fader_cursor); + } + + last_item_entered_n++; + set_verbose_canvas_cursor (cp->line().get_verbose_cursor_string (fraction), at_x, at_y); + if (last_item_entered_n < 10) { + show_verbose_canvas_cursor (); } } break; @@ -1259,7 +1348,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; @@ -1272,14 +1361,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; @@ -1294,13 +1383,20 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ #endif if (is_drawable()) { - track_canvas.get_window()->set_cursor (*trimmer_cursor); + track_canvas->get_window()->set_cursor (*trimmer_cursor); } break; case PlayheadCursorItem: if (is_drawable()) { - track_canvas.get_window()->set_cursor (*grabber_cursor); + switch (_edit_point) { + case EditAtMouse: + track_canvas->get_window()->set_cursor (*grabber_edit_point_cursor); + break; + default: + track_canvas->get_window()->set_cursor (*grabber_cursor); + break; + } } break; @@ -1310,7 +1406,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; @@ -1331,7 +1427,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) { @@ -1348,7 +1444,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); + track_canvas->get_window()->set_cursor (*timebar_cursor); } break; @@ -1362,7 +1458,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); + track_canvas->get_window()->set_cursor (*timebar_cursor); } break; case FadeInHandleItem: @@ -1423,7 +1519,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 (); @@ -1442,7 +1538,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ #endif if (is_drawable()) { - track_canvas.get_window()->set_cursor (*current_canvas_cursor); + track_canvas->get_window()->set_cursor (*current_canvas_cursor); } break; @@ -1455,7 +1551,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; @@ -1463,7 +1559,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; @@ -1475,7 +1571,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); + track_canvas->get_window()->set_cursor (*timebar_cursor); } break; @@ -1492,7 +1588,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case TempoMarkerItem: if (is_drawable()) { - time_canvas.get_window()->set_cursor (*timebar_cursor); + track_canvas->get_window()->set_cursor (*timebar_cursor); } break; @@ -1511,7 +1607,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)); } @@ -1534,6 +1630,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) { @@ -1548,10 +1723,10 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item where DISPLAY = :0.0, and given the cost of what the motion 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 */ current_stepping_trackview = 0; @@ -1569,85 +1744,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; @@ -1680,6 +1783,9 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item case PlayheadCursorItem: case MarkerItem: case ControlPointItem: + case RangeMarkerBarItem: + case TransportMarkerBarItem: + case CdMarkerBarItem: case TempoMarkerItem: case MeterMarkerItem: case RegionViewNameHighlight: @@ -1701,13 +1807,13 @@ 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_horizontally (&event->motion); } (this->*(drag_info.motion_callback)) (item, event); goto handled; } goto not_handled; - + break; default: break; } @@ -1721,7 +1827,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; @@ -1742,6 +1848,45 @@ 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; + range_marker_drag_rect->hide(); + drag_info.clear_copied_locations (); +} + void Editor::start_grab (GdkEvent* event, Gdk::Cursor *cursor) { @@ -1752,7 +1897,7 @@ Editor::start_grab (GdkEvent* event, Gdk::Cursor *cursor) } if (cursor == 0) { - cursor = grabber_cursor; + cursor = which_grabber_cursor (); } // if dragging with button2, the motion is x constrained, with Alt-button2 it is y constrained @@ -1784,7 +1929,11 @@ Editor::start_grab (GdkEvent* event, Gdk::Cursor *cursor) drag_info.want_move_threshold = false; drag_info.pointer_frame_offset = 0; drag_info.brushing = false; - drag_info.copied_location = 0; + drag_info.clear_copied_locations (); + + 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, @@ -1815,7 +1964,7 @@ Editor::swap_grab (ArdourCanvas::Item* new_item, Gdk::Cursor* cursor, uint32_t t drag_info.item = new_item; if (cursor == 0) { - cursor = grabber_cursor; + cursor = which_grabber_cursor (); } drag_info.item->grab (Gdk::POINTER_MOTION_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK, *cursor, time); @@ -1844,21 +1993,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; } @@ -1879,15 +2014,16 @@ Editor::start_fade_in_grab (ArdourCanvas::Item* item, GdkEvent* event) AudioRegionView* arv = static_cast(drag_info.data); - drag_info.pointer_frame_offset = drag_info.grab_frame - ((nframes_t) arv->audio_region()->fade_in()->back()->when + arv->region()->position()); + + drag_info.pointer_frame_offset = drag_info.grab_frame - ((nframes64_t) arv->audio_region()->fade_in()->back()->when + arv->region()->position()); } void Editor::fade_in_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { AudioRegionView* arv = static_cast(drag_info.data); - nframes_t pos; - nframes_t fade_length; + nframes64_t pos; + nframes64_t fade_length; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -1929,8 +2065,8 @@ void Editor::fade_in_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { AudioRegionView* arv = static_cast(drag_info.data); - nframes_t pos; - nframes_t fade_length; + nframes64_t pos; + nframes64_t fade_length; if (drag_info.first_move) return; @@ -1962,6 +2098,7 @@ Editor::fade_in_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* even XMLNode &before = alist->get_state(); tmp->audio_region()->set_fade_in_length (fade_length); + tmp->audio_region()->set_fade_in_active (true); XMLNode &after = alist->get_state(); session->add_command(new MementoCommand(*alist.get(), &before, &after)); @@ -1986,15 +2123,15 @@ Editor::start_fade_out_grab (ArdourCanvas::Item* item, GdkEvent* event) AudioRegionView* arv = static_cast(drag_info.data); - drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region()->length() - (nframes_t) arv->audio_region()->fade_out()->back()->when + arv->region()->position()); + drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region()->length() - (nframes64_t) arv->audio_region()->fade_out()->back()->when + arv->region()->position()); } void Editor::fade_out_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { AudioRegionView* arv = static_cast(drag_info.data); - nframes_t pos; - nframes_t fade_length; + nframes64_t pos; + nframes64_t fade_length; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2040,8 +2177,8 @@ Editor::fade_out_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* eve if (drag_info.first_move) return; AudioRegionView* arv = static_cast(drag_info.data); - nframes_t pos; - nframes_t fade_length; + nframes64_t pos; + nframes64_t fade_length; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2078,6 +2215,7 @@ Editor::fade_out_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* eve XMLNode &before = alist->get_state(); tmp->audio_region()->set_fade_out_length (fade_length); + tmp->audio_region()->set_fade_out_active (true); XMLNode &after = alist->get_state(); session->add_command(new MementoCommand(*alist.get(), &before, &after)); @@ -2123,7 +2261,7 @@ void Editor::cursor_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { Cursor* cursor = (Cursor *) drag_info.data; - nframes_t adjusted_frame; + nframes64_t adjusted_frame; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2141,11 +2279,14 @@ Editor::cursor_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) if (adjusted_frame == drag_info.last_pointer_frame) return; cursor->set_position (adjusted_frame); - - UpdateAllTransportClocks (cursor->current_frame); show_verbose_time_cursor (cursor->current_frame, 10); +#ifdef GTKOSX + track_canvas->update_now (); +#endif + UpdateAllTransportClocks (cursor->current_frame); + drag_info.last_pointer_frame = adjusted_frame; drag_info.first_move = false; } @@ -2176,13 +2317,13 @@ Editor::update_marker_drag_item (Location *location) marker_drag_line_points.front().set_x(x1); marker_drag_line_points.back().set_x(x1); marker_drag_line->property_points() = marker_drag_line_points; - } - else { + } else { range_marker_drag_rect->property_x1() = x1; range_marker_drag_rect->property_x2() = x2; } } + void Editor::start_marker_grab (ArdourCanvas::Item* item, GdkEvent* event) { @@ -2206,7 +2347,6 @@ Editor::start_marker_grab (ArdourCanvas::Item* item, GdkEvent* event) _dragging_edit_point = true; - drag_info.copied_location = new Location (*location); drag_info.pointer_frame_offset = drag_info.grab_frame - (is_start ? location->start() : location->end()); update_marker_drag_item (location); @@ -2216,7 +2356,7 @@ Editor::start_marker_grab (ArdourCanvas::Item* item, GdkEvent* event) // marker_drag_line->raise_to_top(); } else { range_marker_drag_rect->show(); - range_marker_drag_rect->raise_to_top(); + //range_marker_drag_rect->raise_to_top(); } if (is_start) { @@ -2232,35 +2372,74 @@ Editor::start_marker_grab (ArdourCanvas::Item* item, GdkEvent* event) selection->toggle (marker); break; case Selection::Set: - selection->set (marker); + if (!selection->selected (marker)) { + selection->set (marker); + } break; case Selection::Extend: - selection->add (marker); + { + Locations::LocationList ll; + list to_add; + nframes64_t s, e; + selection->markers.range (s, e); + s = min (marker->position(), s); + e = max (marker->position(), e); + s = min (s, e); + e = max (s, e); + if (e < max_frames) { + ++e; + } + session->locations()->find_all_between (s, e, ll, Location::Flags (0)); + for (Locations::LocationList::iterator i = ll.begin(); i != ll.end(); ++i) { + LocationMarkers* lm = find_location_markers (*i); + if (lm) { + if (lm->start) { + to_add.push_back (lm->start); + } + if (lm->end) { + to_add.push_back (lm->end); + } + } + } + if (!to_add.empty()) { + selection->add (to_add); + } break; + } case Selection::Add: selection->add (marker); break; } -} -void -Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) + /* set up copies for us to manipulate during the drag */ + + drag_info.clear_copied_locations (); + + for (MarkerSelection::iterator i = selection->markers.begin(); i != selection->markers.end(); ++i) { + Location *l = find_location_from_marker (*i, is_start); + drag_info.copied_locations.push_back (new Location (*l)); + } +} + +void +Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { - nframes_t f_delta; - Marker* marker = (Marker *) drag_info.data; - Location *real_location; - Location *copy_location; + nframes64_t f_delta = 0; + nframes64_t newframe; bool is_start; bool move_both = false; + Marker* dragged_marker = (Marker*) drag_info.data; + Marker* marker; + Location *real_location; + Location *copy_location; - nframes_t newframe; if (drag_info.pointer_frame_offset <= drag_info.current_pointer_frame) { newframe = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; } else { newframe = 0; } - nframes_t next = newframe; + nframes64_t next = newframe; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (newframe, 0, true); @@ -2270,102 +2449,197 @@ Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) return; } - /* call this to find out if its the start or end */ - - if ((real_location = find_location_from_marker (marker, is_start)) == 0) { - return; + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) { + move_both = true; } - if (real_location->locked()) { + MarkerSelection::iterator i; + list::iterator x; + + /* find the marker we're dragging, and compute the delta */ + + for (i = selection->markers.begin(), x = drag_info.copied_locations.begin(); + x != drag_info.copied_locations.end() && i != selection->markers.end(); + ++i, ++x) { + + copy_location = *x; + marker = *i; + + if (marker == dragged_marker) { + + if ((real_location = find_location_from_marker (marker, is_start)) == 0) { + /* que pasa ?? */ + return; + } + + if (real_location->is_mark()) { + f_delta = newframe - copy_location->start(); + } else { + + + switch (marker->type()) { + case Marker::Start: + case Marker::LoopStart: + case Marker::PunchIn: + f_delta = newframe - copy_location->start(); + break; + + case Marker::End: + case Marker::LoopEnd: + case Marker::PunchOut: + f_delta = newframe - copy_location->end(); + break; + default: + /* what kind of marker is this ? */ + return; + } + } + break; + } + } + + if (i == selection->markers.end()) { + /* hmm, impossible - we didn't find the dragged marker */ return; } - /* use the copy that we're "dragging" around */ - - copy_location = drag_info.copied_location; + /* now move them all */ - f_delta = copy_location->end() - copy_location->start(); - - if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) { - move_both = true; - } + for (i = selection->markers.begin(), x = drag_info.copied_locations.begin(); + x != drag_info.copied_locations.end() && i != selection->markers.end(); + ++i, ++x) { - if (copy_location->is_mark()) { - /* just move it */ + copy_location = *x; + marker = *i; - copy_location->set_start (newframe); + /* call this to find out if its the start or end */ + + if ((real_location = find_location_from_marker (marker, is_start)) == 0) { + continue; + } + + if (real_location->locked()) { + continue; + } - } else { + if (copy_location->is_mark()) { - if (is_start) { // start-of-range marker + /* just move it */ - if (move_both) { - copy_location->set_start (newframe); - copy_location->set_end (newframe + f_delta); - } else if (newframe < copy_location->end()) { - copy_location->set_start (newframe); - } else { - snap_to (next, 1, true); - copy_location->set_end (next); - copy_location->set_start (newframe); - } + copy_location->set_start (copy_location->start() + f_delta); + + } else { - } else { // end marker + nframes64_t new_start = copy_location->start() + f_delta; + nframes64_t new_end = copy_location->end() + f_delta; - if (move_both) { - copy_location->set_end (newframe); - copy_location->set_start (newframe - f_delta); - } else if (newframe > copy_location->start()) { - copy_location->set_end (newframe); + if (is_start) { // start-of-range marker + + if (move_both) { + copy_location->set_start (new_start); + copy_location->set_end (new_end); + } else if (new_start < copy_location->end()) { + copy_location->set_start (new_start); + } else { + snap_to (next, 1, true); + copy_location->set_end (next); + copy_location->set_start (newframe); + } + + } else { // end marker - } else if (newframe > 0) { - snap_to (next, -1, true); - copy_location->set_start (next); - copy_location->set_end (newframe); + if (move_both) { + copy_location->set_end (new_end); + copy_location->set_start (new_start); + } else if (new_end > copy_location->start()) { + copy_location->set_end (new_end); + } else if (newframe > 0) { + snap_to (next, -1, true); + copy_location->set_start (next); + copy_location->set_end (newframe); + } } } + update_marker_drag_item (copy_location); + + LocationMarkers* lm = find_location_markers (real_location); + + if (lm) { + lm->set_position (copy_location->start(), copy_location->end()); + } } drag_info.last_pointer_frame = drag_info.current_pointer_frame; drag_info.first_move = false; - update_marker_drag_item (copy_location); - - LocationMarkers* lm = find_location_markers (real_location); - lm->set_position (copy_location->start(), copy_location->end()); - edit_point_clock.set (copy_location->start()); + if (drag_info.copied_locations.empty()) { + abort(); + } + edit_point_clock.set (drag_info.copied_locations.front()->start()); show_verbose_time_cursor (newframe, 10); + +#ifdef GTKOSX + track_canvas->update_now (); +#endif + edit_point_clock.set (copy_location->start()); } 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 finish + off the selection process + */ + + Selection::Operation op = Keyboard::selection_type (event->button.state); + Marker* marker = (Marker *) drag_info.data; + + switch (op) { + case Selection::Set: + if (selection->selected (marker) && selection->markers.size() > 1) { + selection->set (marker); + } + break; + + case Selection::Toggle: + case Selection::Extend: + case Selection::Add: + break; + } + + return; } _dragging_edit_point = false; - Marker* marker = (Marker *) drag_info.data; - bool is_start; begin_reversible_command ( _("move marker") ); XMLNode &before = session->locations()->get_state(); - - Location * location = find_location_from_marker (marker, is_start); - - if (location) { - if (location->locked()) { - return; - } + MarkerSelection::iterator i; + list::iterator x; + bool is_start; - if (location->is_mark()) { - location->set_start (drag_info.copied_location->start()); - } else { - location->set (drag_info.copied_location->start(), drag_info.copied_location->end()); + for (i = selection->markers.begin(), x = drag_info.copied_locations.begin(); + x != drag_info.copied_locations.end() && i != selection->markers.end(); + ++i, ++x) { + + Location * location = find_location_from_marker ((*i), is_start); + + if (location) { + + if (location->locked()) { + return; + } + + if (location->is_mark()) { + location->set_start ((*x)->start()); + } else { + location->set ((*x)->start(), (*x)->end()); + } } } @@ -2446,7 +2720,7 @@ void Editor::meter_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { MeterMarker* marker = (MeterMarker *) drag_info.data; - nframes_t adjusted_frame; + nframes64_t adjusted_frame; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2578,7 +2852,7 @@ void Editor::tempo_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { TempoMarker* marker = (TempoMarker *) drag_info.data; - nframes_t adjusted_frame; + nframes64_t adjusted_frame; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2690,16 +2964,17 @@ Editor::start_control_point_grab (ArdourCanvas::Item* item, GdkEvent* event) // the point doesn't 'jump' to the mouse after the first drag 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, 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); control_point->line().start_drag (control_point, drag_info.grab_frame, 0); - double fraction = 1.0 - ((control_point->get_y() - control_point->line().y_position()) / (double)control_point->line().height()); + float fraction = 1.0 - (control_point->get_y() / control_point->line().height()); set_verbose_canvas_cursor (control_point->line().get_verbose_cursor_string (fraction), - drag_info.current_pointer_x + 20, drag_info.current_pointer_y + 20); + drag_info.current_pointer_x + 10, drag_info.current_pointer_y + 10); show_verbose_canvas_cursor (); } @@ -2746,16 +3021,16 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* cx = max (0.0, cx); cy = max (0.0, cy); - cy = min ((double) (cp->line().y_position() + cp->line().height()), cy); + cy = min ((double) cp->line().height(), cy); //translate cx to frames - nframes_t cx_frames = unit_to_frame (cx); + nframes64_t cx_frames = unit_to_frame (cx); if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()) && !drag_info.x_constrained) { snap_to (cx_frames); } - const double fraction = 1.0 - ((cy - cp->line().y_position()) / (double)cp->line().height()); + float fraction = 1.0 - (cy / cp->line().height()); bool push; @@ -2822,7 +3097,7 @@ Editor::start_line_grab (AutomationLine* line, GdkEvent* event) { double cx; double cy; - nframes_t frame_within_region; + nframes64_t frame_within_region; /* need to get x coordinate in terms of parent (TimeAxisItemView) origin. @@ -2831,7 +3106,7 @@ Editor::start_line_grab (AutomationLine* line, GdkEvent* event) cx = event->button.x; cy = event->button.y; line->parent_group().w2i (cx, cy); - frame_within_region = (nframes_t) floor (cx * frames_per_unit); + frame_within_region = (nframes64_t) floor (cx * frames_per_unit); if (!line->control_points_adjacent (frame_within_region, current_line_drag_info.before, current_line_drag_info.after)) { @@ -2846,12 +3121,12 @@ Editor::start_line_grab (AutomationLine* line, GdkEvent* event) start_grab (event, fader_cursor); - const double fraction = 1.0 - ((cy - line->y_position()) / (double)line->height()); + double fraction = 1.0 - (cy / line->height()); line->start_drag (0, drag_info.grab_frame, fraction); set_verbose_canvas_cursor (line->get_verbose_cursor_string (fraction), - drag_info.current_pointer_x + 20, drag_info.current_pointer_y + 20); + drag_info.current_pointer_x + 10, drag_info.current_pointer_y + 10); show_verbose_canvas_cursor (); } @@ -2866,7 +3141,6 @@ Editor::line_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) dy *= 0.1; } - double cx = drag_info.current_pointer_x; double cy = drag_info.grab_y + drag_info.cumulative_y_drag + dy; // calculate zero crossing point. back off by .01 to stay on the @@ -2883,12 +3157,10 @@ Editor::line_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) drag_info.cumulative_y_drag = cy - drag_info.grab_y; - line->parent_group().w2i (cx, cy); - cy = max (0.0, cy); cy = min ((double) line->height(), cy); - const double fraction = 1.0 - ((cy - line->y_position()) / (double)line->height()); + double fraction = 1.0 - (cy / line->height()); bool push; @@ -2917,7 +3189,7 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event) if (selection->regions.empty() || clicked_regionview == 0) { return; } - + _region_motion_group->raise_to_top (); drag_info.copy = false; drag_info.item = item; drag_info.data = clicked_regionview; @@ -2940,15 +3212,18 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event) speed = tv->get_diskstream()->speed(); } - drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed); + drag_info.last_frame_position = (nframes64_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; - show_verbose_time_cursor (drag_info.last_frame_position, 10); begin_reversible_command (_("move region(s)")); + + /* sync the canvas to what we think is its current state */ + track_canvas->update_now(); } void @@ -2957,7 +3232,8 @@ Editor::start_create_region_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.copy = false; drag_info.item = item; drag_info.data = clicked_axisview; - drag_info.last_trackview = clicked_axisview; + drag_info.source_trackview = clicked_axisview; + drag_info.dest_trackview = drag_info.source_trackview; drag_info.motion_callback = &Editor::create_region_drag_motion_callback; drag_info.finished_callback = &Editor::create_region_drag_finished_callback; @@ -2970,7 +3246,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) if (selection->regions.empty() || clicked_regionview == 0) { return; } - + _region_motion_group->raise_to_top (); drag_info.copy = true; drag_info.item = item; drag_info.data = clicked_regionview; @@ -2985,8 +3261,9 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) speed = rtv->get_diskstream()->speed(); } - drag_info.last_trackview = &clicked_regionview->get_time_axis_view(); - drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed); + drag_info.source_trackview = &clicked_regionview->get_time_axis_view(); + drag_info.dest_trackview = drag_info.source_trackview; + drag_info.last_frame_position = (nframes64_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 drag_info.want_move_threshold = true; @@ -3018,9 +3295,10 @@ Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event) speed = tv->get_diskstream()->speed(); } - drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed); + drag_info.last_frame_position = (nframes64_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; @@ -3035,30 +3313,34 @@ 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; for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { - RegionView* rv; RegionView* nrv; rv = (*i); - 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); if (arv) { - nrv = new AudioRegionView (*arv); + boost::shared_ptr audioregion_copy + = boost::dynamic_pointer_cast(region_copy); + nrv = new AudioRegionView (*arv, audioregion_copy); } else if (mrv) { - nrv = new MidiRegionView (*mrv); - } else { - continue; - } + boost::shared_ptr midiregion_copy + = boost::dynamic_pointer_cast(region_copy); + nrv = new MidiRegionView (*mrv, midiregion_copy); + } else { + continue; + } nrv->get_canvas_group()->show (); - new_regionviews.push_back (nrv); } @@ -3066,15 +3348,29 @@ 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(); swap_grab (new_regionviews.front()->get_canvas_group (), 0, event->motion.time); + /* + sync the canvas to what we think is its current state + without it, the canvas seems to + "forget" to update properly after the upcoming reparent() + ..only if the mouse is in rapid motion at the time of the grab. + something to do with regionview creation raking so long? + */ + track_canvas->update_now(); } } @@ -3097,7 +3393,7 @@ Editor::check_region_drag_possible (RouteTimeAxisView** tv) hide_verbose_canvas_cursor (); return false; } - + return true; } @@ -3178,8 +3474,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { double x_delta; double y_delta = 0; - RegionView* rv = reinterpret_cast (drag_info.data); - nframes_t pending_region_position = 0; + nframes64_t pending_region_position = 0; int32_t pointer_y_span = 0, canvas_pointer_y_span = 0, original_pointer_order; int32_t visible_y_high = 0, visible_y_low = 512; //high meaning higher numbered.. not the height on the screen bool clamp_y_axis = false; @@ -3193,8 +3488,8 @@ 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 ************************************************************/ @@ -3205,7 +3500,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 @@ -3233,12 +3528,13 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) tracks = tracks |= (0x01 << rtv2->order); } - height_list[rtv2->order] = (*i)->height; + height_list[rtv2->order] = (*i)->current_height(); children = 1; + if ((children_list = rtv2->get_child_list()).size() > 0) { for (TimeAxisView::Children::iterator j = children_list.begin(); j != children_list.end(); ++j) { tracks = tracks |= (0x01 << (rtv2->order + children)); - height_list[rtv2->order + children] = (*j)->height; + height_list[rtv2->order + children] = (*j)->current_height(); numtracks++; children++; } @@ -3249,16 +3545,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++; } @@ -3270,8 +3566,14 @@ 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); + rv2->get_canvas_frame()->i2w (ix1, iy1); + iy1 += vertical_adjustment.get_value() - canvas_timebars_vsize; + TimeAxisView* tvp2 = trackview_by_y_position (iy1); RouteTimeAxisView* rtv2 = dynamic_cast(tvp2); @@ -3341,13 +3643,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; } /************************************************************ @@ -3357,44 +3659,60 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) /* compute the amount of pointer motion in frames, and where 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) { + if (drag_info.current_pointer_frame >= drag_info.pointer_frame_offset) { - nframes_t sync_frame; - nframes_t sync_offset; + nframes64_t sync_frame; + nframes64_t sync_offset; int32_t sync_dir; - + pending_region_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; - sync_offset = rv->region()->sync_offset (sync_dir); - sync_frame = rv->region()->adjust_to_sync (pending_region_position); + sync_offset = clicked_regionview->region()->sync_offset (sync_dir); - /* we snap if the snap modifier is not enabled. + /* 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); + + /* we snap if the snap modifier is not enabled. + */ - if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { - snap_to (sync_frame); - } + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (sync_frame); + } - if (sync_frame - sync_offset <= sync_frame) { - pending_region_position = sync_frame + (sync_dir*sync_offset); + pending_region_position = clicked_regionview->region()->adjust_to_sync (sync_frame); + } else { - pending_region_position = 0; + pending_region_position = drag_info.last_frame_position; } } else { pending_region_position = 0; } - if (pending_region_position > max_frames - rv->region()->length()) { + if (pending_region_position > max_frames - clicked_regionview->region()->length()) { pending_region_position = drag_info.last_frame_position; } - + // 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. @@ -3404,10 +3722,28 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) x_delta = ((double) (pending_region_position - drag_info.last_frame_position) / frames_per_unit); } else { x_delta = -((double) (drag_info.last_frame_position - pending_region_position) / frames_per_unit); - } + for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { + RegionView* rv2 = (*i); + + // If any regionview is at zero, we need to know so we can stop further leftward motion. + + double ix1, ix2, iy1, iy2; + rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); + rv2->get_canvas_frame()->i2w (ix1, iy1); + + if (-x_delta > ix1 + horizontal_adjustment.get_value()) { + // do_move = false; + x_delta = 0; + pending_region_position = drag_info.last_frame_position; + break; + } + } + + } + drag_info.last_frame_position = pending_region_position; - + } else { x_delta = 0; } @@ -3417,7 +3753,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) x_delta = 0; } - + /************************************************************* PREPARE TO MOVE ************************************************************/ @@ -3427,61 +3763,67 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) trackviews. nothing to do. */ return; - } - - - if (x_delta < 0) { - for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { - - RegionView* rv2 = (*i); - - // If any regionview is at zero, we need to know so we can stop further leftward motion. - - double ix1, ix2, iy1, iy2; - rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); - rv2->get_canvas_group()->i2w (ix1, iy1); - - if (ix1 <= 1) { - x_delta = 0; - break; - } - } } /************************************************************* MOTION ************************************************************/ - - bool do_move; - + bool do_move = true; if (drag_info.first_move) { - if (drag_info.move_threshold_passed) { - do_move = true; - } else { + if (!drag_info.move_threshold_passed) { do_move = false; } - } else { - do_move = true; } if (do_move) { pair >::iterator,bool> insert_result; const list& layered_regions = selection->regions.by_layer(); - + for (list::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) { RegionView* rv = (*i); 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. */ rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); - rv->get_canvas_group()->i2w (ix1, iy1); + rv->get_canvas_frame()->i2w (ix1, iy1); + + cerr << "adjust y from " << iy1 << " using " + << vertical_adjustment.get_value() << " - " + << canvas_timebars_vsize + << endl; + + iy1 += get_trackview_group_vertical_offset ();; + + if (drag_info.first_move) { + + // 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(*_region_motion_group); + + rv->fake_set_opaque (true); + } + TimeAxisView* tvp2 = trackview_by_y_position (iy1); RouteTimeAxisView* canvas_rtv = dynamic_cast(tvp2); RouteTimeAxisView* temp_rtv; @@ -3512,6 +3854,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) { @@ -3529,7 +3872,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) tvp2 = trackview_by_y_position (iy1 + y_delta); temp_rtv = dynamic_cast(tvp2); - rv->set_y_position_and_height (0, temp_rtv->height); + rv->set_height (temp_rtv->current_height()); /* if you un-comment the following, the region colours will follow the track colours whilst dragging, personally, i think this can confuse things, but never mind. @@ -3542,44 +3885,11 @@ 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. - */ - /* clamp */ - - if (x_delta < 0) { - if (-x_delta > ix1) { - x_delta = -ix1; - } - } else if ((x_delta > 0) && (rv->region()->last_frame() > max_frames - x_delta)) { - x_delta = max_frames - rv->region()->last_frame(); - } - - - if (drag_info.first_move) { - - /* hide any dependent views */ - - rv->get_time_axis_view().hide_dependent_views (*rv); - - /* this is subtle. raising the regionview itself won't help, - because raise_to_top() just puts the item on the top of - its parent's stack. so, we need to put the trackview canvas_display group - on the top, since its parent is the whole canvas. - */ - - rv->get_canvas_group()->raise_to_top(); - rv->get_time_axis_view().canvas_display->raise_to_top(); - cursor_group->raise_to_top(); - - rv->fake_set_opaque (true); - } if (drag_info.brushing) { mouse_brush_insert_region (rv, pending_region_position); } else { - rv->move (x_delta, y_delta); + rv->move (x_delta, y_delta); } } /* foreach region */ @@ -3599,18 +3909,19 @@ 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* rvdi = reinterpret_cast (drag_info.data); - pair >::iterator,bool> insert_result; bool nocommit = true; - double speed; - RouteTimeAxisView* rtv; - bool regionview_y_movement; - bool regionview_x_movement; vector copies; - list > used_playlists; - list used_connections; - bool preserve_selection = false; + RouteTimeAxisView* source_tv; + boost::shared_ptr ds; + boost::shared_ptr from_playlist; + vector new_selection; + typedef set > PlaylistSet; + PlaylistSet modified_playlists; + PlaylistSet frozen_playlists; + list modified_playlist_connections; + pair insert_result, frozen_insert_result; + nframes64_t drag_delta; + bool changed_tracks, changed_position; /* first_move is set to false if the regionview has been moved in the motion handler. @@ -3623,12 +3934,6 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event nocommit = false; - /* The regionview has been moved at some stage during the grab so we need - to account for any mouse movement between this event and the last one. - */ - - region_drag_motion_callback (item, event); - if (Config->get_edit_mode() == Splice && !pre_drag_region_selection.empty()) { selection->set (pre_drag_region_selection); pre_drag_region_selection.clear (); @@ -3646,21 +3951,15 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event goto out; } - /* adjust for track speed */ - speed = 1.0; - - rtv = dynamic_cast (drag_info.last_trackview); - if (rtv && rtv->get_diskstream()) { - speed = rtv->get_diskstream()->speed(); - } - - regionview_x_movement = (drag_info.last_frame_position != (nframes_t) (rvdi->region()->position()/speed)); - regionview_y_movement = (drag_info.last_trackview != &rvdi->get_time_axis_view()); + char* op_string; - //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()); + /* reverse this here so that we have the correct logic to finalize + the drag. + */ - char* op_string; + if (Config->get_edit_mode() == Lock && !drag_info.copy) { + drag_info.x_constrained = !drag_info.x_constrained; + } if (drag_info.copy) { if (drag_info.x_constrained) { @@ -3678,99 +3977,139 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event begin_reversible_command (op_string); - if (regionview_y_movement) { + changed_position = (drag_info.last_frame_position != (nframes64_t) (clicked_regionview->region()->position())); + changed_tracks = (trackview_by_y_position (drag_info.current_pointer_y) != &clicked_regionview->get_time_axis_view()); - /* 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(); ) { - - RegionView* rv = (*i); + drag_delta = clicked_regionview->region()->position() - drag_info.last_frame_position; - double ix1, ix2, iy1, iy2; + track_canvas->update_now (); + + for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) { - rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); - rv->get_canvas_group()->i2w (ix1, iy1); + RegionView* rv = (*i); + double ix1, ix2, iy1, iy2; + rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); + rv->get_canvas_frame()->i2w (ix1, iy1); + iy1 += vertical_adjustment.get_value() - canvas_timebars_vsize; + + TimeAxisView* dest_tv = trackview_by_y_position (iy1); + RouteTimeAxisView* dest_rtv = dynamic_cast(dest_tv); + nframes64_t where; + + if (rv->region()->locked()) { + ++i; + continue; + } + + if (changed_position && !drag_info.x_constrained) { + where = rv->region()->position() - drag_delta; + } else { + where = rv->region()->position(); + } + + boost::shared_ptr new_region; - RouteTimeAxisView* rtv2 = dynamic_cast(trackview_by_y_position (iy1)); + if (drag_info.copy) { + /* we already made a copy */ + new_region = rv->region(); - boost::shared_ptr to_playlist = rtv2->playlist(); + /* undo the previous hide_dependent_views so that xfades don't + disappear on copying regions + */ + + //rv->get_time_axis_view().reveal_dependent_views (*rv); + + } else if (changed_tracks && dest_rtv->playlist()) { + new_region = RegionFactory::create (rv->region()); + } - if (! to_playlist->frozen()) { - /* - we haven't seen this playlist before. - we want to freeze it because we don't want to relayer per-region. - its much better to do that just once if the playlist is large. - */ + if (changed_tracks || drag_info.copy) { - /* - connect so the selection is changed when the new regionview finally appears (after thaw). - keep track of it so we can disconnect later. - */ + boost::shared_ptr to_playlist = dest_rtv->playlist(); + if (!to_playlist) { + ++i; + continue; + } - sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view)); - used_connections.push_back (c); + latest_regionviews.clear (); - /* undo */ + sigc::connection c = dest_rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); + + insert_result = modified_playlists.insert (to_playlist); + if (insert_result.second) { session->add_command (new MementoCommand(*to_playlist, &to_playlist->get_state(), 0)); - - /* remember used playlists so we can thaw them later */ - used_playlists.push_back(to_playlist); - to_playlist->freeze(); } - - where = (nframes_t) (unit_to_frame (ix1) * speed); - boost::shared_ptr new_region (RegionFactory::create (rv->region())); - - if (!drag_info.copy) { + to_playlist->add_region (new_region, where); - /* 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. - */ - - RouteTimeAxisView* from_playlist_rtv = dynamic_cast(&(*i)->get_trackview()); - boost::shared_ptr from_playlist = from_playlist_rtv->playlist(); + c.disconnect (); + + if (!latest_regionviews.empty()) { + // XXX why just the first one ? we only expect one + // commented out in nick_m's canvas reworking. is that intended? + //dest_atv->reveal_dependent_views (*latest_regionviews.front()); + new_selection.push_back (latest_regionviews.front()); + } - if (! from_playlist->frozen()) { - from_playlist->freeze(); - used_playlists.push_back(from_playlist); + } else { + /* + motion on the same track. plonk the previously reparented region + back to its original canvas group (its streamview). + No need to do anything for copies as they are fake regions which will be deleted. + */ - sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view)); - used_connections.push_back (c); + rv->get_canvas_group()->reparent (*dest_rtv->view()->canvas_item()); + rv->get_canvas_group()->property_y() = 0; + + /* just change the model */ + + boost::shared_ptr playlist = dest_rtv->playlist(); - session->add_command (new MementoCommand(*from_playlist, &from_playlist->get_state(), 0)); - } + insert_result = modified_playlists.insert (playlist); + if (insert_result.second) { + session->add_command (new MementoCommand(*playlist, &playlist->get_state(), 0)); + } + /* freeze to avoid lots of relayering in the case of a multi-region drag */ + frozen_insert_result = frozen_playlists.insert(playlist); + if (frozen_insert_result.second) { + playlist->freeze(); + } - rv->hide_region_editor(); - rv->fake_set_opaque (false); + rv->region()->set_position (where, (void*) this); + } - from_playlist->remove_region ((rv->region())); + if (changed_tracks && !drag_info.copy) { - } else { + /* 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. + */ - /* the regionview we dragged around is a temporary copy, queue it for deletion */ + assert ((source_tv = dynamic_cast (&rv->get_time_axis_view()))); + assert ((ds = source_tv->get_diskstream())); + assert ((from_playlist = ds->playlist())); - copies.push_back (rv); - } + /* moved to a different audio track, without copying */ - latest_regionviews.clear (); - sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); - session->add_command (new MementoCommand(*to_playlist, &to_playlist->get_state(), 0)); + /* 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 */ - 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()); + insert_result = modified_playlists.insert (from_playlist); + if (insert_result.second) { + session->add_command (new MementoCommand(*from_playlist, &from_playlist->get_state(), 0)); } + from_playlist->remove_region ((rv->region())); + /* 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). @@ -3784,139 +4123,55 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event EXCEPT .... if we are doing a copy drag, then the selection hasn't been modified and we can just iterate. - */ - if (drag_info.copy) { - ++i; - } else { - if (selection->regions.empty()) { - break; - } else { - /* - XXX see above .. but we just froze the playlists.. we have to keep iterating, right? - */ - - //i = selection->regions.by_layer().begin(); - ++i; - } - } - } - - } else { - - /* motion within a single track */ - - list regions = selection->regions.by_layer(); - - for (list::iterator i = regions.begin(); i != regions.end(); ++i) { - - RegionView* rv = (*i); - boost::shared_ptr to_playlist = (*i)->region()->playlist(); - RouteTimeAxisView* from_rtv = dynamic_cast (&(rv->get_time_axis_view())); - - if (!rv->region()->can_move()) { - continue; - } - - if (regionview_x_movement) { - double ownspeed = 1.0; - - if (from_rtv && from_rtv->get_diskstream()) { - ownspeed = from_rtv->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(); - } - - if (! to_playlist->frozen()) { - sigc::connection c = from_rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view)); - used_connections.push_back (c); - - /* add the undo */ - session->add_command (new MementoCommand(*to_playlist, &to_playlist->get_state(), 0)); - - used_playlists.push_back(to_playlist); - to_playlist->freeze(); - } - - if (drag_info.copy) { - - boost::shared_ptr newregion; - boost::shared_ptr ar; - boost::shared_ptr mr; - - if ((ar = boost::dynamic_pointer_cast(rv->region())) != 0) { - newregion = RegionFactory::create (ar); - } else if ((mr = boost::dynamic_pointer_cast(rv->region())) != 0) { - newregion = RegionFactory::create (mr); - } - - /* add it */ - - latest_regionviews.clear (); - sigc::connection c = rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); - to_playlist->add_region (newregion, (nframes_t) (where * rtv->get_diskstream()->speed())); - c.disconnect (); - - if (!latest_regionviews.empty()) { - // XXX why just the first one ? we only expect one - rtv->reveal_dependent_views (*latest_regionviews.front()); - selection->add (latest_regionviews); - } - - } else { - - /* just change the model */ - - rv->region()->set_position (where, (void*) this); - preserve_selection = true; - + if (selection->regions.empty()) { + break; + } else { + i = selection->regions.by_layer().begin(); } + } else { + ++i; + } + + if (drag_info.copy) { + copies.push_back (rv); } - - } - if (! preserve_selection) { - //selection->clear_regions(); } - while (used_playlists.size() > 0) { - - list >::iterator i = used_playlists.begin(); - (*i)->thaw(); - - if (used_connections.size()) { - sigc::connection c = used_connections.front(); - c.disconnect(); - used_connections.pop_front(); + + 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(); } - /* add the redo */ - - session->add_command (new MementoCommand(*(*i), 0, &(*i)->get_state())); - used_playlists.pop_front(); + } else { + /* this will clear any existing selection that would have been + cleared in the other clause above + */ + selection->set (new_selection); } + for (set >::iterator p = frozen_playlists.begin(); p != frozen_playlists.end(); ++p) { + (*p)->thaw(); + } + out: - if (!nocommit) { + for (set >::iterator p = modified_playlists.begin(); p != modified_playlists.end(); ++p) { + session->add_command (new MementoCommand(*(*p), 0, &(*p)->get_state())); + } commit_reversible_command (); } for (vector::iterator x = copies.begin(); x != copies.end(); ++x) { delete *x; } -} +} void Editor::create_region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) @@ -3934,7 +4189,7 @@ Editor::create_region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* void Editor::create_region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { - MidiTimeAxisView* mtv = dynamic_cast (drag_info.last_trackview); + MidiTimeAxisView* mtv = dynamic_cast (drag_info.dest_trackview); if (!mtv) return; @@ -3950,7 +4205,7 @@ Editor::create_region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent begin_reversible_command (_("create region")); XMLNode &before = mtv->playlist()->get_state(); - nframes_t start = drag_info.grab_frame; + nframes64_t start = drag_info.grab_frame; snap_to (start, -1); const Meter& m = session->tempo_map().meter_at(start); const Tempo& t = session->tempo_map().tempo_at(start); @@ -3992,35 +4247,43 @@ Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event) if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) { - align_region (rv.region(), SyncPoint, (nframes_t) (where * speed)); + align_region (rv.region(), SyncPoint, (nframes64_t) (where * speed)); } else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) { - align_region (rv.region(), End, (nframes_t) (where * speed)); + align_region (rv.region(), End, (nframes64_t) (where * speed)); } else { - align_region (rv.region(), Start, (nframes_t) (where * speed)); + align_region (rv.region(), Start, (nframes64_t) (where * speed)); } } } } void -Editor::show_verbose_time_cursor (nframes_t frame, double offset, double xpos, double ypos) +Editor::show_verbose_time_cursor (nframes64_t frame, double offset, double xpos, double ypos) { char buf[128]; SMPTE::Time smpte; BBT_Time bbt; int hours, mins; - nframes_t frame_rate; + nframes64_t frame_rate; float secs; if (session == 0) { 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); @@ -4043,7 +4306,7 @@ Editor::show_verbose_time_cursor (nframes_t frame, double offset, double xpos, d break; default: - snprintf (buf, sizeof(buf), "%u", frame); + snprintf (buf, sizeof(buf), "%" PRIi64, frame); break; } @@ -4051,20 +4314,20 @@ Editor::show_verbose_time_cursor (nframes_t frame, double offset, double xpos, d set_verbose_canvas_cursor (buf, xpos + offset, ypos + offset); } else { - set_verbose_canvas_cursor (buf, drag_info.current_pointer_x + offset, drag_info.current_pointer_y + offset); + set_verbose_canvas_cursor (buf, drag_info.current_pointer_x + offset - horizontal_adjustment.get_value(), drag_info.current_pointer_y + offset - vertical_adjustment.get_value() + canvas_timebars_vsize); } show_verbose_canvas_cursor (); } void -Editor::show_verbose_duration_cursor (nframes_t start, nframes_t end, double offset, double xpos, double ypos) +Editor::show_verbose_duration_cursor (nframes64_t start, nframes64_t end, double offset, double xpos, double ypos) { char buf[128]; SMPTE::Time smpte; BBT_Time sbbt; BBT_Time ebbt; int hours, mins; - nframes_t distance, frame_rate; + nframes64_t distance, frame_rate; float secs; Meter meter_at_start(session->tempo_map().meter_at(start)); @@ -4072,7 +4335,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); @@ -4117,7 +4388,7 @@ Editor::show_verbose_duration_cursor (nframes_t start, nframes_t end, double off break; default: - snprintf (buf, sizeof(buf), "%u", end - start); + snprintf (buf, sizeof(buf), "%" PRIi64, end - start); break; } @@ -4127,6 +4398,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 (); } @@ -4152,7 +4424,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event) /* lets try to create new Region for the selection */ - vector > new_regions; + vector > new_regions; create_region_from_selection (new_regions); if (new_regions.empty()) { @@ -4207,7 +4479,8 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event) start_grab (event); - drag_info.last_trackview = clicked_axisview; + drag_info.source_trackview = clicked_routeview; + 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; @@ -4227,8 +4500,8 @@ Editor::cancel_selection () void Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, SelectionOp op) { - nframes_t start = 0; - nframes_t end = 0; + nframes64_t start = 0; + nframes64_t end = 0; if (session == 0) { return; @@ -4285,10 +4558,10 @@ Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, Selection void Editor::drag_selection (ArdourCanvas::Item* item, GdkEvent* event) { - nframes_t start = 0; - nframes_t end = 0; - nframes_t length; - nframes_t pending_position; + nframes64_t start = 0; + nframes64_t end = 0; + nframes64_t length; + nframes64_t pending_position; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { pending_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -4393,7 +4666,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) { @@ -4446,9 +4719,9 @@ Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event) speed = tv->get_diskstream()->speed(); } - nframes_t region_start = (nframes_t) (clicked_regionview->region()->position() / speed); - nframes_t region_end = (nframes_t) (clicked_regionview->region()->last_frame() / speed); - nframes_t region_length = (nframes_t) (clicked_regionview->region()->length() / speed); + nframes64_t region_start = (nframes64_t) (clicked_regionview->region()->position() / speed); + nframes64_t region_end = (nframes64_t) (clicked_regionview->region()->last_frame() / speed); + nframes64_t region_length = (nframes64_t) (clicked_regionview->region()->length() / speed); //drag_info.item = clicked_regionview->get_name_highlight(); drag_info.item = item; @@ -4487,7 +4760,7 @@ void Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { RegionView* rv = clicked_regionview; - nframes_t frame_delta = 0; + nframes64_t frame_delta = 0; bool left_direction; bool obey_snap = !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()); @@ -4572,7 +4845,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) } case EndTrim: - if ((left_direction == true) && (drag_info.current_pointer_frame > (nframes_t) (rv->region()->last_frame()/speed))) { + if ((left_direction == true) && (drag_info.current_pointer_frame > (nframes64_t) (rv->region()->last_frame()/speed))) { break; } else { for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { @@ -4600,10 +4873,10 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) switch (trim_op) { case StartTrim: - show_verbose_time_cursor((nframes_t) (rv->region()->position()/speed), 10); + show_verbose_time_cursor((nframes64_t) (rv->region()->position()/speed), 10); break; case EndTrim: - show_verbose_time_cursor((nframes_t) (rv->region()->last_frame()/speed), 10); + show_verbose_time_cursor((nframes64_t) (rv->region()->last_frame()/speed), 10); break; case ContentsTrim: show_verbose_time_cursor(drag_info.current_pointer_frame, 10); @@ -4615,7 +4888,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) } void -Editor::single_contents_trim (RegionView& rv, nframes_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap) +Editor::single_contents_trim (RegionView& rv, nframes64_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap) { boost::shared_ptr region (rv.region()); @@ -4623,7 +4896,7 @@ Editor::single_contents_trim (RegionView& rv, nframes_t frame_delta, bool left_d return; } - nframes_t new_bound; + nframes64_t new_bound; double speed = 1.0; TimeAxisView* tvp = clicked_axisview; @@ -4635,27 +4908,27 @@ Editor::single_contents_trim (RegionView& rv, nframes_t frame_delta, bool left_d if (left_direction) { if (swap_direction) { - new_bound = (nframes_t) (region->position()/speed) + frame_delta; + new_bound = (nframes64_t) (region->position()/speed) + frame_delta; } else { - new_bound = (nframes_t) (region->position()/speed) - frame_delta; + new_bound = (nframes64_t) (region->position()/speed) - frame_delta; } } else { if (swap_direction) { - new_bound = (nframes_t) (region->position()/speed) - frame_delta; + new_bound = (nframes64_t) (region->position()/speed) - frame_delta; } else { - new_bound = (nframes_t) (region->position()/speed) + frame_delta; + new_bound = (nframes64_t) (region->position()/speed) + frame_delta; } } if (obey_snap) { snap_to (new_bound); } - region->trim_start ((nframes_t) (new_bound * speed), this); + region->trim_start ((nframes64_t) (new_bound * speed), this); rv.region_changed (StartChanged); } void -Editor::single_start_trim (RegionView& rv, nframes_t frame_delta, bool left_direction, bool obey_snap) +Editor::single_start_trim (RegionView& rv, nframes64_t frame_delta, bool left_direction, bool obey_snap) { boost::shared_ptr region (rv.region()); @@ -4663,7 +4936,7 @@ Editor::single_start_trim (RegionView& rv, nframes_t frame_delta, bool left_dire return; } - nframes_t new_bound; + nframes64_t new_bound; double speed = 1.0; TimeAxisView* tvp = clicked_axisview; @@ -4674,22 +4947,22 @@ Editor::single_start_trim (RegionView& rv, nframes_t frame_delta, bool left_dire } if (left_direction) { - new_bound = (nframes_t) (region->position()/speed) - frame_delta; + new_bound = (nframes64_t) (region->position()/speed) - frame_delta; } else { - new_bound = (nframes_t) (region->position()/speed) + frame_delta; + new_bound = (nframes64_t) (region->position()/speed) + frame_delta; } if (obey_snap) { snap_to (new_bound, (left_direction ? 0 : 1)); } - region->trim_front ((nframes_t) (new_bound * speed), this); + region->trim_front ((nframes64_t) (new_bound * speed), this); rv.region_changed (Change (LengthChanged|PositionChanged|StartChanged)); } void -Editor::single_end_trim (RegionView& rv, nframes_t frame_delta, bool left_direction, bool obey_snap) +Editor::single_end_trim (RegionView& rv, nframes64_t frame_delta, bool left_direction, bool obey_snap) { boost::shared_ptr region (rv.region()); @@ -4697,7 +4970,7 @@ Editor::single_end_trim (RegionView& rv, nframes_t frame_delta, bool left_direct return; } - nframes_t new_bound; + nframes64_t new_bound; double speed = 1.0; TimeAxisView* tvp = clicked_axisview; @@ -4708,15 +4981,15 @@ Editor::single_end_trim (RegionView& rv, nframes_t frame_delta, bool left_direct } if (left_direction) { - new_bound = (nframes_t) ((region->last_frame() + 1)/speed) - frame_delta; + new_bound = (nframes64_t) ((region->last_frame() + 1)/speed) - frame_delta; } else { - new_bound = (nframes_t) ((region->last_frame() + 1)/speed) + frame_delta; + new_bound = (nframes64_t) ((region->last_frame() + 1)/speed) + frame_delta; } if (obey_snap) { snap_to (new_bound); } - region->trim_end ((nframes_t) (new_bound * speed), this); + region->trim_end ((nframes64_t) (new_bound * speed), this); rv.region_changed (LengthChanged); } @@ -4756,7 +5029,7 @@ void Editor::point_trim (GdkEvent* event) { RegionView* rv = clicked_regionview; - nframes_t new_bound = drag_info.current_pointer_frame; + nframes64_t new_bound = drag_info.current_pointer_frame; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (new_bound); @@ -4904,9 +5177,25 @@ Editor::start_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event, Ran void Editor::drag_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event) { - nframes_t start = 0; - nframes_t end = 0; - ArdourCanvas::SimpleRect *crect = (range_marker_op == CreateRangeMarker) ? range_bar_drag_rect: transport_bar_drag_rect; + nframes64_t start = 0; + nframes64_t end = 0; + ArdourCanvas::SimpleRect *crect; + + switch (range_marker_op) { + case CreateRangeMarker: + crect = range_bar_drag_rect; + break; + case CreateTransportMarker: + crect = transport_bar_drag_rect; + break; + case CreateCDMarker: + crect = cd_marker_bar_drag_rect; + break; + default: + cerr << "Error: unknown range marker op passed to Editor::drag_range_markerbar_op ()" << endl; + return; + break; + } if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (drag_info.current_pointer_frame); @@ -4946,14 +5235,14 @@ Editor::drag_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event) update_marker_drag_item (temp_location); range_marker_drag_rect->show(); - range_marker_drag_rect->raise_to_top(); + //range_marker_drag_rect->raise_to_top(); } break; } if (event->button.x >= horizontal_adjustment.get_value() + canvas_width) { - start_canvas_autoscroll (1); + start_canvas_autoscroll (1, 0); } if (start != end) { @@ -4993,9 +5282,11 @@ Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event) session->locations()->next_available_name(rangename,"unnamed"); if (range_marker_op == CreateCDMarker) { flags = Location::IsRangeMarker|Location::IsCDMarker; + cd_marker_bar_drag_rect->hide(); } else { flags = Location::IsRangeMarker; + range_bar_drag_rect->hide(); } newloc = new Location(temp_location->start(), temp_location->end(), rangename, (Location::Flags) flags); session->locations()->add (newloc, true); @@ -5003,7 +5294,6 @@ Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event) session->add_command(new MementoCommand(*(session->locations()), &before, &after)); commit_reversible_command (); - range_bar_drag_rect->hide(); range_marker_drag_rect->hide(); break; } @@ -5019,8 +5309,8 @@ Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event) if (Keyboard::no_modifier_keys_pressed (&event->button) && range_marker_op != CreateCDMarker) { - nframes_t start; - nframes_t end; + nframes64_t start; + nframes64_t end; start = session->locations()->first_mark_before (drag_info.grab_frame); end = session->locations()->first_mark_after (drag_info.grab_frame); @@ -5070,8 +5360,8 @@ Editor::start_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event) void Editor::drag_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event) { - nframes_t start; - nframes_t end; + nframes64_t start; + nframes64_t end; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (drag_info.current_pointer_frame); @@ -5131,7 +5421,7 @@ Editor::end_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event) } void -Editor::reposition_zoom_rect (nframes_t start, nframes_t end) +Editor::reposition_zoom_rect (nframes64_t start, nframes64_t end) { double x1 = frame_to_pixel (start); double x2 = frame_to_pixel (end); @@ -5158,8 +5448,8 @@ Editor::start_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event) void Editor::drag_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event) { - nframes_t start; - nframes_t end; + nframes64_t start; + nframes64_t end; double y1; double y2; @@ -5169,7 +5459,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); } @@ -5226,8 +5516,7 @@ Editor::end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event) if (drag_info.current_pointer_y < drag_info.grab_y) { y1 = drag_info.current_pointer_y; y2 = drag_info.grab_y; - } - else { + } else { y2 = drag_info.current_pointer_y; y1 = drag_info.grab_y; } @@ -5332,17 +5621,21 @@ Editor::end_time_fx (ArdourCanvas::Item* item, GdkEvent* event) return; } - nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region()->position(); -#ifdef USE_RUBBERBAND - float percentage = (float) ((double) newlen / (double) clicked_regionview->region()->length()); -#else - float percentage = (float) ((double) newlen - (double) clicked_regionview->region()->length()) / ((double) newlen) * 100.0f; -#endif + nframes64_t newlen = drag_info.last_pointer_frame - clicked_regionview->region()->position(); + float percentage = (double) newlen / (double) clicked_regionview->region()->length(); + +#ifndef USE_RUBBERBAND + // Soundtouch uses percentage / 100 instead of normal (/ 1) + if (clicked_regionview->region()->data_type() == DataType::AUDIO) { + percentage = (float) ((double) newlen - (double) clicked_regionview->region()->length()) / ((double) newlen) * 100.0f; + } +#endif + begin_reversible_command (_("timestretch")); - + // XXX how do timeFX on multiple regions ? - + RegionSelection rs; rs.add (clicked_regionview); @@ -5352,14 +5645,10 @@ Editor::end_time_fx (ArdourCanvas::Item* item, GdkEvent* event) } void -Editor::mouse_brush_insert_region (RegionView* rv, nframes_t pos) +Editor::mouse_brush_insert_region (RegionView* rv, nframes64_t pos) { /* no brushing without a useful snap setting */ - // FIXME - AudioRegionView* arv = dynamic_cast(rv); - assert(arv); - switch (snap_mode) { case SnapMagnetic: return; /* can't work because it allows region to be placed anywhere */ @@ -5381,7 +5670,7 @@ Editor::mouse_brush_insert_region (RegionView* rv, nframes_t pos) return; } - RouteTimeAxisView* rtv = dynamic_cast(&arv->get_time_axis_view()); + RouteTimeAxisView* rtv = dynamic_cast(&rv->get_time_axis_view()); if (rtv == 0 || !rtv->is_track()) { return; @@ -5391,7 +5680,7 @@ Editor::mouse_brush_insert_region (RegionView* rv, nframes_t pos) double speed = rtv->get_diskstream()->speed(); XMLNode &before = playlist->get_state(); - playlist->add_region (boost::dynamic_pointer_cast (RegionFactory::create (arv->audio_region())), (nframes_t) (pos * speed)); + playlist->add_region (RegionFactory::create (rv->region()), (nframes64_t) (pos * speed)); XMLNode &after = playlist->get_state(); session->add_command(new MementoCommand(*playlist.get(), &before, &after)); @@ -5403,13 +5692,7 @@ Editor::mouse_brush_insert_region (RegionView* rv, nframes_t pos) gint Editor::track_height_step_timeout () { - struct timeval now; - struct timeval delta; - - gettimeofday (&now, 0); - timersub (&now, &last_track_height_step_timestamp, &delta); - - if (delta.tv_sec * 1000000 + delta.tv_usec > 250000) { /* milliseconds */ + if (get_microseconds() - last_track_height_step_timestamp < 250000) { current_stepping_trackview = 0; return false; }