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_midi_cc_line.h"
39 #include "automation_time_axis.h"
40 #include "plugin_automation_line.h"
41 #include "canvas_impl.h"
42 #include "simplerect.h"
47 using namespace ARDOUR;
52 Editor::track_canvas_scroll (GdkEventScroll* ev)
57 switch (ev->direction) {
59 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
60 //if (ev->state == GDK_CONTROL_MASK) {
62 the ev->x will be out of step with the canvas
63 if we're in mid zoom, so we have to get the damn mouse
66 track_canvas.get_pointer (x, y);
67 track_canvas.window_to_world (x, y, wx, wy);
68 wx += horizontal_adjustment.get_value();
69 wy += vertical_adjustment.get_value();
72 event.type = GDK_BUTTON_RELEASE;
76 nframes_t where = event_frame (&event, 0, 0);
77 temporal_zoom_to_frame (false, where);
79 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
80 if (!current_stepping_trackview) {
81 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
82 if (!(current_stepping_trackview = trackview_by_y_position (ev->y))) {
86 gettimeofday (&last_track_height_step_timestamp, 0);
87 current_stepping_trackview->step_height (true);
90 scroll_tracks_up_line ();
95 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
96 //if (ev->state == GDK_CONTROL_MASK) {
97 track_canvas.get_pointer (x, y);
98 track_canvas.window_to_world (x, y, wx, wy);
99 wx += horizontal_adjustment.get_value();
100 wy += vertical_adjustment.get_value();
103 event.type = GDK_BUTTON_RELEASE;
107 nframes_t where = event_frame (&event, 0, 0);
108 temporal_zoom_to_frame (true, where);
110 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
111 if (!current_stepping_trackview) {
112 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
113 if (!(current_stepping_trackview = trackview_by_y_position (ev->y))) {
117 gettimeofday (&last_track_height_step_timestamp, 0);
118 current_stepping_trackview->step_height (false);
121 scroll_tracks_down_line ();
127 /* no left/right handling yet */
135 Editor::track_canvas_scroll_event (GdkEventScroll *event)
137 track_canvas.grab_focus();
138 track_canvas_scroll (event);
143 Editor::track_canvas_button_press_event (GdkEventButton *event)
145 track_canvas.grab_focus();
150 Editor::track_canvas_button_release_event (GdkEventButton *event)
152 if (drag_info.item) {
153 end_grab (drag_info.item, (GdkEvent*) event);
159 Editor::track_canvas_motion_notify_event (GdkEventMotion *event)
162 /* keep those motion events coming */
163 track_canvas.get_pointer (x, y);
168 Editor::track_canvas_motion (GdkEvent *ev)
170 if (verbose_cursor_visible) {
171 verbose_canvas_cursor->property_x() = ev->motion.x + 20;
172 verbose_canvas_cursor->property_y() = ev->motion.y + 20;
178 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
182 switch (event->type) {
183 case GDK_BUTTON_PRESS:
184 case GDK_2BUTTON_PRESS:
185 case GDK_3BUTTON_PRESS:
186 ret = button_press_handler (item, event, type);
188 case GDK_BUTTON_RELEASE:
189 ret = button_release_handler (item, event, type);
191 case GDK_MOTION_NOTIFY:
192 ret = motion_handler (item, event, type);
195 case GDK_ENTER_NOTIFY:
196 ret = enter_handler (item, event, type);
199 case GDK_LEAVE_NOTIFY:
200 ret = leave_handler (item, event, type);
211 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
215 if (!rv->sensitive ()) {
220 switch (event->type) {
221 case GDK_BUTTON_PRESS:
222 case GDK_2BUTTON_PRESS:
223 case GDK_3BUTTON_PRESS:
224 clicked_regionview = rv;
225 clicked_control_point = 0;
226 clicked_axisview = &rv->get_time_axis_view();
227 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
228 ret = button_press_handler (item, event, RegionItem);
231 case GDK_BUTTON_RELEASE:
232 ret = button_release_handler (item, event, RegionItem);
235 case GDK_MOTION_NOTIFY:
236 ret = motion_handler (item, event, RegionItem);
239 case GDK_ENTER_NOTIFY:
240 set_entered_regionview (rv);
243 case GDK_LEAVE_NOTIFY:
244 set_entered_regionview (0);
255 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
259 switch (event->type) {
260 case GDK_BUTTON_PRESS:
261 case GDK_2BUTTON_PRESS:
262 case GDK_3BUTTON_PRESS:
263 clicked_regionview = 0;
264 clicked_control_point = 0;
265 clicked_axisview = tv;
266 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(tv);
267 ret = button_press_handler (item, event, StreamItem);
270 case GDK_BUTTON_RELEASE:
271 ret = button_release_handler (item, event, StreamItem);
274 case GDK_MOTION_NOTIFY:
275 ret = motion_handler (item, event, StreamItem);
278 case GDK_ENTER_NOTIFY:
291 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
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 = atv;
303 clicked_routeview = 0;
304 ret = button_press_handler (item, event, AutomationTrackItem);
307 case GDK_BUTTON_RELEASE:
308 ret = button_release_handler (item, event, AutomationTrackItem);
311 case GDK_MOTION_NOTIFY:
312 ret = motion_handler (item, event, AutomationTrackItem);
315 case GDK_ENTER_NOTIFY:
316 ret = enter_handler (item, event, AutomationTrackItem);
319 case GDK_LEAVE_NOTIFY:
320 ret = leave_handler (item, event, AutomationTrackItem);
331 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
333 /* we handle only button 3 press/release events */
335 if (!rv->sensitive()) {
339 switch (event->type) {
340 case GDK_BUTTON_PRESS:
341 clicked_regionview = rv;
342 clicked_control_point = 0;
343 clicked_axisview = &rv->get_time_axis_view();
344 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
345 if (event->button.button == 3) {
346 return button_press_handler (item, event, FadeInItem);
350 case GDK_BUTTON_RELEASE:
351 if (event->button.button == 3) {
352 return button_release_handler (item, event, FadeInItem);
361 /* proxy for the regionview */
363 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
367 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
371 if (!rv->sensitive()) {
375 switch (event->type) {
376 case GDK_BUTTON_PRESS:
377 case GDK_2BUTTON_PRESS:
378 case GDK_3BUTTON_PRESS:
379 clicked_regionview = rv;
380 clicked_control_point = 0;
381 clicked_axisview = &rv->get_time_axis_view();
382 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
383 ret = button_press_handler (item, event, FadeInHandleItem);
386 case GDK_BUTTON_RELEASE:
387 ret = button_release_handler (item, event, FadeInHandleItem);
390 case GDK_MOTION_NOTIFY:
391 ret = motion_handler (item, event, FadeInHandleItem);
394 case GDK_ENTER_NOTIFY:
395 ret = enter_handler (item, event, FadeInHandleItem);
398 case GDK_LEAVE_NOTIFY:
399 ret = leave_handler (item, event, FadeInHandleItem);
410 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
412 /* we handle only button 3 press/release events */
414 if (!rv->sensitive()) {
418 switch (event->type) {
419 case GDK_BUTTON_PRESS:
420 clicked_regionview = rv;
421 clicked_control_point = 0;
422 clicked_axisview = &rv->get_time_axis_view();
423 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
424 if (event->button.button == 3) {
425 return button_press_handler (item, event, FadeOutItem);
429 case GDK_BUTTON_RELEASE:
430 if (event->button.button == 3) {
431 return button_release_handler (item, event, FadeOutItem);
440 /* proxy for the regionview */
442 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
446 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
450 if (!rv->sensitive()) {
454 switch (event->type) {
455 case GDK_BUTTON_PRESS:
456 case GDK_2BUTTON_PRESS:
457 case GDK_3BUTTON_PRESS:
458 clicked_regionview = rv;
459 clicked_control_point = 0;
460 clicked_axisview = &rv->get_time_axis_view();
461 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
462 ret = button_press_handler (item, event, FadeOutHandleItem);
465 case GDK_BUTTON_RELEASE:
466 ret = button_release_handler (item, event, FadeOutHandleItem);
469 case GDK_MOTION_NOTIFY:
470 ret = motion_handler (item, event, FadeOutHandleItem);
473 case GDK_ENTER_NOTIFY:
474 ret = enter_handler (item, event, FadeOutHandleItem);
477 case GDK_LEAVE_NOTIFY:
478 ret = leave_handler (item, event, FadeOutHandleItem);
488 struct DescendingRegionLayerSorter {
489 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
490 return a->layer() > b->layer();
495 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
497 /* we handle only button 3 press/release events */
499 switch (event->type) {
500 case GDK_BUTTON_PRESS:
501 clicked_crossfadeview = xfv;
502 clicked_axisview = &clicked_crossfadeview->get_time_axis_view();
503 if (event->button.button == 3) {
504 return button_press_handler (item, event, CrossfadeViewItem);
508 case GDK_BUTTON_RELEASE:
509 if (event->button.button == 3) {
510 bool ret = button_release_handler (item, event, CrossfadeViewItem);
520 /* XXX do not forward double clicks */
522 if (event->type == GDK_2BUTTON_PRESS) {
526 /* proxy for the upper most regionview */
528 /* XXX really need to check if we are in the name highlight,
529 and proxy to that when required.
532 TimeAxisView& tv (xfv->get_time_axis_view());
533 AudioTimeAxisView* atv;
535 if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
537 if (atv->is_audio_track()) {
539 boost::shared_ptr<AudioPlaylist> pl;
540 if ((pl = boost::dynamic_pointer_cast<AudioPlaylist> (atv->get_diskstream()->playlist())) != 0) {
542 Playlist::RegionList* rl = pl->regions_at (event_frame (event));
545 DescendingRegionLayerSorter cmp;
548 RegionView* rv = atv->view()->find_view (rl->front());
554 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
564 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
568 switch (event->type) {
569 case GDK_BUTTON_PRESS:
570 case GDK_2BUTTON_PRESS:
571 case GDK_3BUTTON_PRESS:
572 clicked_control_point = cp;
573 clicked_axisview = &cp->line.trackview;
574 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
575 clicked_regionview = 0;
581 case GDK_SCROLL_DOWN:
588 if (dynamic_cast<AudioRegionGainLine*> (&cp->line) != 0) {
589 type = GainControlPointItem;
590 } else if (dynamic_cast<AutomationGainLine*> (&cp->line) != 0) {
591 type = GainAutomationControlPointItem;
592 } else if (dynamic_cast<AutomationPanLine*> (&cp->line) != 0) {
593 type = PanAutomationControlPointItem;
594 } else if (dynamic_cast<ProcessorAutomationLine*> (&cp->line) != 0) {
595 type = RedirectAutomationControlPointItem;
596 } else if (dynamic_cast<AutomationMidiCCLine*> (&cp->line) != 0) {
597 type = MidiCCAutomationControlPointItem;
602 return typed_event (item, event, type);
606 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
610 if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
612 } else if (dynamic_cast<AutomationGainLine*> (al) != 0) {
613 type = GainAutomationLineItem;
614 } else if (dynamic_cast<AutomationPanLine*> (al) != 0) {
615 type = PanAutomationLineItem;
616 } else if (dynamic_cast<ProcessorAutomationLine*> (al) != 0) {
617 type = ProcessorAutomationLineItem;
618 } else if (dynamic_cast<AutomationMidiCCLine*> (al) != 0) {
619 type = MidiCCAutomationLineItem;
624 return typed_event (item, event, type);
628 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
632 switch (event->type) {
633 case GDK_BUTTON_PRESS:
634 case GDK_2BUTTON_PRESS:
635 case GDK_3BUTTON_PRESS:
636 clicked_selection = rect->id;
637 ret = button_press_handler (item, event, SelectionItem);
639 case GDK_BUTTON_RELEASE:
640 ret = button_release_handler (item, event, SelectionItem);
642 case GDK_MOTION_NOTIFY:
643 ret = motion_handler (item, event, SelectionItem);
645 /* Don't need these at the moment. */
646 case GDK_ENTER_NOTIFY:
647 ret = enter_handler (item, event, SelectionItem);
650 case GDK_LEAVE_NOTIFY:
651 ret = leave_handler (item, event, SelectionItem);
662 Editor::canvas_selection_start_trim_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, StartSelectionTrimItem);
673 case GDK_BUTTON_RELEASE:
674 ret = button_release_handler (item, event, StartSelectionTrimItem);
676 case GDK_MOTION_NOTIFY:
677 ret = motion_handler (item, event, StartSelectionTrimItem);
679 case GDK_ENTER_NOTIFY:
680 ret = enter_handler (item, event, StartSelectionTrimItem);
683 case GDK_LEAVE_NOTIFY:
684 ret = leave_handler (item, event, StartSelectionTrimItem);
695 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
699 switch (event->type) {
700 case GDK_BUTTON_PRESS:
701 case GDK_2BUTTON_PRESS:
702 case GDK_3BUTTON_PRESS:
703 clicked_selection = rect->id;
704 ret = button_press_handler (item, event, EndSelectionTrimItem);
706 case GDK_BUTTON_RELEASE:
707 ret = button_release_handler (item, event, EndSelectionTrimItem);
709 case GDK_MOTION_NOTIFY:
710 ret = motion_handler (item, event, EndSelectionTrimItem);
712 case GDK_ENTER_NOTIFY:
713 ret = enter_handler (item, event, EndSelectionTrimItem);
716 case GDK_LEAVE_NOTIFY:
717 ret = leave_handler (item, event, EndSelectionTrimItem);
729 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
733 if (!rv->sensitive()) {
737 switch (event->type) {
738 case GDK_BUTTON_PRESS:
739 case GDK_2BUTTON_PRESS:
740 case GDK_3BUTTON_PRESS:
741 clicked_regionview = rv;
742 clicked_control_point = 0;
743 clicked_axisview = &clicked_regionview->get_time_axis_view();
744 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
745 ret = button_press_handler (item, event, RegionViewNameHighlight);
747 case GDK_BUTTON_RELEASE:
748 ret = button_release_handler (item, event, RegionViewNameHighlight);
750 case GDK_MOTION_NOTIFY:
751 ret = motion_handler (item, event, RegionViewNameHighlight);
753 case GDK_ENTER_NOTIFY:
754 ret = enter_handler (item, event, RegionViewNameHighlight);
757 case GDK_LEAVE_NOTIFY:
758 ret = leave_handler (item, event, RegionViewNameHighlight);
769 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
773 if (!rv->sensitive()) {
777 switch (event->type) {
778 case GDK_BUTTON_PRESS:
779 case GDK_2BUTTON_PRESS:
780 case GDK_3BUTTON_PRESS:
781 clicked_regionview = rv;
782 clicked_control_point = 0;
783 clicked_axisview = &clicked_regionview->get_time_axis_view();
784 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
785 ret = button_press_handler (item, event, RegionViewName);
787 case GDK_BUTTON_RELEASE:
788 ret = button_release_handler (item, event, RegionViewName);
790 case GDK_MOTION_NOTIFY:
791 ret = motion_handler (item, event, RegionViewName);
793 case GDK_ENTER_NOTIFY:
794 ret = enter_handler (item, event, RegionViewName);
797 case GDK_LEAVE_NOTIFY:
798 ret = leave_handler (item, event, RegionViewName);
809 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* marker)
811 return typed_event (item, event, MarkerItem);
815 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
817 return typed_event (item, event, MarkerBarItem);
821 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
823 return typed_event (item, event, RangeMarkerBarItem);
827 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
829 return typed_event (item, event, TransportMarkerBarItem);
833 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
835 return typed_event (item, event, TempoMarkerItem);
839 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* marker)
841 return typed_event (item, event, MeterMarkerItem);
845 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
847 return typed_event (item, event, TempoBarItem);
851 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
853 return typed_event (item, event, MeterBarItem);
857 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
859 return typed_event (item, event, PlayheadCursorItem);
863 Editor::canvas_edit_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
865 return typed_event (item, event, EditCursorItem);
869 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
871 return typed_event (item, event, NoItem);