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());
161 Editor::track_canvas_scroll_event (GdkEventScroll *event)
163 track_canvas.grab_focus();
164 track_canvas_scroll (event);
169 Editor::track_canvas_button_press_event (GdkEventButton *event)
172 track_canvas.grab_focus();
177 Editor::track_canvas_button_release_event (GdkEventButton *event)
179 if (drag_info.item) {
180 end_grab (drag_info.item, (GdkEvent*) event);
186 Editor::track_canvas_motion_notify_event (GdkEventMotion *event)
189 /* keep those motion events coming */
190 track_canvas.get_pointer (x, y);
195 Editor::track_canvas_motion (GdkEvent *ev)
197 if (verbose_cursor_visible) {
198 verbose_canvas_cursor->property_x() = ev->motion.x + 20;
199 verbose_canvas_cursor->property_y() = ev->motion.y + 20;
210 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
214 switch (event->type) {
215 case GDK_BUTTON_PRESS:
216 case GDK_2BUTTON_PRESS:
217 case GDK_3BUTTON_PRESS:
218 ret = button_press_handler (item, event, type);
220 case GDK_BUTTON_RELEASE:
221 ret = button_release_handler (item, event, type);
223 case GDK_MOTION_NOTIFY:
224 ret = motion_handler (item, event, type);
227 case GDK_ENTER_NOTIFY:
228 ret = enter_handler (item, event, type);
231 case GDK_LEAVE_NOTIFY:
232 ret = leave_handler (item, event, type);
242 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
246 if (!rv->sensitive ()) {
251 switch (event->type) {
252 case GDK_BUTTON_PRESS:
253 case GDK_2BUTTON_PRESS:
254 case GDK_3BUTTON_PRESS:
255 clicked_regionview = rv;
256 clicked_control_point = 0;
257 clicked_trackview = &rv->get_time_axis_view();
258 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
259 ret = button_press_handler (item, event, RegionItem);
262 case GDK_BUTTON_RELEASE:
263 ret = button_release_handler (item, event, RegionItem);
266 case GDK_MOTION_NOTIFY:
267 ret = motion_handler (item, event, RegionItem);
270 case GDK_ENTER_NOTIFY:
271 set_entered_track (&rv->get_time_axis_view ());
272 set_entered_regionview (rv);
275 case GDK_LEAVE_NOTIFY:
276 set_entered_track (0);
277 set_entered_regionview (0);
288 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
292 switch (event->type) {
293 case GDK_BUTTON_PRESS:
294 case GDK_2BUTTON_PRESS:
295 case GDK_3BUTTON_PRESS:
296 clicked_regionview = 0;
297 clicked_control_point = 0;
298 clicked_trackview = tv;
299 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(tv);
300 ret = button_press_handler (item, event, StreamItem);
303 case GDK_BUTTON_RELEASE:
304 ret = button_release_handler (item, event, StreamItem);
307 case GDK_MOTION_NOTIFY:
308 ret = motion_handler (item, event, StreamItem);
311 case GDK_ENTER_NOTIFY:
312 set_entered_track (tv);
315 case GDK_LEAVE_NOTIFY:
316 set_entered_track (0);
327 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
332 switch (event->type) {
333 case GDK_BUTTON_PRESS:
334 case GDK_2BUTTON_PRESS:
335 case GDK_3BUTTON_PRESS:
336 clicked_regionview = 0;
337 clicked_control_point = 0;
338 clicked_trackview = atv;
339 clicked_audio_trackview = 0;
340 ret = button_press_handler (item, event, AutomationTrackItem);
343 case GDK_BUTTON_RELEASE:
344 ret = button_release_handler (item, event, AutomationTrackItem);
347 case GDK_MOTION_NOTIFY:
348 ret = motion_handler (item, event, AutomationTrackItem);
351 case GDK_ENTER_NOTIFY:
352 ret = enter_handler (item, event, AutomationTrackItem);
355 case GDK_LEAVE_NOTIFY:
356 ret = leave_handler (item, event, AutomationTrackItem);
367 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
369 /* we handle only button 3 press/release events */
371 if (!rv->sensitive()) {
375 switch (event->type) {
376 case GDK_BUTTON_PRESS:
377 clicked_regionview = rv;
378 clicked_control_point = 0;
379 clicked_trackview = &rv->get_time_axis_view();
380 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
381 if (event->button.button == 3) {
382 return button_press_handler (item, event, FadeInItem);
386 case GDK_BUTTON_RELEASE:
387 if (event->button.button == 3) {
388 return button_release_handler (item, event, FadeInItem);
397 /* proxy for the regionview */
399 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
403 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
407 if (!rv->sensitive()) {
411 switch (event->type) {
412 case GDK_BUTTON_PRESS:
413 case GDK_2BUTTON_PRESS:
414 case GDK_3BUTTON_PRESS:
415 clicked_regionview = rv;
416 clicked_control_point = 0;
417 clicked_trackview = &rv->get_time_axis_view();
418 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
419 ret = button_press_handler (item, event, FadeInHandleItem);
422 case GDK_BUTTON_RELEASE:
423 ret = button_release_handler (item, event, FadeInHandleItem);
426 case GDK_MOTION_NOTIFY:
427 ret = motion_handler (item, event, FadeInHandleItem);
430 case GDK_ENTER_NOTIFY:
431 ret = enter_handler (item, event, FadeInHandleItem);
434 case GDK_LEAVE_NOTIFY:
435 ret = leave_handler (item, event, FadeInHandleItem);
446 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
448 /* we handle only button 3 press/release events */
450 if (!rv->sensitive()) {
454 switch (event->type) {
455 case GDK_BUTTON_PRESS:
456 clicked_regionview = rv;
457 clicked_control_point = 0;
458 clicked_trackview = &rv->get_time_axis_view();
459 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
460 if (event->button.button == 3) {
461 return button_press_handler (item, event, FadeOutItem);
465 case GDK_BUTTON_RELEASE:
466 if (event->button.button == 3) {
467 return button_release_handler (item, event, FadeOutItem);
476 /* proxy for the regionview */
478 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
482 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
486 if (!rv->sensitive()) {
490 switch (event->type) {
491 case GDK_BUTTON_PRESS:
492 case GDK_2BUTTON_PRESS:
493 case GDK_3BUTTON_PRESS:
494 clicked_regionview = rv;
495 clicked_control_point = 0;
496 clicked_trackview = &rv->get_time_axis_view();
497 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
498 ret = button_press_handler (item, event, FadeOutHandleItem);
501 case GDK_BUTTON_RELEASE:
502 ret = button_release_handler (item, event, FadeOutHandleItem);
505 case GDK_MOTION_NOTIFY:
506 ret = motion_handler (item, event, FadeOutHandleItem);
509 case GDK_ENTER_NOTIFY:
510 ret = enter_handler (item, event, FadeOutHandleItem);
513 case GDK_LEAVE_NOTIFY:
514 ret = leave_handler (item, event, FadeOutHandleItem);
524 struct DescendingRegionLayerSorter {
525 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
526 return a->layer() > b->layer();
531 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
533 /* we handle only button 3 press/release events */
535 switch (event->type) {
536 case GDK_BUTTON_PRESS:
537 clicked_crossfadeview = xfv;
538 clicked_trackview = &clicked_crossfadeview->get_time_axis_view();
539 if (event->button.button == 3) {
540 return button_press_handler (item, event, CrossfadeViewItem);
544 case GDK_BUTTON_RELEASE:
545 if (event->button.button == 3) {
546 bool ret = button_release_handler (item, event, CrossfadeViewItem);
556 /* XXX do not forward double clicks */
558 if (event->type == GDK_2BUTTON_PRESS) {
562 /* proxy for the upper most regionview */
564 /* XXX really need to check if we are in the name highlight,
565 and proxy to that when required.
568 TimeAxisView& tv (xfv->get_time_axis_view());
569 AudioTimeAxisView* atv;
571 if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
573 if (atv->is_audio_track()) {
575 boost::shared_ptr<AudioPlaylist> pl;
576 if ((pl = boost::dynamic_pointer_cast<AudioPlaylist> (atv->get_diskstream()->playlist())) != 0) {
578 Playlist::RegionList* rl = pl->regions_at (event_frame (event));
581 DescendingRegionLayerSorter cmp;
584 RegionView* rv = atv->view()->find_view (rl->front());
590 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
602 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
606 switch (event->type) {
607 case GDK_BUTTON_PRESS:
608 case GDK_2BUTTON_PRESS:
609 case GDK_3BUTTON_PRESS:
610 clicked_control_point = cp;
611 clicked_trackview = &cp->line.trackview;
612 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
613 clicked_regionview = 0;
619 case GDK_SCROLL_DOWN:
626 if (dynamic_cast<AudioRegionGainLine*> (&cp->line) != 0) {
627 type = GainControlPointItem;
628 } else if (dynamic_cast<AutomationGainLine*> (&cp->line) != 0) {
629 type = GainAutomationControlPointItem;
630 } else if (dynamic_cast<AutomationPanLine*> (&cp->line) != 0) {
631 type = PanAutomationControlPointItem;
632 } else if (dynamic_cast<RedirectAutomationLine*> (&cp->line) != 0) {
633 type = RedirectAutomationControlPointItem;
638 return typed_event (item, event, type);
642 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
646 if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
648 } else if (dynamic_cast<AutomationGainLine*> (al) != 0) {
649 type = GainAutomationLineItem;
650 } else if (dynamic_cast<AutomationPanLine*> (al) != 0) {
651 type = PanAutomationLineItem;
652 } else if (dynamic_cast<RedirectAutomationLine*> (al) != 0) {
653 type = RedirectAutomationLineItem;
658 return typed_event (item, event, type);
662 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
666 switch (event->type) {
667 case GDK_BUTTON_PRESS:
668 case GDK_2BUTTON_PRESS:
669 case GDK_3BUTTON_PRESS:
670 clicked_selection = rect->id;
671 ret = button_press_handler (item, event, SelectionItem);
673 case GDK_BUTTON_RELEASE:
674 ret = button_release_handler (item, event, SelectionItem);
676 case GDK_MOTION_NOTIFY:
677 ret = motion_handler (item, event, SelectionItem);
679 /* Don't need these at the moment. */
680 case GDK_ENTER_NOTIFY:
681 ret = enter_handler (item, event, SelectionItem);
684 case GDK_LEAVE_NOTIFY:
685 ret = leave_handler (item, event, SelectionItem);
696 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
700 switch (event->type) {
701 case GDK_BUTTON_PRESS:
702 case GDK_2BUTTON_PRESS:
703 case GDK_3BUTTON_PRESS:
704 clicked_selection = rect->id;
705 ret = button_press_handler (item, event, StartSelectionTrimItem);
707 case GDK_BUTTON_RELEASE:
708 ret = button_release_handler (item, event, StartSelectionTrimItem);
710 case GDK_MOTION_NOTIFY:
711 ret = motion_handler (item, event, StartSelectionTrimItem);
713 case GDK_ENTER_NOTIFY:
714 ret = enter_handler (item, event, StartSelectionTrimItem);
717 case GDK_LEAVE_NOTIFY:
718 ret = leave_handler (item, event, StartSelectionTrimItem);
729 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
733 switch (event->type) {
734 case GDK_BUTTON_PRESS:
735 case GDK_2BUTTON_PRESS:
736 case GDK_3BUTTON_PRESS:
737 clicked_selection = rect->id;
738 ret = button_press_handler (item, event, EndSelectionTrimItem);
740 case GDK_BUTTON_RELEASE:
741 ret = button_release_handler (item, event, EndSelectionTrimItem);
743 case GDK_MOTION_NOTIFY:
744 ret = motion_handler (item, event, EndSelectionTrimItem);
746 case GDK_ENTER_NOTIFY:
747 ret = enter_handler (item, event, EndSelectionTrimItem);
750 case GDK_LEAVE_NOTIFY:
751 ret = leave_handler (item, event, EndSelectionTrimItem);
763 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
767 if (!rv->sensitive()) {
771 switch (event->type) {
772 case GDK_BUTTON_PRESS:
773 case GDK_2BUTTON_PRESS:
774 case GDK_3BUTTON_PRESS:
775 clicked_regionview = rv;
776 clicked_control_point = 0;
777 clicked_trackview = &clicked_regionview->get_time_axis_view();
778 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
779 ret = button_press_handler (item, event, RegionViewNameHighlight);
781 case GDK_BUTTON_RELEASE:
782 ret = button_release_handler (item, event, RegionViewNameHighlight);
784 case GDK_MOTION_NOTIFY:
785 ret = motion_handler (item, event, RegionViewNameHighlight);
787 case GDK_ENTER_NOTIFY:
788 ret = enter_handler (item, event, RegionViewNameHighlight);
791 case GDK_LEAVE_NOTIFY:
792 ret = leave_handler (item, event, RegionViewNameHighlight);
803 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
807 if (!rv->sensitive()) {
811 switch (event->type) {
812 case GDK_BUTTON_PRESS:
813 case GDK_2BUTTON_PRESS:
814 case GDK_3BUTTON_PRESS:
815 clicked_regionview = rv;
816 clicked_control_point = 0;
817 clicked_trackview = &clicked_regionview->get_time_axis_view();
818 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
819 ret = button_press_handler (item, event, RegionViewName);
821 case GDK_BUTTON_RELEASE:
822 ret = button_release_handler (item, event, RegionViewName);
824 case GDK_MOTION_NOTIFY:
825 ret = motion_handler (item, event, RegionViewName);
827 case GDK_ENTER_NOTIFY:
828 ret = enter_handler (item, event, RegionViewName);
831 case GDK_LEAVE_NOTIFY:
832 ret = leave_handler (item, event, RegionViewName);
843 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* marker)
845 return typed_event (item, event, MarkerItem);
849 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
851 return typed_event (item, event, MarkerBarItem);
855 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
857 return typed_event (item, event, RangeMarkerBarItem);
861 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
863 return typed_event (item, event, TransportMarkerBarItem);
867 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
869 return typed_event (item, event, CdMarkerBarItem);
873 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
875 return typed_event (item, event, TempoMarkerItem);
879 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* marker)
881 return typed_event (item, event, MeterMarkerItem);
885 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
887 return typed_event (item, event, TempoBarItem);
891 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
893 return typed_event (item, event, MeterBarItem);
897 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
899 return typed_event (item, event, PlayheadCursorItem);
903 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
905 return typed_event (item, event, NoItem);