prevent popup deactivation while button_down
[goodguy/history.git] / cinelerra-5.0 / cinelerra / trackcanvas.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "apatchgui.inc"
23 #include "asset.h"
24 #include "autoconf.h"
25 #include "automation.h"
26 #include "bcsignals.h"
27 #include "bctimer.h"
28 #include "clip.h"
29 #include "colors.h"
30 #include "cplayback.h"
31 #include "cursors.h"
32 #include "cwindowgui.h"
33 #include "cwindow.h"
34 #include "edithandles.h"
35 #include "editpopup.h"
36 #include "edits.h"
37 #include "edl.h"
38 #include "edlsession.h"
39 #include "floatauto.h"
40 #include "floatautos.h"
41 #include "format.inc"
42 #include "indexstate.h"
43 #include "intauto.h"
44 #include "intautos.h"
45 #include "keyframe.h"
46 #include "keyframepopup.h"
47 #include "keyframes.h"
48 #include "keys.h"
49 #include "localsession.h"
50 #include "mainclock.h"
51 #include "maincursor.h"
52 #include "mainsession.h"
53 #include "mainundo.h"
54 #include "maskautos.h"
55 #include "mbuttons.h"
56 #include "mtimebar.h"
57 #include "mwindowgui.h"
58 #include "mwindow.h"
59 #include "panautos.h"
60 #include "patchbay.h"
61 #include "playbackengine.h"
62 #include "playtransport.h"
63 #include "plugin.h"
64 #include "pluginpopup.h"
65 #include "pluginserver.h"
66 #include "pluginset.h"
67 #include "plugintoggles.h"
68 #include "preferences.h"
69 #include "resourcepixmap.h"
70 #include "resourcethread.h"
71 #include "swindow.h"
72 #include "theme.h"
73 #include "trackcanvas.h"
74 #include "tracking.h"
75 #include "tracks.h"
76 #include "transition.h"
77 #include "transitionhandles.h"
78 #include "transitionpopup.h"
79 #include "transportque.h"
80 #include "vframe.h"
81 #include "vpatchgui.inc"
82 #include "zoombar.h"
83
84 #include <string.h>
85
86 //#define PIXMAP_AGE -5
87 #define PIXMAP_AGE -32
88
89 TrackCanvas::TrackCanvas(MWindow *mwindow, 
90         TimelinePane *pane, 
91         int x, 
92         int y, 
93         int w, 
94         int h)
95  : BC_SubWindow(x,
96         y,
97         w,
98         h)
99 {
100         this->mwindow = mwindow;
101         this->gui = mwindow->gui;
102         this->pane = pane;
103         
104         selection_midpoint = 0;
105         drag_scroll = 0;
106         active = 0;
107         temp_picon = 0;
108         resource_timer = new Timer;
109         hourglass_enabled = 0;
110         timebar_position = -1;
111 }
112
113 TrackCanvas::~TrackCanvas()
114 {
115 //      delete transition_handles;
116         delete edit_handles;
117         delete keyframe_pixmap;
118         delete camerakeyframe_pixmap;
119         delete modekeyframe_pixmap;
120         delete pankeyframe_pixmap;
121         delete projectorkeyframe_pixmap;
122         delete maskkeyframe_pixmap;
123         delete background_pixmap;
124         if(temp_picon) delete temp_picon;
125         delete resource_timer;
126 }
127
128 void TrackCanvas::create_objects()
129 {
130         background_pixmap = new BC_Pixmap(this, get_w(), get_h());
131 //      transition_handles = new TransitionHandles(mwindow, this);
132         edit_handles = new EditHandles(mwindow, this);
133         keyframe_pixmap = new BC_Pixmap(this, mwindow->theme->keyframe_data, PIXMAP_ALPHA);
134         camerakeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->camerakeyframe_data, PIXMAP_ALPHA);
135         modekeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->modekeyframe_data, PIXMAP_ALPHA);
136         pankeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->pankeyframe_data, PIXMAP_ALPHA);
137         projectorkeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->projectorkeyframe_data, PIXMAP_ALPHA);
138         maskkeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->maskkeyframe_data, PIXMAP_ALPHA);
139         draw();
140         update_cursor(0);
141         flash(0);
142 }
143
144 void TrackCanvas::resize_event()
145 {
146 //printf("TrackCanvas::resize_event 1\n");
147         draw(0, 0);
148         flash(0);
149 //printf("TrackCanvas::resize_event 2\n");
150 }
151
152 int TrackCanvas::keypress_event()
153 {
154         int result = 0;
155
156
157         return result;
158 }
159
160
161 int TrackCanvas::drag_stop_event()
162 {
163         return gui->drag_stop();
164 }
165
166
167 int TrackCanvas::drag_motion_event()
168 {
169         return gui->drag_motion();
170 }
171
172 int TrackCanvas::drag_motion(Track **over_track,
173         Edit **over_edit,
174         PluginSet **over_pluginset,
175         Plugin **over_plugin)
176 {
177         int cursor_x = get_relative_cursor_x();
178         int cursor_y = get_relative_cursor_y();
179
180
181         if(get_cursor_over_window() &&
182                 cursor_x >= 0 && 
183                 cursor_y >= 0 && 
184                 cursor_x < get_w() && 
185                 cursor_y < get_h())
186         {
187 //printf("TrackCanvas::drag_motion %d %d\n", __LINE__, pane->number);
188 // Find the edit and track the cursor is over
189                 for(Track *track = mwindow->edl->tracks->first; track; track = track->next)
190                 {
191                         int64_t track_x, track_y, track_w, track_h;
192                         track_dimensions(track, track_x, track_y, track_w, track_h);
193
194                         if(cursor_y >= track_y && 
195                                 cursor_y < track_y + track_h)
196                         {
197                                 *over_track = track;
198                                 for(Edit *edit = track->edits->first; edit; edit = edit->next)
199                                 {
200                                         int64_t edit_x, edit_y, edit_w, edit_h;
201                                         edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
202
203                                         if(cursor_x >= edit_x && 
204                                                 cursor_y >= edit_y && 
205                                                 cursor_x < edit_x + edit_w && 
206                                                 cursor_y < edit_y + edit_h)
207                                         {
208                                                 *over_edit = edit;
209                                                 break;
210                                         }
211                                 }
212
213                                 for(int i = 0; i < track->plugin_set.total; i++)
214                                 {
215                                         PluginSet *pluginset = track->plugin_set.values[i];
216                                         
217
218
219                                         for(Plugin *plugin = (Plugin*)pluginset->first;
220                                                 plugin;
221                                                 plugin = (Plugin*)plugin->next)
222                                         {
223                                                 int64_t plugin_x, plugin_y, plugin_w, plugin_h;
224                                                 plugin_dimensions(plugin, plugin_x, plugin_y, plugin_w, plugin_h);
225                                                 
226                                                 if(cursor_y >= plugin_y &&
227                                                         cursor_y < plugin_y + plugin_h)
228                                                 {
229                                                         *over_pluginset = plugin->plugin_set;
230                                                 
231                                                         if(cursor_x >= plugin_x &&
232                                                                 cursor_x < plugin_x + plugin_w)
233                                                         {
234                                                                 *over_plugin = plugin;
235                                                                 break;
236                                                         }
237                                                 }
238                                         }
239                                 }
240                                 break;
241                         }
242                 }
243         }
244
245         return 0;
246 }
247
248 int TrackCanvas::drag_stop(int *redraw)
249 {
250         int result = 0;
251         int cursor_x = get_relative_cursor_x();
252         int cursor_y = get_relative_cursor_y();
253
254
255         if(get_cursor_over_window() &&
256                 cursor_x >= 0 && 
257                 cursor_y >= 0 && 
258                 cursor_x < get_w() && 
259                 cursor_y < get_h())
260         {
261                 switch(mwindow->session->current_operation)
262                 {
263                         case DRAG_VTRANSITION:
264                         case DRAG_ATRANSITION:
265                                 if(mwindow->session->edit_highlighted)
266                                 {
267                                         if((mwindow->session->current_operation == DRAG_ATRANSITION &&
268                                                 mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
269                                                 (mwindow->session->current_operation == DRAG_VTRANSITION &&
270                                                 mwindow->session->track_highlighted->data_type == TRACK_VIDEO))
271                                         {
272                                                 mwindow->session->current_operation = NO_OPERATION;
273                                                 mwindow->paste_transition();
274                                                 result = 1;
275                                         }
276                                 }
277                                 *redraw = 1;
278                                 break;
279
280
281
282
283         // Behavior for dragged plugins is limited by the fact that a shared plugin
284         // can only refer to a standalone plugin that exists in the same position in
285         // time.  Dragging a plugin from one point in time to another can't produce
286         // a shared plugin to the original plugin.  In this case we relocate the
287         // plugin instead of sharing it.
288                         case DRAG_AEFFECT_COPY:
289                         case DRAG_VEFFECT_COPY:
290                                 if(mwindow->session->track_highlighted &&
291                                         ((mwindow->session->current_operation == DRAG_AEFFECT_COPY &&
292                                                 mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
293                                                 (mwindow->session->current_operation == DRAG_VEFFECT_COPY &&
294                                                 mwindow->session->track_highlighted->data_type == TRACK_VIDEO)))
295                                 {
296                                         mwindow->session->current_operation = NO_OPERATION;
297
298         // Insert shared plugin in source
299                                         if(mwindow->session->track_highlighted != mwindow->session->drag_plugin->track &&
300                                                 !mwindow->session->plugin_highlighted &&
301                                                 !mwindow->session->pluginset_highlighted)
302                                         {
303         // Move plugin if different startproject
304
305                                                 mwindow->move_effect(mwindow->session->drag_plugin,
306                                                         0,
307                                                         mwindow->session->track_highlighted,
308                                                         0);
309                                                 result = 1;
310                                         }
311                                         else
312         // Move source to different location
313                                         if(mwindow->session->pluginset_highlighted)
314                                         {
315                                                 if(mwindow->session->plugin_highlighted)
316                                                 {
317                                                         if(mwindow->session->plugin_highlighted !=
318                                                                 mwindow->session->drag_plugin)
319                                                         {
320                                                                 mwindow->move_effect(mwindow->session->drag_plugin,
321                                                                         mwindow->session->plugin_highlighted->plugin_set,
322                                                                         0,
323                                                                         mwindow->session->plugin_highlighted->startproject);
324                                                         }
325                                                 }
326                                                 else
327                                                 {
328                                                         mwindow->move_effect(mwindow->session->drag_plugin,
329                                                                 mwindow->session->pluginset_highlighted,
330                                                                 0,
331                                                                 mwindow->session->pluginset_highlighted->length());
332                                                 }
333                                                 result = 1;
334                                         }
335                                         else
336         // Move to a new plugin set between two edits
337                                         if(mwindow->session->edit_highlighted)
338                                         {
339                                                 mwindow->move_effect(mwindow->session->drag_plugin,
340                                                         0,
341                                                         mwindow->session->track_highlighted,
342                                                         mwindow->session->edit_highlighted->startproject);
343                                                 result = 1;
344                                         }
345                                         else
346         // Move to a new plugin set
347                                         if(mwindow->session->track_highlighted)
348                                         {
349                                                 mwindow->move_effect(mwindow->session->drag_plugin,
350                                                         0,
351                                                         mwindow->session->track_highlighted,
352                                                         0);
353                                                 result = 1;
354                                         }
355                                 }
356                                 break;
357
358                         case DRAG_AEFFECT:
359                         case DRAG_VEFFECT:
360                                 if(mwindow->session->track_highlighted && 
361                                         ((mwindow->session->current_operation == DRAG_AEFFECT &&
362                                         mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
363                                         (mwindow->session->current_operation == DRAG_VEFFECT &&
364                                         mwindow->session->track_highlighted->data_type == TRACK_VIDEO)))
365                                 {
366 // Drop all the effects
367                                         PluginSet *plugin_set = mwindow->session->pluginset_highlighted;
368                                         Track *track = mwindow->session->track_highlighted;
369                                         double start = 0;
370                                         double length = track->get_length();
371
372                                         if(mwindow->session->plugin_highlighted)
373                                         {
374                                                 start = track->from_units(mwindow->session->plugin_highlighted->startproject);
375                                                 length = track->from_units(mwindow->session->plugin_highlighted->length);
376                                                 if(length <= 0) length = track->get_length();
377                                         }
378                                         else
379                                         if(mwindow->session->pluginset_highlighted)
380                                         {
381                                                 start = track->from_units(plugin_set->length());
382                                                 length = track->get_length() - start;
383                                                 if(length <= 0) length = track->get_length();
384                                         }
385                                         else
386                                         if(mwindow->edl->local_session->get_selectionend() > 
387                                                 mwindow->edl->local_session->get_selectionstart())
388                                         {
389                                                 start = mwindow->edl->local_session->get_selectionstart();
390                                                 length = mwindow->edl->local_session->get_selectionend() - 
391                                                         mwindow->edl->local_session->get_selectionstart();
392                                         }
393         // Move to a point between two edits
394         //                              else
395         //                              if(mwindow->session->edit_highlighted)
396         //                              {
397         //                                      start = mwindow->session->track_highlighted->from_units(
398         //                                              mwindow->session->edit_highlighted->startproject);
399         //                                      length = mwindow->session->track_highlighted->from_units(
400         //                                              mwindow->session->edit_highlighted->length);
401         //                              }
402
403                                         mwindow->insert_effects_canvas(start, length);
404                                         *redraw = 1;
405                                 }
406                                 if (mwindow->session->track_highlighted)
407                                         result = 1;  // we have to cleanup
408                                 break;
409
410                         case DRAG_ASSET:
411                                 if(mwindow->session->track_highlighted)
412                                 {
413                                         int64_t position = mwindow->session->edit_highlighted ?
414                                                 mwindow->session->edit_highlighted->startproject :
415                                                 mwindow->session->track_highlighted->edits->length();
416                                         double position_f = mwindow->session->track_highlighted->from_units(position);
417                                         Track *track = mwindow->session->track_highlighted;
418                                         mwindow->paste_assets(position_f, track);
419                                         result = 1;    // need to be one no matter what, since we have track highlited so we have to cleanup....
420                                 }
421                                 break;
422
423                         case DRAG_EDIT:
424                                 mwindow->session->current_operation = NO_OPERATION;
425                                 if(mwindow->session->track_highlighted)
426                                 {
427                                         if(mwindow->session->track_highlighted->data_type == mwindow->session->drag_edit->track->data_type)
428                                         {
429                                                 int64_t position;
430                                                 double position_f = 0;
431                                                 if(mwindow->session->free_drag)
432                                                 {
433                                                         position_f = (double)(cursor_x + 
434                                                                 mwindow->edl->local_session->view_start[pane->number]) *
435                                                                 mwindow->edl->local_session->zoom_sample /
436                                                                 mwindow->edl->session->sample_rate;
437                                                 }
438                                                 else
439                                                 {
440                                                         position = mwindow->session->edit_highlighted ?
441                                                                 mwindow->session->edit_highlighted->startproject :
442                                                                 mwindow->session->track_highlighted->edits->length();
443                                                         position_f = mwindow->session->track_highlighted->from_units(position);
444                                                 }
445                                                 Track *track = mwindow->session->track_highlighted;
446                                                 mwindow->move_edits(mwindow->session->drag_edits,
447                                                         track,
448                                                         position_f);
449                                         }
450
451                                         result = 1;
452                                 }
453                                 break;
454                 }
455         }
456         
457         return result;
458 }
459
460
461 int TrackCanvas::drag_start_event()
462 {
463         int result = 0;
464         int redraw = 0;
465         int rerender = 0;
466         int new_cursor, update_cursor;
467
468         if(mwindow->session->current_operation != NO_OPERATION) return 0;
469
470         if(is_event_win())
471         {
472
473                 if(do_plugins(get_drag_x(), 
474                         get_drag_y(), 
475                         1,
476                         0,
477                         redraw,
478                         rerender))
479                 {
480                         result = 1;
481                 }
482                 else
483                 if(do_edits(get_drag_x(),
484                         get_drag_y(),
485                         0,
486                         1,
487                         redraw,
488                         rerender,
489                         new_cursor,
490                         update_cursor))
491                 {
492                         result = 1;
493                 }
494         }
495
496         if(result) mwindow->session->free_drag = ctrl_down();
497
498         return result;
499 }
500
501 int TrackCanvas::cursor_leave_event()
502 {
503 // Because drag motion calls get_cursor_over_window we can be sure that
504 // all highlights get deleted now.
505 // This ended up blocking keyboard input from the drag operations.
506         if(timebar_position >= 0)
507         {
508                 timebar_position = -1;
509                 if(pane->timebar) pane->timebar->update(1);
510         }
511         
512         return 0;
513 //      return drag_motion();
514 }
515
516
517
518
519 void TrackCanvas::draw(int mode, int hide_cursor)
520 {
521         const int debug = 0;
522
523
524 // Swap pixmap layers
525         if(get_w() != background_pixmap->get_w() ||
526                 get_h() != background_pixmap->get_h())
527         {
528                 delete background_pixmap;
529                 background_pixmap = new BC_Pixmap(this, get_w(), get_h());
530         }
531
532 // Cursor disappears after resize when this is called.
533 // Cursor doesn't redraw after editing when this isn't called.
534         if(pane->cursor && hide_cursor) pane->cursor->hide();
535         draw_top_background(get_parent(), 0, 0, get_w(), get_h(), background_pixmap);
536
537         if(debug) PRINT_TRACE
538         draw_resources(mode);
539
540         if(debug) PRINT_TRACE
541         draw_overlays();
542         if(debug) PRINT_TRACE
543 }
544
545 void TrackCanvas::update_cursor(int flush)
546 {
547         switch(mwindow->edl->session->editing_mode)
548         {
549                 case EDITING_ARROW: set_cursor(ARROW_CURSOR, 0, flush); break;
550                 case EDITING_IBEAM: set_cursor(IBEAM_CURSOR, 0, flush); break;
551         }
552 }
553
554
555 void TrackCanvas::test_timer()
556 {
557         if(resource_timer->get_difference() > 1000 && 
558                 !hourglass_enabled)
559         {
560                 start_hourglass();
561                 hourglass_enabled = 1;
562         }
563 }
564
565
566 void TrackCanvas::draw_indexes(Indexable *indexable)
567 {
568 // Don't redraw raw samples
569         IndexState *index_state = 0;
570         index_state = indexable->index_state;
571
572
573         if(index_state->index_zoom > mwindow->edl->local_session->zoom_sample)
574                 return;
575
576
577         draw_resources(0, 1, indexable);
578
579         draw_overlays();
580         flash(0);
581 }
582
583 void TrackCanvas::draw_resources(int mode, 
584         int indexes_only, 
585         Indexable *indexable)
586 {
587         const int debug = 0;
588         
589         if(debug) PRINT_TRACE
590
591         if(!mwindow->edl->session->show_assets) return;
592
593
594 // can't stop thread here, because this is called for every pane
595 //      if(mode != IGNORE_THREAD && !indexes_only)
596 //              gui->resource_thread->stop_draw(!indexes_only);
597
598         if(mode != IGNORE_THREAD && 
599                 !indexes_only &&
600                 !gui->resource_thread->interrupted)
601         {
602                 printf("TrackCanvas::draw_resources %d: called without stopping ResourceThread\n", 
603                         __LINE__);
604                 
605                 BC_Signals::dump_stack();
606         }
607         
608         if(debug) PRINT_TRACE
609
610         resource_timer->update();
611
612 // Age resource pixmaps for deletion
613         if(!indexes_only)
614                 for(int i = 0; i < gui->resource_pixmaps.total; i++)
615                         gui->resource_pixmaps.values[i]->visible--;
616
617         if(mode == FORCE_REDRAW)
618                 gui->resource_pixmaps.remove_all_objects();
619
620         if(debug) PRINT_TRACE
621
622 // Search every edit
623         for(Track *current = mwindow->edl->tracks->first;
624                 current;
625                 current = NEXT)
626         {
627                 if(debug) PRINT_TRACE
628                 for(Edit *edit = current->edits->first; edit; edit = edit->next)
629                 {
630                         if(debug) PRINT_TRACE
631                         if( current->data_type != TRACK_SUBTITLE )
632                                 if(!edit->asset && !edit->nested_edl) continue;
633                         if(indexes_only)
634                         {
635                                 if(edit->track->data_type != TRACK_AUDIO) continue;
636
637                                 if(edit->nested_edl && 
638                                         strcmp(indexable->path, edit->nested_edl->path)) continue;
639                                         
640                                 if(edit->asset &&
641                                         strcmp(indexable->path, edit->asset->path)) continue;
642                         }
643
644                         if(debug) PRINT_TRACE
645
646                         int64_t edit_x, edit_y, edit_w, edit_h;
647                         edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
648
649 // Edit is visible
650                         if(MWindowGUI::visible(edit_x, edit_x + edit_w, 0, get_w()) &&
651                                 MWindowGUI::visible(edit_y, edit_y + edit_h, 0, get_h()))
652                         {
653                                 int64_t pixmap_x, pixmap_w, pixmap_h;
654                                 if(debug) PRINT_TRACE
655
656 // Search for existing pixmap containing edit
657                                 for(int i = 0; i < gui->resource_pixmaps.total; i++)
658                                 {
659                                         ResourcePixmap* pixmap = gui->resource_pixmaps.values[i];
660 // Same pointer can be different edit if editing took place
661                                         if(pixmap->edit_id == edit->id &&
662                                                 pixmap->pane_number == pane->number)
663                                         {
664                                                 pixmap->visible = 1;
665                                                 break;
666                                         }
667                                 }
668                                 if(debug) PRINT_TRACE
669
670 // Get new size, offset of pixmap needed
671                                 get_pixmap_size(edit, 
672                                         edit_x, 
673                                         edit_w, 
674                                         pixmap_x, 
675                                         pixmap_w, 
676                                         pixmap_h);
677                                 if(debug) PRINT_TRACE
678
679 // Draw new data
680                                 if(pixmap_w && pixmap_h)
681                                 {
682 // Create pixmap if it doesn't exist
683                                         ResourcePixmap* pixmap = create_pixmap(edit, 
684                                                 edit_x, 
685                                                 pixmap_x, 
686                                                 pixmap_w, 
687                                                 pixmap_h);
688 // Resize it if it's bigger
689                                         if(pixmap_w > pixmap->pixmap_w ||
690                                                 pixmap_h > pixmap->pixmap_h)
691                                                 pixmap->resize(pixmap_w, pixmap_h);
692                                         pixmap->draw_data(this,
693                                                 edit,
694                                                 edit_x, 
695                                                 edit_w, 
696                                                 pixmap_x, 
697                                                 pixmap_w, 
698                                                 pixmap_h, 
699                                                 mode,
700                                                 indexes_only);
701 // Resize it if it's smaller
702                                         if(pixmap_w < pixmap->pixmap_w ||
703                                                 pixmap_h < pixmap->pixmap_h)
704                                                 pixmap->resize(pixmap_w, pixmap_h);
705
706 // Copy pixmap to background canvas
707                                         background_pixmap->draw_pixmap(pixmap, 
708                                                 pixmap->pixmap_x, 
709                                                 current->y_pixel - mwindow->edl->local_session->track_start[pane->number],
710                                                 pixmap->pixmap_w,
711                                                 edit_h);
712                                 }
713                                 if(debug) PRINT_TRACE
714
715                         }
716                 }
717         }
718
719
720 // Delete unused pixmaps
721         if(debug) PRINT_TRACE
722         if(!indexes_only)
723                 for(int i = gui->resource_pixmaps.total - 1; i >= 0; i--)
724                         if(gui->resource_pixmaps.values[i]->visible < PIXMAP_AGE)
725                         {
726 //printf("TrackCanvas::draw_resources %d\n", __LINE__);
727                                 delete gui->resource_pixmaps.values[i];
728                                 gui->resource_pixmaps.remove(gui->resource_pixmaps.values[i]);
729                         }
730         if(debug) PRINT_TRACE
731
732         if(hourglass_enabled) 
733         {
734                 stop_hourglass();
735                 hourglass_enabled = 0;
736         }
737         if(debug) PRINT_TRACE
738
739 // can't stop thread here, because this is called for every pane
740 //      if(mode != IGNORE_THREAD && !indexes_only)
741 //              gui->resource_thread->start_draw();
742         if(debug) PRINT_TRACE
743
744
745 }
746
747 ResourcePixmap* TrackCanvas::create_pixmap(Edit *edit, 
748         int64_t edit_x, 
749         int64_t pixmap_x, 
750         int64_t pixmap_w, 
751         int64_t pixmap_h)
752 {
753         ResourcePixmap *result = 0;
754
755         for(int i = 0; i < gui->resource_pixmaps.total; i++)
756         {
757 //printf("TrackCanvas::create_pixmap 1 %d %d\n", edit->id, resource_pixmaps.values[i]->edit->id);
758                 if(gui->resource_pixmaps.values[i]->edit_id == edit->id &&
759                         gui->resource_pixmaps.values[i]->pane_number == pane->number) 
760                 {
761                         result = gui->resource_pixmaps.values[i];
762                         break;
763                 }
764         }
765
766         if(!result)
767         {
768 //SET_TRACE
769                 result = new ResourcePixmap(mwindow, 
770                         gui, 
771                         edit,
772                         pane->number, 
773                         pixmap_w, 
774                         pixmap_h);
775 //SET_TRACE
776                 gui->resource_pixmaps.append(result);
777         }
778
779 //      result->resize(pixmap_w, pixmap_h);
780         return result;
781 }
782
783 void TrackCanvas::get_pixmap_size(Edit *edit, 
784         int64_t edit_x, 
785         int64_t edit_w, 
786         int64_t &pixmap_x, 
787         int64_t &pixmap_w,
788         int64_t &pixmap_h)
789 {
790
791 // Align x on frame boundaries
792
793
794 //      switch(edit->edits->track->data_type)
795 //      {
796 //              case TRACK_AUDIO:
797
798                         pixmap_x = edit_x;
799                         pixmap_w = edit_w;
800                         if(pixmap_x < 0)
801                         {
802                                 pixmap_w -= -edit_x;
803                                 pixmap_x = 0;
804                         }
805
806                         if(pixmap_x + pixmap_w > get_w())
807                         {
808                                 pixmap_w = get_w() - pixmap_x;
809                         }
810
811 //                      break;
812 // 
813 //              case TRACK_VIDEO:
814 //              {
815 //                      int64_t picon_w = (int64_t)(edit->picon_w() + 0.5);
816 //                      int64_t frame_w = (int64_t)(edit->frame_w() + 0.5);
817 //                      int64_t pixel_increment = MAX(picon_w, frame_w);
818 //                      int64_t pixmap_x1 = edit_x;
819 //                      int64_t pixmap_x2 = edit_x + edit_w;
820 // 
821 //                      if(pixmap_x1 < 0)
822 //                      {
823 //                              pixmap_x1 = (int64_t)((double)-edit_x / pixel_increment) * 
824 //                                      pixel_increment + 
825 //                                      edit_x;
826 //                      }
827 // 
828 //                      if(pixmap_x2 > get_w())
829 //                      {
830 //                              pixmap_x2 = (int64_t)((double)(get_w() - edit_x) / pixel_increment + 1) * 
831 //                                      pixel_increment + 
832 //                                      edit_x;
833 //                      }
834 //                      pixmap_x = pixmap_x1;
835 //                      pixmap_w = pixmap_x2 - pixmap_x1;
836 //                      break;
837 //              }
838 //      }
839
840         pixmap_h = mwindow->edl->local_session->zoom_track;
841         if(mwindow->edl->session->show_titles) pixmap_h += mwindow->theme->get_image("title_bg_data")->get_h();
842 //printf("get_pixmap_size %d %d %d %d\n", edit_x, edit_w, pixmap_x, pixmap_w);
843 }
844
845 void TrackCanvas::edit_dimensions(Edit *edit, 
846         int64_t &x, 
847         int64_t &y, 
848         int64_t &w, 
849         int64_t &h)
850 {
851 //      w = Units::round(edit->track->from_units(edit->length) * 
852 //              mwindow->edl->session->sample_rate / 
853 //              mwindow->edl->local_session->zoom_sample);
854
855         h = resource_h();
856
857         x = Units::round(edit->track->from_units(edit->startproject) * 
858                         mwindow->edl->session->sample_rate /
859                         mwindow->edl->local_session->zoom_sample - 
860                         mwindow->edl->local_session->view_start[pane->number]);
861
862 // Method for calculating w so when edits are together we never get off by one error due to rounding
863         int64_t x_next = Units::round(edit->track->from_units(edit->startproject + edit->length) * 
864                         mwindow->edl->session->sample_rate /
865                         mwindow->edl->local_session->zoom_sample - 
866                         mwindow->edl->local_session->view_start[pane->number]);
867         w = x_next - x;
868
869         y = edit->edits->track->y_pixel - mwindow->edl->local_session->track_start[pane->number];
870
871         if(mwindow->edl->session->show_titles) 
872                 h += mwindow->theme->get_image("title_bg_data")->get_h();
873 }
874
875 void TrackCanvas::track_dimensions(Track *track, int64_t &x, int64_t &y, int64_t &w, int64_t &h)
876 {
877         x = 0;
878         w = get_w();
879         y = track->y_pixel - mwindow->edl->local_session->track_start[pane->number];
880         h = track->vertical_span(mwindow->theme);
881 }
882
883
884 void TrackCanvas::draw_paste_destination()
885 {
886         int cursor_x = get_relative_cursor_x();
887         //int cursor_y = get_relative_cursor_y();
888         int current_atrack = 0;
889         int current_vtrack = 0;
890         int current_aedit = 0;
891         int current_vedit = 0;
892         int64_t w = 0;
893         int64_t x;
894         double position;
895
896 //if(pane->number == BOTTOM_RIGHT_PANE)
897 //printf("TrackCanvas::draw_paste_destination %d %p\n", __LINE__, mwindow->session->track_highlighted);
898
899         if((mwindow->session->current_operation == DRAG_ASSET &&
900                         (mwindow->session->drag_assets->total ||
901                         mwindow->session->drag_clips->total)) ||
902                 (mwindow->session->current_operation == DRAG_EDIT &&
903                         mwindow->session->drag_edits->total))
904         {
905
906                 Indexable *indexable = 0;
907                 EDL *clip = 0;
908                 //int draw_box = 0;
909
910                 if(mwindow->session->current_operation == DRAG_ASSET &&
911                         mwindow->session->drag_assets->size())
912                         indexable = mwindow->session->drag_assets->get(0);
913
914                 if(mwindow->session->current_operation == DRAG_ASSET &&
915                         mwindow->session->drag_clips->size())
916                         clip = mwindow->session->drag_clips->get(0);
917
918 // Get destination track
919                 for(Track *dest = mwindow->session->track_highlighted; 
920                         dest; 
921                         dest = dest->next)
922                 {
923                         if(dest->record)
924                         {
925 // Get source width in pixels
926                                 w = 0;
927
928 // Use current cursor position
929                                 if(mwindow->session->free_drag)
930                                 {
931                                         position = (double)(cursor_x + 
932                                                 mwindow->edl->local_session->view_start[pane->number]) *
933                                                 mwindow->edl->local_session->zoom_sample /
934                                                 mwindow->edl->session->sample_rate;
935                                 }
936                                 else
937 // Use start of highlighted edit
938                                 if(mwindow->session->edit_highlighted)
939                                 {
940                                         position = mwindow->session->track_highlighted->from_units(
941                                                 mwindow->session->edit_highlighted->startproject);
942                                 }
943                                 else
944 // Use end of highlighted track, disregarding effects
945                                 {
946                                         position = mwindow->session->track_highlighted->from_units(
947                                                 mwindow->session->track_highlighted->edits->length());
948                                 }
949
950 // Get the x coordinate
951                                 x = Units::to_int64(position * 
952                                         mwindow->edl->session->sample_rate /
953                                         mwindow->edl->local_session->zoom_sample) - 
954                                         mwindow->edl->local_session->view_start[pane->number];
955
956                                 if(dest->data_type == TRACK_AUDIO)
957                                 {
958                                         if(indexable && current_atrack < indexable->get_audio_channels())
959                                         {
960 //printf("TrackCanvas::draw_paste_destination %d %d\n", __LINE__, current_atrack);
961                                                 w = Units::to_int64((double)indexable->get_audio_samples() /
962                                                         indexable->get_sample_rate() *
963                                                         mwindow->edl->session->sample_rate / 
964                                                         mwindow->edl->local_session->zoom_sample);
965                                                 current_atrack++;
966                                                 //draw_box = 1;
967                                         }
968                                         else
969                                         if(clip && current_atrack < clip->tracks->total_audio_tracks())
970                                         {
971                                                 w = Units::to_int64((double)clip->tracks->total_length() *
972                                                         mwindow->edl->session->sample_rate / 
973                                                         mwindow->edl->local_session->zoom_sample);
974 //printf("draw_paste_destination %d\n", x);
975                                                 current_atrack++;
976                                                 //draw_box = 1;
977                                         }
978                                         else
979                                         if(mwindow->session->current_operation == DRAG_EDIT &&
980                                                 current_aedit < mwindow->session->drag_edits->total)
981                                         {
982                                                 Edit *edit;
983                                                 while(current_aedit < mwindow->session->drag_edits->total &&
984                                                         mwindow->session->drag_edits->values[current_aedit]->track->data_type != TRACK_AUDIO)
985                                                         current_aedit++;
986
987                                                 if(current_aedit < mwindow->session->drag_edits->total)
988                                                 {
989                                                         edit = mwindow->session->drag_edits->values[current_aedit];
990                                                         w = Units::to_int64(edit->length / mwindow->edl->local_session->zoom_sample);
991
992                                                         current_aedit++;
993                                                         //draw_box = 1;
994                                                 }
995                                         }
996                                 }
997                                 else
998                                 if(dest->data_type == TRACK_VIDEO)
999                                 {
1000 //printf("draw_paste_destination 1\n");
1001                                         if(indexable && current_vtrack < indexable->get_video_layers())
1002                                         {
1003                                                 w = Units::to_int64((double)indexable->get_video_frames() / 
1004                                                         indexable->get_frame_rate() *
1005                                                         mwindow->edl->session->sample_rate /
1006                                                         mwindow->edl->local_session->zoom_sample);
1007                                                 current_vtrack++;
1008                                                 //draw_box = 1;
1009                                         }
1010                                         else
1011                                         if(clip && current_vtrack < clip->tracks->total_video_tracks())
1012                                         {
1013                                                 w = Units::to_int64(clip->tracks->total_length() *
1014                                                         mwindow->edl->session->sample_rate / 
1015                                                         mwindow->edl->local_session->zoom_sample);
1016                                                 current_vtrack++;
1017                                                 //draw_box = 1;
1018                                         }
1019                                         else
1020                                         if(mwindow->session->current_operation == DRAG_EDIT &&
1021                                                 current_vedit < mwindow->session->drag_edits->total)
1022                                         {
1023                                                 Edit *edit;
1024                                                 while(current_vedit < mwindow->session->drag_edits->total &&
1025                                                         mwindow->session->drag_edits->values[current_vedit]->track->data_type != TRACK_VIDEO)
1026                                                         current_vedit++;
1027
1028                                                 if(current_vedit < mwindow->session->drag_edits->total)
1029                                                 {
1030                                                         edit = mwindow->session->drag_edits->values[current_vedit];
1031                                                         w = Units::to_int64(edit->track->from_units(edit->length) *
1032                                                                 mwindow->edl->session->sample_rate / 
1033                                                                 mwindow->edl->local_session->zoom_sample);
1034
1035                                                         current_vedit++;
1036                                                         //draw_box = 1;
1037                                                 }
1038                                         }
1039                                 }
1040
1041                                 if(w)
1042                                 {
1043                                         int y = dest->y_pixel - mwindow->edl->local_session->track_start[pane->number];
1044                                         int h = dest->vertical_span(mwindow->theme);
1045
1046
1047 //printf("TrackCanvas::draw_paste_destination 2 %d %d %d %d\n", x, y, w, h);
1048                                         if(x < -BC_INFINITY)
1049                                         {
1050                                                 w -= -BC_INFINITY - x;
1051                                                 x += -BC_INFINITY - x;
1052                                         }
1053                                         w = MIN(65535, w);
1054 // if(pane->number == TOP_RIGHT_PANE)
1055 // printf("TrackCanvas::draw_paste_destination %d %d %d %d %d\n",
1056 // __LINE__,
1057 // x,
1058 // y,
1059 // w,
1060 // h);
1061                                         draw_highlight_rectangle(x, y, w, h);
1062                                 }
1063                         }
1064                 }
1065         }
1066 }
1067
1068 void TrackCanvas::plugin_dimensions(Plugin *plugin, int64_t &x, int64_t &y, int64_t &w, int64_t &h)
1069 {
1070         x = Units::round(plugin->track->from_units(plugin->startproject) *
1071                 mwindow->edl->session->sample_rate / 
1072                 mwindow->edl->local_session->zoom_sample - 
1073                 mwindow->edl->local_session->view_start[pane->number]);
1074         w = Units::round(plugin->track->from_units(plugin->length) *
1075                 mwindow->edl->session->sample_rate / 
1076                 mwindow->edl->local_session->zoom_sample);
1077         y = plugin->track->y_pixel - 
1078                 mwindow->edl->local_session->track_start[pane->number] + 
1079                 mwindow->edl->local_session->zoom_track +
1080                 plugin->plugin_set->get_number() * 
1081                 mwindow->theme->get_image("plugin_bg_data")->get_h();
1082         if(mwindow->edl->session->show_titles)
1083                 y += mwindow->theme->get_image("title_bg_data")->get_h();
1084         h = mwindow->theme->get_image("plugin_bg_data")->get_h();
1085 }
1086
1087 int TrackCanvas::resource_h()
1088 {
1089         return mwindow->edl->local_session->zoom_track;
1090 }
1091
1092 void TrackCanvas::draw_highlight_rectangle(int x, int y, int w, int h)
1093 {
1094         if(x < -10)
1095         {
1096                 w += x - -10;
1097                 x = -10;
1098         }
1099
1100         if(y < -10)
1101         {
1102                 h += y - -10;
1103                 y = -10;
1104         }
1105
1106         w = MIN(w, get_w() + 20);
1107         h = MIN(h, get_h() + 20);
1108         if(w > 0 && h > 0)
1109         {
1110                 set_color(WHITE);
1111                 set_inverse();
1112                 draw_rectangle(x, y, w, h);
1113                 draw_rectangle(x + 1, y + 1, w - 2, h - 2);
1114                 draw_rectangle(x + 2, y + 2, w - 4, h - 4);
1115                 set_opaque();
1116         }
1117 //if(pane->number == TOP_RIGHT_PANE) 
1118 //printf("TrackCanvas::draw_highlight_rectangle %d %d %d %d %d\n", __LINE__, x, y, w, h);
1119 }
1120
1121 void TrackCanvas::draw_playback_cursor()
1122 {
1123 // Called before playback_cursor exists
1124 //      if(mwindow->playback_cursor && mwindow->playback_cursor->visible)
1125 //      {
1126 //              mwindow->playback_cursor->visible = 0;
1127 //              mwindow->playback_cursor->draw();
1128 //      }
1129 }
1130
1131 void TrackCanvas::get_handle_coords(Edit *edit, int64_t &x, int64_t &y, int64_t &w, int64_t &h, int side)
1132 {
1133         int handle_w = mwindow->theme->edithandlein_data[0]->get_w();
1134         int handle_h = mwindow->theme->edithandlein_data[0]->get_h();
1135
1136         edit_dimensions(edit, x, y, w, h);
1137
1138         if(mwindow->edl->session->show_titles)
1139         {
1140                 y += mwindow->theme->get_image("title_bg_data")->get_h();
1141         }
1142         else
1143         {
1144                 y = 0;
1145         }
1146
1147         if(side == EDIT_OUT)
1148         {
1149                 x += w - handle_w;
1150         }
1151
1152         h = handle_h;
1153         w = handle_w;
1154 }
1155
1156 void TrackCanvas::get_transition_coords(int64_t &x, int64_t &y, int64_t &w, int64_t &h)
1157 {
1158 //printf("TrackCanvas::get_transition_coords 1\n");
1159 //      int transition_w = mwindow->theme->transitionhandle_data[0]->get_w();
1160 //      int transition_h = mwindow->theme->transitionhandle_data[0]->get_h();
1161         int transition_w = 30;
1162         int transition_h = 30;
1163 //printf("TrackCanvas::get_transition_coords 1\n");
1164
1165         if(mwindow->edl->session->show_titles)
1166                 y += mwindow->theme->get_image("title_bg_data")->get_h();
1167 //printf("TrackCanvas::get_transition_coords 2\n");
1168
1169         y += (h - mwindow->theme->get_image("title_bg_data")->get_h()) / 2 - transition_h / 2;
1170         x -= transition_w / 2;
1171
1172         h = transition_h;
1173         w = transition_w;
1174 }
1175
1176 void TrackCanvas::draw_highlighting()
1177 {
1178         int64_t x, y, w, h;
1179         int draw_box = 0;
1180
1181
1182
1183
1184         switch(mwindow->session->current_operation)
1185         {
1186                 case DRAG_ATRANSITION:
1187                 case DRAG_VTRANSITION:
1188 //printf("TrackCanvas::draw_highlighting 1 %p %p\n", 
1189 //      mwindow->session->track_highlighted, mwindow->session->edit_highlighted);
1190                         if(mwindow->session->edit_highlighted)
1191                         {
1192 //printf("TrackCanvas::draw_highlighting 2\n");
1193                                 if((mwindow->session->current_operation == DRAG_ATRANSITION && 
1194                                         mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
1195                                         (mwindow->session->current_operation == DRAG_VTRANSITION && 
1196                                         mwindow->session->track_highlighted->data_type == TRACK_VIDEO))
1197                                 {
1198 //printf("TrackCanvas::draw_highlighting 2\n");
1199                                         edit_dimensions(mwindow->session->edit_highlighted, x, y, w, h);
1200 //printf("TrackCanvas::draw_highlighting 2\n");
1201
1202                                         if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
1203                                                 MWindowGUI::visible(y, y + h, 0, get_h()))
1204                                         {
1205                                                 draw_box = 1;
1206                                                 get_transition_coords(x, y, w, h);
1207                                         }
1208 //printf("TrackCanvas::draw_highlighting 3\n");
1209                                 }
1210                         }
1211                         break;
1212
1213
1214
1215 // Dragging a new effect from the Resource window
1216                 case DRAG_AEFFECT:
1217                 case DRAG_VEFFECT:
1218                         if(mwindow->session->track_highlighted &&
1219                                 ((mwindow->session->current_operation == DRAG_AEFFECT && mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
1220                                         (mwindow->session->current_operation == DRAG_VEFFECT && mwindow->session->track_highlighted->data_type == TRACK_VIDEO)))
1221                         {
1222 // Put it before another plugin
1223                                 if(mwindow->session->plugin_highlighted)
1224                                 {
1225                                         plugin_dimensions(mwindow->session->plugin_highlighted, 
1226                                                 x, 
1227                                                 y, 
1228                                                 w, 
1229                                                 h);
1230 //printf("TrackCanvas::draw_highlighting 1 %d %d\n", x, w);
1231                                 }
1232                                 else
1233 // Put it after a plugin set
1234                                 if(mwindow->session->pluginset_highlighted &&
1235                                         mwindow->session->pluginset_highlighted->last)
1236                                 {
1237                                         plugin_dimensions((Plugin*)mwindow->session->pluginset_highlighted->last, 
1238                                                 x, 
1239                                                 y, 
1240                                                 w, 
1241                                                 h);
1242 //printf("TrackCanvas::draw_highlighting 1 %d %d\n", x, w);
1243                                         int64_t track_x, track_y, track_w, track_h;
1244                                         track_dimensions(mwindow->session->track_highlighted, 
1245                                                 track_x, 
1246                                                 track_y, 
1247                                                 track_w, 
1248                                                 track_h);
1249
1250                                         x += w;
1251                                         w = Units::round(
1252                                                         mwindow->session->track_highlighted->get_length() *
1253                                                         mwindow->edl->session->sample_rate / 
1254                                                         mwindow->edl->local_session->zoom_sample - 
1255                                                         mwindow->edl->local_session->view_start[pane->number]) -
1256                                                 x;
1257 //printf("TrackCanvas::draw_highlighting 2 %d\n", w);
1258                                         if(w <= 0) w = track_w;
1259                                 }
1260                                 else
1261                                 {
1262                                         track_dimensions(mwindow->session->track_highlighted, 
1263                                                 x, 
1264                                                 y, 
1265                                                 w, 
1266                                                 h);
1267
1268 //printf("TrackCanvas::draw_highlighting 1 %d %d %d %d\n", x, y, w, h);
1269 // Put it in a new plugin set determined by the selected range
1270                                         if(mwindow->edl->local_session->get_selectionend() > 
1271                                                 mwindow->edl->local_session->get_selectionstart())
1272                                         {
1273                                                 x = Units::to_int64(mwindow->edl->local_session->get_selectionstart() *
1274                                                         mwindow->edl->session->sample_rate / 
1275                                                         mwindow->edl->local_session->zoom_sample -
1276                                                         mwindow->edl->local_session->view_start[pane->number]);
1277                                                 w = Units::to_int64((mwindow->edl->local_session->get_selectionend() - 
1278                                                         mwindow->edl->local_session->get_selectionstart()) *
1279                                                         mwindow->edl->session->sample_rate / 
1280                                                         mwindow->edl->local_session->zoom_sample);
1281                                         }
1282 // Put it in a new plugin set determined by an edit boundary
1283 //                                      else
1284 //                                      if(mwindow->session->edit_highlighted)
1285 //                                      {
1286 //                                              int64_t temp_y, temp_h;
1287 //                                              edit_dimensions(mwindow->session->edit_highlighted, 
1288 //                                                      x, 
1289 //                                                      temp_y, 
1290 //                                                      w, 
1291 //                                                      temp_h);
1292 //                                      }
1293 // Put it at the beginning of the track in a new plugin set
1294                                 }
1295
1296                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
1297                                         MWindowGUI::visible(y, y + h, 0, get_h()))
1298                                 {
1299 //printf("TrackCanvas::draw_highlighting 1\n");
1300                                         draw_box = 1;
1301                                 }
1302                         }
1303                         break;
1304                 
1305                 case DRAG_ASSET:
1306                         if(mwindow->session->track_highlighted)
1307                         {
1308 //                              track_dimensions(mwindow->session->track_highlighted, x, y, w, h);
1309
1310 //                              if(MWindowGUI::visible(y, y + h, 0, get_h()))
1311 //                              {
1312                                         draw_paste_destination();
1313 //                              }
1314                         }
1315                         break;
1316
1317                 case DRAG_EDIT:
1318                         if(mwindow->session->track_highlighted)
1319                         {
1320 //                              track_dimensions(mwindow->session->track_highlighted, x, y, w, h);
1321 //
1322 //                              if(MWindowGUI::visible(y, y + h, 0, get_h()))
1323 //                              {
1324                                         draw_paste_destination();
1325 //                              }
1326                         }
1327                         break;
1328
1329 // Dragging an effect from the timeline
1330                 case DRAG_AEFFECT_COPY:
1331                 case DRAG_VEFFECT_COPY:
1332                         if((mwindow->session->plugin_highlighted || mwindow->session->track_highlighted) &&
1333                                 ((mwindow->session->current_operation == DRAG_AEFFECT_COPY && mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
1334                                 (mwindow->session->current_operation == DRAG_VEFFECT_COPY && mwindow->session->track_highlighted->data_type == TRACK_VIDEO)))
1335                         {
1336 // Put it before another plugin
1337                                 if(mwindow->session->plugin_highlighted)
1338                                         plugin_dimensions(mwindow->session->plugin_highlighted, x, y, w, h);
1339                                 else
1340 // Put it after a plugin set
1341                                 if(mwindow->session->pluginset_highlighted &&
1342                                         mwindow->session->pluginset_highlighted->last)
1343                                 {
1344                                         plugin_dimensions((Plugin*)mwindow->session->pluginset_highlighted->last, x, y, w, h);
1345                                         x += w;
1346                                 }
1347                                 else
1348                                 if(mwindow->session->track_highlighted)
1349                                 {
1350                                         track_dimensions(mwindow->session->track_highlighted, x, y, w, h);
1351
1352 // Put it in a new plugin set determined by an edit boundary
1353                                         if(mwindow->session->edit_highlighted)
1354                                         {
1355                                                 int64_t temp_y, temp_h;
1356                                                 edit_dimensions(mwindow->session->edit_highlighted, 
1357                                                         x, 
1358                                                         temp_y, 
1359                                                         w, 
1360                                                         temp_h);
1361                                         }
1362 // Put it in a new plugin set at the start of the track
1363                                 }
1364
1365 // Calculate length of plugin based on data type of track and units
1366                                 if(mwindow->session->track_highlighted->data_type == TRACK_VIDEO)
1367                                 {
1368                                         w = (int64_t)((double)mwindow->session->drag_plugin->length / 
1369                                                 mwindow->edl->session->frame_rate *
1370                                                 mwindow->edl->session->sample_rate /
1371                                                 mwindow->edl->local_session->zoom_sample);
1372                                 }
1373                                 else
1374                                 {
1375                                         w = (int64_t)mwindow->session->drag_plugin->length /
1376                                                 mwindow->edl->local_session->zoom_sample;
1377                                 }
1378
1379                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
1380                                         MWindowGUI::visible(y, y + h, 0, get_h()))
1381                                 {
1382                                         draw_box = 1;
1383                                 }
1384                         }
1385                         break;
1386
1387                 case DRAG_PLUGINKEY:
1388                         if(mwindow->session->plugin_highlighted && 
1389                            mwindow->session->current_operation == DRAG_PLUGINKEY)
1390                         {
1391 // Just highlight the plugin
1392                                 plugin_dimensions(mwindow->session->plugin_highlighted, x, y, w, h);
1393
1394                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
1395                                         MWindowGUI::visible(y, y + h, 0, get_h()))
1396                                 {
1397                                         draw_box = 1;
1398                                 }
1399                         }
1400                         break;
1401
1402         }
1403
1404
1405         if(draw_box)
1406         {
1407                 draw_highlight_rectangle(x, y, w, h);
1408         }
1409 }
1410
1411 void TrackCanvas::draw_plugins()
1412 {
1413         char string[BCTEXTLEN];
1414         int current_on = 0;
1415         int current_show = 0;
1416
1417
1418 //      if(!mwindow->edl->session->show_assets) goto done;
1419
1420         for(int i = 0; i < plugin_on_toggles.total; i++)
1421                 plugin_on_toggles.values[i]->in_use = 0;
1422         for(int i = 0; i < plugin_show_toggles.total; i++)
1423                 plugin_show_toggles.values[i]->in_use = 0;
1424
1425
1426         for(Track *track = mwindow->edl->tracks->first;
1427                 track;
1428                 track = track->next)
1429         {
1430                 if(track->expand_view)
1431                 {
1432                         for(int i = 0; i < track->plugin_set.total; i++)
1433                         {
1434                                 PluginSet *pluginset = track->plugin_set.values[i];
1435
1436                                 for(Plugin *plugin = (Plugin*)pluginset->first; plugin; plugin = (Plugin*)plugin->next)
1437                                 {
1438                                         int64_t total_x, y, total_w, h;
1439                                         plugin_dimensions(plugin, total_x, y, total_w, h);
1440                                         
1441                                         if(MWindowGUI::visible(total_x, total_x + total_w, 0, get_w()) &&
1442                                                 MWindowGUI::visible(y, y + h, 0, get_h()) &&
1443                                                 plugin->plugin_type != PLUGIN_NONE)
1444                                         {
1445                                                 int x = total_x, w = total_w, left_margin = 5;
1446                                                 int right_margin = 5;
1447                                                 if(x < 0)
1448                                                 {
1449                                                         w -= -x;
1450                                                         x = 0;
1451                                                 }
1452                                                 if(w + x > get_w()) w -= (w + x) - get_w();
1453
1454                                                 draw_3segmenth(x, 
1455                                                         y, 
1456                                                         w, 
1457                                                         total_x,
1458                                                         total_w,
1459                                                         mwindow->theme->get_image("plugin_bg_data"),
1460                                                         0);
1461                                                 set_color(mwindow->theme->title_color);
1462                                                 set_font(mwindow->theme->title_font);
1463                                                 plugin->calculate_title(string, 0);
1464
1465 // Truncate string to int64_test visible in background
1466                                                 int len = strlen(string), j;
1467                                                 for(j = len; j >= 0; j--)
1468                                                 {
1469                                                         if(left_margin + get_text_width(mwindow->theme->title_font, string) > w)
1470                                                         {
1471                                                                 string[j] = 0;
1472                                                         }
1473                                                         else
1474                                                                 break;
1475                                                 }
1476
1477 // Justify the text on the left boundary of the edit if it is visible.
1478 // Otherwise justify it on the left side of the screen.
1479                                                 int64_t text_x = total_x + left_margin;
1480                                                 int64_t text_w = get_text_width(mwindow->theme->title_font, string, strlen(string));
1481                                                 text_x = MAX(left_margin, text_x);
1482                                                 draw_text(text_x, 
1483                                                         y + get_text_ascent(mwindow->theme->title_font) + 2, 
1484                                                         string,
1485                                                         strlen(string),
1486                                                         0);
1487                                                 int64_t min_x = total_x + text_w;
1488
1489
1490 // Update plugin toggles
1491                                                 int toggle_x = total_x + total_w;
1492                                                 int toggle_y = y;
1493                                                 toggle_x = MIN(get_w() - right_margin, toggle_x);
1494
1495 // On toggle
1496                                                 toggle_x -= PluginOn::calculate_w(mwindow) + 10;
1497                                                 if(toggle_x > min_x)
1498                                                 {
1499                                                         if(current_on >= plugin_on_toggles.total)
1500                                                         {
1501                                                                 PluginOn *plugin_on = new PluginOn(mwindow, toggle_x, toggle_y, plugin);
1502                                                                 add_subwindow(plugin_on);
1503                                                                 plugin_on_toggles.append(plugin_on);
1504                                                         }
1505                                                         else
1506                                                         {
1507                                                                 plugin_on_toggles.values[current_on]->update(toggle_x, toggle_y, plugin);
1508                                                         }
1509                                                         current_on++;
1510                                                 }
1511
1512 // Toggles for standalone plugins only
1513                                                 if(plugin->plugin_type == PLUGIN_STANDALONE)
1514                                                 {
1515 // Show
1516                                                         toggle_x -= PluginShow::calculate_w(mwindow) + 10;
1517                                                         if(toggle_x > min_x)
1518                                                         {
1519                                                                 if(current_show >= plugin_show_toggles.total)
1520                                                                 {
1521                                                                         PluginShow *plugin_show = new PluginShow(mwindow, toggle_x, toggle_y, plugin);
1522                                                                         add_subwindow(plugin_show);
1523                                                                         plugin_show_toggles.append(plugin_show);
1524                                                                 }
1525                                                                 else
1526                                                                 {
1527                                                                         plugin_show_toggles.values[current_show]->update(toggle_x, toggle_y, plugin);
1528                                                                 }
1529                                                                 current_show++;
1530                                                         }
1531
1532
1533                                                         
1534                                                 }
1535                                         }
1536                                 }
1537                         }
1538                 }
1539         }
1540
1541 // Remove unused toggles
1542
1543         while(current_show < plugin_show_toggles.total)
1544         {
1545                 plugin_show_toggles.remove_object_number(current_show);
1546         }
1547
1548         while(current_on < plugin_on_toggles.total)
1549         {
1550                 plugin_on_toggles.remove_object_number(current_on);
1551         }
1552
1553 }
1554
1555 void TrackCanvas::refresh_plugintoggles()
1556 {
1557         for(int i = 0; i < plugin_on_toggles.total; i++)
1558         {
1559                 PluginOn *on = plugin_on_toggles.values[i];
1560                 on->reposition_window(on->get_x(), on->get_y());
1561         }
1562         for(int i = 0; i < plugin_show_toggles.total; i++)
1563         {
1564                 PluginShow *show = plugin_show_toggles.values[i];
1565                 show->reposition_window(show->get_x(), show->get_y());
1566         }
1567 }
1568
1569 void TrackCanvas::draw_inout_points()
1570 {
1571 }
1572
1573
1574 void TrackCanvas::draw_drag_handle()
1575 {
1576         if(mwindow->session->current_operation == DRAG_EDITHANDLE2 ||
1577                 mwindow->session->current_operation == DRAG_PLUGINHANDLE2)
1578         {
1579 //printf("TrackCanvas::draw_drag_handle 1 %ld %ld\n", mwindow->session->drag_sample, mwindow->edl->local_session->view_start);
1580                 int64_t pixel1 = Units::round(mwindow->session->drag_position * 
1581                         mwindow->edl->session->sample_rate /
1582                         mwindow->edl->local_session->zoom_sample - 
1583                         mwindow->edl->local_session->view_start[pane->number]);
1584 //printf("TrackCanvas::draw_drag_handle 2 %d %jd\n", pane->number, pixel1);
1585                 set_color(GREEN);
1586                 set_inverse();
1587 //printf("TrackCanvas::draw_drag_handle 3\n");
1588                 draw_line(pixel1, 0, pixel1, get_h());
1589                 set_opaque();
1590 //printf("TrackCanvas::draw_drag_handle 4\n");
1591         }
1592 }
1593
1594
1595 void TrackCanvas::draw_transitions()
1596 {
1597         int64_t x, y, w, h;
1598
1599 //      if(!mwindow->edl->session->show_assets) return;
1600
1601         for(Track *track = mwindow->edl->tracks->first; track; track = track->next) {
1602                 for(Edit *edit = track->edits->first; edit; edit = edit->next) {
1603                         if(!edit->transition) continue;
1604                         edit_dimensions(edit, x, y, w, h);
1605                         get_transition_coords(x, y, w, h);
1606                         if( !MWindowGUI::visible(x, x + w, 0, get_w()) ) continue;
1607                         if( !MWindowGUI::visible(y, y + h, 0, get_h()) ) continue;
1608                         PluginServer *server = mwindow->scan_plugindb(edit->transition->title,
1609                                                 track->data_type);
1610                         if( !server ) continue;
1611                         VFrame *picon = server->get_picon();
1612                         if( !picon ) continue;
1613                         draw_vframe(picon, x, y, w, h, 0, 0, picon->get_w(), picon->get_h());
1614                 }
1615         }
1616 }
1617
1618 void TrackCanvas::draw_loop_points()
1619 {
1620 //printf("TrackCanvas::draw_loop_points 1\n");
1621         if(mwindow->edl->local_session->loop_playback)
1622         {
1623 //printf("TrackCanvas::draw_loop_points 2\n");
1624                 int64_t x = Units::round(mwindow->edl->local_session->loop_start *
1625                         mwindow->edl->session->sample_rate /
1626                         mwindow->edl->local_session->zoom_sample - 
1627                         mwindow->edl->local_session->view_start[pane->number]);
1628 //printf("TrackCanvas::draw_loop_points 3\n");
1629
1630                 if(MWindowGUI::visible(x, x + 1, 0, get_w()))
1631                 {
1632                         set_color(GREEN);
1633                         draw_line(x, 0, x, get_h());
1634                 }
1635 //printf("TrackCanvas::draw_loop_points 4\n");
1636
1637                 x = Units::round(mwindow->edl->local_session->loop_end *
1638                         mwindow->edl->session->sample_rate /
1639                         mwindow->edl->local_session->zoom_sample - 
1640                         mwindow->edl->local_session->view_start[pane->number]);
1641 //printf("TrackCanvas::draw_loop_points 5\n");
1642
1643                 if(MWindowGUI::visible(x, x + 1, 0, get_w()))
1644                 {
1645                         set_color(GREEN);
1646                         draw_line(x, 0, x, get_h());
1647                 }
1648 //printf("TrackCanvas::draw_loop_points 6\n");
1649         }
1650 //printf("TrackCanvas::draw_loop_points 7\n");
1651 }
1652
1653 void TrackCanvas::draw_brender_start()
1654 {
1655         if(mwindow->preferences->use_brender)
1656         {
1657                 int64_t x = Units::round(mwindow->edl->session->brender_start *
1658                         mwindow->edl->session->sample_rate /
1659                         mwindow->edl->local_session->zoom_sample - 
1660                         mwindow->edl->local_session->view_start[pane->number]);
1661
1662                 if(MWindowGUI::visible(x, x + 1, 0, get_w()))
1663                 {
1664                         set_color(RED);
1665                         draw_line(x, 0, x, get_h());
1666                 }
1667         }
1668 }
1669
1670 static int auto_colors[AUTOMATION_TOTAL] = 
1671 {
1672         BLUE,
1673         RED,
1674         GREEN,
1675         BLUE,
1676         RED,
1677         GREEN,
1678         BLUE,
1679         WHITE,
1680         0,
1681         0,
1682         0,
1683         WHITE
1684 };
1685
1686 // The operations which correspond to each automation type
1687 static int auto_operations[AUTOMATION_TOTAL] = 
1688 {
1689         DRAG_MUTE,
1690         DRAG_CAMERA_X,
1691         DRAG_CAMERA_Y,
1692         DRAG_CAMERA_Z,
1693         DRAG_PROJECTOR_X,
1694         DRAG_PROJECTOR_Y,
1695         DRAG_PROJECTOR_Z,
1696         DRAG_FADE,
1697         DRAG_PAN,
1698         DRAG_MODE,
1699         DRAG_MASK,
1700         DRAG_SPEED
1701 };
1702
1703 // The buttonpress operations, so nothing changes unless the mouse moves
1704 // a certain amount.  This allows the keyframe to be used to position the
1705 // insertion point without moving itself.
1706 static int pre_auto_operations[AUTOMATION_TOTAL] =
1707 {
1708         DRAG_MUTE,
1709         DRAG_CAMERA_X,
1710         DRAG_CAMERA_Y,
1711         DRAG_CAMERA_Z,
1712         DRAG_PROJECTOR_X,
1713         DRAG_PROJECTOR_Y,
1714         DRAG_PROJECTOR_Z,
1715         DRAG_FADE,
1716         DRAG_PAN_PRE,
1717         DRAG_MODE_PRE,
1718         DRAG_MASK_PRE,
1719         DRAG_SPEED
1720 };
1721
1722
1723 int TrackCanvas::do_keyframes(int cursor_x, 
1724         int cursor_y, 
1725         int draw, 
1726         int buttonpress, 
1727         int &new_cursor,
1728         int &update_cursor,
1729         int &rerender)
1730 {
1731 // Note: button 3 (right mouse button) is not eaten to allow
1732 // track context menu to appear
1733         int result = 0;
1734         EDLSession *session = mwindow->edl->session;
1735
1736
1737
1738         BC_Pixmap *auto_pixmaps[AUTOMATION_TOTAL] = 
1739         {
1740                 0, 0, 0, 0, 0, 0, 0, 0,
1741                 pankeyframe_pixmap,
1742                 modekeyframe_pixmap,
1743                 maskkeyframe_pixmap,
1744         };
1745
1746
1747
1748         for(Track *track = mwindow->edl->tracks->first;
1749                 track && !result;
1750                 track = track->next)
1751         {
1752         Auto *auto_keyframe;
1753                 Automation *automation = track->automation;
1754
1755
1756 // Handle keyframes in reverse drawing order if a button press
1757                 int start = 0;
1758                 int end = AUTOMATION_TOTAL;
1759                 int step = 1;
1760                 if(buttonpress)
1761                 {
1762                         start = AUTOMATION_TOTAL - 1;
1763                         end = -1;
1764                         step = -1;
1765                 }
1766                 for(int i = start; i != end && !result; i += step)
1767                 {
1768 // Event not trapped and automation visible
1769                         Autos *autos = automation->autos[i];
1770                         if(!result && session->auto_conf->autos[i] && autos)
1771                         {
1772                                 switch(i)
1773                                 {
1774                                         case AUTOMATION_MODE:
1775                                         case AUTOMATION_PAN:
1776                                         case AUTOMATION_MASK:
1777                                                 result = do_autos(track, 
1778                                                         automation->autos[i],
1779                                                         cursor_x, 
1780                                                         cursor_y, 
1781                                                         draw, 
1782                                                         buttonpress,
1783                                                         auto_pixmaps[i],
1784                                                         auto_keyframe,
1785                                                         rerender);
1786                                                 break;
1787
1788                                         default:
1789                                                 switch(autos->get_type())
1790                                                 {
1791                                                         case Autos::AUTOMATION_TYPE_FLOAT:
1792 // Do dropshadow
1793                                                                 if(draw)
1794                                                                         result = do_float_autos(track, 
1795                                                                                 autos,
1796                                                                                 cursor_x, 
1797                                                                                 cursor_y, 
1798                                                                                 draw, 
1799                                                                                 buttonpress, 
1800                                                                                 1,
1801                                                                                 1,
1802                                                                                 BLACK,
1803                                                                                 auto_keyframe);
1804
1805                                                                 result = do_float_autos(track, 
1806                                                                         autos,
1807                                                                         cursor_x, 
1808                                                                         cursor_y, 
1809                                                                         draw, 
1810                                                                         buttonpress, 
1811                                                                         0,
1812                                                                         0,
1813                                                                         auto_colors[i],
1814                                                                         auto_keyframe);
1815                                                                 break;
1816
1817                                                         case Autos::AUTOMATION_TYPE_INT:
1818 // Do dropshadow
1819                                                                 if(draw)
1820                                                                         result = do_int_autos(track, 
1821                                                                                 autos,
1822                                                                                 cursor_x, 
1823                                                                                 cursor_y, 
1824                                                                                 draw, 
1825                                                                                 buttonpress,
1826                                                                                 1,
1827                                                                                 1,
1828                                                                                 BLACK,
1829                                                                                 auto_keyframe);
1830                                                                 result = do_int_autos(track, 
1831                                                                         autos,
1832                                                                         cursor_x, 
1833                                                                         cursor_y, 
1834                                                                         draw, 
1835                                                                         buttonpress,
1836                                                                         0,
1837                                                                         0,
1838                                                                         auto_colors[i],
1839                                                                         auto_keyframe);
1840                                                                 break;
1841                                                 }
1842                                                 break;
1843                                 }
1844                         
1845
1846
1847                                 if(result)
1848                                 {
1849                                         if(mwindow->session->current_operation == auto_operations[i])
1850                                                 rerender = 1;
1851
1852 // printf("TrackCanvas::do_keyframes %d %d %d\n", 
1853 // __LINE__, 
1854 // mwindow->session->current_operation,
1855 // auto_operations[i]);
1856                                         if(buttonpress)
1857                                         {
1858                                                 if (buttonpress != 3)
1859                                                 {
1860                                                         if(i == AUTOMATION_FADE) 
1861                                                                 synchronize_autos(0, 
1862                                                                         track, 
1863                                                                         (FloatAuto*)mwindow->session->drag_auto, 
1864                                                                         1);
1865                                                         mwindow->session->current_operation = pre_auto_operations[i];
1866                                                         update_drag_caption();
1867                                                 }
1868                                                 else
1869                                                 {
1870                                                         gui->keyframe_menu->update(automation, 
1871                                                                 autos, 
1872                                                                 auto_keyframe);
1873                                                         gui->keyframe_menu->activate_menu();
1874                                                         rerender = 1; // the position changes
1875                                                 }
1876                                         }
1877                                 }
1878                         }
1879                 }
1880
1881
1882
1883
1884                 if(!result && 
1885                         session->auto_conf->plugins /* &&
1886                         mwindow->edl->session->show_assets */)
1887                 {
1888                         Plugin *plugin;
1889                         KeyFrame *keyframe;
1890                         result = do_plugin_autos(track,
1891                                 cursor_x, 
1892                                 cursor_y, 
1893                                 draw, 
1894                                 buttonpress,
1895                                 plugin,
1896                                 keyframe);
1897                         if(result && mwindow->session->current_operation == DRAG_PLUGINKEY)
1898                         {
1899                                 rerender = 1;
1900                         }
1901                         if(result && (buttonpress == 1))
1902                         {
1903                                 mwindow->session->current_operation = DRAG_PLUGINKEY_PRE;
1904                                 update_drag_caption();
1905                                 rerender = 1;
1906                         } else
1907                         if (result && (buttonpress == 3))
1908                         {
1909                                 gui->keyframe_menu->update(plugin, keyframe);
1910                                 gui->keyframe_menu->activate_menu();
1911                                 rerender = 1; // the position changes
1912                         }
1913                 }
1914         }
1915
1916 // Final pass to trap event
1917         for(int i = 0; i < AUTOMATION_TOTAL; i++)
1918         {
1919                 if(mwindow->session->current_operation == pre_auto_operations[i] ||
1920                         mwindow->session->current_operation == auto_operations[i])
1921                 {
1922                         result = 1;
1923                         break;
1924                 }
1925         }
1926
1927         if(mwindow->session->current_operation == DRAG_PLUGINKEY ||
1928                 mwindow->session->current_operation == DRAG_PLUGINKEY_PRE)
1929         {
1930                 result = 1;
1931         }
1932
1933         update_cursor = 1;
1934         if(result)
1935         {
1936                 new_cursor = UPRIGHT_ARROW_CURSOR;
1937         }
1938
1939
1940         return result;
1941 }
1942
1943 void TrackCanvas::draw_auto(Auto *current, 
1944         int x, 
1945         int y, 
1946         int center_pixel, 
1947         int zoom_track)
1948 {
1949         int x1, y1, x2, y2;
1950
1951         x1 = x - HANDLE_W / 2;
1952         x2 = x + HANDLE_W / 2;
1953         y1 = center_pixel + y - HANDLE_W / 2;
1954         y2 = center_pixel + y + HANDLE_W / 2;
1955
1956         if(y1 < center_pixel + -zoom_track / 2) y1 = center_pixel + -zoom_track / 2;
1957         if(y2 > center_pixel + zoom_track / 2) y2 = center_pixel + zoom_track / 2;
1958
1959         draw_box(x1, y1, x2 - x1, y2 - y1);
1960 }
1961
1962
1963
1964
1965
1966
1967
1968
1969 // This draws lines for bezier in & out controls
1970 void TrackCanvas::draw_cropped_line(int x1, 
1971         int y1, 
1972         int x2, 
1973         int y2, 
1974         int min_y,
1975         int max_y)
1976 {
1977
1978
1979 // Don't care about x since it is clipped by the window.
1980 // Put y coords in ascending order
1981         if(y2 < y1)
1982         {
1983                 y2 ^= y1;
1984                 y1 ^= y2;
1985                 y2 ^= y1;
1986                 x2 ^= x1;
1987                 x1 ^= x2;
1988                 x2 ^= x1;
1989         }
1990
1991
1992
1993         double slope = (double)(x2 - x1) / (y2 - y1);
1994 //printf("TrackCanvas::draw_cropped_line %d %d %d %d %d\n", __LINE__, x1, y1, x2, y2);
1995         if(y1 < min_y)
1996         {
1997                 x1 = (int)(x1 + (min_y - y1) * slope);
1998                 y1 = min_y;
1999         }
2000         else
2001         if(y1 >= max_y)
2002         {
2003                 x1 = (int)(x1 + (max_y - 1 - y1) * slope);
2004                 y1 = max_y - 1;
2005         }
2006
2007         if(y2 >= max_y)
2008         {
2009                 x2 = (int)(x2 + (max_y - 1 - y2) * slope);
2010                 y2 = max_y - 1;
2011         }
2012         else
2013         if(y2 < min_y)
2014         {
2015                 x2 = (int)(x2 + (min_y - y2) * slope);
2016                 y1 = min_y;
2017         }
2018
2019
2020 //printf("TrackCanvas::draw_cropped_line %d %d %d %d %d\n", __LINE__, x1, y1, x2, y2);
2021         if(y1 >= min_y && 
2022                 y1 < max_y &&
2023                 y2 >= min_y &&
2024                 y2 < max_y)
2025                 draw_line(x1, y1, x2, y2);
2026 }
2027
2028
2029
2030
2031 void TrackCanvas::draw_floatauto(Auto *current, 
2032         int x, 
2033         int y, 
2034         int in_x, 
2035         int in_y, 
2036         int out_x, 
2037         int out_y, 
2038         int center_pixel, 
2039         int zoom_track)
2040 {
2041         int x1, y1, x2, y2;
2042         //int in_x1, in_x2;
2043         int in_y1, in_y2;
2044         //int out_x1, out_x2;
2045         int out_y1, out_y2;
2046
2047 // Center extents
2048         x1 = x - HANDLE_W / 2;
2049         x2 = x + HANDLE_W / 2;
2050         y1 = center_pixel + y - HANDLE_W / 2;
2051         y2 = center_pixel + y + HANDLE_W / 2;
2052
2053         CLAMP(y1, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
2054         CLAMP(y2, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
2055
2056         if(y2 - 1 > y1)
2057         {
2058                 if(((FloatAuto*)current)->mode == Auto::LINEAR)
2059                 {
2060                         draw_box(x1, y1, x2 - x1, y2 - y1);
2061                 }
2062                 else
2063                 {
2064                         ArrayList<int> polygon_x;
2065                         ArrayList<int> polygon_y;
2066                         polygon_x.append((x1 + x2) / 2 + 1);
2067                         polygon_y.append(y1 + 1);
2068                         polygon_x.append(x2 + 1);
2069                         polygon_y.append((y1 + y2) / 2 + 1);
2070                         polygon_x.append((x1 + x2) / 2 + 1);
2071                         polygon_y.append(y2 + 1);
2072                         polygon_x.append(x1 + 1);
2073                         polygon_y.append((y1 + y2) / 2 + 1);
2074                         fill_polygon(&polygon_x, &polygon_y);
2075                 }
2076         }
2077
2078 // In handle
2079         if(current->mode == Auto::BEZIER)
2080         {
2081                 //in_x1 = in_x - HANDLE_W / 2;
2082                 //in_x2 = in_x + HANDLE_W / 2;
2083                 in_y1 = center_pixel + in_y - HANDLE_W / 2;
2084                 in_y2 = center_pixel + in_y + HANDLE_W / 2;
2085
2086         // Draw line
2087                 draw_cropped_line(x, 
2088                         center_pixel + y, 
2089                         in_x, 
2090                         center_pixel + in_y, 
2091                         center_pixel + -zoom_track / 2,
2092                         center_pixel + zoom_track / 2);
2093
2094                 CLAMP(in_y1, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
2095                 CLAMP(in_y2, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
2096                 CLAMP(in_y, -zoom_track / 2, zoom_track / 2);
2097
2098 //     Draw handle
2099 //      if(in_y2 > in_y1)
2100 //      {
2101 //              set_color(BLACK);
2102 //              draw_box(in_x1 + 1, in_y1 + 1, in_x2 - in_x1, in_y2 - in_y1);
2103 //              set_color(color);
2104 //              draw_box(in_x1, in_y1, in_x2 - in_x1, in_y2 - in_y1);
2105 //      }
2106 //     
2107
2108         // Out handle
2109                 //out_x1 = out_x - HANDLE_W / 2;
2110                 //out_x2 = out_x + HANDLE_W / 2;
2111                 out_y1 = center_pixel + out_y - HANDLE_W / 2;
2112                 out_y2 = center_pixel + out_y + HANDLE_W / 2;
2113
2114         // Draw line
2115                 draw_cropped_line(x, 
2116                         center_pixel + y, 
2117                         out_x, 
2118                         center_pixel + out_y, 
2119                         center_pixel + -zoom_track / 2,
2120                         center_pixel + zoom_track / 2);
2121
2122                 CLAMP(out_y1, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
2123                 CLAMP(out_y2, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
2124                 CLAMP(out_y, -zoom_track / 2, zoom_track / 2);
2125
2126 //      if(out_y2 > out_y1)
2127 //      {
2128 //              set_color(BLACK);
2129 //              draw_box(out_x1 + 1, out_y1 + 1, out_x2 - out_x1, out_y2 - out_y1);
2130 //              set_color(color);
2131 //              draw_box(out_x1, out_y1, out_x2 - out_x1, out_y2 - out_y1);
2132 //      }
2133         }
2134 }
2135
2136 int TrackCanvas::test_auto(Auto *current, 
2137         int x, 
2138         int y, 
2139         int center_pixel, 
2140         int zoom_track, 
2141         int cursor_x, 
2142         int cursor_y, 
2143         int buttonpress)
2144 {
2145         int x1, y1, x2, y2;
2146         int result = 0;
2147
2148         x1 = x - HANDLE_W / 2;
2149         x2 = x + HANDLE_W / 2;
2150         y1 = center_pixel + y - HANDLE_W / 2;
2151         y2 = center_pixel + y + HANDLE_W / 2;
2152
2153         if(y1 < center_pixel + -zoom_track / 2) y1 = center_pixel + -zoom_track / 2;
2154         if(y2 > center_pixel + zoom_track / 2) y2 = center_pixel + zoom_track / 2;
2155
2156         if(cursor_x >= x1 && cursor_x < x2 && cursor_y >= y1 && cursor_y < y2)
2157         {
2158                 if(buttonpress && buttonpress != 3)
2159                 {
2160                         mwindow->session->drag_auto = current;
2161                         mwindow->session->drag_start_percentage = current->value_to_percentage();
2162                         mwindow->session->drag_start_position = current->position;
2163                         mwindow->session->drag_origin_x = cursor_x;
2164                         mwindow->session->drag_origin_y = cursor_y;
2165                 }
2166                 result = 1;
2167         }
2168
2169         if(buttonpress && buttonpress != 3 && result)
2170         {
2171 //printf("TrackCanvas::test_auto %d\n", __LINE__);
2172                 mwindow->undo->update_undo_before();
2173         }
2174
2175         return result;
2176 }
2177
2178 int TrackCanvas::test_floatauto(Auto *current, 
2179         int x, 
2180         int y, 
2181         int in_x,
2182         int in_y,
2183         int out_x,
2184         int out_y,
2185         int center_pixel, 
2186         int zoom_track, 
2187         int cursor_x, 
2188         int cursor_y, 
2189         int buttonpress)
2190 {
2191         int x1, y1, x2, y2;
2192         int in_x1, in_y1, in_x2, in_y2;
2193         int out_x1, out_y1, out_x2, out_y2;
2194         int result = 0;
2195
2196         x1 = x - HANDLE_W / 2;
2197         x2 = x + HANDLE_W / 2;
2198         y1 = center_pixel + y - HANDLE_W / 2;
2199         y2 = center_pixel + y + HANDLE_W / 2;
2200
2201         if(y1 < center_pixel + -zoom_track / 2) y1 = center_pixel + -zoom_track / 2;
2202         if(y2 > center_pixel + zoom_track / 2) y2 = center_pixel + zoom_track / 2;
2203
2204         in_x1 = in_x;
2205         in_x2 = x;
2206
2207 // Compute in handle extents from x position
2208         if(x > in_x)
2209         {
2210                 in_y1 = center_pixel + 
2211                         in_y + 
2212                         (cursor_x - in_x) * 
2213                         (y - in_y) / 
2214                         (x - in_x) - 
2215                         HANDLE_W / 2;
2216         }
2217         else
2218         {
2219                 in_y1 = in_y - HANDLE_W / 2;
2220         }
2221         in_y2 = in_y1 + HANDLE_W;
2222
2223         if(in_y1 < center_pixel + -zoom_track / 2) in_y1 = center_pixel + -zoom_track / 2;
2224         if(in_y2 > center_pixel + zoom_track / 2) in_y2 = center_pixel + zoom_track / 2;
2225
2226         out_x1 = x;
2227         out_x2 = out_x;
2228         if(x < out_x)
2229         {
2230                 out_y1 = center_pixel +
2231                         y +
2232                         (cursor_x - x) *
2233                         (out_y - y) /
2234                         (out_x - x) -
2235                         HANDLE_W / 2;
2236         }
2237         else
2238                 out_y1 = out_y - HANDLE_W / 2;
2239
2240         out_y2 = out_y1 + HANDLE_W;
2241
2242         if(out_y1 < center_pixel + -zoom_track / 2) out_y1 = center_pixel + -zoom_track / 2;
2243         if(out_y2 > center_pixel + zoom_track / 2) out_y2 = center_pixel + zoom_track / 2;
2244
2245
2246 //if(ctrl_down())
2247 //printf("TrackCanvas::test_floatauto %d cursor_x=%d cursor_y=%d in_x1=%d in_x2=%d in_y=%d in_y1=%d in_y2=%d position=" _LD "\n", 
2248 //__LINE__, cursor_x, cursor_y, in_x1, in_x2, in_y, in_y1, in_y2, current->position);
2249 //if(ctrl_down())
2250 //printf("TrackCanvas::test_floatauto %d cursor_x=%d cursor_y=%d out_x1=%d out_x2=%d out_y=%d out_y1=%d out_y2=%d\n", 
2251 //__LINE__, cursor_x, cursor_y, out_x1, out_x2, out_y, out_y1, out_y2);
2252
2253 //printf("TrackCanvas::test_floatauto %d %d %d %d %d %d\n", cursor_x, cursor_y, x1, x2, y1, y2);
2254 // Test value
2255         if(!ctrl_down() &&
2256                 cursor_x >= x1 && 
2257                 cursor_x < x2 && 
2258                 cursor_y >= y1 && 
2259                 cursor_y < y2)
2260         {
2261                 if(buttonpress && (buttonpress != 3))
2262                 {
2263                         mwindow->session->drag_auto = current;
2264                         mwindow->session->drag_start_percentage = current->value_to_percentage();
2265                         mwindow->session->drag_start_position = current->position;
2266                         mwindow->session->drag_origin_x = cursor_x;
2267                         mwindow->session->drag_origin_y = cursor_y;
2268                         mwindow->session->drag_handle = 0;
2269                 }
2270                 result = 1;
2271         }
2272         else
2273 // Test in control line
2274         if(ctrl_down() &&
2275                 cursor_x >= in_x1 && 
2276                 cursor_x < in_x2 && 
2277                 cursor_y >= in_y1 && 
2278                 cursor_y < in_y2 &&
2279                 current->position > 0 &&
2280                 current->mode == Auto::BEZIER)
2281         {
2282                 if(buttonpress && (buttonpress != 3))
2283                 {
2284                         mwindow->session->drag_auto = current;
2285                         mwindow->session->drag_start_percentage = 
2286                                 current->invalue_to_percentage();
2287 //                      mwindow->session->drag_start_position = 
2288 //                              ((FloatAuto*)current)->control_in_position;
2289                         mwindow->session->drag_origin_x = cursor_x;
2290                         mwindow->session->drag_origin_y = cursor_y;
2291                         mwindow->session->drag_handle = 1;
2292                 }
2293                 result = 1;
2294         }
2295         else
2296 // Test out control
2297         if(ctrl_down() &&
2298                 cursor_x >= out_x1 && 
2299                 cursor_x < out_x2 && 
2300                 cursor_y >= out_y1 && 
2301                 cursor_y < out_y2 &&
2302                 current->mode == Auto::BEZIER)
2303         {
2304                 if(buttonpress && (buttonpress != 3))
2305                 {
2306                         mwindow->session->drag_auto = current;
2307                         mwindow->session->drag_start_percentage = 
2308                                 current->outvalue_to_percentage();
2309 //                      mwindow->session->drag_start_position = 
2310 //                              ((FloatAuto*)current)->control_out_position;
2311                         mwindow->session->drag_origin_x = cursor_x;
2312                         mwindow->session->drag_origin_y = cursor_y;
2313                         mwindow->session->drag_handle = 2;
2314                 }
2315                 result = 1;
2316         }
2317
2318 // if(buttonpress)
2319 // 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", 
2320 // mwindow->session->drag_handle,
2321 // ctrl_down(),
2322 // cursor_x,
2323 // cursor_y,
2324 // x1, x2, y1, y2);
2325         if(buttonpress && (buttonpress != 3) && result)
2326         {
2327                 mwindow->undo->update_undo_before();
2328         }
2329
2330         return result;
2331 }
2332
2333
2334 // Get the float value & y for position x on the canvas
2335 #define X_TO_FLOATLINE(x) \
2336         int64_t position1 = (int64_t)(unit_start + x * zoom_units); \
2337         int64_t position2 = (int64_t)(unit_start + x * zoom_units) + 1; \
2338 /* Call by reference fails for some reason here */ \
2339         float value1 = autos->get_value(position1, PLAY_FORWARD, previous1, next1); \
2340         float value2 = autos->get_value(position2, PLAY_FORWARD, previous1, next1); \
2341         double position = unit_start + x * zoom_units; \
2342         double value = 0; \
2343         if(position2 > position1) \
2344         { \
2345                 value = value1 + \
2346                         (value2 - value1) * \
2347                         (position - position1) / \
2348                         (position2 - position1); \
2349         } \
2350         else \
2351         { \
2352                 value = value1; \
2353         } \
2354         int y = center_pixel + \
2355                 (int)(((value - automation_min) / automation_range - 0.5) * -yscale);
2356
2357
2358 void TrackCanvas::draw_floatline(int center_pixel, 
2359         FloatAuto *previous,
2360         FloatAuto *next,
2361         FloatAutos *autos,
2362         double unit_start,
2363         double zoom_units,
2364         double yscale,
2365         int x1,
2366         int y1,
2367         int x2,
2368         int y2)
2369 {
2370 // Solve bezier equation for either every pixel or a certain large number of
2371 // points.
2372
2373 // Not using slope intercept
2374         x1 = MAX(0, x1);
2375         int prev_y = y1;
2376
2377
2378 // Call by reference fails for some reason here
2379         FloatAuto *previous1 = previous, *next1 = next;
2380         float automation_min = mwindow->edl->local_session->automation_min;
2381         float automation_max = mwindow->edl->local_session->automation_max;
2382         float automation_range = automation_max - automation_min;
2383
2384         for(int x = x1; x < x2; x++)
2385         {
2386 // Interpolate value between frames
2387                 X_TO_FLOATLINE(x)
2388
2389                 if(/* x > x1 && */
2390                         y >= center_pixel - yscale / 2 && 
2391                         y < center_pixel + yscale / 2 - 1)
2392                 {
2393 // printf("TrackCanvas::draw_floatline y=%d min=%d max=%d\n",
2394 // y,
2395 // (int)(center_pixel - yscale / 2),
2396 // (int)(center_pixel + yscale / 2 - 1));
2397
2398                         draw_line(x - 1, prev_y, x, y);
2399                 }
2400                 prev_y = y;
2401         }
2402 }
2403
2404
2405
2406
2407
2408 int TrackCanvas::test_floatline(int center_pixel, 
2409                 FloatAutos *autos,
2410                 double unit_start,
2411                 double zoom_units,
2412                 double yscale,
2413                 int x1,
2414                 int x2,
2415                 int cursor_x, 
2416                 int cursor_y, 
2417                 int buttonpress)
2418 {
2419         int result = 0;
2420
2421
2422         float automation_min = mwindow->edl->local_session->automation_min;
2423         float automation_max = mwindow->edl->local_session->automation_max;
2424         float automation_range = automation_max - automation_min;
2425         FloatAuto *previous1 = 0, *next1 = 0;
2426         X_TO_FLOATLINE(cursor_x);
2427
2428         if(cursor_x >= x1 && 
2429                 cursor_x < x2 &&
2430                 cursor_y >= y - HANDLE_W / 2 && 
2431                 cursor_y < y + HANDLE_W / 2 &&
2432                 !ctrl_down())
2433         {
2434                 result = 1;
2435
2436 // Menu
2437                 if(buttonpress == 3)
2438                 {
2439                 }
2440                 else
2441 // Create keyframe
2442                 if(buttonpress)
2443                 {
2444                         Auto *current;
2445                         mwindow->undo->update_undo_before();
2446                         current = mwindow->session->drag_auto = autos->insert_auto(position1);
2447                         ((FloatAuto*)current)->value = value;
2448                         mwindow->session->drag_start_percentage = current->value_to_percentage();
2449                         mwindow->session->drag_start_position = current->position;
2450                         mwindow->session->drag_origin_x = cursor_x;
2451                         mwindow->session->drag_origin_y = cursor_y;
2452                         mwindow->session->drag_handle = 0;
2453                 }
2454         }
2455
2456
2457         return result;
2458 }
2459
2460
2461 void TrackCanvas::synchronize_autos(float change, 
2462         Track *skip, 
2463         FloatAuto *fauto, 
2464         int fill_gangs)
2465 {
2466 // fill mwindow->session->drag_auto_gang
2467         if (fill_gangs == 1 && skip->gang)
2468         {
2469                 for(Track *current = mwindow->edl->tracks->first;
2470                         current;
2471                         current = NEXT)
2472                 {
2473                         if(current->data_type == skip->data_type &&
2474                                 current->gang && 
2475                                 current->record && 
2476                                 current != skip)
2477                         {
2478                                 FloatAutos *fade_autos = (FloatAutos*)current->automation->autos[AUTOMATION_FADE];
2479                                 double position = skip->from_units(fauto->position);
2480                                 FloatAuto *previous = 0, *next = 0;
2481
2482                                 float init_value = fade_autos->get_value(fauto->position, PLAY_FORWARD, previous, next);
2483                                 FloatAuto *keyframe;
2484                                 keyframe = (FloatAuto*)fade_autos->get_auto_at_position(position);
2485                                 
2486                                 if (!keyframe)
2487                                 {
2488 // create keyframe at exactly this point in time
2489                                         keyframe = (FloatAuto*)fade_autos->insert_auto(fauto->position);
2490                                         keyframe->value = init_value;
2491                                 } 
2492                                 else
2493                                 { 
2494 // keyframe exists, just change it
2495                                         keyframe->value += change;              
2496                                 } 
2497                                 
2498                                 keyframe->position = fauto->position;
2499 //                              keyframe->control_out_position = fauto->control_out_position;
2500 //                              keyframe->control_in_position = fauto->control_in_position;
2501                                 keyframe->control_out_value = fauto->control_out_value;
2502                                 keyframe->control_in_value = fauto->control_in_value;
2503
2504                                 mwindow->session->drag_auto_gang->append((Auto *)keyframe);
2505                         }
2506                 }
2507         } else 
2508 // move the gangs
2509         if (fill_gangs == 0)      
2510         {
2511 // Move the gang!
2512                 for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++)
2513                 {
2514                         FloatAuto *keyframe = (FloatAuto *)mwindow->session->drag_auto_gang->values[i];
2515                         
2516                         keyframe->value += change;
2517                         keyframe->position = fauto->position;
2518                         if(skip->data_type == TRACK_AUDIO)
2519                                 CLAMP(keyframe->value, INFINITYGAIN, MAX_AUDIO_FADE);
2520                         else
2521                                 CLAMP(keyframe->value, 0, MAX_VIDEO_FADE);
2522 //                      keyframe->control_out_position = fauto->control_out_position;
2523 //                      keyframe->control_in_position = fauto->control_in_position;
2524                         keyframe->control_out_value = fauto->control_out_value;
2525                         keyframe->control_in_value = fauto->control_in_value;
2526                 } 
2527
2528         } 
2529         else
2530 // remove the gangs
2531         if (fill_gangs == -1)      
2532         {
2533                 for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++)
2534                 {
2535                         FloatAuto *keyframe = (FloatAuto *)mwindow->session->drag_auto_gang->values[i];
2536                         keyframe->autos->remove_nonsequential(
2537                                         keyframe);
2538                 } 
2539                 mwindow->session->drag_auto_gang->remove_all();
2540         }
2541 }
2542
2543
2544 void TrackCanvas::draw_toggleline(int center_pixel, 
2545         int x1,
2546         int y1,
2547         int x2,
2548         int y2)
2549 {
2550         draw_line(x1, center_pixel + y1, x2, center_pixel + y1);
2551
2552         if(y2 != y1)
2553         {
2554                 draw_line(x2, center_pixel + y1, x2, center_pixel + y2);
2555         }
2556 }
2557
2558 int TrackCanvas::test_toggleline(Autos *autos,
2559         int center_pixel, 
2560         int x1,
2561         int y1,
2562         int x2,
2563         int y2, 
2564         int cursor_x, 
2565         int cursor_y, 
2566         int buttonpress)
2567 {
2568         int result = 0;
2569         if(cursor_x >= x1 && cursor_x < x2)
2570         {
2571                 int miny = center_pixel + y1 - HANDLE_W / 2;
2572                 int maxy = center_pixel + y1 + HANDLE_W / 2;
2573                 if(cursor_y >= miny && cursor_y < maxy) 
2574                 {
2575                         result = 1;
2576
2577 // Menu
2578                         if(buttonpress == 3)
2579                         {
2580                         }
2581                         else
2582 // Insert keyframe
2583                         if(buttonpress)
2584                         {
2585                                 Auto *current;
2586                                 double position = (double)(cursor_x +
2587                                                 mwindow->edl->local_session->view_start[pane->number]) * 
2588                                         mwindow->edl->local_session->zoom_sample / 
2589                                         mwindow->edl->session->sample_rate;
2590                                 int64_t unit_position = autos->track->to_units(position, 0);
2591                                 int new_value = (int)((IntAutos*)autos)->get_automation_constant(unit_position, unit_position);
2592
2593                                 mwindow->undo->update_undo_before();
2594
2595                                 current = mwindow->session->drag_auto = autos->insert_auto(unit_position);
2596                                 ((IntAuto*)current)->value = new_value;
2597                                 mwindow->session->drag_start_percentage = current->value_to_percentage();
2598                                 mwindow->session->drag_start_position = current->position;
2599                                 mwindow->session->drag_origin_x = cursor_x;
2600                                 mwindow->session->drag_origin_y = cursor_y;
2601                         }
2602                 }
2603         };
2604
2605         return result;
2606 }
2607
2608 void TrackCanvas::calculate_viewport(Track *track, 
2609         double &view_start,   // Seconds
2610         double &unit_start,
2611         double &view_end,     // Seconds
2612         double &unit_end,
2613         double &yscale,
2614         int &center_pixel,
2615         double &zoom_sample,
2616         double &zoom_units)
2617 {
2618         view_start = (double)mwindow->edl->local_session->view_start[pane->number] * 
2619                 mwindow->edl->local_session->zoom_sample /
2620                 mwindow->edl->session->sample_rate;
2621         unit_start = track->to_doubleunits(view_start);
2622         view_end = (double)(mwindow->edl->local_session->view_start[pane->number] + 
2623                 get_w()) * 
2624                 mwindow->edl->local_session->zoom_sample / 
2625                 mwindow->edl->session->sample_rate;
2626         unit_end = track->to_doubleunits(view_end);
2627         yscale = mwindow->edl->local_session->zoom_track;
2628 //printf("TrackCanvas::calculate_viewport yscale=%.0f\n", yscale);
2629         center_pixel = (int)(track->y_pixel - 
2630                         mwindow->edl->local_session->track_start[pane->number] + 
2631                         yscale / 2) + 
2632                 (mwindow->edl->session->show_titles ? 
2633                         mwindow->theme->get_image("title_bg_data")->get_h() : 
2634                         0);
2635         zoom_sample = mwindow->edl->local_session->zoom_sample;
2636
2637         zoom_units = track->to_doubleunits(zoom_sample / mwindow->edl->session->sample_rate);
2638 }
2639
2640 float TrackCanvas::percentage_to_value(float percentage, 
2641         int is_toggle,
2642         Auto *reference)
2643 {
2644         float result;
2645         if(is_toggle)
2646         {
2647                 if(percentage > 0.5) 
2648                         result = 1;
2649                 else
2650                         result = 0;
2651         }
2652         else
2653         {
2654                 float automation_min = mwindow->edl->local_session->automation_min;
2655                 float automation_max = mwindow->edl->local_session->automation_max;
2656                 float automation_range = automation_max - automation_min;
2657
2658                 result = percentage * automation_range + automation_min;
2659                 if(reference)
2660                 {
2661                         FloatAuto *ptr = (FloatAuto*)reference;
2662                         result -= ptr->value;
2663                 }
2664 //printf("TrackCanvas::percentage_to_value %d %f\n", __LINE__, result);
2665         }
2666         return result;
2667 }
2668
2669
2670 void TrackCanvas::calculate_auto_position(double *x, 
2671         double *y,
2672         double *in_x,
2673         double *in_y,
2674         double *out_x,
2675         double *out_y,
2676         Auto *current,
2677         double unit_start,
2678         double zoom_units,
2679         double yscale)
2680 {
2681         float automation_min = mwindow->edl->local_session->automation_min;
2682         float automation_max = mwindow->edl->local_session->automation_max;
2683         float automation_range = automation_max - automation_min;
2684         FloatAuto *ptr = (FloatAuto*)current;
2685         *x = (double)(ptr->position - unit_start) / zoom_units;
2686         *y = ((ptr->value - automation_min) /
2687                 automation_range - 0.5) * 
2688                 -yscale;
2689
2690         if(in_x)
2691         {
2692 //              if(!EQUIV(ptr->control_in_value, 0.0))
2693                         *in_x = *x - mwindow->theme->control_pixels;
2694 //              else
2695 //                      *in_x = *x;
2696
2697 //              *in_x = (double)(ptr->position + 
2698 //                      ptr->control_in_position - 
2699 //                      unit_start) /
2700 //                      zoom_units;
2701         }
2702
2703         if(in_y)
2704         {
2705                 *in_y = (((ptr->value + ptr->control_in_value) -
2706                         automation_min) /
2707                         automation_range - 0.5) *
2708                         -yscale;
2709         }
2710
2711         if(out_x)
2712         {
2713 //              if(!EQUIV(ptr->control_out_value, 0.0))
2714                         *out_x = *x + mwindow->theme->control_pixels;
2715 //              else
2716 //                      *out_x = *x;
2717
2718 //              *out_x = (double)(ptr->position + 
2719 //                      ptr->control_out_position - 
2720 //                      unit_start) /
2721 //                      zoom_units;
2722         }
2723
2724         if(out_y)
2725         {
2726                 *out_y = (((ptr->value + ptr->control_out_value) -
2727                         automation_min) /
2728                         automation_range - 0.5) *
2729                         -yscale;
2730         }
2731 }
2732
2733
2734
2735
2736
2737 int TrackCanvas::do_float_autos(Track *track, 
2738                 Autos *autos, 
2739                 int cursor_x, 
2740                 int cursor_y, 
2741                 int draw, 
2742                 int buttonpress,
2743                 int x_offset,
2744                 int y_offset,
2745                 int color,
2746                 Auto* &auto_instance)
2747 {
2748         int result = 0;
2749
2750         double view_start;
2751         double unit_start;
2752         double view_end;
2753         double unit_end;
2754         double yscale;
2755         int center_pixel;
2756         double zoom_sample;
2757         double zoom_units;
2758         double ax, ay, ax2, ay2;
2759         double in_x2, in_y2, out_x2, out_y2;
2760         int draw_auto;
2761         double slope;
2762         //int skip = 0;
2763         
2764         auto_instance = 0;
2765
2766         if(draw) set_color(color);
2767
2768         calculate_viewport(track, 
2769                 view_start,
2770                 unit_start,
2771                 view_end,
2772                 unit_end,
2773                 yscale,
2774                 center_pixel,
2775                 zoom_sample,
2776                 zoom_units);
2777
2778
2779
2780 // Get first auto before start
2781         Auto *current = 0;
2782         Auto *previous = 0;
2783         for(current = autos->last; 
2784                 current && current->position >= unit_start; 
2785                 current = PREVIOUS)
2786                 ;
2787
2788         if(current)
2789         {
2790                 calculate_auto_position(&ax, 
2791                         &ay,
2792                         0,
2793                         0,
2794                         0,
2795                         0,
2796                         current,
2797                         unit_start,
2798                         zoom_units,
2799                         yscale);
2800                 current = NEXT;
2801         }
2802         else
2803         {
2804                 current = autos->first ? autos->first : autos->default_auto;
2805                 if(current)
2806                 {
2807                         calculate_auto_position(&ax, 
2808                                 &ay,
2809                                 0,
2810                                 0,
2811                                 0,
2812                                 0,
2813                                 current,
2814                                 unit_start,
2815                                 zoom_units,
2816                                 yscale);
2817                         ax = 0;
2818                 }
2819                 else
2820                 {
2821                         ax = 0;
2822                         ay = 0;
2823                 }
2824         }
2825
2826
2827
2828
2829
2830         do
2831         {
2832                 //skip = 0;
2833                 draw_auto = 1;
2834
2835                 if(current)
2836                 {
2837                         calculate_auto_position(&ax2, 
2838                                 &ay2,
2839                                 &in_x2,
2840                                 &in_y2,
2841                                 &out_x2,
2842                                 &out_y2,
2843                                 current,
2844                                 unit_start,
2845                                 zoom_units,
2846                                 yscale);
2847                 }
2848                 else
2849                 {
2850                         ax2 = get_w();
2851                         ay2 = ay;
2852                         //skip = 1;
2853                 }
2854
2855                 slope = (ay2 - ay) / (ax2 - ax);
2856
2857                 if(ax2 > get_w())
2858                 {
2859                         draw_auto = 0;
2860                         ax2 = get_w();
2861                         ay2 = ay + slope * (get_w() - ax);
2862                 }
2863                 
2864                 if(ax < 0)
2865                 {
2866                         ay = ay + slope * (0 - ax);
2867                         ax = 0;
2868                 }
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883 // Draw handle
2884                 if(current && !result)
2885                 {
2886                         if(current != autos->default_auto)
2887                         {
2888                                 if(!draw)
2889                                 {
2890                                         if(track->record)
2891                                                 result = test_floatauto(current, 
2892                                                         (int)ax2, 
2893                                                         (int)ay2, 
2894                                                         (int)in_x2,
2895                                                         (int)in_y2,
2896                                                         (int)out_x2,
2897                                                         (int)out_y2,
2898                                                         (int)center_pixel, 
2899                                                         (int)yscale, 
2900                                                         cursor_x, 
2901                                                         cursor_y, 
2902                                                         buttonpress);
2903                                         if (result) 
2904                                                 auto_instance = current;
2905                                 }
2906                                 else
2907                                 if(draw_auto)
2908                                         draw_floatauto(current, 
2909                                                 (int)ax2 + x_offset, 
2910                                                 (int)ay2, 
2911                                                 (int)in_x2 + x_offset,
2912                                                 (int)in_y2,
2913                                                 (int)out_x2 + x_offset,
2914                                                 (int)out_y2,
2915                                                 (int)center_pixel + y_offset, 
2916                                                 (int)yscale);
2917                         }
2918                 }
2919
2920
2921
2922
2923
2924 // Draw joining line
2925                 if(!draw)
2926                 {
2927                         if(!result)
2928                         {
2929                                 if(track->record /* && buttonpress != 3 */)
2930                                 {
2931                                         result = test_floatline(center_pixel, 
2932                                                 (FloatAutos*)autos,
2933                                                 unit_start,
2934                                                 zoom_units,
2935                                                 yscale,
2936                                                 (int)ax,
2937 // Exclude auto coverage from the end of the line.  The auto overlaps
2938                                                 (int)ax2 - HANDLE_W / 2,
2939                                                 cursor_x, 
2940                                                 cursor_y, 
2941                                                 buttonpress);
2942                                 }
2943                         }
2944                 }
2945                 else
2946                         draw_floatline(center_pixel + y_offset,
2947                                 (FloatAuto*)previous,
2948                                 (FloatAuto*)current,
2949                                 (FloatAutos*)autos,
2950                                 unit_start,
2951                                 zoom_units,
2952                                 yscale,
2953                                 (int)ax, 
2954                                 (int)ay, 
2955                                 (int)ax2, 
2956                                 (int)ay2);
2957
2958
2959
2960
2961
2962
2963
2964                 if(current)
2965                 {
2966                         previous = current;
2967                         current = NEXT;
2968                 }
2969
2970
2971
2972                 ax = ax2;
2973                 ay = ay2;
2974         }while(current && 
2975                 current->position <= unit_end && 
2976                 !result);
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986         if(ax < get_w() && !result)
2987         {
2988                 ax2 = get_w();
2989                 ay2 = ay;
2990                 if(!draw)
2991                 {
2992                         if(track->record /* && buttonpress != 3 */)
2993                         {
2994                                 result = test_floatline(center_pixel, 
2995                                         (FloatAutos*)autos,
2996                                         unit_start,
2997                                         zoom_units,
2998                                         yscale,
2999                                         (int)ax,
3000                                         (int)ax2,
3001                                         cursor_x, 
3002                                         cursor_y, 
3003                                         buttonpress);
3004                         }
3005                 }
3006                 else
3007                         draw_floatline(center_pixel + y_offset, 
3008                                 (FloatAuto*)previous,
3009                                 (FloatAuto*)current,
3010                                 (FloatAutos*)autos,
3011                                 unit_start,
3012                                 zoom_units,
3013                                 yscale,
3014                                 (int)ax, 
3015                                 (int)ay, 
3016                                 (int)ax2, 
3017                                 (int)ay2);
3018         }
3019
3020
3021
3022
3023
3024
3025
3026
3027         return result;
3028 }
3029
3030
3031 int TrackCanvas::do_int_autos(Track *track, 
3032                 Autos *autos, 
3033                 int cursor_x, 
3034                 int cursor_y, 
3035                 int draw, 
3036                 int buttonpress,
3037                 int x_offset,
3038                 int y_offset,
3039                 int color,
3040                 Auto * &auto_instance)
3041 {
3042         int result = 0;
3043         double view_start;
3044         double unit_start;
3045         double view_end;
3046         double unit_end;
3047         double yscale;
3048         int center_pixel;
3049         double zoom_sample;
3050         double zoom_units;
3051         double ax, ay, ax2, ay2;
3052
3053         auto_instance = 0;
3054
3055         if(draw) set_color(color);
3056
3057         calculate_viewport(track, 
3058                 view_start,
3059                 unit_start,
3060                 view_end,
3061                 unit_end,
3062                 yscale,
3063                 center_pixel,
3064                 zoom_sample,
3065                 zoom_units);
3066
3067
3068         double high = -yscale * 0.8 / 2;
3069         double low = yscale * 0.8 / 2;
3070
3071 // Get first auto before start
3072         Auto *current;
3073         for(current = autos->last; current && current->position >= unit_start; current = PREVIOUS)
3074                 ;
3075
3076         if(current)
3077         {
3078                 ax = 0;
3079                 ay = ((IntAuto*)current)->value > 0 ? high : low;
3080                 current = NEXT;
3081         }
3082         else
3083         {
3084                 current = autos->first ? autos->first : autos->default_auto;
3085                 if(current)
3086                 {
3087                         ax = 0;
3088                         ay = ((IntAuto*)current)->value > 0 ? high : low;
3089                 }
3090                 else
3091                 {
3092                         ax = 0;
3093                         ay = yscale;
3094                 }
3095         }
3096
3097         do
3098         {
3099                 if(current)
3100                 {
3101                         ax2 = (double)(current->position - unit_start) / zoom_units;
3102                         ay2 = ((IntAuto*)current)->value > 0 ? high : low;
3103                 }
3104                 else
3105                 {
3106                         ax2 = get_w();
3107                         ay2 = ay;
3108                 }
3109
3110                 if(ax2 > get_w()) ax2 = get_w();
3111
3112             if(current && !result) 
3113                 {
3114                         if(current != autos->default_auto)
3115                         {
3116                                 if(!draw)
3117                                 {
3118                                         if(track->record)
3119                                         {
3120                                                 result = test_auto(current, 
3121                                                         (int)ax2, 
3122                                                         (int)ay2, 
3123                                                         (int)center_pixel, 
3124                                                         (int)yscale, 
3125                                                         cursor_x, 
3126                                                         cursor_y, 
3127                                                         buttonpress);
3128                                                 if (result)
3129                                                         auto_instance = current;
3130                                         }
3131                                 }
3132                                 else
3133                                         draw_auto(current, 
3134                                                 (int)ax2 + x_offset, 
3135                                                 (int)ay2 + y_offset, 
3136                                                 (int)center_pixel, 
3137                                                 (int)yscale);
3138                         }
3139
3140                         current = NEXT;
3141                 }
3142
3143                 if(!draw)
3144                 {
3145                         if(!result)
3146                         {
3147                                 if(track->record /* && buttonpress != 3 */)
3148                                 {
3149                                         result = test_toggleline(autos, 
3150                                                 center_pixel, 
3151                                                 (int)ax, 
3152                                                 (int)ay, 
3153                                                 (int)ax2, 
3154                                                 (int)ay2,
3155                                                 cursor_x, 
3156                                                 cursor_y, 
3157                                                 buttonpress);
3158                                 }
3159                         }
3160                 }
3161                 else
3162                         draw_toggleline(center_pixel + y_offset, 
3163                                 (int)ax, 
3164                                 (int)ay, 
3165                                 (int)ax2, 
3166                                 (int)ay2);
3167
3168                 ax = ax2;
3169                 ay = ay2;
3170         }while(current && current->position <= unit_end && !result);
3171
3172         if(ax < get_w() && !result)
3173         {
3174                 ax2 = get_w();
3175                 ay2 = ay;
3176                 if(!draw)
3177                 {
3178                         if(track->record /* && buttonpress != 3 */)
3179                         {
3180                                 result = test_toggleline(autos,
3181                                         center_pixel, 
3182                                         (int)ax, 
3183                                         (int)ay, 
3184                                         (int)ax2, 
3185                                         (int)ay2,
3186                                         cursor_x, 
3187                                         cursor_y, 
3188                                         buttonpress);
3189                         }
3190                 }
3191                 else
3192                         draw_toggleline(center_pixel + y_offset, 
3193                                 (int)ax, 
3194                                 (int)ay, 
3195                                 (int)ax2, 
3196                                 (int)ay2);
3197         }
3198         return result;
3199 }
3200
3201 int TrackCanvas::do_autos(Track *track, 
3202                 Autos *autos, 
3203                 int cursor_x, 
3204                 int cursor_y, 
3205                 int draw, 
3206                 int buttonpress,
3207                 BC_Pixmap *pixmap,
3208                 Auto * &auto_instance,
3209                 int &rerender)
3210 {
3211         int result = 0;
3212
3213         double view_start;
3214         double unit_start;
3215         double view_end;
3216         double unit_end;
3217         double yscale;
3218         int center_pixel;
3219         double zoom_sample;
3220         double zoom_units;
3221
3222         calculate_viewport(track, 
3223                 view_start,
3224                 unit_start,
3225                 view_end,
3226                 unit_end,
3227                 yscale,
3228                 center_pixel,
3229                 zoom_sample,
3230                 zoom_units);
3231
3232         Auto *current;
3233         auto_instance = 0;
3234
3235         for(current = autos->first; current && !result; current = NEXT)
3236         {
3237                 if(current->position >= unit_start && current->position < unit_end)
3238                 {
3239                         int64_t x, y;
3240                         x = (int64_t)((double)(current->position - unit_start) / 
3241                                 zoom_units - (pixmap->get_w() / 2 + 0.5));
3242                         y = center_pixel - pixmap->get_h() / 2;
3243
3244                         if(!draw)
3245                         {
3246                                 if(cursor_x >= x && cursor_y >= y &&
3247                                         cursor_x < x + pixmap->get_w() &&
3248                                         cursor_y < y + pixmap->get_h())
3249                                 {
3250                                         result = 1;
3251                                         auto_instance = current;
3252
3253                                         if(buttonpress && (buttonpress != 3))
3254                                         {
3255                                                 mwindow->session->drag_auto = current;
3256                                                 mwindow->session->drag_start_position = current->position;
3257                                                 mwindow->session->drag_origin_x = cursor_x;
3258                                                 mwindow->session->drag_origin_y = cursor_y;
3259
3260                                                 double position = autos->track->from_units(current->position);
3261                                                 double center = (mwindow->edl->local_session->get_selectionstart(1) +
3262                                                         mwindow->edl->local_session->get_selectionend(1)) / 
3263                                                         2;
3264
3265                                                 if(!shift_down())
3266                                                 {
3267                                                         mwindow->edl->local_session->set_selectionstart(position);
3268                                                         mwindow->edl->local_session->set_selectionend(position);
3269                                                 }
3270                                                 else
3271                                                 if(position < center)
3272                                                 {
3273                                                         mwindow->edl->local_session->set_selectionstart(position);
3274                                                 }
3275                                                 else
3276                                                         mwindow->edl->local_session->set_selectionend(position);
3277
3278                                                 rerender = 1;
3279                                         }
3280                                 }
3281                         }
3282                         else
3283                                 draw_pixmap(pixmap, x, y);
3284                 }
3285         }
3286
3287
3288         return result;
3289 }
3290
3291 // so this means it is always >0 when keyframe is found 
3292 int TrackCanvas::do_plugin_autos(Track *track, 
3293                 int cursor_x, 
3294                 int cursor_y, 
3295                 int draw, 
3296                 int buttonpress,
3297                 Plugin* &keyframe_plugin,
3298                 KeyFrame* &keyframe_instance)
3299 {
3300         int result = 0;
3301
3302         double view_start;
3303         double unit_start;
3304         double view_end;
3305         double unit_end;
3306         double yscale;
3307         int center_pixel;
3308         double zoom_sample;
3309         double zoom_units;
3310
3311         if(!track->expand_view) return 0;
3312
3313         calculate_viewport(track, 
3314                 view_start,
3315                 unit_start,
3316                 view_end,
3317                 unit_end,
3318                 yscale,
3319                 center_pixel,
3320                 zoom_sample,
3321                 zoom_units);
3322
3323
3324
3325         for(int i = 0; i < track->plugin_set.total && !result; i++)
3326         {
3327                 PluginSet *plugin_set = track->plugin_set.values[i];
3328                 int center_pixel = (int)(track->y_pixel - 
3329                         mwindow->edl->local_session->track_start[pane->number] + 
3330                         mwindow->edl->local_session->zoom_track +
3331                         (i + 0.5) * mwindow->theme->get_image("plugin_bg_data")->get_h() + 
3332                         (mwindow->edl->session->show_titles ? mwindow->theme->get_image("title_bg_data")->get_h() : 0));
3333
3334                 for(Plugin *plugin = (Plugin*)plugin_set->first; 
3335                         plugin && !result; 
3336                         plugin = (Plugin*)plugin->next)
3337                 {
3338                         for(KeyFrame *keyframe = (KeyFrame*)plugin->keyframes->first; 
3339                                 keyframe && !result; 
3340                                 keyframe = (KeyFrame*)keyframe->next)
3341                         {
3342 //printf("TrackCanvas::draw_plugin_autos 3 %d\n", keyframe->position);
3343                                 if(keyframe->position >= unit_start && keyframe->position < unit_end)
3344                                 {
3345                                         int64_t x = (int64_t)((keyframe->position - unit_start) / zoom_units);
3346                                         int y = center_pixel - keyframe_pixmap->get_h() / 2;
3347
3348 //printf("TrackCanvas::draw_plugin_autos 4 %d %d\n", x, center_pixel);
3349                                         if(!draw)
3350                                         {
3351                                                 if(cursor_x >= x && cursor_y >= y &&
3352                                                         cursor_x < x + keyframe_pixmap->get_w() &&
3353                                                         cursor_y < y + keyframe_pixmap->get_h())
3354                                                 {
3355                                                         result = 1;
3356                                                         keyframe_plugin = plugin;
3357                                                         keyframe_instance = keyframe;
3358
3359                                                         if(buttonpress)
3360                                                         {
3361                                                                 mwindow->session->drag_auto = keyframe;
3362                                                                 mwindow->session->drag_start_position = keyframe->position;
3363                                                                 mwindow->session->drag_origin_x = cursor_x;
3364                                                                 mwindow->session->drag_origin_y = cursor_y;
3365
3366                                                                 double position = track->from_units(keyframe->position);
3367                                                                 double center = (mwindow->edl->local_session->get_selectionstart(1) +
3368                                                                         mwindow->edl->local_session->get_selectionend(1)) / 
3369                                                                         2;
3370
3371                                                                 if(!shift_down())
3372                                                                 {
3373                                                                         mwindow->edl->local_session->set_selectionstart(position);
3374                                                                         mwindow->edl->local_session->set_selectionend(position);
3375                                                                 }
3376                                                                 else
3377                                                                 if(position < center)
3378                                                                 {
3379                                                                         mwindow->edl->local_session->set_selectionstart(position);
3380                                                                 }
3381                                                                 else
3382                                                                         mwindow->edl->local_session->set_selectionend(position);
3383                                                         }
3384                                                 }
3385                                         }
3386                                         else
3387                                                 draw_pixmap(keyframe_pixmap, 
3388                                                         x, 
3389                                                         y);
3390                                 }
3391                         }
3392                 }
3393         }
3394
3395
3396
3397 //      if(buttonpress && buttonpress != 3 && result)
3398 //      {
3399 //              mwindow->undo->update_undo_before();
3400 //      }
3401
3402         return result;
3403 }
3404
3405 void TrackCanvas::draw_overlays()
3406 {
3407         int new_cursor, update_cursor, rerender;
3408
3409 // Move background pixmap to foreground pixmap
3410         draw_pixmap(background_pixmap, 
3411                 0, 
3412                 0,
3413                 get_w(),
3414                 get_h(),
3415                 0,
3416                 0);
3417
3418 // In/Out points
3419         draw_inout_points();
3420
3421 // Transitions
3422         if(mwindow->edl->session->auto_conf->transitions) draw_transitions();
3423
3424 // Plugins
3425         draw_plugins();
3426
3427 // Loop points
3428         draw_loop_points();
3429         draw_brender_start();
3430
3431 // Highlighted areas
3432         draw_highlighting();
3433
3434 // Automation
3435         do_keyframes(0, 
3436                 0, 
3437                 1, 
3438                 0, 
3439                 new_cursor, 
3440                 update_cursor,
3441                 rerender);
3442
3443 // Selection cursor
3444         if(pane->cursor) pane->cursor->restore(1);
3445
3446 // Handle dragging
3447         draw_drag_handle();
3448
3449 // Playback cursor
3450         draw_playback_cursor();
3451
3452         show_window(0);
3453 }
3454
3455 int TrackCanvas::activate()
3456 {
3457         if(!active)
3458         {
3459 //printf("TrackCanvas::activate %d %d\n", __LINE__, pane->number);
3460 //BC_Signals::dump_stack();
3461                 get_top_level()->deactivate();
3462                 active = 1;
3463                 set_active_subwindow(this);
3464                 pane->cursor->activate();
3465                 gui->focused_pane = pane->number;
3466         }
3467         return 0;
3468 }
3469
3470 int TrackCanvas::deactivate()
3471 {
3472         if(active)
3473         {
3474                 active = 0;
3475                 pane->cursor->deactivate();
3476         }
3477         return 0;
3478 }
3479
3480
3481 void TrackCanvas::update_drag_handle()
3482 {
3483         double new_position;
3484
3485         new_position = 
3486                 (double)(get_cursor_x() + 
3487                 mwindow->edl->local_session->view_start[pane->number]) *
3488                 mwindow->edl->local_session->zoom_sample /
3489                 mwindow->edl->session->sample_rate;
3490         new_position = 
3491                 mwindow->edl->align_to_frame(new_position, 0);
3492
3493
3494         if(new_position != mwindow->session->drag_position)
3495         {
3496                 mwindow->session->drag_position = new_position;
3497                 gui->mainclock->update(new_position);
3498                 
3499                 
3500                 timebar_position = new_position;
3501                 gui->update_timebar(0);
3502 // Que the CWindow.  Doesn't do anything if selectionstart and selection end 
3503 // aren't changed.
3504 //              mwindow->cwindow->update(1, 0, 0);
3505         }
3506 }
3507
3508 int TrackCanvas::update_drag_edit()
3509 {
3510         int result = 0;
3511         
3512         
3513         
3514         return result;
3515 }
3516
3517 int TrackCanvas::get_drag_values(float *percentage, 
3518         int64_t *position,
3519         int do_clamp,
3520         int cursor_x,
3521         int cursor_y,
3522         Auto *current)
3523 {
3524         //int x = cursor_x - mwindow->session->drag_origin_x;
3525         //int y = cursor_y - mwindow->session->drag_origin_y;
3526         *percentage = 0;
3527         *position = 0;
3528
3529         if(!current->autos->track->record) return 1;
3530         double view_start;
3531         double unit_start;
3532         double view_end;
3533         double unit_end;
3534         double yscale;
3535         int center_pixel;
3536         double zoom_sample;
3537         double zoom_units;
3538
3539         calculate_viewport(current->autos->track, 
3540                 view_start,
3541                 unit_start,
3542                 view_end,
3543                 unit_end,
3544                 yscale,
3545                 center_pixel,
3546                 zoom_sample,
3547                 zoom_units);
3548
3549         *percentage = (float)(mwindow->session->drag_origin_y - cursor_y) /
3550                 yscale + 
3551                 mwindow->session->drag_start_percentage;
3552         if(do_clamp) CLAMP(*percentage, 0, 1);
3553
3554         *position = Units::to_int64(zoom_units *
3555                 (cursor_x - mwindow->session->drag_origin_x) +
3556                 mwindow->session->drag_start_position + 0.5);
3557
3558         if((do_clamp) && *position < 0) *position = 0;
3559         return 0;
3560 }
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571 int TrackCanvas::update_drag_floatauto(int cursor_x, int cursor_y)
3572 {
3573         FloatAuto *current = (FloatAuto*)mwindow->session->drag_auto;
3574         float value;
3575         float old_value;
3576         float percentage;
3577         int64_t position;
3578         int result = 0;
3579
3580         if(get_drag_values(&percentage, 
3581                 &position,
3582                 mwindow->session->drag_handle == 0,
3583                 cursor_x,
3584                 cursor_y,
3585                 current)) return 0;
3586
3587 //printf("TrackCanvas::update_drag_floatauto %d %f\n", __LINE__, percentage);
3588
3589
3590         switch(mwindow->session->drag_handle)
3591         {
3592 // Center
3593                 case 0:
3594 // Snap to nearby values
3595                         old_value = current->value;
3596                         if(shift_down())
3597                         {
3598                                 double value1 = 0.;
3599                                 double value2 = 0.;
3600                                 double distance1 = percentage_to_value(0., 0, 0);
3601                                 double distance2 =  percentage_to_value(1., 0, 0);
3602                                 value = percentage_to_value(percentage, 0, 0);
3603
3604                                 if(current->previous)
3605                                 {
3606                                         value1 = ((FloatAuto*)current->previous)->value;
3607                                         distance1 = fabs(value - value1);
3608                                         current->value = value1;
3609                                 }
3610
3611                                 if(current->next)
3612                                 {
3613                                         value2 = ((FloatAuto*)current->next)->value;
3614                                         distance2 = fabs(value - value2);
3615                                         if(!current->previous || distance2 < distance1)
3616                                         {
3617                                                 current->value = value2;
3618                                         }
3619                                 }
3620
3621                                 if(!current->previous && !current->next)
3622                                 {
3623                                         current->value = ((FloatAutos*)current->autos)->default_;
3624                                 }
3625                                 value = current->value;
3626                         }
3627                         else
3628                                 value = percentage_to_value(percentage, 0, 0);
3629
3630                         if(value != old_value || position != current->position)
3631                         {
3632                                 result = 1;
3633                                 float change = value - old_value;               
3634                                 current->value = value;
3635                                 current->position = position;
3636                                 synchronize_autos(change, current->autos->track, current, 0);
3637
3638                                 char string[BCTEXTLEN], string2[BCTEXTLEN];
3639                                 Units::totext(string2, 
3640                                         current->autos->track->from_units(current->position),
3641                                         mwindow->edl->session->time_format,
3642                                         mwindow->edl->session->sample_rate,
3643                                         mwindow->edl->session->frame_rate,
3644                                         mwindow->edl->session->frames_per_foot);
3645                                 sprintf(string, "%s, %.2f", string2, current->value);
3646                                 gui->show_message(string);
3647                         }
3648                         break;
3649
3650 // In control
3651                 case 1:
3652                         value = percentage_to_value(percentage, 0, current);
3653                         position = MIN(0, position);
3654                         if(value != current->control_in_value)
3655                         {
3656                                 result = 1;
3657                                 current->control_in_value = value;
3658                                 synchronize_autos(0, current->autos->track, current, 0);
3659
3660                                 char string[BCTEXTLEN];
3661                                 sprintf(string, "%.2f", current->control_in_value);
3662                                 gui->show_message(string);
3663                         }
3664                         break;
3665
3666 // Out control
3667                 case 2:
3668                         value = percentage_to_value(percentage, 0, current);
3669                         position = MAX(0, position);
3670                         if(value != current->control_out_value)
3671                         {
3672                                 result = 1;
3673                                 current->control_out_value = value;
3674                                 synchronize_autos(0, current->autos->track, current, 0);
3675
3676                                 char string[BCTEXTLEN];
3677                                 sprintf(string, "%.2f", 
3678                                         ((FloatAuto*)current)->control_out_value);
3679                                 gui->show_message(string);
3680                         }
3681                         break;
3682         }
3683
3684         return result;
3685 }
3686
3687 int TrackCanvas::update_drag_toggleauto(int cursor_x, int cursor_y)
3688 {
3689         IntAuto *current = (IntAuto*)mwindow->session->drag_auto;
3690         float percentage;
3691         int64_t position;
3692         int result = 0;
3693
3694         if(get_drag_values(&percentage, 
3695                 &position,
3696                 1,
3697                 cursor_x,
3698                 cursor_y,
3699                 current)) return 0;
3700
3701
3702         int value = (int)percentage_to_value(percentage, 1, 0);
3703
3704         if(value != current->value || position != current->position)
3705         {
3706                 result = 1;
3707                 current->value = value;
3708                 current->position = position;
3709
3710                 char string[BCTEXTLEN], string2[BCTEXTLEN];
3711                 Units::totext(string2, 
3712                         current->autos->track->from_units(current->position),
3713                         mwindow->edl->session->time_format,
3714                         mwindow->edl->session->sample_rate,
3715                         mwindow->edl->session->frame_rate,
3716                         mwindow->edl->session->frames_per_foot);
3717                 sprintf(string, "%s, %d", string2, current->value);
3718                 gui->show_message(string);
3719         }
3720
3721         return result;
3722 }
3723
3724 // Autos which can't change value through dragging.
3725
3726 int TrackCanvas::update_drag_auto(int cursor_x, int cursor_y)
3727 {
3728         Auto *current = (Auto*)mwindow->session->drag_auto;
3729         float percentage;
3730         int64_t position;
3731         int result = 0;
3732
3733         if(get_drag_values(&percentage, 
3734                 &position,
3735                 1,
3736                 cursor_x,
3737                 cursor_y,
3738                 current)) return 0;
3739
3740
3741         if(position != current->position)
3742         {
3743                 result = 1;
3744                 current->position = position;
3745
3746                 char string[BCTEXTLEN];
3747                 Units::totext(string, 
3748                         current->autos->track->from_units(current->position),
3749                         mwindow->edl->session->time_format,
3750                         mwindow->edl->session->sample_rate,
3751                         mwindow->edl->session->frame_rate,
3752                         mwindow->edl->session->frames_per_foot);
3753                 gui->show_message(string);
3754
3755                 double position_f = current->autos->track->from_units(current->position);
3756                 double center_f = (mwindow->edl->local_session->get_selectionstart(1) +
3757                         mwindow->edl->local_session->get_selectionend(1)) / 
3758                         2;
3759                 if(!shift_down())
3760                 {
3761                         mwindow->edl->local_session->set_selectionstart(position_f);
3762                         mwindow->edl->local_session->set_selectionend(position_f);
3763                 }
3764                 else
3765                 if(position_f < center_f)
3766                 {
3767                         mwindow->edl->local_session->set_selectionstart(position_f);
3768                 }
3769                 else
3770                         mwindow->edl->local_session->set_selectionend(position_f);
3771         }
3772
3773
3774         return result;
3775 }
3776
3777 int TrackCanvas::update_drag_pluginauto(int cursor_x, int cursor_y)
3778 {
3779         KeyFrame *current = (KeyFrame*)mwindow->session->drag_auto;
3780         float percentage;
3781         int64_t position;
3782         int result = 0;
3783
3784         if(get_drag_values(&percentage, &position, 1,
3785                 cursor_x, cursor_y, current)) return 0;
3786
3787         if(position != current->position)
3788         {
3789 //      printf("uida: autos: %p, track: %p ta: %p\n", current->autos, current->autos->track, current->autos->track->automation);
3790                 Track *track = current->autos->track;
3791                 //PluginAutos *pluginautos = (PluginAutos *)current->autos;
3792                 Plugin *plugin = 0;
3793 // figure out the correct pluginset & correct plugin 
3794                 int found = 0;
3795                 for(int i = 0; i < track->plugin_set.total; i++)
3796                 {
3797                         PluginSet *pluginset = track->plugin_set.values[i];
3798                         for(plugin = (Plugin *)pluginset->first; plugin; plugin = (Plugin *)plugin->next)
3799                         {
3800                                 KeyFrames *keyframes = plugin->keyframes;
3801                                 for(KeyFrame *currentkeyframe = (KeyFrame *)keyframes->first; currentkeyframe; currentkeyframe = (KeyFrame *) currentkeyframe->next)
3802                                 {
3803                                         if (currentkeyframe == current) 
3804                                         {
3805                                                 found = 1;
3806                                                 break;
3807                                         }
3808  
3809                                 }
3810                                 if (found) break;                       
3811                         }
3812                         if (found) break;                       
3813                 }       
3814         
3815                 mwindow->session->plugin_highlighted = plugin;
3816                 mwindow->session->track_highlighted = track;
3817                 result = 1;
3818                 current->position = position;
3819
3820                 char string[BCTEXTLEN];
3821                 Units::totext(string, 
3822                         current->autos->track->from_units(current->position),
3823                         mwindow->edl->session->time_format,
3824                         mwindow->edl->session->sample_rate,
3825                         mwindow->edl->session->frame_rate,
3826                         mwindow->edl->session->frames_per_foot);
3827                 gui->show_message(string);
3828
3829                 double position_f = current->autos->track->from_units(current->position);
3830                 double center_f = (mwindow->edl->local_session->get_selectionstart(1) +
3831                         mwindow->edl->local_session->get_selectionend(1)) / 
3832                         2;
3833                 if(!shift_down())
3834                 {
3835                         mwindow->edl->local_session->set_selectionstart(position_f);
3836                         mwindow->edl->local_session->set_selectionend(position_f);
3837                 }
3838                 else
3839                 if(position_f < center_f)
3840                 {
3841                         mwindow->edl->local_session->set_selectionstart(position_f);
3842                 }
3843                 else
3844                         mwindow->edl->local_session->set_selectionend(position_f);
3845         }
3846
3847
3848         return result;
3849 }
3850
3851 void TrackCanvas::update_drag_caption()
3852 {
3853         switch(mwindow->session->current_operation)
3854         {
3855                 case DRAG_FADE:
3856                         break;
3857         }
3858 }
3859
3860
3861
3862 int TrackCanvas::cursor_motion_event()
3863 {
3864         int result = 0;
3865         int cursor_x = 0;
3866         int cursor_y = 0;
3867         int update_clock = 0;
3868         int update_zoom = 0;
3869         int update_scroll = 0;
3870         int update_overlay = 0;
3871         int update_cursor = 0;
3872         int new_cursor = 0;
3873         int rerender = 0;
3874         double position = 0.;
3875 //printf("TrackCanvas::cursor_motion_event %d\n", __LINE__);
3876
3877 // Default cursor
3878         switch(mwindow->edl->session->editing_mode)
3879         {
3880                 case EDITING_ARROW: new_cursor = ARROW_CURSOR; break;
3881                 case EDITING_IBEAM: new_cursor = IBEAM_CURSOR; break;
3882         }
3883
3884         switch(mwindow->session->current_operation)
3885         {
3886                 case DRAG_EDITHANDLE1:
3887 // Outside threshold.  Upgrade status
3888                         if(active)
3889                         {
3890                                 if(labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W)
3891                                 {
3892                                         mwindow->session->current_operation = DRAG_EDITHANDLE2;
3893                                         update_overlay = 1;
3894                                 }
3895                         }
3896                         break;
3897
3898                 case DRAG_EDITHANDLE2:
3899                         if(active)
3900                         {
3901                                 update_drag_handle();
3902                                 update_overlay = 1;
3903                         }
3904                         break;
3905
3906                 case DRAG_PLUGINHANDLE1:
3907                         if(active)
3908                         {
3909                                 if(labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W)
3910                                 {
3911                                         mwindow->session->current_operation = DRAG_PLUGINHANDLE2;
3912                                         update_overlay = 1;
3913                                 }
3914                         }
3915                         break;
3916
3917                 case DRAG_PLUGINHANDLE2:
3918                         if(active)
3919                         {
3920                                 update_drag_handle();
3921                                 update_overlay = 1;
3922                         }
3923                         break;
3924
3925 // Rubber band curves
3926                 case DRAG_FADE:
3927                 case DRAG_SPEED:
3928                 case DRAG_CZOOM:
3929                 case DRAG_PZOOM:
3930                 case DRAG_CAMERA_X:
3931                 case DRAG_CAMERA_Y:
3932                 case DRAG_CAMERA_Z:
3933                 case DRAG_PROJECTOR_X:
3934                 case DRAG_PROJECTOR_Y:
3935                 case DRAG_PROJECTOR_Z:
3936                         if(active) rerender = 
3937                                 update_overlay =
3938                                 update_drag_floatauto(get_cursor_x(), get_cursor_y());
3939                         break;
3940
3941                 case DRAG_PLAY:
3942                         if(active) rerender = 
3943                                 update_overlay =
3944                                 update_drag_toggleauto(get_cursor_x(), get_cursor_y());
3945                         break;
3946
3947                 case DRAG_MUTE:
3948                         if(active) rerender = 
3949                                 update_overlay = 
3950                                 update_drag_toggleauto(get_cursor_x(), get_cursor_y());
3951                         break;
3952
3953 // Keyframe icons are sticky
3954                 case DRAG_PAN_PRE:
3955                 case DRAG_MASK_PRE:
3956                 case DRAG_MODE_PRE:
3957                 case DRAG_PLUGINKEY_PRE:
3958                         if(active) 
3959                         {
3960                                 if(labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W)
3961                                 {
3962                                         mwindow->session->current_operation++;
3963                                         update_overlay = 1;
3964
3965                                         mwindow->undo->update_undo_before();
3966                                 }
3967                         }
3968                         break;
3969
3970                 case DRAG_PAN:
3971                 case DRAG_MASK:
3972                 case DRAG_MODE:
3973                         if(active) rerender = 
3974                                 update_overlay = 
3975                                 update_drag_auto(get_cursor_x(), get_cursor_y());
3976                         break;
3977
3978                 case DRAG_PLUGINKEY:
3979                         if(active) rerender = 
3980                                 update_overlay = 
3981                                 update_drag_pluginauto(get_cursor_x(), get_cursor_y());
3982                         break;
3983
3984                 case SELECT_REGION:
3985                         if(active) 
3986                         {
3987                                 cursor_x = get_cursor_x();
3988                                 cursor_y = get_cursor_y();
3989                                 position = (double)(cursor_x + mwindow->edl->local_session->view_start[pane->number]) * 
3990                                         mwindow->edl->local_session->zoom_sample /
3991                                         mwindow->edl->session->sample_rate;
3992
3993                                 position = mwindow->edl->align_to_frame(position, 0);
3994                                 position = MAX(position, 0);
3995
3996                                 if(position < selection_midpoint)
3997                                 {
3998                                         mwindow->edl->local_session->set_selectionend(selection_midpoint);
3999                                         mwindow->edl->local_session->set_selectionstart(position);
4000         // Que the CWindow
4001                                         gui->unlock_window();
4002                                         mwindow->cwindow->update(1, 0, 0, 0, 1);
4003                                         gui->lock_window("TrackCanvas::cursor_motion_event 1");
4004         // Update the faders
4005                                         mwindow->update_plugin_guis();
4006                                         gui->update_patchbay();
4007                                 }
4008                                 else
4009                                 {
4010                                         mwindow->edl->local_session->set_selectionstart(selection_midpoint);
4011                                         mwindow->edl->local_session->set_selectionend(position);
4012         // Don't que the CWindow
4013                                 }
4014
4015                                 timebar_position = mwindow->edl->local_session->get_selectionend(1);
4016
4017                                 gui->hide_cursor(0);
4018                                 gui->draw_cursor(1);
4019                                 gui->update_timebar(0);
4020                                 gui->flash_canvas(1);
4021                                 result = 1;
4022                                 update_clock = 1;
4023                                 update_zoom = 1;
4024                                 update_scroll = 1;
4025                         }
4026                         break;
4027
4028                 default:
4029                         if(is_event_win() && cursor_inside())
4030                         {
4031 // Update clocks
4032                                 cursor_x = get_cursor_x();
4033                                 position = (double)cursor_x * 
4034                                         (double)mwindow->edl->local_session->zoom_sample / 
4035                                         (double)mwindow->edl->session->sample_rate + 
4036                                         (double)mwindow->edl->local_session->view_start[pane->number] * 
4037                                         (double)mwindow->edl->local_session->zoom_sample / 
4038                                         (double)mwindow->edl->session->sample_rate;
4039                                 position = mwindow->edl->align_to_frame(position, 0);
4040                                 update_clock = 1;
4041
4042 // set all timebars
4043                                 for(int i = 0; i < TOTAL_PANES; i++)
4044                                         if(gui->pane[i]) gui->pane[i]->canvas->timebar_position = position;
4045
4046 //printf("TrackCanvas::cursor_motion_event %d %d %p %p\n", __LINE__, pane->number, pane, pane->timebar);
4047                                 gui->update_timebar(0);
4048
4049 // Update cursor
4050                                 if(do_transitions(get_cursor_x(), 
4051                                                 get_cursor_y(), 
4052                                                 0, 
4053                                                 new_cursor, 
4054                                                 update_cursor))
4055                                 {
4056                                         break;
4057                                 }
4058                                 else
4059 // Update cursor
4060                                 if(do_keyframes(get_cursor_x(), 
4061                                         get_cursor_y(), 
4062                                         0, 
4063                                         0, 
4064                                         new_cursor,
4065                                         update_cursor,
4066                                         rerender))
4067                                 {
4068                                         break;
4069                                 }
4070                                 else
4071 // Edit boundaries
4072                                 if(do_edit_handles(get_cursor_x(), 
4073                                         get_cursor_y(), 
4074                                         0, 
4075                                         new_cursor,
4076                                         update_cursor))
4077                                 {
4078                                         break;
4079                                 }
4080                                 else
4081 // Plugin boundaries
4082                                 if(do_plugin_handles(get_cursor_x(), 
4083                                         get_cursor_y(), 
4084                                         0, 
4085                                         new_cursor,
4086                                         update_cursor))
4087                                 {
4088                                         break;
4089                                 }
4090                                 else
4091                                 if(do_edits(get_cursor_x(), 
4092                                         get_cursor_y(), 
4093                                         0, 
4094                                         0, 
4095                                         update_overlay, 
4096                                         rerender,
4097                                         new_cursor,
4098                                         update_cursor))
4099                                 {
4100                                         break;
4101                                 }
4102                         }
4103                         break;
4104         }
4105
4106 //printf("TrackCanvas::cursor_motion_event 1\n");
4107         if(update_cursor && new_cursor != get_cursor())
4108         {
4109                 set_cursor(new_cursor, 0, 1);
4110         }
4111
4112 //printf("TrackCanvas::cursor_motion_event 1 %d\n", rerender);
4113         if(rerender)
4114         {
4115                 mwindow->restart_brender();
4116                 mwindow->sync_parameters(CHANGE_PARAMS);
4117                 mwindow->update_plugin_guis();
4118                 gui->unlock_window();
4119                 mwindow->cwindow->update(1, 0, 0, 0, 1);
4120                 gui->lock_window("TrackCanvas::cursor_motion_event 2");
4121 // Update faders
4122                 gui->update_patchbay();
4123         }
4124
4125
4126         if(update_clock)
4127         {
4128                 if(!mwindow->cwindow->playback_engine->is_playing_back)
4129                         gui->mainclock->update(position);
4130         }
4131
4132         if(update_zoom)
4133         {
4134                 gui->zoombar->update();
4135         }
4136
4137         if(update_scroll)
4138         {
4139                 if(!drag_scroll && 
4140                         (cursor_x >= get_w() || cursor_x < 0 || cursor_y >= get_h() || cursor_y < 0))
4141                         start_dragscroll();
4142                 else
4143                 if(drag_scroll &&
4144                         (cursor_x < get_w() && cursor_x >= 0 && cursor_y < get_h() && cursor_y >= 0))
4145                         stop_dragscroll();
4146         }
4147
4148         if(update_overlay)
4149         {
4150                 gui->draw_overlays(1);
4151         }
4152
4153
4154 //printf("TrackCanvas::cursor_motion_event %d\n", __LINE__);
4155         return result;
4156 }
4157
4158 void TrackCanvas::start_dragscroll()
4159 {
4160         if(!drag_scroll)
4161         {
4162                 drag_scroll = 1;
4163                 set_repeat(BC_WindowBase::get_resources()->scroll_repeat);
4164 //printf("TrackCanvas::start_dragscroll 1\n");
4165         }
4166 }
4167
4168 void TrackCanvas::stop_dragscroll()
4169 {
4170         if(drag_scroll)
4171         {
4172                 drag_scroll = 0;
4173                 unset_repeat(BC_WindowBase::get_resources()->scroll_repeat);
4174 //printf("TrackCanvas::stop_dragscroll 1\n");
4175         }
4176 }
4177
4178 int TrackCanvas::repeat_event(int64_t duration)
4179 {
4180         if(!drag_scroll) return 0;
4181         if(duration != BC_WindowBase::get_resources()->scroll_repeat) return 0;
4182
4183         int sample_movement = 0;
4184         int track_movement = 0;
4185         int64_t x_distance = 0;
4186         int64_t y_distance = 0;
4187         double position = 0;
4188         int result = 0;
4189
4190         switch(mwindow->session->current_operation)
4191         {
4192                 case SELECT_REGION:
4193 //printf("TrackCanvas::repeat_event 1 %d\n", mwindow->edl->local_session->view_start);
4194                         if(get_cursor_x() > get_w())
4195                         {
4196                                 x_distance = get_cursor_x() - get_w();
4197                                 sample_movement = 1;
4198                         }
4199                         else
4200                         if(get_cursor_x() < 0)
4201                         {
4202                                 x_distance = get_cursor_x();
4203                                 sample_movement = 1;
4204                         }
4205
4206                         if(get_cursor_y() > get_h())
4207                         {
4208                                 y_distance = get_cursor_y() - get_h();
4209                                 track_movement = 1;
4210                         }
4211                         else
4212                         if(get_cursor_y() < 0)
4213                         {
4214                                 y_distance = get_cursor_y();
4215                                 track_movement = 1;
4216                         }
4217                         result = 1;
4218                         break;
4219         }
4220
4221
4222         if(sample_movement)
4223         {
4224                 position = (double)(get_cursor_x() + 
4225                         mwindow->edl->local_session->view_start[pane->number] + 
4226                         x_distance) * 
4227                         mwindow->edl->local_session->zoom_sample /
4228                         mwindow->edl->session->sample_rate;
4229                 position = mwindow->edl->align_to_frame(position, 0);
4230                 position = MAX(position, 0);
4231
4232 //printf("TrackCanvas::repeat_event 1 %f\n", position);
4233                 switch(mwindow->session->current_operation)
4234                 {
4235                         case SELECT_REGION:
4236                                 if(position < selection_midpoint)
4237                                 {
4238                                         mwindow->edl->local_session->set_selectionend(selection_midpoint);
4239                                         mwindow->edl->local_session->set_selectionstart(position);
4240 // Que the CWindow
4241                                         gui->unlock_window();
4242                                         mwindow->cwindow->update(1, 0, 0);
4243                                         gui->lock_window("TrackCanvas::repeat_event");
4244 // Update the faders
4245                                         mwindow->update_plugin_guis();
4246                                         gui->update_patchbay();
4247                                 }
4248                                 else
4249                                 {
4250                                         mwindow->edl->local_session->set_selectionstart(selection_midpoint);
4251                                         mwindow->edl->local_session->set_selectionend(position);
4252 // Don't que the CWindow
4253                                 }
4254                                 break;
4255                 }
4256
4257                 mwindow->samplemovement(
4258                         mwindow->edl->local_session->view_start[pane->number] + x_distance,
4259                         pane->number);
4260
4261         }
4262
4263         if(track_movement)
4264         {
4265                 mwindow->trackmovement(y_distance, pane->number);
4266         }
4267
4268         return result;
4269 }
4270
4271 int TrackCanvas::button_release_event()
4272 {
4273         int redraw = 0, update_overlay = 0, result = 0;
4274
4275 // printf("TrackCanvas::button_release_event %d\n", 
4276 // mwindow->session->current_operation);
4277         if(active)
4278         {
4279                 switch(mwindow->session->current_operation)
4280                 {
4281                         case DRAG_EDITHANDLE2:
4282                                 mwindow->session->current_operation = NO_OPERATION;
4283                                 drag_scroll = 0;
4284                                 result = 1;
4285
4286                                 end_edithandle_selection();
4287                                 break;
4288
4289                         case DRAG_EDITHANDLE1:
4290                                 mwindow->session->current_operation = NO_OPERATION;
4291                                 drag_scroll = 0;
4292                                 result = 1;
4293                                 break;
4294
4295                         case DRAG_PLUGINHANDLE2:
4296                                 mwindow->session->current_operation = NO_OPERATION;
4297                                 drag_scroll = 0;
4298                                 result = 1;
4299
4300                                 end_pluginhandle_selection();
4301                                 break;
4302
4303                         case DRAG_PLUGINHANDLE1:
4304                                 mwindow->session->current_operation = NO_OPERATION;
4305                                 drag_scroll = 0;
4306                                 result = 1;
4307                                 break;
4308
4309                         case DRAG_FADE:
4310                         case DRAG_SPEED:
4311         // delete the drag_auto_gang first and remove out of order keys
4312                                 synchronize_autos(0, 0, 0, -1); 
4313                         case DRAG_CZOOM:
4314                         case DRAG_PZOOM:
4315                         case DRAG_PLAY:
4316                         case DRAG_MUTE:
4317                         case DRAG_MASK:
4318                         case DRAG_MODE:
4319                         case DRAG_PAN:
4320                         case DRAG_CAMERA_X:
4321                         case DRAG_CAMERA_Y:
4322                         case DRAG_CAMERA_Z:
4323                         case DRAG_PROJECTOR_X:
4324                         case DRAG_PROJECTOR_Y:
4325                         case DRAG_PROJECTOR_Z:
4326                         case DRAG_PLUGINKEY:
4327                                 mwindow->session->current_operation = NO_OPERATION;
4328                                 mwindow->session->drag_handle = 0;
4329         // Remove any out-of-order keyframe
4330                                 if(mwindow->session->drag_auto)
4331                                 {
4332                                         mwindow->session->drag_auto->autos->remove_nonsequential(
4333                                                 mwindow->session->drag_auto);
4334         //                              mwindow->session->drag_auto->autos->optimize();
4335                                         update_overlay = 1;
4336                                 }
4337
4338
4339                                 mwindow->undo->update_undo_after(_("keyframe"), LOAD_AUTOMATION);
4340                                 result = 1;
4341                                 break;
4342
4343                         case DRAG_EDIT:
4344                         case DRAG_AEFFECT_COPY:
4345                         case DRAG_VEFFECT_COPY:
4346         // Trap in drag stop
4347
4348                                 break;
4349
4350
4351                         default:
4352                                 if(mwindow->session->current_operation)
4353                                 {
4354         //                              if(mwindow->session->current_operation == SELECT_REGION)
4355         //                              {
4356         //                                      mwindow->undo->update_undo_after(_("select"), LOAD_SESSION, 0, 0);
4357         //                              }
4358
4359                                         mwindow->session->current_operation = NO_OPERATION;
4360                                         drag_scroll = 0;
4361         // Traps button release events
4362         //                              result = 1;
4363                                 }
4364                                 break;
4365                 }
4366         }
4367         
4368         if (result) 
4369                 cursor_motion_event();
4370
4371         if(update_overlay)
4372         {
4373                 gui->draw_overlays(1);
4374         }
4375         if(redraw)
4376         {
4377                 gui->draw_canvas(NORMAL_DRAW, 0);
4378         }
4379         return result;
4380 }
4381
4382 int TrackCanvas::do_edit_handles(int cursor_x, 
4383         int cursor_y, 
4384         int button_press, 
4385         int &new_cursor,
4386         int &update_cursor)
4387 {
4388         Edit *edit_result = 0;
4389         int handle_result = 0;
4390         int result = 0;
4391
4392         if(!mwindow->edl->session->show_assets) return 0;
4393
4394         for(Track *track = mwindow->edl->tracks->first;
4395                 track && !result;
4396                 track = track->next)
4397         {
4398                 for(Edit *edit = track->edits->first;
4399                         edit && !result;
4400                         edit = edit->next)
4401                 {
4402                         int64_t edit_x, edit_y, edit_w, edit_h;
4403                         edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
4404
4405                         if(cursor_x >= edit_x && cursor_x <= edit_x + edit_w &&
4406                                 cursor_y >= edit_y && cursor_y < edit_y + edit_h)
4407                         {
4408                                 if(cursor_x < edit_x + HANDLE_W)
4409                                 {
4410                                         edit_result = edit;
4411                                         handle_result = 0;
4412                                         result = 1;
4413                                 }
4414                                 else
4415                                 if(cursor_x >= edit_x + edit_w - HANDLE_W)
4416                                 {
4417                                         edit_result = edit;
4418                                         handle_result = 1;
4419                                         result = 1;
4420                                 }
4421                                 else
4422                                 {
4423                                         result = 0;
4424                                 }
4425                         }
4426                 }
4427         }
4428
4429         update_cursor = 1;
4430         if(result)
4431         {
4432                 double position = 0;
4433                 if(handle_result == 0)
4434                 {
4435                         position = edit_result->track->from_units(edit_result->startproject);
4436                         new_cursor = LEFT_CURSOR;
4437                 }
4438                 else
4439                 if(handle_result == 1)
4440                 {
4441                         position = edit_result->track->from_units(edit_result->startproject + edit_result->length);
4442                         new_cursor = RIGHT_CURSOR;
4443                 }
4444
4445 // Reposition cursor
4446                 if(button_press)
4447                 {
4448                         mwindow->session->drag_edit = edit_result;
4449                         mwindow->session->drag_handle = handle_result;
4450                         mwindow->session->drag_button = get_buttonpress() - 1;
4451                         mwindow->session->drag_position = position;
4452                         mwindow->session->current_operation = DRAG_EDITHANDLE1;
4453                         mwindow->session->drag_origin_x = get_cursor_x();
4454                         mwindow->session->drag_origin_y = get_cursor_y();
4455                         mwindow->session->drag_start = position;
4456
4457                         int rerender = start_selection(position);
4458                         if(rerender)
4459                         {
4460                                 gui->unlock_window();
4461                                 mwindow->cwindow->update(1, 0, 0);
4462                                 gui->lock_window("TrackCanvas::do_edit_handles");
4463                         }
4464                         gui->update_timebar(0);
4465                         gui->zoombar->update();
4466                         gui->hide_cursor(0);
4467                         gui->draw_cursor(1);
4468                         draw_overlays();
4469                         flash(0);
4470                 }
4471         }
4472
4473         return result;
4474 }
4475
4476 int TrackCanvas::do_plugin_handles(int cursor_x, 
4477         int cursor_y, 
4478         int button_press,
4479         int &new_cursor,
4480         int &update_cursor)
4481 {
4482         Plugin *plugin_result = 0;
4483         int handle_result = 0;
4484         int result = 0;
4485
4486 //      if(!mwindow->edl->session->show_assets) return 0;
4487
4488         for(Track *track = mwindow->edl->tracks->first;
4489                 track && !result;
4490                 track = track->next)
4491         {
4492                 for(int i = 0; i < track->plugin_set.total && !result; i++)
4493                 {
4494                         PluginSet *plugin_set = track->plugin_set.values[i];
4495                         for(Plugin *plugin = (Plugin*)plugin_set->first; 
4496                                 plugin && !result; 
4497                                 plugin = (Plugin*)plugin->next)
4498                         {
4499                                 int64_t plugin_x, plugin_y, plugin_w, plugin_h;
4500                                 plugin_dimensions(plugin, plugin_x, plugin_y, plugin_w, plugin_h);
4501
4502                                 if(cursor_x >= plugin_x && cursor_x <= plugin_x + plugin_w &&
4503                                         cursor_y >= plugin_y && cursor_y < plugin_y + plugin_h)
4504                                 {
4505                                         if(cursor_x < plugin_x + HANDLE_W)
4506                                         {
4507                                                 plugin_result = plugin;
4508                                                 handle_result = 0;
4509                                                 result = 1;
4510                                         }
4511                                         else
4512                                         if(cursor_x >= plugin_x + plugin_w - HANDLE_W)
4513                                         {
4514                                                 plugin_result = plugin;
4515                                                 handle_result = 1;
4516                                                 result = 1;
4517                                         }
4518                                 }
4519                         }
4520
4521                         if(result && shift_down())
4522                                 mwindow->session->trim_edits = plugin_set;
4523                 }
4524         }
4525
4526         update_cursor = 1;
4527         if(result)
4528         {
4529                 double position = 0;
4530                 if(handle_result == 0)
4531                 {
4532                         position = plugin_result->track->from_units(plugin_result->startproject);
4533                         new_cursor = LEFT_CURSOR;
4534                 }
4535                 else
4536                 if(handle_result == 1)
4537                 {
4538                         position = plugin_result->track->from_units(plugin_result->startproject + plugin_result->length);
4539                         new_cursor = RIGHT_CURSOR;
4540                 }
4541                 
4542                 if(button_press)
4543                 {
4544                         mwindow->session->drag_plugin = plugin_result;
4545                         mwindow->session->drag_handle = handle_result;
4546                         mwindow->session->drag_button = get_buttonpress() - 1;
4547                         mwindow->session->drag_position = position;
4548                         mwindow->session->current_operation = DRAG_PLUGINHANDLE1;
4549                         mwindow->session->drag_origin_x = get_cursor_x();
4550                         mwindow->session->drag_origin_y = get_cursor_y();
4551                         mwindow->session->drag_start = position;
4552
4553                         int rerender = start_selection(position);
4554                         if(rerender) 
4555                         {
4556                                 gui->unlock_window();
4557                                 mwindow->cwindow->update(1, 0, 0);
4558                                 gui->lock_window("TrackCanvas::do_plugin_handles");
4559                         }
4560                         gui->update_timebar(0);
4561                         gui->zoombar->update();
4562                         gui->hide_cursor(0);
4563                         gui->draw_cursor(1);
4564                         gui->draw_overlays(0);
4565                         gui->flash_canvas(1);
4566                 }
4567         }
4568         
4569         return result;
4570 }
4571
4572
4573 int TrackCanvas::do_tracks(int cursor_x, 
4574                 int cursor_y,
4575                 int button_press)
4576 {
4577         int result = 0;
4578
4579
4580 //      if(!mwindow->edl->session->show_assets) return 0;
4581
4582
4583         for(Track *track = mwindow->edl->tracks->first;
4584                 track && !result;
4585                 track = track->next)
4586         {
4587                 int64_t track_x, track_y, track_w, track_h;
4588                 track_dimensions(track, track_x, track_y, track_w, track_h);
4589
4590                 if(button_press && 
4591                         get_buttonpress() == 3 &&
4592                         cursor_y >= track_y && 
4593                         cursor_y < track_y + track_h)
4594                 {
4595                         gui->edit_menu->update(track, 0);
4596                         gui->edit_menu->activate_menu();
4597                         result = 1;
4598                 }
4599         }
4600
4601         return result;
4602 }
4603
4604 int TrackCanvas::do_edits(int cursor_x, 
4605         int cursor_y, 
4606         int button_press,
4607         int drag_start,
4608         int &redraw,
4609         int &rerender,
4610         int &new_cursor,
4611         int &update_cursor)
4612 {
4613         int result = 0;
4614
4615         if(!mwindow->edl->session->show_assets) return 0;
4616
4617         for(Track *track = mwindow->edl->tracks->first;
4618                 track && !result;
4619                 track = track->next)
4620         {
4621                 for(Edit *edit = track->edits->first;
4622                         edit && !result;
4623                         edit = edit->next)
4624                 {
4625                         int64_t edit_x, edit_y, edit_w, edit_h;
4626                         edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
4627
4628 // Cursor inside a track
4629 // Cursor inside an edit
4630                         if(cursor_x >= edit_x && cursor_x < edit_x + edit_w &&
4631                                 cursor_y >= edit_y && cursor_y < edit_y + edit_h)
4632                         {
4633 // Select duration of edit
4634                                 if(button_press)
4635                                 {
4636                                         if(get_double_click() && !drag_start)
4637                                         {
4638                                                 mwindow->edl->local_session->set_selectionstart(edit->track->from_units(edit->startproject));
4639                                                 mwindow->edl->local_session->set_selectionend(edit->track->from_units(edit->startproject) + 
4640                                                         edit->track->from_units(edit->length));
4641                                                 if(mwindow->edl->session->cursor_on_frames) 
4642                                                 {
4643                                                         mwindow->edl->local_session->set_selectionstart(
4644                                                                 mwindow->edl->align_to_frame(mwindow->edl->local_session->get_selectionstart(1), 0));
4645                                                         mwindow->edl->local_session->set_selectionend(
4646                                                                 mwindow->edl->align_to_frame(mwindow->edl->local_session->get_selectionend(1), 1));
4647                                                 }
4648                                                 redraw = 1;
4649                                                 rerender = 1;
4650                                                 update_cursor = -1;
4651                                                 result = 1;
4652                                         }
4653                                 }
4654                                 else
4655                                 if(drag_start && track->record)
4656                                 {
4657                                         if(mwindow->edl->session->editing_mode == EDITING_ARROW)
4658                                         {
4659 // Need to create drag window
4660                                                 mwindow->session->current_operation = DRAG_EDIT;
4661                                                 mwindow->session->drag_edit = edit;
4662 //printf("TrackCanvas::do_edits 2\n");
4663
4664 // Drag only one edit if ctrl is initially down
4665                                                 if(ctrl_down())
4666                                                 {
4667                                                         mwindow->session->drag_edits->remove_all();
4668                                                         mwindow->session->drag_edits->append(edit);
4669                                                 }
4670                                                 else
4671 // Construct list of all affected edits
4672                                                 {
4673                                                         mwindow->edl->tracks->get_affected_edits(
4674                                                                 mwindow->session->drag_edits, 
4675                                                                 edit->track->from_units(edit->startproject),
4676                                                                 edit->track);
4677                                                 }
4678                                                 mwindow->session->drag_origin_x = cursor_x;
4679                                                 mwindow->session->drag_origin_y = cursor_y;
4680
4681                                                 gui->drag_popup = new BC_DragWindow(gui, 
4682                                                         mwindow->theme->get_image("clip_icon") /*, 
4683                                                         get_abs_cursor_x(0) - mwindow->theme->get_image("clip_icon")->get_w() / 2,
4684                                                         get_abs_cursor_y(0) - mwindow->theme->get_image("clip_icon")->get_h() / 2 */);
4685
4686                                                 result = 1;
4687                                         }
4688                                 }
4689                         }
4690                 }
4691         }
4692         return result;
4693 }
4694
4695
4696 int TrackCanvas::test_resources(int cursor_x, int cursor_y)
4697 {
4698         return 0;
4699 }
4700
4701 int TrackCanvas::do_plugins(int cursor_x, 
4702         int cursor_y, 
4703         int drag_start,
4704         int button_press,
4705         int &redraw,
4706         int &rerender)
4707 {
4708         Plugin *plugin = 0;
4709         int result = 0;
4710         int done = 0;
4711         int64_t x, y, w, h;
4712         Track *track = 0;
4713
4714
4715 //      if(!mwindow->edl->session->show_assets) return 0;
4716
4717
4718         for(track = mwindow->edl->tracks->first;
4719                 track && !done;
4720                 track = track->next)
4721         {
4722                 if(!track->expand_view) continue;
4723
4724
4725                 for(int i = 0; i < track->plugin_set.total && !done; i++)
4726                 {
4727                         PluginSet *plugin_set = track->plugin_set.values[i];
4728                         for(plugin = (Plugin*)plugin_set->first;
4729                                 plugin && !done;
4730                                 plugin = (Plugin*)plugin->next)
4731                         {
4732                                 plugin_dimensions(plugin, x, y, w, h);
4733                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
4734                                         MWindowGUI::visible(y, y + h, 0, get_h()))
4735                                 {
4736                                         if(cursor_x >= x && cursor_x < x + w &&
4737                                                 cursor_y >= y && cursor_y < y + h)
4738                                         {
4739                                                 done = 1;
4740                                                 break;
4741                                         }
4742                                 }
4743                         }
4744                 }
4745         }
4746
4747         if(plugin)
4748         {
4749 // Start plugin popup
4750                 if(button_press)
4751                 {
4752                         if(get_buttonpress() == 3)
4753                         {
4754                                 gui->plugin_menu->update(plugin);
4755                                 gui->plugin_menu->activate_menu();
4756                                 result = 1;
4757                         } 
4758                         else
4759 // Select range of plugin on doubleclick over plugin
4760                         if (get_double_click() && !drag_start)
4761                         {
4762                                 mwindow->edl->local_session->set_selectionstart(plugin->track->from_units(plugin->startproject));
4763                                 mwindow->edl->local_session->set_selectionend(plugin->track->from_units(plugin->startproject) + 
4764                                         plugin->track->from_units(plugin->length));
4765                                 if(mwindow->edl->session->cursor_on_frames) 
4766                                 {
4767                                         mwindow->edl->local_session->set_selectionstart(
4768                                                 mwindow->edl->align_to_frame(mwindow->edl->local_session->get_selectionstart(1), 0));
4769                                         mwindow->edl->local_session->set_selectionend(
4770                                                 mwindow->edl->align_to_frame(mwindow->edl->local_session->get_selectionend(1), 1));
4771                                 }
4772                                 rerender = 1;
4773                                 redraw = 1;
4774                                 result = 1;
4775                         }
4776                 }
4777                 else
4778 // Move plugin
4779                 if(drag_start && plugin->track->record)
4780                 {
4781                         if(mwindow->edl->session->editing_mode == EDITING_ARROW)
4782                         {
4783                                 if(plugin->track->data_type == TRACK_AUDIO)
4784                                         mwindow->session->current_operation = DRAG_AEFFECT_COPY;
4785                                 else
4786                                 if(plugin->track->data_type == TRACK_VIDEO)
4787                                         mwindow->session->current_operation = DRAG_VEFFECT_COPY;
4788
4789                                 mwindow->session->drag_plugin = plugin;
4790
4791
4792
4793
4794
4795 // Create picon
4796                                 switch(plugin->plugin_type)
4797                                 {
4798                                         case PLUGIN_STANDALONE:
4799                                         {
4800                                                 PluginServer *server = mwindow->scan_plugindb(
4801                                                         plugin->title,
4802                                                         plugin->track->data_type);
4803                                                 VFrame *frame = server->picon;
4804
4805                                                 if(!frame)
4806                                                 {
4807                                                         if(plugin->track->data_type == TRACK_AUDIO)
4808                                                         {
4809                                                                 frame = mwindow->theme->get_image("aeffect_icon");
4810                                                         }
4811                                                         else
4812                                                         {
4813                                                                 frame = mwindow->theme->get_image("veffect_icon");
4814                                                         }
4815                                                 }
4816
4817                                                 gui->drag_popup = new BC_DragWindow(gui, 
4818                                                         frame /*, 
4819                                                         get_abs_cursor_x(0) - frame->get_w() / 2,
4820                                                         get_abs_cursor_y(0) - frame->get_h() / 2 */);
4821                                                 break;
4822                                         }
4823                                         
4824                                         case PLUGIN_SHAREDPLUGIN:
4825                                         case PLUGIN_SHAREDMODULE:
4826                                                 gui->drag_popup = new BC_DragWindow(gui, 
4827                                                         mwindow->theme->get_image("clip_icon") /*, 
4828                                                         get_abs_cursor_x(0) - mwindow->theme->get_image("clip_icon")->get_w() / 2,
4829                                                         get_abs_cursor_y(0) - mwindow->theme->get_image("clip_icon")->get_h() / 2 */);
4830                                                 break;
4831                                 }
4832
4833
4834                                 result = 1;
4835                         }
4836                 }
4837         }
4838
4839         return result;
4840 }
4841
4842 int TrackCanvas::do_transitions(int cursor_x, 
4843         int cursor_y, 
4844         int button_press,
4845         int &new_cursor,
4846         int &update_cursor)
4847 {
4848         Transition *transition = 0;
4849         int result = 0;
4850         int64_t x, y, w, h;
4851
4852
4853
4854         if(/* !mwindow->edl->session->show_assets || */
4855                 !mwindow->edl->session->auto_conf->transitions) return 0;
4856                                         
4857
4858
4859         for(Track *track = mwindow->edl->tracks->first;
4860                 track && !result;
4861                 track = track->next)
4862         {
4863                 for(Edit *edit = track->edits->first;
4864                         edit;
4865                         edit = edit->next)
4866                 {
4867                         if(edit->transition)
4868                         {
4869                                 edit_dimensions(edit, x, y, w, h);
4870                                 get_transition_coords(x, y, w, h);
4871
4872                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
4873                                         MWindowGUI::visible(y, y + h, 0, get_h()))
4874                                 {
4875                                         if(cursor_x >= x && cursor_x < x + w &&
4876                                                 cursor_y >= y && cursor_y < y + h)
4877                                         {
4878                                                 transition = edit->transition;
4879                                                 result = 1;
4880                                                 break;
4881                                         }
4882                                 }
4883                         }
4884                 }
4885         }
4886         
4887         update_cursor = 1;
4888         if(transition)
4889         {
4890                 if(!button_press)
4891                 {
4892                         new_cursor = UPRIGHT_ARROW_CURSOR;
4893                 }
4894                 else
4895                 if(get_buttonpress() == 3)
4896                 {
4897                         gui->transition_menu->update(transition);
4898                         gui->transition_menu->activate_menu();
4899                 }
4900         }
4901
4902         return result;
4903 }
4904
4905 int TrackCanvas::button_press_event()
4906 {
4907         int result = 0;
4908         int cursor_x, cursor_y;
4909         int new_cursor;
4910
4911         cursor_x = get_cursor_x();
4912         cursor_y = get_cursor_y();
4913         mwindow->session->trim_edits = 0;
4914
4915         if(is_event_win() && cursor_inside())
4916         {
4917                 if(!active)
4918                 {
4919                         activate();
4920                 }
4921
4922                 if(get_buttonpress() == LEFT_BUTTON)
4923                 {
4924                         gui->unlock_window();
4925                         gui->mbuttons->transport->handle_transport(STOP, 1, 0, 0);
4926                         gui->lock_window("TrackCanvas::button_press_event");
4927                 }
4928
4929                 int update_overlay = 0, update_cursor = 0, rerender = 0;
4930
4931                 if(get_buttonpress() == WHEEL_UP)
4932                 {
4933                         if(shift_down())
4934                                 mwindow->expand_sample();
4935                         else
4936                                 mwindow->move_up(get_h() / 10);
4937                         result = 1;
4938                 }
4939                 else
4940                 if(get_buttonpress() == WHEEL_DOWN)
4941                 {
4942                         if(shift_down())
4943                                 mwindow->zoom_in_sample();
4944                         else
4945                                 mwindow->move_down(get_h() / 10);
4946                         result = 1;
4947                 }
4948                 else
4949                 switch(mwindow->edl->session->editing_mode)
4950                 {
4951 // Test handles and resource boundaries and highlight a track
4952                         case EDITING_ARROW:
4953                         {
4954                                 if(mwindow->edl->session->auto_conf->transitions && 
4955                                         do_transitions(cursor_x, cursor_y, 
4956                                                 1, new_cursor, update_cursor))
4957                                 {
4958                                         break;
4959                                 }
4960                                 else
4961                                 if(do_keyframes(cursor_x, cursor_y, 
4962                                         0, get_buttonpress(), new_cursor, 
4963                                         update_cursor, rerender))
4964                                 {
4965                                         break;
4966                                 }
4967                                 else
4968 // Test edit boundaries
4969                                 if(do_edit_handles(cursor_x, cursor_y, 
4970                                         1, new_cursor, update_cursor))
4971                                 {
4972                                         break;
4973                                 }
4974                                 else
4975 // Test plugin boundaries
4976                                 if(do_plugin_handles(cursor_x, cursor_y, 
4977                                         1, new_cursor, update_cursor))
4978                                 {
4979                                         break;
4980                                 }
4981                                 else
4982                                 if(do_edits(cursor_x, cursor_y, 1, 0,
4983                                         update_cursor, rerender, new_cursor, update_cursor))
4984                                 {
4985                                         break;
4986                                 }
4987                                 else
4988                                 if(do_plugins(cursor_x, cursor_y, 0, 1,
4989                                         update_cursor, rerender))
4990                                 {
4991                                         break;
4992                                 }
4993                                 else
4994                                 if(test_resources(cursor_x, cursor_y))
4995                                 {
4996                                         break;
4997                                 }
4998                                 else
4999                                 if(do_tracks(cursor_x, cursor_y, 1))
5000                                 {
5001                                         break;
5002                                 }
5003                                 break;
5004                         }
5005
5006 // Test handles only and select a region
5007                         case EDITING_IBEAM:
5008                         {
5009                                 double position = (double)cursor_x * 
5010                                         mwindow->edl->local_session->zoom_sample /
5011                                         mwindow->edl->session->sample_rate + 
5012                                         (double)mwindow->edl->local_session->view_start[pane->number] * 
5013                                         mwindow->edl->local_session->zoom_sample /
5014                                         mwindow->edl->session->sample_rate;
5015 //printf("TrackCanvas::button_press_event %d\n", position);
5016
5017                                 if(mwindow->edl->session->auto_conf->transitions && 
5018                                         do_transitions(cursor_x, cursor_y, 
5019                                                 1, new_cursor, update_cursor))
5020                                 {
5021                                         break;
5022                                 }
5023                                 else
5024                                 if(do_keyframes(cursor_x, cursor_y, 
5025                                         0, get_buttonpress(), new_cursor, 
5026                                         update_cursor, rerender))
5027                                 {
5028                                         update_overlay = 1;
5029                                         break;
5030                                 }
5031                                 else
5032 // Test edit boundaries
5033                                 if(do_edit_handles(cursor_x, cursor_y, 
5034                                         1, new_cursor, update_cursor))
5035                                 {
5036                                         break;
5037                                 }
5038                                 else
5039 // Test plugin boundaries
5040                                 if(do_plugin_handles(cursor_x, cursor_y, 
5041                                         1, new_cursor, update_cursor))
5042                                 {
5043                                         break;
5044                                 }
5045                                 else
5046                                 if(do_edits(cursor_x, cursor_y, 
5047                                         1, 0, update_cursor, 
5048                                         rerender, new_cursor, update_cursor))
5049                                 {
5050                                         break;
5051                                 }
5052                                 else
5053                                 if(do_plugins(cursor_x, cursor_y, 
5054                                         0, 1, update_cursor, rerender))
5055                                 {
5056                                         break;
5057                                 }
5058                                 else
5059                                 if(do_tracks(cursor_x, cursor_y, 1))
5060                                 {
5061                                         break;
5062                                 }
5063 // Highlight selection
5064                                 else
5065                                 {
5066                                         rerender = start_selection(position);
5067                                         mwindow->session->current_operation = SELECT_REGION;
5068                                         update_cursor = 1;
5069                                 }
5070
5071                                 break;
5072                         }
5073                 }
5074
5075
5076                 if(rerender)
5077                 {
5078                         gui->unlock_window();
5079                         mwindow->cwindow->update(1, 0, 0, 0, 1);
5080
5081                         gui->lock_window("TrackCanvas::button_press_event 2");
5082 // Update faders
5083                         mwindow->update_plugin_guis();
5084                         gui->update_patchbay();
5085                 }
5086
5087                 if(update_overlay)
5088                 {
5089                         gui->draw_overlays(1);
5090                 }
5091
5092                 if(update_cursor > 0)
5093                 {
5094                         gui->update_timebar(0);
5095                         gui->hide_cursor(0);
5096                         gui->show_cursor(1);
5097                         gui->zoombar->update();
5098                         gui->flash_canvas(1);
5099                         result = 1;
5100                 }
5101                 else if(update_cursor < 0)
5102                         gui->swindow->update_selection();
5103
5104
5105
5106         }
5107         return result;
5108 }
5109
5110 int TrackCanvas::start_selection(double position)
5111 {
5112         int rerender = 0;
5113         position = mwindow->edl->align_to_frame(position, 0);
5114
5115
5116 // Extend a border
5117         if(shift_down())
5118         {
5119                 double midpoint = (mwindow->edl->local_session->get_selectionstart(1) + 
5120                         mwindow->edl->local_session->get_selectionend(1)) / 2;
5121
5122                 if(position < midpoint)
5123                 {
5124                         mwindow->edl->local_session->set_selectionstart(position);
5125                         selection_midpoint = mwindow->edl->local_session->get_selectionend(1);
5126 // Que the CWindow
5127                         rerender = 1;
5128                 }
5129                 else
5130                 {
5131                         mwindow->edl->local_session->set_selectionend(position);
5132                         selection_midpoint = mwindow->edl->local_session->get_selectionstart(1);
5133 // Don't que the CWindow for the end
5134                 }
5135         }
5136         else
5137 // Start a new selection
5138         {
5139 //printf("TrackCanvas::start_selection %f\n", position);
5140                 mwindow->edl->local_session->set_selectionstart(position);
5141                 mwindow->edl->local_session->set_selectionend(position);
5142                 selection_midpoint = position;
5143 // Que the CWindow
5144                 rerender = 1;
5145         }
5146         
5147         return rerender;
5148 }
5149
5150 void TrackCanvas::end_edithandle_selection()
5151 {
5152         mwindow->modify_edithandles();
5153 }
5154
5155 void TrackCanvas::end_pluginhandle_selection()
5156 {
5157         mwindow->modify_pluginhandles();
5158 }
5159
5160
5161 double TrackCanvas::time_visible()
5162 {
5163         return (double)get_w() * 
5164                 mwindow->edl->local_session->zoom_sample / 
5165                 mwindow->edl->session->sample_rate;
5166 }
5167
5168 // Patchbay* TrackCanvas::get_patchbay()
5169 // {
5170 //      if(pane->patchbay) return pane->patchbay;
5171 //      if(gui->total_panes() == 2 &&
5172 //              gui->pane[TOP_LEFT_PANE] &&
5173 //              gui->pane[TOP_RIGHT_PANE])
5174 //              return gui->pane[TOP_LEFT_PANE]->patchbay;
5175 //      if(gui->total_panes() == 4)
5176 //      {
5177 //              if(pane->number == TOP_RIGHT_PANE)
5178 //                      return gui->pane[TOP_LEFT_PANE]->patchbay;
5179 //              else
5180 //                      return gui->pane[BOTTOM_LEFT_PANE]->patchbay;
5181 //      }
5182 // 
5183 //      return 0;
5184 // }
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225