X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_mouse.cc;h=10f4c0eb032f354f3b9e3c7732984ace8dbe68a6;hb=aa60114843f4990ef93ba83974501495ddda358b;hp=7eade9e793799b2dc02f9ac1981b3a31268255b2;hpb=d38e2213d79b1c8952c776a3b60f7709457edc0c;p=ardour.git diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 7eade9e793..10f4c0eb03 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -18,6 +18,7 @@ $Id$ */ +#include #include #include #include @@ -27,12 +28,13 @@ #include #include +#include #include "ardour_ui.h" #include "editor.h" #include "time_axis_view.h" #include "audio_time_axis.h" -#include "regionview.h" +#include "audio_region_view.h" #include "marker.h" #include "streamview.h" #include "region_gain_line.h" @@ -43,12 +45,11 @@ #include "keyboard.h" #include "editing.h" #include "rgb_macros.h" -#include "extra_bind.h" #include #include #include -#include +#include #include #include #include @@ -62,11 +63,12 @@ using namespace std; using namespace ARDOUR; +using namespace PBD; using namespace sigc; using namespace Gtk; using namespace Editing; -jack_nframes_t +nframes_t Editor::event_frame (GdkEvent* event, double* pcx, double* pcy) { double cx, cy; @@ -86,17 +88,21 @@ Editor::event_frame (GdkEvent* event, double* pcx, double* pcy) case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: - gtk_canvas_w2c_d (GTK_CANVAS(track_gtk_canvas), event->button.x, event->button.y, pcx, pcy); + track_canvas.w2c(event->button.x, event->button.y, *pcx, *pcy); break; case GDK_MOTION_NOTIFY: - gtk_canvas_w2c_d (GTK_CANVAS(track_gtk_canvas), event->motion.x, event->motion.y, pcx, pcy); + track_canvas.w2c(event->motion.x, event->motion.y, *pcx, *pcy); break; case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: - gtk_canvas_w2c_d (GTK_CANVAS(track_gtk_canvas), 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); break; default: - warning << compose (_("Editor::event_frame() used on unhandled event type %1"), event->type) << endmsg; + warning << string_compose (_("Editor::event_frame() used on unhandled event type %1"), event->type) << endmsg; break; } @@ -104,7 +110,7 @@ Editor::event_frame (GdkEvent* event, double* pcx, double* pcy) position is negative (as can be the case with motion events in particular), the frame location is always positive. */ - + return pixel_to_frame (*pcx); } @@ -164,7 +170,7 @@ Editor::set_mouse_mode (MouseMode m, bool force) return; } - if (m == mouse_mode && !force) { + if (!force && m == mouse_mode) { return; } @@ -178,7 +184,7 @@ Editor::set_mouse_mode (MouseMode m, bool force) show the object (region) selection. */ - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { (*i)->set_should_show_selection (true); } for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { @@ -187,15 +193,12 @@ Editor::set_mouse_mode (MouseMode m, bool force) } else { - /* in range mode, hide object (region) selection, and show the - range selection. + /* + in range mode,show the range selection. */ - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { - (*i)->set_should_show_selection (false); - } for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { - if ((*i)->selected()) { + if ((*i)->get_selected()) { (*i)->show_selection (selection->time); } } @@ -243,7 +246,7 @@ Editor::set_mouse_mode (MouseMode m, bool force) ignore_mouse_mode_toggle = false; if (is_drawable()) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); + track_canvas.get_window()->set_cursor(*current_canvas_cursor); } } @@ -283,96 +286,117 @@ Editor::step_mouse_mode (bool next) } } -gint -Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) +void +Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { - jack_nframes_t where = event_frame (event, 0, 0); - - if (session && session->actively_recording()) { - return TRUE; - } + bool commit = false; /* 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. + + note: not dbl-click or triple-click */ - if (((mouse_mode == MouseObject) || - (mouse_mode == MouseAudition && item_type == RegionItem) || - (mouse_mode == MouseTimeFX && item_type == RegionItem)) && - event->type == GDK_BUTTON_PRESS && - event->button.button <= 3) { + if (((mouse_mode != MouseObject) && + (mouse_mode != MouseAudition || item_type != RegionItem) && + (mouse_mode != MouseTimeFX || item_type != RegionItem) && + (mouse_mode != MouseRange)) || - AudioRegionView* rv; - ControlPoint* cp; + (event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE || event->button.button > 3)) { + + return; + } - /* not dbl-click or triple-click */ + if (event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) { - switch (item_type) { - case RegionItem: - set_selected_regionview_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true); - break; + if ((event->button.state & Keyboard::RelevantModifierKeyMask) && event->button.button != 1) { - case AudioRegionViewNameHighlight: - case AudioRegionViewName: - if ((rv = reinterpret_cast (gtk_object_get_data(GTK_OBJECT(item), "regionview"))) != 0) { - set_selected_regionview_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true); - } - break; + /* no selection action on modified button-2 or button-3 events */ - case GainAutomationControlPointItem: - case PanAutomationControlPointItem: - case RedirectAutomationControlPointItem: - if ((cp = reinterpret_cast (gtk_object_get_data(GTK_OBJECT(item), "control_point"))) != 0) { - set_selected_control_point_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true); - } - break; + return; + } + } + + Selection::Operation op = Keyboard::selection_type (event->button.state); + bool press = (event->type == GDK_BUTTON_PRESS); - case StreamItem: - break; + begin_reversible_command (_("select on click")); - case AutomationTrackItem: - break; + switch (item_type) { + case RegionItem: + if (mouse_mode != MouseRange) { + commit = set_selected_regionview_from_click (press, op, true); + } + break; + + case RegionViewNameHighlight: + case RegionViewName: + if (mouse_mode != MouseRange) { + commit = set_selected_regionview_from_click (press, op, true); + } + break; - default: - break; + case FadeInHandleItem: + case FadeInItem: + case FadeOutHandleItem: + case FadeOutItem: + if (mouse_mode != MouseRange) { + commit = set_selected_regionview_from_click (press, op, true); } + break; + + case GainAutomationControlPointItem: + case PanAutomationControlPointItem: + case RedirectAutomationControlPointItem: + if (mouse_mode != MouseRange) { + commit = set_selected_control_point_from_click (op, false); + } + break; + + case StreamItem: + /* for context click or range selection, select track */ + if (event->button.button == 3) { + commit = set_selected_track_from_click (press, op, true); + } else if (event->type == GDK_BUTTON_PRESS && mouse_mode == MouseRange) { + commit = set_selected_track_from_click (press, op, false); + } + break; + + case AutomationTrackItem: + commit = set_selected_track_from_click (press, op, true); + break; + + default: + break; } + + if (commit) { + commit_reversible_command (); + } +} -#define SELECT_TRACK_FROM_CANVAS_IN_RANGE_MODE -#ifdef SELECT_TRACK_FROM_CANVAS_IN_RANGE_MODE - /* in range mode, button 1/2/3 press potentially selects a track */ - - if (mouse_mode == MouseRange && - event->type == GDK_BUTTON_PRESS && - event->button.button <= 3) { - - AudioRegionView* rv; +bool +Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) +{ + nframes_t where = event_frame (event, 0, 0); - switch (item_type) { - case StreamItem: - case RegionItem: - case AutomationTrackItem: - set_selected_track_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true, true); - break; + track_canvas.grab_focus(); - case AudioRegionViewNameHighlight: - case AudioRegionViewName: - rv = reinterpret_cast (gtk_object_get_data(GTK_OBJECT(item), "regionview")); - default: - break; - } + if (session && session->actively_recording()) { + return true; } -#endif + button_selection (item, event, item_type); + if (drag_info.item == 0 && (Keyboard::is_delete_event (&event->button) || Keyboard::is_context_menu_event (&event->button) || Keyboard::is_edit_event (&event->button))) { /* handled by button release */ - return TRUE; + return true; } switch (event->button.button) { @@ -381,7 +405,7 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite if (event->type == GDK_BUTTON_PRESS) { if (drag_info.item) { - gtk_canvas_item_ungrab (drag_info.item, event->button.time); + drag_info.item->ungrab (event->button.time); } /* single mouse clicks on any of these item types operate @@ -394,7 +418,7 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite case EditCursorItem: case PlayheadCursorItem: start_cursor_grab (item, event); - return TRUE; + return true; case MarkerItem: if (Keyboard::modifier_state_equals (event->button.state, @@ -403,29 +427,38 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite } else { start_marker_grab (item, event); } - return TRUE; + return true; case TempoMarkerItem: - start_tempo_marker_grab (item, event); - return TRUE; + if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) { + start_tempo_marker_copy_grab (item, event); + } else { + start_tempo_marker_grab (item, event); + } + return true; case MeterMarkerItem: - start_meter_marker_grab (item, event); - return TRUE; + if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) { + start_meter_marker_copy_grab (item, event); + } else { + start_meter_marker_grab (item, event); + } + return true; case TempoBarItem: - return TRUE; + return true; case MeterBarItem: - return TRUE; + return true; case RangeMarkerBarItem: start_range_markerbar_op (item, event, CreateRangeMarker); - return TRUE; + return true; break; + case TransportMarkerBarItem: start_range_markerbar_op (item, event, CreateTransportMarker); - return TRUE; + return true; break; default: @@ -463,14 +496,13 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite default: start_selection_op (item, event, CreateSelection); } - return TRUE; + return true; break; case MouseObject: - if (Keyboard::modifier_state_contains (event->button.state, - Keyboard::ModifierMask(Keyboard::Control|Keyboard::Alt)) - && event->type == GDK_BUTTON_PRESS) { - + if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::Control|Keyboard::Alt)) && + event->type == GDK_BUTTON_PRESS) { + start_rubberband_select (item, event); } else if (event->type == GDK_BUTTON_PRESS) { @@ -478,11 +510,11 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite switch (item_type) { case FadeInHandleItem: start_fade_in_grab (item, event); - return TRUE; + return true; case FadeOutHandleItem: start_fade_out_grab (item, event); - return TRUE; + return true; case RegionItem: if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) { @@ -494,29 +526,29 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite } break; - case AudioRegionViewNameHighlight: + case RegionViewNameHighlight: start_trim (item, event); - return TRUE; + return true; break; - case AudioRegionViewName: + case RegionViewName: /* rename happens on edit clicks */ start_trim (clicked_regionview->get_name_highlight(), event); - return TRUE; + return true; break; case GainAutomationControlPointItem: case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: start_control_point_grab (item, event); - return TRUE; + return true; break; case GainAutomationLineItem: case PanAutomationLineItem: case RedirectAutomationLineItem: start_line_grab_from_line (item, event); - return TRUE; + return true; break; case StreamItem: @@ -527,19 +559,19 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite /* */ case ImageFrameHandleStartItem: imageframe_start_handle_op(item, event) ; - return(TRUE) ; + return(true) ; break ; case ImageFrameHandleEndItem: imageframe_end_handle_op(item, event) ; - return(TRUE) ; + return(true) ; break ; case MarkerViewHandleStartItem: markerview_item_start_handle_op(item, event) ; - return(TRUE) ; + return(true) ; break ; case MarkerViewHandleEndItem: markerview_item_end_handle_op(item, event) ; - return(TRUE) ; + return(true) ; break ; /* */ @@ -552,11 +584,15 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite break ; /* */ + case MarkerBarItem: + + break; + default: break; } } - return TRUE; + return true; break; case MouseGain: @@ -567,23 +603,23 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite case GainControlPointItem: start_control_point_grab (item, event); - return TRUE; + return true; case GainLineItem: start_line_grab_from_line (item, event); - return TRUE; + return true; case GainAutomationControlPointItem: case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: start_control_point_grab (item, event); - return TRUE; + return true; break; default: break; } - return TRUE; + return true; break; switch (item_type) { @@ -608,7 +644,7 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite default: break; } - return TRUE; + return true; break; case MouseZoom: @@ -616,7 +652,7 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite start_mouse_zoom (item, event); } - return TRUE; + return true; break; case MouseTimeFX: @@ -651,7 +687,7 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: start_control_point_grab (item, event); - return TRUE; + return true; break; default: @@ -661,14 +697,14 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite switch (item_type) { - case AudioRegionViewNameHighlight: + case RegionViewNameHighlight: start_trim (item, event); - return TRUE; + return true; break; - case AudioRegionViewName: + case RegionViewName: start_trim (clicked_regionview->get_name_highlight(), event); - return TRUE; + return true; break; default: @@ -681,7 +717,7 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite if (event->type == GDK_BUTTON_PRESS) { /* relax till release */ } - return TRUE; + return true; break; @@ -691,7 +727,7 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite } else { temporal_zoom_to_frame (true, event_frame(event)); } - return TRUE; + return true; break; default: @@ -718,6 +754,7 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::Alt))) { scroll_backward (0.6f); + return true; } else if (Keyboard::no_modifier_keys_pressed (&event->button)) { scroll_tracks_up_line (); @@ -725,8 +762,7 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) { if (clicked_trackview) { if (!current_stepping_trackview) { - TimeoutSig t; - step_timeout = t.connect (mem_fun(*this, &Editor::track_height_step_timeout), 500); + step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500); current_stepping_trackview = clicked_trackview; } gettimeofday (&last_track_height_step_timestamp, 0); @@ -755,6 +791,7 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::Alt))) { scroll_forward (0.6f); + return true; } else if (Keyboard::no_modifier_keys_pressed (&event->button)) { scroll_tracks_down_line (); @@ -762,8 +799,7 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) { if (clicked_trackview) { if (!current_stepping_trackview) { - TimeoutSig t; - step_timeout = t.connect (mem_fun(*this, &Editor::track_height_step_timeout), 500); + step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500); current_stepping_trackview = clicked_trackview; } gettimeofday (&last_track_height_step_timestamp, 0); @@ -780,18 +816,19 @@ Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType ite break; } - return FALSE; + + return false; } -gint -Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) +bool +Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { - jack_nframes_t where = event_frame (event, 0, 0); + nframes_t where = event_frame (event, 0, 0); /* no action if we're recording */ if (session && session->actively_recording()) { - return TRUE; + return true; } /* first, see if we're finishing a drag ... */ @@ -799,10 +836,12 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i if (drag_info.item) { if (end_grab (item, event)) { /* grab dragged, so do nothing else */ - return TRUE; + return true; } } + button_selection (item, event, item_type); + /* edit events get handled here */ if (drag_info.item == 0 && Keyboard::is_edit_event (&event->button)) { @@ -819,7 +858,7 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i edit_meter_marker (item); break; - case AudioRegionViewName: + case RegionViewName: if (clicked_regionview->name_active()) { return mouse_rename_region (item, event); } @@ -828,7 +867,7 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i default: break; } - return TRUE; + return true; } /* context menu events get handled here */ @@ -854,8 +893,8 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i break; case RegionItem: - case AudioRegionViewNameHighlight: - case AudioRegionViewName: + case RegionViewNameHighlight: + case RegionViewName: popup_track_context_menu (1, event->button.time, item_type, false, where); break; @@ -911,7 +950,7 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i break; } - return TRUE; + return true; } } @@ -929,7 +968,7 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i break; case MarkerItem: - remove_marker (item, event); + remove_marker (*item, event); break; case RegionItem: @@ -953,7 +992,7 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i default: break; } - return TRUE; + return true; } switch (event->button.button) { @@ -970,25 +1009,25 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i case RedirectAutomationLineItem: case StartSelectionTrimItem: case EndSelectionTrimItem: - return TRUE; + return true; case MarkerBarItem: if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (where, 0, true); } mouse_add_new_marker (where); - return TRUE; + return true; case TempoBarItem: if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (where); } mouse_add_new_tempo_event (where); - return TRUE; + return true; case MeterBarItem: mouse_add_new_meter_event (pixel_to_frame (event->button.x)); - return TRUE; + return true; break; default: @@ -1004,7 +1043,7 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i event, where, event->button.y); - return TRUE; + return true; break; default: @@ -1013,16 +1052,20 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i break; case MouseGain: + // Gain only makes sense for audio regions + if ( ! dynamic_cast(clicked_regionview)) + break; + switch (item_type) { case RegionItem: - clicked_regionview->add_gain_point_event (item, event); - return TRUE; + dynamic_cast(clicked_regionview)->add_gain_point_event (item, event); + return true; break; case AutomationTrackItem: dynamic_cast(clicked_trackview)-> add_automation_event (item, event, where, event->button.y); - return TRUE; + return true; break; default: break; @@ -1044,7 +1087,7 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i } - return TRUE; + return true; break; @@ -1061,7 +1104,7 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i } else { // Button2 click is unused } - return TRUE; + return true; break; @@ -1073,7 +1116,7 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i case MouseRange: // x_style_paste (where, 1.0); - return TRUE; + return true; break; default: @@ -1088,36 +1131,11 @@ Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType i default: break; } - return FALSE; + return false; } -void -Editor::maybe_autoscroll (GdkEvent* event) -{ - jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit); - jack_nframes_t rightmost_frame = leftmost_frame + one_page; - - jack_nframes_t frame = drag_info.current_pointer_frame; - - if (autoscroll_timeout_tag < 0) { - if (frame > rightmost_frame) { - if (rightmost_frame < max_frames) { - start_canvas_autoscroll (1); - } - } else if (frame < leftmost_frame) { - if (leftmost_frame > 0) { - start_canvas_autoscroll (-1); - } - } - } else { - if (frame >= leftmost_frame && frame < rightmost_frame) { - stop_canvas_autoscroll (); - } - } -} - -gint -Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) +bool +Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { ControlPoint* cp; Marker * marker; @@ -1126,13 +1144,13 @@ Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) switch (item_type) { case GainControlPointItem: if (mouse_mode == MouseGain) { - cp = reinterpret_cast(gtk_object_get_data (GTK_OBJECT(item), "control_point")); + cp = static_cast(item->get_data ("control_point")); cp->set_visible (true); double at_x, at_y; at_x = cp->get_x(); at_y = cp->get_y (); - gtk_canvas_item_i2w (cp->item, &at_x, &at_y); + cp->item->i2w (at_x, at_y); at_x += 20.0; at_y += 20.0; @@ -1142,7 +1160,7 @@ Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) show_verbose_canvas_cursor (); if (is_drawable()) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), fader_cursor); + track_canvas.get_window()->set_cursor (*fader_cursor); } } break; @@ -1150,13 +1168,13 @@ Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) case GainAutomationControlPointItem: case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: - cp = reinterpret_cast(gtk_object_get_data (GTK_OBJECT(item), "control_point")); + cp = static_cast(item->get_data ("control_point")); cp->set_visible (true); double at_x, at_y; at_x = cp->get_x(); at_y = cp->get_y (); - gtk_canvas_item_i2w (cp->item, &at_x, &at_y); + cp->item->i2w (at_x, at_y); at_x += 20.0; at_y += 20.0; @@ -1166,15 +1184,17 @@ Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) show_verbose_canvas_cursor (); if (is_drawable()) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), fader_cursor); + track_canvas.get_window()->set_cursor (*fader_cursor); } break; case GainLineItem: if (mouse_mode == MouseGain) { - gtk_canvas_item_set (item, "fill_color_rgba", color_map[cEnteredGainLine], NULL); + ArdourCanvas::Line *line = dynamic_cast (item); + if (line) + line->property_fill_color_rgba() = color_map[cEnteredGainLine]; if (is_drawable()) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), fader_cursor); + track_canvas.get_window()->set_cursor (*fader_cursor); } } break; @@ -1182,15 +1202,19 @@ Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) case GainAutomationLineItem: case RedirectAutomationLineItem: case PanAutomationLineItem: - gtk_canvas_item_set (item, "fill_color_rgba", color_map[cEnteredAutomationLine], NULL); + { + ArdourCanvas::Line *line = dynamic_cast (item); + if (line) + line->property_fill_color_rgba() = color_map[cEnteredAutomationLine]; + } if (is_drawable()) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), fader_cursor); + track_canvas.get_window()->set_cursor (*fader_cursor); } break; - case AudioRegionViewNameHighlight: + case RegionViewNameHighlight: if (is_drawable() && mouse_mode == MouseObject) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), trimmer_cursor); + track_canvas.get_window()->set_cursor (*trimmer_cursor); } break; @@ -1204,24 +1228,24 @@ Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) /* */ if (is_drawable()) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), trimmer_cursor); + track_canvas.get_window()->set_cursor (*trimmer_cursor); } break; case EditCursorItem: case PlayheadCursorItem: if (is_drawable()) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), grabber_cursor); + track_canvas.get_window()->set_cursor (*grabber_cursor); } break; - case AudioRegionViewName: + case RegionViewName: /* when the name is not an active item, the entire name highlight is for trimming */ - if (!reinterpret_cast (gtk_object_get_data(GTK_OBJECT(item), "regionview"))->name_active()) { + if (!reinterpret_cast (item->get_data ("regionview"))->name_active()) { if (mouse_mode == MouseObject && is_drawable()) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), trimmer_cursor); + track_canvas.get_window()->set_cursor (*trimmer_cursor); } } break; @@ -1229,7 +1253,7 @@ Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) case AutomationTrackItem: if (is_drawable()) { - GdkCursor *cursor; + Gdk::Cursor *cursor; switch (mouse_mode) { case MouseRange: cursor = selector_cursor; @@ -1242,10 +1266,10 @@ Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) break; } - gdk_window_set_cursor (track_canvas_scroller.get_window(), cursor); + track_canvas.get_window()->set_cursor (*cursor); AutomationTimeAxisView* atv; - if ((atv = static_cast(gtk_object_get_data(GTK_OBJECT(item), "trackview"))) != 0) { + if ((atv = static_cast(item->get_data ("trackview"))) != 0) { clear_entered_track = false; set_entered_track (atv); } @@ -1258,12 +1282,12 @@ Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) case MeterBarItem: case TempoBarItem: if (is_drawable()) { - gdk_window_set_cursor (time_canvas_scroller.get_window(), timebar_cursor); + time_canvas.get_window()->set_cursor (*timebar_cursor); } break; case MarkerItem: - if ((marker = static_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + if ((marker = static_cast (item->get_data ("marker"))) == 0) { break; } marker->set_color_rgba (color_map[cEnteredMarker]); @@ -1271,13 +1295,17 @@ Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) case MeterMarkerItem: case TempoMarkerItem: if (is_drawable()) { - gdk_window_set_cursor (time_canvas_scroller.get_window(), timebar_cursor); + time_canvas.get_window()->set_cursor (*timebar_cursor); } break; case FadeInHandleItem: case FadeOutHandleItem: if (mouse_mode == MouseObject) { - gtk_canvas_item_set (item, "fill_color_rgba", 0, "outline_pixels", 1, NULL); + ArdourCanvas::SimpleRect *rect = dynamic_cast (item); + if (rect) { + rect->property_fill_color_rgba() = 0; + rect->property_outline_pixels() = 1; + } } break; @@ -1310,17 +1338,17 @@ Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) break; } - return FALSE; + return false; } -gint -Editor::leave_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) +bool +Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { AutomationLine* al; ControlPoint* cp; Marker *marker; Location *loc; - AudioRegionView* rv; + RegionView* rv; bool is_start; switch (item_type) { @@ -1328,7 +1356,7 @@ Editor::leave_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) case GainAutomationControlPointItem: case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: - cp = reinterpret_cast(gtk_object_get_data (GTK_OBJECT(item), "control_point")); + cp = reinterpret_cast(item->get_data ("control_point")); if (cp->line.npoints() > 1) { if (!cp->selected) { cp->set_visible (false); @@ -1336,13 +1364,13 @@ Editor::leave_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) } if (is_drawable()) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); + track_canvas.get_window()->set_cursor (*current_canvas_cursor); } hide_verbose_canvas_cursor (); break; - case AudioRegionViewNameHighlight: + case RegionViewNameHighlight: case StartSelectionTrimItem: case EndSelectionTrimItem: case EditCursorItem: @@ -1354,7 +1382,7 @@ Editor::leave_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) case MarkerViewHandleEndItem: /* */ if (is_drawable()) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); + track_canvas.get_window()->set_cursor (*current_canvas_cursor); } break; @@ -1362,18 +1390,22 @@ Editor::leave_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) case GainAutomationLineItem: case RedirectAutomationLineItem: case PanAutomationLineItem: - al = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item),"line")); - gtk_canvas_item_set (item, "fill_color_rgba", al->get_line_color(), NULL); + al = reinterpret_cast (item->get_data ("line")); + { + ArdourCanvas::Line *line = dynamic_cast (item); + if (line) + line->property_fill_color_rgba() = al->get_line_color(); + } if (is_drawable()) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); + track_canvas.get_window()->set_cursor (*current_canvas_cursor); } break; - case AudioRegionViewName: + case RegionViewName: /* see enter_handler() for notes */ - if (!reinterpret_cast (gtk_object_get_data(GTK_OBJECT(item), "regionview"))->name_active()) { + if (!reinterpret_cast (item->get_data ("regionview"))->name_active()) { if (is_drawable() && mouse_mode == MouseObject) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); + track_canvas.get_window()->set_cursor (*current_canvas_cursor); } } break; @@ -1384,12 +1416,12 @@ Editor::leave_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) case TempoBarItem: case MarkerBarItem: if (is_drawable()) { - gdk_window_set_cursor (time_canvas_scroller.get_window(), timebar_cursor); + time_canvas.get_window()->set_cursor (*timebar_cursor); } break; case MarkerItem: - if ((marker = static_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + if ((marker = static_cast (item->get_data ("marker"))) == 0) { break; } loc = find_location_from_marker (marker, is_start); @@ -1399,23 +1431,28 @@ Editor::leave_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) case TempoMarkerItem: if (is_drawable()) { - gdk_window_set_cursor (time_canvas_scroller.get_window(), timebar_cursor); + time_canvas.get_window()->set_cursor (*timebar_cursor); } break; case FadeInHandleItem: case FadeOutHandleItem: - rv = static_cast(gtk_object_get_data (GTK_OBJECT(item), "regionview")); - gtk_canvas_item_set (item, "fill_color_rgba", rv->get_fill_color(), "outline_pixels", 0, NULL); + rv = static_cast(item->get_data ("regionview")); + { + ArdourCanvas::SimpleRect *rect = dynamic_cast (item); + if (rect) { + rect->property_fill_color_rgba() = rv->get_fill_color(); + rect->property_outline_pixels() = 0; + } + } break; case AutomationTrackItem: if (is_drawable()) { - gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); - + track_canvas.get_window()->set_cursor (*current_canvas_cursor); clear_entered_track = true; - Main::idle.connect (mem_fun(*this, &Editor::left_automation_track)); + Glib::signal_idle().connect (mem_fun(*this, &Editor::left_automation_track)); } break; @@ -1423,7 +1460,7 @@ Editor::leave_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) break; } - return FALSE; + return false; } gint @@ -1433,11 +1470,11 @@ Editor::left_automation_track () set_entered_track (0); clear_entered_track = false; } - return FALSE; + return false; } -gint -Editor::motion_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) +bool +Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type, bool from_autoscroll) { gint x, y; @@ -1450,7 +1487,7 @@ Editor::motion_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type 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 */ @@ -1460,21 +1497,23 @@ Editor::motion_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type if (session && session->actively_recording()) { /* Sorry. no dragging stuff around while we record */ - return TRUE; + return true; } + drag_info.item_type = item_type; drag_info.current_pointer_frame = event_frame (event, &drag_info.current_pointer_x, &drag_info.current_pointer_y); - if (drag_info.item) { - /* item != 0 is the best test i can think of for - dragging. + + if (!from_autoscroll && drag_info.item) { + /* item != 0 is the best test i can think of for dragging. */ - if (!drag_info.move_threshold_passsed) - { - drag_info.move_threshold_passsed = (abs ((int) (drag_info.current_pointer_x - drag_info.grab_x)) > 4); + if (!drag_info.move_threshold_passed) { + drag_info.move_threshold_passed = (abs ((int) (drag_info.current_pointer_x - drag_info.grab_x)) > 4); + // and change the initial grab loc/frame if this drag info wants us to - if (drag_info.want_move_threshold && drag_info.move_threshold_passsed) { + + if (drag_info.want_move_threshold && drag_info.move_threshold_passed) { drag_info.grab_frame = drag_info.current_pointer_frame; drag_info.grab_x = drag_info.current_pointer_x; drag_info.grab_y = drag_info.current_pointer_y; @@ -1494,7 +1533,7 @@ Editor::motion_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type case PanAutomationControlPointItem: case TempoMarkerItem: case MeterMarkerItem: - case AudioRegionViewNameHighlight: + case RegionViewNameHighlight: case StartSelectionTrimItem: case EndSelectionTrimItem: case SelectionItem: @@ -1510,14 +1549,16 @@ Editor::motion_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type case MarkerViewHandleStartItem: case MarkerViewHandleEndItem: /* */ - if (drag_info.item && (event->motion.state & GDK_BUTTON1_MASK || - (event->motion.state & GDK_BUTTON2_MASK))) { - maybe_autoscroll (event); - (this->*(drag_info.motion_callback)) (item, event); - goto handled; - } - goto not_handled; - + if (drag_info.item && (event->motion.state & Gdk::BUTTON1_MASK || + (event->motion.state & Gdk::BUTTON2_MASK))) { + if (!from_autoscroll) { + maybe_autoscroll (event); + } + (this->*(drag_info.motion_callback)) (item, event); + goto handled; + } + goto not_handled; + default: break; } @@ -1529,7 +1570,9 @@ Editor::motion_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type case MouseTimeFX: if (drag_info.item && (event->motion.state & GDK_BUTTON1_MASK || (event->motion.state & GDK_BUTTON2_MASK))) { - maybe_autoscroll (event); + if (!from_autoscroll) { + maybe_autoscroll (event); + } (this->*(drag_info.motion_callback)) (item, event); goto handled; } @@ -1541,15 +1584,16 @@ Editor::motion_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type } handled: - track_canvas_motion (item, event); - return TRUE; + track_canvas_motion (event); + // drag_info.last_pointer_frame = drag_info.current_pointer_frame; + return true; not_handled: - return FALSE; + return false; } void -Editor::start_grab (GdkEvent* event, GdkCursor *cursor) +Editor::start_grab (GdkEvent* event, Gdk::Cursor *cursor) { if (drag_info.item == 0) { fatal << _("programming error: start_grab called without drag item") << endmsg; @@ -1564,9 +1608,16 @@ Editor::start_grab (GdkEvent* event, GdkCursor *cursor) // if dragging with button2, the motion is x constrained, with Alt-button2 it is y constrained if (event->button.button == 2) { - drag_info.x_constrained = true; + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Alt)) { + drag_info.y_constrained = true; + drag_info.x_constrained = false; + } else { + drag_info.y_constrained = false; + drag_info.x_constrained = true; + } } else { drag_info.x_constrained = false; + drag_info.y_constrained = false; } drag_info.grab_frame = event_frame(event, &drag_info.grab_x, &drag_info.grab_y); @@ -1577,15 +1628,14 @@ Editor::start_grab (GdkEvent* event, GdkCursor *cursor) drag_info.cumulative_x_drag = 0; drag_info.cumulative_y_drag = 0; drag_info.first_move = true; - drag_info.move_threshold_passsed = false; + drag_info.move_threshold_passed = false; drag_info.want_move_threshold = false; drag_info.pointer_frame_offset = 0; drag_info.brushing = false; drag_info.copied_location = 0; - gtk_canvas_item_grab (drag_info.item, - Gdk::POINTER_MOTION_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK, - cursor, + drag_info.item->grab (Gdk::POINTER_MOTION_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK, + *cursor, event->button.time); if (session && session->transport_rolling()) { @@ -1606,8 +1656,21 @@ Editor::start_grab (GdkEvent* event, GdkCursor *cursor) } } +void +Editor::swap_grab (ArdourCanvas::Item* new_item, Gdk::Cursor* cursor, uint32_t time) +{ + drag_info.item->ungrab (0); + drag_info.item = new_item; + + if (cursor == 0) { + cursor = grabber_cursor; + } + + drag_info.item->grab (Gdk::POINTER_MOTION_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK, *cursor, time); +} + bool -Editor::end_grab (GtkCanvasItem* item, GdkEvent* event) +Editor::end_grab (ArdourCanvas::Item* item, GdkEvent* event) { bool did_drag = false; @@ -1617,7 +1680,7 @@ Editor::end_grab (GtkCanvasItem* item, GdkEvent* event) return false; } - gtk_canvas_item_ungrab (drag_info.item, event->button.time); + drag_info.item->ungrab (event->button.time); if (drag_info.finished_callback) { (this->*(drag_info.finished_callback)) (item, event); @@ -1649,7 +1712,7 @@ Editor::end_grab (GtkCanvasItem* item, GdkEvent* event) void Editor::set_edit_cursor (GdkEvent* event) { - jack_nframes_t pointer_frame = event_frame (event); + nframes_t pointer_frame = event_frame (event); if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { if (snap_type != SnapToEditCursor) { @@ -1664,7 +1727,7 @@ Editor::set_edit_cursor (GdkEvent* event) void Editor::set_playhead_cursor (GdkEvent* event) { - jack_nframes_t pointer_frame = event_frame (event); + nframes_t pointer_frame = event_frame (event); if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (pointer_frame); @@ -1676,7 +1739,7 @@ Editor::set_playhead_cursor (GdkEvent* event) } void -Editor::start_fade_in_grab (GtkCanvasItem* item, GdkEvent* event) +Editor::start_fade_in_grab (ArdourCanvas::Item* item, GdkEvent* event) { drag_info.item = item; drag_info.motion_callback = &Editor::fade_in_drag_motion_callback; @@ -1684,24 +1747,24 @@ Editor::start_fade_in_grab (GtkCanvasItem* item, GdkEvent* event) start_grab (event); - if ((drag_info.data = (gtk_object_get_data (GTK_OBJECT(item), "regionview"))) == 0) { + if ((drag_info.data = (item->get_data ("regionview"))) == 0) { fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg; /*NOTREACHED*/ } AudioRegionView* arv = static_cast(drag_info.data); - drag_info.pointer_frame_offset = drag_info.grab_frame - ((jack_nframes_t) arv->region.fade_in().back()->when + arv->region.position()); + drag_info.pointer_frame_offset = drag_info.grab_frame - ((nframes_t) arv->audio_region()->fade_in().back()->when + arv->region()->position()); } void -Editor::fade_in_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::fade_in_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { AudioRegionView* arv = static_cast(drag_info.data); - jack_nframes_t pos; - jack_nframes_t fade_length; + nframes_t pos; + nframes_t fade_length; - if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { + if ((int32_t)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; } else { @@ -1711,62 +1774,79 @@ Editor::fade_in_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (pos); } - - if (pos < (arv->region.position() + 64)) { + + if (pos < (arv->region()->position() + 64)) { fade_length = 64; // this should be a minimum defined somewhere - } else if (pos > arv->region.last_frame()) { - fade_length = arv->region.length(); + } else if (pos > arv->region()->last_frame()) { + fade_length = arv->region()->length(); } else { - fade_length = pos - arv->region.position(); - } + fade_length = pos - arv->region()->position(); + } + /* mapover the region selection */ + + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + + AudioRegionView* tmp = dynamic_cast (*i); + + if (!tmp) { + continue; + } - arv->reset_fade_in_shape_width (fade_length); + tmp->reset_fade_in_shape_width (fade_length); + } - show_verbose_duration_cursor (arv->region.position(), arv->region.position() + fade_length, 10); + show_verbose_duration_cursor (arv->region()->position(), arv->region()->position() + fade_length, 10); drag_info.first_move = false; } void -Editor::fade_in_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::fade_in_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { - if (drag_info.first_move) return; - AudioRegionView* arv = static_cast(drag_info.data); - jack_nframes_t pos; - jack_nframes_t fade_length; + nframes_t pos; + nframes_t fade_length; - if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { + if (drag_info.first_move) return; + + if ((int32_t)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; - } - else { + } else { pos = 0; } - if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { - snap_to (pos); - } - - if (pos < (arv->region.position() + 64)) { + if (pos < (arv->region()->position() + 64)) { fade_length = 64; // this should be a minimum defined somewhere + } else if (pos > arv->region()->last_frame()) { + fade_length = arv->region()->length(); + } else { + fade_length = pos - arv->region()->position(); } - else if (pos > arv->region.last_frame()) { - fade_length = arv->region.length(); - } - else { - fade_length = pos - arv->region.position(); + + begin_reversible_command (_("change fade in length")); + + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + + AudioRegionView* tmp = dynamic_cast (*i); + + if (!tmp) { + continue; + } + + AutomationList& alist = tmp->audio_region()->fade_in(); + XMLNode &before = alist.get_state(); + + tmp->audio_region()->set_fade_in_length (fade_length); + + XMLNode &after = alist.get_state(); + session->add_command(new MementoCommand(alist, &before, &after)); } - begin_reversible_command (_("change fade in length")); - session->add_undo (arv->region.get_memento()); - arv->region.set_fade_in_length (fade_length); - session->add_redo_no_execute (arv->region.get_memento()); commit_reversible_command (); - fade_in_drag_motion_callback (item, event); } void -Editor::start_fade_out_grab (GtkCanvasItem* item, GdkEvent* event) +Editor::start_fade_out_grab (ArdourCanvas::Item* item, GdkEvent* event) { drag_info.item = item; drag_info.motion_callback = &Editor::fade_out_drag_motion_callback; @@ -1774,22 +1854,22 @@ Editor::start_fade_out_grab (GtkCanvasItem* item, GdkEvent* event) start_grab (event); - if ((drag_info.data = (gtk_object_get_data (GTK_OBJECT(item), "regionview"))) == 0) { + if ((drag_info.data = (item->get_data ("regionview"))) == 0) { fatal << _("programming error: fade out canvas item has no regionview data pointer!") << endmsg; /*NOTREACHED*/ } AudioRegionView* arv = static_cast(drag_info.data); - drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region.length() - (jack_nframes_t) arv->region.fade_out().back()->when + arv->region.position()); + drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region()->length() - (nframes_t) arv->audio_region()->fade_out().back()->when + arv->region()->position()); } void -Editor::fade_out_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::fade_out_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { AudioRegionView* arv = static_cast(drag_info.data); - jack_nframes_t pos; - jack_nframes_t fade_length; + nframes_t pos; + nframes_t fade_length; if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -1801,32 +1881,43 @@ Editor::fade_out_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (pos); } - - if (pos > (arv->region.last_frame() - 64)) { + + if (pos > (arv->region()->last_frame() - 64)) { fade_length = 64; // this should really be a minimum fade defined somewhere } - else if (pos < arv->region.position()) { - fade_length = arv->region.length(); + else if (pos < arv->region()->position()) { + fade_length = arv->region()->length(); } else { - fade_length = arv->region.last_frame() - pos; + fade_length = arv->region()->last_frame() - pos; } + + /* mapover the region selection */ + + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + + AudioRegionView* tmp = dynamic_cast (*i); + + if (!tmp) { + continue; + } - arv->reset_fade_out_shape_width (fade_length); + tmp->reset_fade_out_shape_width (fade_length); + } - show_verbose_duration_cursor (arv->region.last_frame() - fade_length, arv->region.last_frame(), 10); + show_verbose_duration_cursor (arv->region()->last_frame() - fade_length, arv->region()->last_frame(), 10); drag_info.first_move = false; } void -Editor::fade_out_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::fade_out_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { if (drag_info.first_move) return; AudioRegionView* arv = static_cast(drag_info.data); - jack_nframes_t pos; - jack_nframes_t fade_length; + nframes_t pos; + nframes_t fade_length; if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -1839,27 +1930,40 @@ Editor::fade_out_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) snap_to (pos); } - if (pos > (arv->region.last_frame() - 64)) { + if (pos > (arv->region()->last_frame() - 64)) { fade_length = 64; // this should really be a minimum fade defined somewhere } - else if (pos < arv->region.position()) { - fade_length = arv->region.length(); + else if (pos < arv->region()->position()) { + fade_length = arv->region()->length(); } else { - fade_length = arv->region.last_frame() - pos; + fade_length = arv->region()->last_frame() - pos; } begin_reversible_command (_("change fade out length")); - session->add_undo (arv->region.get_memento()); - arv->region.set_fade_out_length (fade_length); - session->add_redo_no_execute (arv->region.get_memento()); - commit_reversible_command (); - fade_out_drag_motion_callback (item, event); + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + + AudioRegionView* tmp = dynamic_cast (*i); + + if (!tmp) { + continue; + } + + AutomationList& alist = tmp->audio_region()->fade_out(); + XMLNode &before = alist.get_state(); + + tmp->audio_region()->set_fade_out_length (fade_length); + + XMLNode &after = alist.get_state(); + session->add_command(new MementoCommand(alist, &before, &after)); + } + + commit_reversible_command (); } void -Editor::start_cursor_grab (GtkCanvasItem* item, GdkEvent* event) +Editor::start_cursor_grab (ArdourCanvas::Item* item, GdkEvent* event) { drag_info.item = item; drag_info.motion_callback = &Editor::cursor_drag_motion_callback; @@ -1867,15 +1971,17 @@ Editor::start_cursor_grab (GtkCanvasItem* item, GdkEvent* event) start_grab (event); - if ((drag_info.data = (gtk_object_get_data (GTK_OBJECT(item), "cursor"))) == 0) { + 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; - if (session && cursor == playhead_cursor) { - if (drag_info.was_rolling) { + if (cursor == playhead_cursor) { + _dragging_playhead = true; + + if (session && drag_info.was_rolling) { session->request_stop (); } } @@ -1886,10 +1992,10 @@ Editor::start_cursor_grab (GtkCanvasItem* item, GdkEvent* event) } void -Editor::cursor_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::cursor_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { Cursor* cursor = (Cursor *) drag_info.data; - jack_nframes_t adjusted_frame; + nframes_t adjusted_frame; if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -1910,6 +2016,8 @@ Editor::cursor_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) if (cursor == edit_cursor) { edit_cursor_clock.set (cursor->current_frame); + } else { + UpdateAllTransportClocks (cursor->current_frame); } show_verbose_time_cursor (cursor->current_frame, 10); @@ -1919,17 +2027,19 @@ Editor::cursor_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) } void -Editor::cursor_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::cursor_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { if (drag_info.first_move) return; cursor_drag_motion_callback (item, event); + + _dragging_playhead = false; - if (item == playhead_cursor->canvas_item) { + if (item == &playhead_cursor->canvas_item) { if (session) { session->request_locate (playhead_cursor->current_frame, drag_info.was_rolling); } - } else if (item == edit_cursor->canvas_item) { + } else if (item == &edit_cursor->canvas_item) { edit_cursor->set_position (edit_cursor->current_frame); edit_cursor_clock.set (edit_cursor->current_frame); } @@ -1942,21 +2052,22 @@ Editor::update_marker_drag_item (Location *location) double x2 = frame_to_pixel (location->end()); if (location->is_mark()) { - marker_drag_line_points->coords[0] = x1; - marker_drag_line_points->coords[2] = x1; - gtk_canvas_item_set (marker_drag_line, "points", marker_drag_line_points, NULL); + 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 { - gtk_canvas_item_set (range_marker_drag_rect, "x1", x1, "x2", x2, NULL); + range_marker_drag_rect->property_x1() = x1; + range_marker_drag_rect->property_x2() = x2; } } void -Editor::start_marker_grab (GtkCanvasItem* item, GdkEvent* event) +Editor::start_marker_grab (ArdourCanvas::Item* item, GdkEvent* event) { Marker* marker; - if ((marker = static_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + if ((marker = static_cast (item->get_data ("marker"))) == 0) { fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; /*NOTREACHED*/ } @@ -1974,16 +2085,16 @@ Editor::start_marker_grab (GtkCanvasItem* item, GdkEvent* event) 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); if (location->is_mark()) { - gtk_canvas_item_show (marker_drag_line); - gtk_canvas_item_raise_to_top (marker_drag_line); + marker_drag_line->show(); + marker_drag_line->raise_to_top(); } else { - gtk_canvas_item_show (range_marker_drag_rect); - gtk_canvas_item_raise_to_top (range_marker_drag_rect); + range_marker_drag_rect->show(); + range_marker_drag_rect->raise_to_top(); } if (is_start) show_verbose_time_cursor (location->start(), 10); @@ -1991,30 +2102,33 @@ Editor::start_marker_grab (GtkCanvasItem* item, GdkEvent* event) } void -Editor::marker_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { - jack_nframes_t f_delta; + nframes_t f_delta; Marker* marker = (Marker *) drag_info.data; Location *real_location; Location *copy_location; bool is_start; bool move_both = false; - jack_nframes_t newframe; + + nframes_t newframe; if (drag_info.pointer_frame_offset <= (long) drag_info.current_pointer_frame) { newframe = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; } else { newframe = 0; } - - jack_nframes_t next = newframe; + + nframes_t next = newframe; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (newframe, 0, true); } - if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) return; + if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) { + return; + } /* call this to find out if its the start or end */ @@ -2030,31 +2144,39 @@ Editor::marker_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) move_both = true; } - if (is_start) { // start marker + if (copy_location->is_mark()) { + /* 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 (newframe); - } else { // end marker + } else { - 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 (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); + } - } else if (newframe > 0) { - snap_to (next, -1, true); - copy_location->set_start (next); - copy_location->set_end (newframe); + } else { // end marker + + 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); + + } else if (newframe > 0) { + snap_to (next, -1, true); + copy_location->set_start (next); + copy_location->set_end (newframe); + } } } @@ -2070,7 +2192,7 @@ Editor::marker_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) } void -Editor::marker_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { if (drag_info.first_move) { marker_drag_motion_callback (item, event); @@ -2079,22 +2201,36 @@ Editor::marker_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) 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) { - location->set (drag_info.copied_location->start(), drag_info.copied_location->end()); + 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()); + } } + + XMLNode &after = session->locations()->get_state(); + session->add_command(new MementoCommand(*(session->locations()), &before, &after)); + commit_reversible_command (); - gtk_canvas_item_hide (marker_drag_line); - gtk_canvas_item_hide (range_marker_drag_rect); + marker_drag_line->hide(); + range_marker_drag_rect->hide(); } void -Editor::start_meter_marker_grab (GtkCanvasItem* item, GdkEvent* event) +Editor::start_meter_marker_grab (ArdourCanvas::Item* item, GdkEvent* event) { Marker* marker; MeterMarker* meter_marker; - if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + if ((marker = reinterpret_cast (item->get_data ("marker"))) == 0) { fatal << _("programming error: meter marker canvas item has no marker object pointer!") << endmsg; /*NOTREACHED*/ } @@ -2120,10 +2256,43 @@ Editor::start_meter_marker_grab (GtkCanvasItem* item, GdkEvent* event) } void -Editor::meter_marker_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::start_meter_marker_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) +{ + Marker* marker; + MeterMarker* meter_marker; + + if ((marker = reinterpret_cast (item->get_data ("marker"))) == 0) { + fatal << _("programming error: meter marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + meter_marker = dynamic_cast (marker); + + // create a dummy marker for visual representation of moving the copy. + // The actual copying is not done before we reach the finish callback. + char name[64]; + snprintf (name, sizeof(name), "%g/%g", meter_marker->meter().beats_per_bar(), meter_marker->meter().note_divisor ()); + MeterMarker* new_marker = new MeterMarker(*this, *meter_group, color_map[cMeterMarker], name, + *new MeterSection(meter_marker->meter())); + + drag_info.item = &new_marker->the_item(); + drag_info.copy = true; + drag_info.data = new_marker; + drag_info.motion_callback = &Editor::meter_marker_drag_motion_callback; + drag_info.finished_callback = &Editor::meter_marker_drag_finished_callback; + + start_grab (event); + + drag_info.pointer_frame_offset = drag_info.grab_frame - meter_marker->meter().frame(); + + show_verbose_time_cursor (drag_info.current_pointer_frame, 10); +} + +void +Editor::meter_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { MeterMarker* marker = (MeterMarker *) drag_info.data; - jack_nframes_t adjusted_frame; + nframes_t adjusted_frame; if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2148,11 +2317,11 @@ Editor::meter_marker_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) } void -Editor::meter_marker_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::meter_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { if (drag_info.first_move) return; - meter_marker_drag_motion_callback (item, event); + meter_marker_drag_motion_callback (drag_info.item, event); MeterMarker* marker = (MeterMarker *) drag_info.data; BBT_Time when; @@ -2160,20 +2329,34 @@ Editor::meter_marker_drag_finished_callback (GtkCanvasItem* item, GdkEvent* even TempoMap& map (session->tempo_map()); map.bbt_time (drag_info.last_pointer_frame, when); - begin_reversible_command (_("move meter mark")); - session->add_undo (map.get_memento()); - map.move_meter (marker->meter(), when); - session->add_redo_no_execute (map.get_memento()); - commit_reversible_command (); + if (drag_info.copy == true) { + begin_reversible_command (_("copy meter mark")); + XMLNode &before = map.get_state(); + map.add_meter (marker->meter(), when); + XMLNode &after = map.get_state(); + session->add_command(new MementoCommand(map, &before, &after)); + commit_reversible_command (); + + // delete the dummy marker we used for visual representation of copying. + // a new visual marker will show up automatically. + delete marker; + } else { + begin_reversible_command (_("move meter mark")); + XMLNode &before = map.get_state(); + map.move_meter (marker->meter(), when); + XMLNode &after = map.get_state(); + session->add_command(new MementoCommand(map, &before, &after)); + commit_reversible_command (); + } } void -Editor::start_tempo_marker_grab (GtkCanvasItem* item, GdkEvent* event) +Editor::start_tempo_marker_grab (ArdourCanvas::Item* item, GdkEvent* event) { Marker* marker; TempoMarker* tempo_marker; - if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "tempo_marker"))) == 0) { + if ((marker = reinterpret_cast (item->get_data ("marker"))) == 0) { fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg; /*NOTREACHED*/ } @@ -2201,10 +2384,46 @@ Editor::start_tempo_marker_grab (GtkCanvasItem* item, GdkEvent* event) } void -Editor::tempo_marker_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::start_tempo_marker_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) +{ + Marker* marker; + TempoMarker* tempo_marker; + + if ((marker = reinterpret_cast (item->get_data ("marker"))) == 0) { + fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + if ((tempo_marker = dynamic_cast (marker)) == 0) { + fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg; + /*NOTREACHED*/ + } + + // create a dummy marker for visual representation of moving the copy. + // The actual copying is not done before we reach the finish callback. + char name[64]; + snprintf (name, sizeof (name), "%.2f", tempo_marker->tempo().beats_per_minute()); + TempoMarker* new_marker = new TempoMarker(*this, *tempo_group, color_map[cTempoMarker], name, + *new TempoSection(tempo_marker->tempo())); + + drag_info.item = &new_marker->the_item(); + drag_info.copy = true; + drag_info.data = new_marker; + drag_info.motion_callback = &Editor::tempo_marker_drag_motion_callback; + drag_info.finished_callback = &Editor::tempo_marker_drag_finished_callback; + + start_grab (event); + + drag_info.pointer_frame_offset = drag_info.grab_frame - tempo_marker->tempo().frame(); + + show_verbose_time_cursor (drag_info.current_pointer_frame, 10); +} + +void +Editor::tempo_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { TempoMarker* marker = (TempoMarker *) drag_info.data; - jack_nframes_t adjusted_frame; + nframes_t adjusted_frame; if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2230,31 +2449,45 @@ Editor::tempo_marker_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) } void -Editor::tempo_marker_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::tempo_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { if (drag_info.first_move) return; - tempo_marker_drag_motion_callback (item, event); + tempo_marker_drag_motion_callback (drag_info.item, event); TempoMarker* marker = (TempoMarker *) drag_info.data; BBT_Time when; TempoMap& map (session->tempo_map()); map.bbt_time (drag_info.last_pointer_frame, when); - - begin_reversible_command (_("move tempo mark")); - session->add_undo (map.get_memento()); - map.move_tempo (marker->tempo(), when); - session->add_redo_no_execute (map.get_memento()); - commit_reversible_command (); + + if (drag_info.copy == true) { + begin_reversible_command (_("copy tempo mark")); + XMLNode &before = map.get_state(); + map.add_tempo (marker->tempo(), when); + XMLNode &after = map.get_state(); + session->add_command (new MementoCommand(map, &before, &after)); + commit_reversible_command (); + + // delete the dummy marker we used for visual representation of copying. + // a new visual marker will show up automatically. + delete marker; + } else { + begin_reversible_command (_("move tempo mark")); + XMLNode &before = map.get_state(); + map.move_tempo (marker->tempo(), when); + XMLNode &after = map.get_state(); + session->add_command (new MementoCommand(map, &before, &after)); + commit_reversible_command (); + } } void -Editor::remove_gain_control_point (GtkCanvasItem*item, GdkEvent* event) +Editor::remove_gain_control_point (ArdourCanvas::Item*item, GdkEvent* event) { ControlPoint* control_point; - if ((control_point = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "control_point"))) == 0) { + if ((control_point = reinterpret_cast (item->get_data ("control_point"))) == 0) { fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg; /*NOTREACHED*/ } @@ -2269,11 +2502,11 @@ Editor::remove_gain_control_point (GtkCanvasItem*item, GdkEvent* event) } void -Editor::remove_control_point (GtkCanvasItem*item, GdkEvent* event) +Editor::remove_control_point (ArdourCanvas::Item*item, GdkEvent* event) { ControlPoint* control_point; - if ((control_point = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "control_point"))) == 0) { + if ((control_point = reinterpret_cast (item->get_data ("control_point"))) == 0) { fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg; /*NOTREACHED*/ } @@ -2282,11 +2515,11 @@ Editor::remove_control_point (GtkCanvasItem*item, GdkEvent* event) } void -Editor::start_control_point_grab (GtkCanvasItem* item, GdkEvent* event) +Editor::start_control_point_grab (ArdourCanvas::Item* item, GdkEvent* event) { ControlPoint* control_point; - if ((control_point = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "control_point"))) == 0) { + if ((control_point = reinterpret_cast (item->get_data ("control_point"))) == 0) { fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg; /*NOTREACHED*/ } @@ -2298,7 +2531,7 @@ Editor::start_control_point_grab (GtkCanvasItem* item, GdkEvent* event) start_grab (event, fader_cursor); - control_point->line.start_drag (control_point, 0); + control_point->line.start_drag (control_point, drag_info.grab_frame, 0); float fraction = 1.0 - (control_point->get_y() / control_point->line.height()); set_verbose_canvas_cursor (control_point->line.get_verbose_cursor_string (fraction), @@ -2308,7 +2541,7 @@ Editor::start_control_point_grab (GtkCanvasItem* item, GdkEvent* event) } void -Editor::control_point_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { ControlPoint* cp = reinterpret_cast (drag_info.data); @@ -2318,29 +2551,23 @@ Editor::control_point_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event drag_info.cumulative_x_drag = cx - drag_info.grab_x ; drag_info.cumulative_y_drag = cy - drag_info.grab_y ; - bool x_constrained = false; - if (drag_info.x_constrained) { - if (fabs(drag_info.cumulative_x_drag) < fabs(drag_info.cumulative_y_drag)) { - cx = drag_info.grab_x; - x_constrained = true; - - } else { - cy = drag_info.grab_y; - } - - } + cx = drag_info.grab_x; + } + if (drag_info.y_constrained) { + cy = drag_info.grab_y; + } - gtk_canvas_item_w2i (cp->line.parent_group(), &cx, &cy); + cp->line.parent_group().w2i (cx, cy); cx = max (0.0, cx); cy = max (0.0, cy); cy = min ((double) cp->line.height(), cy); //translate cx to frames - jack_nframes_t cx_frames = (jack_nframes_t) floor (cx * frames_per_unit); + nframes_t cx_frames = unit_to_frame (cx); - if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()) && !x_constrained) { + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()) && !drag_info.x_constrained) { snap_to (cx_frames); } @@ -2357,22 +2584,36 @@ Editor::control_point_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event cp->line.point_drag (*cp, cx_frames , fraction, push); set_verbose_canvas_cursor_text (cp->line.get_verbose_cursor_string (fraction)); + + drag_info.first_move = false; } void -Editor::control_point_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::control_point_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { ControlPoint* cp = reinterpret_cast (drag_info.data); - control_point_drag_motion_callback (item, event); + + if (drag_info.first_move) { + + /* just a click */ + + if ((event->type == GDK_BUTTON_RELEASE) && (event->button.button == 1) && Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) { + reset_point_selection (); + } + + } else { + control_point_drag_motion_callback (item, event); + } cp->line.end_drag (cp); } void -Editor::start_line_grab_from_regionview (GtkCanvasItem* item, GdkEvent* event) +Editor::start_line_grab_from_regionview (ArdourCanvas::Item* item, GdkEvent* event) { switch (mouse_mode) { case MouseGain: - start_line_grab (clicked_regionview->get_gain_line(), event); + assert(dynamic_cast(clicked_regionview)); + start_line_grab (dynamic_cast(clicked_regionview)->get_gain_line(), event); break; default: break; @@ -2380,11 +2621,11 @@ Editor::start_line_grab_from_regionview (GtkCanvasItem* item, GdkEvent* event) } void -Editor::start_line_grab_from_line (GtkCanvasItem* item, GdkEvent* event) +Editor::start_line_grab_from_line (ArdourCanvas::Item* item, GdkEvent* event) { AutomationLine* al; - if ((al = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "line"))) == 0) { + if ((al = reinterpret_cast (item->get_data ("line"))) == 0) { fatal << _("programming error: line canvas item has no line pointer!") << endmsg; /*NOTREACHED*/ } @@ -2397,7 +2638,7 @@ Editor::start_line_grab (AutomationLine* line, GdkEvent* event) { double cx; double cy; - jack_nframes_t frame_within_region; + nframes_t frame_within_region; /* need to get x coordinate in terms of parent (TimeAxisItemView) origin. @@ -2405,8 +2646,8 @@ Editor::start_line_grab (AutomationLine* line, GdkEvent* event) cx = event->button.x; cy = event->button.y; - gtk_canvas_item_w2i (line->parent_group(), &cx, &cy); - frame_within_region = (jack_nframes_t) floor (cx * frames_per_unit); + line->parent_group().w2i (cx, cy); + frame_within_region = (nframes_t) floor (cx * frames_per_unit); if (!line->control_points_adjacent (frame_within_region, current_line_drag_info.before, current_line_drag_info.after)) { @@ -2414,7 +2655,7 @@ Editor::start_line_grab (AutomationLine* line, GdkEvent* event) return; } - drag_info.item = line->grab_item(); + drag_info.item = &line->grab_item(); drag_info.data = line; drag_info.motion_callback = &Editor::line_drag_motion_callback; drag_info.finished_callback = &Editor::line_drag_finished_callback; @@ -2423,7 +2664,7 @@ Editor::start_line_grab (AutomationLine* line, GdkEvent* event) double fraction = 1.0 - (cy / line->height()); - line->start_drag (0, fraction); + 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); @@ -2431,13 +2672,13 @@ Editor::start_line_grab (AutomationLine* line, GdkEvent* event) } void -Editor::line_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::line_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { AutomationLine* line = reinterpret_cast (drag_info.data); double cx = drag_info.current_pointer_x; double cy = drag_info.current_pointer_y; - gtk_canvas_item_w2i (line->parent_group(), &cx, &cy); + line->parent_group().w2i (cx, cy); double fraction; fraction = 1.0 - (cy / line->height()); @@ -2456,7 +2697,7 @@ Editor::line_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) } void -Editor::line_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::line_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { AutomationLine* line = reinterpret_cast (drag_info.data); line_drag_motion_callback (item, event); @@ -2464,9 +2705,9 @@ Editor::line_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) } void -Editor::start_region_grab (GtkCanvasItem* item, GdkEvent* event) +Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event) { - if (selection->audio_regions.empty() || clicked_regionview == 0) { + if (selection->regions.empty() || clicked_regionview == 0) { return; } @@ -2480,13 +2721,13 @@ Editor::start_region_grab (GtkCanvasItem* item, GdkEvent* event) double speed = 1.0; TimeAxisView* tvp = clicked_trackview; - AudioTimeAxisView* tv = dynamic_cast(tvp); + RouteTimeAxisView* tv = dynamic_cast(tvp); if (tv && tv->is_audio_track()) { speed = tv->get_diskstream()->speed(); } - drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed); + drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; drag_info.last_trackview = &clicked_regionview->get_time_axis_view(); // we want a move threshold @@ -2498,70 +2739,20 @@ Editor::start_region_grab (GtkCanvasItem* item, GdkEvent* event) } void -Editor::start_region_copy_grab (GtkCanvasItem* item, GdkEvent* event) +Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) { - if (selection->audio_regions.empty() || clicked_regionview == 0) { - return; - } - - /* this is committed in the grab finished callback. */ - - begin_reversible_command (_("Drag region copy")); - - /* duplicate the region(s) */ - - vector new_regionviews; - - for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { - AudioRegionView* rv; - - rv = (*i); - - Playlist* to_playlist = rv->region.playlist(); - AudioTimeAxisView* atv = dynamic_cast(&rv->get_time_axis_view()); - - session->add_undo (to_playlist->get_memento ()); - latest_regionview = 0; - - sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); - - /* create a new region with the same name. - */ - - AudioRegion* newregion = new AudioRegion (rv->region); - - /* if the original region was locked, we don't care */ - - newregion->set_locked (false); - - to_playlist->add_region (*newregion, (jack_nframes_t) (rv->region.position() * atv->get_diskstream()->speed())); - - c.disconnect (); - - if (latest_regionview) { - new_regionviews.push_back (latest_regionview); - } - - } - - if (new_regionviews.empty()) { + if (selection->regions.empty() || clicked_regionview == 0) { return; } - /* reset selection to new regionviews */ - - selection->set (new_regionviews); - - drag_info.item = new_regionviews.front()->get_canvas_group (); drag_info.copy = true; - drag_info.data = new_regionviews.front(); - drag_info.motion_callback = &Editor::region_drag_motion_callback; - drag_info.finished_callback = &Editor::region_drag_finished_callback; + drag_info.item = item; + drag_info.data = clicked_regionview; start_grab(event); TimeAxisView* tv = &clicked_regionview->get_time_axis_view(); - AudioTimeAxisView* atv = dynamic_cast(tv); + RouteTimeAxisView* atv = dynamic_cast(tv); double speed = 1.0; if (atv && atv->is_audio_track()) { @@ -2569,20 +2760,19 @@ Editor::start_region_copy_grab (GtkCanvasItem* item, GdkEvent* event) } drag_info.last_trackview = &clicked_regionview->get_time_axis_view(); - drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed); + drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; // we want a move threshold 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); - - begin_reversible_command (_("copy region(s)")); } void -Editor::start_region_brush_grab (GtkCanvasItem* item, GdkEvent* event) +Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event) { - if (selection->audio_regions.empty() || clicked_regionview == 0) { + if (selection->regions.empty() || clicked_regionview == 0) { return; } @@ -2596,13 +2786,13 @@ Editor::start_region_brush_grab (GtkCanvasItem* item, GdkEvent* event) double speed = 1.0; TimeAxisView* tvp = clicked_trackview; - AudioTimeAxisView* tv = dynamic_cast(tvp); + RouteTimeAxisView* tv = dynamic_cast(tvp); if (tv && tv->is_audio_track()) { speed = tv->get_diskstream()->speed(); } - drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed); + drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; drag_info.last_trackview = &clicked_regionview->get_time_axis_view(); // we want a move threshold @@ -2613,18 +2803,91 @@ Editor::start_region_brush_grab (GtkCanvasItem* item, GdkEvent* event) } void -Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { double x_delta; double y_delta = 0; - AudioRegionView *rv = reinterpret_cast (drag_info.data); - jack_nframes_t pending_region_position = 0; + RegionView* rv = reinterpret_cast (drag_info.data); + nframes_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; vector height_list(512) ; vector::iterator j; + if (drag_info.copy && drag_info.move_threshold_passed && drag_info.want_move_threshold) { + + drag_info.want_move_threshold = false; // don't copy again + + /* this is committed in the grab finished callback. */ + + begin_reversible_command (_("Drag region copy")); + + /* duplicate the region(s) */ + + vector new_regionviews; + + set > affected_playlists; + pair >::iterator,bool> insert_result; + + for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { + RegionView* rv; + + rv = (*i); + + boost::shared_ptr to_playlist = rv->region()->playlist(); + RouteTimeAxisView* atv = dynamic_cast(&rv->get_time_axis_view()); + + insert_result = affected_playlists.insert (to_playlist); + if (insert_result.second) { + session->add_command (new MementoCommand(*to_playlist, &to_playlist->get_state(), 0)); + } + + latest_regionview = 0; + + sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); + + /* create a new region with the same name. */ + + // FIXME: ew. need a (virtual) Region::duplicate() or something? + + boost::shared_ptr newregion; + boost::shared_ptr ar; + + if ((ar = boost::dynamic_pointer_cast(rv->region())) != 0) { + newregion = RegionFactory::create (ar); + } + assert(newregion != 0); + + /* if the original region was locked, we don't care */ + + newregion->set_locked (false); + + to_playlist->add_region (newregion, (nframes_t) (rv->region()->position() * atv->get_diskstream()->speed())); + + c.disconnect (); + + if (latest_regionview) { + new_regionviews.push_back (latest_regionview); + } + } + + + + if (new_regionviews.empty()) { + return; + } + + /* reset selection to new regionviews */ + + selection->set (new_regionviews); + + /* 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); + } + /* Which trackview is this ? */ TimeAxisView* tvp = trackview_by_y_position (drag_info.current_pointer_y); @@ -2657,7 +2920,8 @@ Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) if ((pointer_y_span = (drag_info.last_trackview->order - tv->order)) != 0) { int32_t children = 0, numtracks = 0; - bitset <512> tracks (0x00); + // XXX hard coding track limit, oh my, so very very bad + bitset <1024> tracks (0x00); /* get a bitmask representing the visible tracks */ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { @@ -2713,16 +2977,15 @@ Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) } } - for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { - AudioRegionView* rv2; - rv2 = (*i); + for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { + RegionView* rv2 = (*i); double ix1, ix2, iy1, iy2; int32_t n = 0; - gtk_canvas_item_get_bounds (rv2->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2); - gtk_canvas_item_i2w (rv2->get_canvas_group(), &ix1, &iy1); + rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); + rv2->get_canvas_group()->i2w (ix1, iy1); TimeAxisView* tvp2 = trackview_by_y_position (iy1); - AudioTimeAxisView* atv2 = dynamic_cast(tvp2); + RouteTimeAxisView* atv2 = dynamic_cast(tvp2); if (atv2->order != original_pointer_order) { /* this isn't the pointer track */ @@ -2807,18 +3070,18 @@ Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) the region would be if we moved it by that much. */ - if (drag_info.move_threshold_passsed) { + if (drag_info.move_threshold_passed) { if ((int32_t)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { - jack_nframes_t sync_frame; - jack_nframes_t sync_offset; + nframes_t sync_frame; + nframes_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 = rv->region()->sync_offset (sync_dir); + sync_frame = rv->region()->adjust_to_sync (pending_region_position); /* we snap if the snap modifier is not enabled. */ @@ -2837,7 +3100,7 @@ Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) pending_region_position = 0; } - if (pending_region_position > max_frames - rv->region.length()) { + if (pending_region_position > max_frames - rv->region()->length()) { pending_region_position = drag_info.last_frame_position; } @@ -2879,18 +3142,15 @@ Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) } if (x_delta < 0) { - for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { - AudioRegionView* rv2; - rv2 = (*i); + RegionView* rv2 = (*i); - /* if any regionview is at zero, we need to know so we can - stop further leftward motion. - */ + // If any regionview is at zero, we need to know so we can stop further leftward motion. double ix1, ix2, iy1, iy2; - gtk_canvas_item_get_bounds (rv2->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2); - gtk_canvas_item_i2w (rv2->get_canvas_group(), &ix1, &iy1); + rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); + rv2->get_canvas_group()->i2w (ix1, iy1); if (ix1 <= 1) { x_delta = 0; @@ -2903,12 +3163,12 @@ Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) MOTION ************************************************************/ - pair::iterator,bool> insert_result; + pair >::iterator,bool> insert_result; + const list& layered_regions = selection->regions.by_layer(); - for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + for (list::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) { - AudioRegionView* rv; - rv = (*i); + RegionView* rv = (*i); double ix1, ix2, iy1, iy2; int32_t temp_pointer_y_span = pointer_y_span; @@ -2917,8 +3177,8 @@ Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) the parent. */ - gtk_canvas_item_get_bounds (rv->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2); - gtk_canvas_item_i2w (rv->get_canvas_group(), &ix1, &iy1); + rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); + rv->get_canvas_group()->i2w (ix1, iy1); TimeAxisView* tvp2 = trackview_by_y_position (iy1); AudioTimeAxisView* canvas_atv = dynamic_cast(tvp2); AudioTimeAxisView* temp_atv; @@ -2989,15 +3249,15 @@ Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) 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(); + } 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); + 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 @@ -3005,9 +3265,9 @@ Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) on the top, since its parent is the whole canvas. */ - gtk_canvas_item_raise_to_top (rv->get_canvas_group()); - gtk_canvas_item_raise_to_top (rv->get_time_axis_view().canvas_display); - gtk_canvas_item_raise_to_top (cursor_group); + rv->get_canvas_group()->raise_to_top(); + rv->get_time_axis_view().canvas_display->raise_to_top(); + cursor_group->raise_to_top(); /* freeze the playlists from notifying till the motion is done. @@ -3015,17 +3275,18 @@ Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) AudioTimeAxisView* atv = dynamic_cast (&rv->get_time_axis_view()); if (atv && atv->is_audio_track()) { - AudioPlaylist* pl = atv->get_diskstream()->playlist(); + boost::shared_ptr pl = boost::dynamic_pointer_cast(atv->get_diskstream()->playlist()); if (pl) { /* only freeze and capture state once */ insert_result = motion_frozen_playlists.insert (pl); if (insert_result.second) { pl->freeze(); - session->add_undo(pl->get_memento()); + session->add_command(new MementoCommand(*pl, &pl->get_state(), 0)); } } } + rv->region()->set_opaque(false); } if (drag_info.brushing) { @@ -3036,7 +3297,7 @@ Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) } if (drag_info.first_move) { - gtk_canvas_item_raise_to_top (cursor_group); + cursor_group->raise_to_top(); } drag_info.first_move = false; @@ -3048,14 +3309,14 @@ Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) } void -Editor::region_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { - jack_nframes_t where; - AudioRegionView* rv = reinterpret_cast (drag_info.data); - pair::iterator,bool> insert_result; + nframes_t where; + RegionView* rv = reinterpret_cast (drag_info.data); + pair >::iterator,bool> insert_result; bool nocommit = true; double speed; - AudioTimeAxisView* atv; + RouteTimeAxisView* atv; bool regionview_y_movement; bool regionview_x_movement; @@ -3089,7 +3350,7 @@ Editor::region_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) speed = atv->get_diskstream()->speed(); } - regionview_x_movement = (drag_info.last_frame_position != (jack_nframes_t) (rv->region.position()/speed)); + regionview_x_movement = (drag_info.last_frame_position != (nframes_t) (rv->region()->position()/speed)); regionview_y_movement = (drag_info.last_trackview != &rv->get_time_axis_view()); //printf ("last_frame: %s position is %lu %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed); @@ -3099,13 +3360,13 @@ Editor::region_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) /* motion between tracks */ - list new_selection; + list new_selection; /* moved to a different audio track. */ - for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ) { + for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) { - AudioRegionView* rv2 = (*i); + RegionView* rv2 = (*i); /* 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, @@ -3122,19 +3383,21 @@ Editor::region_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) /* first, freeze the target tracks */ - for (list::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) { + for (list::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) { - Playlist* from_playlist; - Playlist* to_playlist; + boost::shared_ptr from_playlist; + boost::shared_ptr to_playlist; double ix1, ix2, iy1, iy2; - gtk_canvas_item_get_bounds ((*i)->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2); - gtk_canvas_item_i2w ((*i)->get_canvas_group(), &ix1, &iy1); + (*i)->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); + (*i)->get_canvas_group()->i2w (ix1, iy1); TimeAxisView* tvp2 = trackview_by_y_position (iy1); AudioTimeAxisView* atv2 = dynamic_cast(tvp2); + + (*i)->region()->set_opaque (true); - from_playlist = (*i)->region.playlist(); + from_playlist = (*i)->region()->playlist(); to_playlist = atv2->playlist(); /* the from_playlist was frozen in the "first_move" case @@ -3150,39 +3413,39 @@ Editor::region_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) insert_result = motion_frozen_playlists.insert(to_playlist); if (insert_result.second) { to_playlist->freeze(); - session->add_undo(to_playlist->get_memento()); + session->add_command(new MementoCommand(*to_playlist, &to_playlist->get_state(), 0)); } } /* now do it again with the actual operations */ - for (list::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) { + for (list::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) { - Playlist* from_playlist; - Playlist* to_playlist; + boost::shared_ptr from_playlist; + boost::shared_ptr to_playlist; double ix1, ix2, iy1, iy2; - gtk_canvas_item_get_bounds ((*i)->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2); - gtk_canvas_item_i2w ((*i)->get_canvas_group(), &ix1, &iy1); + (*i)->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); + (*i)->get_canvas_group()->i2w (ix1, iy1); TimeAxisView* tvp2 = trackview_by_y_position (iy1); AudioTimeAxisView* atv2 = dynamic_cast(tvp2); - from_playlist = (*i)->region.playlist(); + from_playlist = (*i)->region()->playlist(); to_playlist = atv2->playlist(); latest_regionview = 0; - where = (jack_nframes_t) (unit_to_frame (ix1) * speed); - Region* new_region = createRegion ((*i)->region); + where = (nframes_t) (unit_to_frame (ix1) * speed); + boost::shared_ptr new_region (RegionFactory::create ((*i)->region())); - from_playlist->remove_region (&((*i)->region)); - - sigc::connection c = atv2->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); - to_playlist->add_region (*new_region, where); - c.disconnect (); + from_playlist->remove_region (((*i)->region())); + sigc::connection c = atv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); + to_playlist->add_region (new_region, where); + c.disconnect (); + if (latest_regionview) { selection->add (latest_regionview); } @@ -3191,12 +3454,12 @@ Editor::region_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) } else { /* motion within a single track */ - - for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + + for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { rv = (*i); - if (rv->region.locked()) { + if (rv->region()->locked()) { continue; } @@ -3212,26 +3475,28 @@ Editor::region_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) double ix1, ix2, iy1, iy2; - gtk_canvas_item_get_bounds (rv->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2); - gtk_canvas_item_i2w (rv->get_canvas_group(), &ix1, &iy1); - where = (jack_nframes_t) (unit_to_frame (ix1) * ownspeed); + 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(); + where = rv->region()->position(); } rv->get_time_axis_view().reveal_dependent_views (*rv); + + /* no need to add an undo here, we did that when we added this playlist to motion_frozen playlists */ - session->add_undo (rv->region.playlist()->get_memento()); - rv->region.set_position (where, (void *) this); + rv->region()->set_position (where, (void *) this); + rv->region()->set_opaque (true); } } out: - for (set::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) { + for (set >::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) { (*p)->thaw (); - session->add_redo_no_execute ((*p)->get_memento()); + session->add_command (new MementoCommand(*((*p).get()), 0, & (*p)->get_state())); } motion_frozen_playlists.clear (); @@ -3258,25 +3523,27 @@ Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event) if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) { - align_region (rv.region, SyncPoint, (jack_nframes_t) (edit_cursor->current_frame * speed)); + align_region (rv.region(), SyncPoint, (nframes_t) (edit_cursor->current_frame * speed)); } else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) { - align_region (rv.region, End, (jack_nframes_t) (edit_cursor->current_frame * speed)); + align_region (rv.region(), End, (nframes_t) (edit_cursor->current_frame * speed)); } else { - align_region (rv.region, Start, (jack_nframes_t) (edit_cursor->current_frame * speed)); + align_region (rv.region(), Start, (nframes_t) (edit_cursor->current_frame * speed)); } } } void -Editor::show_verbose_time_cursor (jack_nframes_t frame, double offset, double xpos, double ypos) +Editor::show_verbose_time_cursor (nframes_t frame, double offset, double xpos, double ypos) { char buf[128]; - SMPTE_Time smpte; + SMPTE::Time smpte; BBT_Time bbt; + int hours, mins; + nframes_t frame_rate; float secs; if (session == 0) { @@ -3295,10 +3562,14 @@ Editor::show_verbose_time_cursor (jack_nframes_t frame, double offset, double xp break; case AudioClock::MinSec: - /* XXX fix this to compute min/sec properly */ - session->smpte_time (frame, smpte); - secs = smpte.seconds + ((float) smpte.frames / session->smpte_frames_per_second); - snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%.4f", smpte.hours, smpte.minutes, secs); + /* XXX this is copied from show_verbose_duration_cursor() */ + frame_rate = session->frame_rate(); + hours = frame / (frame_rate * 3600); + frame = frame % (frame_rate * 3600); + mins = frame / (frame_rate * 60); + frame = frame % (frame_rate * 60); + secs = (float) frame / (float) frame_rate; + snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%.4f", hours, mins, secs); break; default: @@ -3316,12 +3587,14 @@ Editor::show_verbose_time_cursor (jack_nframes_t frame, double offset, double xp } void -Editor::show_verbose_duration_cursor (jack_nframes_t start, jack_nframes_t end, double offset, double xpos, double ypos) +Editor::show_verbose_duration_cursor (nframes_t start, nframes_t end, double offset, double xpos, double ypos) { char buf[128]; - SMPTE_Time smpte; + SMPTE::Time smpte; BBT_Time sbbt; BBT_Time ebbt; + int hours, mins; + nframes_t distance, frame_rate; float secs; Meter meter_at_start(session->tempo_map().meter_at(start)); @@ -3362,10 +3635,15 @@ Editor::show_verbose_duration_cursor (jack_nframes_t start, jack_nframes_t end, break; case AudioClock::MinSec: - /* XXX fix this to compute min/sec properly */ - session->smpte_duration (end - start, smpte); - secs = smpte.seconds + ((float) smpte.frames / session->smpte_frames_per_second); - snprintf (buf, sizeof (buf), "%02ld:%02ld:%.4f", smpte.hours, smpte.minutes, secs); + /* XXX this stuff should be elsewhere.. */ + distance = end - start; + frame_rate = session->frame_rate(); + hours = distance / (frame_rate * 3600); + distance = distance % (frame_rate * 3600); + mins = distance / (frame_rate * 60); + distance = distance % (frame_rate * 60); + secs = (float) distance / (float) frame_rate; + snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%.4f", hours, mins, secs); break; default: @@ -3383,13 +3661,13 @@ Editor::show_verbose_duration_cursor (jack_nframes_t start, jack_nframes_t end, } void -Editor::collect_new_region_view (AudioRegionView* rv) +Editor::collect_new_region_view (RegionView* rv) { latest_regionview = rv; } void -Editor::start_selection_grab (GtkCanvasItem* item, GdkEvent* event) +Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event) { if (clicked_regionview == 0) { return; @@ -3397,7 +3675,7 @@ Editor::start_selection_grab (GtkCanvasItem* 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()) { @@ -3406,7 +3684,7 @@ Editor::start_selection_grab (GtkCanvasItem* item, GdkEvent* event) /* XXX fix me one day to use all new regions */ - Region* region = new_regions.front(); + boost::shared_ptr region (new_regions.front()); /* add it to the current stream/playlist. @@ -3416,7 +3694,7 @@ Editor::start_selection_grab (GtkCanvasItem* item, GdkEvent* event) */ latest_regionview = 0; - sigc::connection c = clicked_audio_trackview->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); + sigc::connection c = clicked_audio_trackview->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); /* A selection grab currently creates two undo/redo operations, one for creating the new region and another for moving it. @@ -3424,11 +3702,12 @@ Editor::start_selection_grab (GtkCanvasItem* item, GdkEvent* event) begin_reversible_command (_("selection grab")); - Playlist* playlist = clicked_trackview->playlist(); + boost::shared_ptr playlist = clicked_trackview->playlist(); - session->add_undo (playlist->get_memento ()); - clicked_trackview->playlist()->add_region (*region, selection->time[clicked_selection].start); - session->add_redo_no_execute (playlist->get_memento ()); + XMLNode *before = &(playlist->get_state()); + clicked_trackview->playlist()->add_region (region, selection->time[clicked_selection].start); + XMLNode *after = &(playlist->get_state()); + session->add_command(new MementoCommand(*playlist, before, after)); commit_reversible_command (); @@ -3451,7 +3730,7 @@ Editor::start_selection_grab (GtkCanvasItem* item, GdkEvent* event) start_grab (event); drag_info.last_trackview = clicked_trackview; - drag_info.last_frame_position = latest_regionview->region.position(); + drag_info.last_frame_position = latest_regionview->region()->position(); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; show_verbose_time_cursor (drag_info.last_frame_position, 10); @@ -3460,18 +3739,20 @@ Editor::start_selection_grab (GtkCanvasItem* item, GdkEvent* event) void Editor::cancel_selection () { - for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { (*i)->hide_selection (); } + begin_reversible_command (_("cancel selection")); selection->clear (); clicked_selection = 0; + commit_reversible_command (); } void -Editor::start_selection_op (GtkCanvasItem* item, GdkEvent* event, SelectionOp op) +Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, SelectionOp op) { - jack_nframes_t start = 0; - jack_nframes_t end = 0; + nframes_t start = 0; + nframes_t end = 0; if (session == 0) { return; @@ -3485,7 +3766,6 @@ Editor::start_selection_op (GtkCanvasItem* item, GdkEvent* event, SelectionOp op switch (op) { case CreateSelection: - if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) { drag_info.copy = true; } else { @@ -3495,14 +3775,18 @@ Editor::start_selection_op (GtkCanvasItem* item, GdkEvent* event, SelectionOp op break; case SelectionStartTrim: - clicked_trackview->order_selection_trims (item, true); + if (clicked_trackview) { + clicked_trackview->order_selection_trims (item, true); + } start_grab (event, trimmer_cursor); start = selection->time[clicked_selection].start; drag_info.pointer_frame_offset = drag_info.grab_frame - start; break; case SelectionEndTrim: - clicked_trackview->order_selection_trims (item, false); + if (clicked_trackview) { + clicked_trackview->order_selection_trims (item, false); + } start_grab (event, trimmer_cursor); end = selection->time[clicked_selection].end; drag_info.pointer_frame_offset = drag_info.grab_frame - end; @@ -3523,12 +3807,12 @@ Editor::start_selection_op (GtkCanvasItem* item, GdkEvent* event, SelectionOp op } void -Editor::drag_selection (GtkCanvasItem* item, GdkEvent* event) +Editor::drag_selection (ArdourCanvas::Item* item, GdkEvent* event) { - jack_nframes_t start = 0; - jack_nframes_t end = 0; - jack_nframes_t length; - jack_nframes_t pending_position; + nframes_t start = 0; + nframes_t end = 0; + nframes_t length; + nframes_t pending_position; if ((int32_t) drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { pending_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -3633,8 +3917,7 @@ Editor::drag_selection (GtkCanvasItem* item, GdkEvent* event) break; } - - if (event->button.x >= track_canvas_scroller.get_hadjustment()->get_value() + canvas_width) { + if (event->button.x >= horizontal_adjustment.get_value() + canvas_width) { start_canvas_autoscroll (1); } @@ -3653,7 +3936,7 @@ Editor::drag_selection (GtkCanvasItem* item, GdkEvent* event) } void -Editor::end_selection_op (GtkCanvasItem* item, GdkEvent* event) +Editor::end_selection_op (ArdourCanvas::Item* item, GdkEvent* event) { if (!drag_info.first_move) { drag_selection (item, event); @@ -3678,7 +3961,7 @@ Editor::end_selection_op (GtkCanvasItem* item, GdkEvent* event) } void -Editor::start_trim (GtkCanvasItem* item, GdkEvent* event) +Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event) { double speed = 1.0; TimeAxisView* tvp = clicked_trackview; @@ -3688,9 +3971,11 @@ Editor::start_trim (GtkCanvasItem* item, GdkEvent* event) speed = tv->get_diskstream()->speed(); } - jack_nframes_t region_start = (jack_nframes_t) (clicked_regionview->region.position() / speed); - jack_nframes_t region_end = (jack_nframes_t) (clicked_regionview->region.last_frame() / speed); - jack_nframes_t region_length = (jack_nframes_t) (clicked_regionview->region.length() / 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); + + motion_frozen_playlists.clear(); //drag_info.item = clicked_regionview->get_name_highlight(); drag_info.item = item; @@ -3723,15 +4008,13 @@ Editor::start_trim (GtkCanvasItem* item, GdkEvent* event) show_verbose_time_cursor(drag_info.current_pointer_frame, 10); break; } - - flush_track_canvas (); } void -Editor::trim_motion_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { - AudioRegionView* rv = clicked_regionview; - jack_nframes_t frame_delta = 0; + RegionView* rv = clicked_regionview; + nframes_t frame_delta = 0; bool left_direction; bool obey_snap = !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()); @@ -3742,7 +4025,8 @@ Editor::trim_motion_callback (GtkCanvasItem* item, GdkEvent* event) double speed = 1.0; TimeAxisView* tvp = clicked_trackview; - AudioTimeAxisView* tv = dynamic_cast(tvp); + RouteTimeAxisView* tv = dynamic_cast(tvp); + pair >::iterator,bool> insert_result; if (tv && tv->is_audio_track()) { speed = tv->get_diskstream()->speed(); @@ -3780,10 +4064,19 @@ Editor::trim_motion_callback (GtkCanvasItem* item, GdkEvent* event) begin_reversible_command (trim_type); - for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { - (*i)->region.freeze (); - (*i)->temporarily_hide_envelope (); - session->add_undo ((*i)->region.playlist()->get_memento()); + for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { + (*i)->region()->set_opaque(false); + (*i)->region()->freeze (); + + AudioRegionView* const arv = dynamic_cast(*i); + if (arv) + arv->temporarily_hide_envelope (); + + boost::shared_ptr pl = (*i)->region()->playlist(); + insert_result = motion_frozen_playlists.insert (pl); + if (insert_result.second) { + session->add_command(new MementoCommand(*pl, &pl->get_state(), 0)); + } } } @@ -3795,20 +4088,20 @@ Editor::trim_motion_callback (GtkCanvasItem* item, GdkEvent* event) switch (trim_op) { case StartTrim: - if ((left_direction == false) && (drag_info.current_pointer_frame <= rv->region.first_frame()/speed)) { + if ((left_direction == false) && (drag_info.current_pointer_frame <= rv->region()->first_frame()/speed)) { break; } else { - for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { single_start_trim (**i, frame_delta, left_direction, obey_snap); } break; } case EndTrim: - if ((left_direction == true) && (drag_info.current_pointer_frame > (jack_nframes_t) (rv->region.last_frame()/speed))) { + if ((left_direction == true) && (drag_info.current_pointer_frame > (nframes_t) (rv->region()->last_frame()/speed))) { break; } else { - for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { single_end_trim (**i, frame_delta, left_direction, obey_snap); } break; @@ -3822,8 +4115,8 @@ Editor::trim_motion_callback (GtkCanvasItem* item, GdkEvent* event) swap_direction = true; } - for (list::const_iterator i = selection->audio_regions.by_layer().begin(); - i != selection->audio_regions.by_layer().end(); ++i) + for (list::const_iterator i = selection->regions.by_layer().begin(); + i != selection->regions.by_layer().end(); ++i) { single_contents_trim (**i, frame_delta, left_direction, swap_direction, obey_snap); } @@ -3833,10 +4126,10 @@ Editor::trim_motion_callback (GtkCanvasItem* item, GdkEvent* event) switch (trim_op) { case StartTrim: - show_verbose_time_cursor((jack_nframes_t) (rv->region.position()/speed), 10); + show_verbose_time_cursor((nframes_t) (rv->region()->position()/speed), 10); break; case EndTrim: - show_verbose_time_cursor((jack_nframes_t) (rv->region.last_frame()/speed), 10); + show_verbose_time_cursor((nframes_t) (rv->region()->last_frame()/speed), 10); break; case ContentsTrim: show_verbose_time_cursor(drag_info.current_pointer_frame, 10); @@ -3848,19 +4141,19 @@ Editor::trim_motion_callback (GtkCanvasItem* item, GdkEvent* event) } void -Editor::single_contents_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap) +Editor::single_contents_trim (RegionView& rv, nframes_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap) { - Region& region (rv.region); + boost::shared_ptr region (rv.region()); - if (region.locked()) { + if (region->locked()) { return; } - jack_nframes_t new_bound; + nframes_t new_bound; double speed = 1.0; TimeAxisView* tvp = clicked_trackview; - AudioTimeAxisView* tv = dynamic_cast(tvp); + RouteTimeAxisView* tv = dynamic_cast(tvp); if (tv && tv->is_audio_track()) { speed = tv->get_diskstream()->speed(); @@ -3868,35 +4161,35 @@ Editor::single_contents_trim (AudioRegionView& rv, jack_nframes_t frame_delta, b if (left_direction) { if (swap_direction) { - new_bound = (jack_nframes_t) (region.position()/speed) + frame_delta; + new_bound = (nframes_t) (region->position()/speed) + frame_delta; } else { - new_bound = (jack_nframes_t) (region.position()/speed) - frame_delta; + new_bound = (nframes_t) (region->position()/speed) - frame_delta; } } else { if (swap_direction) { - new_bound = (jack_nframes_t) (region.position()/speed) - frame_delta; + new_bound = (nframes_t) (region->position()/speed) - frame_delta; } else { - new_bound = (jack_nframes_t) (region.position()/speed) + frame_delta; + new_bound = (nframes_t) (region->position()/speed) + frame_delta; } } if (obey_snap) { snap_to (new_bound); } - region.trim_start ((jack_nframes_t) (new_bound * speed), this); + region->trim_start ((nframes_t) (new_bound * speed), this); rv.region_changed (StartChanged); } void -Editor::single_start_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap) +Editor::single_start_trim (RegionView& rv, nframes_t frame_delta, bool left_direction, bool obey_snap) { - Region& region (rv.region); + boost::shared_ptr region (rv.region()); - if (region.locked()) { + if (region->locked()) { return; } - jack_nframes_t new_bound; + nframes_t new_bound; double speed = 1.0; TimeAxisView* tvp = clicked_trackview; @@ -3907,30 +4200,30 @@ Editor::single_start_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool } if (left_direction) { - new_bound = (jack_nframes_t) (region.position()/speed) - frame_delta; + new_bound = (nframes_t) (region->position()/speed) - frame_delta; } else { - new_bound = (jack_nframes_t) (region.position()/speed) + frame_delta; + new_bound = (nframes_t) (region->position()/speed) + frame_delta; } if (obey_snap) { snap_to (new_bound, (left_direction ? 0 : 1)); } - region.trim_front ((jack_nframes_t) (new_bound * speed), this); + region->trim_front ((nframes_t) (new_bound * speed), this); rv.region_changed (Change (LengthChanged|PositionChanged|StartChanged)); } void -Editor::single_end_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap) +Editor::single_end_trim (RegionView& rv, nframes_t frame_delta, bool left_direction, bool obey_snap) { - Region& region (rv.region); + boost::shared_ptr region (rv.region()); - if (region.locked()) { + if (region->locked()) { return; } - jack_nframes_t new_bound; + nframes_t new_bound; double speed = 1.0; TimeAxisView* tvp = clicked_trackview; @@ -3941,20 +4234,20 @@ Editor::single_end_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool l } if (left_direction) { - new_bound = (jack_nframes_t) ((region.last_frame() + 1)/speed) - frame_delta; + new_bound = (nframes_t) ((region->last_frame() + 1)/speed) - frame_delta; } else { - new_bound = (jack_nframes_t) ((region.last_frame() + 1)/speed) + frame_delta; + new_bound = (nframes_t) ((region->last_frame() + 1)/speed) + frame_delta; } if (obey_snap) { snap_to (new_bound); } - region.trim_end ((jack_nframes_t) (new_bound * speed), this); + region->trim_end ((nframes_t) (new_bound * speed), this); rv.region_changed (LengthChanged); } void -Editor::trim_finished_callback (GtkCanvasItem* item, GdkEvent* event) +Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { if (!drag_info.first_move) { trim_motion_callback (item, event); @@ -3963,26 +4256,33 @@ Editor::trim_finished_callback (GtkCanvasItem* item, GdkEvent* event) thaw_region_after_trim (*clicked_regionview); } else { - for (list::const_iterator i = selection->audio_regions.by_layer().begin(); - i != selection->audio_regions.by_layer().end(); ++i) + for (list::const_iterator i = selection->regions.by_layer().begin(); + i != selection->regions.by_layer().end(); ++i) { thaw_region_after_trim (**i); + (*i)->region()->set_opaque(true); } } + + for (set >::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) { + //(*p)->thaw (); + session->add_command (new MementoCommand(*(*p).get(), 0, &(*p)->get_state())); + } + + motion_frozen_playlists.clear (); + commit_reversible_command(); } else { /* no mouse movement */ point_trim (event); } - - flush_track_canvas (); } void Editor::point_trim (GdkEvent* event) { - AudioRegionView* rv = clicked_regionview; - jack_nframes_t new_bound = drag_info.current_pointer_frame; + RegionView* rv = clicked_regionview; + nframes_t new_bound = drag_info.current_pointer_frame; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (new_bound); @@ -3996,22 +4296,26 @@ Editor::point_trim (GdkEvent* event) if (rv->get_selected()) { - for (list::const_iterator i = selection->audio_regions.by_layer().begin(); - i != selection->audio_regions.by_layer().end(); ++i) + for (list::const_iterator i = selection->regions.by_layer().begin(); + i != selection->regions.by_layer().end(); ++i) { - if (!(*i)->region.locked()) { - session->add_undo ((*i)->region.playlist()->get_memento()); - (*i)->region.trim_front (new_bound, this); - session->add_redo_no_execute ((*i)->region.playlist()->get_memento()); + if (!(*i)->region()->locked()) { + boost::shared_ptr pl = (*i)->region()->playlist(); + XMLNode &before = pl->get_state(); + (*i)->region()->trim_front (new_bound, this); + XMLNode &after = pl->get_state(); + session->add_command(new MementoCommand(*pl.get(), &before, &after)); } } } else { - if (!rv->region.locked()) { - session->add_undo (rv->region.playlist()->get_memento()); - rv->region.trim_front (new_bound, this); - session->add_redo_no_execute (rv->region.playlist()->get_memento()); + if (!rv->region()->locked()) { + boost::shared_ptr pl = rv->region()->playlist(); + XMLNode &before = pl->get_state(); + rv->region()->trim_front (new_bound, this); + XMLNode &after = pl->get_state(); + session->add_command(new MementoCommand(*pl.get(), &before, &after)); } } @@ -4024,21 +4328,25 @@ Editor::point_trim (GdkEvent* event) if (rv->get_selected()) { - for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) + for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { - if (!(*i)->region.locked()) { - session->add_undo ((*i)->region.playlist()->get_memento()); - (*i)->region.trim_end (new_bound, this); - session->add_redo_no_execute ((*i)->region.playlist()->get_memento()); + if (!(*i)->region()->locked()) { + boost::shared_ptr pl = (*i)->region()->playlist(); + XMLNode &before = pl->get_state(); + (*i)->region()->trim_end (new_bound, this); + XMLNode &after = pl->get_state(); + session->add_command(new MementoCommand(*pl.get(), &before, &after)); } } } else { - if (!rv->region.locked()) { - session->add_undo (rv->region.playlist()->get_memento()); - rv->region.trim_end (new_bound, this); - session->add_redo_no_execute (rv->region.playlist()->get_memento()); + if (!rv->region()->locked()) { + boost::shared_ptr pl = rv->region()->playlist(); + XMLNode &before = pl->get_state(); + rv->region()->trim_end (new_bound, this); + XMLNode &after = pl->get_state(); + session->add_command (new MementoCommand(*pl.get(), &before, &after)); } } @@ -4051,27 +4359,30 @@ Editor::point_trim (GdkEvent* event) } void -Editor::thaw_region_after_trim (AudioRegionView& rv) +Editor::thaw_region_after_trim (RegionView& rv) { - Region& region (rv.region); + boost::shared_ptr region (rv.region()); - if (region.locked()) { + if (region->locked()) { return; } - region.thaw (_("trimmed region")); - session->add_redo_no_execute (region.playlist()->get_memento()); + region->thaw (_("trimmed region")); + XMLNode &after = region->playlist()->get_state(); + session->add_command (new MementoCommand(*(region->playlist()), 0, &after)); - rv.unhide_envelope (); + AudioRegionView* arv = dynamic_cast(&rv); + if (arv) + arv->unhide_envelope (); } void -Editor::hide_marker (GtkCanvasItem* item, GdkEvent* event) +Editor::hide_marker (ArdourCanvas::Item* item, GdkEvent* event) { Marker* marker; bool is_start; - if ((marker = static_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + if ((marker = static_cast (item->get_data ("marker"))) == 0) { fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; /*NOTREACHED*/ } @@ -4082,9 +4393,8 @@ Editor::hide_marker (GtkCanvasItem* item, GdkEvent* event) void -Editor::start_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event, RangeMarkerOp op) +Editor::start_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event, RangeMarkerOp op) { - if (session == 0) { return; } @@ -4117,12 +4427,11 @@ Editor::start_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event, RangeMar } void -Editor::drag_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event) +Editor::drag_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event) { - jack_nframes_t start = 0; - jack_nframes_t end = 0; - - GtkCanvasItem * crect = (range_marker_op == CreateRangeMarker) ? range_bar_drag_rect: transport_bar_drag_rect; + nframes_t start = 0; + nframes_t end = 0; + ArdourCanvas::SimpleRect *crect = (range_marker_op == CreateRangeMarker) ? range_bar_drag_rect: transport_bar_drag_rect; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (drag_info.current_pointer_frame); @@ -4150,25 +4459,24 @@ Editor::drag_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event) } /* first drag: Either add to the selection - or create a new selection-> + or create a new selection. */ if (drag_info.first_move) { temp_location->set (start, end); - gtk_canvas_item_show (crect); + crect->show (); update_marker_drag_item (temp_location); - gtk_canvas_item_show (range_marker_drag_rect); - gtk_canvas_item_raise_to_top (range_marker_drag_rect); + range_marker_drag_rect->show(); + range_marker_drag_rect->raise_to_top(); } break; } - - if (event->button.x >= track_canvas_scroller.get_hadjustment()->get_value() + canvas_width) { + if (event->button.x >= horizontal_adjustment.get_value() + canvas_width) { start_canvas_autoscroll (1); } @@ -4177,7 +4485,8 @@ Editor::drag_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event) double x1 = frame_to_pixel (start); double x2 = frame_to_pixel (end); - gtk_canvas_item_set (crect, "x1", x1, "x2", x2, NULL); + crect->property_x1() = x1; + crect->property_x2() = x2; update_marker_drag_item (temp_location); } @@ -4190,26 +4499,30 @@ Editor::drag_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event) } void -Editor::end_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event) +Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event) { Location * newloc = 0; + string rangename; if (!drag_info.first_move) { drag_range_markerbar_op (item, event); - switch (range_marker_op) - { + switch (range_marker_op) { case CreateRangeMarker: + { begin_reversible_command (_("new range marker")); - session->add_undo (session->locations()->get_memento()); - newloc = new Location(temp_location->start(), temp_location->end(), "unnamed"); + XMLNode &before = session->locations()->get_state(); + session->locations()->next_available_name(rangename,"unnamed"); + newloc = new Location(temp_location->start(), temp_location->end(), rangename, Location::IsRangeMarker); session->locations()->add (newloc, true); - session->add_redo_no_execute (session->locations()->get_memento()); + XMLNode &after = session->locations()->get_state(); + session->add_command(new MementoCommand(*(session->locations()), &before, &after)); commit_reversible_command (); - gtk_canvas_item_hide (range_bar_drag_rect); - gtk_canvas_item_hide (range_marker_drag_rect); + range_bar_drag_rect->hide(); + range_marker_drag_rect->hide(); break; + } case CreateTransportMarker: // popup menu to pick loop or punch @@ -4218,12 +4531,39 @@ Editor::end_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event) break; } } else { - /* just a click, no pointer movement.*/ + /* just a click, no pointer movement. remember that context menu stuff was handled elsewhere */ if (Keyboard::no_modifier_keys_pressed (&event->button)) { - // nothing yet + nframes_t start; + nframes_t end; + + start = session->locations()->first_mark_before (drag_info.grab_frame); + end = session->locations()->first_mark_after (drag_info.grab_frame); + + if (end == max_frames) { + end = session->current_end_frame (); + } + + if (start == 0) { + start = session->current_start_frame (); + } + + switch (mouse_mode) { + case MouseObject: + /* find the two markers on either side and then make the selection from it */ + cerr << "select between " << start << " .. " << end << endl; + select_all_within (start, end, 0.0f, FLT_MAX, Selection::Set); + break; + case MouseRange: + /* find the two markers on either side of the click and make the range out of it */ + selection->set (0, start, end); + break; + + default: + break; + } } } @@ -4233,7 +4573,7 @@ Editor::end_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event) void -Editor::start_mouse_zoom (GtkCanvasItem* item, GdkEvent* event) +Editor::start_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event) { drag_info.item = item; drag_info.motion_callback = &Editor::drag_mouse_zoom; @@ -4245,10 +4585,10 @@ Editor::start_mouse_zoom (GtkCanvasItem* item, GdkEvent* event) } void -Editor::drag_mouse_zoom (GtkCanvasItem* item, GdkEvent* event) +Editor::drag_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event) { - jack_nframes_t start; - jack_nframes_t end; + nframes_t start; + nframes_t end; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (drag_info.current_pointer_frame); @@ -4272,8 +4612,8 @@ Editor::drag_mouse_zoom (GtkCanvasItem* item, GdkEvent* event) if (start != end) { if (drag_info.first_move) { - gtk_canvas_item_show (zoom_rect); - gtk_canvas_item_raise_to_top (zoom_rect); + zoom_rect->show(); + zoom_rect->raise_to_top(); } reposition_zoom_rect(start, end); @@ -4286,7 +4626,7 @@ Editor::drag_mouse_zoom (GtkCanvasItem* item, GdkEvent* event) } void -Editor::end_mouse_zoom (GtkCanvasItem* item, GdkEvent* event) +Editor::end_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event) { if (!drag_info.first_move) { drag_mouse_zoom (item, event); @@ -4304,26 +4644,24 @@ Editor::end_mouse_zoom (GtkCanvasItem* item, GdkEvent* event) */ } - gtk_canvas_item_hide (zoom_rect); + zoom_rect->hide(); } void -Editor::reposition_zoom_rect (jack_nframes_t start, jack_nframes_t end) +Editor::reposition_zoom_rect (nframes_t start, nframes_t end) { double x1 = frame_to_pixel (start); double x2 = frame_to_pixel (end); - double y2 = canvas_height - 2; - - gtk_object_set (GTK_OBJECT(zoom_rect), - "x1", x1, - "y1", 1.0, - "x2", x2, - "y2", y2, - NULL); + double y2 = full_canvas_height - 1.0; + + zoom_rect->property_x1() = x1; + zoom_rect->property_y1() = 1.0; + zoom_rect->property_x2() = x2; + zoom_rect->property_y2() = y2; } void -Editor::start_rubberband_select (GtkCanvasItem* item, GdkEvent* event) +Editor::start_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event) { drag_info.item = item; drag_info.motion_callback = &Editor::drag_rubberband_select; @@ -4335,10 +4673,10 @@ Editor::start_rubberband_select (GtkCanvasItem* item, GdkEvent* event) } void -Editor::drag_rubberband_select (GtkCanvasItem* item, GdkEvent* event) +Editor::drag_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event) { - jack_nframes_t start; - jack_nframes_t end; + nframes_t start; + nframes_t end; double y1; double y2; @@ -4348,16 +4686,15 @@ Editor::drag_rubberband_select (GtkCanvasItem* item, GdkEvent* event) return; } -// if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { -// snap_to (drag_info.current_pointer_frame); - -// if (drag_info.first_move) { -// snap_to (drag_info.grab_frame); -// } -// } - + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + if (drag_info.first_move) { + snap_to (drag_info.grab_frame); + } + snap_to (drag_info.current_pointer_frame); + } /* base start and end on initial click position */ + if (drag_info.current_pointer_frame < drag_info.grab_frame) { start = drag_info.current_pointer_frame; end = drag_info.grab_frame; @@ -4369,8 +4706,7 @@ Editor::drag_rubberband_select (GtkCanvasItem* 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; } @@ -4381,15 +4717,13 @@ Editor::drag_rubberband_select (GtkCanvasItem* item, GdkEvent* event) double x1 = frame_to_pixel (start); double x2 = frame_to_pixel (end); - gtk_object_set (GTK_OBJECT(rubberband_rect), - "x1", x1, - "y1", y1, - "x2", x2, - "y2", y2, - NULL); - - gtk_canvas_item_show (rubberband_rect); - gtk_canvas_item_raise_to_top (rubberband_rect); + rubberband_rect->property_x1() = x1; + rubberband_rect->property_y1() = y1; + rubberband_rect->property_x2() = x2; + rubberband_rect->property_y2() = y2; + + rubberband_rect->show(); + rubberband_rect->raise_to_top(); drag_info.last_pointer_frame = drag_info.current_pointer_frame; drag_info.first_move = false; @@ -4399,7 +4733,7 @@ Editor::drag_rubberband_select (GtkCanvasItem* item, GdkEvent* event) } void -Editor::end_rubberband_select (GtkCanvasItem* item, GdkEvent* event) +Editor::end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event) { if (!drag_info.first_move) { @@ -4416,15 +4750,15 @@ Editor::end_rubberband_select (GtkCanvasItem* item, GdkEvent* event) } - bool add = Keyboard::modifier_state_contains (event->button.state, Keyboard::Shift); + Selection::Operation op = Keyboard::selection_type (event->button.state); bool commit; - begin_reversible_command (_("select regions")); + begin_reversible_command (_("rubberband selection")); if (drag_info.grab_frame < drag_info.last_pointer_frame) { - commit = select_all_within (drag_info.grab_frame, drag_info.last_pointer_frame, y1, y2, add); + commit = select_all_within (drag_info.grab_frame, drag_info.last_pointer_frame, y1, y2, op); } else { - commit = select_all_within (drag_info.last_pointer_frame, drag_info.grab_frame, y1, y2, add); + commit = select_all_within (drag_info.last_pointer_frame, drag_info.grab_frame, y1, y2, op); } if (commit) { @@ -4432,43 +4766,42 @@ Editor::end_rubberband_select (GtkCanvasItem* item, GdkEvent* event) } } else { - selection->clear_audio_regions(); + selection->clear_tracks(); + selection->clear_regions(); selection->clear_points (); selection->clear_lines (); } - gtk_canvas_item_hide (rubberband_rect); + rubberband_rect->hide(); } gint -Editor::mouse_rename_region (GtkCanvasItem* item, GdkEvent* event) +Editor::mouse_rename_region (ArdourCanvas::Item* item, GdkEvent* event) { using namespace Gtkmm2ext; ArdourPrompter prompter (false); prompter.set_prompt (_("Name for region:")); - prompter.set_initial_text (clicked_regionview->region.name()); + prompter.set_initial_text (clicked_regionview->region()->name()); + prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT); + prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false); prompter.show_all (); - prompter.done.connect (Main::quit.slot()); - - Main::run (); - - if (prompter.status == Prompter::cancelled) { - return TRUE; + switch (prompter.run ()) { + case Gtk::RESPONSE_ACCEPT: + string str; + prompter.get_result(str); + if (str.length()) { + clicked_regionview->region()->set_name (str); + } + break; } - - string str; - - prompter.get_result(str); - clicked_regionview->region.set_name (str); - - return TRUE; + return true; } void -Editor::start_time_fx (GtkCanvasItem* item, GdkEvent* event) +Editor::start_time_fx (ArdourCanvas::Item* item, GdkEvent* event) { drag_info.item = item; drag_info.motion_callback = &Editor::time_fx_motion; @@ -4480,9 +4813,9 @@ Editor::start_time_fx (GtkCanvasItem* item, GdkEvent* event) } void -Editor::time_fx_motion (GtkCanvasItem *item, GdkEvent* event) +Editor::time_fx_motion (ArdourCanvas::Item *item, GdkEvent* event) { - AudioRegionView* rv = clicked_regionview; + RegionView* rv = clicked_regionview; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (drag_info.current_pointer_frame); @@ -4492,8 +4825,8 @@ Editor::time_fx_motion (GtkCanvasItem *item, GdkEvent* event) return; } - if (drag_info.current_pointer_frame > rv->region.position()) { - rv->get_time_axis_view().show_timestretch (rv->region.position(), drag_info.current_pointer_frame); + if (drag_info.current_pointer_frame > rv->region()->position()) { + rv->get_time_axis_view().show_timestretch (rv->region()->position(), drag_info.current_pointer_frame); } drag_info.last_pointer_frame = drag_info.current_pointer_frame; @@ -4503,7 +4836,7 @@ Editor::time_fx_motion (GtkCanvasItem *item, GdkEvent* event) } void -Editor::end_time_fx (GtkCanvasItem* item, GdkEvent* event) +Editor::end_time_fx (ArdourCanvas::Item* item, GdkEvent* event) { clicked_regionview->get_time_axis_view().hide_timestretch (); @@ -4511,21 +4844,25 @@ Editor::end_time_fx (GtkCanvasItem* item, GdkEvent* event) return; } - jack_nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region.position(); - float percentage = (float) ((double) newlen - (double) clicked_regionview->region.length()) / ((double) newlen) * 100.0f; + nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region()->position(); + float percentage = (float) ((double) newlen - (double) clicked_regionview->region()->length()) / ((double) newlen) * 100.0f; begin_reversible_command (_("timestretch")); - if (run_timestretch (selection->audio_regions, percentage) == 0) { + if (run_timestretch (selection->regions, percentage) == 0) { session->commit_reversible_command (); } } void -Editor::mouse_brush_insert_region (AudioRegionView* rv, jack_nframes_t pos) +Editor::mouse_brush_insert_region (RegionView* rv, nframes_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 */ @@ -4545,26 +4882,27 @@ Editor::mouse_brush_insert_region (AudioRegionView* rv, jack_nframes_t pos) /* don't brush a copy over the original */ - if (pos == rv->region.position()) { + if (pos == rv->region()->position()) { return; } - AudioTimeAxisView* atv = dynamic_cast(&rv->get_time_axis_view()); + RouteTimeAxisView* atv = dynamic_cast(&arv->get_time_axis_view()); if (atv == 0 || !atv->is_audio_track()) { return; } - Playlist* playlist = atv->playlist(); + boost::shared_ptr playlist = atv->playlist(); double speed = atv->get_diskstream()->speed(); - session->add_undo (playlist->get_memento()); - playlist->add_region (*(new AudioRegion (rv->region)), (jack_nframes_t) (pos * speed)); - session->add_redo_no_execute (playlist->get_memento()); + XMLNode &before = playlist->get_state(); + playlist->add_region (boost::dynamic_pointer_cast (RegionFactory::create (arv->audio_region())), (nframes_t) (pos * speed)); + XMLNode &after = playlist->get_state(); + session->add_command(new MementoCommand(*playlist.get(), &before, &after)); // playlist is frozen, so we have to update manually - playlist->StateChanged (Change (~0)); /* EMIT SIGNAL */ + playlist->Modified(); /* EMIT SIGNAL */ } gint @@ -4578,7 +4916,7 @@ Editor::track_height_step_timeout () if (delta.tv_sec * 1000000 + delta.tv_usec > 250000) { /* milliseconds */ current_stepping_trackview = 0; - return FALSE; + return false; } - return TRUE; + return true; }