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 switch (ev->direction) {
58 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
59 //if (ev->state == GDK_CONTROL_MASK) {
61 the ev->x will be out of step with the canvas
62 if we're in mid zoom, so we have to get the damn mouse
65 track_canvas.get_pointer (x, y);
66 track_canvas.window_to_world (x, y, wx, wy);
67 wx += horizontal_adjustment.get_value();
68 wy += vertical_adjustment.get_value();
71 event.type = GDK_BUTTON_RELEASE;
75 nframes_t where = event_frame (&event, 0, 0);
76 temporal_zoom_to_frame (false, where);
78 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
79 if (!current_stepping_trackview) {
80 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
81 if (!(current_stepping_trackview = trackview_by_y_position (ev->y))) {
85 gettimeofday (&last_track_height_step_timestamp, 0);
86 current_stepping_trackview->step_height (true);
89 scroll_tracks_up_line ();
94 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
95 //if (ev->state == GDK_CONTROL_MASK) {
96 track_canvas.get_pointer (x, y);
97 track_canvas.window_to_world (x, y, wx, wy);
98 wx += horizontal_adjustment.get_value();
99 wy += vertical_adjustment.get_value();
102 event.type = GDK_BUTTON_RELEASE;
106 nframes_t where = event_frame (&event, 0, 0);
107 temporal_zoom_to_frame (true, where);
109 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
110 if (!current_stepping_trackview) {
111 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
112 if (!(current_stepping_trackview = trackview_by_y_position (ev->y))) {
116 gettimeofday (&last_track_height_step_timestamp, 0);
117 current_stepping_trackview->step_height (false);
120 scroll_tracks_down_line ();
126 /* no left/right handling yet */
134 Editor::track_canvas_scroll_event (GdkEventScroll *event)
136 track_canvas.grab_focus();
137 track_canvas_scroll (event);
142 Editor::track_canvas_button_press_event (GdkEventButton *event)
144 track_canvas.grab_focus();
149 Editor::track_canvas_button_release_event (GdkEventButton *event)
151 if (drag_info.item) {
152 end_grab (drag_info.item, (GdkEvent*) event);
158 Editor::track_canvas_motion_notify_event (GdkEventMotion *event)
161 /* keep those motion events coming */
162 track_canvas.get_pointer (x, y);
167 Editor::track_canvas_motion (GdkEvent *ev)
169 if (verbose_cursor_visible) {
170 verbose_canvas_cursor->property_x() = ev->motion.x + 20;
171 verbose_canvas_cursor->property_y() = ev->motion.y + 20;
177 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
181 switch (event->type) {
182 case GDK_BUTTON_PRESS:
183 case GDK_2BUTTON_PRESS:
184 case GDK_3BUTTON_PRESS:
185 ret = button_press_handler (item, event, type);
187 case GDK_BUTTON_RELEASE:
188 ret = button_release_handler (item, event, type);
190 case GDK_MOTION_NOTIFY:
191 ret = motion_handler (item, event, type);
194 case GDK_ENTER_NOTIFY:
195 ret = enter_handler (item, event, type);
198 case GDK_LEAVE_NOTIFY:
199 ret = leave_handler (item, event, type);
210 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
214 if (!rv->sensitive ()) {
219 switch (event->type) {
220 case GDK_BUTTON_PRESS:
221 case GDK_2BUTTON_PRESS:
222 case GDK_3BUTTON_PRESS:
223 clicked_regionview = rv;
224 clicked_control_point = 0;
225 clicked_trackview = &rv->get_time_axis_view();
226 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
227 ret = button_press_handler (item, event, RegionItem);
230 case GDK_BUTTON_RELEASE:
231 ret = button_release_handler (item, event, RegionItem);
234 case GDK_MOTION_NOTIFY:
235 ret = motion_handler (item, event, RegionItem);
238 case GDK_ENTER_NOTIFY:
239 set_entered_regionview (rv);
242 case GDK_LEAVE_NOTIFY:
243 set_entered_regionview (0);
254 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
258 switch (event->type) {
259 case GDK_BUTTON_PRESS:
260 case GDK_2BUTTON_PRESS:
261 case GDK_3BUTTON_PRESS:
262 clicked_regionview = 0;
263 clicked_control_point = 0;
264 clicked_trackview = tv;
265 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(tv);
266 ret = button_press_handler (item, event, StreamItem);
269 case GDK_BUTTON_RELEASE:
270 ret = button_release_handler (item, event, StreamItem);
273 case GDK_MOTION_NOTIFY:
274 ret = motion_handler (item, event, StreamItem);
277 case GDK_ENTER_NOTIFY:
290 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
295 switch (event->type) {
296 case GDK_BUTTON_PRESS:
297 case GDK_2BUTTON_PRESS:
298 case GDK_3BUTTON_PRESS:
299 clicked_regionview = 0;
300 clicked_control_point = 0;
301 clicked_trackview = atv;
302 clicked_audio_trackview = 0;
303 ret = button_press_handler (item, event, AutomationTrackItem);
306 case GDK_BUTTON_RELEASE:
307 ret = button_release_handler (item, event, AutomationTrackItem);
310 case GDK_MOTION_NOTIFY:
311 ret = motion_handler (item, event, AutomationTrackItem);
314 case GDK_ENTER_NOTIFY:
315 ret = enter_handler (item, event, AutomationTrackItem);
318 case GDK_LEAVE_NOTIFY:
319 ret = leave_handler (item, event, AutomationTrackItem);
330 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
332 /* we handle only button 3 press/release events */
334 if (!rv->sensitive()) {
338 switch (event->type) {
339 case GDK_BUTTON_PRESS:
340 clicked_regionview = rv;
341 clicked_control_point = 0;
342 clicked_trackview = &rv->get_time_axis_view();
343 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
344 if (event->button.button == 3) {
345 return button_press_handler (item, event, FadeInItem);
349 case GDK_BUTTON_RELEASE:
350 if (event->button.button == 3) {
351 return button_release_handler (item, event, FadeInItem);
360 /* proxy for the regionview */
362 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
366 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
370 if (!rv->sensitive()) {
374 switch (event->type) {
375 case GDK_BUTTON_PRESS:
376 case GDK_2BUTTON_PRESS:
377 case GDK_3BUTTON_PRESS:
378 clicked_regionview = rv;
379 clicked_control_point = 0;
380 clicked_trackview = &rv->get_time_axis_view();
381 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
382 ret = button_press_handler (item, event, FadeInHandleItem);
385 case GDK_BUTTON_RELEASE:
386 ret = button_release_handler (item, event, FadeInHandleItem);
389 case GDK_MOTION_NOTIFY:
390 ret = motion_handler (item, event, FadeInHandleItem);
393 case GDK_ENTER_NOTIFY:
394 ret = enter_handler (item, event, FadeInHandleItem);
397 case GDK_LEAVE_NOTIFY:
398 ret = leave_handler (item, event, FadeInHandleItem);
409 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
411 /* we handle only button 3 press/release events */
413 if (!rv->sensitive()) {
417 switch (event->type) {
418 case GDK_BUTTON_PRESS:
419 clicked_regionview = rv;
420 clicked_control_point = 0;
421 clicked_trackview = &rv->get_time_axis_view();
422 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
423 if (event->button.button == 3) {
424 return button_press_handler (item, event, FadeOutItem);
428 case GDK_BUTTON_RELEASE:
429 if (event->button.button == 3) {
430 return button_release_handler (item, event, FadeOutItem);
439 /* proxy for the regionview */
441 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
445 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
449 if (!rv->sensitive()) {
453 switch (event->type) {
454 case GDK_BUTTON_PRESS:
455 case GDK_2BUTTON_PRESS:
456 case GDK_3BUTTON_PRESS:
457 clicked_regionview = rv;
458 clicked_control_point = 0;
459 clicked_trackview = &rv->get_time_axis_view();
460 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
461 ret = button_press_handler (item, event, FadeOutHandleItem);
464 case GDK_BUTTON_RELEASE:
465 ret = button_release_handler (item, event, FadeOutHandleItem);
468 case GDK_MOTION_NOTIFY:
469 ret = motion_handler (item, event, FadeOutHandleItem);
472 case GDK_ENTER_NOTIFY:
473 ret = enter_handler (item, event, FadeOutHandleItem);
476 case GDK_LEAVE_NOTIFY:
477 ret = leave_handler (item, event, FadeOutHandleItem);
487 struct DescendingRegionLayerSorter {
488 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
489 return a->layer() > b->layer();
494 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
496 /* we handle only button 3 press/release events */
498 switch (event->type) {
499 case GDK_BUTTON_PRESS:
500 clicked_crossfadeview = xfv;
501 clicked_trackview = &clicked_crossfadeview->get_time_axis_view();
502 if (event->button.button == 3) {
503 return button_press_handler (item, event, CrossfadeViewItem);
507 case GDK_BUTTON_RELEASE:
508 if (event->button.button == 3) {
509 bool ret = button_release_handler (item, event, CrossfadeViewItem);
519 /* XXX do not forward double clicks */
521 if (event->type == GDK_2BUTTON_PRESS) {
525 /* proxy for the upper most regionview */
527 /* XXX really need to check if we are in the name highlight,
528 and proxy to that when required.
531 TimeAxisView& tv (xfv->get_time_axis_view());
532 AudioTimeAxisView* atv;
534 if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
536 if (atv->is_audio_track()) {
538 boost::shared_ptr<AudioPlaylist> pl;
539 if ((pl = boost::dynamic_pointer_cast<AudioPlaylist> (atv->get_diskstream()->playlist())) != 0) {
541 Playlist::RegionList* rl = pl->regions_at (event_frame (event));
544 DescendingRegionLayerSorter cmp;
547 RegionView* rv = atv->view()->find_view (rl->front());
553 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
563 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
567 switch (event->type) {
568 case GDK_BUTTON_PRESS:
569 case GDK_2BUTTON_PRESS:
570 case GDK_3BUTTON_PRESS:
571 clicked_control_point = cp;
572 clicked_trackview = &cp->line.trackview;
573 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
574 clicked_regionview = 0;
580 case GDK_SCROLL_DOWN:
587 if (dynamic_cast<AudioRegionGainLine*> (&cp->line) != 0) {
588 type = GainControlPointItem;
589 } else if (dynamic_cast<AutomationGainLine*> (&cp->line) != 0) {
590 type = GainAutomationControlPointItem;
591 } else if (dynamic_cast<AutomationPanLine*> (&cp->line) != 0) {
592 type = PanAutomationControlPointItem;
593 } else if (dynamic_cast<RedirectAutomationLine*> (&cp->line) != 0) {
594 type = RedirectAutomationControlPointItem;
599 return typed_event (item, event, type);
603 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
607 if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
609 } else if (dynamic_cast<AutomationGainLine*> (al) != 0) {
610 type = GainAutomationLineItem;
611 } else if (dynamic_cast<AutomationPanLine*> (al) != 0) {
612 type = PanAutomationLineItem;
613 } else if (dynamic_cast<RedirectAutomationLine*> (al) != 0) {
614 type = RedirectAutomationLineItem;
619 return typed_event (item, event, type);
623 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
627 switch (event->type) {
628 case GDK_BUTTON_PRESS:
629 case GDK_2BUTTON_PRESS:
630 case GDK_3BUTTON_PRESS:
631 clicked_selection = rect->id;
632 ret = button_press_handler (item, event, SelectionItem);
634 case GDK_BUTTON_RELEASE:
635 ret = button_release_handler (item, event, SelectionItem);
637 case GDK_MOTION_NOTIFY:
638 ret = motion_handler (item, event, SelectionItem);
640 /* Don't need these at the moment. */
641 case GDK_ENTER_NOTIFY:
642 ret = enter_handler (item, event, SelectionItem);
645 case GDK_LEAVE_NOTIFY:
646 ret = leave_handler (item, event, SelectionItem);
657 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
661 switch (event->type) {
662 case GDK_BUTTON_PRESS:
663 case GDK_2BUTTON_PRESS:
664 case GDK_3BUTTON_PRESS:
665 clicked_selection = rect->id;
666 ret = button_press_handler (item, event, StartSelectionTrimItem);
668 case GDK_BUTTON_RELEASE:
669 ret = button_release_handler (item, event, StartSelectionTrimItem);
671 case GDK_MOTION_NOTIFY:
672 ret = motion_handler (item, event, StartSelectionTrimItem);
674 case GDK_ENTER_NOTIFY:
675 ret = enter_handler (item, event, StartSelectionTrimItem);
678 case GDK_LEAVE_NOTIFY:
679 ret = leave_handler (item, event, StartSelectionTrimItem);
690 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
694 switch (event->type) {
695 case GDK_BUTTON_PRESS:
696 case GDK_2BUTTON_PRESS:
697 case GDK_3BUTTON_PRESS:
698 clicked_selection = rect->id;
699 ret = button_press_handler (item, event, EndSelectionTrimItem);
701 case GDK_BUTTON_RELEASE:
702 ret = button_release_handler (item, event, EndSelectionTrimItem);
704 case GDK_MOTION_NOTIFY:
705 ret = motion_handler (item, event, EndSelectionTrimItem);
707 case GDK_ENTER_NOTIFY:
708 ret = enter_handler (item, event, EndSelectionTrimItem);
711 case GDK_LEAVE_NOTIFY:
712 ret = leave_handler (item, event, EndSelectionTrimItem);
724 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
728 if (!rv->sensitive()) {
732 switch (event->type) {
733 case GDK_BUTTON_PRESS:
734 case GDK_2BUTTON_PRESS:
735 case GDK_3BUTTON_PRESS:
736 clicked_regionview = rv;
737 clicked_control_point = 0;
738 clicked_trackview = &clicked_regionview->get_time_axis_view();
739 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
740 ret = button_press_handler (item, event, RegionViewNameHighlight);
742 case GDK_BUTTON_RELEASE:
743 ret = button_release_handler (item, event, RegionViewNameHighlight);
745 case GDK_MOTION_NOTIFY:
746 ret = motion_handler (item, event, RegionViewNameHighlight);
748 case GDK_ENTER_NOTIFY:
749 ret = enter_handler (item, event, RegionViewNameHighlight);
752 case GDK_LEAVE_NOTIFY:
753 ret = leave_handler (item, event, RegionViewNameHighlight);
764 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
768 if (!rv->sensitive()) {
772 switch (event->type) {
773 case GDK_BUTTON_PRESS:
774 case GDK_2BUTTON_PRESS:
775 case GDK_3BUTTON_PRESS:
776 clicked_regionview = rv;
777 clicked_control_point = 0;
778 clicked_trackview = &clicked_regionview->get_time_axis_view();
779 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
780 ret = button_press_handler (item, event, RegionViewName);
782 case GDK_BUTTON_RELEASE:
783 ret = button_release_handler (item, event, RegionViewName);
785 case GDK_MOTION_NOTIFY:
786 ret = motion_handler (item, event, RegionViewName);
788 case GDK_ENTER_NOTIFY:
789 ret = enter_handler (item, event, RegionViewName);
792 case GDK_LEAVE_NOTIFY:
793 ret = leave_handler (item, event, RegionViewName);
804 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* marker)
806 return typed_event (item, event, MarkerItem);
810 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
812 return typed_event (item, event, MarkerBarItem);
816 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
818 return typed_event (item, event, RangeMarkerBarItem);
822 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
824 return typed_event (item, event, TransportMarkerBarItem);
828 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
830 return typed_event (item, event, TempoMarkerItem);
834 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* marker)
836 return typed_event (item, event, MeterMarkerItem);
840 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
842 return typed_event (item, event, TempoBarItem);
846 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
848 return typed_event (item, event, MeterBarItem);
852 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
854 return typed_event (item, event, PlayheadCursorItem);
858 Editor::canvas_edit_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
860 return typed_event (item, event, EditCursorItem);
864 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
866 return typed_event (item, event, NoItem);