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