2 Copyright (C) 2000 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "pbd/stacktrace.h"
27 #include "ardour/audio_track.h"
28 #include "ardour/midi_track.h"
29 #include "ardour/midi_region.h"
30 #include "ardour/region_factory.h"
31 #include "ardour/profile.h"
33 #include "canvas/canvas.h"
34 #include "canvas/text.h"
35 #include "canvas/scroll_group.h"
39 #include "public_editor.h"
40 #include "audio_region_view.h"
41 #include "audio_streamview.h"
42 #include "audio_time_axis.h"
43 #include "region_gain_line.h"
44 #include "automation_line.h"
45 #include "automation_time_axis.h"
46 #include "automation_line.h"
47 #include "control_point.h"
48 #include "editor_drag.h"
49 #include "midi_time_axis.h"
50 #include "editor_regions.h"
51 #include "editor_sources.h"
52 #include "ui_config.h"
53 #include "verbose_cursor.h"
58 using namespace ARDOUR;
61 using namespace ArdourCanvas;
63 using Gtkmm2ext::Keyboard;
66 Editor::track_canvas_scroll (GdkEventScroll* ev)
68 int direction = ev->direction;
70 /* this event arrives without transformation by the canvas, so we have
71 * to transform the coordinates to be able to look things up.
74 Duple event_coords = _track_canvas->window_to_canvas (Duple (ev->x, ev->y));
78 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) {
79 if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
80 temporal_zoom_step_mouse_focus (false);
82 temporal_zoom_step (false);
85 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) {
88 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) {
89 if (!current_stepping_trackview) {
90 step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
91 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (event_coords.y, false);
92 current_stepping_trackview = p.first;
93 if (!current_stepping_trackview) {
97 last_track_height_step_timestamp = get_microseconds();
98 current_stepping_trackview->step_height (false);
101 scroll_up_one_track ();
106 case GDK_SCROLL_DOWN:
107 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) {
108 if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
109 temporal_zoom_step_mouse_focus (true);
111 temporal_zoom_step (true);
114 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) {
115 scroll_right_step ();
117 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) {
118 if (!current_stepping_trackview) {
119 step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
120 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (event_coords.y, false);
121 current_stepping_trackview = p.first;
122 if (!current_stepping_trackview) {
126 last_track_height_step_timestamp = get_microseconds();
127 current_stepping_trackview->step_height (true);
130 scroll_down_one_track ();
135 case GDK_SCROLL_LEFT:
140 case GDK_SCROLL_RIGHT:
141 scroll_right_step ();
154 Editor::canvas_scroll_event (GdkEventScroll *event, bool from_canvas)
157 boost::optional<ArdourCanvas::Rect> rulers = _time_markers_group->bounding_box();
158 if (rulers && rulers->contains (Duple (event->x, event->y))) {
159 return canvas_ruler_event ((GdkEvent*) event, timecode_ruler, TimecodeRulerItem);
163 _track_canvas->grab_focus();
164 return track_canvas_scroll (event);
168 Editor::track_canvas_button_press_event (GdkEventButton *event)
170 _track_canvas->grab_focus();
171 if (!Keyboard::is_context_menu_event (event)) {
172 begin_reversible_selection_op (X_("Clear Selection Click (track canvas)"));
174 commit_reversible_selection_op();
180 Editor::track_canvas_button_release_event (GdkEventButton *event)
182 if (!Keyboard::is_context_menu_event (event)) {
183 if (_drags->active ()) {
184 _drags->end_grab ((GdkEvent*) event);
191 Editor::track_canvas_motion_notify_event (GdkEventMotion */*event*/)
194 /* keep those motion events coming */
195 _track_canvas->get_pointer (x, y);
200 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
202 if (!session () || session()->loading () || session()->deletion_in_progress ()) {
208 switch (event->type) {
209 case GDK_BUTTON_PRESS:
210 case GDK_2BUTTON_PRESS:
211 case GDK_3BUTTON_PRESS:
212 ret = button_press_handler (item, event, type);
214 case GDK_BUTTON_RELEASE:
215 ret = button_release_handler (item, event, type);
217 case GDK_MOTION_NOTIFY:
218 ret = motion_handler (item, event);
221 case GDK_ENTER_NOTIFY:
222 ret = enter_handler (item, event, type);
225 case GDK_LEAVE_NOTIFY:
226 ret = leave_handler (item, event, type);
230 ret = key_press_handler (item, event, type);
233 case GDK_KEY_RELEASE:
234 ret = key_release_handler (item, event, type);
244 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
248 if (!rv->sensitive ()) {
252 switch (event->type) {
253 case GDK_BUTTON_PRESS:
254 case GDK_2BUTTON_PRESS:
255 case GDK_3BUTTON_PRESS:
256 clicked_regionview = rv;
257 clicked_control_point = 0;
258 clicked_axisview = &rv->get_time_axis_view();
259 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
260 ret = button_press_handler (item, event, RegionItem);
263 case GDK_BUTTON_RELEASE:
264 ret = button_release_handler (item, event, RegionItem);
267 case GDK_MOTION_NOTIFY:
268 ret = motion_handler (item, event);
271 case GDK_ENTER_NOTIFY:
272 set_entered_regionview (rv);
273 ret = enter_handler (item, event, RegionItem);
276 case GDK_LEAVE_NOTIFY:
277 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
278 set_entered_regionview (0);
279 ret = leave_handler (item, event, RegionItem);
291 Editor::canvas_wave_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
293 /* we only care about enter events here, required for mouse/cursor
294 * tracking. there is a non-linear (non-child/non-parent) relationship
295 * between various components of a regionview and so when we leave one
296 * of them (e.g. a trim handle) and enter another (e.g. the waveview)
297 * no other items get notified. enter/leave handling does not propagate
298 * in the same way as other events, so we need to catch this because
299 * entering (and leaving) the waveview is equivalent to
300 * entering/leaving the regionview (which is why it is passed in as a
303 * And in fact, we really only care about enter events.
308 if (!rv->sensitive ()) {
312 switch (event->type) {
313 case GDK_ENTER_NOTIFY:
314 set_entered_regionview (rv);
315 ret = enter_handler (item, event, WaveItem);
327 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
331 switch (event->type) {
332 case GDK_BUTTON_PRESS:
333 case GDK_2BUTTON_PRESS:
334 case GDK_3BUTTON_PRESS:
335 clicked_regionview = 0;
336 clicked_control_point = 0;
337 clicked_axisview = tv;
338 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
339 ret = button_press_handler (item, event, StreamItem);
342 case GDK_BUTTON_RELEASE:
343 ret = button_release_handler (item, event, StreamItem);
346 case GDK_MOTION_NOTIFY:
347 ret = motion_handler (item, event);
350 case GDK_ENTER_NOTIFY:
351 set_entered_track (tv);
352 ret = enter_handler (item, event, StreamItem);
355 case GDK_LEAVE_NOTIFY:
356 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
357 set_entered_track (0);
359 ret = leave_handler (item, event, StreamItem);
370 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
374 switch (event->type) {
375 case GDK_BUTTON_PRESS:
376 case GDK_2BUTTON_PRESS:
377 case GDK_3BUTTON_PRESS:
378 clicked_regionview = 0;
379 clicked_control_point = 0;
380 clicked_axisview = atv;
381 clicked_routeview = 0;
382 ret = button_press_handler (item, event, AutomationTrackItem);
385 case GDK_BUTTON_RELEASE:
386 ret = button_release_handler (item, event, AutomationTrackItem);
389 case GDK_MOTION_NOTIFY:
390 ret = motion_handler (item, event);
393 case GDK_ENTER_NOTIFY:
394 ret = enter_handler (item, event, AutomationTrackItem);
397 case GDK_LEAVE_NOTIFY:
398 ret = leave_handler (item, event, AutomationTrackItem);
409 Editor::canvas_start_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
411 if (!rv->sensitive()) {
415 switch (event->type) {
416 case GDK_BUTTON_PRESS:
417 clicked_regionview = rv;
418 clicked_control_point = 0;
419 clicked_axisview = &rv->get_time_axis_view();
420 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
421 if (event->button.button == 3) {
422 return button_press_handler (item, event, StartCrossFadeItem);
426 case GDK_BUTTON_RELEASE:
427 if (event->button.button == 3) {
428 return button_release_handler (item, event, StartCrossFadeItem);
437 /* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/
438 /* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */
439 /* if we return RegionItem here then we avoid the issue until it is resolved later */
440 return typed_event (item, event, RegionItem); // StartCrossFadeItem);
444 Editor::canvas_end_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
446 if (!rv->sensitive()) {
450 switch (event->type) {
451 case GDK_BUTTON_PRESS:
452 clicked_regionview = rv;
453 clicked_control_point = 0;
454 clicked_axisview = &rv->get_time_axis_view();
455 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
456 if (event->button.button == 3) {
457 return button_press_handler (item, event, EndCrossFadeItem);
461 case GDK_BUTTON_RELEASE:
462 if (event->button.button == 3) {
463 return button_release_handler (item, event, EndCrossFadeItem);
472 /* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/
473 /* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */
474 /* if we return RegionItem here then we avoid the issue until it is resolved later */
475 return typed_event (item, event, RegionItem); // EndCrossFadeItem);
479 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
481 /* we handle only button 3 press/release events */
483 if (!rv->sensitive()) {
487 switch (event->type) {
488 case GDK_BUTTON_PRESS:
489 clicked_regionview = rv;
490 clicked_control_point = 0;
491 clicked_axisview = &rv->get_time_axis_view();
492 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
493 if (event->button.button == 3) {
494 return button_press_handler (item, event, FadeInItem);
498 case GDK_BUTTON_RELEASE:
499 if (event->button.button == 3) {
500 return button_release_handler (item, event, FadeInItem);
509 /* proxy for the regionview, except enter/leave events */
511 if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
514 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
519 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
523 if (!rv->sensitive()) {
527 switch (event->type) {
528 case GDK_BUTTON_PRESS:
529 case GDK_2BUTTON_PRESS:
530 case GDK_3BUTTON_PRESS:
531 clicked_regionview = rv;
532 clicked_control_point = 0;
533 clicked_axisview = &rv->get_time_axis_view();
534 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
535 ret = button_press_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
538 case GDK_BUTTON_RELEASE:
539 ret = button_release_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
542 case GDK_MOTION_NOTIFY:
543 ret = motion_handler (item, event);
546 case GDK_ENTER_NOTIFY:
547 ret = enter_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
550 case GDK_LEAVE_NOTIFY:
551 ret = leave_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
562 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
564 /* we handle only button 3 press/release events */
566 if (!rv->sensitive()) {
570 switch (event->type) {
571 case GDK_BUTTON_PRESS:
572 clicked_regionview = rv;
573 clicked_control_point = 0;
574 clicked_axisview = &rv->get_time_axis_view();
575 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
576 if (event->button.button == 3) {
577 return button_press_handler (item, event, FadeOutItem);
581 case GDK_BUTTON_RELEASE:
582 if (event->button.button == 3) {
583 return button_release_handler (item, event, FadeOutItem);
592 /* proxy for the regionview, except enter/leave events */
594 if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
597 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
602 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
606 if (!rv->sensitive()) {
610 switch (event->type) {
611 case GDK_BUTTON_PRESS:
612 case GDK_2BUTTON_PRESS:
613 case GDK_3BUTTON_PRESS:
614 clicked_regionview = rv;
615 clicked_control_point = 0;
616 clicked_axisview = &rv->get_time_axis_view();
617 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
618 ret = button_press_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
621 case GDK_BUTTON_RELEASE:
622 ret = button_release_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
625 case GDK_MOTION_NOTIFY:
626 ret = motion_handler (item, event);
629 case GDK_ENTER_NOTIFY:
630 ret = enter_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
633 case GDK_LEAVE_NOTIFY:
634 ret = leave_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
644 struct DescendingRegionLayerSorter {
645 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
646 return a->layer() > b->layer();
651 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
653 switch (event->type) {
654 case GDK_BUTTON_PRESS:
655 case GDK_2BUTTON_PRESS:
656 case GDK_3BUTTON_PRESS:
657 clicked_control_point = cp;
658 clicked_axisview = &cp->line().trackview;
659 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
660 clicked_regionview = 0;
666 case GDK_SCROLL_DOWN:
673 return typed_event (item, event, ControlPointItem);
677 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
680 AudioRegionGainLine* gl;
681 if ((gl = dynamic_cast<AudioRegionGainLine*> (al)) != 0) {
683 if (event->type == GDK_BUTTON_PRESS) {
684 clicked_regionview = &gl->region_view ();
687 type = AutomationLineItem;
688 if (event->type == GDK_BUTTON_PRESS) {
689 clicked_regionview = 0;
693 clicked_control_point = 0;
694 clicked_axisview = &al->trackview;
695 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
697 return typed_event (item, event, type);
701 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
705 switch (event->type) {
706 case GDK_BUTTON_PRESS:
707 case GDK_2BUTTON_PRESS:
708 case GDK_3BUTTON_PRESS:
709 clicked_selection = rect->id;
710 ret = button_press_handler (item, event, SelectionItem);
712 case GDK_BUTTON_RELEASE:
713 ret = button_release_handler (item, event, SelectionItem);
715 case GDK_MOTION_NOTIFY:
716 ret = motion_handler (item, event);
718 /* Don't need these at the moment. */
719 case GDK_ENTER_NOTIFY:
720 ret = enter_handler (item, event, SelectionItem);
723 case GDK_LEAVE_NOTIFY:
724 ret = leave_handler (item, event, SelectionItem);
735 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
739 switch (event->type) {
740 case GDK_BUTTON_PRESS:
741 case GDK_2BUTTON_PRESS:
742 case GDK_3BUTTON_PRESS:
743 clicked_selection = rect->id;
744 ret = button_press_handler (item, event, StartSelectionTrimItem);
746 case GDK_BUTTON_RELEASE:
747 ret = button_release_handler (item, event, StartSelectionTrimItem);
749 case GDK_MOTION_NOTIFY:
750 ret = motion_handler (item, event);
752 case GDK_ENTER_NOTIFY:
753 ret = enter_handler (item, event, StartSelectionTrimItem);
756 case GDK_LEAVE_NOTIFY:
757 ret = leave_handler (item, event, StartSelectionTrimItem);
768 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
772 switch (event->type) {
773 case GDK_BUTTON_PRESS:
774 case GDK_2BUTTON_PRESS:
775 case GDK_3BUTTON_PRESS:
776 clicked_selection = rect->id;
777 ret = button_press_handler (item, event, EndSelectionTrimItem);
779 case GDK_BUTTON_RELEASE:
780 ret = button_release_handler (item, event, EndSelectionTrimItem);
782 case GDK_MOTION_NOTIFY:
783 ret = motion_handler (item, event);
785 case GDK_ENTER_NOTIFY:
786 ret = enter_handler (item, event, EndSelectionTrimItem);
789 case GDK_LEAVE_NOTIFY:
790 ret = leave_handler (item, event, EndSelectionTrimItem);
801 Editor::canvas_frame_handle_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
805 /* frame handles are not active when in internal edit mode, because actual notes
806 might be in the area occupied by the handle - we want them to be editable as normal.
809 if (internal_editing() || !rv->sensitive()) {
813 /* NOTE: frame handles pretend to be the colored trim bar from an event handling
814 perspective. XXX change this ??
819 if (item->get_data ("isleft")) {
820 type = LeftFrameHandle;
822 type = RightFrameHandle;
825 switch (event->type) {
826 case GDK_BUTTON_PRESS:
827 case GDK_2BUTTON_PRESS:
828 case GDK_3BUTTON_PRESS:
829 clicked_regionview = rv;
830 clicked_control_point = 0;
831 clicked_axisview = &clicked_regionview->get_time_axis_view();
832 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
833 ret = button_press_handler (item, event, type);
835 case GDK_BUTTON_RELEASE:
836 ret = button_release_handler (item, event, type);
838 case GDK_MOTION_NOTIFY:
839 ret = motion_handler (item, event);
841 case GDK_ENTER_NOTIFY:
842 ret = enter_handler (item, event, type);
845 case GDK_LEAVE_NOTIFY:
846 ret = leave_handler (item, event, type);
858 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
862 if (!rv->sensitive()) {
866 switch (event->type) {
867 case GDK_BUTTON_PRESS:
868 case GDK_2BUTTON_PRESS:
869 case GDK_3BUTTON_PRESS:
870 clicked_regionview = rv;
871 clicked_control_point = 0;
872 clicked_axisview = &clicked_regionview->get_time_axis_view();
873 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
874 ret = button_press_handler (item, event, RegionViewNameHighlight);
876 case GDK_BUTTON_RELEASE:
877 ret = button_release_handler (item, event, RegionViewNameHighlight);
879 case GDK_MOTION_NOTIFY:
880 motion_handler (item, event);
881 ret = true; // force this to avoid progagating the event into the regionview
883 case GDK_ENTER_NOTIFY:
884 ret = enter_handler (item, event, RegionViewNameHighlight);
887 case GDK_LEAVE_NOTIFY:
888 ret = leave_handler (item, event, RegionViewNameHighlight);
899 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
903 if (!rv->sensitive()) {
907 switch (event->type) {
908 case GDK_BUTTON_PRESS:
909 case GDK_2BUTTON_PRESS:
910 case GDK_3BUTTON_PRESS:
911 clicked_regionview = rv;
912 clicked_control_point = 0;
913 clicked_axisview = &clicked_regionview->get_time_axis_view();
914 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
915 ret = button_press_handler (item, event, RegionViewName);
917 case GDK_BUTTON_RELEASE:
918 ret = button_release_handler (item, event, RegionViewName);
920 case GDK_MOTION_NOTIFY:
921 ret = motion_handler (item, event);
923 case GDK_ENTER_NOTIFY:
924 ret = enter_handler (item, event, RegionViewName);
927 case GDK_LEAVE_NOTIFY:
928 ret = leave_handler (item, event, RegionViewName);
939 Editor::canvas_feature_line_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView*)
943 switch (event->type) {
944 case GDK_BUTTON_PRESS:
945 case GDK_2BUTTON_PRESS:
946 case GDK_3BUTTON_PRESS:
947 clicked_regionview = 0;
948 clicked_control_point = 0;
949 clicked_axisview = 0;
950 clicked_routeview = 0; //dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
951 ret = button_press_handler (item, event, FeatureLineItem);
954 case GDK_BUTTON_RELEASE:
955 ret = button_release_handler (item, event, FeatureLineItem);
958 case GDK_MOTION_NOTIFY:
959 ret = motion_handler (item, event);
962 case GDK_ENTER_NOTIFY:
963 ret = enter_handler (item, event, FeatureLineItem);
966 case GDK_LEAVE_NOTIFY:
967 ret = leave_handler (item, event, FeatureLineItem);
978 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, ArdourMarker* /*marker*/)
980 return typed_event (item, event, MarkerItem);
984 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
986 return typed_event (item, event, MarkerBarItem);
990 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
992 return typed_event (item, event, RangeMarkerBarItem);
996 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
998 return typed_event (item, event, TransportMarkerBarItem);
1002 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1004 return typed_event (item, event, CdMarkerBarItem);
1008 Editor::canvas_videotl_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1010 return typed_event (item, event, VideoBarItem);
1014 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
1016 return typed_event (item, event, TempoMarkerItem);
1020 Editor::canvas_tempo_curve_event (GdkEvent *event, ArdourCanvas::Item* item, TempoCurve* /*marker*/)
1022 return typed_event (item, event, TempoCurveItem);
1026 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* /*marker*/)
1028 return typed_event (item, event, MeterMarkerItem);
1032 Editor::canvas_ruler_event (GdkEvent *event, ArdourCanvas::Item* item, ItemType type)
1034 bool handled = false;
1036 if (event->type == GDK_SCROLL) {
1038 /* scroll events in the rulers are handled a little differently from
1039 scrolling elsewhere in the canvas.
1042 switch (event->scroll.direction) {
1044 if (Keyboard::modifier_state_equals(event->scroll.state,
1045 Keyboard::ScrollHorizontalModifier)) {
1046 scroll_left_step ();
1047 } else if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
1048 temporal_zoom_step_mouse_focus (false);
1050 temporal_zoom_step (false);
1055 case GDK_SCROLL_DOWN:
1056 if (Keyboard::modifier_state_equals(event->scroll.state,
1057 Keyboard::ScrollHorizontalModifier)) {
1058 scroll_right_step ();
1059 } else if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
1060 temporal_zoom_step_mouse_focus (true);
1062 temporal_zoom_step (true);
1067 case GDK_SCROLL_LEFT:
1068 scroll_left_half_page ();
1072 case GDK_SCROLL_RIGHT:
1073 scroll_right_half_page ();
1084 return typed_event (item, event, type);
1088 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1090 return typed_event (item, event, TempoBarItem);
1094 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1096 return typed_event (item, event, MeterBarItem);
1100 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
1102 return typed_event (item, event, PlayheadCursorItem);
1106 Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
1108 if (!internal_editing()) {
1112 return typed_event (item, event, NoteItem);
1116 Editor::canvas_drop_zone_event (GdkEvent* event)
1118 printf("canvas_drop_zone_event\n");
1119 GdkEventScroll scroll;
1120 ArdourCanvas::Duple winpos;
1122 switch (event->type) {
1123 case GDK_BUTTON_RELEASE:
1124 if (event->button.button == 1) {
1125 begin_reversible_selection_op (X_("Nowhere Click"));
1126 selection->clear_objects ();
1127 selection->clear_tracks ();
1128 commit_reversible_selection_op ();
1133 /* convert coordinates back into window space so that
1134 we can just call canvas_scroll_event().
1136 winpos = _track_canvas->canvas_to_window (Duple (event->scroll.x, event->scroll.y));
1137 scroll = event->scroll;
1138 scroll.x = winpos.x;
1139 scroll.y = winpos.y;
1140 return canvas_scroll_event (&scroll, true);
1143 case GDK_ENTER_NOTIFY:
1144 return typed_event (_canvas_drop_zone, event, DropZoneItem);
1146 case GDK_LEAVE_NOTIFY:
1147 return typed_event (_canvas_drop_zone, event, DropZoneItem);
1157 Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const& context, int x, int y, guint time)
1159 boost::shared_ptr<Region> region;
1160 boost::shared_ptr<Region> region_copy;
1161 RouteTimeAxisView* rtav;
1166 string target = _track_canvas->drag_dest_find_target (context, _track_canvas->drag_dest_get_target_list());
1168 if (target.empty()) {
1172 printf("DRAGGING: track_canvas_drag_motion\n");
1174 event.type = GDK_MOTION_NOTIFY;
1177 /* assume we're dragging with button 1 */
1178 event.motion.state = Gdk::BUTTON1_MASK;
1180 (void) window_event_sample (&event, &px, &py);
1182 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py, false);
1183 bool can_drop = false;
1185 if (tv.first != 0) {
1187 /* over a time axis view of some kind */
1189 rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1191 if (rtav != 0 && rtav->is_track ()) {
1192 /* over a track, not a bus */
1198 /* not over a time axis view, so drop is possible */
1203 region = _regions->get_dragged_region ();
1205 boost::shared_ptr<ARDOUR::Source> src = _sources->get_dragged_source ();
1206 region = RegionFactory::get_whole_region_for_source (src);
1213 boost::dynamic_pointer_cast<AudioRegion> (region) != 0 ||
1214 boost::dynamic_pointer_cast<MidiRegion> (region) != 0
1218 /* drop to drop-zone */
1219 context->drag_status (context->get_suggested_action(), time);
1223 if ((boost::dynamic_pointer_cast<AudioRegion> (region) != 0 &&
1224 dynamic_cast<AudioTimeAxisView*> (tv.first) != 0) ||
1225 (boost::dynamic_pointer_cast<MidiRegion> (region) != 0 &&
1226 dynamic_cast<MidiTimeAxisView*> (tv.first) != 0)) {
1233 context->drag_status (context->get_suggested_action(), time);
1237 /* DND originating from outside ardour
1239 * TODO: check if file is audio/midi, allow drops on same track-type only,
1240 * currently: if audio is dropped on a midi-track, it is only added to the region-list
1242 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1243 context->drag_status(Gdk::ACTION_COPY, time);
1245 if ((context->get_actions() & (Gdk::ACTION_COPY | Gdk::ACTION_LINK | Gdk::ACTION_MOVE)) == Gdk::ACTION_COPY) {
1246 context->drag_status(Gdk::ACTION_COPY, time);
1248 context->drag_status(Gdk::ACTION_LINK, time);
1256 context->drag_status (Gdk::DragAction (0), time);
1261 Editor::drop_regions (const Glib::RefPtr<Gdk::DragContext>& /*context*/,
1263 const SelectionData& /*data*/,
1264 guint /*info*/, guint /*time*/)
1270 event.type = GDK_MOTION_NOTIFY;
1273 /* assume we're dragging with button 1 */
1274 event.motion.state = Gdk::BUTTON1_MASK;
1275 samplepos_t const pos = window_event_sample (&event, &px, &py);
1277 boost::shared_ptr<Region> region = _regions->get_dragged_region ();
1279 boost::shared_ptr<ARDOUR::Source> src = _sources->get_dragged_source ();
1280 region = RegionFactory::get_whole_region_for_source (src);
1283 if (!region) { return; }
1285 RouteTimeAxisView* rtav = 0;
1286 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py, false);
1288 if (tv.first != 0) {
1289 rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1292 if (boost::dynamic_pointer_cast<AudioRegion> (region)) {
1293 uint32_t output_chan = region->n_channels();
1294 if ((Config->get_output_auto_connect() & AutoConnectMaster) && session()->master_out()) {
1295 output_chan = session()->master_out()->n_inputs().n_audio();
1297 list<boost::shared_ptr<AudioTrack> > audio_tracks;
1298 audio_tracks = session()->new_audio_track (region->n_channels(), output_chan, 0, 1, region->name(), PresentationInfo::max_order);
1299 rtav = dynamic_cast<RouteTimeAxisView*> (time_axis_view_from_stripable (audio_tracks.front()));
1300 } else if (boost::dynamic_pointer_cast<MidiRegion> (region)) {
1301 ChanCount one_midi_port (DataType::MIDI, 1);
1302 list<boost::shared_ptr<MidiTrack> > midi_tracks;
1303 midi_tracks = session()->new_midi_track (one_midi_port, one_midi_port,
1304 Config->get_strict_io () || Profile->get_mixbus (),
1305 boost::shared_ptr<ARDOUR::PluginInfo>(),
1306 (ARDOUR::Plugin::PresetRecord*) 0,
1307 (ARDOUR::RouteGroup*) 0, 1, region->name(), PresentationInfo::max_order);
1308 rtav = dynamic_cast<RouteTimeAxisView*> (time_axis_view_from_stripable (midi_tracks.front()));
1313 error << _("Could not create new track after region placed in the drop zone") << endmsg;
1318 if (rtav != 0 && rtav->is_track ()) {
1319 boost::shared_ptr<Region> region_copy = RegionFactory::create (region, true);
1321 if ((boost::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 && dynamic_cast<AudioTimeAxisView*> (rtav) != 0) ||
1322 (boost::dynamic_pointer_cast<MidiRegion> (region_copy) != 0 && dynamic_cast<MidiTimeAxisView*> (rtav) != 0)) {
1323 _drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event);
1324 _drags->end_grab (&event);
1330 Editor::key_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType)
1336 Editor::key_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType type)
1339 bool handled = false;
1342 case TempoMarkerItem:
1343 switch (event->key.keyval) {
1345 remove_tempo_marker (item);
1353 case MeterMarkerItem:
1354 switch (event->key.keyval) {
1356 remove_meter_marker (item);