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_diskstream.h>
28 #include <ardour/audioplaylist.h>
32 #include "public_editor.h"
33 #include "audio_region_view.h"
34 #include "audio_streamview.h"
35 #include "crossfade_view.h"
36 #include "audio_time_axis.h"
37 #include "region_gain_line.h"
38 #include "automation_line.h"
39 #include "automation_time_axis.h"
40 #include "automation_line.h"
41 #include "control_point.h"
42 #include "canvas_impl.h"
43 #include "simplerect.h"
44 #include "interactive-item.h"
50 using namespace ARDOUR;
53 using namespace ArdourCanvas;
56 Editor::track_canvas_scroll (GdkEventScroll* ev)
61 int direction = ev->direction;
63 Gnome::Canvas::Item* item = track_canvas->get_item_at(ev->x, ev->y);
64 InteractiveItem* interactive_item = dynamic_cast<InteractiveItem*>(item);
65 if (interactive_item) {
66 return interactive_item->on_event(reinterpret_cast<GdkEvent*>(ev));
72 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
73 //if (ev->state == GDK_CONTROL_MASK) {
75 the ev->x will be out of step with the canvas
76 if we're in mid zoom, so we have to get the damn mouse
79 track_canvas->get_pointer (x, y);
80 track_canvas->window_to_world (x, y, wx, wy);
83 event.type = GDK_BUTTON_RELEASE;
87 nframes64_t where = event_frame (&event, 0, 0);
88 temporal_zoom_to_frame (false, where);
90 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
91 direction = GDK_SCROLL_LEFT;
93 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
94 if (!current_stepping_trackview) {
95 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
96 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize);
97 current_stepping_trackview = p.first;
98 if (!current_stepping_trackview) {
102 last_track_height_step_timestamp = get_microseconds();
103 current_stepping_trackview->step_height (true);
106 scroll_tracks_up_line ();
111 case GDK_SCROLL_DOWN:
112 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
113 //if (ev->state == GDK_CONTROL_MASK) {
114 track_canvas->get_pointer (x, y);
115 track_canvas->window_to_world (x, y, wx, wy);
118 event.type = GDK_BUTTON_RELEASE;
122 nframes64_t where = event_frame (&event, 0, 0);
123 temporal_zoom_to_frame (true, where);
125 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
126 direction = GDK_SCROLL_RIGHT;
128 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
129 if (!current_stepping_trackview) {
130 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
131 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize);
132 current_stepping_trackview = p.first;
133 if (!current_stepping_trackview) {
137 last_track_height_step_timestamp = get_microseconds();
138 current_stepping_trackview->step_height (false);
141 scroll_tracks_down_line ();
146 case GDK_SCROLL_LEFT:
147 xdelta = (current_page_frames() / 8);
148 if (leftmost_frame > xdelta) {
149 reset_x_origin (leftmost_frame - xdelta);
155 case GDK_SCROLL_RIGHT:
156 xdelta = (current_page_frames() / 8);
157 if (max_frames - xdelta > leftmost_frame) {
158 reset_x_origin (leftmost_frame + xdelta);
160 reset_x_origin (max_frames - current_page_frames());
173 Editor::track_canvas_scroll_event (GdkEventScroll *event)
175 track_canvas->grab_focus();
176 track_canvas_scroll (event);
181 Editor::track_canvas_button_press_event (GdkEventButton *event)
184 track_canvas->grab_focus();
189 Editor::track_canvas_button_release_event (GdkEventButton *event)
191 if (drag_info.item) {
192 end_grab (drag_info.item, (GdkEvent*) event);
198 Editor::track_canvas_motion_notify_event (GdkEventMotion *event)
201 /* keep those motion events coming */
202 track_canvas->get_pointer (x, y);
207 Editor::track_canvas_motion (GdkEvent *ev)
209 if (verbose_cursor_visible) {
210 verbose_canvas_cursor->property_x() = clamp_verbose_cursor_x (ev->motion.x + 10);
211 verbose_canvas_cursor->property_y() = clamp_verbose_cursor_y (ev->motion.y + 10);
218 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
222 switch (event->type) {
223 case GDK_BUTTON_PRESS:
224 case GDK_2BUTTON_PRESS:
225 case GDK_3BUTTON_PRESS:
226 ret = button_press_handler (item, event, type);
228 case GDK_BUTTON_RELEASE:
229 ret = button_release_handler (item, event, type);
231 case GDK_MOTION_NOTIFY:
232 ret = motion_handler (item, event, type);
235 case GDK_ENTER_NOTIFY:
236 ret = enter_handler (item, event, type);
239 case GDK_LEAVE_NOTIFY:
240 ret = leave_handler (item, event, type);
250 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
254 if (!rv->sensitive ()) {
259 switch (event->type) {
260 case GDK_BUTTON_PRESS:
261 case GDK_2BUTTON_PRESS:
262 case GDK_3BUTTON_PRESS:
263 clicked_regionview = rv;
264 clicked_control_point = 0;
265 clicked_axisview = &rv->get_time_axis_view();
266 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
267 ret = button_press_handler (item, event, RegionItem);
270 case GDK_BUTTON_RELEASE:
271 ret = button_release_handler (item, event, RegionItem);
274 case GDK_MOTION_NOTIFY:
275 ret = motion_handler (item, event, RegionItem);
278 case GDK_ENTER_NOTIFY:
279 set_entered_track (&rv->get_time_axis_view ());
280 set_entered_regionview (rv);
283 case GDK_LEAVE_NOTIFY:
284 set_entered_track (0);
285 set_entered_regionview (0);
296 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
300 switch (event->type) {
301 case GDK_BUTTON_PRESS:
302 case GDK_2BUTTON_PRESS:
303 case GDK_3BUTTON_PRESS:
304 clicked_regionview = 0;
305 clicked_control_point = 0;
306 clicked_axisview = tv;
307 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(tv);
308 ret = button_press_handler (item, event, StreamItem);
311 case GDK_BUTTON_RELEASE:
312 ret = button_release_handler (item, event, StreamItem);
315 case GDK_MOTION_NOTIFY:
316 ret = motion_handler (item, event, StreamItem);
319 case GDK_ENTER_NOTIFY:
320 set_entered_track (tv);
323 case GDK_LEAVE_NOTIFY:
324 set_entered_track (0);
335 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
340 switch (event->type) {
341 case GDK_BUTTON_PRESS:
342 case GDK_2BUTTON_PRESS:
343 case GDK_3BUTTON_PRESS:
344 clicked_regionview = 0;
345 clicked_control_point = 0;
346 clicked_axisview = atv;
347 clicked_routeview = 0;
348 ret = button_press_handler (item, event, AutomationTrackItem);
351 case GDK_BUTTON_RELEASE:
352 ret = button_release_handler (item, event, AutomationTrackItem);
355 case GDK_MOTION_NOTIFY:
356 ret = motion_handler (item, event, AutomationTrackItem);
359 case GDK_ENTER_NOTIFY:
360 ret = enter_handler (item, event, AutomationTrackItem);
363 case GDK_LEAVE_NOTIFY:
364 ret = leave_handler (item, event, AutomationTrackItem);
375 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
377 /* we handle only button 3 press/release events */
379 if (!rv->sensitive()) {
383 switch (event->type) {
384 case GDK_BUTTON_PRESS:
385 clicked_regionview = rv;
386 clicked_control_point = 0;
387 clicked_axisview = &rv->get_time_axis_view();
388 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
389 if (event->button.button == 3) {
390 return button_press_handler (item, event, FadeInItem);
394 case GDK_BUTTON_RELEASE:
395 if (event->button.button == 3) {
396 return button_release_handler (item, event, FadeInItem);
405 /* proxy for the regionview */
407 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
411 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
415 if (!rv->sensitive()) {
419 switch (event->type) {
420 case GDK_BUTTON_PRESS:
421 case GDK_2BUTTON_PRESS:
422 case GDK_3BUTTON_PRESS:
423 clicked_regionview = rv;
424 clicked_control_point = 0;
425 clicked_axisview = &rv->get_time_axis_view();
426 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
427 ret = button_press_handler (item, event, FadeInHandleItem);
430 case GDK_BUTTON_RELEASE:
431 ret = button_release_handler (item, event, FadeInHandleItem);
434 case GDK_MOTION_NOTIFY:
435 ret = motion_handler (item, event, FadeInHandleItem);
438 case GDK_ENTER_NOTIFY:
439 ret = enter_handler (item, event, FadeInHandleItem);
442 case GDK_LEAVE_NOTIFY:
443 ret = leave_handler (item, event, FadeInHandleItem);
454 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
456 /* we handle only button 3 press/release events */
458 if (!rv->sensitive()) {
462 switch (event->type) {
463 case GDK_BUTTON_PRESS:
464 clicked_regionview = rv;
465 clicked_control_point = 0;
466 clicked_axisview = &rv->get_time_axis_view();
467 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
468 if (event->button.button == 3) {
469 return button_press_handler (item, event, FadeOutItem);
473 case GDK_BUTTON_RELEASE:
474 if (event->button.button == 3) {
475 return button_release_handler (item, event, FadeOutItem);
484 /* proxy for the regionview */
486 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
490 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
494 if (!rv->sensitive()) {
498 switch (event->type) {
499 case GDK_BUTTON_PRESS:
500 case GDK_2BUTTON_PRESS:
501 case GDK_3BUTTON_PRESS:
502 clicked_regionview = rv;
503 clicked_control_point = 0;
504 clicked_axisview = &rv->get_time_axis_view();
505 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
506 ret = button_press_handler (item, event, FadeOutHandleItem);
509 case GDK_BUTTON_RELEASE:
510 ret = button_release_handler (item, event, FadeOutHandleItem);
513 case GDK_MOTION_NOTIFY:
514 ret = motion_handler (item, event, FadeOutHandleItem);
517 case GDK_ENTER_NOTIFY:
518 ret = enter_handler (item, event, FadeOutHandleItem);
521 case GDK_LEAVE_NOTIFY:
522 ret = leave_handler (item, event, FadeOutHandleItem);
532 struct DescendingRegionLayerSorter {
533 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
534 return a->layer() > b->layer();
539 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
541 /* we handle only button 3 press/release events */
543 switch (event->type) {
544 case GDK_BUTTON_PRESS:
545 clicked_crossfadeview = xfv;
546 clicked_axisview = &clicked_crossfadeview->get_time_axis_view();
547 if (event->button.button == 3) {
548 return button_press_handler (item, event, CrossfadeViewItem);
552 case GDK_BUTTON_RELEASE:
553 if (event->button.button == 3) {
554 bool ret = button_release_handler (item, event, CrossfadeViewItem);
564 /* XXX do not forward double clicks */
566 if (event->type == GDK_2BUTTON_PRESS) {
570 /* proxy for the upper most regionview */
572 /* XXX really need to check if we are in the name highlight,
573 and proxy to that when required.
576 TimeAxisView& tv (xfv->get_time_axis_view());
577 AudioTimeAxisView* atv;
579 if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
581 if (atv->is_audio_track()) {
583 boost::shared_ptr<AudioPlaylist> pl;
584 if ((pl = boost::dynamic_pointer_cast<AudioPlaylist> (atv->get_diskstream()->playlist())) != 0) {
586 Playlist::RegionList* rl = pl->regions_at (event_frame (event));
589 DescendingRegionLayerSorter cmp;
592 RegionView* rv = atv->view()->find_view (rl->front());
598 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
610 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
612 switch (event->type) {
613 case GDK_BUTTON_PRESS:
614 case GDK_2BUTTON_PRESS:
615 case GDK_3BUTTON_PRESS:
616 clicked_control_point = cp;
617 clicked_axisview = &cp->line().trackview;
618 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
619 clicked_regionview = 0;
625 case GDK_SCROLL_DOWN:
632 return typed_event (item, event, ControlPointItem);
636 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
640 if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
643 type = AutomationLineItem;
646 return typed_event (item, event, type);
650 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
654 switch (event->type) {
655 case GDK_BUTTON_PRESS:
656 case GDK_2BUTTON_PRESS:
657 case GDK_3BUTTON_PRESS:
658 clicked_selection = rect->id;
659 ret = button_press_handler (item, event, SelectionItem);
661 case GDK_BUTTON_RELEASE:
662 ret = button_release_handler (item, event, SelectionItem);
664 case GDK_MOTION_NOTIFY:
665 ret = motion_handler (item, event, SelectionItem);
667 /* Don't need these at the moment. */
668 case GDK_ENTER_NOTIFY:
669 ret = enter_handler (item, event, SelectionItem);
672 case GDK_LEAVE_NOTIFY:
673 ret = leave_handler (item, event, SelectionItem);
684 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
688 switch (event->type) {
689 case GDK_BUTTON_PRESS:
690 case GDK_2BUTTON_PRESS:
691 case GDK_3BUTTON_PRESS:
692 clicked_selection = rect->id;
693 ret = button_press_handler (item, event, StartSelectionTrimItem);
695 case GDK_BUTTON_RELEASE:
696 ret = button_release_handler (item, event, StartSelectionTrimItem);
698 case GDK_MOTION_NOTIFY:
699 ret = motion_handler (item, event, StartSelectionTrimItem);
701 case GDK_ENTER_NOTIFY:
702 ret = enter_handler (item, event, StartSelectionTrimItem);
705 case GDK_LEAVE_NOTIFY:
706 ret = leave_handler (item, event, StartSelectionTrimItem);
717 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
721 switch (event->type) {
722 case GDK_BUTTON_PRESS:
723 case GDK_2BUTTON_PRESS:
724 case GDK_3BUTTON_PRESS:
725 clicked_selection = rect->id;
726 ret = button_press_handler (item, event, EndSelectionTrimItem);
728 case GDK_BUTTON_RELEASE:
729 ret = button_release_handler (item, event, EndSelectionTrimItem);
731 case GDK_MOTION_NOTIFY:
732 ret = motion_handler (item, event, EndSelectionTrimItem);
734 case GDK_ENTER_NOTIFY:
735 ret = enter_handler (item, event, EndSelectionTrimItem);
738 case GDK_LEAVE_NOTIFY:
739 ret = leave_handler (item, event, EndSelectionTrimItem);
751 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
755 if (!rv->sensitive()) {
759 switch (event->type) {
760 case GDK_BUTTON_PRESS:
761 case GDK_2BUTTON_PRESS:
762 case GDK_3BUTTON_PRESS:
763 clicked_regionview = rv;
764 clicked_control_point = 0;
765 clicked_axisview = &clicked_regionview->get_time_axis_view();
766 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
767 ret = button_press_handler (item, event, RegionViewNameHighlight);
769 case GDK_BUTTON_RELEASE:
770 ret = button_release_handler (item, event, RegionViewNameHighlight);
772 case GDK_MOTION_NOTIFY:
773 ret = motion_handler (item, event, RegionViewNameHighlight);
775 case GDK_ENTER_NOTIFY:
776 ret = enter_handler (item, event, RegionViewNameHighlight);
779 case GDK_LEAVE_NOTIFY:
780 ret = leave_handler (item, event, RegionViewNameHighlight);
791 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
795 if (!rv->sensitive()) {
799 switch (event->type) {
800 case GDK_BUTTON_PRESS:
801 case GDK_2BUTTON_PRESS:
802 case GDK_3BUTTON_PRESS:
803 clicked_regionview = rv;
804 clicked_control_point = 0;
805 clicked_axisview = &clicked_regionview->get_time_axis_view();
806 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
807 ret = button_press_handler (item, event, RegionViewName);
809 case GDK_BUTTON_RELEASE:
810 ret = button_release_handler (item, event, RegionViewName);
812 case GDK_MOTION_NOTIFY:
813 ret = motion_handler (item, event, RegionViewName);
815 case GDK_ENTER_NOTIFY:
816 ret = enter_handler (item, event, RegionViewName);
819 case GDK_LEAVE_NOTIFY:
820 ret = leave_handler (item, event, RegionViewName);
831 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* marker)
833 return typed_event (item, event, MarkerItem);
837 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
839 return typed_event (item, event, MarkerBarItem);
843 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
845 return typed_event (item, event, RangeMarkerBarItem);
849 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
851 return typed_event (item, event, TransportMarkerBarItem);
855 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
857 return typed_event (item, event, CdMarkerBarItem);
861 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
863 return typed_event (item, event, TempoMarkerItem);
867 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* marker)
869 return typed_event (item, event, MeterMarkerItem);
873 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
875 return typed_event (item, event, TempoBarItem);
879 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
881 return typed_event (item, event, MeterBarItem);
885 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
887 return typed_event (item, event, PlayheadCursorItem);
891 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
893 return typed_event (item, event, NoItem);