X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_canvas_events.cc;h=79cc1e066fcacbc0b8f5c87a5a6ca6d71e6ca89a;hb=a5de2c10679cc920a7409d02e32e6dd67778ea75;hp=0f07875eacbc38c330f3f4eca9e502dfe69e1c17;hpb=33c61757fc8352fdb1280bca28b54d1adee183ff;p=ardour.git diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index 0f07875eac..79cc1e066f 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -24,10 +24,9 @@ #include "pbd/stacktrace.h" -#include "ardour/audioplaylist.h" -#include "ardour/audioregion.h" -#include "ardour/region_factory.h" #include "ardour/midi_region.h" +#include "ardour/region_factory.h" +#include "ardour/profile.h" #include "editor.h" #include "keyboard.h" @@ -35,7 +34,6 @@ #include "audio_region_view.h" #include "audio_streamview.h" #include "canvas-noevent-text.h" -#include "crossfade_view.h" #include "audio_time_axis.h" #include "region_gain_line.h" #include "automation_line.h" @@ -68,13 +66,17 @@ Editor::track_canvas_scroll (GdkEventScroll* ev) retry: switch (direction) { case GDK_SCROLL_UP: - if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { + if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) { + //for mouse-wheel zoom, force zoom-focus to mouse + Editing::ZoomFocus temp_focus = zoom_focus; + zoom_focus = Editing::ZoomFocusMouse; temporal_zoom_step (false); + zoom_focus = temp_focus; return true; - } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) { + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) { direction = GDK_SCROLL_LEFT; goto retry; - } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) { + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) { if (!current_stepping_trackview) { step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500); std::pair const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize); @@ -93,13 +95,17 @@ Editor::track_canvas_scroll (GdkEventScroll* ev) break; case GDK_SCROLL_DOWN: - if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { + if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) { + //for mouse-wheel zoom, force zoom-focus to mouse + Editing::ZoomFocus temp_focus = zoom_focus; + zoom_focus = Editing::ZoomFocusMouse; temporal_zoom_step (true); + zoom_focus = temp_focus; return true; - } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) { + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) { direction = GDK_SCROLL_RIGHT; goto retry; - } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) { + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) { if (!current_stepping_trackview) { step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500); std::pair const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize); @@ -349,6 +355,76 @@ Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item return ret; } +bool +Editor::canvas_start_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv) +{ + if (!rv->sensitive()) { + return false; + } + + switch (event->type) { + case GDK_BUTTON_PRESS: + clicked_regionview = rv; + clicked_control_point = 0; + clicked_axisview = &rv->get_time_axis_view(); + clicked_routeview = dynamic_cast(clicked_axisview); + if (event->button.button == 3) { + return button_press_handler (item, event, StartCrossFadeItem); + } + break; + + case GDK_BUTTON_RELEASE: + if (event->button.button == 3) { + return button_release_handler (item, event, StartCrossFadeItem); + } + break; + + default: + break; + + } + + /* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/ + /* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */ + /* if we return RegionItem here then we avoid the issue until it is resolved later */ + return typed_event (item, event, RegionItem); // StartCrossFadeItem); +} + +bool +Editor::canvas_end_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv) +{ + if (!rv->sensitive()) { + return false; + } + + switch (event->type) { + case GDK_BUTTON_PRESS: + clicked_regionview = rv; + clicked_control_point = 0; + clicked_axisview = &rv->get_time_axis_view(); + clicked_routeview = dynamic_cast(clicked_axisview); + if (event->button.button == 3) { + return button_press_handler (item, event, EndCrossFadeItem); + } + break; + + case GDK_BUTTON_RELEASE: + if (event->button.button == 3) { + return button_release_handler (item, event, EndCrossFadeItem); + } + break; + + default: + break; + + } + + /* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/ + /* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */ + /* if we return RegionItem here then we avoid the issue until it is resolved later */ + return typed_event (item, event, RegionItem); // EndCrossFadeItem); +} + bool Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv) { @@ -407,6 +483,7 @@ Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, case GDK_BUTTON_RELEASE: ret = button_release_handler (item, event, FadeInHandleItem); + maybe_locate_with_edit_preroll ( rv->region()->position() ); break; case GDK_MOTION_NOTIFY: @@ -488,6 +565,7 @@ Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, case GDK_BUTTON_RELEASE: ret = button_release_handler (item, event, FadeOutHandleItem); + maybe_locate_with_edit_preroll ( rv->region()->last_frame() - rv->get_fade_out_shape_width() ); break; case GDK_MOTION_NOTIFY: @@ -517,127 +595,6 @@ struct DescendingRegionLayerSorter { } }; -bool -Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv) -{ - /* we handle only button 3 press/release events */ - - switch (event->type) { - case GDK_BUTTON_PRESS: - clicked_crossfadeview = xfv; - clicked_axisview = &clicked_crossfadeview->get_time_axis_view(); - clicked_routeview = dynamic_cast(clicked_axisview); - if (event->button.button == 3) { - return button_press_handler (item, event, CrossfadeViewItem); - } - break; - - case GDK_BUTTON_RELEASE: - if (event->button.button == 3) { - bool ret = button_release_handler (item, event, CrossfadeViewItem); - return ret; - } - break; - - default: - break; - - } - - /* XXX do not forward double clicks */ - - if (event->type == GDK_2BUTTON_PRESS) { - return false; - } - - /* proxy for an underlying regionview */ - - /* XXX really need to check if we are in the name highlight, - and proxy to that when required. - - XXX or in the trim rectangles - */ - - TimeAxisView& tv (xfv->get_time_axis_view()); - AudioTimeAxisView* atv; - - if ((atv = dynamic_cast(&tv)) != 0) { - - if (atv->is_audio_track()) { - - boost::shared_ptr pl; - if ((pl = boost::dynamic_pointer_cast (atv->track()->playlist())) != 0) { - - boost::shared_ptr rl = pl->regions_at (event_frame (event)); - if (!rl->empty()) { - - if (atv->layer_display() == Overlaid) { - - /* we're in overlaid mode; proxy to the uppermost region view */ - - DescendingRegionLayerSorter cmp; - rl->sort (cmp); - - RegionView* rv = atv->view()->find_view (rl->front()); - - /* proxy */ - return canvas_region_view_event (event, rv->get_canvas_group(), rv); - - } else { - - /* we're in stacked mode; proxy to the region view under the mouse */ - - double cx = 0; - double cy = 0; - switch (event->type) { - case GDK_BUTTON_PRESS: - case GDK_BUTTON_RELEASE: - cx = event->button.x; - cy = event->button.y; - break; - case GDK_MOTION_NOTIFY: - cx = event->motion.x; - cy = event->motion.y; - break; - case GDK_ENTER_NOTIFY: - case GDK_LEAVE_NOTIFY: - cx = event->crossing.x; - cy = event->crossing.y; - break; - default: - /* XXX: this may be wrong for some events */ - cx = event->button.x; - cy = event->button.y; - } - - /* position of the event within the track */ - atv->view()->canvas_item()->w2i (cx, cy); - - /* hence layer that we're over */ - double const c = atv->view()->child_height (); - layer_t const l = pl->top_layer () + 1 - (cy / c); - - /* hence region */ - RegionList::iterator i = rl->begin(); - while (i != rl->end() && (*i)->layer() != l) { - ++i; - } - - if (i != rl->end()) { - RegionView* rv = atv->view()->find_view (*i); - - /* proxy */ - return canvas_region_view_event (event, rv->get_canvas_group(), rv); - } - } - } - } - } - } - - return TRUE; -} - bool Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp) { @@ -991,6 +948,12 @@ Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item) return typed_event (item, event, CdMarkerBarItem); } +bool +Editor::canvas_videotl_bar_event (GdkEvent *event, ArdourCanvas::Item* item) +{ + return typed_event (item, event, VideoBarItem); +} + bool Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* /*marker*/) { @@ -1038,63 +1001,152 @@ Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item) } bool -Editor::track_canvas_drag_motion (Glib::RefPtr const & /*c*/, int x, int y, guint /*time*/) +Editor::track_canvas_drag_motion (Glib::RefPtr const& context, int x, int y, guint time) { double wx; double wy; + boost::shared_ptr region; + boost::shared_ptr region_copy; + RouteTimeAxisView* rtav; + GdkEvent event; + double px; + double py; + + string target = track_canvas->drag_dest_find_target (context, track_canvas->drag_dest_get_target_list()); + + if (target.empty()) { + return false; + } + track_canvas->window_to_world (x, y, wx, wy); - GdkEvent event; event.type = GDK_MOTION_NOTIFY; event.button.x = wx; event.button.y = wy; /* assume we're dragging with button 1 */ event.motion.state = Gdk::BUTTON1_MASK; - if (!_drags->active ()) { + (void) event_frame (&event, &px, &py); - double px; - double py; - framepos_t const pos = event_frame (&event, &px, &py); + std::pair const tv = trackview_by_y_position (py); + bool can_drop = false; + + if (tv.first != 0) { - std::pair const tv = trackview_by_y_position (py); - if (tv.first == 0) { - return true; - } + /* over a time axis view of some kind */ - RouteTimeAxisView* rtav = dynamic_cast (tv.first); - if (rtav == 0 || !rtav->is_track ()) { - return true; + rtav = dynamic_cast (tv.first); + + if (rtav != 0 && rtav->is_track ()) { + /* over a track, not a bus */ + can_drop = true; } + - boost::shared_ptr region = _regions->get_dragged_region (); + } else { + /* not over a time axis view, so drop is possible */ + can_drop = true; + } - if (!region) { + if (can_drop) { + region = _regions->get_dragged_region (); + + if (region) { + + if ((boost::dynamic_pointer_cast (region) != 0 && + dynamic_cast (tv.first) != 0) || + (boost::dynamic_pointer_cast (region) != 0 && + dynamic_cast (tv.first) != 0)) { + + /* audio to audio + OR + midi to midi + */ + + context->drag_status (context->get_suggested_action(), time); + return true; + } + } else { + /* DND originating from outside ardour + * + * TODO: check if file is audio/midi, allow drops on same track-type only, + * currently: if audio is dropped on a midi-track, it is only added to the region-list + */ + if (Profile->get_sae() || Config->get_only_copy_imported_files()) { + context->drag_status(Gdk::ACTION_COPY, time); + } else { + if ((context->get_actions() & (Gdk::ACTION_COPY | Gdk::ACTION_LINK | Gdk::ACTION_MOVE)) == Gdk::ACTION_COPY) { + context->drag_status(Gdk::ACTION_COPY, time); + } else { + context->drag_status(Gdk::ACTION_LINK, time); + } + } return true; } + } - boost::shared_ptr region_copy = RegionFactory::create (region); + /* no drop here */ + context->drag_status (Gdk::DragAction (0), time); + return false; +} - if (boost::dynamic_pointer_cast (region_copy) != 0 && - dynamic_cast (tv.first) == 0) { +void +Editor::drop_regions (const Glib::RefPtr& /*context*/, + int x, int y, + const SelectionData& /*data*/, + guint /*info*/, guint /*time*/) +{ + double wx; + double wy; + boost::shared_ptr region; + boost::shared_ptr region_copy; + RouteTimeAxisView* rtav; + GdkEvent event; + double px; + double py; - /* audio -> non-audio */ - return true; - } + track_canvas->window_to_world (x, y, wx, wy); + + event.type = GDK_MOTION_NOTIFY; + event.button.x = wx; + event.button.y = wy; + /* assume we're dragging with button 1 */ + event.motion.state = Gdk::BUTTON1_MASK; - if (boost::dynamic_pointer_cast (region_copy) == 0 && - dynamic_cast (tv.first) != 0) { + framepos_t const pos = event_frame (&event, &px, &py); - /* MIDI -> non-MIDI */ - return true; - } + std::pair const tv = trackview_by_y_position (py); - _drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event); - } + if (tv.first != 0) { - _drags->motion_handler (&event, false); + rtav = dynamic_cast (tv.first); + + if (rtav != 0 && rtav->is_track ()) { - return true; + boost::shared_ptr region = _regions->get_dragged_region (); + + if (region) { + + region_copy = RegionFactory::create (region, true); + + + if ((boost::dynamic_pointer_cast (region_copy) != 0 && + dynamic_cast (tv.first) != 0) || + (boost::dynamic_pointer_cast (region_copy) != 0 && + dynamic_cast (tv.first) != 0)) { + + /* audio to audio + OR + midi to midi + */ + + + _drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event); + _drags->end_grab (0); + } + } + } + } } bool