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.
25 #include "pbd/stacktrace.h"
27 #include "ardour/audio_diskstream.h"
28 #include "ardour/audioplaylist.h"
29 #include "ardour/midi_region.h"
30 #include "ardour/audioregion.h"
31 #include "ardour/region_factory.h"
35 #include "public_editor.h"
36 #include "audio_region_view.h"
37 #include "audio_streamview.h"
38 #include "crossfade_view.h"
39 #include "audio_time_axis.h"
40 #include "region_gain_line.h"
41 #include "automation_line.h"
42 #include "automation_time_axis.h"
43 #include "automation_line.h"
44 #include "control_point.h"
45 #include "canvas_impl.h"
46 #include "simplerect.h"
47 #include "interactive-item.h"
48 #include "editor_drag.h"
49 #include "midi_time_axis.h"
55 using namespace ARDOUR;
58 using namespace ArdourCanvas;
61 Editor::track_canvas_scroll (GdkEventScroll* ev)
66 int direction = ev->direction;
68 Gnome::Canvas::Item* item = track_canvas->get_item_at(ev->x, ev->y);
69 InteractiveItem* interactive_item = dynamic_cast<InteractiveItem*>(item);
70 if (interactive_item) {
71 return interactive_item->on_event(reinterpret_cast<GdkEvent*>(ev));
77 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
78 //if (ev->state == GDK_CONTROL_MASK) {
80 the ev->x will be out of step with the canvas
81 if we're in mid zoom, so we have to get the damn mouse
84 track_canvas->get_pointer (x, y);
85 track_canvas->window_to_world (x, y, wx, wy);
88 event.type = GDK_BUTTON_RELEASE;
92 nframes64_t where = event_frame (&event, 0, 0);
93 temporal_zoom_to_frame (false, where);
95 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
96 direction = GDK_SCROLL_LEFT;
98 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
99 if (!current_stepping_trackview) {
100 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
101 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize);
102 current_stepping_trackview = p.first;
103 if (!current_stepping_trackview) {
107 last_track_height_step_timestamp = get_microseconds();
108 current_stepping_trackview->step_height (true);
111 scroll_tracks_up_line ();
116 case GDK_SCROLL_DOWN:
117 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
118 //if (ev->state == GDK_CONTROL_MASK) {
119 track_canvas->get_pointer (x, y);
120 track_canvas->window_to_world (x, y, wx, wy);
123 event.type = GDK_BUTTON_RELEASE;
127 nframes64_t where = event_frame (&event, 0, 0);
128 temporal_zoom_to_frame (true, where);
130 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
131 direction = GDK_SCROLL_RIGHT;
133 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
134 if (!current_stepping_trackview) {
135 step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
136 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize);
137 current_stepping_trackview = p.first;
138 if (!current_stepping_trackview) {
142 last_track_height_step_timestamp = get_microseconds();
143 current_stepping_trackview->step_height (false);
146 scroll_tracks_down_line ();
151 case GDK_SCROLL_LEFT:
152 xdelta = (current_page_frames() / 8);
153 if (leftmost_frame > xdelta) {
154 reset_x_origin (leftmost_frame - xdelta);
160 case GDK_SCROLL_RIGHT:
161 xdelta = (current_page_frames() / 8);
162 if (max_frames - xdelta > leftmost_frame) {
163 reset_x_origin (leftmost_frame + xdelta);
165 reset_x_origin (max_frames - current_page_frames());
178 Editor::track_canvas_scroll_event (GdkEventScroll *event)
180 track_canvas->grab_focus();
181 track_canvas_scroll (event);
186 Editor::track_canvas_button_press_event (GdkEventButton *event)
189 track_canvas->grab_focus();
194 Editor::track_canvas_button_release_event (GdkEventButton *event)
197 _drag->end_grab ((GdkEvent*) event);
205 Editor::track_canvas_motion_notify_event (GdkEventMotion *event)
208 /* keep those motion events coming */
209 track_canvas->get_pointer (x, y);
214 Editor::track_canvas_motion (GdkEvent *ev)
216 if (verbose_cursor_visible) {
217 verbose_canvas_cursor->property_x() = clamp_verbose_cursor_x (ev->motion.x + 10);
218 verbose_canvas_cursor->property_y() = clamp_verbose_cursor_y (ev->motion.y + 10);
225 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
229 switch (event->type) {
230 case GDK_BUTTON_PRESS:
231 case GDK_2BUTTON_PRESS:
232 case GDK_3BUTTON_PRESS:
233 ret = button_press_handler (item, event, type);
235 case GDK_BUTTON_RELEASE:
236 ret = button_release_handler (item, event, type);
238 case GDK_MOTION_NOTIFY:
239 ret = motion_handler (item, event);
242 case GDK_ENTER_NOTIFY:
243 ret = enter_handler (item, event, type);
246 case GDK_LEAVE_NOTIFY:
247 ret = leave_handler (item, event, type);
257 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
261 if (!rv->sensitive ()) {
266 switch (event->type) {
267 case GDK_BUTTON_PRESS:
268 case GDK_2BUTTON_PRESS:
269 case GDK_3BUTTON_PRESS:
270 clicked_regionview = rv;
271 clicked_control_point = 0;
272 clicked_axisview = &rv->get_time_axis_view();
273 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
274 ret = button_press_handler (item, event, RegionItem);
277 case GDK_BUTTON_RELEASE:
278 ret = button_release_handler (item, event, RegionItem);
281 case GDK_MOTION_NOTIFY:
282 ret = motion_handler (item, event);
285 case GDK_ENTER_NOTIFY:
286 set_entered_track (&rv->get_time_axis_view ());
287 set_entered_regionview (rv);
290 case GDK_LEAVE_NOTIFY:
291 set_entered_track (0);
292 set_entered_regionview (0);
303 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
307 switch (event->type) {
308 case GDK_BUTTON_PRESS:
309 case GDK_2BUTTON_PRESS:
310 case GDK_3BUTTON_PRESS:
311 clicked_regionview = 0;
312 clicked_control_point = 0;
313 clicked_axisview = tv;
314 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(tv);
315 ret = button_press_handler (item, event, StreamItem);
318 case GDK_BUTTON_RELEASE:
319 ret = button_release_handler (item, event, StreamItem);
322 case GDK_MOTION_NOTIFY:
323 ret = motion_handler (item, event, StreamItem);
326 case GDK_ENTER_NOTIFY:
327 set_entered_track (tv);
330 case GDK_LEAVE_NOTIFY:
331 set_entered_track (0);
342 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
346 switch (event->type) {
347 case GDK_BUTTON_PRESS:
348 case GDK_2BUTTON_PRESS:
349 case GDK_3BUTTON_PRESS:
350 clicked_regionview = 0;
351 clicked_control_point = 0;
352 clicked_axisview = atv;
353 clicked_routeview = 0;
354 ret = button_press_handler (item, event, AutomationTrackItem);
357 case GDK_BUTTON_RELEASE:
358 ret = button_release_handler (item, event, AutomationTrackItem);
361 case GDK_MOTION_NOTIFY:
362 ret = motion_handler (item, event);
365 case GDK_ENTER_NOTIFY:
366 ret = enter_handler (item, event, AutomationTrackItem);
369 case GDK_LEAVE_NOTIFY:
370 ret = leave_handler (item, event, AutomationTrackItem);
381 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
383 /* we handle only button 3 press/release events */
385 if (!rv->sensitive()) {
389 switch (event->type) {
390 case GDK_BUTTON_PRESS:
391 clicked_regionview = rv;
392 clicked_control_point = 0;
393 clicked_axisview = &rv->get_time_axis_view();
394 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
395 if (event->button.button == 3) {
396 return button_press_handler (item, event, FadeInItem);
400 case GDK_BUTTON_RELEASE:
401 if (event->button.button == 3) {
402 return button_release_handler (item, event, FadeInItem);
411 /* proxy for the regionview */
413 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
417 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
421 if (!rv->sensitive()) {
425 switch (event->type) {
426 case GDK_BUTTON_PRESS:
427 case GDK_2BUTTON_PRESS:
428 case GDK_3BUTTON_PRESS:
429 clicked_regionview = rv;
430 clicked_control_point = 0;
431 clicked_axisview = &rv->get_time_axis_view();
432 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
433 ret = button_press_handler (item, event, FadeInHandleItem);
436 case GDK_BUTTON_RELEASE:
437 ret = button_release_handler (item, event, FadeInHandleItem);
440 case GDK_MOTION_NOTIFY:
441 ret = motion_handler (item, event);
444 case GDK_ENTER_NOTIFY:
445 ret = enter_handler (item, event, FadeInHandleItem);
448 case GDK_LEAVE_NOTIFY:
449 ret = leave_handler (item, event, FadeInHandleItem);
460 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
462 /* we handle only button 3 press/release events */
464 if (!rv->sensitive()) {
468 switch (event->type) {
469 case GDK_BUTTON_PRESS:
470 clicked_regionview = rv;
471 clicked_control_point = 0;
472 clicked_axisview = &rv->get_time_axis_view();
473 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
474 if (event->button.button == 3) {
475 return button_press_handler (item, event, FadeOutItem);
479 case GDK_BUTTON_RELEASE:
480 if (event->button.button == 3) {
481 return button_release_handler (item, event, FadeOutItem);
490 /* proxy for the regionview */
492 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
496 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
500 if (!rv->sensitive()) {
504 switch (event->type) {
505 case GDK_BUTTON_PRESS:
506 case GDK_2BUTTON_PRESS:
507 case GDK_3BUTTON_PRESS:
508 clicked_regionview = rv;
509 clicked_control_point = 0;
510 clicked_axisview = &rv->get_time_axis_view();
511 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
512 ret = button_press_handler (item, event, FadeOutHandleItem);
515 case GDK_BUTTON_RELEASE:
516 ret = button_release_handler (item, event, FadeOutHandleItem);
519 case GDK_MOTION_NOTIFY:
520 ret = motion_handler (item, event);
523 case GDK_ENTER_NOTIFY:
524 ret = enter_handler (item, event, FadeOutHandleItem);
527 case GDK_LEAVE_NOTIFY:
528 ret = leave_handler (item, event, FadeOutHandleItem);
538 struct DescendingRegionLayerSorter {
539 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
540 return a->layer() > b->layer();
545 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
547 /* we handle only button 3 press/release events */
549 switch (event->type) {
550 case GDK_BUTTON_PRESS:
551 clicked_crossfadeview = xfv;
552 clicked_axisview = &clicked_crossfadeview->get_time_axis_view();
553 if (event->button.button == 3) {
554 return button_press_handler (item, event, CrossfadeViewItem);
558 case GDK_BUTTON_RELEASE:
559 if (event->button.button == 3) {
560 bool ret = button_release_handler (item, event, CrossfadeViewItem);
570 /* XXX do not forward double clicks */
572 if (event->type == GDK_2BUTTON_PRESS) {
576 /* proxy for the upper most regionview */
578 /* XXX really need to check if we are in the name highlight,
579 and proxy to that when required.
582 TimeAxisView& tv (xfv->get_time_axis_view());
583 AudioTimeAxisView* atv;
585 if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
587 if (atv->is_audio_track()) {
589 boost::shared_ptr<AudioPlaylist> pl;
590 if ((pl = boost::dynamic_pointer_cast<AudioPlaylist> (atv->get_diskstream()->playlist())) != 0) {
592 Playlist::RegionList* rl = pl->regions_at (event_frame (event));
595 DescendingRegionLayerSorter cmp;
598 RegionView* rv = atv->view()->find_view (rl->front());
604 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
616 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
618 switch (event->type) {
619 case GDK_BUTTON_PRESS:
620 case GDK_2BUTTON_PRESS:
621 case GDK_3BUTTON_PRESS:
622 clicked_control_point = cp;
623 clicked_axisview = &cp->line().trackview;
624 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
625 clicked_regionview = 0;
631 case GDK_SCROLL_DOWN:
638 return typed_event (item, event, ControlPointItem);
642 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
646 if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
649 type = AutomationLineItem;
652 return typed_event (item, event, type);
656 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
660 switch (event->type) {
661 case GDK_BUTTON_PRESS:
662 case GDK_2BUTTON_PRESS:
663 case GDK_3BUTTON_PRESS:
664 clicked_selection = rect->id;
665 ret = button_press_handler (item, event, SelectionItem);
667 case GDK_BUTTON_RELEASE:
668 ret = button_release_handler (item, event, SelectionItem);
670 case GDK_MOTION_NOTIFY:
671 ret = motion_handler (item, event);
673 /* Don't need these at the moment. */
674 case GDK_ENTER_NOTIFY:
675 ret = enter_handler (item, event, SelectionItem);
678 case GDK_LEAVE_NOTIFY:
679 ret = leave_handler (item, event, SelectionItem);
690 Editor::canvas_selection_start_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, StartSelectionTrimItem);
701 case GDK_BUTTON_RELEASE:
702 ret = button_release_handler (item, event, StartSelectionTrimItem);
704 case GDK_MOTION_NOTIFY:
705 ret = motion_handler (item, event);
707 case GDK_ENTER_NOTIFY:
708 ret = enter_handler (item, event, StartSelectionTrimItem);
711 case GDK_LEAVE_NOTIFY:
712 ret = leave_handler (item, event, StartSelectionTrimItem);
723 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
727 switch (event->type) {
728 case GDK_BUTTON_PRESS:
729 case GDK_2BUTTON_PRESS:
730 case GDK_3BUTTON_PRESS:
731 clicked_selection = rect->id;
732 ret = button_press_handler (item, event, EndSelectionTrimItem);
734 case GDK_BUTTON_RELEASE:
735 ret = button_release_handler (item, event, EndSelectionTrimItem);
737 case GDK_MOTION_NOTIFY:
738 ret = motion_handler (item, event);
740 case GDK_ENTER_NOTIFY:
741 ret = enter_handler (item, event, EndSelectionTrimItem);
744 case GDK_LEAVE_NOTIFY:
745 ret = leave_handler (item, event, EndSelectionTrimItem);
757 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
761 if (!rv->sensitive()) {
765 switch (event->type) {
766 case GDK_BUTTON_PRESS:
767 case GDK_2BUTTON_PRESS:
768 case GDK_3BUTTON_PRESS:
769 clicked_regionview = rv;
770 clicked_control_point = 0;
771 clicked_axisview = &clicked_regionview->get_time_axis_view();
772 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
773 ret = button_press_handler (item, event, RegionViewNameHighlight);
775 case GDK_BUTTON_RELEASE:
776 ret = button_release_handler (item, event, RegionViewNameHighlight);
778 case GDK_MOTION_NOTIFY:
779 ret = motion_handler (item, event);
781 case GDK_ENTER_NOTIFY:
782 ret = enter_handler (item, event, RegionViewNameHighlight);
785 case GDK_LEAVE_NOTIFY:
786 ret = leave_handler (item, event, RegionViewNameHighlight);
797 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
801 if (!rv->sensitive()) {
805 switch (event->type) {
806 case GDK_BUTTON_PRESS:
807 case GDK_2BUTTON_PRESS:
808 case GDK_3BUTTON_PRESS:
809 clicked_regionview = rv;
810 clicked_control_point = 0;
811 clicked_axisview = &clicked_regionview->get_time_axis_view();
812 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
813 ret = button_press_handler (item, event, RegionViewName);
815 case GDK_BUTTON_RELEASE:
816 ret = button_release_handler (item, event, RegionViewName);
818 case GDK_MOTION_NOTIFY:
819 ret = motion_handler (item, event);
821 case GDK_ENTER_NOTIFY:
822 ret = enter_handler (item, event, RegionViewName);
825 case GDK_LEAVE_NOTIFY:
826 ret = leave_handler (item, event, RegionViewName);
837 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* marker)
839 return typed_event (item, event, MarkerItem);
843 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
845 return typed_event (item, event, MarkerBarItem);
849 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
851 return typed_event (item, event, RangeMarkerBarItem);
855 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
857 return typed_event (item, event, TransportMarkerBarItem);
861 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
863 return typed_event (item, event, CdMarkerBarItem);
867 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
869 return typed_event (item, event, TempoMarkerItem);
873 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* marker)
875 return typed_event (item, event, MeterMarkerItem);
879 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
881 return typed_event (item, event, TempoBarItem);
885 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
887 return typed_event (item, event, MeterBarItem);
891 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
893 return typed_event (item, event, PlayheadCursorItem);
897 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
899 return typed_event (item, event, NoItem);
903 Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const & c, int x, int y, guint time)
907 track_canvas->window_to_world (x, y, wx, wy);
910 event.type = GDK_MOTION_NOTIFY;
913 /* assume we're dragging with button 1 */
914 event.motion.state = Gdk::BUTTON1_MASK;
920 nframes64_t const pos = event_frame (&event, &px, &py);
922 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py);
927 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
928 if (rtav == 0 || !rtav->is_track ()) {
932 list<boost::shared_ptr<Region> > regions;
934 region_list_display.get_object_drag_data (regions, &source);
935 assert (regions.size() == 1);
936 boost::shared_ptr<Region> region = regions.front ();
938 boost::shared_ptr<Region> region_copy = RegionFactory::create (region);
940 if (boost::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 &&
941 dynamic_cast<AudioTimeAxisView*> (tv.first) == 0) {
943 /* audio -> non-audio */
947 if (boost::dynamic_pointer_cast<MidiRegion> (region_copy) == 0 &&
948 dynamic_cast<MidiTimeAxisView*> (tv.first) != 0) {
950 /* MIDI -> non-MIDI */
954 _drag = new RegionInsertDrag (this, region_copy, rtav, pos);
955 _drag->start_grab (&event);
958 _drag->motion_handler (&event, false);