r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / cinelerra / trackcanvas.C
blob8172a8e21780bacf41cb09b229465881ba56ae25
1 #include "asset.h"
2 #include "autoconf.h"
3 #include "automation.h"
4 #include "bcsignals.h"
5 #include "bezierauto.h"
6 #include "bezierautos.h"
7 #include "clip.h"
8 #include "colors.h"
9 #include "cplayback.h"
10 #include "cursors.h"
11 #include "cwindow.h"
12 #include "cwindowgui.h"
13 #include "edithandles.h"
14 #include "editpopup.h"
15 #include "edits.h"
16 #include "edl.h"
17 #include "edlsession.h"
18 #include "floatauto.h"
19 #include "floatautos.h"
20 #include "intauto.h"
21 #include "keyframe.h"
22 #include "keyframepopup.h"
23 #include "keyframes.h"
24 #include "keys.h"
25 #include "localsession.h"
26 #include "mainclock.h"
27 #include "maincursor.h"
28 #include "mainundo.h"
29 #include "maskautos.h"
30 #include "mbuttons.h"
31 #include "mtimebar.h"
32 #include "mwindow.h"
33 #include "mwindowgui.h"
34 #include "patchbay.h"
35 #include "tracking.h"
36 #include "panautos.h"
37 #include "playbackengine.h"
38 #include "playtransport.h"
39 #include "plugin.h"
40 #include "pluginpopup.h"
41 #include "pluginset.h"
42 #include "pluginserver.h"
43 #include "preferences.h"
44 #include "resourcepixmap.h"
45 #include "mainsession.h"
46 #include "transitionhandles.h"
47 #include "transitionpopup.h"
48 #include "transportque.h"
49 #include "zoombar.h"
50 #include "theme.h"
51 #include "intautos.h"
52 #include "trackcanvas.h"
53 #include "tracks.h"
54 #include "transition.h"
55 #include "vframe.h"
56 #include "apatchgui.inc"
57 #include "vpatchgui.inc"
59 #include <string.h>
61 TrackCanvas::TrackCanvas(MWindow *mwindow, MWindowGUI *gui)
62  : BC_SubWindow(mwindow->theme->mcanvas_x,
63         mwindow->theme->mcanvas_y,
64         gui->view_w,
65         gui->view_h)
67         this->mwindow = mwindow;
68         this->gui = gui;
69         current_end = 0;
70         selection_midpoint1 = selection_midpoint2 = 0;
71         selection_type = 0;
72         region_selected = 0;
73         handle_selected = 0;
74         auto_selected = 0;
75         translate_selected = 0;
76         which_handle = 0;
77         handle_pixel = 0;
78         drag_scroll = 0;
79         drag_popup = 0;
80         active = 0;
81         temp_picon = 0;
84 TrackCanvas::~TrackCanvas()
86         for(int i = 0; i < resource_pixmaps.total; i++)
87                 delete resource_pixmaps.values[i];
88 //      delete transition_handles;
89         delete edit_handles;
90         delete keyframe_pixmap;
91         delete camerakeyframe_pixmap;
92         delete modekeyframe_pixmap;
93         delete pankeyframe_pixmap;
94         delete projectorkeyframe_pixmap;
95         delete maskkeyframe_pixmap;
96         delete background_pixmap;
97         if(temp_picon) delete temp_picon;
100 int TrackCanvas::create_objects()
102         background_pixmap = new BC_Pixmap(this, get_w(), get_h());
103 //      transition_handles = new TransitionHandles(mwindow, this);
104         edit_handles = new EditHandles(mwindow, this);
105         keyframe_pixmap = new BC_Pixmap(this, mwindow->theme->keyframe_data, PIXMAP_ALPHA);
106         camerakeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->camerakeyframe_data, PIXMAP_ALPHA);
107         modekeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->modekeyframe_data, PIXMAP_ALPHA);
108         pankeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->pankeyframe_data, PIXMAP_ALPHA);
109         projectorkeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->projectorkeyframe_data, PIXMAP_ALPHA);
110         maskkeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->maskkeyframe_data, PIXMAP_ALPHA);
111         draw();
112         update_cursor();
113         flash();
114         return 0;
117 void TrackCanvas::resize_event()
119 //printf("TrackCanvas::resize_event 1\n");
120         draw(0, 0);
121         flash();
122 //printf("TrackCanvas::resize_event 2\n");
125 int TrackCanvas::keypress_event()
127         int result = 0;
129         switch(get_keypress())
130         {
131                 case LEFT:
132                         if(!ctrl_down()) 
133                         { 
134                                 mwindow->move_left(); 
135                                 result = 1; 
136                         }
137                         break;
138                 case RIGHT:
139                         if(!ctrl_down()) 
140                         { 
141                                 mwindow->move_right(); 
142                                 result = 1; 
143                         }
144                         break;
146                 case UP:
147                         if(!ctrl_down())
148                         {
149                                 mwindow->expand_sample();
150                                 result = 1;
151                         }
152                         else
153                         {
154                                 mwindow->expand_y();
155                                 result = 1;
156                         }
157                         break;
159                 case DOWN:
160                         if(!ctrl_down())
161                         {
162                                 mwindow->zoom_in_sample();
163                                 result = 1;
164                         }
165                         else
166                         {
167                                 mwindow->zoom_in_y();
168                                 result = 1;
169                         }
170                         break;
172                 case PGUP:
173                         if(!ctrl_down())
174                         {
175                                 mwindow->move_up();
176                                 result = 1;
177                         }
178                         else
179                         {
180                                 mwindow->expand_t();
181                                 result = 1;
182                         }
183                         break;
185                 case PGDN:
186                         if(!ctrl_down())
187                         {
188                                 mwindow->move_down();
189                                 result = 1;
190                         }
191                         else
192                         {
193                                 mwindow->zoom_in_t();
194                                 result = 1;
195                         }
196                         break;
197                 case TAB:
198                 case LEFTTAB:
199                         int cursor_x = get_relative_cursor_x();
200                         int cursor_y = get_relative_cursor_y();
201                         if(get_keypress() == TAB)
202                         {
203                                 // Switch the record button
204                                 for(Track *track = mwindow->edl->tracks->first; track; track = track->next)
205                                 {
206                                         int64_t track_x, track_y, track_w, track_h;
207                                         track_dimensions(track, track_x, track_y, track_w, track_h);
208         
209                                         if(cursor_y >= track_y && 
210                                                 cursor_y < track_y + track_h)
211                                         {
212                                                 if (track->record)
213                                                         track->record = 0;
214                                                 else
215                                                         track->record = 1;
216                                                 result = 1; 
217                                                 break;
218                                         }
219                                 }
220                         } else 
221                         {
222                                 Track *this_track;
223                                 for(Track *track = mwindow->edl->tracks->first; track; track = track->next)
224                                 {
225                                         int64_t track_x, track_y, track_w, track_h;
226                                         track_dimensions(track, track_x, track_y, track_w, track_h);
227         
228                                         if(cursor_y >= track_y && 
229                                                 cursor_y < track_y + track_h)
230                                         {
231                                                 // This is our track
232                                                 this_track = track;
233                                                 break;
234                                         }
235                                 }
237                                 int total_selected = mwindow->edl->tracks->total_of(Tracks::RECORD);
239 // nothing previously selected
240                                 if(total_selected == 0)
241                                 {
242                                         mwindow->edl->tracks->select_all(Tracks::RECORD,
243                                                 1);
244                                 }
245                                 else
246                                 if(total_selected == 1)
247                                 {
248 // this patch was previously the only one on
249                                         if(this_track && this_track->record)
250                                         {
251                                                 mwindow->edl->tracks->select_all(Tracks::RECORD,
252                                                         1);
253                                         }
254 // another patch was previously the only one on
255                                         else
256                                         {
257                                                 mwindow->edl->tracks->select_all(Tracks::RECORD,
258                                                         0);
259                                                 if (this_track) 
260                                                         this_track->record = 1;
261                                                 
262                                         }
263                                 }
264                                 else
265                                 if(total_selected > 1)
266                                 {
267                                         mwindow->edl->tracks->select_all(Tracks::RECORD,
268                                                 0);
269                                         if (this_track) 
270                                                 this_track->record = 1;
271                                 }
273                         }
275                         gui->update (0,
276                                         1,
277                                         0,
278                                         0,
279                                         1,
280                                         0,
281                                         1);
282                         mwindow->cwindow->update(0, 1, 1);
284                         result = 1;
285                         break;
286         }
288 // since things under cursor have changed...
289         if (result) 
290                 cursor_motion_event(); 
292         return result;
295 int TrackCanvas::drag_motion()
298         int cursor_x = get_relative_cursor_x();
299         int cursor_y = get_relative_cursor_y();
300         Track *over_track = 0;
301         Edit *over_edit = 0;
302         PluginSet *over_pluginset = 0;
303         Plugin *over_plugin = 0;
304         int redraw = 0;
307         if(drag_popup)
308         {
309                 drag_popup->cursor_motion_event();
310         }
315         if(get_cursor_over_window() &&
316                 cursor_x >= 0 && 
317                 cursor_y >= 0 && 
318                 cursor_x < get_w() && 
319                 cursor_y < get_h())
320         {
321 // Find the edit and track the cursor is over
322                 for(Track *track = mwindow->edl->tracks->first; track; track = track->next)
323                 {
324                         int64_t track_x, track_y, track_w, track_h;
325                         track_dimensions(track, track_x, track_y, track_w, track_h);
327                         if(cursor_y >= track_y && 
328                                 cursor_y < track_y + track_h)
329                         {
330                                 over_track = track;
331                                 for(Edit *edit = track->edits->first; edit; edit = edit->next)
332                                 {
333                                         int64_t edit_x, edit_y, edit_w, edit_h;
334                                         edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
336                                         if(cursor_x >= edit_x && 
337                                                 cursor_y >= edit_y && 
338                                                 cursor_x < edit_x + edit_w && 
339                                                 cursor_y < edit_y + edit_h)
340                                         {
341                                                 over_edit = edit;
342                                                 break;
343                                         }
344                                 }
346                                 for(int i = 0; i < track->plugin_set.total; i++)
347                                 {
348                                         PluginSet *pluginset = track->plugin_set.values[i];
349                                         
352                                         for(Plugin *plugin = (Plugin*)pluginset->first;
353                                                 plugin;
354                                                 plugin = (Plugin*)plugin->next)
355                                         {
356                                                 int64_t plugin_x, plugin_y, plugin_w, plugin_h;
357                                                 plugin_dimensions(plugin, plugin_x, plugin_y, plugin_w, plugin_h);
358                                                 
359                                                 if(cursor_y >= plugin_y &&
360                                                         cursor_y < plugin_y + plugin_h)
361                                                 {
362                                                         over_pluginset = plugin->plugin_set;
363                                                 
364                                                         if(cursor_x >= plugin_x &&
365                                                                 cursor_x < plugin_x + plugin_w)
366                                                         {
367                                                                 over_plugin = plugin;
368                                                                 break;
369                                                         }
370                                                 }
371                                         }
372                                 }
373                                 break;
374                         }
375                 }
376         }
378         if(mwindow->session->track_highlighted != over_track) 
379         {
380                 mwindow->session->track_highlighted = over_track;
381                 redraw = 1;
382         }
384         if(mwindow->session->edit_highlighted != over_edit)
385         {
386                 mwindow->session->edit_highlighted = over_edit;
387                 redraw = 1;
388         }
390         if(mwindow->session->pluginset_highlighted != over_pluginset)
391         {
392                 mwindow->session->pluginset_highlighted = over_pluginset;
393                 redraw = 1;
394         }
396         if(mwindow->session->plugin_highlighted != over_plugin)
397         {
398                 mwindow->session->plugin_highlighted = over_plugin;
399                 redraw = 1;
400         }
402 //printf("TrackCanvas::drag_motion 2 %p\n", mwindow->session->track_highlighted);
403         if(redraw)
404         {
405                 lock_window("TrackCanvas::drag_motion");
406                 draw_overlays();
407                 flash();
408                 unlock_window();
409         }
411         return 0;
414 int TrackCanvas::drag_start_event()
416         int result = 0;
417         int redraw = 0;
418         int rerender = 0;
419         int new_cursor, update_cursor;
421         if(mwindow->session->current_operation != NO_OPERATION) return 0;
423         if(is_event_win())
424         {
425                 if(test_plugins(get_drag_x(), 
426                         get_drag_y(), 
427                         1,
428                         0,
429                         redraw,
430                         rerender))
431                 {
432                         result = 1;
433                 }
434                 else
435                 if(test_edits(get_drag_x(),
436                         get_drag_y(),
437                         0,
438                         1,
439                         redraw,
440                         rerender,
441                         new_cursor,
442                         update_cursor))
443                 {
444                         result = 1;
445                 }
446         }
448         return result;
451 int TrackCanvas::drag_motion_event()
453         return drag_motion();
456 int TrackCanvas::cursor_leave_event()
458 // because drag motion calls get_cursor_over_window we can be sure that
459 // all highlights get deleted now
460         drag_motion();
461         return 0;
465 int TrackCanvas::drag_stop_event()
467         int result = drag_stop();
469         if(drag_popup)
470         {
471                 delete drag_popup;
472                 drag_popup = 0;
473         }
474         return result;
478 int TrackCanvas::drag_stop()
480 // In most cases the editing routine redraws and not the drag_stop
481         int result = 0, redraw = 0;
483         switch(mwindow->session->current_operation)
484         {
485                 case DRAG_VTRANSITION:
486                 case DRAG_ATRANSITION:
487                         if(mwindow->session->edit_highlighted)
488                         {
489                                 if((mwindow->session->current_operation == DRAG_ATRANSITION &&
490                                         mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
491                                         (mwindow->session->current_operation == DRAG_VTRANSITION &&
492                                         mwindow->session->track_highlighted->data_type == TRACK_VIDEO))
493                                 {
494                                         mwindow->session->current_operation = NO_OPERATION;
495                                         mwindow->paste_transition();
496                                         result = 1;
497                                 }
498                         }
499                         redraw = 1;
500                         break;
505 // Behavior for dragged plugins is limited by the fact that a shared plugin
506 // can only refer to a standalone plugin that exists in the same position in
507 // time.  Dragging a plugin from one point in time to another can't produce
508 // a shared plugin to the original plugin.  In this case we relocate the
509 // plugin instead of sharing it.
510                 case DRAG_AEFFECT_COPY:
511                 case DRAG_VEFFECT_COPY:
512                         if(mwindow->session->track_highlighted &&
513                                 ((mwindow->session->current_operation == DRAG_AEFFECT_COPY &&
514                                         mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
515                                         (mwindow->session->current_operation == DRAG_VEFFECT_COPY &&
516                                         mwindow->session->track_highlighted->data_type == TRACK_VIDEO)))
517                         {
518                                 mwindow->session->current_operation = NO_OPERATION;
520 // Insert shared plugin in source
521                                 if(mwindow->session->track_highlighted != mwindow->session->drag_plugin->track &&
522                                         !mwindow->session->plugin_highlighted &&
523                                         !mwindow->session->pluginset_highlighted)
524                                 {
525 // Move plugin if different startproject
526                                         mwindow->move_effect(mwindow->session->drag_plugin,
527                                                 0,
528                                                 mwindow->session->track_highlighted,
529                                                 0);
530                                         result = 1;
531                                 }
532                                 else
533 // Move source to different location
534                                 if(mwindow->session->pluginset_highlighted)
535                                 {
536 //printf("TrackCanvas::drag_stop 6\n");
537                                         if(mwindow->session->plugin_highlighted)
538                                         {
539                                                 mwindow->move_effect(mwindow->session->drag_plugin,
540                                                         mwindow->session->plugin_highlighted->plugin_set,
541                                                         0,
542                                                         mwindow->session->plugin_highlighted->startproject);
543                                         }
544                                         else
545                                         {
546                                                 mwindow->move_effect(mwindow->session->drag_plugin,
547                                                         mwindow->session->pluginset_highlighted,
548                                                         0,
549                                                         mwindow->session->pluginset_highlighted->length());
550                                         }
551                                         result = 1;
552                                 }
553                                 else
554 // Move to a new plugin set between two edits
555                                 if(mwindow->session->edit_highlighted)
556                                 {
557                                         mwindow->move_effect(mwindow->session->drag_plugin,
558                                                 0,
559                                                 mwindow->session->track_highlighted,
560                                                 mwindow->session->edit_highlighted->startproject);
561                                         result = 1;
562                                 }
563                                 else
564 // Move to a new plugin set
565                                 if(mwindow->session->track_highlighted)
566                                 {
567                                         mwindow->move_effect(mwindow->session->drag_plugin,
568                                                 0,
569                                                 mwindow->session->track_highlighted,
570                                                 0);
571                                         result = 1;
572                                 }
573                         }
574                         break;
576                 case DRAG_AEFFECT:
577                 case DRAG_VEFFECT:
578                         if(mwindow->session->track_highlighted && 
579                                 ((mwindow->session->current_operation == DRAG_AEFFECT &&
580                                 mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
581                                 (mwindow->session->current_operation == DRAG_VEFFECT &&
582                                 mwindow->session->track_highlighted->data_type == TRACK_VIDEO)))
583                         {
584 // Drop all the effects
585                                 PluginSet *plugin_set = mwindow->session->pluginset_highlighted;
586                                 Track *track = mwindow->session->track_highlighted;
587                                 double start = 0;
588                                 double length = track->get_length();
590                                 if(mwindow->session->plugin_highlighted)
591                                 {
592                                         start = track->from_units(mwindow->session->plugin_highlighted->startproject);
593                                         length = track->from_units(mwindow->session->plugin_highlighted->length);
594                                         if(length <= 0) length = track->get_length();
595                                 }
596                                 else
597                                 if(mwindow->session->pluginset_highlighted)
598                                 {
599                                         start = track->from_units(plugin_set->length());
600                                         length = track->get_length() - start;
601                                         if(length <= 0) length = track->get_length();
602                                 }
603                                 else
604                                 if(mwindow->edl->local_session->get_selectionend() > 
605                                         mwindow->edl->local_session->get_selectionstart())
606                                 {
607                                         start = mwindow->edl->local_session->get_selectionstart();
608                                         length = mwindow->edl->local_session->get_selectionend() - 
609                                                 mwindow->edl->local_session->get_selectionstart();
610                                 }
611 // Move to a point between two edits
612 //                              else
613 //                              if(mwindow->session->edit_highlighted)
614 //                              {
615 //                                      start = mwindow->session->track_highlighted->from_units(
616 //                                              mwindow->session->edit_highlighted->startproject);
617 //                                      length = mwindow->session->track_highlighted->from_units(
618 //                                              mwindow->session->edit_highlighted->length);
619 //                              }
621                                 mwindow->insert_effects_canvas(start, length);
622                                 redraw = 1;
623                         }
624                         if (mwindow->session->track_highlighted)
625                                 result = 1;  // we have to cleanup
626                         break;
628                 case DRAG_ASSET:
629                         if(mwindow->session->track_highlighted)
630                         {
631                                 int64_t position = mwindow->session->edit_highlighted ?
632                                         mwindow->session->edit_highlighted->startproject :
633                                         mwindow->session->track_highlighted->edits->length();
634                                 double position_f = mwindow->session->track_highlighted->from_units(position);
635                                 Track *track = mwindow->session->track_highlighted;
636                                 mwindow->paste_assets(position_f, track);
637                                 result = 1;    // need to be one no matter what, since we have track highlited so we have to cleanup....
638                         }
639                         break;
641                 case DRAG_EDIT:
642                         mwindow->session->current_operation = NO_OPERATION;
643                         if(mwindow->session->track_highlighted)
644                         {
645                                 if(mwindow->session->track_highlighted->data_type == mwindow->session->drag_edit->track->data_type)
646                                 {
647                                         int64_t position = mwindow->session->edit_highlighted ?
648                                                 mwindow->session->edit_highlighted->startproject :
649                                                 mwindow->session->track_highlighted->edits->length();
650                                         double position_f = mwindow->session->track_highlighted->from_units(position);
651                                         Track *track = mwindow->session->track_highlighted;
652                                         mwindow->move_edits(mwindow->session->drag_edits,
653                                                 track,
654                                                 position_f);
655                                 }
657                                 result = 1;
658                         }
659                         break;
660         }
662 // since we don't have subwindows we have to terminate any drag operation
663         if(result)
664         {
665                 if (mwindow->session->track_highlighted
666                         || mwindow->session->edit_highlighted
667                         || mwindow->session->plugin_highlighted
668                         || mwindow->session->pluginset_highlighted) 
669                         redraw = 1;
670                 mwindow->session->track_highlighted = 0;
671                 mwindow->session->edit_highlighted = 0;
672                 mwindow->session->plugin_highlighted = 0;
673                 mwindow->session->pluginset_highlighted = 0;
674                 mwindow->session->current_operation = NO_OPERATION;
675         }
678 //printf("TrackCanvas::drag_stop %d %d\n", redraw, mwindow->session->current_operation);
679         if(redraw)
680         {
681                 mwindow->edl->tracks->update_y_pixels(mwindow->theme);
682                 gui->get_scrollbars();
683                 draw();
684                 gui->patchbay->update();
685                 gui->cursor->update();
686                 flash();
687                 flush();
688         }
690         return result;
694 void TrackCanvas::draw(int force, int hide_cursor)
696 // Swap pixmap layers
697 TRACE("TrackCanvas::draw 1")
698         if(get_w() != background_pixmap->get_w() ||
699                 get_h() != background_pixmap->get_h())
700         {
701                 delete background_pixmap;
702                 background_pixmap = new BC_Pixmap(this, get_w(), get_h());
703         }
705 TRACE("TrackCanvas::draw 10")
706 // Cursor disappears after resize when this is called.
707 // Cursor doesn't redraw after editing when this isn't called.
708         if(gui->cursor && hide_cursor) gui->cursor->hide();
709 TRACE("TrackCanvas::draw 20")
710         draw_top_background(get_parent(), 0, 0, get_w(), get_h(), background_pixmap);
711 TRACE("TrackCanvas::draw 30")
712         draw_resources(force);
713 TRACE("TrackCanvas::draw 40")
714         draw_overlays();
715 UNTRACE
718 void TrackCanvas::update_cursor()
720         switch(mwindow->edl->session->editing_mode)
721         {
722                 case EDITING_ARROW: set_cursor(ARROW_CURSOR); break;
723                 case EDITING_IBEAM: set_cursor(IBEAM_CURSOR); break;
724         }
728 void TrackCanvas::draw_indexes(Asset *asset)
730 // Don't redraw raw samples
731         if(asset->index_zoom > mwindow->edl->local_session->zoom_sample)
732                 return;
734         draw_resources(0, 1, asset);
736         draw_overlays();
737         draw_automation();
738         flash();
739         flush();
742 void TrackCanvas::draw_resources(int force, 
743         int indexes_only, 
744         Asset *index_asset)
746 // Age resource pixmaps for deletion
747         if(!indexes_only)
748                 for(int i = 0; i < resource_pixmaps.total; i++)
749                         resource_pixmaps.values[i]->visible--;
751         if(force)
752                 resource_pixmaps.remove_all_objects();
754 //printf("TrackCanvas::draw_resources 1 %d %d\n", force, indexes_only);
756 // Search every edit
757         for(Track *current = mwindow->edl->tracks->first;
758                 current;
759                 current = NEXT)
760         {
761 //printf("TrackCanvas::draw_resources 2\n");
762                 for(Edit *edit = current->edits->first; edit; edit = edit->next)
763                 {
764 //printf("TrackCanvas::draw_resources 3\n");
765                         if(!edit->asset) continue;
766 //printf("TrackCanvas::draw_resources 4\n");
767                         if(indexes_only)
768                         {
769                                 if(edit->track->data_type != TRACK_AUDIO) continue;
770                                 if(!edit->asset->test_path(index_asset->path)) continue;
771                         }
773                         int64_t edit_x, edit_y, edit_w, edit_h;
774                         edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
775 //printf("TrackCanvas::draw_resources 10\n");
777 // Edit is visible
778                         if(MWindowGUI::visible(edit_x, edit_x + edit_w, 0, get_w()) &&
779                                 MWindowGUI::visible(edit_y, edit_y + edit_h, 0, get_h()))
780                         {
781                                 int64_t pixmap_x, pixmap_w, pixmap_h;
783 //printf("TrackCanvas::draw_resources 20\n");
784 // Search for existing pixmap containing edit
785                                 for(int i = 0; i < resource_pixmaps.total; i++)
786                                 {
787                                         ResourcePixmap* pixmap = resource_pixmaps.values[i];
788 //printf("TrackCanvas::draw_resources 30\n");
789 // Same pointer can be different edit if editing took place
790                                         if(pixmap->edit_id == edit->id)
791                                         {
792 //printf("TrackCanvas::draw_resources 40\n");
793                                                 pixmap->visible = 1;
794                                                 break;
795                                         }
796 //printf("TrackCanvas::draw_resources 50\n");
797                                 }
799 // Get new size, offset of pixmap needed
800                                 get_pixmap_size(edit, 
801                                         edit_x, 
802                                         edit_w, 
803                                         pixmap_x, 
804                                         pixmap_w, 
805                                         pixmap_h);
806 //printf("TrackCanvas::draw_resources 60\n");
808 // Draw new data
809                                 if(pixmap_w && pixmap_h)
810                                 {
811 // Create pixmap if it doesn't exist
812                                         ResourcePixmap* pixmap = create_pixmap(edit, 
813                                                 edit_x, 
814                                                 pixmap_x, 
815                                                 pixmap_w, 
816                                                 pixmap_h);
817 //printf("TrackCanvas::draw_resources 70\n");
818 // Resize it if it's bigger
819                                         if(pixmap_w > pixmap->pixmap_w ||
820                                                 pixmap_h > pixmap->pixmap_h)
821                                                 pixmap->resize(pixmap_w, pixmap_h);
822 //printf("TrackCanvas::draw_resources 80\n");
823                                         pixmap->draw_data(edit,
824                                                 edit_x, 
825                                                 edit_w, 
826                                                 pixmap_x, 
827                                                 pixmap_w, 
828                                                 pixmap_h, 
829                                                 force,
830                                                 indexes_only);
831 //printf("TrackCanvas::draw_resources 90\n");
832 // Resize it if it's smaller
833                                         if(pixmap_w < pixmap->pixmap_w ||
834                                                 pixmap_h < pixmap->pixmap_h)
835                                                 pixmap->resize(pixmap_w, pixmap_h);
836 //printf("TrackCanvas::draw_resources 100\n");
837 // Copy pixmap to background canvas
838                                         background_pixmap->draw_pixmap(pixmap, 
839                                                 pixmap->pixmap_x, 
840                                                 current->y_pixel,
841                                                 pixmap->pixmap_w,
842                                                 edit_h);
843 //printf("TrackCanvas::draw_resources 110\n");
844                                 }
845                         }
846                 }
847         }
848 //printf("TrackCanvas::draw_resources 200\n");
850 // Delete unused pixmaps
851         if(!indexes_only)
852                 for(int i = resource_pixmaps.total - 1; i >= 0; i--)
853                         if(resource_pixmaps.values[i]->visible < -5)
854                         {
855                                 delete resource_pixmaps.values[i];
856                                 resource_pixmaps.remove(resource_pixmaps.values[i]);
857                         }
860 ResourcePixmap* TrackCanvas::create_pixmap(Edit *edit, 
861         int64_t edit_x, 
862         int64_t pixmap_x, 
863         int64_t pixmap_w, 
864         int64_t pixmap_h)
866         ResourcePixmap *result = 0;
868         for(int i = 0; i < resource_pixmaps.total; i++)
869         {
870 //printf("TrackCanvas::create_pixmap 1 %d %d\n", edit->id, resource_pixmaps.values[i]->edit->id);
871                 if(resource_pixmaps.values[i]->edit_id == edit->id) 
872                 {
873                         result = resource_pixmaps.values[i];
874                         break;
875                 }
876         }
878         if(!result)
879         {
880 //printf("TrackCanvas::create_pixmap 2\n");
881                 result = new ResourcePixmap(mwindow, 
882                         this, 
883                         edit, 
884                         pixmap_w, 
885                         pixmap_h);
886                 resource_pixmaps.append(result);
887         }
889 //      result->resize(pixmap_w, pixmap_h);
890         return result;
893 void TrackCanvas::get_pixmap_size(Edit *edit, 
894         int64_t edit_x, 
895         int64_t edit_w, 
896         int64_t &pixmap_x, 
897         int64_t &pixmap_w,
898         int64_t &pixmap_h)
901 // Align x on frame boundaries
904 //      switch(edit->edits->track->data_type)
905 //      {
906 //              case TRACK_AUDIO:
908                         pixmap_x = edit_x;
909                         pixmap_w = edit_w;
910                         if(pixmap_x < 0)
911                         {
912                                 pixmap_w -= -edit_x;
913                                 pixmap_x = 0;
914                         }
916                         if(pixmap_x + pixmap_w > get_w())
917                         {
918                                 pixmap_w = get_w() - pixmap_x;
919                         }
921 //                      break;
922 // 
923 //              case TRACK_VIDEO:
924 //              {
925 //                      int64_t picon_w = (int64_t)(edit->picon_w() + 0.5);
926 //                      int64_t frame_w = (int64_t)(edit->frame_w() + 0.5);
927 //                      int64_t pixel_increment = MAX(picon_w, frame_w);
928 //                      int64_t pixmap_x1 = edit_x;
929 //                      int64_t pixmap_x2 = edit_x + edit_w;
930 // 
931 //                      if(pixmap_x1 < 0)
932 //                      {
933 //                              pixmap_x1 = (int64_t)((double)-edit_x / pixel_increment) * 
934 //                                      pixel_increment + 
935 //                                      edit_x;
936 //                      }
937 // 
938 //                      if(pixmap_x2 > get_w())
939 //                      {
940 //                              pixmap_x2 = (int64_t)((double)(get_w() - edit_x) / pixel_increment + 1) * 
941 //                                      pixel_increment + 
942 //                                      edit_x;
943 //                      }
944 //                      pixmap_x = pixmap_x1;
945 //                      pixmap_w = pixmap_x2 - pixmap_x1;
946 //                      break;
947 //              }
948 //      }
950         pixmap_h = mwindow->edl->local_session->zoom_track;
951         if(mwindow->edl->session->show_titles) pixmap_h += mwindow->theme->title_bg_data->get_h();
952 //printf("get_pixmap_size %d %d %d %d\n", edit_x, edit_w, pixmap_x, pixmap_w);
955 void TrackCanvas::edit_dimensions(Edit *edit, 
956         int64_t &x, 
957         int64_t &y, 
958         int64_t &w, 
959         int64_t &h)
961 //printf("TrackCanvas::edit_dimensions 1 %p\n", edit->track);
962         w = Units::round(edit->track->from_units(edit->length) * 
963                 mwindow->edl->session->sample_rate / 
964                 mwindow->edl->local_session->zoom_sample);
965 //printf("TrackCanvas::edit_dimensions 1\n");
967         h = resource_h();
969 //printf("TrackCanvas::edit_dimensions 1\n");
970         x = Units::round(edit->track->from_units(edit->startproject) * 
971                         mwindow->edl->session->sample_rate /
972                         mwindow->edl->local_session->zoom_sample - 
973                         mwindow->edl->local_session->view_start);
975 //printf("TrackCanvas::edit_dimensions 1\n");
976         y = edit->edits->track->y_pixel;
977 //printf("TrackCanvas::edit_dimensions 1\n");
979         if(mwindow->edl->session->show_titles) 
980                 h += mwindow->theme->title_bg_data->get_h();
981 //printf("TrackCanvas::edit_dimensions 2\n");
984 void TrackCanvas::track_dimensions(Track *track, int64_t &x, int64_t &y, int64_t &w, int64_t &h)
986         x = 0;
987         w = get_w();
988         y = track->y_pixel;
989         h = track->vertical_span(mwindow->theme);
993 void TrackCanvas::draw_paste_destination()
995         int cursor_x = get_cursor_x();
996         int cursor_y = get_cursor_y();
997         int current_atrack = 0;
998         int current_vtrack = 0;
999         int current_aedit = 0;
1000         int current_vedit = 0;
1001         int64_t w = 0;
1002         int64_t x;
1003         double position;
1005 //printf("TrackCanvas::draw_paste_destination 1\n");
1006         if((mwindow->session->current_operation == DRAG_ASSET &&
1007                         (mwindow->session->drag_assets->total ||
1008                         mwindow->session->drag_clips->total)) ||
1009                 (mwindow->session->current_operation == DRAG_EDIT &&
1010                         mwindow->session->drag_edits->total))
1011         {
1012 //printf("TrackCanvas::draw_paste_destination 1\n");
1013                 Asset *asset = 0;
1014                 EDL *clip = 0;
1015                 int draw_box = 0;
1017                 if(mwindow->session->current_operation == DRAG_ASSET &&
1018                         mwindow->session->drag_assets->total)
1019                         asset = mwindow->session->drag_assets->values[0];
1021                 if(mwindow->session->current_operation == DRAG_ASSET &&
1022                         mwindow->session->drag_clips->total)
1023                         clip = mwindow->session->drag_clips->values[0];
1025 // Get destination track
1026                 for(Track *dest = mwindow->session->track_highlighted; 
1027                         dest; 
1028                         dest = dest->next)
1029                 {
1030                         if(dest->record)
1031                         {
1032 // Get source width in pixels
1033                                 w = 0;
1036 // Use start of highlighted edit
1037                                 if(mwindow->session->edit_highlighted)
1038                                         position = mwindow->session->track_highlighted->from_units(
1039                                                 mwindow->session->edit_highlighted->startproject);
1040                                 else
1041 // Use end of highlighted track, disregarding effects
1042                                         position = mwindow->session->track_highlighted->from_units(
1043                                                 mwindow->session->track_highlighted->edits->length());
1045 // Get the x coordinate
1046                                 x = Units::to_int64(position * 
1047                                         mwindow->edl->session->sample_rate /
1048                                         mwindow->edl->local_session->zoom_sample) - 
1049                                         mwindow->edl->local_session->view_start;
1051                                 if(dest->data_type == TRACK_AUDIO)
1052                                 {
1053                                         if(asset && current_atrack < asset->channels)
1054                                         {
1055                                                 w = Units::to_int64((double)asset->audio_length /
1056                                                         asset->sample_rate *
1057                                                         mwindow->edl->session->sample_rate / 
1058                                                         mwindow->edl->local_session->zoom_sample);
1059                                                 current_atrack++;
1060                                                 draw_box = 1;
1061                                         }
1062                                         else
1063                                         if(clip && current_atrack < clip->tracks->total_audio_tracks())
1064                                         {
1065                                                 w = Units::to_int64((double)clip->tracks->total_length() *
1066                                                         mwindow->edl->session->sample_rate / 
1067                                                         mwindow->edl->local_session->zoom_sample);
1068 //printf("draw_paste_destination %d\n", x);
1069                                                 current_atrack++;
1070                                                 draw_box = 1;
1071                                         }
1072                                         else
1073                                         if(mwindow->session->current_operation == DRAG_EDIT &&
1074                                                 current_aedit < mwindow->session->drag_edits->total)
1075                                         {
1076                                                 Edit *edit;
1077                                                 while(current_aedit < mwindow->session->drag_edits->total &&
1078                                                         mwindow->session->drag_edits->values[current_aedit]->track->data_type != TRACK_AUDIO)
1079                                                         current_aedit++;
1081                                                 if(current_aedit < mwindow->session->drag_edits->total)
1082                                                 {
1083                                                         edit = mwindow->session->drag_edits->values[current_aedit];
1084                                                         w = Units::to_int64(edit->length / mwindow->edl->local_session->zoom_sample);
1086                                                         current_aedit++;
1087                                                         draw_box = 1;
1088                                                 }
1089                                         }
1090                                 }
1091                                 else
1092                                 if(dest->data_type == TRACK_VIDEO)
1093                                 {
1094 //printf("draw_paste_destination 1\n");
1095                                         if(asset && current_vtrack < asset->layers)
1096                                         {
1097                                                 w = Units::to_int64((double)asset->video_length / 
1098                                                         asset->frame_rate *
1099                                                         mwindow->edl->session->sample_rate /
1100                                                         mwindow->edl->local_session->zoom_sample);
1101                                                 current_vtrack++;
1102                                                 draw_box = 1;
1103                                         }
1104                                         else
1105                                         if(clip && current_vtrack < clip->tracks->total_video_tracks())
1106                                         {
1107                                                 w = Units::to_int64(clip->tracks->total_length() *
1108                                                         mwindow->edl->session->sample_rate / 
1109                                                         mwindow->edl->local_session->zoom_sample);
1110                                                 current_vtrack++;
1111                                                 draw_box = 1;
1112                                         }
1113                                         else
1114                                         if(mwindow->session->current_operation == DRAG_EDIT &&
1115                                                 current_vedit < mwindow->session->drag_edits->total)
1116                                         {
1117 //printf("draw_paste_destination 2\n");
1118                                                 Edit *edit;
1119                                                 while(current_vedit < mwindow->session->drag_edits->total &&
1120                                                         mwindow->session->drag_edits->values[current_vedit]->track->data_type != TRACK_VIDEO)
1121                                                         current_vedit++;
1123                                                 if(current_vedit < mwindow->session->drag_edits->total)
1124                                                 {
1125 //printf("draw_paste_destination 3\n");
1126                                                         edit = mwindow->session->drag_edits->values[current_vedit];
1127                                                         w = Units::to_int64(edit->track->from_units(edit->length) *
1128                                                                 mwindow->edl->session->sample_rate / 
1129                                                                 mwindow->edl->local_session->zoom_sample);
1131                                                         current_vedit++;
1132                                                         draw_box = 1;
1133                                                 }
1134                                         }
1135                                 }
1137                                 if(w)
1138                                 {
1139                                         int y = dest->y_pixel;
1140                                         int h = dest->vertical_span(mwindow->theme);
1143 //printf("TrackCanvas::draw_paste_destination 2 %d %d %d %d\n", x, y, w, h);
1144                                         if(x < -BC_INFINITY)
1145                                         {
1146                                                 w -= -BC_INFINITY - x;
1147                                                 x += -BC_INFINITY - x;
1148                                         }
1149                                         w = MIN(65535, w);
1150                                         draw_highlight_rectangle(x, y, w, h);
1151                                 }
1152                         }
1153                 }
1154         }
1157 void TrackCanvas::plugin_dimensions(Plugin *plugin, int64_t &x, int64_t &y, int64_t &w, int64_t &h)
1159         x = Units::round(plugin->track->from_units(plugin->startproject) *
1160                 mwindow->edl->session->sample_rate / 
1161                 mwindow->edl->local_session->zoom_sample - 
1162                 mwindow->edl->local_session->view_start);
1163         w = Units::round(plugin->track->from_units(plugin->length) *
1164                 mwindow->edl->session->sample_rate / 
1165                 mwindow->edl->local_session->zoom_sample);
1166         y = plugin->track->y_pixel + 
1167                         mwindow->edl->local_session->zoom_track +
1168                         plugin->plugin_set->get_number() * 
1169                         mwindow->theme->plugin_bg_data->get_h();
1170         if(mwindow->edl->session->show_titles)
1171                 y += mwindow->theme->title_bg_data->get_h();
1172         h = mwindow->theme->plugin_bg_data->get_h();
1175 int TrackCanvas::resource_h()
1177         return mwindow->edl->local_session->zoom_track;
1180 void TrackCanvas::draw_highlight_rectangle(int x, int y, int w, int h)
1182         if(x < -10)
1183         {
1184                 w += x - -10;
1185                 x = -10;
1186         }
1187         if(y < -10)
1188         {
1189                 h += y - -10;
1190                 y = -10;
1191         }
1192         w = MIN(w, get_w() + 20);
1193         h = MIN(h, get_h() + 20);
1194         set_color(WHITE);
1195         set_inverse();
1196         draw_rectangle(x, y, w, h);
1197         draw_rectangle(x + 1, y + 1, w - 2, h - 2);
1198         set_opaque();
1199 //printf("TrackCanvas::draw_highlight_rectangle %d %d %d %d\n", x, y, w, h);
1202 void TrackCanvas::draw_playback_cursor()
1204 // Called before playback_cursor exists
1205 //      if(mwindow->playback_cursor && mwindow->playback_cursor->visible)
1206 //      {
1207 //              mwindow->playback_cursor->visible = 0;
1208 //              mwindow->playback_cursor->draw();
1209 //      }
1212 void TrackCanvas::get_handle_coords(Edit *edit, int64_t &x, int64_t &y, int64_t &w, int64_t &h, int side)
1214         int handle_w = mwindow->theme->edithandlein_data[0]->get_w();
1215         int handle_h = mwindow->theme->edithandlein_data[0]->get_h();
1217         edit_dimensions(edit, x, y, w, h);
1219         if(mwindow->edl->session->show_titles)
1220         {
1221                 y += mwindow->theme->title_bg_data->get_h();
1222         }
1223         else
1224         {
1225                 y = 0;
1226         }
1228         if(side == EDIT_OUT)
1229         {
1230                 x += w - handle_w;
1231         }
1233         h = handle_h;
1234         w = handle_w;
1237 void TrackCanvas::get_transition_coords(int64_t &x, int64_t &y, int64_t &w, int64_t &h)
1239 //printf("TrackCanvas::get_transition_coords 1\n");
1240 //      int transition_w = mwindow->theme->transitionhandle_data[0]->get_w();
1241 //      int transition_h = mwindow->theme->transitionhandle_data[0]->get_h();
1242         int transition_w = 30;
1243         int transition_h = 30;
1244 //printf("TrackCanvas::get_transition_coords 1\n");
1246         if(mwindow->edl->session->show_titles)
1247                 y += mwindow->theme->title_bg_data->get_h();
1248 //printf("TrackCanvas::get_transition_coords 2\n");
1250         y += (h - mwindow->theme->title_bg_data->get_h()) / 2 - transition_h / 2;
1251         x -= transition_w / 2;
1253         h = transition_h;
1254         w = transition_w;
1257 void TrackCanvas::draw_highlighting()
1259         int64_t x, y, w, h;
1260         int draw_box = 0;
1261 //printf("TrackCanvas::draw_highlighting 1 %p %d\n", mwindow->session->track_highlighted, mwindow->session->current_operation);
1265         switch(mwindow->session->current_operation)
1266         {
1267                 case DRAG_ATRANSITION:
1268                 case DRAG_VTRANSITION:
1269 //printf("TrackCanvas::draw_highlighting 1 %p %p\n", 
1270 //      mwindow->session->track_highlighted, mwindow->session->edit_highlighted);
1271                         if(mwindow->session->edit_highlighted)
1272                         {
1273 //printf("TrackCanvas::draw_highlighting 2\n");
1274                                 if((mwindow->session->current_operation == DRAG_ATRANSITION && 
1275                                         mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
1276                                         (mwindow->session->current_operation == DRAG_VTRANSITION && 
1277                                         mwindow->session->track_highlighted->data_type == TRACK_VIDEO))
1278                                 {
1279 //printf("TrackCanvas::draw_highlighting 2\n");
1280                                         edit_dimensions(mwindow->session->edit_highlighted, x, y, w, h);
1281 //printf("TrackCanvas::draw_highlighting 2\n");
1283                                         if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
1284                                                 MWindowGUI::visible(y, y + h, 0, get_h()))
1285                                         {
1286                                                 draw_box = 1;
1287                                                 get_transition_coords(x, y, w, h);
1288                                         }
1289 //printf("TrackCanvas::draw_highlighting 3\n");
1290                                 }
1291                         }
1292                         break;
1296 // Dragging a new effect from the Resource window
1297                 case DRAG_AEFFECT:
1298                 case DRAG_VEFFECT:
1299                         if(mwindow->session->track_highlighted &&
1300                                 ((mwindow->session->current_operation == DRAG_AEFFECT && mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
1301                                         (mwindow->session->current_operation == DRAG_VEFFECT && mwindow->session->track_highlighted->data_type == TRACK_VIDEO)))
1302                         {
1303 // Put it before another plugin
1304                                 if(mwindow->session->plugin_highlighted)
1305                                 {
1306                                         plugin_dimensions(mwindow->session->plugin_highlighted, 
1307                                                 x, 
1308                                                 y, 
1309                                                 w, 
1310                                                 h);
1311 //printf("TrackCanvas::draw_highlighting 1 %d %d\n", x, w);
1312                                 }
1313                                 else
1314 // Put it after a plugin set
1315                                 if(mwindow->session->pluginset_highlighted &&
1316                                         mwindow->session->pluginset_highlighted->last)
1317                                 {
1318                                         plugin_dimensions((Plugin*)mwindow->session->pluginset_highlighted->last, 
1319                                                 x, 
1320                                                 y, 
1321                                                 w, 
1322                                                 h);
1323 //printf("TrackCanvas::draw_highlighting 1 %d %d\n", x, w);
1324                                         int64_t track_x, track_y, track_w, track_h;
1325                                         track_dimensions(mwindow->session->track_highlighted, 
1326                                                 track_x, 
1327                                                 track_y, 
1328                                                 track_w, 
1329                                                 track_h);
1331                                         x += w;
1332                                         w = Units::round(
1333                                                         mwindow->session->track_highlighted->get_length() *
1334                                                         mwindow->edl->session->sample_rate / 
1335                                                         mwindow->edl->local_session->zoom_sample - 
1336                                                         mwindow->edl->local_session->view_start) -
1337                                                 x;
1338 //printf("TrackCanvas::draw_highlighting 2 %d\n", w);
1339                                         if(w <= 0) w = track_w;
1340                                 }
1341                                 else
1342                                 {
1343                                         track_dimensions(mwindow->session->track_highlighted, 
1344                                                 x, 
1345                                                 y, 
1346                                                 w, 
1347                                                 h);
1349 //printf("TrackCanvas::draw_highlighting 1 %d %d %d %d\n", x, y, w, h);
1350 // Put it in a new plugin set determined by the selected range
1351                                         if(mwindow->edl->local_session->get_selectionend() > 
1352                                                 mwindow->edl->local_session->get_selectionstart())
1353                                         {
1354                                                 x = Units::to_int64(mwindow->edl->local_session->get_selectionstart() *
1355                                                         mwindow->edl->session->sample_rate / 
1356                                                         mwindow->edl->local_session->zoom_sample -
1357                                                         mwindow->edl->local_session->view_start);
1358                                                 w = Units::to_int64((mwindow->edl->local_session->get_selectionend() - 
1359                                                         mwindow->edl->local_session->get_selectionstart()) *
1360                                                         mwindow->edl->session->sample_rate / 
1361                                                         mwindow->edl->local_session->zoom_sample);
1362                                         }
1363 // Put it in a new plugin set determined by an edit boundary
1364 //                                      else
1365 //                                      if(mwindow->session->edit_highlighted)
1366 //                                      {
1367 //                                              int64_t temp_y, temp_h;
1368 //                                              edit_dimensions(mwindow->session->edit_highlighted, 
1369 //                                                      x, 
1370 //                                                      temp_y, 
1371 //                                                      w, 
1372 //                                                      temp_h);
1373 //                                      }
1374 // Put it at the beginning of the track in a new plugin set
1375                                 }
1377                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
1378                                         MWindowGUI::visible(y, y + h, 0, get_h()))
1379                                 {
1380 //printf("TrackCanvas::draw_highlighting 1\n");
1381                                         draw_box = 1;
1382                                 }
1383                         }
1384                         break;
1385                 
1386                 case DRAG_ASSET:
1387                         if(mwindow->session->track_highlighted)
1388                         {
1389                                 track_dimensions(mwindow->session->track_highlighted, x, y, w, h);
1391                                 if(MWindowGUI::visible(y, y + h, 0, get_h()))
1392                                 {
1393                                         draw_paste_destination();
1394                                 }
1395                         }
1396                         break;
1398 // Dragging an effect from the timeline
1399                 case DRAG_AEFFECT_COPY:
1400                 case DRAG_VEFFECT_COPY:
1401                         if((mwindow->session->plugin_highlighted || mwindow->session->track_highlighted) &&
1402                                 ((mwindow->session->current_operation == DRAG_AEFFECT_COPY && mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
1403                                 (mwindow->session->current_operation == DRAG_VEFFECT_COPY && mwindow->session->track_highlighted->data_type == TRACK_VIDEO)))
1404                         {
1405 // Put it before another plugin
1406                                 if(mwindow->session->plugin_highlighted)
1407                                         plugin_dimensions(mwindow->session->plugin_highlighted, x, y, w, h);
1408                                 else
1409 // Put it after a plugin set
1410                                 if(mwindow->session->pluginset_highlighted &&
1411                                         mwindow->session->pluginset_highlighted->last)
1412                                 {
1413                                         plugin_dimensions((Plugin*)mwindow->session->pluginset_highlighted->last, x, y, w, h);
1414                                         x += w;
1415                                 }
1416                                 else
1417                                 if(mwindow->session->track_highlighted)
1418                                 {
1419                                         track_dimensions(mwindow->session->track_highlighted, x, y, w, h);
1421 // Put it in a new plugin set determined by an edit boundary
1422                                         if(mwindow->session->edit_highlighted)
1423                                         {
1424                                                 int64_t temp_y, temp_h;
1425                                                 edit_dimensions(mwindow->session->edit_highlighted, 
1426                                                         x, 
1427                                                         temp_y, 
1428                                                         w, 
1429                                                         temp_h);
1430                                         }
1431 // Put it in a new plugin set at the start of the track
1432                                 }
1434 // Calculate length of plugin based on data type of track and units
1435                                 if(mwindow->session->track_highlighted->data_type == TRACK_VIDEO)
1436                                 {
1437                                         w = (int64_t)((double)mwindow->session->drag_plugin->length / 
1438                                                 mwindow->edl->session->frame_rate *
1439                                                 mwindow->edl->session->sample_rate /
1440                                                 mwindow->edl->local_session->zoom_sample);
1441                                 }
1442                                 else
1443                                 {
1444                                         w = (int64_t)mwindow->session->drag_plugin->length /
1445                                                 mwindow->edl->local_session->zoom_sample;
1446                                 }
1448                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
1449                                         MWindowGUI::visible(y, y + h, 0, get_h()))
1450                                 {
1451                                         draw_box = 1;
1452                                 }
1454                         }
1455                         break;
1457                 case DRAG_EDIT:
1458 //printf("TrackCanvas::draw_highlighting 1\n");
1459                         if(mwindow->session->track_highlighted)
1460                         {
1461                                 track_dimensions(mwindow->session->track_highlighted, x, y, w, h);
1463                                 if(MWindowGUI::visible(y, y + h, 0, get_h()))
1464                                 {
1465                                         draw_paste_destination();
1466                                 }
1467                         }
1470                         break;
1471         }
1474         if(draw_box)
1475         {
1476                 draw_highlight_rectangle(x, y, w, h);
1477         }
1480 void TrackCanvas::draw_plugins()
1482         char string[BCTEXTLEN];
1484         for(Track *track = mwindow->edl->tracks->first;
1485                 track;
1486                 track = track->next)
1487         {
1488                 if(track->expand_view)
1489                 {
1490                         for(int i = 0; i < track->plugin_set.total; i++)
1491                         {
1492                                 PluginSet *pluginset = track->plugin_set.values[i];
1494                                 for(Plugin *plugin = (Plugin*)pluginset->first; plugin; plugin = (Plugin*)plugin->next)
1495                                 {
1496                                         int64_t total_x, y, total_w, h;
1497                                         plugin_dimensions(plugin, total_x, y, total_w, h);
1498                                         
1499                                         if(MWindowGUI::visible(total_x, total_x + total_w, 0, get_w()) &&
1500                                                 MWindowGUI::visible(y, y + h, 0, get_h()) &&
1501                                                 plugin->plugin_type != PLUGIN_NONE)
1502                                         {
1503                                                 int x = total_x, w = total_w, left_margin = 5;
1504                                                 if(x < 0)
1505                                                 {
1506                                                         w -= -x;
1507                                                         x = 0;
1508                                                 }
1509                                                 if(w + x > get_w()) w -= (w + x) - get_w();
1511                                                 draw_3segmenth(x, 
1512                                                         y, 
1513                                                         w, 
1514                                                         total_x,
1515                                                         total_w,
1516                                                         mwindow->theme->plugin_bg_data,
1517                                                         0);
1518                                                 set_color(WHITE);
1519                                                 set_font(MEDIUMFONT_3D);
1520                                                 plugin->calculate_title(string, 0);
1522 // Truncate string to int64_test visible in background
1523                                                 int len = strlen(string), j;
1524                                                 for(j = len; j >= 0; j--)
1525                                                 {
1526                                                         if(left_margin + get_text_width(MEDIUMFONT_3D, string) > w)
1527                                                         {
1528                                                                 string[j] = 0;
1529                                                         }
1530                                                         else
1531                                                                 break;
1532                                                 }
1534 // Justify the text on the left boundary of the edit if it is visible.
1535 // Otherwise justify it on the left side of the screen.
1536                                                 int text_x = total_x + left_margin;
1537                                                 text_x = MAX(left_margin, text_x);
1538                                                 draw_text(text_x, 
1539                                                         y + get_text_ascent(MEDIUMFONT_3D) + 2, 
1540                                                         string,
1541                                                         strlen(string),
1542                                                         0);
1543                                         }
1544                                 }
1545                         }
1546                 }
1547         }
1551 void TrackCanvas::draw_inout_points()
1556 void TrackCanvas::draw_drag_handle()
1558         if(mwindow->session->current_operation == DRAG_EDITHANDLE2 ||
1559                 mwindow->session->current_operation == DRAG_PLUGINHANDLE2)
1560         {
1561 //printf("TrackCanvas::draw_drag_handle 1 %ld %ld\n", mwindow->session->drag_sample, mwindow->edl->local_session->view_start);
1562                 int64_t pixel1 = Units::round(mwindow->session->drag_position * 
1563                         mwindow->edl->session->sample_rate /
1564                         mwindow->edl->local_session->zoom_sample - 
1565                         mwindow->edl->local_session->view_start);
1566 //printf("TrackCanvas::draw_drag_handle 2 %d\n", pixel1);
1567                 set_color(GREEN);
1568                 set_inverse();
1569 //printf("TrackCanvas::draw_drag_handle 3\n");
1570                 draw_line(pixel1, 0, pixel1, get_h());
1571                 set_opaque();
1572 //printf("TrackCanvas::draw_drag_handle 4\n");
1573         }
1577 void TrackCanvas::draw_transitions()
1579         int64_t x, y, w, h;
1581         for(Track *track = mwindow->edl->tracks->first;
1582                 track;
1583                 track = track->next)
1584         {
1585                 for(Edit *edit = track->edits->first;
1586                         edit;
1587                         edit = edit->next)
1588                 {
1589                         if(edit->transition)
1590                         {
1591                                 edit_dimensions(edit, x, y, w, h);
1592                                 get_transition_coords(x, y, w, h);
1594                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
1595                                         MWindowGUI::visible(y, y + h, 0, get_h()))
1596                                 {
1597                                         PluginServer *server = mwindow->scan_plugindb(edit->transition->title,
1598                                                 track->data_type);
1599                                         draw_vframe(server->picon, 
1600                                                 x, 
1601                                                 y, 
1602                                                 w, 
1603                                                 h, 
1604                                                 0, 
1605                                                 0, 
1606                                                 server->picon->get_w(), 
1607                                                 server->picon->get_h());
1608                                 }
1609                         }
1610                 }
1611         }
1614 void TrackCanvas::draw_loop_points()
1616 //printf("TrackCanvas::draw_loop_points 1\n");
1617         if(mwindow->edl->local_session->loop_playback)
1618         {
1619 //printf("TrackCanvas::draw_loop_points 2\n");
1620                 int64_t x = Units::round(mwindow->edl->local_session->loop_start *
1621                         mwindow->edl->session->sample_rate /
1622                         mwindow->edl->local_session->zoom_sample - 
1623                         mwindow->edl->local_session->view_start);
1624 //printf("TrackCanvas::draw_loop_points 3\n");
1626                 if(MWindowGUI::visible(x, x + 1, 0, get_w()))
1627                 {
1628                         set_color(GREEN);
1629                         draw_line(x, 0, x, get_h());
1630                 }
1631 //printf("TrackCanvas::draw_loop_points 4\n");
1633                 x = Units::round(mwindow->edl->local_session->loop_end *
1634                         mwindow->edl->session->sample_rate /
1635                         mwindow->edl->local_session->zoom_sample - 
1636                         mwindow->edl->local_session->view_start);
1637 //printf("TrackCanvas::draw_loop_points 5\n");
1639                 if(MWindowGUI::visible(x, x + 1, 0, get_w()))
1640                 {
1641                         set_color(GREEN);
1642                         draw_line(x, 0, x, get_h());
1643                 }
1644 //printf("TrackCanvas::draw_loop_points 6\n");
1645         }
1646 //printf("TrackCanvas::draw_loop_points 7\n");
1649 void TrackCanvas::draw_brender_start()
1651         if(mwindow->preferences->use_brender)
1652         {
1653                 int64_t x = Units::round(mwindow->edl->session->brender_start *
1654                         mwindow->edl->session->sample_rate /
1655                         mwindow->edl->local_session->zoom_sample - 
1656                         mwindow->edl->local_session->view_start);
1658                 if(MWindowGUI::visible(x, x + 1, 0, get_w()))
1659                 {
1660                         set_color(RED);
1661                         draw_line(x, 0, x, get_h());
1662                 }
1663         }
1666 int TrackCanvas::do_keyframes(int cursor_x, 
1667         int cursor_y, 
1668         int draw, 
1669         int buttonpress, 
1670         int &new_cursor,
1671         int &update_cursor,
1672         int &rerender)
1674         int current_tool = 0;
1675         int result = 0;
1676         EDLSession *session = mwindow->edl->session;
1678         for(Track *track = mwindow->edl->tracks->first;
1679                 track && !result;
1680                 track = track->next)
1681         {
1682                 Automation *automation = track->automation;
1684 //printf("TrackCanvas::draw_keyframes 1\n");
1685                 if(!result && session->auto_conf->fade)
1686                 {
1687                         result = do_float_autos(track, 
1688                                 automation->fade_autos,
1689                                 cursor_x, 
1690                                 cursor_y, 
1691                                 draw, 
1692                                 buttonpress, 
1693                                 WHITE);
1694                         if(result && mwindow->session->current_operation == DRAG_FADE)
1695                         {
1696                                 rerender = 1;
1697                         }
1698                         if(result && buttonpress)
1699                         {
1700                                 synchronize_autos(0, track, (FloatAuto*)mwindow->session->drag_auto, 1);
1701                                 mwindow->session->current_operation = DRAG_FADE;
1702                                 update_drag_caption();
1703                         }
1704                 }
1706 //printf("TrackCanvas::draw_keyframes 1 %d\n", result);
1708                 if(!result && session->auto_conf->czoom && automation->czoom_autos)
1709                 {
1710                         result = do_float_autos(track, 
1711                                 automation->czoom_autos,
1712                                 cursor_x, 
1713                                 cursor_y, 
1714                                 draw, 
1715                                 buttonpress,
1716                                 MEPURPLE);
1717                         if(result && mwindow->session->current_operation == DRAG_CZOOM)
1718                         {
1719                                 rerender = 1;
1720                         }
1721                         if(result && buttonpress)
1722                         {
1723                                 mwindow->session->current_operation = DRAG_CZOOM;
1724                                 update_drag_caption();
1725                         }
1726                 }
1728 //printf("TrackCanvas::draw_keyframes 2 %d\n", result);
1729                 if(!result && session->auto_conf->pzoom && automation->pzoom_autos)
1730                 {
1731                         result = do_float_autos(track, 
1732                                 automation->pzoom_autos,
1733                                 cursor_x, 
1734                                 cursor_y, 
1735                                 draw, 
1736                                 buttonpress,
1737                                 PINK);
1738                         if(result && mwindow->session->current_operation == DRAG_PZOOM)
1739                         {
1740                                 rerender = 1;
1741                         }
1742                         if(result && buttonpress)
1743                         {
1744                                 mwindow->session->current_operation = DRAG_PZOOM;
1745                                 update_drag_caption();
1746                         }
1747                 }
1749 //printf("TrackCanvas::draw_keyframes 1 %d\n", result);
1750                 if(!result && session->auto_conf->mute)
1751                 {
1752                         result = do_toggle_autos(track, 
1753                                 automation->mute_autos,
1754                                 cursor_x, 
1755                                 cursor_y, 
1756                                 draw, 
1757                                 buttonpress,
1758                                 BLUE);
1759                         if(result && mwindow->session->current_operation == DRAG_MUTE)
1760                         {
1761                                 rerender = 1;
1762                         }
1763                         if(result && buttonpress)
1764                         {
1765                                 mwindow->session->current_operation = DRAG_MUTE;
1766                                 update_drag_caption();
1767                         }
1768                 }
1770 //printf("TrackCanvas::draw_keyframes 1 %d\n", result);
1771                 if(!result && session->auto_conf->camera && automation->camera_autos)
1772                 {
1773                         result = do_autos(track, 
1774                                 automation->camera_autos,
1775                                 cursor_x, 
1776                                 cursor_y, 
1777                                 draw, 
1778                                 buttonpress,
1779                                 camerakeyframe_pixmap);
1780                         if(result && mwindow->session->current_operation == DRAG_CAMERA)
1781                         {
1782                                 rerender = 1;
1783                         }
1784                         if(result && buttonpress)
1785                         {
1786                                 mwindow->session->current_operation = DRAG_CAMERA_PRE;
1787                                 update_drag_caption();
1788                                 rerender = 1;
1789                         }
1790                 }
1792                 if(!result && session->auto_conf->mode && automation->mode_autos)
1793                 {
1794                         result = do_autos(track, 
1795                                 automation->mode_autos,
1796                                 cursor_x, 
1797                                 cursor_y, 
1798                                 draw, 
1799                                 buttonpress,
1800                                 modekeyframe_pixmap);
1801                         if(result && mwindow->session->current_operation == DRAG_MODE)
1802                         {
1803                                 rerender = 1;
1804                         }
1805                         if(result && buttonpress)
1806                         {
1807                                 mwindow->session->current_operation = DRAG_MODE_PRE;
1808                                 update_drag_caption();
1809                                 rerender = 1;
1810                         }
1811                 }
1813 //printf("TrackCanvas::draw_keyframes 1 %d\n", result);
1814                 if(!result && session->auto_conf->projector && automation->projector_autos)
1815                 {
1816                         result = do_autos(track, 
1817                                 automation->projector_autos,
1818                                 cursor_x, 
1819                                 cursor_y, 
1820                                 draw, 
1821                                 buttonpress,
1822                                 projectorkeyframe_pixmap);
1823                         if(result && mwindow->session->current_operation == DRAG_PROJECTOR)
1824                         {
1825                                 rerender = 1;
1826                         }
1827                         if(result && buttonpress)
1828                         {
1829                                 mwindow->session->current_operation = DRAG_PROJECTOR_PRE;
1830                                 update_drag_caption();
1831                                 rerender = 1;
1832                         }
1833                 }
1835                 if(!result && session->auto_conf->mask && automation->mask_autos)
1836                 {
1837                         result = do_autos(track, 
1838                                 automation->mask_autos,
1839                                 cursor_x, 
1840                                 cursor_y, 
1841                                 draw, 
1842                                 buttonpress,
1843                                 maskkeyframe_pixmap);
1844                         if(result && mwindow->session->current_operation == DRAG_MASK)
1845                         {
1846                                 rerender = 1;
1847                         }
1848                         if(result && buttonpress)
1849                         {
1850                                 mwindow->session->current_operation = DRAG_MASK_PRE;
1851                                 update_drag_caption();
1852                                 rerender = 1;
1853                         }
1854                 }
1856 //printf("TrackCanvas::draw_keyframes 1 %d\n", result);
1857                 if(!result && session->auto_conf->pan && automation->pan_autos)
1858                 {
1859                         result = do_autos(track, 
1860                                 automation->pan_autos,
1861                                 cursor_x, 
1862                                 cursor_y, 
1863                                 draw, 
1864                                 buttonpress,
1865                                 pankeyframe_pixmap);
1866                         if(result && mwindow->session->current_operation == DRAG_PAN)
1867                         {
1868                                 rerender = 1;
1869                         }
1870                         if(result && buttonpress)
1871                         {
1872                                 mwindow->session->current_operation = DRAG_PAN_PRE;
1873                                 update_drag_caption();
1874                                 rerender = 1;
1875                         }
1876                 }
1878 //printf("TrackCanvas::draw_keyframes 1 %d\n", result);
1879                 if(!result && session->auto_conf->plugins)
1880                 {
1881                         Plugin *plugin;
1882                         KeyFrame *keyframe;
1883                         result = do_plugin_autos(track,
1884                                 cursor_x, 
1885                                 cursor_y, 
1886                                 draw, 
1887                                 buttonpress,
1888                                 plugin,
1889                                 keyframe);
1890                         if(result && mwindow->session->current_operation == DRAG_PLUGINKEY)
1891                         {
1892                                 rerender = 1;
1893                         }
1894                         if(result && (buttonpress == 1))
1895                         {
1896                                 mwindow->session->current_operation = DRAG_PLUGINKEY_PRE;
1897                                 update_drag_caption();
1898                                 rerender = 1;
1899                         }
1900                         else
1901                         if(result && (buttonpress == 3))
1902                         {
1903                                 gui->keyframe_menu->update(plugin, keyframe);
1904                                 gui->keyframe_menu->activate_menu();
1905                                 rerender = 1; // the position changes
1906                         }
1907                 }
1908 //printf("TrackCanvas::draw_keyframes 1 %d\n", result);
1909         }
1911         if(mwindow->session->current_operation == DRAG_FADE ||
1912                 mwindow->session->current_operation == DRAG_CZOOM ||
1913                 mwindow->session->current_operation == DRAG_PZOOM ||
1914                 mwindow->session->current_operation == DRAG_PLAY ||
1915                 mwindow->session->current_operation == DRAG_MUTE ||
1916                 mwindow->session->current_operation == DRAG_CAMERA ||
1917                 mwindow->session->current_operation == DRAG_CAMERA_PRE ||
1918                 mwindow->session->current_operation == DRAG_MASK ||
1919                 mwindow->session->current_operation == DRAG_MASK_PRE ||
1920                 mwindow->session->current_operation == DRAG_MODE ||
1921                 mwindow->session->current_operation == DRAG_MODE_PRE ||
1922                 mwindow->session->current_operation == DRAG_PAN ||
1923                 mwindow->session->current_operation == DRAG_PAN_PRE ||
1924                 mwindow->session->current_operation == DRAG_PLUGINKEY ||
1925                 mwindow->session->current_operation == DRAG_PLUGINKEY_PRE ||
1926                 mwindow->session->current_operation == DRAG_PROJECTOR ||
1927                 mwindow->session->current_operation == DRAG_PROJECTOR_PRE)
1928         {
1929                 result = 1;
1930         }
1932 //printf("TrackCanvas::draw_keyframes 2 %d\n", result);
1933         update_cursor = 1;
1934         if(result)
1935         {
1936                 new_cursor = UPRIGHT_ARROW_CURSOR;
1937 //              rerender = 1;
1938         }
1940 //printf("TrackCanvas::do_keyframes 3 %d\n", result);
1941         return result;
1944 void TrackCanvas::draw_auto(Auto *current, 
1945         int x, 
1946         int y, 
1947         int center_pixel, 
1948         int zoom_track,
1949         int color)
1951         int x1, y1, x2, y2;
1952         char string[BCTEXTLEN];
1954         x1 = x - HANDLE_W / 2;
1955         x2 = x + HANDLE_W / 2;
1956         y1 = center_pixel + y - HANDLE_W / 2;
1957         y2 = center_pixel + y + HANDLE_W / 2;
1959         if(y1 < center_pixel + -zoom_track / 2) y1 = center_pixel + -zoom_track / 2;
1960         if(y2 > center_pixel + zoom_track / 2) y2 = center_pixel + zoom_track / 2;
1962         set_color(BLACK);
1963         draw_box(x1 + 1, y1 + 1, x2 - x1, y2 - y1);
1964         set_color(color);
1965         draw_box(x1, y1, x2 - x1, y2 - y1);
1968 void TrackCanvas::draw_floatauto(Auto *current, 
1969         int x, 
1970         int y, 
1971         int in_x, 
1972         int in_y, 
1973         int out_x, 
1974         int out_y, 
1975         int center_pixel, 
1976         int zoom_track,
1977         int color)
1979         int x1, y1, x2, y2;
1980         int in_x1, in_y1, in_x2, in_y2;
1981         int out_x1, out_y1, out_x2, out_y2;
1982         char string[BCTEXTLEN];
1984 // Center
1985         x1 = x - HANDLE_W / 2;
1986         x2 = x + HANDLE_W / 2;
1987         y1 = center_pixel + y - HANDLE_W / 2;
1988         y2 = center_pixel + y + HANDLE_W / 2;
1990         CLAMP(y1, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
1991         CLAMP(y2, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
1993         set_color(BLACK);
1994         draw_box(x1 + 1, y1 + 1, x2 - x1, y2 - y1);
1995         set_color(color);
1996         draw_box(x1, y1, x2 - x1, y2 - y1);
1998 // In handle
1999         in_x1 = in_x - HANDLE_W / 2;
2000         in_x2 = in_x + HANDLE_W / 2;
2001         in_y1 = center_pixel + in_y - HANDLE_W / 2;
2002         in_y2 = center_pixel + in_y + HANDLE_W / 2;
2004         CLAMP(in_y1, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
2005         CLAMP(in_y2, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
2006         CLAMP(in_y, -zoom_track / 2, zoom_track / 2);
2008         set_color(BLACK);
2009         draw_line(x + 1, center_pixel + y + 1, in_x + 1, center_pixel + in_y + 1);
2010         draw_box(in_x1 + 1, in_y1 + 1, in_x2 - in_x1, in_y2 - in_y1);
2011         set_color(color);
2012         draw_line(x, center_pixel + y, in_x, center_pixel + in_y);
2013         draw_box(in_x1, in_y1, in_x2 - in_x1, in_y2 - in_y1);
2017 // Out handle
2018         out_x1 = out_x - HANDLE_W / 2;
2019         out_x2 = out_x + HANDLE_W / 2;
2020         out_y1 = center_pixel + out_y - HANDLE_W / 2;
2021         out_y2 = center_pixel + out_y + HANDLE_W / 2;
2023         CLAMP(out_y1, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
2024         CLAMP(out_y2, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
2025         CLAMP(out_y, -zoom_track / 2, zoom_track / 2);
2028         set_color(BLACK);
2029         draw_line(x + 1, center_pixel + y + 1, out_x + 1, center_pixel + out_y + 1);
2030         draw_box(out_x1 + 1, out_y1 + 1, out_x2 - out_x1, out_y2 - out_y1);
2031         set_color(color);
2032         draw_line(x, center_pixel + y, out_x, center_pixel + out_y);
2033         draw_box(out_x1, out_y1, out_x2 - out_x1, out_y2 - out_y1);
2037 int TrackCanvas::test_auto(Auto *current, 
2038         int x, 
2039         int y, 
2040         int center_pixel, 
2041         int zoom_track, 
2042         int cursor_x, 
2043         int cursor_y, 
2044         int buttonpress)
2046         int x1, y1, x2, y2;
2047         char string[BCTEXTLEN];
2048         int result = 0;
2050         x1 = x - HANDLE_W / 2;
2051         x2 = x + HANDLE_W / 2;
2052         y1 = center_pixel + y - HANDLE_W / 2;
2053         y2 = center_pixel + y + HANDLE_W / 2;
2055         if(y1 < center_pixel + -zoom_track / 2) y1 = center_pixel + -zoom_track / 2;
2056         if(y2 > center_pixel + zoom_track / 2) y2 = center_pixel + zoom_track / 2;
2057 //printf("test_auto 1 %d %d %d %d %d %d\n", cursor_x, cursor_y, x1, x2, y1, y2);
2059         if(cursor_x >= x1 && cursor_x < x2 && cursor_y >= y1 && cursor_y < y2)
2060         {
2061 //printf("test_auto 2 %d\n", buttonpress);
2062                 if(buttonpress)
2063                 {
2064 //printf("test_auto 3\n");
2065                         mwindow->session->drag_auto = current;
2066                         mwindow->session->drag_start_percentage = current->value_to_percentage();
2067                         mwindow->session->drag_start_position = current->position;
2068                         mwindow->session->drag_origin_x = cursor_x;
2069                         mwindow->session->drag_origin_y = cursor_y;
2070                 }
2071                 result = 1;
2072         }
2074         return result;
2077 int TrackCanvas::test_floatauto(Auto *current, 
2078         int x, 
2079         int y, 
2080         int in_x,
2081         int in_y,
2082         int out_x,
2083         int out_y,
2084         int center_pixel, 
2085         int zoom_track, 
2086         int cursor_x, 
2087         int cursor_y, 
2088         int buttonpress)
2090         int x1, y1, x2, y2;
2091         int in_x1, in_y1, in_x2, in_y2;
2092         int out_x1, out_y1, out_x2, out_y2;
2093         char string[BCTEXTLEN];
2094         int result = 0;
2096         x1 = x - HANDLE_W / 2;
2097         x2 = x + HANDLE_W / 2;
2098         y1 = center_pixel + y - HANDLE_W / 2;
2099         y2 = center_pixel + y + HANDLE_W / 2;
2101         if(y1 < center_pixel + -zoom_track / 2) y1 = center_pixel + -zoom_track / 2;
2102         if(y2 > center_pixel + zoom_track / 2) y2 = center_pixel + zoom_track / 2;
2104         in_x1 = in_x - HANDLE_W / 2;
2105         in_x2 = in_x + HANDLE_W / 2;
2106         in_y1 = center_pixel + in_y - HANDLE_W / 2;
2107         in_y2 = center_pixel + in_y + HANDLE_W / 2;
2109         if(in_y1 < center_pixel + -zoom_track / 2) in_y1 = center_pixel + -zoom_track / 2;
2110         if(in_y2 > center_pixel + zoom_track / 2) in_y2 = center_pixel + zoom_track / 2;
2112         out_x1 = out_x - HANDLE_W / 2;
2113         out_x2 = out_x + HANDLE_W / 2;
2114         out_y1 = center_pixel + out_y - HANDLE_W / 2;
2115         out_y2 = center_pixel + out_y + HANDLE_W / 2;
2117         if(out_y1 < center_pixel + -zoom_track / 2) out_y1 = center_pixel + -zoom_track / 2;
2118         if(out_y2 > center_pixel + zoom_track / 2) out_y2 = center_pixel + zoom_track / 2;
2122 //printf("TrackCanvas::test_floatauto %d %d %d %d %d %d\n", cursor_x, cursor_y, x1, x2, y1, y2);
2123 // Test value
2124         if(!ctrl_down() &&
2125                 cursor_x >= x1 && 
2126                 cursor_x < x2 && 
2127                 cursor_y >= y1 && 
2128                 cursor_y < y2)
2129         {
2130                 if(buttonpress)
2131                 {
2132                         mwindow->session->drag_auto = current;
2133                         mwindow->session->drag_start_percentage = current->value_to_percentage();
2134                         mwindow->session->drag_start_position = current->position;
2135                         mwindow->session->drag_origin_x = cursor_x;
2136                         mwindow->session->drag_origin_y = cursor_y;
2137                         mwindow->session->drag_handle = 0;
2138                 }
2139                 result = 1;
2140         }
2141         else
2142 // Test in control
2143         if(ctrl_down() &&
2144                 cursor_x >= in_x1 && 
2145                 cursor_x < in_x2 && 
2146                 cursor_y >= in_y1 && 
2147                 cursor_y < in_y2 &&
2148                 current->position > 0)
2149         {
2150                 if(buttonpress)
2151                 {
2152                         mwindow->session->drag_auto = current;
2153                         mwindow->session->drag_start_percentage = 
2154                                 current->invalue_to_percentage();
2155                         mwindow->session->drag_start_position = 
2156                                 ((FloatAuto*)current)->control_in_position;
2157                         mwindow->session->drag_origin_x = cursor_x;
2158                         mwindow->session->drag_origin_y = cursor_y;
2159                         mwindow->session->drag_handle = 1;
2160                 }
2161                 result = 1;
2162         }
2163         else
2164 // Test out control
2165         if(ctrl_down() &&
2166                 cursor_x >= out_x1 && 
2167                 cursor_x < out_x2 && 
2168                 cursor_y >= out_y1 && 
2169                 cursor_y < out_y2)
2170         {
2171                 if(buttonpress)
2172                 {
2173                         mwindow->session->drag_auto = current;
2174                         mwindow->session->drag_start_percentage = 
2175                                 current->outvalue_to_percentage();
2176                         mwindow->session->drag_start_position = 
2177                                 ((FloatAuto*)current)->control_out_position;
2178                         mwindow->session->drag_origin_x = cursor_x;
2179                         mwindow->session->drag_origin_y = cursor_y;
2180                         mwindow->session->drag_handle = 2;
2181                 }
2182                 result = 1;
2183         }
2185 // if(buttonpress) 
2186 // printf("TrackCanvas::test_floatauto 2 drag_handle=%d ctrl_down=%d cursor_x=%d cursor_y=%d x1=%d x2=%d y1=%d y2=%d\n", 
2187 // mwindow->session->drag_handle,
2188 // ctrl_down(),
2189 // cursor_x,
2190 // cursor_y,
2191 // x1, x2, y1, y2);
2193         return result;
2196 void TrackCanvas::draw_floatline(int center_pixel, 
2197         FloatAuto *previous,
2198         FloatAuto *next,
2199         FloatAutos *autos,
2200         int64_t unit_start,
2201         double zoom_units,
2202         double yscale,
2203         int x1,
2204         int y1,
2205         int x2,
2206         int y2,
2207         int color)
2209 // Solve bezier equation for either every pixel or a certain large number of
2210 // points.
2214 // Not using slope intercept
2215         x1 = MAX(0, x1);
2220         int prev_y;
2221 // Call by reference fails for some reason here
2222         FloatAuto *previous1 = previous, *next1 = next;
2223         for(int x = x1; x < x2; x++)
2224         {
2225                 int64_t position = (int64_t)(unit_start + x * zoom_units);
2226                 float value = autos->get_value(position, PLAY_FORWARD, previous1, next1);
2228                 int y = (int)(center_pixel + 
2229                         (autos->value_to_percentage(value) - 0.5) * -yscale);
2231                 if(x > x1)
2232                 {
2233                         set_color(BLACK);
2234                         draw_line(x - 1, prev_y + 1, x, y + 1);
2235                         set_color(color);
2236                         draw_line(x - 1, prev_y, x, y);
2237                 }
2238                 prev_y = y;
2239         }
2243 //      set_color(BLACK);
2244 //      draw_line(x1, center_pixel + y1 + 1, x2, center_pixel + y2 + 1);
2245 //      set_color(WHITE);
2246 //      draw_line(x1, center_pixel + y1, x2, center_pixel + y2);
2254 void TrackCanvas::synchronize_autos(float change, Track *skip, FloatAuto *fauto, int fill_gangs)
2256         if (fill_gangs == 1 && skip->gang) // fill mwindow->session->drag_auto_gang
2257         {
2258                 for(Track *current = mwindow->edl->tracks->first;
2259                         current;
2260                         current = NEXT)
2261                 {
2262                         if(current->data_type == skip->data_type &&
2263                                 current->gang && 
2264                                 current->record && 
2265                                 current != skip)
2266                         {
2267                                 FloatAutos *fade_autos = current->automation->fade_autos;
2268                                 double position = skip->from_units(fauto->position);
2269                                 FloatAuto *previous = 0, *next = 0;
2271                                 float init_value = fade_autos->get_value(fauto->position, PLAY_FORWARD, previous, next);
2272                                 FloatAuto *keyframe;
2273                                 keyframe = (FloatAuto*)fade_autos->get_auto_at_position(position);
2274                                 
2275                                 if (!keyframe)
2276                                 {
2277 // create keyframe at exactly this point in time
2278                                         keyframe = (FloatAuto*)fade_autos->insert_auto(fauto->position);
2279                                         keyframe->value = init_value;
2280                                 } 
2281                                 else
2282                                 { 
2283 // keyframe exists, just change it
2284                                         keyframe->value += change;              
2285                                 } 
2286                                 
2287                                 keyframe->position = fauto->position;
2288                                 keyframe->control_out_position = fauto->control_out_position;
2289                                 keyframe->control_in_position = fauto->control_in_position;
2290                                 keyframe->control_out_value = fauto->control_out_value;
2291                                 keyframe->control_in_value = fauto->control_in_value;
2293                                 mwindow->session->drag_auto_gang->append((Auto *)keyframe);
2294                         }
2295                 }
2296         } else 
2297         if (fill_gangs == 0)      // move the gangs
2298         {
2300                 // Move the gang!
2301                 for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++)
2302                 {
2303                         FloatAuto *keyframe = (FloatAuto *)mwindow->session->drag_auto_gang->values[i];
2304                         
2305                         keyframe->value += change;
2306                         keyframe->position = fauto->position;
2307                         if(skip->data_type == TRACK_AUDIO)
2308                                 CLAMP(keyframe->value, INFINITYGAIN, MAX_AUDIO_FADE);
2309                         else
2310                                 CLAMP(keyframe->value, 0, MAX_VIDEO_FADE);
2311                         keyframe->control_out_position = fauto->control_out_position;
2312                         keyframe->control_in_position = fauto->control_in_position;
2313                         keyframe->control_out_value = fauto->control_out_value;
2314                         keyframe->control_in_value = fauto->control_in_value;
2315                 } 
2317         } else
2318         if (fill_gangs == -1)      // remove the gangs
2319         {
2320                 for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++)
2321                 {
2322                         FloatAuto *keyframe = (FloatAuto *)mwindow->session->drag_auto_gang->values[i];
2323                         keyframe->autos->remove_nonsequential(
2324                                         keyframe);
2325                 } 
2326                 mwindow->session->drag_auto_gang->remove_all();
2327         }
2331 int TrackCanvas::test_floatline(int center_pixel, 
2332                 FloatAutos *autos,
2333                 int64_t unit_start,
2334                 double zoom_units,
2335                 double yscale,
2336                 int x1,
2337                 int x2,
2338                 int cursor_x, 
2339                 int cursor_y, 
2340                 int buttonpress)
2342         int result = 0;
2345         int64_t position = (int64_t)(unit_start + cursor_x * zoom_units);
2346 // Call by reference fails for some reason here
2347         FloatAuto *previous = 0, *next = 0;
2348         float value = autos->get_value(position, PLAY_FORWARD, previous, next);
2349         int y = (int)(center_pixel + 
2350                 (autos->value_to_percentage(value) - 0.5) * -yscale);
2352         if(cursor_x >= x1 && 
2353                 cursor_x < x2 &&
2354                 cursor_y >= y - HANDLE_W / 2 && 
2355                 cursor_y < y + HANDLE_W / 2 &&
2356                 !ctrl_down())
2357         {
2358                 result = 1;
2361                 if(buttonpress)
2362                 {
2363                         mwindow->undo->update_undo_before(_("keyframe"), LOAD_AUTOMATION);
2366                         Auto *current;
2367                         current = mwindow->session->drag_auto = autos->insert_auto(position);
2368                         ((FloatAuto*)current)->value = value;
2369                         mwindow->session->drag_start_percentage = current->value_to_percentage();
2370                         mwindow->session->drag_start_position = current->position;
2371                         mwindow->session->drag_origin_x = cursor_x;
2372                         mwindow->session->drag_origin_y = cursor_y;
2373                         mwindow->session->drag_handle = 0;
2375                 }
2376         }
2379         return result;
2382 void TrackCanvas::draw_toggleline(int center_pixel, 
2383         int x1,
2384         int y1,
2385         int x2,
2386         int y2,
2387         int color)
2389         set_color(BLACK);
2390         draw_line(x1, center_pixel + y1 + 1, x2, center_pixel + y1 + 1);
2391         set_color(color);
2392         draw_line(x1, center_pixel + y1, x2, center_pixel + y1);
2394         if(y2 != y1)
2395         {
2396                 set_color(BLACK);
2397                 draw_line(x2 + 1, center_pixel + y1, x2 + 1, center_pixel + y2);
2398                 set_color(color);
2399                 draw_line(x2, center_pixel + y1, x2, center_pixel + y2);
2400         }
2403 int TrackCanvas::test_toggleline(Autos *autos,
2404         int center_pixel, 
2405         int x1,
2406         int y1,
2407         int x2,
2408         int y2, 
2409         int cursor_x, 
2410         int cursor_y, 
2411         int buttonpress)
2413         int result = 0;
2414         if(cursor_x >= x1 && cursor_x < x2)
2415         {
2416                 int miny = center_pixel + y1 - HANDLE_W / 2;
2417                 int maxy = center_pixel + y1 + HANDLE_W / 2;
2418                 if(cursor_y >= miny && cursor_y < maxy) 
2419                 {
2420                         result = 1;
2422                         if(buttonpress)
2423                         {
2424                                 mwindow->undo->update_undo_before(_("keyframe"), LOAD_AUTOMATION);
2427                                 Auto *current;
2428                                 double position = (double)(cursor_x +
2429                                                 mwindow->edl->local_session->view_start) * 
2430                                         mwindow->edl->local_session->zoom_sample / 
2431                                         mwindow->edl->session->sample_rate;
2432                                 int64_t unit_position = autos->track->to_units(position, 0);
2433                                 int new_value = (int)((IntAutos*)autos)->get_automation_constant(unit_position, unit_position);
2435                                 current = mwindow->session->drag_auto = autos->insert_auto(unit_position);
2436                                 ((IntAuto*)current)->value = new_value;
2437                                 mwindow->session->drag_start_percentage = current->value_to_percentage();
2438                                 mwindow->session->drag_start_position = current->position;
2439                                 mwindow->session->drag_origin_x = cursor_x;
2440                                 mwindow->session->drag_origin_y = cursor_y;
2442                         }
2443                 }
2444         }
2445         return result;
2448 void TrackCanvas::calculate_viewport(Track *track, 
2449         double &view_start,   // Seconds
2450         int64_t &unit_start,
2451         double &view_end,     // Seconds
2452         int64_t &unit_end,
2453         double &yscale,
2454         int &center_pixel,
2455         double &zoom_sample,
2456         double &zoom_units)
2458         view_start = (double)mwindow->edl->local_session->view_start * 
2459                 mwindow->edl->local_session->zoom_sample /
2460                 mwindow->edl->session->sample_rate;
2461         unit_start = track->to_units(view_start, 0);
2462         view_end = (double)(mwindow->edl->local_session->view_start + 
2463                 get_w()) * 
2464                 mwindow->edl->local_session->zoom_sample / 
2465                 mwindow->edl->session->sample_rate;
2466         unit_end = (int64_t)(track->to_units(view_end, 1));
2467         yscale = mwindow->edl->local_session->zoom_track;
2468         center_pixel = (int)(track->y_pixel + yscale / 2) + 
2469                 (mwindow->edl->session->show_titles ? 
2470                         mwindow->theme->title_bg_data->get_h() : 
2471                         0);
2472         zoom_sample = mwindow->edl->local_session->zoom_sample;
2474         zoom_units = track->to_doubleunits(zoom_sample / mwindow->edl->session->sample_rate);
2477 int TrackCanvas::do_float_autos(Track *track, 
2478                 Autos *autos, 
2479                 int cursor_x, 
2480                 int cursor_y, 
2481                 int draw, 
2482                 int buttonpress,
2483                 int color)
2485         int result = 0;
2487         double view_start;
2488         int64_t unit_start;
2489         double view_end;
2490         int64_t unit_end;
2491         double yscale;
2492         int center_pixel;
2493         double zoom_sample;
2494         double zoom_units;
2495         double ax, ay, ax2, ay2;
2496         double in_x2, in_y2, out_x2, out_y2;
2497         int draw_auto;
2498         double slope;
2499         int skip = 0;
2501         calculate_viewport(track, 
2502                 view_start,
2503                 unit_start,
2504                 view_end,
2505                 unit_end,
2506                 yscale,
2507                 center_pixel,
2508                 zoom_sample,
2509                 zoom_units);
2513 // Get first auto before start
2514         Auto *current = 0;
2515         Auto *previous = 0;
2516         for(current = autos->last; 
2517                 current && current->position >= unit_start; 
2518                 current = PREVIOUS)
2519                 ;
2521         if(current)
2522         {
2523                 ax = (double)(current->position - unit_start) / zoom_units;
2524                 ay = (((FloatAuto*)current)->value_to_percentage() - 0.5) * -yscale;
2525                 current = NEXT;
2526         }
2527         else
2528         {
2529                 current = autos->first ? autos->first : autos->default_auto;
2530                 if(current)
2531                 {               
2532                         ax = 0;
2533                         ay = (((FloatAuto*)current)->value_to_percentage() - 0.5) * -yscale;
2534                 }
2535                 else
2536                 {
2537                         ax = 0;
2538                         ay = 0;
2539                 }
2540         }
2543 //printf("TrackCanvas::do_float_autos 1\n");
2547         do
2548         {
2549                 skip = 0;
2550                 draw_auto = 1;
2552                 if(current)
2553                 {
2554                         ax2 = (double)(current->position - unit_start) / zoom_units;
2555                         ay2 = (((FloatAuto*)current)->value_to_percentage() - 0.5) * -yscale;
2556                         in_x2 = (double)(current->position + 
2557                                 ((FloatAuto*)current)->control_in_position - 
2558                                 unit_start) / 
2559                                 zoom_units;
2560                         in_y2 = (((FloatAuto*)current)->invalue_to_percentage() - 0.5) * -yscale;
2561                         out_x2 = (double)(current->position + 
2562                                 ((FloatAuto*)current)->control_out_position - 
2563                                 unit_start) / 
2564                                 zoom_units;
2565                         out_y2 = (((FloatAuto*)current)->outvalue_to_percentage() - 0.5) * -yscale;
2566                 }
2567                 else
2568                 {
2569                         ax2 = get_w();
2570                         ay2 = ay;
2571                         skip = 1;
2572                 }
2574                 slope = (ay2 - ay) / (ax2 - ax);
2576                 if(ax2 > get_w())
2577                 {
2578                         draw_auto = 0;
2579                         ax2 = get_w();
2580                         ay2 = ay + slope * (get_w() - ax);
2581                 }
2582                 
2583                 if(ax < 0)
2584                 {
2585                         ay = ay + slope * (0 - ax);
2586                         ax = 0;
2587                 }
2602 // Draw handle
2603                 if(current && !result)
2604                 {
2605                         if(current != autos->default_auto)
2606                         {
2607                                 if(!draw)
2608                                 {
2609                                         if(track->record)
2610                                                 result = test_floatauto(current, 
2611                                                         (int)ax2, 
2612                                                         (int)ay2, 
2613                                                         (int)in_x2,
2614                                                         (int)in_y2,
2615                                                         (int)out_x2,
2616                                                         (int)out_y2,
2617                                                         (int)center_pixel, 
2618                                                         (int)yscale, 
2619                                                         cursor_x, 
2620                                                         cursor_y, 
2621                                                         buttonpress);
2622                                 }
2623                                 else
2624                                 if(draw_auto)
2625                                         draw_floatauto(current, 
2626                                                 (int)ax2, 
2627                                                 (int)ay2, 
2628                                                 (int)in_x2,
2629                                                 (int)in_y2,
2630                                                 (int)out_x2,
2631                                                 (int)out_y2,
2632                                                 (int)center_pixel, 
2633                                                 (int)yscale,
2634                                                 color);
2635                         }
2636                 }
2642 // Draw joining line
2643                 if(!draw)
2644                 {
2645                         if(!result)
2646                         {
2647                                 if(track->record)
2648                                 {
2649                                         result = test_floatline(center_pixel, 
2650                                                 (FloatAutos*)autos,
2651                                                 unit_start,
2652                                                 zoom_units,
2653                                                 yscale,
2654                                                 (int)ax,
2655 // Exclude auto coverage from the end of the line.  The auto overlaps
2656                                                 (int)ax2 - HANDLE_W / 2,
2657                                                 cursor_x, 
2658                                                 cursor_y, 
2659                                                 buttonpress);
2660                                 }
2661                         }
2662                 }
2663                 else
2664                         draw_floatline(center_pixel,
2665                                 (FloatAuto*)previous,
2666                                 (FloatAuto*)current,
2667                                 (FloatAutos*)autos,
2668                                 unit_start,
2669                                 zoom_units,
2670                                 yscale,
2671                                 (int)ax, 
2672                                 (int)ay, 
2673                                 (int)ax2, 
2674                                 (int)ay2,
2675                                 color);
2683                 if(current)
2684                 {
2685                         previous = current;
2686                         current = NEXT;
2687                 }
2691                 ax = ax2;
2692                 ay = ay2;
2693         }while(current && 
2694                 current->position <= unit_end && 
2695                 !result);
2697 //printf("TrackCanvas::do_float_autos 100\n");
2706         if(ax < get_w() && !result)
2707         {
2708                 ax2 = get_w();
2709                 ay2 = ay;
2710                 if(!draw)
2711                 {
2712                         if(track->record)
2713                         {
2714                                 result = test_floatline(center_pixel, 
2715                                         (FloatAutos*)autos,
2716                                         unit_start,
2717                                         zoom_units,
2718                                         yscale,
2719                                         (int)ax,
2720                                         (int)ax2,
2721                                         cursor_x, 
2722                                         cursor_y, 
2723                                         buttonpress);
2724                         }
2725                 }
2726                 else
2727                         draw_floatline(center_pixel, 
2728                                 (FloatAuto*)previous,
2729                                 (FloatAuto*)current,
2730                                 (FloatAutos*)autos,
2731                                 unit_start,
2732                                 zoom_units,
2733                                 yscale,
2734                                 (int)ax, 
2735                                 (int)ay, 
2736                                 (int)ax2, 
2737                                 (int)ay2,
2738                                 color);
2739         }
2748         return result;
2752 int TrackCanvas::do_toggle_autos(Track *track, 
2753                 Autos *autos, 
2754                 int cursor_x, 
2755                 int cursor_y, 
2756                 int draw, 
2757                 int buttonpress,
2758                 int color)
2760         int result = 0;
2761         double view_start;
2762         int64_t unit_start;
2763         double view_end;
2764         int64_t unit_end;
2765         double yscale;
2766         int center_pixel;
2767         double zoom_sample;
2768         double zoom_units;
2769         double ax, ay, ax2, ay2;
2771         calculate_viewport(track, 
2772                 view_start,
2773                 unit_start,
2774                 view_end,
2775                 unit_end,
2776                 yscale,
2777                 center_pixel,
2778                 zoom_sample,
2779                 zoom_units);
2782         double high = -yscale * 0.8 / 2;
2783         double low = yscale * 0.8 / 2;
2785 // Get first auto before start
2786         Auto *current;
2787         for(current = autos->last; current && current->position >= unit_start; current = PREVIOUS)
2788                 ;
2790         if(current)
2791         {
2792                 ax = 0;
2793                 ay = ((IntAuto*)current)->value > 0 ? high : low;
2794                 current = NEXT;
2795         }
2796         else
2797         {
2798                 current = autos->first ? autos->first : autos->default_auto;
2799                 if(current)
2800                 {
2801                         ax = 0;
2802                         ay = ((IntAuto*)current)->value > 0 ? high : low;
2803                 }
2804                 else
2805                 {
2806                         ax = 0;
2807                         ay = yscale;
2808                 }
2809         }
2811         do
2812         {
2813                 if(current)
2814                 {
2815                         ax2 = (double)(current->position - unit_start) / zoom_units;
2816                         ay2 = ((IntAuto*)current)->value > 0 ? high : low;
2817                 }
2818                 else
2819                 {
2820                         ax2 = get_w();
2821                         ay2 = ay;
2822                 }
2824                 if(ax2 > get_w()) ax2 = get_w();
2826             if(current && !result) 
2827                 {
2828                         if(current != autos->default_auto)
2829                         {
2830                                 if(!draw)
2831                                 {
2832                                         if(track->record)
2833                                         {
2834                                                 result = test_auto(current, 
2835                                                         (int)ax2, 
2836                                                         (int)ay2, 
2837                                                         (int)center_pixel, 
2838                                                         (int)yscale, 
2839                                                         cursor_x, 
2840                                                         cursor_y, 
2841                                                         buttonpress);
2842                                         }
2843                                 }
2844                                 else
2845                                         draw_auto(current, 
2846                                                 (int)ax2, 
2847                                                 (int)ay2, 
2848                                                 (int)center_pixel, 
2849                                                 (int)yscale,
2850                                                 color);
2851                         }
2853                         current = NEXT;
2854                 }
2856                 if(!draw)
2857                 {
2858                         if(!result)
2859                         {
2860                                 if(track->record)
2861                                 {
2862                                         result = test_toggleline(autos, 
2863                                                 center_pixel, 
2864                                                 (int)ax, 
2865                                                 (int)ay, 
2866                                                 (int)ax2, 
2867                                                 (int)ay2,
2868                                                 cursor_x, 
2869                                                 cursor_y, 
2870                                                 buttonpress);
2871                                 }
2872                         }
2873                 }
2874                 else
2875                         draw_toggleline(center_pixel, 
2876                                 (int)ax, 
2877                                 (int)ay, 
2878                                 (int)ax2, 
2879                                 (int)ay2,
2880                                 color);
2882                 ax = ax2;
2883                 ay = ay2;
2884         }while(current && current->position <= unit_end && !result);
2886         if(ax < get_w() && !result)
2887         {
2888                 ax2 = get_w();
2889                 ay2 = ay;
2890                 if(!draw)
2891                 {
2892                         if(track->record)
2893                         {
2894                                 result = test_toggleline(autos,
2895                                         center_pixel, 
2896                                         (int)ax, 
2897                                         (int)ay, 
2898                                         (int)ax2, 
2899                                         (int)ay2,
2900                                         cursor_x, 
2901                                         cursor_y, 
2902                                         buttonpress);
2903                         }
2904                 }
2905                 else
2906                         draw_toggleline(center_pixel, 
2907                                 (int)ax, 
2908                                 (int)ay, 
2909                                 (int)ax2, 
2910                                 (int)ay2,
2911                                 color);
2912         }
2913         return result;
2916 int TrackCanvas::do_autos(Track *track, 
2917                 Autos *autos, 
2918                 int cursor_x, 
2919                 int cursor_y, 
2920                 int draw, 
2921                 int buttonpress,
2922                 BC_Pixmap *pixmap)
2924         int result = 0;
2926         double view_start;
2927         int64_t unit_start;
2928         double view_end;
2929         int64_t unit_end;
2930         double yscale;
2931         int center_pixel;
2932         double zoom_sample;
2933         double zoom_units;
2935         calculate_viewport(track, 
2936                 view_start,
2937                 unit_start,
2938                 view_end,
2939                 unit_end,
2940                 yscale,
2941                 center_pixel,
2942                 zoom_sample,
2943                 zoom_units);
2945         Auto *current;
2947         for(current = autos->first; current && !result; current = NEXT)
2948         {
2949                 if(current->position >= unit_start && current->position < unit_end)
2950                 {
2951                         int64_t x, y;
2952                         x = (int64_t)((double)(current->position - unit_start) / 
2953                                 zoom_units - (pixmap->get_w() / 2 + 0.5));
2954                         y = center_pixel - pixmap->get_h() / 2;
2956                         if(!draw)
2957                         {
2958                                 if(cursor_x >= x && cursor_y >= y &&
2959                                         cursor_x < x + pixmap->get_w() &&
2960                                         cursor_y < y + pixmap->get_h())
2961                                 {
2962                                         result = 1;
2964                                         if(buttonpress)
2965                                         {
2966                                                 mwindow->session->drag_auto = current;
2967                                                 mwindow->session->drag_start_position = current->position;
2968                                                 mwindow->session->drag_origin_x = cursor_x;
2969                                                 mwindow->session->drag_origin_y = cursor_y;
2971                                                 double position = autos->track->from_units(current->position);
2972                                                 double center = (mwindow->edl->local_session->selectionstart +
2973                                                         mwindow->edl->local_session->selectionend) / 
2974                                                         2;
2976                                                 if(!shift_down())
2977                                                 {
2978                                                         mwindow->edl->local_session->selectionstart = position;
2979                                                         mwindow->edl->local_session->selectionend = position;
2980                                                 }
2981                                                 else
2982                                                 if(position < center)
2983                                                 {
2984                                                         mwindow->edl->local_session->selectionstart = position;
2985                                                 }
2986                                                 else
2987                                                         mwindow->edl->local_session->selectionend = position;
2988                                         }
2989                                 }
2990                         }
2991                         else
2992                                 draw_pixmap(pixmap, x, y);
2993                 }
2994         }
2995         return result;
2998 int TrackCanvas::do_plugin_autos(Track *track, 
2999                 int cursor_x, 
3000                 int cursor_y, 
3001                 int draw, 
3002                 int buttonpress,
3003                 Plugin* &keyframe_plugin,
3004                 KeyFrame* &keyframe_instance)
3006         int result = 0;
3008         double view_start;
3009         int64_t unit_start;
3010         double view_end;
3011         int64_t unit_end;
3012         double yscale;
3013         int center_pixel;
3014         double zoom_sample;
3015         double zoom_units;
3017         if(!track->expand_view) return 0;
3019         calculate_viewport(track, 
3020                 view_start,
3021                 unit_start,
3022                 view_end,
3023                 unit_end,
3024                 yscale,
3025                 center_pixel,
3026                 zoom_sample,
3027                 zoom_units);
3031         for(int i = 0; i < track->plugin_set.total && !result; i++)
3032         {
3033                 PluginSet *plugin_set = track->plugin_set.values[i];
3034                 int center_pixel = (int)(track->y_pixel + 
3035                         mwindow->edl->local_session->zoom_track +
3036                         (i + 0.5) * mwindow->theme->plugin_bg_data->get_h() + 
3037                         (mwindow->edl->session->show_titles ? mwindow->theme->title_bg_data->get_h() : 0));
3039                 for(Plugin *plugin = (Plugin*)plugin_set->first; 
3040                         plugin && !result; 
3041                         plugin = (Plugin*)plugin->next)
3042                 {
3043                         for(KeyFrame *keyframe = (KeyFrame*)plugin->keyframes->first; 
3044                                 keyframe && !result; 
3045                                 keyframe = (KeyFrame*)keyframe->next)
3046                         {
3047 //printf("TrackCanvas::draw_plugin_autos 3 %d\n", keyframe->position);
3048                                 if(keyframe->position >= unit_start && keyframe->position < unit_end)
3049                                 {
3050                                         int64_t x = (int64_t)((keyframe->position - unit_start) / zoom_units);
3051                                         int y = center_pixel - keyframe_pixmap->get_h() / 2;
3053 //printf("TrackCanvas::draw_plugin_autos 4 %d %d\n", x, center_pixel);
3054                                         if(!draw)
3055                                         {
3056                                                 if(cursor_x >= x && cursor_y >= y &&
3057                                                         cursor_x < x + keyframe_pixmap->get_w() &&
3058                                                         cursor_y < y + keyframe_pixmap->get_h())
3059                                                 {
3060                                                         result = 1;
3061                                                         keyframe_plugin = plugin;
3062                                                         keyframe_instance = keyframe;
3064                                                         if(buttonpress)
3065                                                         {
3066                                                                 mwindow->session->drag_auto = keyframe;
3067                                                                 mwindow->session->drag_start_position = keyframe->position;
3068                                                                 mwindow->session->drag_origin_x = cursor_x;
3069                                                                 mwindow->session->drag_origin_y = cursor_y;
3071                                                                 double position = track->from_units(keyframe->position);
3072                                                                 double center = (mwindow->edl->local_session->selectionstart +
3073                                                                         mwindow->edl->local_session->selectionend) / 
3074                                                                         2;
3076                                                                 if(!shift_down())
3077                                                                 {
3078                                                                         mwindow->edl->local_session->selectionstart = position;
3079                                                                         mwindow->edl->local_session->selectionend = position;
3080                                                                 }
3081                                                                 else
3082                                                                 if(position < center)
3083                                                                 {
3084                                                                         mwindow->edl->local_session->selectionstart = position;
3085                                                                 }
3086                                                                 else
3087                                                                         mwindow->edl->local_session->selectionend = position;
3088                                                         }
3089                                                 }
3090                                         }
3091                                         else
3092                                                 draw_pixmap(keyframe_pixmap, 
3093                                                         x, 
3094                                                         y);
3095                                 }
3096                         }
3097                 }
3098         }
3099 //printf("TrackCanvas::draw_plugin_autos 5\n");
3100         return result;
3103 void TrackCanvas::draw_overlays()
3105         int new_cursor, update_cursor, rerender;
3106 //TRACE("TrackCanvas::draw_overlays 1")
3108 // Move background pixmap to foreground pixmap
3109         draw_pixmap(background_pixmap, 
3110                 0, 
3111                 0,
3112                 get_w(),
3113                 get_h(),
3114                 0,
3115                 0);
3116 //TRACE("TrackCanvas::draw_overlays 10")
3118 // In/Out points
3119         draw_inout_points();
3121 //TRACE("TrackCanvas::draw_overlays 11");
3122 // Transitions
3123         if(mwindow->edl->session->auto_conf->transitions) draw_transitions();
3125 //TRACE("TrackCanvas::draw_overlays 12");
3126 // Plugins
3127         draw_plugins();
3129 //TRACE("TrackCanvas::draw_overlays 13");
3130 // Loop points
3131         draw_loop_points();
3132         draw_brender_start();
3134 //TRACE("TrackCanvas::draw_overlays 14");
3135 // Highlighted areas
3136         draw_highlighting();
3138 //TRACE("TrackCanvas::draw_overlays 15");
3139 // Automation
3140         do_keyframes(0, 
3141                 0, 
3142                 1, 
3143                 0, 
3144                 new_cursor, 
3145                 update_cursor,
3146                 rerender);
3148 //TRACE("TrackCanvas::draw_overlays 16\n");
3149 // Selection cursor
3150         if(gui->cursor) gui->cursor->restore();
3152 //TRACE("TrackCanvas::draw_overlays 17\n");
3153 // Handle dragging
3154         draw_drag_handle();
3156 //TRACE("TrackCanvas::draw_overlays 20");
3157 // Playback cursor
3158         draw_playback_cursor();
3162 int TrackCanvas::activate()
3164         if(!active)
3165         {
3166                 get_top_level()->deactivate();
3167                 active = 1;
3168                 set_active_subwindow(this);
3169                 gui->cursor->activate();
3170         }
3171         return 0;
3174 int TrackCanvas::deactivate()
3176         if(active)
3177         {
3178                 active = 0;
3179                 gui->cursor->deactivate();
3180         }
3181         return 0;
3185 void TrackCanvas::update_drag_handle()
3187         double new_position;
3189         new_position = 
3190                 (double)(get_cursor_x() + mwindow->edl->local_session->view_start) *
3191                 mwindow->edl->local_session->zoom_sample /
3192                 mwindow->edl->session->sample_rate;
3193         new_position = 
3194                 mwindow->edl->align_to_frame(new_position, 0);
3197         if(new_position != mwindow->session->drag_position)
3198         {
3199                 mwindow->session->drag_position = new_position;
3200                 gui->mainclock->update(new_position);
3201 // Que the CWindow.  Doesn't do anything if selectionstart and selection end 
3202 // aren't changed.
3203 //              mwindow->cwindow->update(1, 0, 0);
3204         }
3207 int TrackCanvas::update_drag_edit()
3209         int result = 0;
3210         
3211         
3212         
3213         return result;
3216 #define UPDATE_DRAG_HEAD(do_clamp) \
3217         int result = 0; \
3218         int x = cursor_x - mwindow->session->drag_origin_x; \
3219         int y = cursor_y - mwindow->session->drag_origin_y; \
3221         if(!current->autos->track->record) return 0; \
3222         double view_start; \
3223         int64_t unit_start; \
3224         double view_end; \
3225         int64_t unit_end; \
3226         double yscale; \
3227         int center_pixel; \
3228         double zoom_sample; \
3229         double zoom_units; \
3231         mwindow->undo->update_undo_before(_("tweek"), LOAD_AUTOMATION); \
3232         calculate_viewport(current->autos->track,  \
3233                 view_start, \
3234                 unit_start, \
3235                 view_end, \
3236                 unit_end, \
3237                 yscale, \
3238                 center_pixel, \
3239                 zoom_sample, \
3240                 zoom_units); \
3242         float percentage = (float)(mwindow->session->drag_origin_y - cursor_y) / \
3243                 MAX(128, yscale) +  \
3244                 mwindow->session->drag_start_percentage; \
3245         if(do_clamp) CLAMP(percentage, 0, 1); \
3247         int64_t position = Units::to_int64(zoom_units * \
3248                 (cursor_x - mwindow->session->drag_origin_x) + \
3249                 mwindow->session->drag_start_position); \
3251         if((do_clamp) && position < 0) position = 0;
3261 int TrackCanvas::update_drag_floatauto(int cursor_x, int cursor_y)
3263         FloatAuto *current = (FloatAuto*)mwindow->session->drag_auto;
3265         UPDATE_DRAG_HEAD(mwindow->session->drag_handle == 0);
3267         float value;
3268         float old_value;
3269 //printf("TrackCanvas::update_drag_floatauto %ld %d\n", 
3270 //position, 
3271 //mwindow->session->drag_handle);
3273         switch(mwindow->session->drag_handle)
3274         {
3275 // Center
3276                 case 0:
3277 // Snap to nearby values
3278                         old_value = current->value;
3279                         if(shift_down())
3280                         {
3281                                 double value1;
3282                                 double distance1;
3283                                 double value2;
3284                                 double distance2;
3285                                 value = ((FloatAuto*)current)->percentage_to_value(percentage);
3287                                 if(current->previous)
3288                                 {
3289                                         value1 = ((FloatAuto*)current->previous)->value;
3290                                         distance1 = fabs(value - value1);
3291                                         current->value = value1;
3292                                 }
3294                                 if(current->next)
3295                                 {
3296                                         value2 = ((FloatAuto*)current->next)->value;
3297                                         distance2 = fabs(value - value2);
3298                                         if(!current->previous || distance2 < distance1)
3299                                         {
3300                                                 current->value = value2;
3301                                         }
3302                                 }
3304                                 if(!current->previous && !current->next)
3305                                 {
3306                                         current->value = ((FloatAutos*)current->autos)->default_;
3307                                 }
3308                                 value = current->value;
3309                         }
3310                         else
3311                                 value = ((FloatAuto*)current)->percentage_to_value(percentage);
3313 //printf("TrackCanvas::update_drag_floatauto 1 %f\n", value);
3314                         if(value != old_value || position != current->position)
3315                         {
3316                                 result = 1;
3317                                 float change = value - old_value;               
3318                                 current->value = value;
3319                                 current->position = position;
3320                                 synchronize_autos(change, current->autos->track, current, 0);
3322                                 char string[BCTEXTLEN], string2[BCTEXTLEN];
3323                                 Units::totext(string2, 
3324                                         current->autos->track->from_units(current->position),
3325                                         mwindow->edl->session->time_format,
3326                                         mwindow->edl->session->sample_rate,
3327                                         mwindow->edl->session->frame_rate,
3328                                         mwindow->edl->session->frames_per_foot);
3329                                 sprintf(string, "%s, %.2f", string2, current->value);
3330                                 gui->show_message(string);
3331                         }
3332                         break;
3334 // In control
3335                 case 1:
3336                         value = ((FloatAuto*)current)->percentage_to_invalue(percentage);
3337                         position = MIN(0, position);
3338                         if(value != current->control_in_value || 
3339                                 position != current->control_in_position)
3340                         {
3341                                 result = 1;
3342                                 current->control_in_value = value;
3343                                 current->control_in_position = position;
3344                                 synchronize_autos(0, current->autos->track, current, 0);
3346                                 char string[BCTEXTLEN], string2[BCTEXTLEN];
3347                                 Units::totext(string2, 
3348                                         current->autos->track->from_units(current->control_in_position),
3349                                         mwindow->edl->session->time_format,
3350                                         mwindow->edl->session->sample_rate,
3351                                         mwindow->edl->session->frame_rate,
3352                                         mwindow->edl->session->frames_per_foot);
3353                                 sprintf(string, "%s, %.2f", string2, current->control_in_value);
3354                                 gui->show_message(string);
3355                         }
3356                         break;
3358 // Out control
3359                 case 2:
3360                         value = ((FloatAuto*)current)->percentage_to_outvalue(percentage);
3361                         position = MAX(0, position);
3362                         if(value != current->control_out_value || 
3363                                 position != current->control_out_position)
3364                         {
3365                                 result = 1;
3366                                 current->control_out_value = value;
3367                                 current->control_out_position = position;
3368                                 synchronize_autos(0, current->autos->track, current, 0);
3370                                 char string[BCTEXTLEN], string2[BCTEXTLEN];
3371                                 Units::totext(string2, 
3372                                         current->autos->track->from_units(
3373                                                 ((FloatAuto*)current)->control_out_position),
3374                                         mwindow->edl->session->time_format,
3375                                         mwindow->edl->session->sample_rate,
3376                                         mwindow->edl->session->frame_rate,
3377                                         mwindow->edl->session->frames_per_foot);
3378                                 sprintf(string, "%s, %.2f", 
3379                                         string2, 
3380                                         ((FloatAuto*)current)->control_out_value);
3381                                 gui->show_message(string);
3382                         }
3383                         break;
3384         }
3386         return result;
3389 int TrackCanvas::update_drag_toggleauto(int cursor_x, int cursor_y)
3391         IntAuto *current = (IntAuto*)mwindow->session->drag_auto;
3393         UPDATE_DRAG_HEAD(1);
3395         int value = ((IntAuto*)current)->percentage_to_value(percentage);
3397         if(value != current->value || position != current->position)
3398         {
3399                 result = 1;
3400                 current->value = value;
3401                 current->position = position;
3403                 char string[BCTEXTLEN], string2[BCTEXTLEN];
3404                 Units::totext(string2, 
3405                         current->autos->track->from_units(current->position),
3406                         mwindow->edl->session->time_format,
3407                         mwindow->edl->session->sample_rate,
3408                         mwindow->edl->session->frame_rate,
3409                         mwindow->edl->session->frames_per_foot);
3410                 sprintf(string, "%s, %d", string2, current->value);
3411                 gui->show_message(string);
3412         }
3414         return result;
3417 // Autos which can't change value through dragging.
3419 int TrackCanvas::update_drag_auto(int cursor_x, int cursor_y)
3421         Auto *current = (Auto*)mwindow->session->drag_auto;
3423         UPDATE_DRAG_HEAD(1)
3425         if(position != current->position)
3426         {
3427                 result = 1;
3428                 current->position = position;
3430                 char string[BCTEXTLEN];
3431                 Units::totext(string, 
3432                         current->autos->track->from_units(current->position),
3433                         mwindow->edl->session->time_format,
3434                         mwindow->edl->session->sample_rate,
3435                         mwindow->edl->session->frame_rate,
3436                         mwindow->edl->session->frames_per_foot);
3437                 gui->show_message(string);
3439                 double position_f = current->autos->track->from_units(current->position);
3440                 double center_f = (mwindow->edl->local_session->selectionstart +
3441                         mwindow->edl->local_session->selectionend) / 
3442                         2;
3443                 if(!shift_down())
3444                 {
3445                         mwindow->edl->local_session->selectionstart = position_f;
3446                         mwindow->edl->local_session->selectionend = position_f;
3447                 }
3448                 else
3449                 if(position_f < center_f)
3450                 {
3451                         mwindow->edl->local_session->selectionstart = position_f;
3452                 }
3453                 else
3454                         mwindow->edl->local_session->selectionend = position_f;
3455         }
3458         return result;
3461 void TrackCanvas::update_drag_caption()
3463         switch(mwindow->session->current_operation)
3464         {
3465                 case DRAG_FADE:
3466                         
3467                         break;
3468         }
3473 int TrackCanvas::cursor_motion_event()
3475         int result, cursor_x, cursor_y;
3476         int update_clock = 0;
3477         int update_zoom = 0;
3478         int update_scroll = 0;
3479         int update_overlay = 0;
3480         int update_cursor = 0;
3481         int new_cursor = 0;
3482         int rerender = 0;
3483         double position = 0;
3484 //printf("TrackCanvas::cursor_motion_event 1\n");
3485         result = 0;
3487 // Default cursor
3488         switch(mwindow->edl->session->editing_mode)
3489         {
3490                 case EDITING_ARROW: new_cursor = ARROW_CURSOR; break;
3491                 case EDITING_IBEAM: new_cursor = IBEAM_CURSOR; break;
3492         }
3494         switch(mwindow->session->current_operation)
3495         {
3496                 case DRAG_EDITHANDLE1:
3497 // Outside threshold.  Upgrade status
3498 //printf("TrackCanvas::cursor_motion_event 1\n");
3499                         if(labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W)
3500                         {
3501 //printf("TrackCanvas::cursor_motion_event 2\n");
3502                                 mwindow->session->current_operation = DRAG_EDITHANDLE2;
3503                                 update_overlay = 1;
3504                         }
3505                         break;
3507                 case DRAG_EDITHANDLE2:
3508                         update_drag_handle();
3509                         update_overlay = 1;
3510                         break;
3512                 case DRAG_PLUGINHANDLE1:
3513                         if(labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W)
3514                         {
3515 //printf("TrackCanvas::cursor_motion_event 2\n");
3516                                 mwindow->session->current_operation = DRAG_PLUGINHANDLE2;
3517                                 update_overlay = 1;
3518                         }
3519                         break;
3521                 case DRAG_PLUGINHANDLE2:
3522                         update_drag_handle();
3523                         update_overlay = 1;
3524                         break;
3526 // Rubber band curves
3527                 case DRAG_FADE:
3528                         rerender = update_overlay = update_drag_floatauto(get_cursor_x(), get_cursor_y());
3529                         break;
3531                 case DRAG_CZOOM:
3532                         rerender = update_overlay = update_drag_floatauto(get_cursor_x(), get_cursor_y());
3533                         break;
3535                 case DRAG_PZOOM:
3536                         rerender = update_overlay = update_drag_floatauto(get_cursor_x(), get_cursor_y());
3537                         break;
3539                 case DRAG_PLAY:
3540                         rerender = update_overlay = update_drag_toggleauto(get_cursor_x(), get_cursor_y());
3541                         break;
3543                 case DRAG_MUTE:
3544                         rerender = update_overlay = update_drag_toggleauto(get_cursor_x(), get_cursor_y());
3545                         break;
3547 // Keyframe icons are sticky
3548                 case DRAG_PAN_PRE:
3549                 case DRAG_CAMERA_PRE:
3550                 case DRAG_MASK_PRE:
3551                 case DRAG_MODE_PRE:
3552                 case DRAG_PROJECTOR_PRE:
3553                 case DRAG_PLUGINKEY_PRE:
3554                         if(labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W)
3555                         {
3556 //printf("TrackCanvas::cursor_motion_event 2\n");
3557                                 mwindow->session->current_operation++;
3558                                 update_overlay = 1;
3559                         }
3560                         break;
3562                 case DRAG_PAN:
3563                 case DRAG_CAMERA:
3564                 case DRAG_MASK:
3565                 case DRAG_MODE:
3566                 case DRAG_PROJECTOR:
3567                 case DRAG_PLUGINKEY:
3568                         rerender = update_overlay = 
3569                                 update_drag_auto(get_cursor_x(), get_cursor_y());
3570                         break;
3572                 case SELECT_REGION:
3573                 {
3574                         cursor_x = get_cursor_x();
3575                         cursor_y = get_cursor_y();
3576                         position = (double)(cursor_x + mwindow->edl->local_session->view_start) * 
3577                                 mwindow->edl->local_session->zoom_sample /
3578                                 mwindow->edl->session->sample_rate;
3580                         position = mwindow->edl->align_to_frame(position, 0);
3581                         position = MAX(position, 0);
3583                         if(position < selection_midpoint1)
3584                         {
3585                                 mwindow->edl->local_session->selectionend = selection_midpoint1;
3586                                 mwindow->edl->local_session->selectionstart = position;
3587 // Que the CWindow
3588                                 mwindow->cwindow->update(1, 0, 0, 0, 1);
3589 // Update the faders
3590                                 mwindow->update_plugin_guis();
3591                                 gui->patchbay->update();
3592                         }
3593                         else
3594                         {
3595                                 mwindow->edl->local_session->selectionstart = selection_midpoint1;
3596                                 mwindow->edl->local_session->selectionend = position;
3597 // Don't que the CWindow
3598                         }
3599 //printf("TrackCanvas::cursor_motion_event 1 %f %f %f\n", position, mwindow->edl->local_session->selectionstart, mwindow->edl->local_session->selectionend);
3601                         gui->cursor->hide();
3602                         gui->cursor->draw();
3603                         flash();
3604                         result = 1;
3605                         update_clock = 1;
3606                         update_zoom = 1;
3607                         update_scroll = 1;
3608                         break;
3609                 }
3611                 default:
3612                         if(is_event_win() && cursor_inside())
3613                         {
3614 // Update clocks
3615                                 cursor_x = get_cursor_x();
3616                                 position = (double)cursor_x * 
3617                                         (double)mwindow->edl->local_session->zoom_sample / 
3618                                         (double)mwindow->edl->session->sample_rate + 
3619                                         (double)mwindow->edl->local_session->view_start * 
3620                                         (double)mwindow->edl->local_session->zoom_sample / 
3621                                         (double)mwindow->edl->session->sample_rate;
3622                                 position = mwindow->edl->align_to_frame(position, 0);
3623                                 update_clock = 1;
3625 // Update cursor
3626                                 if(mwindow->edl->session->auto_conf->transitions && 
3627                                         test_transitions(get_cursor_x(), 
3628                                                 get_cursor_y(), 
3629                                                 0, 
3630                                                 new_cursor, 
3631                                                 update_cursor))
3632                                 {
3633                                         break;
3634                                 }
3635                                 else
3636 // Update cursor
3637                                 if(do_keyframes(get_cursor_x(), 
3638                                         get_cursor_y(), 
3639                                         0, 
3640                                         0, 
3641                                         new_cursor,
3642                                         update_cursor,
3643                                         rerender))
3644                                 {
3645                                         break;
3646                                 }
3647                                 else
3648 // Edit boundaries
3649                                 if(test_edit_handles(get_cursor_x(), 
3650                                         get_cursor_y(), 
3651                                         0, 
3652                                         new_cursor,
3653                                         update_cursor))
3654                                 {
3655                                         break;
3656                                 }
3657                                 else
3658 // Plugin boundaries
3659                                 if(test_plugin_handles(get_cursor_x(), 
3660                                         get_cursor_y(), 
3661                                         0, 
3662                                         new_cursor,
3663                                         update_cursor))
3664                                 {
3665                                         break;
3666                                 }
3667                                 else
3668                                 if(test_edits(get_cursor_x(), 
3669                                         get_cursor_y(), 
3670                                         0, 
3671                                         0, 
3672                                         update_overlay, 
3673                                         rerender,
3674                                         new_cursor,
3675                                         update_cursor))
3676                                 {
3677                                         break;
3678                                 }
3679                         }
3680                         break;
3681         }
3683 //printf("TrackCanvas::cursor_motion_event 1\n");
3684         if(update_cursor && new_cursor != get_cursor())
3685         {
3686                 set_cursor(new_cursor);
3687         }
3689 //printf("TrackCanvas::cursor_motion_event 1 %d\n", rerender);
3690         if(rerender)
3691         {
3692                 mwindow->restart_brender();
3693                 mwindow->sync_parameters(CHANGE_PARAMS);
3694                 mwindow->update_plugin_guis();
3695                 mwindow->cwindow->update(1, 0, 0, 0, 1);
3696 // Update faders
3697                 gui->patchbay->update();
3698         }
3701         if(update_clock)
3702         {
3703                 if(!mwindow->cwindow->playback_engine->is_playing_back)
3704                         gui->mainclock->update(position);
3705         }
3707         if(update_zoom)
3708         {
3709                 gui->zoombar->update();
3710         }
3712         if(update_scroll)
3713         {
3714                 if(!drag_scroll && 
3715                         (cursor_x >= get_w() || cursor_x < 0 || cursor_y >= get_h() || cursor_y < 0))
3716                         start_dragscroll();
3717                 else
3718                 if(drag_scroll &&
3719                         (cursor_x < get_w() && cursor_x >= 0 && cursor_y < get_h() && cursor_y >= 0))
3720                         stop_dragscroll();
3721         }
3723         if(update_overlay)
3724         {
3725                 draw_overlays();
3726                 flash();
3727                 flush();
3728         }
3731 //printf("TrackCanvas::cursor_motion_event 100\n");
3732         return result;
3735 void TrackCanvas::start_dragscroll()
3737         if(!drag_scroll)
3738         {
3739                 drag_scroll = 1;
3740                 set_repeat(BC_WindowBase::get_resources()->scroll_repeat);
3741 //printf("TrackCanvas::start_dragscroll 1\n");
3742         }
3745 void TrackCanvas::stop_dragscroll()
3747         if(drag_scroll)
3748         {
3749                 drag_scroll = 0;
3750                 unset_repeat(BC_WindowBase::get_resources()->scroll_repeat);
3751 //printf("TrackCanvas::stop_dragscroll 1\n");
3752         }
3755 int TrackCanvas::repeat_event(int64_t duration)
3757         if(!drag_scroll) return 0;
3758         if(duration != BC_WindowBase::get_resources()->scroll_repeat) return 0;
3760         int sample_movement = 0;
3761         int track_movement = 0;
3762         int64_t x_distance = 0;
3763         int64_t y_distance = 0;
3764         double position = 0;
3765         int result = 0;
3767         switch(mwindow->session->current_operation)
3768         {
3769                 case SELECT_REGION:
3770 //printf("TrackCanvas::repeat_event 1 %d\n", mwindow->edl->local_session->view_start);
3771                         if(get_cursor_x() > get_w())
3772                         {
3773                                 x_distance = get_cursor_x() - get_w();
3774                                 sample_movement = 1;
3775                         }
3776                         else
3777                         if(get_cursor_x() < 0)
3778                         {
3779                                 x_distance = get_cursor_x();
3780                                 sample_movement = 1;
3781                         }
3783                         if(get_cursor_y() > get_h())
3784                         {
3785                                 y_distance = get_cursor_y() - get_h();
3786                                 track_movement = 1;
3787                         }
3788                         else
3789                         if(get_cursor_y() < 0)
3790                         {
3791                                 y_distance = get_cursor_y();
3792                                 track_movement = 1;
3793                         }
3794                         result = 1;
3795                         break;
3796         }
3799         if(sample_movement)
3800         {
3801                 position = (double)(get_cursor_x() + 
3802                         mwindow->edl->local_session->view_start + 
3803                         x_distance) * 
3804                         mwindow->edl->local_session->zoom_sample /
3805                         mwindow->edl->session->sample_rate;
3806                 position = mwindow->edl->align_to_frame(position, 0);
3807                 position = MAX(position, 0);
3809 //printf("TrackCanvas::repeat_event 1 %f\n", position);
3810                 switch(mwindow->session->current_operation)
3811                 {
3812                         case SELECT_REGION:
3813                                 if(position < selection_midpoint1)
3814                                 {
3815                                         mwindow->edl->local_session->selectionend = selection_midpoint1;
3816                                         mwindow->edl->local_session->selectionstart = position;
3817 // Que the CWindow
3818                                         mwindow->cwindow->update(1, 0, 0);
3819 // Update the faders
3820                                         mwindow->update_plugin_guis();
3821                                         gui->patchbay->update();
3822                                 }
3823                                 else
3824                                 {
3825                                         mwindow->edl->local_session->selectionstart = selection_midpoint1;
3826                                         mwindow->edl->local_session->selectionend = position;
3827 // Don't que the CWindow
3828                                 }
3829                                 break;
3830                 }
3832                 mwindow->samplemovement(mwindow->edl->local_session->view_start + 
3833                         x_distance);
3834         }
3836         if(track_movement)
3837         {
3838                 mwindow->trackmovement(mwindow->edl->local_session->track_start + 
3839                         y_distance);
3840         }
3842         return result;
3845 int TrackCanvas::button_release_event()
3847         int redraw = 0, update_overlay = 0, result = 0;
3849         switch(mwindow->session->current_operation)
3850         {
3851                 case DRAG_EDITHANDLE2:
3852                         mwindow->session->current_operation = NO_OPERATION;
3853                         drag_scroll = 0;
3854                         result = 1;
3855                         
3856                         end_edithandle_selection();
3857                         break;
3859                 case DRAG_EDITHANDLE1:
3860                         mwindow->session->current_operation = NO_OPERATION;
3861                         drag_scroll = 0;
3862                         result = 1;
3863                         break;
3865                 case DRAG_PLUGINHANDLE2:
3866                         mwindow->session->current_operation = NO_OPERATION;
3867                         drag_scroll = 0;
3868                         result = 1;
3869                         
3870                         end_pluginhandle_selection();
3871                         break;
3873                 case DRAG_PLUGINHANDLE1:
3874                         mwindow->session->current_operation = NO_OPERATION;
3875                         drag_scroll = 0;
3876                         result = 1;
3877                         break;
3879                 case DRAG_FADE:
3880                         synchronize_autos(0, 0, 0, -1); // delete the drag_auto_gang first and remove out of order keys
3881                 case DRAG_CZOOM:
3882                 case DRAG_PZOOM:
3883                 case DRAG_PLAY:
3884                 case DRAG_MUTE:
3885                 case DRAG_MASK:
3886                 case DRAG_MODE:
3887                 case DRAG_PAN:
3888                 case DRAG_CAMERA:
3889                 case DRAG_PROJECTOR:
3890                 case DRAG_PLUGINKEY:
3891                         mwindow->session->current_operation = NO_OPERATION;
3892                         mwindow->session->drag_handle = 0;
3893 // Remove any out-of-order keyframe
3894                         if(mwindow->session->drag_auto)
3895                         {
3896                                 mwindow->session->drag_auto->autos->remove_nonsequential(
3897                                         mwindow->session->drag_auto);
3898 //                              mwindow->session->drag_auto->autos->optimize();
3899                                 update_overlay = 1;
3900                         }
3901                         mwindow->undo->update_undo_after();
3902                         result = 1;
3903                         break;
3905                 case DRAG_EDIT:
3906                 case DRAG_AEFFECT_COPY:
3907                 case DRAG_VEFFECT_COPY:
3908 // Trap in drag stop
3910                         break;
3913                 default:
3914                         if(mwindow->session->current_operation)
3915                         {
3916                                 mwindow->session->current_operation = NO_OPERATION;
3917                                 drag_scroll = 0;
3918 // Traps button release events
3919 //                              result = 1;
3920                         }
3921                         break;
3922         }
3923         if (result) 
3924                 cursor_motion_event();
3925         if(update_overlay)
3926         {
3927                 draw_overlays();
3928                 flash();
3929                 flush();
3930         }
3931         if(redraw)
3932         {
3933                 draw();
3934                 flash();
3935                 flush();
3936         }
3937         return result;
3940 int TrackCanvas::test_edit_handles(int cursor_x, 
3941         int cursor_y, 
3942         int button_press, 
3943         int &new_cursor,
3944         int &update_cursor)
3946         Edit *edit_result = 0;
3947         int handle_result = 0;
3948         int result = 0;
3950         for(Track *track = mwindow->edl->tracks->first;
3951                 track && !result;
3952                 track = track->next)
3953         {
3954                 for(Edit *edit = track->edits->first;
3955                         edit && !result;
3956                         edit = edit->next)
3957                 {
3958                         int64_t edit_x, edit_y, edit_w, edit_h;
3959                         edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
3961                         if(cursor_x >= edit_x && cursor_x <= edit_x + edit_w &&
3962                                 cursor_y >= edit_y && cursor_y < edit_y + edit_h)
3963                         {
3964                                 if(cursor_x < edit_x + HANDLE_W)
3965                                 {
3966                                         edit_result = edit;
3967                                         handle_result = 0;
3968                                         result = 1;
3969                                 }
3970                                 else
3971                                 if(cursor_x >= edit_x + edit_w - HANDLE_W)
3972                                 {
3973                                         edit_result = edit;
3974                                         handle_result = 1;
3975                                         result = 1;
3976                                 }
3977                                 else
3978                                 {
3979                                         result = 0;
3980                                 }
3981                         }
3982                 }
3983         }
3985         update_cursor = 1;
3986         if(result)
3987         {
3988                 double position;
3989                 if(handle_result == 0)
3990                 {
3991                         position = edit_result->track->from_units(edit_result->startproject);
3992                         new_cursor = LEFT_CURSOR;
3993                 }
3994                 else
3995                 if(handle_result == 1)
3996                 {
3997                         position = edit_result->track->from_units(edit_result->startproject + edit_result->length);
3998                         new_cursor = RIGHT_CURSOR;
3999                 }
4001 // Reposition cursor
4002                 if(button_press)
4003                 {
4004                         mwindow->session->drag_edit = edit_result;
4005                         mwindow->session->drag_handle = handle_result;
4006                         mwindow->session->drag_button = get_buttonpress() - 1;
4007                         mwindow->session->drag_position = position;
4008                         mwindow->session->current_operation = DRAG_EDITHANDLE1;
4009                         mwindow->session->drag_origin_x = get_cursor_x();
4010                         mwindow->session->drag_origin_y = get_cursor_y();
4011                         mwindow->session->drag_start = position;
4013                         int rerender = start_selection(position);
4014                         if(rerender)
4015                                 mwindow->cwindow->update(1, 0, 0);
4016                         gui->timebar->update_highlights();
4017                         gui->zoombar->update();
4018                         gui->cursor->hide();
4019                         gui->cursor->draw();
4020                         draw_overlays();
4021                         flash();
4022                         flush();
4023                 }
4024         }
4026         return result;
4029 int TrackCanvas::test_plugin_handles(int cursor_x, 
4030         int cursor_y, 
4031         int button_press,
4032         int &new_cursor,
4033         int &update_cursor)
4035         Plugin *plugin_result = 0;
4036         int handle_result = 0;
4037         int result = 0;
4038         
4039         for(Track *track = mwindow->edl->tracks->first;
4040                 track && !result;
4041                 track = track->next)
4042         {
4043                 for(int i = 0; i < track->plugin_set.total && !result; i++)
4044                 {
4045                         PluginSet *plugin_set = track->plugin_set.values[i];
4046                         for(Plugin *plugin = (Plugin*)plugin_set->first; 
4047                                 plugin && !result; 
4048                                 plugin = (Plugin*)plugin->next)
4049                         {
4050                                 int64_t plugin_x, plugin_y, plugin_w, plugin_h;
4051                                 plugin_dimensions(plugin, plugin_x, plugin_y, plugin_w, plugin_h);
4052                                 
4053                                 if(cursor_x >= plugin_x && cursor_x <= plugin_x + plugin_w &&
4054                                         cursor_y >= plugin_y && cursor_y < plugin_y + plugin_h)
4055                                 {
4056                                         if(cursor_x < plugin_x + HANDLE_W)
4057                                         {
4058                                                 plugin_result = plugin;
4059                                                 handle_result = 0;
4060                                                 result = 1;
4061                                         }
4062                                         else
4063                                         if(cursor_x >= plugin_x + plugin_w - HANDLE_W)
4064                                         {
4065                                                 plugin_result = plugin;
4066                                                 handle_result = 1;
4067                                                 result = 1;
4068                                         }
4069                                 }
4070                         }
4071                 }
4072         }
4074 //printf("TrackCanvas::test_plugin_handles %d %d %d\n", button_press, handle_result, result);
4075         update_cursor = 1;
4076         if(result)
4077         {
4078                 double position;
4079                 if(handle_result == 0)
4080                 {
4081                         position = plugin_result->track->from_units(plugin_result->startproject);
4082                         new_cursor = LEFT_CURSOR;
4083                 }
4084                 else
4085                 if(handle_result == 1)
4086                 {
4087                         position = plugin_result->track->from_units(plugin_result->startproject + plugin_result->length);
4088                         new_cursor = RIGHT_CURSOR;
4089                 }
4090                 
4091                 if(button_press)
4092                 {
4093                         mwindow->session->drag_plugin = plugin_result;
4094                         mwindow->session->drag_handle = handle_result;
4095                         mwindow->session->drag_button = get_buttonpress() - 1;
4096                         mwindow->session->drag_position = position;
4097                         mwindow->session->current_operation = DRAG_PLUGINHANDLE1;
4098                         mwindow->session->drag_origin_x = get_cursor_x();
4099                         mwindow->session->drag_origin_y = get_cursor_y();
4100                         mwindow->session->drag_start = position;
4102                         int rerender = start_selection(position);
4103                         if(rerender) mwindow->cwindow->update(1, 0, 0);
4104                         gui->timebar->update_highlights();
4105                         gui->zoombar->update();
4106                         gui->cursor->hide();
4107                         gui->cursor->draw();
4108                         draw_overlays();
4109                         flash();
4110                         flush();
4111                 }
4112         }
4113         
4114         return result;
4118 int TrackCanvas::test_tracks(int cursor_x, 
4119                 int cursor_y,
4120                 int button_press)
4122         int result = 0;
4123         for(Track *track = mwindow->edl->tracks->first;
4124                 track && !result;
4125                 track = track->next)
4126         {
4127                 int64_t track_x, track_y, track_w, track_h;
4128                 track_dimensions(track, track_x, track_y, track_w, track_h);
4130                 if(button_press && 
4131                         get_buttonpress() == 3 &&
4132                         cursor_y >= track_y && 
4133                         cursor_y < track_y + track_h)
4134                 {
4135                         gui->edit_menu->update(track, 0);
4136                         gui->edit_menu->activate_menu();
4137                         result = 1;
4138                 }
4139         }
4140         return result;
4143 int TrackCanvas::test_edits(int cursor_x, 
4144         int cursor_y, 
4145         int button_press,
4146         int drag_start,
4147         int &redraw,
4148         int &rerender,
4149         int &new_cursor,
4150         int &update_cursor)
4152         int result = 0;
4153         int over_edit_handle = 0;
4155 //printf("TrackCanvas::test_edits 1\n");
4156         for(Track *track = mwindow->edl->tracks->first;
4157                 track && !result;
4158                 track = track->next)
4159         {
4160                 for(Edit *edit = track->edits->first;
4161                         edit && !result;
4162                         edit = edit->next)
4163                 {
4164                         int64_t edit_x, edit_y, edit_w, edit_h;
4165 //printf("TrackCanvas::test_edits 1\n");
4166                         edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
4168 // Cursor inside a track
4169 // Cursor inside an edit
4170                         if(cursor_x >= edit_x && cursor_x < edit_x + edit_w &&
4171                                 cursor_y >= edit_y && cursor_y < edit_y + edit_h)
4172                         {
4173 // Select duration of edit
4174 //printf("TrackCanvas::test_edits 2\n");
4175                                 if(button_press)
4176                                 {
4177                                         if(get_double_click() && !drag_start)
4178                                         {
4179 //printf("TrackCanvas::test_edits 3\n");
4180                                                 mwindow->edl->local_session->selectionstart = 
4181                                                         edit->track->from_units(edit->startproject);
4182                                                 mwindow->edl->local_session->selectionend = 
4183                                                         edit->track->from_units(edit->startproject) + 
4184                                                         edit->track->from_units(edit->length);
4185                                                 if(mwindow->edl->session->cursor_on_frames) 
4186                                                 {
4187                                                         mwindow->edl->local_session->selectionstart = 
4188                                                                 mwindow->edl->align_to_frame(mwindow->edl->local_session->selectionstart, 0);
4189                                                         mwindow->edl->local_session->selectionend = 
4190                                                                 mwindow->edl->align_to_frame(mwindow->edl->local_session->selectionend, 1);
4191                                                 }
4192                                                 redraw = 1;
4193                                                 rerender = 1;
4194                                                 result = 1;
4195                                         }
4196                                 }
4197                                 else
4198                                 if(drag_start)
4199                                 {
4200                                         if(mwindow->edl->session->editing_mode == EDITING_ARROW)
4201                                         {
4202 // Need to create drag window
4203                                                 mwindow->session->current_operation = DRAG_EDIT;
4204                                                 mwindow->session->drag_edit = edit;
4205 //printf("TrackCanvas::test_edits 2\n");
4207 // Drag only one edit
4208                                                 if(ctrl_down())
4209                                                 {
4210                                                         mwindow->session->drag_edits->remove_all();
4211                                                         mwindow->session->drag_edits->append(edit);
4212                                                 }
4213                                                 else
4214 // Construct list of all affected edits
4215                                                 {
4216                                                         mwindow->edl->tracks->get_affected_edits(
4217                                                                 mwindow->session->drag_edits, 
4218                                                                 edit->track->from_units(edit->startproject),
4219                                                                 edit->track);
4220                                                 }
4221                                                 mwindow->session->drag_origin_x = cursor_x;
4222                                                 mwindow->session->drag_origin_y = cursor_y;
4224                                                 drag_popup = new BC_DragWindow(gui, 
4225                                                         mwindow->theme->clip_icon, 
4226                                                         get_abs_cursor_x(0) - mwindow->theme->clip_icon->get_w() / 2,
4227                                                         get_abs_cursor_y(0) - mwindow->theme->clip_icon->get_h() / 2);
4228 //printf("TrackCanvas::test_edits 3 %p\n", drag_popup);
4230                                                 result = 1;
4231                                         }
4232                                 }
4233                         }
4234                 }
4235         }
4236         return result;
4240 int TrackCanvas::test_resources(int cursor_x, int cursor_y)
4242         return 0;
4245 int TrackCanvas::test_plugins(int cursor_x, 
4246         int cursor_y, 
4247         int drag_start,
4248         int button_press,
4249         int &redraw,
4250         int &rerender)
4252         Plugin *plugin = 0;
4253         int result = 0;
4254         int done = 0;
4255         int64_t x, y, w, h;
4256         Track *track = 0;
4258 //printf("TrackCanvas::test_plugins 1\n");
4259         for(track = mwindow->edl->tracks->first;
4260                 track && !done;
4261                 track = track->next)
4262         {
4263                 for(int i = 0; i < track->plugin_set.total && !done; i++)
4264                 {
4265                         PluginSet *plugin_set = track->plugin_set.values[i];
4266                         for(plugin = (Plugin*)plugin_set->first;
4267                                 plugin && !done;
4268                                 plugin = (Plugin*)plugin->next)
4269                         {
4270                                 plugin_dimensions(plugin, x, y, w, h);
4271                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
4272                                         MWindowGUI::visible(y, y + h, 0, get_h()))
4273                                 {
4274                                         if(cursor_x >= x && cursor_x < x + w &&
4275                                                 cursor_y >= y && cursor_y < y + h)
4276                                         {
4277                                                 done = 1;
4278                                                 break;
4279                                         }
4280                                 }
4281                         }
4282                 }
4283         }
4285 //printf("TrackCanvas::test_plugins 1\n");
4286         if(plugin)
4287         {
4288 // Start plugin popup
4289                 if(button_press)
4290                 {
4291 //printf("TrackCanvas::test_plugins 2\n");
4292                         if(get_buttonpress() == 3)
4293                         {
4294                                 gui->plugin_menu->update(plugin);
4295                                 gui->plugin_menu->activate_menu();
4296                                 result = 1;
4297                         } 
4298                         else
4299 // Select range of plugin on doubleclick over plugin
4300                         if (get_double_click() && !drag_start)
4301                         {
4302                                 mwindow->edl->local_session->selectionstart = 
4303                                         plugin->track->from_units(plugin->startproject);
4304                                 mwindow->edl->local_session->selectionend = 
4305                                         plugin->track->from_units(plugin->startproject) + 
4306                                         plugin->track->from_units(plugin->length);
4307                                 if(mwindow->edl->session->cursor_on_frames) 
4308                                 {
4309                                         mwindow->edl->local_session->selectionstart = 
4310                                                 mwindow->edl->align_to_frame(mwindow->edl->local_session->selectionstart, 0);
4311                                         mwindow->edl->local_session->selectionend = 
4312                                                 mwindow->edl->align_to_frame(mwindow->edl->local_session->selectionend, 1);
4313                                 }
4314                                 rerender = 1;
4315                                 redraw = 1;
4316                                 result = 1;
4317                         }
4318 //printf("TrackCanvas::test_plugins 3\n");
4319                 }
4320                 else
4321 // Move plugin
4322                 if(drag_start)
4323                 {
4324 //printf("TrackCanvas::test_plugins 4\n");
4325                         if(mwindow->edl->session->editing_mode == EDITING_ARROW)
4326                         {
4327 //printf("TrackCanvas::test_plugins 5\n");
4328                                 if(plugin->track->data_type == TRACK_AUDIO)
4329                                         mwindow->session->current_operation = DRAG_AEFFECT_COPY;
4330                                 else
4331                                 if(plugin->track->data_type == TRACK_VIDEO)
4332                                         mwindow->session->current_operation = DRAG_VEFFECT_COPY;
4334                                 mwindow->session->drag_plugin = plugin;
4335 //printf("TrackCanvas::test_plugins 6\n");
4341 // Create picon
4342                                 switch(plugin->plugin_type)
4343                                 {
4344                                         case PLUGIN_STANDALONE:
4345                                         {
4346                                                 PluginServer *server = mwindow->scan_plugindb(
4347                                                         plugin->title,
4348                                                         plugin->track->data_type);
4349                                                 VFrame *frame = server->picon;
4350 //printf("TrackCanvas::test_plugins 7\n");
4351                                                 drag_popup = new BC_DragWindow(gui, 
4352                                                         frame, 
4353                                                         get_abs_cursor_x(0) - frame->get_w() / 2,
4354                                                         get_abs_cursor_y(0) - frame->get_h() / 2);
4355                                                 break;
4356                                         }
4357                                         
4358                                         case PLUGIN_SHAREDPLUGIN:
4359                                         case PLUGIN_SHAREDMODULE:
4360                                                 drag_popup = new BC_DragWindow(gui, 
4361                                                         mwindow->theme->clip_icon, 
4362                                                         get_abs_cursor_x(0) - mwindow->theme->clip_icon->get_w() / 2,
4363                                                         get_abs_cursor_y(0) - mwindow->theme->clip_icon->get_h() / 2);
4364                                                 break;
4365 //printf("test plugins %d %p\n", mwindow->edl->session->editing_mode, mwindow->session->drag_plugin);
4366                                 }
4368 //printf("TrackCanvas::test_plugins 9 %p\n");
4370 //printf("TrackCanvas::test_plugins 10\n");
4371                                 result = 1;
4372                         }
4373                 }
4374         }
4376 //printf("TrackCanvas::test_plugins 11\n");
4377         return result;
4380 int TrackCanvas::test_transitions(int cursor_x, 
4381         int cursor_y, 
4382         int button_press,
4383         int &new_cursor,
4384         int &update_cursor)
4386         Transition *transition = 0;
4387         int result = 0;
4388         int64_t x, y, w, h;
4389         
4390         for(Track *track = mwindow->edl->tracks->first;
4391                 track && !result;
4392                 track = track->next)
4393         {
4394                 for(Edit *edit = track->edits->first;
4395                         edit;
4396                         edit = edit->next)
4397                 {
4398                         if(edit->transition)
4399                         {
4400                                 edit_dimensions(edit, x, y, w, h);
4401                                 get_transition_coords(x, y, w, h);
4403                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
4404                                         MWindowGUI::visible(y, y + h, 0, get_h()))
4405                                 {
4406                                         if(cursor_x >= x && cursor_x < x + w &&
4407                                                 cursor_y >= y && cursor_y < y + h)
4408                                         {
4409                                                 transition = edit->transition;
4410                                                 result = 1;
4411                                                 break;
4412                                         }
4413                                 }
4414                         }
4415                 }
4416         }
4417         
4418         update_cursor = 1;
4419         if(transition)
4420         {
4421                 if(!button_press)
4422                 {
4423                         new_cursor = UPRIGHT_ARROW_CURSOR;
4424                 }
4425                 else
4426                 if(get_buttonpress() == 3)
4427                 {
4428                         gui->transition_menu->update(transition);
4429                         gui->transition_menu->activate_menu();
4430                 }
4431         }
4433         return result;
4436 int TrackCanvas::button_press_event()
4438         int result = 0;
4439         int cursor_x, cursor_y;
4440         int new_cursor, update_cursor;
4442 //printf("TrackCanvas::button_press_event 1\n");
4443         cursor_x = get_cursor_x();
4444         cursor_y = get_cursor_y();
4446         if(is_event_win() && cursor_inside())
4447         {
4448                 if(!active)
4449                 {
4450                         activate();
4451                 }
4453                 if(get_buttonpress() == 1)
4454                 {
4455                         gui->unlock_window();
4456                         gui->mbuttons->transport->handle_transport(STOP, 1);
4457                         gui->lock_window("TrackCanvas::button_press_event");
4458                 }
4460                 int update_overlay = 0, update_cursor = 0, rerender = 0;
4462                 if(get_buttonpress() == 4)
4463                 {
4464 //printf("TrackCanvas::button_press_event 1\n");
4465                         mwindow->move_up(get_h() / 10);
4466                         result = 1;
4467                 }
4468                 else
4469                 if(get_buttonpress() == 5)
4470                 {
4471 //printf("TrackCanvas::button_press_event 2\n");
4472                         mwindow->move_down(get_h() / 10);
4473                         result = 1;
4474                 }
4475                 else
4476                 switch(mwindow->edl->session->editing_mode)
4477                 {
4478 // Test handles and resource boundaries and highlight a track
4479                         case EDITING_ARROW:
4480                         {
4481                                 Edit *edit;
4482                                 int handle;
4483                                 if(mwindow->edl->session->auto_conf->transitions && 
4484                                         test_transitions(cursor_x, 
4485                                                 cursor_y, 
4486                                                 1, 
4487                                                 new_cursor, 
4488                                                 update_cursor))
4489                                 {
4490                                         break;
4491                                 }
4492                                 else
4493                                 if(do_keyframes(cursor_x, 
4494                                         cursor_y, 
4495                                         0, 
4496                                         get_buttonpress(), 
4497                                         new_cursor, 
4498                                         update_cursor,
4499                                         rerender))
4500                                 {
4501                                         break;
4502                                 }
4503                                 else
4504 // Test edit boundaries
4505                                 if(test_edit_handles(cursor_x, cursor_y, 1, new_cursor, update_cursor))
4506                                 {
4507                                         break;
4508                                 }
4509                                 else
4510 // Test plugin boundaries
4511                                 if(test_plugin_handles(cursor_x, cursor_y, 1, new_cursor, update_cursor))
4512                                 {
4513                                         break;
4514                                 }
4515                                 else
4516                                 if(test_edits(cursor_x, cursor_y, 1, 0, update_cursor, rerender, new_cursor, update_cursor))
4517                                 {
4518                                         break;
4519                                 }
4520                                 else
4521                                 if(test_plugins(cursor_x, cursor_y, 0, 1, update_cursor, rerender))
4522                                 {
4523                                         break;
4524                                 }
4525                                 else
4526                                 if(test_resources(cursor_x, cursor_y))
4527                                 {
4528                                         break;
4529                                 }
4530                                 else
4531                                 if(test_tracks(cursor_x, cursor_y, 1))
4532                                 {
4533                                         break;
4534                                 }
4535                                 break;
4536                         }
4538 // Test handles only and select a region
4539                         case EDITING_IBEAM:
4540                         {
4541                                 double position = (double)cursor_x * 
4542                                         mwindow->edl->local_session->zoom_sample /
4543                                         mwindow->edl->session->sample_rate + 
4544                                         (double)mwindow->edl->local_session->view_start * 
4545                                         mwindow->edl->local_session->zoom_sample /
4546                                         mwindow->edl->session->sample_rate;
4547 //printf("TrackCanvas::button_press_event %d\n", position);
4549                                 if(mwindow->edl->session->auto_conf->transitions && 
4550                                         test_transitions(cursor_x, 
4551                                                 cursor_y, 
4552                                                 1, 
4553                                                 new_cursor, 
4554                                                 update_cursor))
4555                                 {
4556                                         break;
4557                                 }
4558                                 else
4559                                 if(do_keyframes(cursor_x, 
4560                                         cursor_y, 
4561                                         0, 
4562                                         get_buttonpress(), 
4563                                         new_cursor, 
4564                                         update_cursor,
4565                                         rerender))
4566                                 {
4567                                         update_overlay = 1;
4568                                         break;
4569                                 }
4570                                 else
4571 // Test edit boundaries
4572                                 if(test_edit_handles(cursor_x, cursor_y, 1, new_cursor, update_cursor))
4573                                 {
4574                                         break;
4575                                 }
4576                                 else
4577 // Test plugin boundaries
4578                                 if(test_plugin_handles(cursor_x, cursor_y, 1, new_cursor, update_cursor))
4579                                 {
4580                                         break;
4581                                 }
4582                                 else
4583                                 if(test_edits(cursor_x, cursor_y, 1, 0, update_cursor, rerender, new_cursor, update_cursor))
4584                                 {
4585                                         break;
4586                                 }
4587                                 else
4588                                 if(test_plugins(cursor_x, cursor_y, 0, 1, update_cursor, rerender))
4589                                 {
4590                                         break;
4591                                 }
4592                                 else
4593                                 if(test_tracks(cursor_x, cursor_y, 1))
4594                                 {
4595                                         break;
4596                                 }
4597 // Highlight selection
4598                                 else
4599                                 {
4600                                         rerender = start_selection(position);
4601                                         mwindow->session->current_operation = SELECT_REGION;
4602                                         update_cursor = 1;
4603                                 }
4605                                 break;
4606                         }
4607                 }
4610                 if(rerender)
4611                 {
4612                         mwindow->cwindow->update(1, 0, 0, 0, 1);
4613 // Update faders
4614                         mwindow->update_plugin_guis();
4615                         gui->patchbay->update();
4616                 }
4618                 if(update_overlay)
4619                 {
4620                         draw_overlays();
4621                         flash();
4622                 }
4624                 if(update_cursor)
4625                 {
4626                         gui->timebar->update_highlights();
4627                         gui->cursor->hide();
4628                         gui->cursor->show();
4629                         gui->zoombar->update();
4630                         flash();
4631                         result = 1;
4632                 }
4636         }
4637         return result;
4640 int TrackCanvas::start_selection(double position)
4642         int rerender = 0;
4643         position = mwindow->edl->align_to_frame(position, 0);
4645 // Extend a border
4646         if(shift_down())
4647         {
4648                 double midpoint = (mwindow->edl->local_session->selectionstart + 
4649                         mwindow->edl->local_session->selectionend) / 2;
4651                 if(position < midpoint)
4652                 {
4653                         mwindow->edl->local_session->selectionstart = position;
4654                         selection_midpoint1 = mwindow->edl->local_session->selectionend;
4655 // Que the CWindow
4656                         rerender = 1;
4657                 }
4658                 else
4659                 {
4660                         mwindow->edl->local_session->selectionend = position;
4661                         selection_midpoint1 = mwindow->edl->local_session->selectionstart;
4662 // Don't que the CWindow for the end
4663                 }
4664         }
4665         else
4666 // Start a new selection
4667         {
4668 //printf("TrackCanvas::start_selection %f\n", position);
4669                 mwindow->edl->local_session->selectionstart = 
4670                         mwindow->edl->local_session->selectionend = 
4671                         position;
4672                 selection_midpoint1 = position;
4673 // Que the CWindow
4674                 rerender = 1;
4675         }
4676         
4677         return rerender;
4680 void TrackCanvas::end_edithandle_selection()
4682         mwindow->modify_edithandles();
4685 void TrackCanvas::end_pluginhandle_selection()
4687         mwindow->modify_pluginhandles();
4691 double TrackCanvas::time_visible()
4693         return (double)get_w() * 
4694                 mwindow->edl->local_session->zoom_sample / 
4695                 mwindow->edl->session->sample_rate;
4738 void TrackCanvas::draw_automation()
4743 int TrackCanvas::set_index_file(int flash, Asset *asset)
4745         return 0;
4749 int TrackCanvas::button_release()
4751         return 0;
4755 int TrackCanvas::auto_reposition(int &cursor_x, int &cursor_y, int64_t cursor_position)
4757         return 0;
4761 int TrackCanvas::draw_floating_handle(int flash)
4763         return 0;
4766 int TrackCanvas::draw_loop_point(int64_t position, int flash)
4768         return 0;
4771 int TrackCanvas::draw_playback_cursor(int pixel, int flash)
4773         return 0;
4777 int TrackCanvas::update_handle_selection(int64_t cursor_position)
4779         return 0;
4782 int TrackCanvas::end_translation()
4784         return 0;