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.
24 #include <ardour/diskstream.h>
25 #include <ardour/audioplaylist.h>
28 #include "public_editor.h"
29 #include "regionview.h"
30 #include "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;
48 Editor::track_canvas_scroll (GdkEventScroll* ev)
53 switch (ev->direction) {
55 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
56 //if (ev->state == GDK_CONTROL_MASK) {
58 the ev->x will be out of step with the canvas
59 if we're in mid zoom, so we have to get the damn mouse
62 track_canvas.get_pointer (x, y);
63 track_canvas.window_to_world (x, y, wx, wy);
64 wx += horizontal_adjustment.get_value();
65 wy += vertical_adjustment.get_value();
68 event.type = GDK_BUTTON_RELEASE;
72 jack_nframes_t where = event_frame (&event, 0, 0);
73 temporal_zoom_to_frame (true, where);
75 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
76 if (!current_stepping_trackview) {
77 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
78 if (!(current_stepping_trackview = dynamic_cast<AudioTimeAxisView*> (trackview_by_y_position (ev->y)))) {
82 gettimeofday (&last_track_height_step_timestamp, 0);
83 current_stepping_trackview->step_height (true);
86 scroll_tracks_up_line ();
91 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
92 //if (ev->state == GDK_CONTROL_MASK) {
93 track_canvas.get_pointer (x, y);
94 track_canvas.window_to_world (x, y, wx, wy);
95 wx += horizontal_adjustment.get_value();
96 wy += vertical_adjustment.get_value();
99 event.type = GDK_BUTTON_RELEASE;
103 jack_nframes_t where = event_frame (&event, 0, 0);
104 temporal_zoom_to_frame (false, where);
106 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
107 if (!current_stepping_trackview) {
108 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
109 if (!(current_stepping_trackview = dynamic_cast<AudioTimeAxisView*> (trackview_by_y_position (ev->y)))) {
113 gettimeofday (&last_track_height_step_timestamp, 0);
114 current_stepping_trackview->step_height (false);
117 scroll_tracks_down_line ();
122 /* no left/right handling yet */
130 Editor::track_canvas_event (GdkEvent *event, ArdourCanvas::Item* item)
134 /* this is the handler for events that are not handled by
138 switch (event->type) {
139 case GDK_MOTION_NOTIFY:
140 /* keep those motion events coming */
141 track_canvas.get_pointer (x, y);
142 return track_canvas_motion (event);
144 case GDK_BUTTON_PRESS:
145 track_canvas.grab_focus();
148 case GDK_BUTTON_RELEASE:
149 switch (event->button.button) {
152 button_release_handler (item, event, NoItem);
158 track_canvas.grab_focus();
159 track_canvas_scroll (&event->scroll);
170 Editor::track_canvas_motion (GdkEvent *ev)
172 if (verbose_cursor_visible) {
173 verbose_canvas_cursor->property_x() = ev->motion.x + 20;
174 verbose_canvas_cursor->property_y() = ev->motion.y + 20;
180 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
184 switch (event->type) {
185 case GDK_BUTTON_PRESS:
186 case GDK_2BUTTON_PRESS:
187 case GDK_3BUTTON_PRESS:
188 ret = button_press_handler (item, event, type);
190 case GDK_BUTTON_RELEASE:
191 ret = button_release_handler (item, event, type);
193 case GDK_MOTION_NOTIFY:
194 ret = motion_handler (item, event, type);
197 case GDK_ENTER_NOTIFY:
198 ret = enter_handler (item, event, type);
201 case GDK_LEAVE_NOTIFY:
202 ret = leave_handler (item, event, type);
213 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
217 switch (event->type) {
218 case GDK_BUTTON_PRESS:
219 case GDK_2BUTTON_PRESS:
220 case GDK_3BUTTON_PRESS:
221 clicked_regionview = rv;
222 clicked_control_point = 0;
223 clicked_trackview = &rv->get_time_axis_view();
224 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
225 ret = button_press_handler (item, event, RegionItem);
228 case GDK_BUTTON_RELEASE:
229 ret = button_release_handler (item, event, RegionItem);
232 case GDK_MOTION_NOTIFY:
233 ret = motion_handler (item, event, RegionItem);
236 case GDK_ENTER_NOTIFY:
237 set_entered_regionview (rv);
240 case GDK_LEAVE_NOTIFY:
241 set_entered_regionview (0);
252 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, AudioTimeAxisView *tv)
256 switch (event->type) {
257 case GDK_BUTTON_PRESS:
258 case GDK_2BUTTON_PRESS:
259 case GDK_3BUTTON_PRESS:
260 clicked_regionview = 0;
261 clicked_control_point = 0;
262 clicked_trackview = tv;
263 clicked_audio_trackview = tv;
264 ret = button_press_handler (item, event, StreamItem);
267 case GDK_BUTTON_RELEASE:
268 ret = button_release_handler (item, event, StreamItem);
271 case GDK_MOTION_NOTIFY:
272 ret = motion_handler (item, event, StreamItem);
275 case GDK_ENTER_NOTIFY:
288 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
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 = atv;
299 clicked_audio_trackview = 0;
300 ret = button_press_handler (item, event, AutomationTrackItem);
303 case GDK_BUTTON_RELEASE:
304 ret = button_release_handler (item, event, AutomationTrackItem);
307 case GDK_MOTION_NOTIFY:
308 ret = motion_handler (item, event, AutomationTrackItem);
311 case GDK_ENTER_NOTIFY:
312 ret = enter_handler (item, event, AutomationTrackItem);
315 case GDK_LEAVE_NOTIFY:
316 ret = leave_handler (item, event, AutomationTrackItem);
327 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
329 /* we handle only button 3 press/release events */
331 switch (event->type) {
332 case GDK_BUTTON_PRESS:
333 clicked_regionview = rv;
334 clicked_control_point = 0;
335 clicked_trackview = &rv->get_time_axis_view();
336 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
337 if (event->button.button == 3) {
338 return button_press_handler (item, event, FadeInItem);
342 case GDK_BUTTON_RELEASE:
343 if (event->button.button == 3) {
344 return button_release_handler (item, event, FadeInItem);
353 /* proxy for the regionview */
355 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
359 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
363 switch (event->type) {
364 case GDK_BUTTON_PRESS:
365 case GDK_2BUTTON_PRESS:
366 case GDK_3BUTTON_PRESS:
367 clicked_regionview = rv;
368 clicked_control_point = 0;
369 clicked_trackview = &rv->get_time_axis_view();
370 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
371 ret = button_press_handler (item, event, FadeInHandleItem);
374 case GDK_BUTTON_RELEASE:
375 ret = button_release_handler (item, event, FadeInHandleItem);
378 case GDK_MOTION_NOTIFY:
379 ret = motion_handler (item, event, FadeInHandleItem);
382 case GDK_ENTER_NOTIFY:
383 ret = enter_handler (item, event, FadeInHandleItem);
386 case GDK_LEAVE_NOTIFY:
387 ret = leave_handler (item, event, FadeInHandleItem);
398 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
400 /* we handle only button 3 press/release events */
402 switch (event->type) {
403 case GDK_BUTTON_PRESS:
404 clicked_regionview = rv;
405 clicked_control_point = 0;
406 clicked_trackview = &rv->get_time_axis_view();
407 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
408 if (event->button.button == 3) {
409 return button_press_handler (item, event, FadeOutItem);
413 case GDK_BUTTON_RELEASE:
414 if (event->button.button == 3) {
415 return button_release_handler (item, event, FadeOutItem);
424 /* proxy for the regionview */
426 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
430 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
434 switch (event->type) {
435 case GDK_BUTTON_PRESS:
436 case GDK_2BUTTON_PRESS:
437 case GDK_3BUTTON_PRESS:
438 clicked_regionview = rv;
439 clicked_control_point = 0;
440 clicked_trackview = &rv->get_time_axis_view();
441 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
442 ret = button_press_handler (item, event, FadeOutHandleItem);
445 case GDK_BUTTON_RELEASE:
446 ret = button_release_handler (item, event, FadeOutHandleItem);
449 case GDK_MOTION_NOTIFY:
450 ret = motion_handler (item, event, FadeOutHandleItem);
453 case GDK_ENTER_NOTIFY:
454 ret = enter_handler (item, event, FadeOutHandleItem);
457 case GDK_LEAVE_NOTIFY:
458 ret = leave_handler (item, event, FadeOutHandleItem);
468 struct DescendingRegionLayerSorter {
469 bool operator()(Region* a, Region* b) {
470 return a->layer() > b->layer();
475 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
477 /* we handle only button 3 press/release events */
479 switch (event->type) {
480 case GDK_BUTTON_PRESS:
481 clicked_crossfadeview = xfv;
482 clicked_trackview = &clicked_crossfadeview->get_time_axis_view();
483 if (event->button.button == 3) {
484 return button_press_handler (item, event, CrossfadeViewItem);
488 case GDK_BUTTON_RELEASE:
489 if (event->button.button == 3) {
490 bool ret = button_release_handler (item, event, CrossfadeViewItem);
501 /* proxy for the upper most regionview */
503 /* XXX really need to check if we are in the name highlight,
504 and proxy to that when required.
507 TimeAxisView& tv (xfv->get_time_axis_view());
508 AudioTimeAxisView* atv;
510 if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
512 if (atv->is_audio_track()) {
514 AudioPlaylist* pl = atv->get_diskstream()->playlist();
515 Playlist::RegionList* rl = pl->regions_at (event_frame (event));
518 DescendingRegionLayerSorter cmp;
521 AudioRegionView* arv = atv->view->find_view (*(dynamic_cast<AudioRegion*> (rl->front())));
527 return canvas_region_view_event (event, arv->get_canvas_group(), arv);
536 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
540 switch (event->type) {
541 case GDK_BUTTON_PRESS:
542 case GDK_2BUTTON_PRESS:
543 case GDK_3BUTTON_PRESS:
544 clicked_control_point = cp;
545 clicked_trackview = &cp->line.trackview;
546 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
547 clicked_regionview = 0;
554 if (dynamic_cast<AudioRegionGainLine*> (&cp->line) != 0) {
555 type = GainControlPointItem;
556 } else if (dynamic_cast<AutomationGainLine*> (&cp->line) != 0) {
557 type = GainAutomationControlPointItem;
558 } else if (dynamic_cast<AutomationPanLine*> (&cp->line) != 0) {
559 type = PanAutomationControlPointItem;
560 } else if (dynamic_cast<RedirectAutomationLine*> (&cp->line) != 0) {
561 type = RedirectAutomationControlPointItem;
566 return typed_event (item, event, type);
570 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
574 if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
576 } else if (dynamic_cast<AutomationGainLine*> (al) != 0) {
577 type = GainAutomationLineItem;
578 } else if (dynamic_cast<AutomationPanLine*> (al) != 0) {
579 type = PanAutomationLineItem;
580 } else if (dynamic_cast<RedirectAutomationLine*> (al) != 0) {
581 type = RedirectAutomationLineItem;
586 return typed_event (item, event, type);
590 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
594 switch (event->type) {
595 case GDK_BUTTON_PRESS:
596 case GDK_2BUTTON_PRESS:
597 case GDK_3BUTTON_PRESS:
598 clicked_selection = rect->id;
599 ret = button_press_handler (item, event, SelectionItem);
601 case GDK_BUTTON_RELEASE:
602 ret = button_release_handler (item, event, SelectionItem);
604 case GDK_MOTION_NOTIFY:
605 ret = motion_handler (item, event, SelectionItem);
607 /* Don't need these at the moment. */
608 case GDK_ENTER_NOTIFY:
609 ret = enter_handler (item, event, SelectionItem);
612 case GDK_LEAVE_NOTIFY:
613 ret = leave_handler (item, event, SelectionItem);
624 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
628 switch (event->type) {
629 case GDK_BUTTON_PRESS:
630 case GDK_2BUTTON_PRESS:
631 case GDK_3BUTTON_PRESS:
632 clicked_selection = rect->id;
633 ret = button_press_handler (item, event, StartSelectionTrimItem);
635 case GDK_BUTTON_RELEASE:
636 ret = button_release_handler (item, event, StartSelectionTrimItem);
638 case GDK_MOTION_NOTIFY:
639 ret = motion_handler (item, event, StartSelectionTrimItem);
641 case GDK_ENTER_NOTIFY:
642 ret = enter_handler (item, event, StartSelectionTrimItem);
645 case GDK_LEAVE_NOTIFY:
646 ret = leave_handler (item, event, StartSelectionTrimItem);
657 Editor::canvas_selection_end_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, EndSelectionTrimItem);
668 case GDK_BUTTON_RELEASE:
669 ret = button_release_handler (item, event, EndSelectionTrimItem);
671 case GDK_MOTION_NOTIFY:
672 ret = motion_handler (item, event, EndSelectionTrimItem);
674 case GDK_ENTER_NOTIFY:
675 ret = enter_handler (item, event, EndSelectionTrimItem);
678 case GDK_LEAVE_NOTIFY:
679 ret = leave_handler (item, event, EndSelectionTrimItem);
691 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, AudioRegionView* rv)
695 switch (event->type) {
696 case GDK_BUTTON_PRESS:
697 case GDK_2BUTTON_PRESS:
698 case GDK_3BUTTON_PRESS:
699 clicked_regionview = rv;
700 clicked_control_point = 0;
701 clicked_trackview = &clicked_regionview->get_time_axis_view();
702 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
703 ret = button_press_handler (item, event, AudioRegionViewNameHighlight);
705 case GDK_BUTTON_RELEASE:
706 ret = button_release_handler (item, event, AudioRegionViewNameHighlight);
708 case GDK_MOTION_NOTIFY:
709 ret = motion_handler (item, event, AudioRegionViewNameHighlight);
711 case GDK_ENTER_NOTIFY:
712 ret = enter_handler (item, event, AudioRegionViewNameHighlight);
715 case GDK_LEAVE_NOTIFY:
716 ret = leave_handler (item, event, AudioRegionViewNameHighlight);
727 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView* rv)
731 switch (event->type) {
732 case GDK_BUTTON_PRESS:
733 case GDK_2BUTTON_PRESS:
734 case GDK_3BUTTON_PRESS:
735 clicked_regionview = rv;
736 clicked_control_point = 0;
737 clicked_trackview = &clicked_regionview->get_time_axis_view();
738 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
739 ret = button_press_handler (item, event, AudioRegionViewName);
741 case GDK_BUTTON_RELEASE:
742 ret = button_release_handler (item, event, AudioRegionViewName);
744 case GDK_MOTION_NOTIFY:
745 ret = motion_handler (item, event, AudioRegionViewName);
747 case GDK_ENTER_NOTIFY:
748 ret = enter_handler (item, event, AudioRegionViewName);
751 case GDK_LEAVE_NOTIFY:
752 ret = leave_handler (item, event, AudioRegionViewName);
763 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* marker)
765 return typed_event (item, event, MarkerItem);
769 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
771 return typed_event (item, event, MarkerBarItem);
775 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
777 return typed_event (item, event, RangeMarkerBarItem);
781 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
783 return typed_event (item, event, TransportMarkerBarItem);
787 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
789 return typed_event (item, event, TempoMarkerItem);
793 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* marker)
795 return typed_event (item, event, MeterMarkerItem);
799 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
801 return typed_event (item, event, TempoBarItem);
805 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
807 return typed_event (item, event, MeterBarItem);
811 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
813 return typed_event (item, event, PlayheadCursorItem);
817 Editor::canvas_edit_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
819 return typed_event (item, event, EditCursorItem);
823 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
825 return typed_event (item, event, NoItem);