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.
24 #include <pbd/stacktrace.h>
26 #include <ardour/audio_diskstream.h>
27 #include <ardour/audioplaylist.h>
31 #include "public_editor.h"
32 #include "audio_region_view.h"
33 #include "audio_streamview.h"
34 #include "crossfade_view.h"
35 #include "audio_time_axis.h"
36 #include "region_gain_line.h"
37 #include "automation_line.h"
38 #include "automation_time_axis.h"
39 #include "automation_line.h"
40 #include "control_point.h"
41 #include "canvas_impl.h"
42 #include "simplerect.h"
43 #include "canvas-note-event.h"
49 using namespace ARDOUR;
52 using namespace ArdourCanvas;
55 Editor::track_canvas_scroll (GdkEventScroll* ev)
60 int direction = ev->direction;
61 CanvasNoteEvent *midi_event = dynamic_cast<CanvasNoteEvent *>(track_canvas->get_item_at(ev->x, ev->y));
66 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
67 //if (ev->state == GDK_CONTROL_MASK) {
69 the ev->x will be out of step with the canvas
70 if we're in mid zoom, so we have to get the damn mouse
73 track_canvas->get_pointer (x, y);
74 track_canvas->window_to_world (x, y, wx, wy);
77 event.type = GDK_BUTTON_RELEASE;
81 nframes64_t where = event_frame (&event, 0, 0);
82 temporal_zoom_to_frame (false, where);
84 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
85 direction = GDK_SCROLL_LEFT;
87 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
88 if (!current_stepping_trackview) {
89 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
90 if (!(current_stepping_trackview = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize))) {
94 last_track_height_step_timestamp = get_microseconds();
95 current_stepping_trackview->step_height (true);
99 return midi_event->on_event(reinterpret_cast<GdkEvent *>(ev));
101 scroll_tracks_up_line ();
106 case GDK_SCROLL_DOWN:
107 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
108 //if (ev->state == GDK_CONTROL_MASK) {
109 track_canvas->get_pointer (x, y);
110 track_canvas->window_to_world (x, y, wx, wy);
113 event.type = GDK_BUTTON_RELEASE;
117 nframes64_t where = event_frame (&event, 0, 0);
118 temporal_zoom_to_frame (true, where);
120 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
121 direction = GDK_SCROLL_RIGHT;
123 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
124 if (!current_stepping_trackview) {
125 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
126 if (!(current_stepping_trackview = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize))) {
130 last_track_height_step_timestamp = get_microseconds();
131 current_stepping_trackview->step_height (false);
135 return midi_event->on_event(reinterpret_cast<GdkEvent *>(ev));
137 scroll_tracks_down_line ();
142 case GDK_SCROLL_LEFT:
143 xdelta = (current_page_frames() / 8);
144 if (leftmost_frame > xdelta) {
145 reset_x_origin (leftmost_frame - xdelta);
151 case GDK_SCROLL_RIGHT:
152 xdelta = (current_page_frames() / 8);
153 if (max_frames - xdelta > leftmost_frame) {
154 reset_x_origin (leftmost_frame + xdelta);
156 reset_x_origin (max_frames - current_page_frames());
169 Editor::track_canvas_scroll_event (GdkEventScroll *event)
171 track_canvas->grab_focus();
172 track_canvas_scroll (event);
177 Editor::track_canvas_button_press_event (GdkEventButton *event)
180 track_canvas->grab_focus();
185 Editor::track_canvas_button_release_event (GdkEventButton *event)
187 if (drag_info.item) {
188 end_grab (drag_info.item, (GdkEvent*) event);
194 Editor::track_canvas_motion_notify_event (GdkEventMotion *event)
197 /* keep those motion events coming */
198 track_canvas->get_pointer (x, y);
203 Editor::track_canvas_motion (GdkEvent *ev)
205 if (verbose_cursor_visible) {
206 verbose_canvas_cursor->property_x() = clamp_verbose_cursor_x (ev->motion.x + 10);
207 verbose_canvas_cursor->property_y() = clamp_verbose_cursor_y (ev->motion.y + 10);
214 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
218 switch (event->type) {
219 case GDK_BUTTON_PRESS:
220 case GDK_2BUTTON_PRESS:
221 case GDK_3BUTTON_PRESS:
222 ret = button_press_handler (item, event, type);
224 case GDK_BUTTON_RELEASE:
225 ret = button_release_handler (item, event, type);
227 case GDK_MOTION_NOTIFY:
228 ret = motion_handler (item, event, type);
231 case GDK_ENTER_NOTIFY:
232 ret = enter_handler (item, event, type);
235 case GDK_LEAVE_NOTIFY:
236 ret = leave_handler (item, event, type);
246 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
250 if (!rv->sensitive ()) {
255 switch (event->type) {
256 case GDK_BUTTON_PRESS:
257 case GDK_2BUTTON_PRESS:
258 case GDK_3BUTTON_PRESS:
259 clicked_regionview = rv;
260 clicked_control_point = 0;
261 clicked_axisview = &rv->get_time_axis_view();
262 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
263 ret = button_press_handler (item, event, RegionItem);
266 case GDK_BUTTON_RELEASE:
267 ret = button_release_handler (item, event, RegionItem);
270 case GDK_MOTION_NOTIFY:
271 ret = motion_handler (item, event, RegionItem);
274 case GDK_ENTER_NOTIFY:
275 set_entered_track (&rv->get_time_axis_view ());
276 set_entered_regionview (rv);
279 case GDK_LEAVE_NOTIFY:
280 set_entered_track (0);
281 set_entered_regionview (0);
292 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
296 switch (event->type) {
297 case GDK_BUTTON_PRESS:
298 case GDK_2BUTTON_PRESS:
299 case GDK_3BUTTON_PRESS:
300 clicked_regionview = 0;
301 clicked_control_point = 0;
302 clicked_axisview = tv;
303 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(tv);
304 ret = button_press_handler (item, event, StreamItem);
307 case GDK_BUTTON_RELEASE:
308 ret = button_release_handler (item, event, StreamItem);
311 case GDK_MOTION_NOTIFY:
312 ret = motion_handler (item, event, StreamItem);
315 case GDK_ENTER_NOTIFY:
316 set_entered_track (tv);
319 case GDK_LEAVE_NOTIFY:
320 set_entered_track (0);
331 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
336 switch (event->type) {
337 case GDK_BUTTON_PRESS:
338 case GDK_2BUTTON_PRESS:
339 case GDK_3BUTTON_PRESS:
340 clicked_regionview = 0;
341 clicked_control_point = 0;
342 clicked_axisview = atv;
343 clicked_routeview = 0;
344 ret = button_press_handler (item, event, AutomationTrackItem);
347 case GDK_BUTTON_RELEASE:
348 ret = button_release_handler (item, event, AutomationTrackItem);
351 case GDK_MOTION_NOTIFY:
352 ret = motion_handler (item, event, AutomationTrackItem);
355 case GDK_ENTER_NOTIFY:
356 ret = enter_handler (item, event, AutomationTrackItem);
359 case GDK_LEAVE_NOTIFY:
360 ret = leave_handler (item, event, AutomationTrackItem);
371 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
373 /* we handle only button 3 press/release events */
375 if (!rv->sensitive()) {
379 switch (event->type) {
380 case GDK_BUTTON_PRESS:
381 clicked_regionview = rv;
382 clicked_control_point = 0;
383 clicked_axisview = &rv->get_time_axis_view();
384 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
385 if (event->button.button == 3) {
386 return button_press_handler (item, event, FadeInItem);
390 case GDK_BUTTON_RELEASE:
391 if (event->button.button == 3) {
392 return button_release_handler (item, event, FadeInItem);
401 /* proxy for the regionview */
403 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
407 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
411 if (!rv->sensitive()) {
415 switch (event->type) {
416 case GDK_BUTTON_PRESS:
417 case GDK_2BUTTON_PRESS:
418 case GDK_3BUTTON_PRESS:
419 clicked_regionview = rv;
420 clicked_control_point = 0;
421 clicked_axisview = &rv->get_time_axis_view();
422 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
423 ret = button_press_handler (item, event, FadeInHandleItem);
426 case GDK_BUTTON_RELEASE:
427 ret = button_release_handler (item, event, FadeInHandleItem);
430 case GDK_MOTION_NOTIFY:
431 ret = motion_handler (item, event, FadeInHandleItem);
434 case GDK_ENTER_NOTIFY:
435 ret = enter_handler (item, event, FadeInHandleItem);
438 case GDK_LEAVE_NOTIFY:
439 ret = leave_handler (item, event, FadeInHandleItem);
450 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
452 /* we handle only button 3 press/release events */
454 if (!rv->sensitive()) {
458 switch (event->type) {
459 case GDK_BUTTON_PRESS:
460 clicked_regionview = rv;
461 clicked_control_point = 0;
462 clicked_axisview = &rv->get_time_axis_view();
463 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
464 if (event->button.button == 3) {
465 return button_press_handler (item, event, FadeOutItem);
469 case GDK_BUTTON_RELEASE:
470 if (event->button.button == 3) {
471 return button_release_handler (item, event, FadeOutItem);
480 /* proxy for the regionview */
482 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
486 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
490 if (!rv->sensitive()) {
494 switch (event->type) {
495 case GDK_BUTTON_PRESS:
496 case GDK_2BUTTON_PRESS:
497 case GDK_3BUTTON_PRESS:
498 clicked_regionview = rv;
499 clicked_control_point = 0;
500 clicked_axisview = &rv->get_time_axis_view();
501 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
502 ret = button_press_handler (item, event, FadeOutHandleItem);
505 case GDK_BUTTON_RELEASE:
506 ret = button_release_handler (item, event, FadeOutHandleItem);
509 case GDK_MOTION_NOTIFY:
510 ret = motion_handler (item, event, FadeOutHandleItem);
513 case GDK_ENTER_NOTIFY:
514 ret = enter_handler (item, event, FadeOutHandleItem);
517 case GDK_LEAVE_NOTIFY:
518 ret = leave_handler (item, event, FadeOutHandleItem);
528 struct DescendingRegionLayerSorter {
529 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
530 return a->layer() > b->layer();
535 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
537 /* we handle only button 3 press/release events */
539 switch (event->type) {
540 case GDK_BUTTON_PRESS:
541 clicked_crossfadeview = xfv;
542 clicked_axisview = &clicked_crossfadeview->get_time_axis_view();
543 if (event->button.button == 3) {
544 return button_press_handler (item, event, CrossfadeViewItem);
548 case GDK_BUTTON_RELEASE:
549 if (event->button.button == 3) {
550 bool ret = button_release_handler (item, event, CrossfadeViewItem);
560 /* XXX do not forward double clicks */
562 if (event->type == GDK_2BUTTON_PRESS) {
566 /* proxy for the upper most regionview */
568 /* XXX really need to check if we are in the name highlight,
569 and proxy to that when required.
572 TimeAxisView& tv (xfv->get_time_axis_view());
573 AudioTimeAxisView* atv;
575 if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
577 if (atv->is_audio_track()) {
579 boost::shared_ptr<AudioPlaylist> pl;
580 if ((pl = boost::dynamic_pointer_cast<AudioPlaylist> (atv->get_diskstream()->playlist())) != 0) {
582 Playlist::RegionList* rl = pl->regions_at (event_frame (event));
585 DescendingRegionLayerSorter cmp;
588 RegionView* rv = atv->view()->find_view (rl->front());
594 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
606 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
608 switch (event->type) {
609 case GDK_BUTTON_PRESS:
610 case GDK_2BUTTON_PRESS:
611 case GDK_3BUTTON_PRESS:
612 clicked_control_point = cp;
613 clicked_axisview = &cp->line().trackview;
614 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
615 clicked_regionview = 0;
621 case GDK_SCROLL_DOWN:
628 return typed_event (item, event, ControlPointItem);
632 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
636 if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
639 type = AutomationLineItem;
642 return typed_event (item, event, type);
646 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
650 switch (event->type) {
651 case GDK_BUTTON_PRESS:
652 case GDK_2BUTTON_PRESS:
653 case GDK_3BUTTON_PRESS:
654 clicked_selection = rect->id;
655 ret = button_press_handler (item, event, SelectionItem);
657 case GDK_BUTTON_RELEASE:
658 ret = button_release_handler (item, event, SelectionItem);
660 case GDK_MOTION_NOTIFY:
661 ret = motion_handler (item, event, SelectionItem);
663 /* Don't need these at the moment. */
664 case GDK_ENTER_NOTIFY:
665 ret = enter_handler (item, event, SelectionItem);
668 case GDK_LEAVE_NOTIFY:
669 ret = leave_handler (item, event, SelectionItem);
680 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
684 switch (event->type) {
685 case GDK_BUTTON_PRESS:
686 case GDK_2BUTTON_PRESS:
687 case GDK_3BUTTON_PRESS:
688 clicked_selection = rect->id;
689 ret = button_press_handler (item, event, StartSelectionTrimItem);
691 case GDK_BUTTON_RELEASE:
692 ret = button_release_handler (item, event, StartSelectionTrimItem);
694 case GDK_MOTION_NOTIFY:
695 ret = motion_handler (item, event, StartSelectionTrimItem);
697 case GDK_ENTER_NOTIFY:
698 ret = enter_handler (item, event, StartSelectionTrimItem);
701 case GDK_LEAVE_NOTIFY:
702 ret = leave_handler (item, event, StartSelectionTrimItem);
713 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
717 switch (event->type) {
718 case GDK_BUTTON_PRESS:
719 case GDK_2BUTTON_PRESS:
720 case GDK_3BUTTON_PRESS:
721 clicked_selection = rect->id;
722 ret = button_press_handler (item, event, EndSelectionTrimItem);
724 case GDK_BUTTON_RELEASE:
725 ret = button_release_handler (item, event, EndSelectionTrimItem);
727 case GDK_MOTION_NOTIFY:
728 ret = motion_handler (item, event, EndSelectionTrimItem);
730 case GDK_ENTER_NOTIFY:
731 ret = enter_handler (item, event, EndSelectionTrimItem);
734 case GDK_LEAVE_NOTIFY:
735 ret = leave_handler (item, event, EndSelectionTrimItem);
747 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
751 if (!rv->sensitive()) {
755 switch (event->type) {
756 case GDK_BUTTON_PRESS:
757 case GDK_2BUTTON_PRESS:
758 case GDK_3BUTTON_PRESS:
759 clicked_regionview = rv;
760 clicked_control_point = 0;
761 clicked_axisview = &clicked_regionview->get_time_axis_view();
762 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
763 ret = button_press_handler (item, event, RegionViewNameHighlight);
765 case GDK_BUTTON_RELEASE:
766 ret = button_release_handler (item, event, RegionViewNameHighlight);
768 case GDK_MOTION_NOTIFY:
769 ret = motion_handler (item, event, RegionViewNameHighlight);
771 case GDK_ENTER_NOTIFY:
772 ret = enter_handler (item, event, RegionViewNameHighlight);
775 case GDK_LEAVE_NOTIFY:
776 ret = leave_handler (item, event, RegionViewNameHighlight);
787 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
791 if (!rv->sensitive()) {
795 switch (event->type) {
796 case GDK_BUTTON_PRESS:
797 case GDK_2BUTTON_PRESS:
798 case GDK_3BUTTON_PRESS:
799 clicked_regionview = rv;
800 clicked_control_point = 0;
801 clicked_axisview = &clicked_regionview->get_time_axis_view();
802 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
803 ret = button_press_handler (item, event, RegionViewName);
805 case GDK_BUTTON_RELEASE:
806 ret = button_release_handler (item, event, RegionViewName);
808 case GDK_MOTION_NOTIFY:
809 ret = motion_handler (item, event, RegionViewName);
811 case GDK_ENTER_NOTIFY:
812 ret = enter_handler (item, event, RegionViewName);
815 case GDK_LEAVE_NOTIFY:
816 ret = leave_handler (item, event, RegionViewName);
827 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* marker)
829 return typed_event (item, event, MarkerItem);
833 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
835 return typed_event (item, event, MarkerBarItem);
839 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
841 return typed_event (item, event, RangeMarkerBarItem);
845 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
847 return typed_event (item, event, TransportMarkerBarItem);
851 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
853 return typed_event (item, event, CdMarkerBarItem);
857 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
859 return typed_event (item, event, TempoMarkerItem);
863 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* marker)
865 return typed_event (item, event, MeterMarkerItem);
869 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
871 return typed_event (item, event, TempoBarItem);
875 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
877 return typed_event (item, event, MeterBarItem);
881 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
883 return typed_event (item, event, PlayheadCursorItem);
887 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
889 return typed_event (item, event, NoItem);