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.
23 #include <pbd/stacktrace.h>
25 #include <ardour/audio_diskstream.h>
26 #include <ardour/audioplaylist.h>
30 #include "public_editor.h"
31 #include "audio_region_view.h"
32 #include "audio_streamview.h"
33 #include "crossfade_view.h"
34 #include "audio_time_axis.h"
35 #include "region_gain_line.h"
36 #include "automation_gain_line.h"
37 #include "automation_pan_line.h"
38 #include "automation_time_axis.h"
39 #include "redirect_automation_line.h"
40 #include "canvas_impl.h"
41 #include "simplerect.h"
46 using namespace ARDOUR;
51 Editor::track_canvas_scroll (GdkEventScroll* ev)
56 int direction = ev->direction;
61 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
62 //if (ev->state == GDK_CONTROL_MASK) {
64 the ev->x will be out of step with the canvas
65 if we're in mid zoom, so we have to get the damn mouse
68 track_canvas.get_pointer (x, y);
69 track_canvas.window_to_world (x, y, wx, wy);
70 wx += horizontal_adjustment.get_value();
71 wy += vertical_adjustment.get_value();
74 event.type = GDK_BUTTON_RELEASE;
78 nframes_t where = event_frame (&event, 0, 0);
79 temporal_zoom_to_frame (false, where);
81 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
82 direction = GDK_SCROLL_LEFT;
84 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
85 if (!current_stepping_trackview) {
86 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
87 if (!(current_stepping_trackview = trackview_by_y_position (ev->y))) {
91 gettimeofday (&last_track_height_step_timestamp, 0);
92 current_stepping_trackview->step_height (true);
95 scroll_tracks_up_line ();
100 case GDK_SCROLL_DOWN:
101 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
102 //if (ev->state == GDK_CONTROL_MASK) {
103 track_canvas.get_pointer (x, y);
104 track_canvas.window_to_world (x, y, wx, wy);
105 wx += horizontal_adjustment.get_value();
106 wy += vertical_adjustment.get_value();
109 event.type = GDK_BUTTON_RELEASE;
113 nframes_t where = event_frame (&event, 0, 0);
114 temporal_zoom_to_frame (true, where);
116 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
117 direction = GDK_SCROLL_RIGHT;
119 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
120 if (!current_stepping_trackview) {
121 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
122 if (!(current_stepping_trackview = trackview_by_y_position (ev->y))) {
126 gettimeofday (&last_track_height_step_timestamp, 0);
127 current_stepping_trackview->step_height (false);
130 scroll_tracks_down_line ();
135 case GDK_SCROLL_LEFT:
136 xdelta = (current_page_frames() / 2);
137 if (leftmost_frame > xdelta) {
138 reset_x_origin (leftmost_frame - xdelta);
144 case GDK_SCROLL_RIGHT:
145 xdelta = (current_page_frames() / 2);
146 if (max_frames - xdelta > leftmost_frame) {
147 reset_x_origin (leftmost_frame + xdelta);
149 reset_x_origin (max_frames - current_page_frames());
162 Editor::track_canvas_scroll_event (GdkEventScroll *event)
164 track_canvas.grab_focus();
165 track_canvas_scroll (event);
170 Editor::time_canvas_scroll (GdkEventScroll* ev)
173 int direction = ev->direction;
177 temporal_zoom_step (true);
180 case GDK_SCROLL_DOWN:
181 temporal_zoom_step (false);
184 case GDK_SCROLL_LEFT:
185 xdelta = (current_page_frames() / 2);
186 if (leftmost_frame > xdelta) {
187 reset_x_origin (leftmost_frame - xdelta);
193 case GDK_SCROLL_RIGHT:
194 xdelta = (current_page_frames() / 2);
195 if (max_frames - xdelta > leftmost_frame) {
196 reset_x_origin (leftmost_frame + xdelta);
198 reset_x_origin (max_frames - current_page_frames());
211 Editor::time_canvas_scroll_event (GdkEventScroll *event)
213 time_canvas.grab_focus();
214 time_canvas_scroll (event);
219 Editor::track_canvas_button_press_event (GdkEventButton *event)
222 track_canvas.grab_focus();
227 Editor::track_canvas_button_release_event (GdkEventButton *event)
229 if (drag_info.item) {
230 end_grab (drag_info.item, (GdkEvent*) event);
236 Editor::track_canvas_motion_notify_event (GdkEventMotion *event)
239 /* keep those motion events coming */
240 track_canvas.get_pointer (x, y);
245 Editor::track_canvas_motion (GdkEvent *ev)
247 if (verbose_cursor_visible) {
248 verbose_canvas_cursor->property_x() = ev->motion.x + 20;
249 verbose_canvas_cursor->property_y() = ev->motion.y + 20;
260 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
264 switch (event->type) {
265 case GDK_BUTTON_PRESS:
266 case GDK_2BUTTON_PRESS:
267 case GDK_3BUTTON_PRESS:
268 ret = button_press_handler (item, event, type);
270 case GDK_BUTTON_RELEASE:
271 ret = button_release_handler (item, event, type);
273 case GDK_MOTION_NOTIFY:
274 ret = motion_handler (item, event, type);
277 case GDK_ENTER_NOTIFY:
278 ret = enter_handler (item, event, type);
281 case GDK_LEAVE_NOTIFY:
282 ret = leave_handler (item, event, type);
292 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
296 if (!rv->sensitive ()) {
301 switch (event->type) {
302 case GDK_BUTTON_PRESS:
303 case GDK_2BUTTON_PRESS:
304 case GDK_3BUTTON_PRESS:
305 clicked_regionview = rv;
306 clicked_control_point = 0;
307 clicked_trackview = &rv->get_time_axis_view();
308 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
309 ret = button_press_handler (item, event, RegionItem);
312 case GDK_BUTTON_RELEASE:
313 ret = button_release_handler (item, event, RegionItem);
316 case GDK_MOTION_NOTIFY:
317 ret = motion_handler (item, event, RegionItem);
320 case GDK_ENTER_NOTIFY:
321 set_entered_track (&rv->get_time_axis_view ());
322 set_entered_regionview (rv);
325 case GDK_LEAVE_NOTIFY:
326 set_entered_track (0);
327 set_entered_regionview (0);
338 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
342 switch (event->type) {
343 case GDK_BUTTON_PRESS:
344 case GDK_2BUTTON_PRESS:
345 case GDK_3BUTTON_PRESS:
346 clicked_regionview = 0;
347 clicked_control_point = 0;
348 clicked_trackview = tv;
349 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(tv);
350 ret = button_press_handler (item, event, StreamItem);
353 case GDK_BUTTON_RELEASE:
354 ret = button_release_handler (item, event, StreamItem);
357 case GDK_MOTION_NOTIFY:
358 ret = motion_handler (item, event, StreamItem);
361 case GDK_ENTER_NOTIFY:
362 set_entered_track (tv);
365 case GDK_LEAVE_NOTIFY:
366 set_entered_track (0);
377 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
382 switch (event->type) {
383 case GDK_BUTTON_PRESS:
384 case GDK_2BUTTON_PRESS:
385 case GDK_3BUTTON_PRESS:
386 clicked_regionview = 0;
387 clicked_control_point = 0;
388 clicked_trackview = atv;
389 clicked_audio_trackview = 0;
390 ret = button_press_handler (item, event, AutomationTrackItem);
393 case GDK_BUTTON_RELEASE:
394 ret = button_release_handler (item, event, AutomationTrackItem);
397 case GDK_MOTION_NOTIFY:
398 ret = motion_handler (item, event, AutomationTrackItem);
401 case GDK_ENTER_NOTIFY:
402 ret = enter_handler (item, event, AutomationTrackItem);
405 case GDK_LEAVE_NOTIFY:
406 ret = leave_handler (item, event, AutomationTrackItem);
417 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
419 /* we handle only button 3 press/release events */
421 if (!rv->sensitive()) {
425 switch (event->type) {
426 case GDK_BUTTON_PRESS:
427 clicked_regionview = rv;
428 clicked_control_point = 0;
429 clicked_trackview = &rv->get_time_axis_view();
430 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
431 if (event->button.button == 3) {
432 return button_press_handler (item, event, FadeInItem);
436 case GDK_BUTTON_RELEASE:
437 if (event->button.button == 3) {
438 return button_release_handler (item, event, FadeInItem);
447 /* proxy for the regionview */
449 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
453 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
457 if (!rv->sensitive()) {
461 switch (event->type) {
462 case GDK_BUTTON_PRESS:
463 case GDK_2BUTTON_PRESS:
464 case GDK_3BUTTON_PRESS:
465 clicked_regionview = rv;
466 clicked_control_point = 0;
467 clicked_trackview = &rv->get_time_axis_view();
468 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
469 ret = button_press_handler (item, event, FadeInHandleItem);
472 case GDK_BUTTON_RELEASE:
473 ret = button_release_handler (item, event, FadeInHandleItem);
476 case GDK_MOTION_NOTIFY:
477 ret = motion_handler (item, event, FadeInHandleItem);
480 case GDK_ENTER_NOTIFY:
481 ret = enter_handler (item, event, FadeInHandleItem);
484 case GDK_LEAVE_NOTIFY:
485 ret = leave_handler (item, event, FadeInHandleItem);
496 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
498 /* we handle only button 3 press/release events */
500 if (!rv->sensitive()) {
504 switch (event->type) {
505 case GDK_BUTTON_PRESS:
506 clicked_regionview = rv;
507 clicked_control_point = 0;
508 clicked_trackview = &rv->get_time_axis_view();
509 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
510 if (event->button.button == 3) {
511 return button_press_handler (item, event, FadeOutItem);
515 case GDK_BUTTON_RELEASE:
516 if (event->button.button == 3) {
517 return button_release_handler (item, event, FadeOutItem);
526 /* proxy for the regionview */
528 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
532 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
536 if (!rv->sensitive()) {
540 switch (event->type) {
541 case GDK_BUTTON_PRESS:
542 case GDK_2BUTTON_PRESS:
543 case GDK_3BUTTON_PRESS:
544 clicked_regionview = rv;
545 clicked_control_point = 0;
546 clicked_trackview = &rv->get_time_axis_view();
547 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
548 ret = button_press_handler (item, event, FadeOutHandleItem);
551 case GDK_BUTTON_RELEASE:
552 ret = button_release_handler (item, event, FadeOutHandleItem);
555 case GDK_MOTION_NOTIFY:
556 ret = motion_handler (item, event, FadeOutHandleItem);
559 case GDK_ENTER_NOTIFY:
560 ret = enter_handler (item, event, FadeOutHandleItem);
563 case GDK_LEAVE_NOTIFY:
564 ret = leave_handler (item, event, FadeOutHandleItem);
574 struct DescendingRegionLayerSorter {
575 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
576 return a->layer() > b->layer();
581 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
583 /* we handle only button 3 press/release events */
585 switch (event->type) {
586 case GDK_BUTTON_PRESS:
587 clicked_crossfadeview = xfv;
588 clicked_trackview = &clicked_crossfadeview->get_time_axis_view();
589 if (event->button.button == 3) {
590 return button_press_handler (item, event, CrossfadeViewItem);
594 case GDK_BUTTON_RELEASE:
595 if (event->button.button == 3) {
596 bool ret = button_release_handler (item, event, CrossfadeViewItem);
606 /* XXX do not forward double clicks */
608 if (event->type == GDK_2BUTTON_PRESS) {
612 /* proxy for the upper most regionview */
614 /* XXX really need to check if we are in the name highlight,
615 and proxy to that when required.
618 TimeAxisView& tv (xfv->get_time_axis_view());
619 AudioTimeAxisView* atv;
621 if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
623 if (atv->is_audio_track()) {
625 boost::shared_ptr<AudioPlaylist> pl;
626 if ((pl = boost::dynamic_pointer_cast<AudioPlaylist> (atv->get_diskstream()->playlist())) != 0) {
628 Playlist::RegionList* rl = pl->regions_at (event_frame (event));
631 DescendingRegionLayerSorter cmp;
634 RegionView* rv = atv->view()->find_view (rl->front());
640 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
652 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
656 switch (event->type) {
657 case GDK_BUTTON_PRESS:
658 case GDK_2BUTTON_PRESS:
659 case GDK_3BUTTON_PRESS:
660 clicked_control_point = cp;
661 clicked_trackview = &cp->line.trackview;
662 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
663 clicked_regionview = 0;
669 case GDK_SCROLL_DOWN:
676 if (dynamic_cast<AudioRegionGainLine*> (&cp->line) != 0) {
677 type = GainControlPointItem;
678 } else if (dynamic_cast<AutomationGainLine*> (&cp->line) != 0) {
679 type = GainAutomationControlPointItem;
680 } else if (dynamic_cast<AutomationPanLine*> (&cp->line) != 0) {
681 type = PanAutomationControlPointItem;
682 } else if (dynamic_cast<RedirectAutomationLine*> (&cp->line) != 0) {
683 type = RedirectAutomationControlPointItem;
688 return typed_event (item, event, type);
692 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
696 if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
698 } else if (dynamic_cast<AutomationGainLine*> (al) != 0) {
699 type = GainAutomationLineItem;
700 } else if (dynamic_cast<AutomationPanLine*> (al) != 0) {
701 type = PanAutomationLineItem;
702 } else if (dynamic_cast<RedirectAutomationLine*> (al) != 0) {
703 type = RedirectAutomationLineItem;
708 return typed_event (item, event, type);
712 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
716 switch (event->type) {
717 case GDK_BUTTON_PRESS:
718 case GDK_2BUTTON_PRESS:
719 case GDK_3BUTTON_PRESS:
720 clicked_selection = rect->id;
721 ret = button_press_handler (item, event, SelectionItem);
723 case GDK_BUTTON_RELEASE:
724 ret = button_release_handler (item, event, SelectionItem);
726 case GDK_MOTION_NOTIFY:
727 ret = motion_handler (item, event, SelectionItem);
729 /* Don't need these at the moment. */
730 case GDK_ENTER_NOTIFY:
731 ret = enter_handler (item, event, SelectionItem);
734 case GDK_LEAVE_NOTIFY:
735 ret = leave_handler (item, event, SelectionItem);
746 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
750 switch (event->type) {
751 case GDK_BUTTON_PRESS:
752 case GDK_2BUTTON_PRESS:
753 case GDK_3BUTTON_PRESS:
754 clicked_selection = rect->id;
755 ret = button_press_handler (item, event, StartSelectionTrimItem);
757 case GDK_BUTTON_RELEASE:
758 ret = button_release_handler (item, event, StartSelectionTrimItem);
760 case GDK_MOTION_NOTIFY:
761 ret = motion_handler (item, event, StartSelectionTrimItem);
763 case GDK_ENTER_NOTIFY:
764 ret = enter_handler (item, event, StartSelectionTrimItem);
767 case GDK_LEAVE_NOTIFY:
768 ret = leave_handler (item, event, StartSelectionTrimItem);
779 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
783 switch (event->type) {
784 case GDK_BUTTON_PRESS:
785 case GDK_2BUTTON_PRESS:
786 case GDK_3BUTTON_PRESS:
787 clicked_selection = rect->id;
788 ret = button_press_handler (item, event, EndSelectionTrimItem);
790 case GDK_BUTTON_RELEASE:
791 ret = button_release_handler (item, event, EndSelectionTrimItem);
793 case GDK_MOTION_NOTIFY:
794 ret = motion_handler (item, event, EndSelectionTrimItem);
796 case GDK_ENTER_NOTIFY:
797 ret = enter_handler (item, event, EndSelectionTrimItem);
800 case GDK_LEAVE_NOTIFY:
801 ret = leave_handler (item, event, EndSelectionTrimItem);
813 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
817 if (!rv->sensitive()) {
821 switch (event->type) {
822 case GDK_BUTTON_PRESS:
823 case GDK_2BUTTON_PRESS:
824 case GDK_3BUTTON_PRESS:
825 clicked_regionview = rv;
826 clicked_control_point = 0;
827 clicked_trackview = &clicked_regionview->get_time_axis_view();
828 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
829 ret = button_press_handler (item, event, RegionViewNameHighlight);
831 case GDK_BUTTON_RELEASE:
832 ret = button_release_handler (item, event, RegionViewNameHighlight);
834 case GDK_MOTION_NOTIFY:
835 ret = motion_handler (item, event, RegionViewNameHighlight);
837 case GDK_ENTER_NOTIFY:
838 ret = enter_handler (item, event, RegionViewNameHighlight);
841 case GDK_LEAVE_NOTIFY:
842 ret = leave_handler (item, event, RegionViewNameHighlight);
853 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
857 if (!rv->sensitive()) {
861 switch (event->type) {
862 case GDK_BUTTON_PRESS:
863 case GDK_2BUTTON_PRESS:
864 case GDK_3BUTTON_PRESS:
865 clicked_regionview = rv;
866 clicked_control_point = 0;
867 clicked_trackview = &clicked_regionview->get_time_axis_view();
868 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
869 ret = button_press_handler (item, event, RegionViewName);
871 case GDK_BUTTON_RELEASE:
872 ret = button_release_handler (item, event, RegionViewName);
874 case GDK_MOTION_NOTIFY:
875 ret = motion_handler (item, event, RegionViewName);
877 case GDK_ENTER_NOTIFY:
878 ret = enter_handler (item, event, RegionViewName);
881 case GDK_LEAVE_NOTIFY:
882 ret = leave_handler (item, event, RegionViewName);
893 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* marker)
895 return typed_event (item, event, MarkerItem);
899 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
901 return typed_event (item, event, MarkerBarItem);
905 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
907 return typed_event (item, event, RangeMarkerBarItem);
911 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
913 return typed_event (item, event, TransportMarkerBarItem);
917 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
919 return typed_event (item, event, CdMarkerBarItem);
923 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
925 return typed_event (item, event, TempoMarkerItem);
929 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* marker)
931 return typed_event (item, event, MeterMarkerItem);
935 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
937 return typed_event (item, event, TempoBarItem);
941 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
943 return typed_event (item, event, MeterBarItem);
947 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
949 return typed_event (item, event, PlayheadCursorItem);
953 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
955 return typed_event (item, event, NoItem);