X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_mouse.cc;h=490112d43010ceee2518190843d8d976a402b0e5;hb=c89c77c8c3382c27565d22e5e87eda191186dac9;hp=9a11ab3791d6b441ddb4a5781b4948662d67f9ba;hpb=a30fb19cb326fe13d72cab11543ca0bcd3084f7d;p=ardour.git diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 9a11ab3791..490112d430 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -1,3 +1,4 @@ + /* Copyright (C) 2000-2001 Paul Davis @@ -85,23 +86,15 @@ Editor::mouse_frame (nframes64_t& where, bool& in_track_canvas) const 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); + 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; @@ -131,10 +124,16 @@ 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: @@ -214,9 +213,9 @@ Editor::which_grabber_cursor () return grabber_edit_point_cursor; break; default: - return grabber_cursor; break; } + return grabber_cursor; } void @@ -337,8 +336,15 @@ Editor::step_mouse_mode (bool next) { switch (current_mouse_mode()) { case MouseObject: - if (next) set_mouse_mode (MouseRange); - else set_mouse_mode (MouseTimeFX); + if (next) { + if (Profile->get_sae()) { + set_mouse_mode (MouseZoom); + } else { + set_mouse_mode (MouseRange); + } + } else { + set_mouse_mode (MouseTimeFX); + } break; case MouseRange: @@ -347,8 +353,19 @@ Editor::step_mouse_mode (bool next) break; case MouseZoom: - if (next) set_mouse_mode (MouseGain); - else set_mouse_mode (MouseRange); + if (next) { + if (Profile->get_sae()) { + set_mouse_mode (MouseTimeFX); + } else { + set_mouse_mode (MouseGain); + } + } else { + if (Profile->get_sae()) { + set_mouse_mode (MouseObject); + } else { + set_mouse_mode (MouseRange); + } + } break; case MouseGain: @@ -357,8 +374,15 @@ Editor::step_mouse_mode (bool next) break; case MouseTimeFX: - if (next) set_mouse_mode (MouseAudition); - else set_mouse_mode (MouseGain); + if (next) { + set_mouse_mode (MouseAudition); + } else { + if (Profile->get_sae()) { + set_mouse_mode (MouseZoom); + } else { + set_mouse_mode (MouseGain); + } + } break; case MouseAudition: @@ -371,10 +395,11 @@ Editor::step_mouse_mode (bool next) void Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { - /* in object/audition/timefx mode, any button press sets - the selection if the object can be selected. this is a - bit of hack, because we want to avoid this if the - mouse operation is a region alignment. + /* in object/audition/timefx/gain-automation mode, + any button press sets the selection if the object + can be selected. this is a bit of hack, because + we want to avoid this if the mouse operation is a + region alignment. note: not dbl-click or triple-click */ @@ -382,9 +407,10 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it if (((mouse_mode != MouseObject) && (mouse_mode != MouseAudition || item_type != RegionItem) && (mouse_mode != MouseTimeFX || item_type != RegionItem) && + (mouse_mode != MouseGain) && (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; } @@ -400,7 +426,7 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it } } } - + Selection::Operation op = Keyboard::selection_type (event->button.state); bool press = (event->type == GDK_BUTTON_PRESS); @@ -467,6 +493,24 @@ const static double ZERO_GAIN_FRACTION = gain_to_slider_position(dB_to_coefficie bool Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { + 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()) { @@ -474,7 +518,25 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp } button_selection (item, event, item_type); - + + //ctrl-drag or right-click-drag on a "range" ruler should start a range drag + if (event->type == GDK_BUTTON_PRESS) { + if (event->button.button == 3 || ( (event->button.button == 1) && (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier) ))) { + if (item_type == TransportMarkerBarItem) { + start_range_markerbar_op (item, event, CreateTransportMarker); + return true; + } + if (item_type == RangeMarkerBarItem) { + start_range_markerbar_op (item, event, CreateRangeMarker); + return true; + } + if (item_type == CdMarkerBarItem) { + start_range_markerbar_op (item, event, CreateCDMarker); + return true; + } + } + } + if (drag_info.item == 0 && (Keyboard::is_delete_event (&event->button) || Keyboard::is_context_menu_event (&event->button) || @@ -528,24 +590,15 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp } return true; + case MarkerBarItem: case TempoBarItem: - return true; - case MeterBarItem: - return true; - + case TransportMarkerBarItem: case RangeMarkerBarItem: - start_range_markerbar_op (item, event, CreateRangeMarker); - return true; - break; - case CdMarkerBarItem: - start_range_markerbar_op (item, event, CreateCDMarker); - return true; - break; - - case TransportMarkerBarItem: - start_range_markerbar_op (item, event, CreateTransportMarker); + if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) { + start_cursor_grab_no_stop(&playhead_cursor->canvas_item, event); + } return true; break; @@ -620,8 +673,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 GainAutomationControlPointItem: @@ -685,7 +738,13 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp case MouseGain: switch (item_type) { case RegionItem: - // start_line_grab_from_regionview (item, event); + /* start a grab so that if we finish after moving + we can tell what happened. + */ + drag_info.item = item; + drag_info.motion_callback = &Editor::region_gain_motion_callback; + drag_info.finished_callback = 0; + start_grab (event, current_canvas_cursor); break; case GainControlPointItem: @@ -844,9 +903,9 @@ 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 */ if (session && session->actively_recording()) { @@ -865,7 +924,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT button_selection (item, event, item_type); /* edit events get handled here */ - + if (drag_info.item == 0 && Keyboard::is_edit_event (&event->button)) { switch (item_type) { case RegionItem: @@ -934,7 +993,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT case CdMarkerBarItem: case TempoBarItem: case MeterBarItem: - popup_ruler_menu (pixel_to_frame(event->button.x), item_type); + popup_ruler_menu (where, item_type); break; case MarkerItem: @@ -1034,36 +1093,44 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT return true; case MarkerBarItem: - if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { - snap_to (where, 0, true); + if (!_dragging_playhead) { + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (where, 0, true); + } + mouse_add_new_marker (where); } - mouse_add_new_marker (where); return true; case CdMarkerBarItem: - // if we get here then a dragged range wasn't done - if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { - snap_to (where, 0, true); + if (!_dragging_playhead) { + // if we get here then a dragged range wasn't done + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (where, 0, true); + } + mouse_add_new_marker (where, true); } - mouse_add_new_marker (where, true); return true; case TempoBarItem: - if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { - snap_to (where); + if (!_dragging_playhead) { + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (where); + } + mouse_add_new_tempo_event (where); } - mouse_add_new_tempo_event (where); return true; case MeterBarItem: - mouse_add_new_meter_event (pixel_to_frame (event->button.x)); + if (!_dragging_playhead) { + mouse_add_new_meter_event (pixel_to_frame (event->button.x)); + } return true; break; default: break; } - + switch (mouse_mode) { case MouseObject: switch (item_type) { @@ -1090,7 +1157,13 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT switch (item_type) { case RegionItem: - dynamic_cast(clicked_regionview)->add_gain_point_event (item, event); + /* check that we didn't drag before releasing, since + its really annoying to create new control + points when doing this. + */ + if (drag_info.first_move) { + dynamic_cast(clicked_regionview)->add_gain_point_event (item, event); + } return true; break; @@ -1196,8 +1269,8 @@ 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()); @@ -1224,8 +1297,8 @@ 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()); @@ -1341,7 +1414,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; @@ -1355,7 +1428,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: @@ -1476,7 +1549,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 (*current_canvas_cursor); } break; @@ -1493,7 +1566,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; @@ -1628,7 +1701,7 @@ 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); } @@ -1686,6 +1759,12 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item switch (item_type) { case PlayheadCursorItem: case MarkerItem: + case MarkerBarItem: + case TempoBarItem: + case MeterBarItem: + case RangeMarkerBarItem: + case TransportMarkerBarItem: + case CdMarkerBarItem: case GainControlPointItem: case RedirectAutomationControlPointItem: case GainAutomationControlPointItem: @@ -1709,20 +1788,32 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item case MarkerViewHandleEndItem: /* */ if (drag_info.item && (event->motion.state & Gdk::BUTTON1_MASK || + (event->motion.state & Gdk::BUTTON3_MASK) || (event->motion.state & Gdk::BUTTON2_MASK))) { if (!from_autoscroll) { - maybe_autoscroll (&event->motion); + maybe_autoscroll_horizontally (&event->motion); + } + if (drag_info.motion_callback) { + (this->*(drag_info.motion_callback)) (item, event); } - (this->*(drag_info.motion_callback)) (item, event); goto handled; } goto not_handled; - + break; default: break; } switch (mouse_mode) { + case MouseGain: + if (item_type == RegionItem) { + if (drag_info.item && drag_info.motion_callback) { + (this->*(drag_info.motion_callback)) (item, event); + } + goto handled; + } + break; + case MouseObject: case MouseRange: case MouseZoom: @@ -1732,7 +1823,9 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item if (!from_autoscroll) { maybe_autoscroll (&event->motion); } - (this->*(drag_info.motion_callback)) (item, event); + if (drag_info.motion_callback) { + (this->*(drag_info.motion_callback)) (item, event); + } goto handled; } goto not_handled; @@ -1786,11 +1879,8 @@ Editor::finalize_drag () 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; - } + range_marker_drag_rect->hide(); + drag_info.clear_copied_locations (); } void @@ -1808,7 +1898,7 @@ Editor::start_grab (GdkEvent* event, Gdk::Cursor *cursor) // if dragging with button2, the motion is x constrained, with Alt-button2 it is y constrained - if (event->button.button == 2) { + if (Keyboard::is_button2_event (&event->button)) { if (Keyboard::modifier_state_equals (event->button.state, Keyboard::SecondaryModifier)) { drag_info.y_constrained = true; drag_info.x_constrained = false; @@ -1835,7 +1925,7 @@ 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; @@ -1887,9 +1977,9 @@ Editor::end_grab (ArdourCanvas::Item* item, GdkEvent* event) return false; } - drag_info.item->ungrab (event->button.time); + drag_info.item->ungrab (event ? event->button.time : 0); - if (drag_info.finished_callback) { + if (drag_info.finished_callback && event) { drag_info.last_pointer_x = drag_info.current_pointer_x; drag_info.last_pointer_y = drag_info.current_pointer_y; (this->*(drag_info.finished_callback)) (item, event); @@ -1904,6 +1994,14 @@ Editor::end_grab (ArdourCanvas::Item* item, GdkEvent* event) return did_drag; } +void +Editor::region_gain_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) +{ + if (drag_info.first_move && drag_info.move_threshold_passed) { + drag_info.first_move = false; + } +} + void Editor::start_fade_in_grab (ArdourCanvas::Item* item, GdkEvent* event) { @@ -1920,15 +2018,15 @@ 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; @@ -1970,8 +2068,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; @@ -2028,15 +2126,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; @@ -2082,8 +2180,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; @@ -2162,11 +2260,44 @@ Editor::start_cursor_grab (ArdourCanvas::Item* item, GdkEvent* event) show_verbose_time_cursor (cursor->current_frame, 10); } +void +Editor::start_cursor_grab_no_stop (ArdourCanvas::Item* item, GdkEvent* event) +{ + drag_info.item = item; + drag_info.motion_callback = &Editor::cursor_drag_motion_callback; + drag_info.finished_callback = &Editor::cursor_drag_finished_ensure_locate_callback; + + start_grab (event); + + if ((drag_info.data = (item->get_data ("cursor"))) == 0) { + fatal << _("programming error: cursor canvas item has no cursor data pointer!") << endmsg; + /*NOTREACHED*/ + } + + Cursor* cursor = (Cursor *) drag_info.data; + nframes64_t where = event_frame (event, 0, 0); + + snap_to(where); + playhead_cursor->set_position (where); + + if (cursor == playhead_cursor) { + _dragging_playhead = true; + + if (session && session->is_auditioning()) { + session->cancel_audition (); + } + } + + drag_info.pointer_frame_offset = drag_info.grab_frame - cursor->current_frame; + + show_verbose_time_cursor (cursor->current_frame, 10); +} + 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; @@ -2184,11 +2315,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; } @@ -2196,12 +2330,28 @@ Editor::cursor_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) void Editor::cursor_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { - if (drag_info.first_move) return; + _dragging_playhead = false; + + if (drag_info.first_move) { + return; + } cursor_drag_motion_callback (item, event); + + if (item == &playhead_cursor->canvas_item) { + if (session) { + session->request_locate (playhead_cursor->current_frame, drag_info.was_rolling); + } + } +} +void +Editor::cursor_drag_finished_ensure_locate_callback (ArdourCanvas::Item* item, GdkEvent* event) +{ _dragging_playhead = false; + cursor_drag_motion_callback (item, event); + if (item == &playhead_cursor->canvas_item) { if (session) { session->request_locate (playhead_cursor->current_frame, drag_info.was_rolling); @@ -2219,8 +2369,7 @@ 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; } @@ -2249,7 +2398,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); @@ -2259,7 +2407,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) { @@ -2275,35 +2423,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; } + + /* 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); @@ -2313,102 +2500,198 @@ 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(); + } + if (Profile->get_sae()) { + edit_point_clock.set (drag_info.copied_locations.front()->start()); + } show_verbose_time_cursor (newframe, 10); + +#ifdef GTKOSX + track_canvas->update_now (); +#endif } void Editor::marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { if (drag_info.first_move) { - /* just a click, do nothing but whatever selection occured */ + + /* 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()); + } } } @@ -2489,7 +2772,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; @@ -2621,7 +2904,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; @@ -2734,8 +3017,7 @@ Editor::start_control_point_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.grab_x = control_point->get_x(); drag_info.grab_y = control_point->get_y(); control_point->line.parent_group().i2w(drag_info.grab_x, drag_info.grab_y); - track_canvas->w2c(drag_info.grab_x, drag_info.grab_y, - 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); @@ -2743,7 +3025,7 @@ Editor::start_control_point_grab (ArdourCanvas::Item* item, GdkEvent* event) 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 (); } @@ -2793,7 +3075,7 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* 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); @@ -2866,16 +3148,18 @@ 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. + origin, and ditto for y. */ 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)) { @@ -2890,12 +3174,17 @@ Editor::start_line_grab (AutomationLine* line, GdkEvent* event) start_grab (event, fader_cursor); + /* store grab start in parent frame */ + + drag_info.grab_x = cx; + drag_info.grab_y = cy; + 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 (); } @@ -2905,35 +3194,19 @@ Editor::line_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) AutomationLine* line = reinterpret_cast (drag_info.data); double dy = drag_info.current_pointer_y - drag_info.last_pointer_y; - + if (event->button.state & Keyboard::SecondaryModifier) { 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 - // positive side of zero - double _unused = 0; - double zero_gain_y = (1.0 - ZERO_GAIN_FRACTION) * line->height() - .01; - line->parent_group().i2w(_unused, zero_gain_y); - - // make sure we hit zero when passing through - if ((cy < zero_gain_y and (cy - dy) > zero_gain_y) - or (cy > zero_gain_y and (cy - dy) < zero_gain_y)) { - cy = zero_gain_y; - } - 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); - double fraction; - fraction = 1.0 - (cy / line->height()); + double fraction = 1.0 - (cy / line->height()); bool push; @@ -2985,7 +3258,7 @@ 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.source_trackview = &clicked_regionview->get_time_axis_view(); drag_info.dest_trackview = drag_info.source_trackview; @@ -2995,6 +3268,11 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event) show_verbose_time_cursor (drag_info.last_frame_position, 10); begin_reversible_command (_("move region(s)")); + + _region_motion_group->raise_to_top (); + + /* sync the canvas to what we think is its current state */ + track_canvas->update_now(); } void @@ -3020,13 +3298,14 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.source_trackview = &clicked_regionview->get_time_axis_view(); drag_info.dest_trackview = drag_info.source_trackview; - drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed); + drag_info.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; drag_info.motion_callback = &Editor::region_drag_motion_callback; drag_info.finished_callback = &Editor::region_drag_finished_callback; show_verbose_time_cursor (drag_info.last_frame_position, 10); + _region_motion_group->raise_to_top (); } void @@ -3052,7 +3331,7 @@ 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.source_trackview = &clicked_regionview->get_time_axis_view(); drag_info.dest_trackview = drag_info.source_trackview; @@ -3075,18 +3354,14 @@ Editor::possibly_copy_regions_during_grab (GdkEvent* event) vector new_regionviews; for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { - RegionView* rv; RegionView* nrv; AudioRegionView* arv; - rv = (*i); - - - if ((arv = dynamic_cast(rv)) == 0) { + if ((arv = dynamic_cast(*i)) == 0) { /* XXX handle MIDI here */ continue; } - + const boost::shared_ptr original = arv->region(); boost::shared_ptr region_copy = RegionFactory::create (original); boost::shared_ptr ar = boost::dynamic_pointer_cast (region_copy); @@ -3116,6 +3391,14 @@ Editor::possibly_copy_regions_during_grab (GdkEvent* event) 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(); } } @@ -3219,8 +3502,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; @@ -3235,7 +3517,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) } original_pointer_order = drag_info.dest_trackview->order; - + /************************************************************ Y-Delta Computation ************************************************************/ @@ -3250,7 +3532,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) int32_t children = 0, numtracks = 0; // XXX hard coding track limit, oh my, so very very bad - bitset <1024> tracks (0x00); + bitset <1024> tracks (0x00ul); /* get a bitmask representing the visible tracks */ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { @@ -3274,12 +3556,12 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) tracks = tracks |= (0x01 << atv2->order); } - height_list[atv2->order] = (*i)->height; + height_list[atv2->order] = (*i)->current_height(); children = 1; if ((children_list = atv2->get_child_list()).size() > 0) { for (list::iterator j = children_list.begin(); j != children_list.end(); ++j) { tracks = tracks |= (0x01 << (atv2->order + children)); - height_list[atv2->order + children] = (*j)->height; + height_list[atv2->order + children] = (*j)->current_height(); numtracks++; children++; } @@ -3317,6 +3599,8 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); rv2->get_canvas_group()->i2w (ix1, iy1); + iy1 += vertical_adjustment.get_value() - canvas_timebars_vsize; + TimeAxisView* tvp2 = trackview_by_y_position (iy1); RouteTimeAxisView* atv2 = dynamic_cast(tvp2); @@ -3402,18 +3686,17 @@ 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.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_offset = clicked_regionview->region()->sync_offset (sync_dir); /* we don't handle a sync point that lies before zero. */ @@ -3427,7 +3710,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) snap_to (sync_frame); } - pending_region_position = rv->region()->adjust_to_sync (sync_frame); + pending_region_position = clicked_regionview->region()->adjust_to_sync (sync_frame); } else { pending_region_position = drag_info.last_frame_position; @@ -3437,26 +3720,21 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) 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 ); 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; - } + 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 ) { + 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. @@ -3466,10 +3744,27 @@ 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_group()->i2w (ix1, iy1); + + if (-x_delta > ix1 + horizontal_adjustment.get_value()) { + x_delta = 0; + pending_region_position = drag_info.last_frame_position; + break; + } + } + } + drag_info.last_frame_position = pending_region_position; - + } else { x_delta = 0; } @@ -3489,41 +3784,16 @@ 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) { @@ -3548,6 +3818,31 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); rv->get_canvas_group()->i2w (ix1, iy1); + + /* for evaluation of the track position of iy1, we have to adjust + to allow for the vertical scrolling adjustment and the height of the timebars. + */ + + 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); AudioTimeAxisView* canvas_atv = dynamic_cast(tvp2); AudioTimeAxisView* temp_atv; @@ -3596,7 +3891,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) tvp2 = trackview_by_y_position (iy1 + y_delta); temp_atv = dynamic_cast(tvp2); - rv->set_height (temp_atv->height); + rv->set_height (temp_atv->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. @@ -3610,43 +3905,10 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) } } - - /* 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 */ @@ -3674,7 +3936,11 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event vector new_selection; typedef set > PlaylistSet; PlaylistSet modified_playlists; - pair insert_result; + 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. @@ -3687,12 +3953,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 (); @@ -3716,7 +3976,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event the drag. */ - if (Config->get_edit_mode() == Lock && !drag_info.copy) { + if (Config->get_edit_mode() == Lock) { drag_info.x_constrained = !drag_info.x_constrained; } @@ -3735,6 +3995,12 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event } begin_reversible_command (op_string); + 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()); + + drag_delta = clicked_regionview->region()->position() - drag_info.last_frame_position; + + track_canvas->update_now (); for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) { @@ -3742,47 +4008,36 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event double ix1, ix2, iy1, iy2; rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); rv->get_canvas_group()->i2w (ix1, iy1); + iy1 += vertical_adjustment.get_value() - canvas_timebars_vsize; + TimeAxisView* dest_tv = trackview_by_y_position (iy1); AudioTimeAxisView* dest_atv = dynamic_cast(dest_tv); - double speed; - bool changed_tracks; - bool changed_position; - nframes_t where; + nframes64_t where; if (rv->region()->locked()) { ++i; continue; } - /* adjust for track speed */ - - speed = 1.0; - - if (dest_atv && dest_atv->get_diskstream()) { - speed = dest_atv->get_diskstream()->speed(); - } - - changed_position = (drag_info.last_frame_position != (nframes_t) (rv->region()->position()/speed)); - changed_tracks = (dest_tv != &rv->get_time_axis_view()); - if (changed_position && !drag_info.x_constrained) { - where = (nframes_t) (unit_to_frame (ix1) * speed); + where = rv->region()->position() - drag_delta; } else { where = rv->region()->position(); } - /* undo the previous hide_dependent_views so that xfades don't - disappear on copying regions - */ - - rv->get_time_axis_view().reveal_dependent_views (*rv); - boost::shared_ptr new_region; if (drag_info.copy) { /* we already made a copy */ new_region = rv->region(); - } else { + + /* 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) { new_region = RegionFactory::create (rv->region()); } @@ -3796,7 +4051,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event insert_result = modified_playlists.insert (to_playlist); if (insert_result.second) { - session->add_command (new MementoCommand(*to_playlist, &to_playlist->get_state(), 0)); + session->add_command (new MementoCommand(*to_playlist, &to_playlist->get_state(), 0)); } to_playlist->add_region (new_region, where); @@ -3805,19 +4060,33 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event if (!latest_regionviews.empty()) { // XXX why just the first one ? we only expect one - dest_atv->reveal_dependent_views (*latest_regionviews.front()); + //dest_atv->reveal_dependent_views (*latest_regionviews.front()); new_selection.push_back (latest_regionviews.front()); } } 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. + */ + + RouteTimeAxisView* dest_rtv = dynamic_cast (dest_atv); + 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_atv->playlist(); insert_result = modified_playlists.insert (playlist); if (insert_result.second) { - session->add_command (new MementoCommand(*playlist, &playlist->get_state(), 0)); + 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->region()->set_position (where, (void*) this); @@ -3848,7 +4117,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event insert_result = modified_playlists.insert (from_playlist); if (insert_result.second) { - session->add_command (new MementoCommand(*from_playlist, &from_playlist->get_state(), 0)); + session->add_command (new MementoCommand(*from_playlist, &from_playlist->get_state(), 0)); } from_playlist->remove_region ((rv->region())); @@ -3884,7 +4153,6 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event copies.push_back (rv); } } - if (new_selection.empty()) { if (drag_info.copy) { @@ -3900,6 +4168,10 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event */ selection->set (new_selection); } + + for (set >::iterator p = frozen_playlists.begin(); p != frozen_playlists.end(); ++p) { + (*p)->thaw(); + } out: if (!nocommit) { @@ -3912,6 +4184,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event for (vector::iterator x = copies.begin(); x != copies.end(); ++x) { delete *x; } + } void @@ -3935,28 +4208,28 @@ 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) { @@ -3994,7 +4267,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; } @@ -4002,20 +4275,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)); @@ -4076,7 +4349,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; } @@ -4181,8 +4454,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; @@ -4239,10 +4512,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; @@ -4400,9 +4673,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; @@ -4441,7 +4714,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()); @@ -4525,7 +4798,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) { @@ -4553,10 +4826,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); @@ -4568,7 +4841,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()); @@ -4576,7 +4849,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_trackview; @@ -4588,27 +4861,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()); @@ -4616,7 +4889,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_trackview; @@ -4627,22 +4900,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()); @@ -4650,7 +4923,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_trackview; @@ -4661,15 +4934,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); } @@ -4709,7 +4982,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); @@ -4857,8 +5130,8 @@ 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; + nframes64_t start = 0; + nframes64_t end = 0; ArdourCanvas::SimpleRect *crect; switch (range_marker_op) { @@ -4915,7 +5188,7 @@ 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; @@ -4989,8 +5262,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); @@ -5040,8 +5313,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); @@ -5101,7 +5374,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); @@ -5128,8 +5401,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; @@ -5196,8 +5469,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; } @@ -5219,7 +5491,9 @@ Editor::end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event) } } else { - selection->clear_tracks(); + if (!getenv("ARDOUR_SAE")) { + selection->clear_tracks(); + } selection->clear_regions(); selection->clear_points (); selection->clear_lines (); @@ -5302,7 +5576,7 @@ Editor::end_time_fx (ArdourCanvas::Item* item, GdkEvent* event) return; } - nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region()->position(); + nframes64_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 @@ -5322,7 +5596,7 @@ 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 */ @@ -5361,7 +5635,7 @@ Editor::mouse_brush_insert_region (RegionView* rv, nframes_t pos) double speed = atv->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 (boost::dynamic_pointer_cast (RegionFactory::create (arv->audio_region())), (nframes64_t) (pos * speed)); XMLNode &after = playlist->get_state(); session->add_command(new MementoCommand(*playlist.get(), &before, &after)); @@ -5373,13 +5647,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; }