1 /*
2  * Copyright (C) 2005-2018 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2005 Taybin Rutkin <taybin@taybin.com>
4  * Copyright (C) 2006-2012 David Robillard <d@drobilla.net>
5  * Copyright (C) 2008 Hans Baier <hansfbaier@googlemail.com>
6  * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
7  * Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
8  * Copyright (C) 2015-2016 Tim Mayberry <mojofunk@gmail.com>
9  * Copyright (C) 2015-2017 Nick Mainsbridge <mainsbridge@gmail.com>
10  * Copyright (C) 2015-2019 Ben Loftis <ben@harrisonconsoles.com>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26 
27 #include <cstdlib>
28 #include <cmath>
29 #include <algorithm>
30 #include <typeinfo>
31 
32 #include "ardour/audio_track.h"
33 #include "ardour/midi_track.h"
34 #include "ardour/midi_region.h"
35 #include "ardour/profile.h"
36 #include "ardour/region_factory.h"
37 
38 #include "canvas/canvas.h"
39 #include "canvas/text.h"
40 #include "canvas/scroll_group.h"
41 
42 #include "editor.h"
43 #include "keyboard.h"
44 #include "public_editor.h"
45 #include "audio_region_view.h"
46 #include "audio_streamview.h"
47 #include "audio_time_axis.h"
48 #include "region_gain_line.h"
49 #include "automation_line.h"
50 #include "automation_time_axis.h"
51 #include "automation_line.h"
52 #include "control_point.h"
53 #include "editor_drag.h"
54 #include "midi_time_axis.h"
55 #include "editor_regions.h"
56 #include "editor_sources.h"
57 #include "ui_config.h"
58 #include "verbose_cursor.h"
59 
60 #include "pbd/i18n.h"
61 
62 using namespace std;
63 using namespace ARDOUR;
64 using namespace PBD;
65 using namespace Gtk;
66 using namespace ArdourCanvas;
67 
68 using Gtkmm2ext::Keyboard;
69 
70 bool
track_canvas_scroll(GdkEventScroll * ev)71 Editor::track_canvas_scroll (GdkEventScroll* ev)
72 {
73 	int direction = ev->direction;
74 
75 	/* this event arrives without transformation by the canvas, so we have
76 	 * to transform the coordinates to be able to look things up.
77 	 */
78 
79 	Duple event_coords = _track_canvas->window_to_canvas (Duple (ev->x, ev->y));
80 
81 	switch (direction) {
82 	case GDK_SCROLL_UP:
83 		if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) {
84 			temporal_zoom_step_mouse_focus (false);
85 			return true;
86 		} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) {
87 			scroll_left_step ();
88 			return true;
89 		} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) {
90 			if (!current_stepping_trackview) {
91 				step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
92 				std::pair<TimeAxisView*, int> const p = trackview_by_y_position (event_coords.y, false);
93 				current_stepping_trackview = p.first;
94 				if (!current_stepping_trackview) {
95 					return false;
96 				}
97 			}
98 			last_track_height_step_timestamp = get_microseconds();
99 			current_stepping_trackview->step_height (false);
100 			return true;
101 		} else {
102 			scroll_up_one_track ();
103 			return true;
104 		}
105 		break;
106 
107 	case GDK_SCROLL_DOWN:
108 		if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) {
109 			temporal_zoom_step_mouse_focus (true);
110 			return true;
111 		} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) {
112 			scroll_right_step ();
113 			return true;
114 		} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) {
115 			if (!current_stepping_trackview) {
116 				step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
117 				std::pair<TimeAxisView*, int> const p = trackview_by_y_position (event_coords.y, false);
118 				current_stepping_trackview = p.first;
119 				if (!current_stepping_trackview) {
120 					return false;
121 				}
122 			}
123 			last_track_height_step_timestamp = get_microseconds();
124 			current_stepping_trackview->step_height (true);
125 			return true;
126 		} else {
127 			scroll_down_one_track ();
128 			return true;
129 		}
130 		break;
131 
132 	case GDK_SCROLL_LEFT:
133 		scroll_left_step ();
134 		return true;
135 		break;
136 
137 	case GDK_SCROLL_RIGHT:
138 		scroll_right_step ();
139 		return true;
140 		break;
141 
142 	default:
143 		/* what? */
144 		break;
145 	}
146 
147 	return false;
148 }
149 
150 bool
canvas_scroll_event(GdkEventScroll * event,bool from_canvas)151 Editor::canvas_scroll_event (GdkEventScroll *event, bool from_canvas)
152 {
153 	if (from_canvas) {
154 		boost::optional<ArdourCanvas::Rect> rulers = _time_markers_group->bounding_box();
155 		if (rulers && rulers->contains (Duple (event->x, event->y))) {
156 			return canvas_ruler_event ((GdkEvent*) event, timecode_ruler, TimecodeRulerItem);
157 		}
158 	}
159 
160 	_track_canvas->grab_focus();
161 	return track_canvas_scroll (event);
162 }
163 
164 bool
track_canvas_button_press_event(GdkEventButton * event)165 Editor::track_canvas_button_press_event (GdkEventButton *event)
166 {
167 	_track_canvas->grab_focus();
168 	if (!internal_editing() && !Keyboard::is_context_menu_event (event)) {
169 		begin_reversible_selection_op (X_("Clear Selection Click (track canvas)"));
170 		selection->clear ();
171 		commit_reversible_selection_op();
172 	}
173 	return false;
174 }
175 
176 bool
track_canvas_button_release_event(GdkEventButton * event)177 Editor::track_canvas_button_release_event (GdkEventButton *event)
178 {
179 	if (!Keyboard::is_context_menu_event (event)) {
180 		if (_drags->active ()) {
181 
182 			GdkEvent copy = *((GdkEvent*) event);
183 			Duple winpos = Duple (event->x, event->y);
184 			Duple where = _track_canvas->window_to_canvas (winpos);
185 
186 			copy.button.x = where.x;
187 			copy.button.y = where.y;
188 
189 			_drags->end_grab (&copy);
190 		}
191 	}
192 	return false;
193 }
194 
195 bool
track_canvas_motion_notify_event(GdkEventMotion *)196 Editor::track_canvas_motion_notify_event (GdkEventMotion */*event*/)
197 {
198 	int x, y;
199 	/* keep those motion events coming */
200 	_track_canvas->get_pointer (x, y);
201 	return false;
202 }
203 
204 bool
typed_event(ArdourCanvas::Item * item,GdkEvent * event,ItemType type)205 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
206 {
207 	if (!session () || session()->loading () || session()->deletion_in_progress ()) {
208 		return false;
209 	}
210 
211 	gint ret = FALSE;
212 
213 	switch (event->type) {
214 	case GDK_BUTTON_PRESS:
215 	case GDK_2BUTTON_PRESS:
216 	case GDK_3BUTTON_PRESS:
217 		ret = button_press_handler (item, event, type);
218 		break;
219 	case GDK_BUTTON_RELEASE:
220 		ret = button_release_handler (item, event, type);
221 		break;
222 	case GDK_MOTION_NOTIFY:
223 		ret = motion_handler (item, event);
224 		break;
225 
226 	case GDK_ENTER_NOTIFY:
227 		ret = enter_handler (item, event, type);
228 		break;
229 
230 	case GDK_LEAVE_NOTIFY:
231 		ret = leave_handler (item, event, type);
232 		break;
233 
234 	case GDK_KEY_PRESS:
235 		ret = key_press_handler (item, event, type);
236 		break;
237 
238 	case GDK_KEY_RELEASE:
239 		ret = key_release_handler (item, event, type);
240 		break;
241 
242 	default:
243 		break;
244 	}
245 	return ret;
246 }
247 
248 bool
canvas_region_view_event(GdkEvent * event,ArdourCanvas::Item * item,RegionView * rv)249 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
250 {
251 	bool ret = false;
252 
253 	if (!rv->sensitive ()) {
254 		return false;
255 	}
256 
257 	switch (event->type) {
258 	case GDK_BUTTON_PRESS:
259 	case GDK_2BUTTON_PRESS:
260 	case GDK_3BUTTON_PRESS:
261 		clicked_regionview = rv;
262 		clicked_control_point = 0;
263 		clicked_axisview = &rv->get_time_axis_view();
264 		clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
265 		ret = button_press_handler (item, event, RegionItem);
266 		break;
267 
268 	case GDK_BUTTON_RELEASE:
269 		ret = button_release_handler (item, event, RegionItem);
270 		break;
271 
272 	case GDK_MOTION_NOTIFY:
273 		ret = motion_handler (item, event);
274 		break;
275 
276 	case GDK_ENTER_NOTIFY:
277 		set_entered_regionview (rv);
278 		ret = enter_handler (item, event, RegionItem);
279 		break;
280 
281 	case GDK_LEAVE_NOTIFY:
282 		if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
283 			set_entered_regionview (0);
284 			ret = leave_handler (item, event, RegionItem);
285 		}
286 		break;
287 
288 	default:
289 		break;
290 	}
291 
292 	return ret;
293 }
294 
295 bool
canvas_wave_view_event(GdkEvent * event,ArdourCanvas::Item * item,RegionView * rv)296 Editor::canvas_wave_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
297 {
298 	/* we only care about enter events here, required for mouse/cursor
299 	 * tracking. there is a non-linear (non-child/non-parent) relationship
300 	 * between various components of a regionview and so when we leave one
301 	 * of them (e.g. a trim handle) and enter another (e.g. the waveview)
302 	 * no other items get notified. enter/leave handling does not propagate
303 	 * in the same way as other events, so we need to catch this because
304 	 * entering (and leaving) the waveview is equivalent to
305 	 * entering/leaving the regionview (which is why it is passed in as a
306 	 * third argument).
307 	 *
308 	 * And in fact, we really only care about enter events.
309 	 */
310 
311 	bool ret = false;
312 
313 	if (!rv->sensitive ()) {
314 		return false;
315 	}
316 
317 	switch (event->type) {
318 	case GDK_ENTER_NOTIFY:
319 		set_entered_regionview (rv);
320 		ret = enter_handler (item, event, WaveItem);
321 		break;
322 
323 	default:
324 		break;
325 	}
326 
327 	return ret;
328 }
329 
330 
331 bool
canvas_stream_view_event(GdkEvent * event,ArdourCanvas::Item * item,RouteTimeAxisView * tv)332 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
333 {
334 	bool ret = FALSE;
335 
336 	switch (event->type) {
337 	case GDK_BUTTON_PRESS:
338 	case GDK_2BUTTON_PRESS:
339 	case GDK_3BUTTON_PRESS:
340 		clicked_regionview = 0;
341 		clicked_control_point = 0;
342 		clicked_axisview = tv;
343 		clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
344 		ret = button_press_handler (item, event, StreamItem);
345 		break;
346 
347 	case GDK_BUTTON_RELEASE:
348 		ret = button_release_handler (item, event, StreamItem);
349 		break;
350 
351 	case GDK_MOTION_NOTIFY:
352 		ret = motion_handler (item, event);
353 		break;
354 
355 	case GDK_ENTER_NOTIFY:
356 		set_entered_track (tv);
357 		ret = enter_handler (item, event, StreamItem);
358 		break;
359 
360 	case GDK_LEAVE_NOTIFY:
361 		if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
362 			set_entered_track (0);
363 		}
364 		ret = leave_handler (item, event, StreamItem);
365 		break;
366 
367 	default:
368 		break;
369 	}
370 
371 	return ret;
372 }
373 
374 bool
canvas_automation_track_event(GdkEvent * event,ArdourCanvas::Item * item,AutomationTimeAxisView * atv)375 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
376 {
377 	bool ret = false;
378 
379 	switch (event->type) {
380 	case GDK_BUTTON_PRESS:
381 	case GDK_2BUTTON_PRESS:
382 	case GDK_3BUTTON_PRESS:
383 		clicked_regionview = 0;
384 		clicked_control_point = 0;
385 		clicked_axisview = atv;
386 		clicked_routeview = 0;
387 		ret = button_press_handler (item, event, AutomationTrackItem);
388 		break;
389 
390 	case GDK_BUTTON_RELEASE:
391 		ret = button_release_handler (item, event, AutomationTrackItem);
392 		break;
393 
394 	case GDK_MOTION_NOTIFY:
395 		ret = motion_handler (item, event);
396 		break;
397 
398 	case GDK_ENTER_NOTIFY:
399 		ret = enter_handler (item, event, AutomationTrackItem);
400 		break;
401 
402 	case GDK_LEAVE_NOTIFY:
403 		ret = leave_handler (item, event, AutomationTrackItem);
404 		break;
405 
406 	default:
407 		break;
408 	}
409 
410 	return ret;
411 }
412 
413 bool
canvas_start_xfade_event(GdkEvent * event,ArdourCanvas::Item * item,AudioRegionView * rv)414 Editor::canvas_start_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
415 {
416 	if (!rv->sensitive()) {
417 		return false;
418 	}
419 
420 	switch (event->type) {
421 	case GDK_BUTTON_PRESS:
422 		clicked_regionview = rv;
423 		clicked_control_point = 0;
424 		clicked_axisview = &rv->get_time_axis_view();
425 		clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
426 		if (event->button.button == 3) {
427 			return button_press_handler (item, event, StartCrossFadeItem);
428 		}
429 		break;
430 
431 	case GDK_BUTTON_RELEASE:
432 		if (event->button.button == 3) {
433 			return button_release_handler (item, event, StartCrossFadeItem);
434 		}
435 		break;
436 
437 	default:
438 		break;
439 
440 	}
441 
442 	/* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/
443 	/* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */
444 	/* if we return RegionItem here then we avoid the issue until it is resolved later */
445 	return typed_event (item, event, RegionItem); // StartCrossFadeItem);
446 }
447 
448 bool
canvas_end_xfade_event(GdkEvent * event,ArdourCanvas::Item * item,AudioRegionView * rv)449 Editor::canvas_end_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
450 {
451 	if (!rv->sensitive()) {
452 		return false;
453 	}
454 
455 	switch (event->type) {
456 	case GDK_BUTTON_PRESS:
457 		clicked_regionview = rv;
458 		clicked_control_point = 0;
459 		clicked_axisview = &rv->get_time_axis_view();
460 		clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
461 		if (event->button.button == 3) {
462 			return button_press_handler (item, event, EndCrossFadeItem);
463 		}
464 		break;
465 
466 	case GDK_BUTTON_RELEASE:
467 		if (event->button.button == 3) {
468 			return button_release_handler (item, event, EndCrossFadeItem);
469 		}
470 		break;
471 
472 	default:
473 		break;
474 
475 	}
476 
477 	/* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/
478 	/* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */
479 	/* if we return RegionItem here then we avoid the issue until it is resolved later */
480 	return typed_event (item, event, RegionItem); // EndCrossFadeItem);
481 }
482 
483 bool
canvas_fade_in_event(GdkEvent * event,ArdourCanvas::Item * item,AudioRegionView * rv)484 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
485 {
486 	/* we handle only button 3 press/release events */
487 
488 	if (!rv->sensitive()) {
489 		return false;
490 	}
491 
492 	switch (event->type) {
493 	case GDK_BUTTON_PRESS:
494 		clicked_regionview = rv;
495 		clicked_control_point = 0;
496 		clicked_axisview = &rv->get_time_axis_view();
497 		clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
498 		if (event->button.button == 3) {
499 			return button_press_handler (item, event, FadeInItem);
500 		}
501 		break;
502 
503 	case GDK_BUTTON_RELEASE:
504 		if (event->button.button == 3) {
505 			return button_release_handler (item, event, FadeInItem);
506 		}
507 		break;
508 
509 	default:
510 		break;
511 
512 	}
513 
514 	/* proxy for the regionview, except enter/leave events */
515 
516 	if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
517 		return true;
518 	} else {
519 		return canvas_region_view_event (event, rv->get_canvas_group(), rv);
520 	}
521 }
522 
523 bool
canvas_fade_in_handle_event(GdkEvent * event,ArdourCanvas::Item * item,AudioRegionView * rv,bool trim)524 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
525 {
526 	bool ret = false;
527 
528 	if (!rv->sensitive()) {
529 		return false;
530 	}
531 
532 	switch (event->type) {
533 	case GDK_BUTTON_PRESS:
534 	case GDK_2BUTTON_PRESS:
535 	case GDK_3BUTTON_PRESS:
536 		clicked_regionview = rv;
537 		clicked_control_point = 0;
538 		clicked_axisview = &rv->get_time_axis_view();
539 		clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
540 		ret = button_press_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
541 		break;
542 
543 	case GDK_BUTTON_RELEASE:
544 		ret = button_release_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
545 		break;
546 
547 	case GDK_MOTION_NOTIFY:
548 		ret = motion_handler (item, event);
549 		break;
550 
551 	case GDK_ENTER_NOTIFY:
552 		ret = enter_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
553 		break;
554 
555 	case GDK_LEAVE_NOTIFY:
556 		ret = leave_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
557 		break;
558 
559 	default:
560 		break;
561 	}
562 
563 	return ret;
564 }
565 
566 bool
canvas_fade_out_event(GdkEvent * event,ArdourCanvas::Item * item,AudioRegionView * rv)567 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
568 {
569 	/* we handle only button 3 press/release events */
570 
571 	if (!rv->sensitive()) {
572 		return false;
573 	}
574 
575 	switch (event->type) {
576 	case GDK_BUTTON_PRESS:
577 		clicked_regionview = rv;
578 		clicked_control_point = 0;
579 		clicked_axisview = &rv->get_time_axis_view();
580 		clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
581 		if (event->button.button == 3) {
582 			return button_press_handler (item, event, FadeOutItem);
583 		}
584 		break;
585 
586 	case GDK_BUTTON_RELEASE:
587 		if (event->button.button == 3) {
588 			return button_release_handler (item, event, FadeOutItem);
589 		}
590 		break;
591 
592 	default:
593 		break;
594 
595 	}
596 
597 	/* proxy for the regionview, except enter/leave events */
598 
599 	if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
600 		return true;
601 	} else {
602 		return canvas_region_view_event (event, rv->get_canvas_group(), rv);
603 	}
604 }
605 
606 bool
canvas_fade_out_handle_event(GdkEvent * event,ArdourCanvas::Item * item,AudioRegionView * rv,bool trim)607 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
608 {
609 	bool ret = false;
610 
611 	if (!rv->sensitive()) {
612 		return false;
613 	}
614 
615 	switch (event->type) {
616 	case GDK_BUTTON_PRESS:
617 	case GDK_2BUTTON_PRESS:
618 	case GDK_3BUTTON_PRESS:
619 		clicked_regionview = rv;
620 		clicked_control_point = 0;
621 		clicked_axisview = &rv->get_time_axis_view();
622 		clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
623 		ret = button_press_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
624 		break;
625 
626 	case GDK_BUTTON_RELEASE:
627 		ret = button_release_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
628 		break;
629 
630 	case GDK_MOTION_NOTIFY:
631 		ret = motion_handler (item, event);
632 		break;
633 
634 	case GDK_ENTER_NOTIFY:
635 		ret = enter_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
636 		break;
637 
638 	case GDK_LEAVE_NOTIFY:
639 		ret = leave_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
640 		break;
641 
642 	default:
643 		break;
644 	}
645 
646 	return ret;
647 }
648 
649 struct DescendingRegionLayerSorter {
operator ()DescendingRegionLayerSorter650 	bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
651 		return a->layer() > b->layer();
652 	}
653 };
654 
655 bool
canvas_control_point_event(GdkEvent * event,ArdourCanvas::Item * item,ControlPoint * cp)656 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
657 {
658 	switch (event->type) {
659 	case GDK_BUTTON_PRESS:
660 	case GDK_2BUTTON_PRESS:
661 	case GDK_3BUTTON_PRESS:
662 		clicked_control_point = cp;
663 		clicked_axisview = &cp->line().trackview;
664 		clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
665 		clicked_regionview = 0;
666 		break;
667 	default:
668 		break;
669 	}
670 
671 	return typed_event (item, event, ControlPointItem);
672 }
673 
674 bool
canvas_line_event(GdkEvent * event,ArdourCanvas::Item * item,AutomationLine * al)675 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
676 {
677 	ItemType type;
678 	AudioRegionGainLine* gl;
679 	if ((gl = dynamic_cast<AudioRegionGainLine*> (al)) != 0) {
680 		type = GainLineItem;
681 		if (event->type == GDK_BUTTON_PRESS) {
682 			clicked_regionview = &gl->region_view ();
683 		}
684 	} else {
685 		type = AutomationLineItem;
686 		if (event->type == GDK_BUTTON_PRESS) {
687 			clicked_regionview = 0;
688 		}
689 	}
690 
691 	clicked_control_point = 0;
692 	clicked_axisview = &al->trackview;
693 	clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
694 
695 	return typed_event (item, event, type);
696 }
697 
698 bool
canvas_selection_rect_event(GdkEvent * event,ArdourCanvas::Item * item,SelectionRect * rect)699 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
700 {
701 	bool ret = false;
702 
703 	switch (event->type) {
704 	case GDK_BUTTON_PRESS:
705 	case GDK_2BUTTON_PRESS:
706 	case GDK_3BUTTON_PRESS:
707 		clicked_selection = rect->id;
708 		ret = button_press_handler (item, event, SelectionItem);
709 		break;
710 	case GDK_BUTTON_RELEASE:
711 		ret = button_release_handler (item, event, SelectionItem);
712 		break;
713 	case GDK_MOTION_NOTIFY:
714 		ret = motion_handler (item, event);
715 		break;
716 		/* Don't need these at the moment. */
717 	case GDK_ENTER_NOTIFY:
718 		ret = enter_handler (item, event, SelectionItem);
719 		break;
720 
721 	case GDK_LEAVE_NOTIFY:
722 		ret = leave_handler (item, event, SelectionItem);
723 		break;
724 
725 	default:
726 		break;
727 	}
728 
729 	return ret;
730 }
731 
732 bool
canvas_selection_start_trim_event(GdkEvent * event,ArdourCanvas::Item * item,SelectionRect * rect)733 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
734 {
735 	bool ret = false;
736 
737 	switch (event->type) {
738 	case GDK_BUTTON_PRESS:
739 	case GDK_2BUTTON_PRESS:
740 	case GDK_3BUTTON_PRESS:
741 		clicked_selection = rect->id;
742 		ret = button_press_handler (item, event, StartSelectionTrimItem);
743 		break;
744 	case GDK_BUTTON_RELEASE:
745 		ret = button_release_handler (item, event, StartSelectionTrimItem);
746 		break;
747 	case GDK_MOTION_NOTIFY:
748 		ret = motion_handler (item, event);
749 		break;
750 	case GDK_ENTER_NOTIFY:
751 		ret = enter_handler (item, event, StartSelectionTrimItem);
752 		break;
753 
754 	case GDK_LEAVE_NOTIFY:
755 		ret = leave_handler (item, event, StartSelectionTrimItem);
756 		break;
757 
758 	default:
759 		break;
760 	}
761 
762 	return ret;
763 }
764 
765 bool
canvas_selection_end_trim_event(GdkEvent * event,ArdourCanvas::Item * item,SelectionRect * rect)766 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
767 {
768 	bool ret = false;
769 
770 	switch (event->type) {
771 	case GDK_BUTTON_PRESS:
772 	case GDK_2BUTTON_PRESS:
773 	case GDK_3BUTTON_PRESS:
774 		clicked_selection = rect->id;
775 		ret = button_press_handler (item, event, EndSelectionTrimItem);
776 		break;
777 	case GDK_BUTTON_RELEASE:
778 		ret = button_release_handler (item, event, EndSelectionTrimItem);
779 		break;
780 	case GDK_MOTION_NOTIFY:
781 		ret = motion_handler (item, event);
782 		break;
783 	case GDK_ENTER_NOTIFY:
784 		ret = enter_handler (item, event, EndSelectionTrimItem);
785 		break;
786 
787 	case GDK_LEAVE_NOTIFY:
788 		ret = leave_handler (item, event, EndSelectionTrimItem);
789 		break;
790 
791 	default:
792 		break;
793 	}
794 
795 	return ret;
796 }
797 
798 bool
canvas_frame_handle_event(GdkEvent * event,ArdourCanvas::Item * item,RegionView * rv)799 Editor::canvas_frame_handle_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
800 {
801 	bool ret = false;
802 
803 	/* frame handles are not active when in internal edit mode, because actual notes
804 	   might be in the area occupied by the handle - we want them to be editable as normal.
805 	*/
806 
807 	if (internal_editing() || !rv->sensitive()) {
808 		return false;
809 	}
810 
811 	/* NOTE: frame handles pretend to be the colored trim bar from an event handling
812 	   perspective. XXX change this ??
813 	*/
814 
815 	ItemType type;
816 
817 	if (item->get_data ("isleft")) {
818 		type = LeftFrameHandle;
819 	} else {
820 		type = RightFrameHandle;
821 	}
822 
823 	switch (event->type) {
824 	case GDK_BUTTON_PRESS:
825 	case GDK_2BUTTON_PRESS:
826 	case GDK_3BUTTON_PRESS:
827 		clicked_regionview = rv;
828 		clicked_control_point = 0;
829 		clicked_axisview = &clicked_regionview->get_time_axis_view();
830 		clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
831 		ret = button_press_handler (item, event, type);
832 		break;
833 	case GDK_BUTTON_RELEASE:
834 		ret = button_release_handler (item, event, type);
835 		break;
836 	case GDK_MOTION_NOTIFY:
837 		ret = motion_handler (item, event);
838 		break;
839 	case GDK_ENTER_NOTIFY:
840 		ret = enter_handler (item, event, type);
841 		break;
842 
843 	case GDK_LEAVE_NOTIFY:
844 		ret = leave_handler (item, event, type);
845 		break;
846 
847 	default:
848 		break;
849 	}
850 
851 	return ret;
852 }
853 
854 
855 bool
canvas_region_view_name_highlight_event(GdkEvent * event,ArdourCanvas::Item * item,RegionView * rv)856 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
857 {
858 	bool ret = false;
859 
860 	if (!rv->sensitive()) {
861 		return false;
862 	}
863 
864 	switch (event->type) {
865 	case GDK_BUTTON_PRESS:
866 	case GDK_2BUTTON_PRESS:
867 	case GDK_3BUTTON_PRESS:
868 		clicked_regionview = rv;
869 		clicked_control_point = 0;
870 		clicked_axisview = &clicked_regionview->get_time_axis_view();
871 		clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
872 		ret = button_press_handler (item, event, RegionViewNameHighlight);
873 		break;
874 	case GDK_BUTTON_RELEASE:
875 		ret = button_release_handler (item, event, RegionViewNameHighlight);
876 		break;
877 	case GDK_MOTION_NOTIFY:
878 		motion_handler (item, event);
879 		ret = true; // force this to avoid progagating the event into the regionview
880 		break;
881 	case GDK_ENTER_NOTIFY:
882 		ret = enter_handler (item, event, RegionViewNameHighlight);
883 		break;
884 
885 	case GDK_LEAVE_NOTIFY:
886 		ret = leave_handler (item, event, RegionViewNameHighlight);
887 		break;
888 
889 	default:
890 		break;
891 	}
892 
893 	return ret;
894 }
895 
896 bool
canvas_region_view_name_event(GdkEvent * event,ArdourCanvas::Item * item,RegionView * rv)897 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
898 {
899 	bool ret = false;
900 
901 	if (!rv->sensitive()) {
902 		return false;
903 	}
904 
905 	switch (event->type) {
906 	case GDK_BUTTON_PRESS:
907 	case GDK_2BUTTON_PRESS:
908 	case GDK_3BUTTON_PRESS:
909 		clicked_regionview = rv;
910 		clicked_control_point = 0;
911 		clicked_axisview = &clicked_regionview->get_time_axis_view();
912 		clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
913 		ret = button_press_handler (item, event, RegionViewName);
914 		break;
915 	case GDK_BUTTON_RELEASE:
916 		ret = button_release_handler (item, event, RegionViewName);
917 		break;
918 	case GDK_MOTION_NOTIFY:
919 		ret = motion_handler (item, event);
920 		break;
921 	case GDK_ENTER_NOTIFY:
922 		ret = enter_handler (item, event, RegionViewName);
923 		break;
924 
925 	case GDK_LEAVE_NOTIFY:
926 		ret = leave_handler (item, event, RegionViewName);
927 		break;
928 
929 	default:
930 		break;
931 	}
932 
933 	return ret;
934 }
935 
936 bool
canvas_feature_line_event(GdkEvent * event,ArdourCanvas::Item * item,RegionView *)937 Editor::canvas_feature_line_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView*)
938 {
939 	bool ret = false;
940 
941 	switch (event->type) {
942 	case GDK_BUTTON_PRESS:
943 	case GDK_2BUTTON_PRESS:
944 	case GDK_3BUTTON_PRESS:
945 		clicked_regionview = 0;
946 		clicked_control_point = 0;
947 		clicked_axisview = 0;
948 		clicked_routeview = 0; //dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
949 		ret = button_press_handler (item, event, FeatureLineItem);
950 		break;
951 
952 	case GDK_BUTTON_RELEASE:
953 		ret = button_release_handler (item, event, FeatureLineItem);
954 		break;
955 
956 	case GDK_MOTION_NOTIFY:
957 		ret = motion_handler (item, event);
958 		break;
959 
960 	case GDK_ENTER_NOTIFY:
961 		ret = enter_handler (item, event, FeatureLineItem);
962 		break;
963 
964 	case GDK_LEAVE_NOTIFY:
965 		ret = leave_handler (item, event, FeatureLineItem);
966 		break;
967 
968 	default:
969 		break;
970 	}
971 
972 	return ret;
973 }
974 
975 bool
canvas_marker_event(GdkEvent * event,ArdourCanvas::Item * item,ArdourMarker *)976 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, ArdourMarker* /*marker*/)
977 {
978 	return typed_event (item, event, MarkerItem);
979 }
980 
981 bool
canvas_marker_bar_event(GdkEvent * event,ArdourCanvas::Item * item)982 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
983 {
984 	return typed_event (item, event, MarkerBarItem);
985 }
986 
987 bool
canvas_range_marker_bar_event(GdkEvent * event,ArdourCanvas::Item * item)988 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
989 {
990 	return typed_event (item, event, RangeMarkerBarItem);
991 }
992 
993 bool
canvas_transport_marker_bar_event(GdkEvent * event,ArdourCanvas::Item * item)994 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
995 {
996 	return typed_event (item, event, TransportMarkerBarItem);
997 }
998 
999 bool
canvas_cd_marker_bar_event(GdkEvent * event,ArdourCanvas::Item * item)1000 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1001 {
1002 	return typed_event (item, event, CdMarkerBarItem);
1003 }
1004 
1005 bool
canvas_videotl_bar_event(GdkEvent * event,ArdourCanvas::Item * item)1006 Editor::canvas_videotl_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1007 {
1008 	return typed_event (item, event, VideoBarItem);
1009 }
1010 
1011 bool
canvas_tempo_marker_event(GdkEvent * event,ArdourCanvas::Item * item,TempoMarker * marker)1012 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
1013 {
1014 	return typed_event (item, event, TempoMarkerItem);
1015 }
1016 
1017 bool
canvas_tempo_curve_event(GdkEvent * event,ArdourCanvas::Item * item,TempoCurve *)1018 Editor::canvas_tempo_curve_event (GdkEvent *event, ArdourCanvas::Item* item, TempoCurve* /*marker*/)
1019 {
1020 	return typed_event (item, event, TempoCurveItem);
1021 }
1022 
1023 bool
canvas_meter_marker_event(GdkEvent * event,ArdourCanvas::Item * item,MeterMarker *)1024 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* /*marker*/)
1025 {
1026 	return typed_event (item, event, MeterMarkerItem);
1027 }
1028 
1029 bool
canvas_ruler_event(GdkEvent * event,ArdourCanvas::Item * item,ItemType type)1030 Editor::canvas_ruler_event (GdkEvent *event, ArdourCanvas::Item* item, ItemType type)
1031 {
1032 	bool handled = false;
1033 
1034 	if (event->type == GDK_SCROLL) {
1035 
1036 		/* scroll events in the rulers are handled a little differently from
1037 		   scrolling elsewhere in the canvas.
1038 		*/
1039 
1040 		switch (event->scroll.direction) {
1041 		case GDK_SCROLL_UP:
1042 			if (Keyboard::modifier_state_equals (event->scroll.state, Keyboard::ScrollHorizontalModifier)) {
1043 				scroll_left_step ();
1044 			} else if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
1045 				temporal_zoom_step_mouse_focus (false);
1046 			} else if (Keyboard::modifier_state_equals (event->scroll.state, Keyboard::PrimaryModifier)) {
1047 				temporal_zoom_step_mouse_focus (false);
1048 			} else {
1049 				temporal_zoom_step (false);
1050 			}
1051 			handled = true;
1052 			break;
1053 
1054 		case GDK_SCROLL_DOWN:
1055 			if (Keyboard::modifier_state_equals (event->scroll.state, Keyboard::ScrollHorizontalModifier)) {
1056 				scroll_right_step ();
1057 			} else if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
1058 				temporal_zoom_step_mouse_focus (true);
1059 			} else if (Keyboard::modifier_state_equals (event->scroll.state, Keyboard::PrimaryModifier)) {
1060 				temporal_zoom_step_mouse_focus (true);
1061 			} else {
1062 				temporal_zoom_step (true);
1063 			}
1064 			handled = true;
1065 			break;
1066 
1067 		case GDK_SCROLL_LEFT:
1068 			scroll_left_half_page ();
1069 			handled = true;
1070 			break;
1071 
1072 		case GDK_SCROLL_RIGHT:
1073 			scroll_right_half_page ();
1074 			handled = true;
1075 			break;
1076 
1077 		default:
1078 			/* what? */
1079 			break;
1080 		}
1081 		return handled;
1082 	}
1083 
1084 	return typed_event (item, event, type);
1085 }
1086 
1087 bool
canvas_tempo_bar_event(GdkEvent * event,ArdourCanvas::Item * item)1088 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1089 {
1090 	return typed_event (item, event, TempoBarItem);
1091 }
1092 
1093 bool
canvas_meter_bar_event(GdkEvent * event,ArdourCanvas::Item * item)1094 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1095 {
1096 	return typed_event (item, event, MeterBarItem);
1097 }
1098 
1099 bool
canvas_playhead_cursor_event(GdkEvent * event,ArdourCanvas::Item * item)1100 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
1101 {
1102 	return typed_event (item, event, PlayheadCursorItem);
1103 }
1104 
1105 bool
canvas_note_event(GdkEvent * event,ArdourCanvas::Item * item)1106 Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
1107 {
1108 	if (!internal_editing()) {
1109 		return false;
1110 	}
1111 
1112 	return typed_event (item, event, NoteItem);
1113 }
1114 
1115 bool
canvas_drop_zone_event(GdkEvent * event)1116 Editor::canvas_drop_zone_event (GdkEvent* event)
1117 {
1118 	GdkEventScroll scroll;
1119 	ArdourCanvas::Duple winpos;
1120 
1121 	switch (event->type) {
1122 	case GDK_BUTTON_RELEASE:
1123 		if (event->button.button == 1) {
1124 			begin_reversible_selection_op (X_("Nowhere Click"));
1125 			selection->clear_objects ();
1126 			selection->clear_tracks ();
1127 			commit_reversible_selection_op ();
1128 		}
1129 		break;
1130 
1131 	case GDK_SCROLL:
1132 		/* convert coordinates back into window space so that
1133 		   we can just call canvas_scroll_event().
1134 		*/
1135 		winpos = _track_canvas->canvas_to_window (Duple (event->scroll.x, event->scroll.y));
1136 		scroll = event->scroll;
1137 		scroll.x = winpos.x;
1138 		scroll.y = winpos.y;
1139 		return canvas_scroll_event (&scroll, true);
1140 		break;
1141 
1142 	case GDK_ENTER_NOTIFY:
1143 		return typed_event (_canvas_drop_zone, event, DropZoneItem);
1144 
1145 	case GDK_LEAVE_NOTIFY:
1146 		return typed_event (_canvas_drop_zone, event, DropZoneItem);
1147 
1148 	default:
1149 		break;
1150 	}
1151 
1152 	return true;
1153 }
1154 
1155 bool
track_canvas_drag_motion(Glib::RefPtr<Gdk::DragContext> const & context,int x,int y,guint time)1156 Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const& context, int x, int y, guint time)
1157 {
1158 	boost::shared_ptr<Region> region;
1159 	boost::shared_ptr<Region> region_copy;
1160 	RouteTimeAxisView* rtav;
1161 	GdkEvent event;
1162 	double px;
1163 	double py;
1164 
1165 	string target = _track_canvas->drag_dest_find_target (context, _track_canvas->drag_dest_get_target_list());
1166 
1167 	if (target.empty()) {
1168 		return false;
1169 	}
1170 
1171 	event.type = GDK_MOTION_NOTIFY;
1172 	event.button.x = x;
1173 	event.button.y = y;
1174 	/* assume we're dragging with button 1 */
1175 	event.motion.state = Gdk::BUTTON1_MASK;
1176 
1177 	(void) window_event_sample (&event, &px, &py);
1178 
1179 	std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py, false);
1180 	bool can_drop = false;
1181 
1182 	if (tv.first != 0) {
1183 
1184 		/* over a time axis view of some kind */
1185 
1186 		rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1187 
1188 		if (rtav != 0 && rtav->is_track ()) {
1189 			/* over a track, not a bus */
1190 			can_drop = true;
1191 		}
1192 
1193 
1194 	} else {
1195 		/* not over a time axis view, so drop is possible */
1196 		can_drop = true;
1197 	}
1198 
1199 	if (can_drop) {
1200 
1201 		if (target == X_("regions")) {
1202 			region = _regions->get_dragged_region ();
1203 		}
1204 
1205 		if (region) {
1206 
1207 			if (tv.first == 0
1208 			    && (
1209 				boost::dynamic_pointer_cast<AudioRegion> (region) != 0 ||
1210 				boost::dynamic_pointer_cast<MidiRegion> (region) != 0
1211 			       )
1212 			   )
1213 			{
1214 				/* drop to drop-zone */
1215 				context->drag_status (context->get_suggested_action(), time);
1216 				return true;
1217 			}
1218 
1219 			if ((boost::dynamic_pointer_cast<AudioRegion> (region) != 0 &&
1220 			     dynamic_cast<AudioTimeAxisView*> (tv.first) != 0) ||
1221 			    (boost::dynamic_pointer_cast<MidiRegion> (region) != 0 &&
1222 			     dynamic_cast<MidiTimeAxisView*> (tv.first) != 0)) {
1223 
1224 				/* audio to audio
1225 				   OR
1226 				   midi to midi
1227 				*/
1228 
1229 				context->drag_status (context->get_suggested_action(), time);
1230 				return true;
1231 			}
1232 		} else {
1233 			/* DND originating from outside ardour
1234 			 *
1235 			 * TODO: check if file is audio/midi, allow drops on same track-type only,
1236 			 * currently: if audio is dropped on a midi-track, it is only added to the region-list
1237 			 */
1238 			if (UIConfiguration::instance().get_only_copy_imported_files()) {
1239 				context->drag_status(Gdk::ACTION_COPY, time);
1240 			} else {
1241 				if ((context->get_actions() & (Gdk::ACTION_COPY | Gdk::ACTION_LINK | Gdk::ACTION_MOVE)) == Gdk::ACTION_COPY) {
1242 					context->drag_status(Gdk::ACTION_COPY, time);
1243 				} else {
1244 					context->drag_status(Gdk::ACTION_LINK, time);
1245 				}
1246 			}
1247 			return true;
1248 		}
1249 	}
1250 
1251 	/* no drop here */
1252 	context->drag_status (Gdk::DragAction (0), time);
1253 	return false;
1254 }
1255 
1256 void
drop_regions(const Glib::RefPtr<Gdk::DragContext> &,int x,int y,const SelectionData &,guint,guint,bool from_region_list)1257 Editor::drop_regions (const Glib::RefPtr<Gdk::DragContext>& /*context*/,
1258                       int x, int y,
1259                       const SelectionData& /*data*/,
1260                       guint /*info*/, guint /*time*/,
1261                       bool from_region_list)
1262 {
1263 	GdkEvent event;
1264 	double px;
1265 	double py;
1266 
1267 	event.type = GDK_MOTION_NOTIFY;
1268 	event.button.x = x;
1269 	event.button.y = y;
1270 	/* assume we're dragging with button 1 */
1271 	event.motion.state = Gdk::BUTTON1_MASK;
1272 	samplepos_t const pos = window_event_sample (&event, &px, &py);
1273 
1274 	boost::shared_ptr<Region> region;
1275 
1276 	if (from_region_list) {
1277 		region = _regions->get_dragged_region ();
1278 	} else {
1279 		region = _sources->get_dragged_region ();
1280 	}
1281 
1282 	if (!region) { return; }
1283 
1284 	RouteTimeAxisView* rtav = 0;
1285 	std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py, false);
1286 
1287 	if (tv.first != 0) {
1288 		rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1289 	} else {
1290 		try {
1291 			if (boost::dynamic_pointer_cast<AudioRegion> (region)) {
1292 				uint32_t output_chan = region->n_channels();
1293 				if ((Config->get_output_auto_connect() & AutoConnectMaster) && session()->master_out()) {
1294 					output_chan =  session()->master_out()->n_inputs().n_audio();
1295 				}
1296 				list<boost::shared_ptr<AudioTrack> > audio_tracks;
1297 				audio_tracks = session()->new_audio_track (region->n_channels(), output_chan, 0, 1, region->name(), PresentationInfo::max_order);
1298 				rtav = dynamic_cast<RouteTimeAxisView*> (time_axis_view_from_stripable (audio_tracks.front()));
1299 			} else if (boost::dynamic_pointer_cast<MidiRegion> (region)) {
1300 				ChanCount one_midi_port (DataType::MIDI, 1);
1301 				list<boost::shared_ptr<MidiTrack> > midi_tracks;
1302 				midi_tracks = session()->new_midi_track (one_midi_port, one_midi_port,
1303 				                                         Config->get_strict_io () || Profile->get_mixbus (),
1304 				                                         boost::shared_ptr<ARDOUR::PluginInfo>(),
1305 				                                         (ARDOUR::Plugin::PresetRecord*) 0,
1306 				                                         (ARDOUR::RouteGroup*) 0, 1, region->name(), PresentationInfo::max_order);
1307 				rtav = dynamic_cast<RouteTimeAxisView*> (time_axis_view_from_stripable (midi_tracks.front()));
1308 			} else {
1309 				return;
1310 			}
1311 		} catch (...) {
1312 			error << _("Could not create new track after region placed in the drop zone") << endmsg;
1313 			return;
1314 		}
1315 	}
1316 
1317 	if (rtav != 0 && rtav->is_track ()) {
1318 		boost::shared_ptr<Region> region_copy = RegionFactory::create (region, true);
1319 
1320 		if ((boost::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 && dynamic_cast<AudioTimeAxisView*> (rtav) != 0) ||
1321 		    (boost::dynamic_pointer_cast<MidiRegion> (region_copy) != 0 && dynamic_cast<MidiTimeAxisView*> (rtav) != 0)) {
1322 			_drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event);
1323 			_drags->end_grab (&event);
1324 		}
1325 	}
1326 }
1327 
1328 bool
key_press_handler(ArdourCanvas::Item *,GdkEvent *,ItemType)1329 Editor::key_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType)
1330 {
1331 	return false;
1332 }
1333 
1334 bool
key_release_handler(ArdourCanvas::Item * item,GdkEvent * event,ItemType type)1335 Editor::key_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType type)
1336 {
1337 
1338 	bool handled = false;
1339 
1340 	switch (type) {
1341 	case TempoMarkerItem:
1342 		switch (event->key.keyval) {
1343 		case GDK_Delete:
1344 			remove_tempo_marker (item);
1345 			handled = true;
1346 			break;
1347 		default:
1348 			break;
1349 		}
1350 		break;
1351 
1352 	case MeterMarkerItem:
1353 		switch (event->key.keyval) {
1354 		case GDK_Delete:
1355 			remove_meter_marker (item);
1356 			handled = true;
1357 			break;
1358 		default:
1359 			break;
1360 		}
1361 		break;
1362 
1363 	default:
1364 		break;
1365 	}
1366 
1367 	return handled;
1368 }
1369