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