convert set_property("foo", bar) to property_foo() = bar
[ardour.git] / gtk2_ardour / editor_canvas_events.cc
1 /*
2     Copyright (C) 2000 Paul Davis 
3
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.
8
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.
13
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.
17
18     $Id$
19 */
20
21 #include <cstdlib>
22 #include <cmath>
23
24 #include <ardour/diskstream.h>
25 #include <ardour/audioplaylist.h>
26
27 #include "editor.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"
40
41 #include "i18n.h"
42
43 using namespace sigc;
44 using namespace ARDOUR;
45 using namespace Gtk;
46
47 bool
48 Editor::track_canvas_event (GdkEvent *event, ArdourCanvas::Item* item)
49 {
50         gint x, y;
51
52         switch (event->type) {
53         case GDK_MOTION_NOTIFY:
54                 /* keep those motion events coming */
55                 track_canvas.get_pointer (x, y);
56                 return track_canvas_motion (event);
57
58         case GDK_BUTTON_RELEASE:
59                 switch (event->button.button) {
60                 case 4:
61                 case 5:
62                         button_release_handler (item, event, NoItem);
63                         break;
64                 }
65                 break;
66
67         default:
68                 break;
69         }
70
71         return FALSE;
72 }
73
74 bool
75 Editor::track_canvas_motion (GdkEvent *ev)
76 {
77         if (verbose_cursor_visible) {
78                 verbose_canvas_cursor->property_x() = ev->motion.x + 20;
79                 verbose_canvas_cursor->property_y() = ev->motion.y + 20;
80         }
81         return false;
82 }
83
84 bool
85 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
86 {
87         gint ret = FALSE;
88         
89         switch (event->type) {
90         case GDK_BUTTON_PRESS:
91         case GDK_2BUTTON_PRESS:
92         case GDK_3BUTTON_PRESS:
93                 ret = button_press_handler (item, event, type);
94                 break;
95         case GDK_BUTTON_RELEASE:
96                 ret = button_release_handler (item, event, type);
97                 break;
98         case GDK_MOTION_NOTIFY:
99                 ret = motion_handler (item, event, type);
100                 break;
101
102         case GDK_ENTER_NOTIFY:
103                 ret = enter_handler (item, event, type);
104                 break;
105
106         case GDK_LEAVE_NOTIFY:
107                 ret = leave_handler (item, event, type);
108                 break;
109
110         default:
111                 break;
112         }
113                         
114         return ret;
115 }
116
117 bool
118 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
119 {
120         gint ret = FALSE;
121         
122         switch (event->type) {
123         case GDK_BUTTON_PRESS:
124         case GDK_2BUTTON_PRESS:
125         case GDK_3BUTTON_PRESS:
126                 clicked_regionview = rv;
127                 clicked_control_point = 0;
128                 clicked_trackview = &rv->get_time_axis_view();
129                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
130                 ret = button_press_handler (item, event, RegionItem);
131                 break;
132
133         case GDK_BUTTON_RELEASE:
134                 ret = button_release_handler (item, event, RegionItem);
135                 break;
136
137         case GDK_MOTION_NOTIFY:
138                 ret = motion_handler (item, event, RegionItem);
139                 break;
140
141         case GDK_ENTER_NOTIFY:
142                 set_entered_regionview (rv);
143                 break;
144
145         case GDK_LEAVE_NOTIFY:
146                 set_entered_regionview (0);
147                 break;
148
149         default:
150                 break;
151         }
152
153         return ret;
154 }
155
156 bool
157 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, AudioTimeAxisView *tv)
158 {
159         bool ret = FALSE;
160         
161         switch (event->type) {
162         case GDK_BUTTON_PRESS:
163         case GDK_2BUTTON_PRESS:
164         case GDK_3BUTTON_PRESS:
165                 clicked_regionview = 0;
166                 clicked_control_point = 0;
167                 clicked_trackview = tv;
168                 clicked_audio_trackview = tv;
169                 ret = button_press_handler (item, event, StreamItem);
170                 break;
171
172         case GDK_BUTTON_RELEASE:
173                 ret = button_release_handler (item, event, StreamItem);
174                 break;
175
176         case GDK_MOTION_NOTIFY:
177                 ret = motion_handler (item, event, StreamItem);
178                 break;
179
180         case GDK_ENTER_NOTIFY:
181                 break;
182
183         default:
184                 break;
185         }
186
187         return ret;
188 }
189
190
191
192 bool
193 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
194 {
195         bool ret = false;
196         
197         switch (event->type) {
198         case GDK_BUTTON_PRESS:
199         case GDK_2BUTTON_PRESS:
200         case GDK_3BUTTON_PRESS:
201                 clicked_regionview = 0;
202                 clicked_control_point = 0;
203                 clicked_trackview = atv;
204                 clicked_audio_trackview = 0;
205                 ret = button_press_handler (item, event, AutomationTrackItem);
206                 break;
207
208         case GDK_BUTTON_RELEASE:
209                 ret = button_release_handler (item, event, AutomationTrackItem);
210                 break;
211
212         case GDK_MOTION_NOTIFY:
213                 ret = motion_handler (item, event, AutomationTrackItem);
214                 break;
215
216         case GDK_ENTER_NOTIFY:
217                 ret = enter_handler (item, event, AutomationTrackItem);
218                 break;
219
220         case GDK_LEAVE_NOTIFY:
221                 ret = leave_handler (item, event, AutomationTrackItem);
222                 break;
223
224         default:
225                 break;
226         }
227
228         return ret;
229 }
230
231 bool
232 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
233 {
234         /* we handle only button 3 press/release events */
235
236         switch (event->type) {
237         case GDK_BUTTON_PRESS:
238                 clicked_regionview = rv;
239                 clicked_control_point = 0;
240                 clicked_trackview = &rv->get_time_axis_view();
241                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
242                 if (event->button.button == 3) {
243                         return button_press_handler (item, event, FadeInItem);
244                 }
245                 break;
246
247         case GDK_BUTTON_RELEASE:
248                 if (event->button.button == 3) {
249                         return button_release_handler (item, event, FadeInItem);
250                 }
251                 break;
252
253         default:
254                 break;
255                 
256         }
257
258         /* proxy for the regionview */
259         
260         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
261 }
262
263 bool
264 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
265 {
266         bool ret = false;
267         
268         switch (event->type) {
269         case GDK_BUTTON_PRESS:
270         case GDK_2BUTTON_PRESS:
271         case GDK_3BUTTON_PRESS:
272                 clicked_regionview = rv;
273                 clicked_control_point = 0;
274                 clicked_trackview = &rv->get_time_axis_view();
275                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
276                 ret = button_press_handler (item, event, FadeInHandleItem);
277                 break;
278
279         case GDK_BUTTON_RELEASE:
280                 ret = button_release_handler (item, event, FadeInHandleItem);
281                 break;
282
283         case GDK_MOTION_NOTIFY:
284                 ret = motion_handler (item, event, FadeInHandleItem);
285                 break;
286
287         case GDK_ENTER_NOTIFY:
288                 ret = enter_handler (item, event, FadeInHandleItem);
289                 break;
290
291         case GDK_LEAVE_NOTIFY:
292                 ret = leave_handler (item, event, FadeInHandleItem);
293                 break;
294
295         default:
296                 break;
297         }
298
299         return ret;
300 }
301
302 bool
303 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
304 {
305         /* we handle only button 3 press/release events */
306
307         switch (event->type) {
308         case GDK_BUTTON_PRESS:
309                 clicked_regionview = rv;
310                 clicked_control_point = 0;
311                 clicked_trackview = &rv->get_time_axis_view();
312                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
313                 if (event->button.button == 3) {
314                         return button_press_handler (item, event, FadeOutItem);
315                 }
316                 break;
317
318         case GDK_BUTTON_RELEASE:
319                 if (event->button.button == 3) {
320                         return button_release_handler (item, event, FadeOutItem);
321                 }
322                 break;
323
324         default:
325                 break;
326                 
327         }
328
329         /* proxy for the regionview */
330         
331         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
332 }
333
334 bool
335 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
336 {
337         bool ret = false;
338         
339         switch (event->type) {
340         case GDK_BUTTON_PRESS:
341         case GDK_2BUTTON_PRESS:
342         case GDK_3BUTTON_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                 ret = button_press_handler (item, event, FadeOutHandleItem);
348                 break;
349
350         case GDK_BUTTON_RELEASE:
351                 ret = button_release_handler (item, event, FadeOutHandleItem);
352                 break;
353
354         case GDK_MOTION_NOTIFY:
355                 ret = motion_handler (item, event, FadeOutHandleItem);
356                 break;
357
358         case GDK_ENTER_NOTIFY:
359                 ret = enter_handler (item, event, FadeOutHandleItem);
360                 break;
361
362         case GDK_LEAVE_NOTIFY:
363                 ret = leave_handler (item, event, FadeOutHandleItem);
364                 break;
365
366         default:
367                 break;
368         }
369
370         return ret;
371 }
372
373 struct DescendingRegionLayerSorter {
374     bool operator()(Region* a, Region* b) {
375             return a->layer() > b->layer();
376     }
377 };
378
379 bool
380 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
381 {
382         /* we handle only button 3 press/release events */
383
384         switch (event->type) {
385         case GDK_BUTTON_PRESS:
386                 clicked_crossfadeview = xfv;
387                 clicked_trackview = &clicked_crossfadeview->get_time_axis_view();
388                 if (event->button.button == 3) {
389                         return button_press_handler (item, event, CrossfadeViewItem);
390                 } 
391                 break;
392
393         case GDK_BUTTON_RELEASE:
394                 if (event->button.button == 3) {
395                         bool ret = button_release_handler (item, event, CrossfadeViewItem);
396                         return ret;
397                 }
398                 break;
399
400         default:
401                 break;
402                 
403         }
404
405         
406         /* proxy for the upper most regionview */
407
408         /* XXX really need to check if we are in the name highlight,
409            and proxy to that when required.
410         */
411         
412         TimeAxisView& tv (xfv->get_time_axis_view());
413         AudioTimeAxisView* atv;
414
415         if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
416
417                 if (atv->is_audio_track()) {
418
419                         AudioPlaylist* pl = atv->get_diskstream()->playlist();
420                         Playlist::RegionList* rl = pl->regions_at (event_frame (event));
421
422                         if (!rl->empty()) {
423                                 DescendingRegionLayerSorter cmp;
424                                 rl->sort (cmp);
425
426                                 AudioRegionView* arv = atv->view->find_view (*(dynamic_cast<AudioRegion*> (rl->front())));
427
428                                 /* proxy */
429                                 
430                                 delete rl;
431
432                                 return canvas_region_view_event (event, arv->get_canvas_group(), arv);
433                         }
434                 }
435         }
436
437         return TRUE;
438 }
439
440 bool
441 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
442 {
443         ItemType type;
444
445         switch (event->type) {
446         case GDK_BUTTON_PRESS:
447         case GDK_2BUTTON_PRESS:
448         case GDK_3BUTTON_PRESS:
449                 clicked_control_point = cp;
450                 clicked_trackview = &cp->line.trackview;
451                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
452                 clicked_regionview = 0;
453                 break;
454
455         default:
456                 break;
457         }
458
459         if (dynamic_cast<AudioRegionGainLine*> (&cp->line) != 0) {
460                 type = GainControlPointItem;
461         } else if (dynamic_cast<AutomationGainLine*> (&cp->line) != 0) {
462                 type = GainAutomationControlPointItem;
463         } else if (dynamic_cast<AutomationPanLine*> (&cp->line) != 0) {
464                 type = PanAutomationControlPointItem;
465         } else if (dynamic_cast<RedirectAutomationLine*> (&cp->line) != 0) {
466                 type = RedirectAutomationControlPointItem;
467         } else {
468                 return false;
469         }
470
471         return typed_event (item, event, type);
472 }
473
474 bool
475 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
476 {
477         ItemType type;
478
479         if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
480                 type = GainLineItem;
481         } else if (dynamic_cast<AutomationGainLine*> (al) != 0) {
482                 type = GainAutomationLineItem;
483         } else if (dynamic_cast<AutomationPanLine*> (al) != 0) {
484                 type = PanAutomationLineItem;
485         } else if (dynamic_cast<RedirectAutomationLine*> (al) != 0) {
486                 type = RedirectAutomationLineItem;
487         } else {
488                 return false;
489         }
490
491         return typed_event (item, event, type);
492 }
493
494 bool
495 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
496 {
497         bool ret = false;
498         
499         switch (event->type) {
500         case GDK_BUTTON_PRESS:
501         case GDK_2BUTTON_PRESS:
502         case GDK_3BUTTON_PRESS:
503                 clicked_selection = rect->id;
504                 ret = button_press_handler (item, event, SelectionItem);
505                 break;
506         case GDK_BUTTON_RELEASE:
507                 ret = button_release_handler (item, event, SelectionItem);
508                 break;
509         case GDK_MOTION_NOTIFY:
510                 ret = motion_handler (item, event, SelectionItem);
511                 break;
512                 /* Don't need these at the moment. */
513         case GDK_ENTER_NOTIFY:
514                 ret = enter_handler (item, event, SelectionItem);
515                 break;
516
517         case GDK_LEAVE_NOTIFY:
518                 ret = leave_handler (item, event, SelectionItem);
519                 break;
520
521         default:
522                 break;
523         }
524                         
525         return ret;
526 }
527
528 bool
529 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
530 {
531         bool ret = false;
532
533         switch (event->type) {
534         case GDK_BUTTON_PRESS:
535         case GDK_2BUTTON_PRESS:
536         case GDK_3BUTTON_PRESS:
537                 clicked_selection = rect->id;
538                 ret = button_press_handler (item, event, StartSelectionTrimItem);
539                 break;
540         case GDK_BUTTON_RELEASE:
541                 ret = button_release_handler (item, event, StartSelectionTrimItem);
542                 break;
543         case GDK_MOTION_NOTIFY:
544                 ret = motion_handler (item, event, StartSelectionTrimItem);
545                 break;
546         case GDK_ENTER_NOTIFY:
547                 ret = enter_handler (item, event, StartSelectionTrimItem);
548                 break;
549
550         case GDK_LEAVE_NOTIFY:
551                 ret = leave_handler (item, event, StartSelectionTrimItem);
552                 break;
553
554         default:
555                 break;
556         }
557                         
558         return ret;
559 }
560
561 bool
562 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
563 {
564         bool ret = false;
565
566         switch (event->type) {
567         case GDK_BUTTON_PRESS:
568         case GDK_2BUTTON_PRESS:
569         case GDK_3BUTTON_PRESS:
570                 clicked_selection = rect->id;
571                 ret = button_press_handler (item, event, EndSelectionTrimItem);
572                 break;
573         case GDK_BUTTON_RELEASE:
574                 ret = button_release_handler (item, event, EndSelectionTrimItem);
575                 break;
576         case GDK_MOTION_NOTIFY:
577                 ret = motion_handler (item, event, EndSelectionTrimItem);
578                 break;
579         case GDK_ENTER_NOTIFY:
580                 ret = enter_handler (item, event, EndSelectionTrimItem);
581                 break;
582
583         case GDK_LEAVE_NOTIFY:
584                 ret = leave_handler (item, event, EndSelectionTrimItem);
585                 break;
586
587         default:
588                 break;
589         }
590                         
591         return ret;
592 }
593
594
595 bool
596 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, AudioRegionView* rv)
597 {
598         bool ret = false;
599         
600         switch (event->type) {
601         case GDK_BUTTON_PRESS:
602         case GDK_2BUTTON_PRESS:
603         case GDK_3BUTTON_PRESS:
604                 clicked_regionview = rv;
605                 clicked_control_point = 0;
606                 clicked_trackview = &clicked_regionview->get_time_axis_view();
607                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
608                 ret = button_press_handler (item, event, AudioRegionViewNameHighlight);
609                 break;
610         case GDK_BUTTON_RELEASE:
611                 ret = button_release_handler (item, event, AudioRegionViewNameHighlight);
612                 break;
613         case GDK_MOTION_NOTIFY:
614                 ret = motion_handler (item, event, AudioRegionViewNameHighlight);
615                 break;
616         case GDK_ENTER_NOTIFY:
617                 ret = enter_handler (item, event, AudioRegionViewNameHighlight);
618                 break;
619
620         case GDK_LEAVE_NOTIFY:
621                 ret = leave_handler (item, event, AudioRegionViewNameHighlight);
622                 break;
623
624         default:
625                 break;
626         }
627
628         return ret;
629 }
630
631 bool
632 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView* rv)
633 {
634         bool ret = false;
635
636         switch (event->type) {
637         case GDK_BUTTON_PRESS:
638         case GDK_2BUTTON_PRESS:
639         case GDK_3BUTTON_PRESS:
640                 clicked_regionview = rv;
641                 clicked_control_point = 0;
642                 clicked_trackview = &clicked_regionview->get_time_axis_view();
643                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
644                 ret = button_press_handler (item, event, AudioRegionViewName);
645                 break;
646         case GDK_BUTTON_RELEASE:
647                 ret = button_release_handler (item, event, AudioRegionViewName);
648                 break;
649         case GDK_MOTION_NOTIFY:
650                 ret = motion_handler (item, event, AudioRegionViewName);
651                 break;
652         case GDK_ENTER_NOTIFY:
653                 ret = enter_handler (item, event, AudioRegionViewName);
654                 break;
655
656         case GDK_LEAVE_NOTIFY:
657                 ret = leave_handler (item, event, AudioRegionViewName);
658                 break;
659
660         default:
661                 break;
662         }
663
664         return ret;
665 }
666
667 bool
668 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* marker)
669 {
670         return typed_event (item, event, MarkerItem);
671 }
672
673 bool
674 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
675 {
676         return typed_event (item, event, MarkerBarItem);
677 }
678
679 bool
680 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
681 {
682         return typed_event (item, event, RangeMarkerBarItem);
683 }
684
685 bool
686 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
687 {
688         return typed_event (item, event, TransportMarkerBarItem);
689 }
690
691 bool
692 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
693 {
694         return typed_event (item, event, TempoMarkerItem);
695 }
696
697 bool
698 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* marker)
699 {
700         return typed_event (item, event, MeterMarkerItem);
701 }
702
703 bool
704 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
705 {
706         return typed_event (item, event, TempoBarItem);
707 }
708
709 bool
710 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
711 {
712         return typed_event (item, event, MeterBarItem);
713 }
714
715 bool
716 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
717 {
718         return typed_event (item, event, PlayheadCursorItem);
719 }
720
721 bool
722 Editor::canvas_edit_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
723 {
724         return typed_event (item, event, EditCursorItem);
725 }
726
727 bool
728 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
729 {
730         return typed_event (item, event, NoItem);
731 }
732