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 <ardour/audio_diskstream.h>
24 #include <ardour/audioplaylist.h>
28 #include "public_editor.h"
29 #include "audio_region_view.h"
30 #include "audio_streamview.h"
31 #include "crossfade_view.h"
32 #include "audio_time_axis.h"
33 #include "region_gain_line.h"
34 #include "automation_gain_line.h"
35 #include "automation_pan_line.h"
36 #include "automation_time_axis.h"
37 #include "redirect_automation_line.h"
38 #include "canvas_impl.h"
39 #include "simplerect.h"
44 using namespace ARDOUR;
49 Editor::track_canvas_scroll (GdkEventScroll* ev)
54 switch (ev->direction) {
56 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
57 //if (ev->state == GDK_CONTROL_MASK) {
59 the ev->x will be out of step with the canvas
60 if we're in mid zoom, so we have to get the damn mouse
63 track_canvas.get_pointer (x, y);
64 track_canvas.window_to_world (x, y, wx, wy);
65 wx += horizontal_adjustment.get_value();
66 wy += vertical_adjustment.get_value();
69 event.type = GDK_BUTTON_RELEASE;
73 nframes_t where = event_frame (&event, 0, 0);
74 temporal_zoom_to_frame (false, where);
76 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
77 if (!current_stepping_trackview) {
78 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
79 if (!(current_stepping_trackview = trackview_by_y_position (ev->y))) {
83 gettimeofday (&last_track_height_step_timestamp, 0);
84 current_stepping_trackview->step_height (true);
87 scroll_tracks_up_line ();
92 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
93 //if (ev->state == GDK_CONTROL_MASK) {
94 track_canvas.get_pointer (x, y);
95 track_canvas.window_to_world (x, y, wx, wy);
96 wx += horizontal_adjustment.get_value();
97 wy += vertical_adjustment.get_value();
100 event.type = GDK_BUTTON_RELEASE;
104 nframes_t where = event_frame (&event, 0, 0);
105 temporal_zoom_to_frame (true, where);
107 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
108 if (!current_stepping_trackview) {
109 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
110 if (!(current_stepping_trackview = trackview_by_y_position (ev->y))) {
114 gettimeofday (&last_track_height_step_timestamp, 0);
115 current_stepping_trackview->step_height (false);
118 scroll_tracks_down_line ();
124 /* no left/right handling yet */
132 Editor::track_canvas_event (GdkEvent *event, ArdourCanvas::Item* item)
136 /* this is the handler for events that are not handled by
140 switch (event->type) {
141 case GDK_MOTION_NOTIFY:
142 /* keep those motion events coming */
143 track_canvas.get_pointer (x, y);
144 return track_canvas_motion (event);
146 case GDK_BUTTON_PRESS:
147 track_canvas.grab_focus();
150 case GDK_BUTTON_RELEASE:
151 switch (event->button.button) {
154 button_release_handler (item, event, NoItem);
160 track_canvas.grab_focus();
161 track_canvas_scroll (&event->scroll);
172 Editor::track_canvas_motion (GdkEvent *ev)
174 if (verbose_cursor_visible) {
175 verbose_canvas_cursor->property_x() = ev->motion.x + 20;
176 verbose_canvas_cursor->property_y() = ev->motion.y + 20;
182 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
186 switch (event->type) {
187 case GDK_BUTTON_PRESS:
188 case GDK_2BUTTON_PRESS:
189 case GDK_3BUTTON_PRESS:
190 ret = button_press_handler (item, event, type);
192 case GDK_BUTTON_RELEASE:
193 ret = button_release_handler (item, event, type);
195 case GDK_MOTION_NOTIFY:
196 ret = motion_handler (item, event, type);
199 case GDK_ENTER_NOTIFY:
200 ret = enter_handler (item, event, type);
203 case GDK_LEAVE_NOTIFY:
204 ret = leave_handler (item, event, type);
215 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
219 if (!rv->sensitive ()) {
223 switch (event->type) {
224 case GDK_BUTTON_PRESS:
225 case GDK_2BUTTON_PRESS:
226 case GDK_3BUTTON_PRESS:
227 clicked_regionview = rv;
228 clicked_control_point = 0;
229 clicked_trackview = &rv->get_time_axis_view();
230 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
231 ret = button_press_handler (item, event, RegionItem);
234 case GDK_BUTTON_RELEASE:
235 ret = button_release_handler (item, event, RegionItem);
238 case GDK_MOTION_NOTIFY:
239 ret = motion_handler (item, event, RegionItem);
242 case GDK_ENTER_NOTIFY:
243 set_entered_regionview (rv);
246 case GDK_LEAVE_NOTIFY:
247 set_entered_regionview (0);
258 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
262 switch (event->type) {
263 case GDK_BUTTON_PRESS:
264 case GDK_2BUTTON_PRESS:
265 case GDK_3BUTTON_PRESS:
266 clicked_regionview = 0;
267 clicked_control_point = 0;
268 clicked_trackview = tv;
269 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(tv);
270 ret = button_press_handler (item, event, StreamItem);
273 case GDK_BUTTON_RELEASE:
274 ret = button_release_handler (item, event, StreamItem);
277 case GDK_MOTION_NOTIFY:
278 ret = motion_handler (item, event, StreamItem);
281 case GDK_ENTER_NOTIFY:
294 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
298 switch (event->type) {
299 case GDK_BUTTON_PRESS:
300 case GDK_2BUTTON_PRESS:
301 case GDK_3BUTTON_PRESS:
302 clicked_regionview = 0;
303 clicked_control_point = 0;
304 clicked_trackview = atv;
305 clicked_audio_trackview = 0;
306 ret = button_press_handler (item, event, AutomationTrackItem);
309 case GDK_BUTTON_RELEASE:
310 ret = button_release_handler (item, event, AutomationTrackItem);
313 case GDK_MOTION_NOTIFY:
314 ret = motion_handler (item, event, AutomationTrackItem);
317 case GDK_ENTER_NOTIFY:
318 ret = enter_handler (item, event, AutomationTrackItem);
321 case GDK_LEAVE_NOTIFY:
322 ret = leave_handler (item, event, AutomationTrackItem);
333 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
335 /* we handle only button 3 press/release events */
337 if (!rv->sensitive()) {
341 switch (event->type) {
342 case GDK_BUTTON_PRESS:
343 clicked_regionview = rv;
344 clicked_control_point = 0;
345 clicked_trackview = &rv->get_time_axis_view();
346 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
347 if (event->button.button == 3) {
348 return button_press_handler (item, event, FadeInItem);
352 case GDK_BUTTON_RELEASE:
353 if (event->button.button == 3) {
354 return button_release_handler (item, event, FadeInItem);
363 /* proxy for the regionview */
365 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
369 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
373 if (!rv->sensitive()) {
377 switch (event->type) {
378 case GDK_BUTTON_PRESS:
379 case GDK_2BUTTON_PRESS:
380 case GDK_3BUTTON_PRESS:
381 clicked_regionview = rv;
382 clicked_control_point = 0;
383 clicked_trackview = &rv->get_time_axis_view();
384 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
385 ret = button_press_handler (item, event, FadeInHandleItem);
388 case GDK_BUTTON_RELEASE:
389 ret = button_release_handler (item, event, FadeInHandleItem);
392 case GDK_MOTION_NOTIFY:
393 ret = motion_handler (item, event, FadeInHandleItem);
396 case GDK_ENTER_NOTIFY:
397 ret = enter_handler (item, event, FadeInHandleItem);
400 case GDK_LEAVE_NOTIFY:
401 ret = leave_handler (item, event, FadeInHandleItem);
412 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
414 /* we handle only button 3 press/release events */
416 if (!rv->sensitive()) {
420 switch (event->type) {
421 case GDK_BUTTON_PRESS:
422 clicked_regionview = rv;
423 clicked_control_point = 0;
424 clicked_trackview = &rv->get_time_axis_view();
425 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
426 if (event->button.button == 3) {
427 return button_press_handler (item, event, FadeOutItem);
431 case GDK_BUTTON_RELEASE:
432 if (event->button.button == 3) {
433 return button_release_handler (item, event, FadeOutItem);
442 /* proxy for the regionview */
444 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
448 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
452 if (!rv->sensitive()) {
456 switch (event->type) {
457 case GDK_BUTTON_PRESS:
458 case GDK_2BUTTON_PRESS:
459 case GDK_3BUTTON_PRESS:
460 clicked_regionview = rv;
461 clicked_control_point = 0;
462 clicked_trackview = &rv->get_time_axis_view();
463 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
464 ret = button_press_handler (item, event, FadeOutHandleItem);
467 case GDK_BUTTON_RELEASE:
468 ret = button_release_handler (item, event, FadeOutHandleItem);
471 case GDK_MOTION_NOTIFY:
472 ret = motion_handler (item, event, FadeOutHandleItem);
475 case GDK_ENTER_NOTIFY:
476 ret = enter_handler (item, event, FadeOutHandleItem);
479 case GDK_LEAVE_NOTIFY:
480 ret = leave_handler (item, event, FadeOutHandleItem);
490 struct DescendingRegionLayerSorter {
491 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
492 return a->layer() > b->layer();
497 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
499 /* we handle only button 3 press/release events */
501 switch (event->type) {
502 case GDK_BUTTON_PRESS:
503 clicked_crossfadeview = xfv;
504 clicked_trackview = &clicked_crossfadeview->get_time_axis_view();
505 if (event->button.button == 3) {
506 return button_press_handler (item, event, CrossfadeViewItem);
510 case GDK_BUTTON_RELEASE:
511 if (event->button.button == 3) {
512 bool ret = button_release_handler (item, event, CrossfadeViewItem);
523 /* proxy for the upper most regionview */
525 /* XXX really need to check if we are in the name highlight,
526 and proxy to that when required.
529 TimeAxisView& tv (xfv->get_time_axis_view());
530 AudioTimeAxisView* atv;
532 if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
534 if (atv->is_audio_track()) {
536 boost::shared_ptr<AudioPlaylist> pl;
537 if ((pl = boost::dynamic_pointer_cast<AudioPlaylist> (atv->get_diskstream()->playlist())) != 0) {
539 Playlist::RegionList* rl = pl->regions_at (event_frame (event));
542 DescendingRegionLayerSorter cmp;
545 RegionView* rv = atv->view()->find_view (rl->front());
551 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
561 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
565 switch (event->type) {
566 case GDK_BUTTON_PRESS:
567 case GDK_2BUTTON_PRESS:
568 case GDK_3BUTTON_PRESS:
569 clicked_control_point = cp;
570 clicked_trackview = &cp->line.trackview;
571 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
572 clicked_regionview = 0;
578 case GDK_SCROLL_DOWN:
585 if (dynamic_cast<AudioRegionGainLine*> (&cp->line) != 0) {
586 type = GainControlPointItem;
587 } else if (dynamic_cast<AutomationGainLine*> (&cp->line) != 0) {
588 type = GainAutomationControlPointItem;
589 } else if (dynamic_cast<AutomationPanLine*> (&cp->line) != 0) {
590 type = PanAutomationControlPointItem;
591 } else if (dynamic_cast<RedirectAutomationLine*> (&cp->line) != 0) {
592 type = RedirectAutomationControlPointItem;
597 return typed_event (item, event, type);
601 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
605 if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
607 } else if (dynamic_cast<AutomationGainLine*> (al) != 0) {
608 type = GainAutomationLineItem;
609 } else if (dynamic_cast<AutomationPanLine*> (al) != 0) {
610 type = PanAutomationLineItem;
611 } else if (dynamic_cast<RedirectAutomationLine*> (al) != 0) {
612 type = RedirectAutomationLineItem;
617 return typed_event (item, event, type);
621 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
625 switch (event->type) {
626 case GDK_BUTTON_PRESS:
627 case GDK_2BUTTON_PRESS:
628 case GDK_3BUTTON_PRESS:
629 clicked_selection = rect->id;
630 ret = button_press_handler (item, event, SelectionItem);
632 case GDK_BUTTON_RELEASE:
633 ret = button_release_handler (item, event, SelectionItem);
635 case GDK_MOTION_NOTIFY:
636 ret = motion_handler (item, event, SelectionItem);
638 /* Don't need these at the moment. */
639 case GDK_ENTER_NOTIFY:
640 ret = enter_handler (item, event, SelectionItem);
643 case GDK_LEAVE_NOTIFY:
644 ret = leave_handler (item, event, SelectionItem);
655 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
659 switch (event->type) {
660 case GDK_BUTTON_PRESS:
661 case GDK_2BUTTON_PRESS:
662 case GDK_3BUTTON_PRESS:
663 clicked_selection = rect->id;
664 ret = button_press_handler (item, event, StartSelectionTrimItem);
666 case GDK_BUTTON_RELEASE:
667 ret = button_release_handler (item, event, StartSelectionTrimItem);
669 case GDK_MOTION_NOTIFY:
670 ret = motion_handler (item, event, StartSelectionTrimItem);
672 case GDK_ENTER_NOTIFY:
673 ret = enter_handler (item, event, StartSelectionTrimItem);
676 case GDK_LEAVE_NOTIFY:
677 ret = leave_handler (item, event, StartSelectionTrimItem);
688 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
692 switch (event->type) {
693 case GDK_BUTTON_PRESS:
694 case GDK_2BUTTON_PRESS:
695 case GDK_3BUTTON_PRESS:
696 clicked_selection = rect->id;
697 ret = button_press_handler (item, event, EndSelectionTrimItem);
699 case GDK_BUTTON_RELEASE:
700 ret = button_release_handler (item, event, EndSelectionTrimItem);
702 case GDK_MOTION_NOTIFY:
703 ret = motion_handler (item, event, EndSelectionTrimItem);
705 case GDK_ENTER_NOTIFY:
706 ret = enter_handler (item, event, EndSelectionTrimItem);
709 case GDK_LEAVE_NOTIFY:
710 ret = leave_handler (item, event, EndSelectionTrimItem);
722 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
726 if (!rv->sensitive()) {
730 switch (event->type) {
731 case GDK_BUTTON_PRESS:
732 case GDK_2BUTTON_PRESS:
733 case GDK_3BUTTON_PRESS:
734 clicked_regionview = rv;
735 clicked_control_point = 0;
736 clicked_trackview = &clicked_regionview->get_time_axis_view();
737 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
738 ret = button_press_handler (item, event, RegionViewNameHighlight);
740 case GDK_BUTTON_RELEASE:
741 ret = button_release_handler (item, event, RegionViewNameHighlight);
743 case GDK_MOTION_NOTIFY:
744 ret = motion_handler (item, event, RegionViewNameHighlight);
746 case GDK_ENTER_NOTIFY:
747 ret = enter_handler (item, event, RegionViewNameHighlight);
750 case GDK_LEAVE_NOTIFY:
751 ret = leave_handler (item, event, RegionViewNameHighlight);
762 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
766 if (!rv->sensitive()) {
770 switch (event->type) {
771 case GDK_BUTTON_PRESS:
772 case GDK_2BUTTON_PRESS:
773 case GDK_3BUTTON_PRESS:
774 clicked_regionview = rv;
775 clicked_control_point = 0;
776 clicked_trackview = &clicked_regionview->get_time_axis_view();
777 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
778 ret = button_press_handler (item, event, RegionViewName);
780 case GDK_BUTTON_RELEASE:
781 ret = button_release_handler (item, event, RegionViewName);
783 case GDK_MOTION_NOTIFY:
784 ret = motion_handler (item, event, RegionViewName);
786 case GDK_ENTER_NOTIFY:
787 ret = enter_handler (item, event, RegionViewName);
790 case GDK_LEAVE_NOTIFY:
791 ret = leave_handler (item, event, RegionViewName);
802 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* marker)
804 return typed_event (item, event, MarkerItem);
808 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
810 return typed_event (item, event, MarkerBarItem);
814 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
816 return typed_event (item, event, RangeMarkerBarItem);
820 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
822 return typed_event (item, event, TransportMarkerBarItem);
826 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
828 return typed_event (item, event, TempoMarkerItem);
832 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* marker)
834 return typed_event (item, event, MeterMarkerItem);
838 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
840 return typed_event (item, event, TempoBarItem);
844 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
846 return typed_event (item, event, MeterBarItem);
850 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
852 return typed_event (item, event, PlayheadCursorItem);
856 Editor::canvas_edit_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
858 return typed_event (item, event, EditCursorItem);
862 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
864 return typed_event (item, event, NoItem);