Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

trackcanvas.C

Go to the documentation of this file.
00001 #include "asset.h"
00002 #include "autoconf.h"
00003 #include "automation.h"
00004 #include "bcsignals.h"
00005 #include "bctimer.h"
00006 #include "clip.h"
00007 #include "colors.h"
00008 #include "cplayback.h"
00009 #include "cursors.h"
00010 #include "cwindow.h"
00011 #include "cwindowgui.h"
00012 #include "edithandles.h"
00013 #include "editpopup.h"
00014 #include "edits.h"
00015 #include "edl.h"
00016 #include "edlsession.h"
00017 #include "floatauto.h"
00018 #include "floatautos.h"
00019 #include "intauto.h"
00020 #include "keyframe.h"
00021 #include "keyframepopup.h"
00022 #include "keyframes.h"
00023 #include "keys.h"
00024 #include "localsession.h"
00025 #include "mainclock.h"
00026 #include "maincursor.h"
00027 #include "mainundo.h"
00028 #include "maskautos.h"
00029 #include "mbuttons.h"
00030 #include "mtimebar.h"
00031 #include "mwindow.h"
00032 #include "mwindowgui.h"
00033 #include "patchbay.h"
00034 #include "tracking.h"
00035 #include "panautos.h"
00036 #include "playbackengine.h"
00037 #include "playtransport.h"
00038 #include "plugin.h"
00039 #include "pluginpopup.h"
00040 #include "pluginset.h"
00041 #include "pluginserver.h"
00042 #include "preferences.h"
00043 #include "resourcepixmap.h"
00044 #include "mainsession.h"
00045 #include "transitionhandles.h"
00046 #include "transitionpopup.h"
00047 #include "transportque.h"
00048 #include "zoombar.h"
00049 #include "theme.h"
00050 #include "intautos.h"
00051 #include "trackcanvas.h"
00052 #include "tracks.h"
00053 #include "transition.h"
00054 #include "vframe.h"
00055 #include "apatchgui.inc"
00056 #include "vpatchgui.inc"
00057 
00058 #include <string.h>
00059 
00060 TrackCanvas::TrackCanvas(MWindow *mwindow, MWindowGUI *gui)
00061  : BC_SubWindow(mwindow->theme->mcanvas_x,
00062         mwindow->theme->mcanvas_y,
00063         gui->view_w,
00064         gui->view_h)
00065 {
00066         this->mwindow = mwindow;
00067         this->gui = gui;
00068         current_end = 0;
00069         selection_midpoint1 = selection_midpoint2 = 0;
00070         selection_type = 0;
00071         region_selected = 0;
00072         handle_selected = 0;
00073         auto_selected = 0;
00074         translate_selected = 0;
00075         which_handle = 0;
00076         handle_pixel = 0;
00077         drag_scroll = 0;
00078         drag_popup = 0;
00079         active = 0;
00080         temp_picon = 0;
00081         resource_timer = new Timer;
00082         hourglass_enabled = 0;
00083 }
00084 
00085 TrackCanvas::~TrackCanvas()
00086 {
00087         for(int i = 0; i < resource_pixmaps.total; i++)
00088                 delete resource_pixmaps.values[i];
00089 //      delete transition_handles;
00090         delete edit_handles;
00091         delete keyframe_pixmap;
00092         delete camerakeyframe_pixmap;
00093         delete modekeyframe_pixmap;
00094         delete pankeyframe_pixmap;
00095         delete projectorkeyframe_pixmap;
00096         delete maskkeyframe_pixmap;
00097         delete background_pixmap;
00098         if(temp_picon) delete temp_picon;
00099         delete resource_timer;
00100 }
00101 
00102 int TrackCanvas::create_objects()
00103 {
00104         background_pixmap = new BC_Pixmap(this, get_w(), get_h());
00105 //      transition_handles = new TransitionHandles(mwindow, this);
00106         edit_handles = new EditHandles(mwindow, this);
00107         keyframe_pixmap = new BC_Pixmap(this, mwindow->theme->keyframe_data, PIXMAP_ALPHA);
00108         camerakeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->camerakeyframe_data, PIXMAP_ALPHA);
00109         modekeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->modekeyframe_data, PIXMAP_ALPHA);
00110         pankeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->pankeyframe_data, PIXMAP_ALPHA);
00111         projectorkeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->projectorkeyframe_data, PIXMAP_ALPHA);
00112         maskkeyframe_pixmap = new BC_Pixmap(this, mwindow->theme->maskkeyframe_data, PIXMAP_ALPHA);
00113         draw();
00114         update_cursor();
00115         flash();
00116         return 0;
00117 }
00118 
00119 void TrackCanvas::resize_event()
00120 {
00121 //printf("TrackCanvas::resize_event 1\n");
00122         draw(0, 0);
00123         flash();
00124 //printf("TrackCanvas::resize_event 2\n");
00125 }
00126 
00127 int TrackCanvas::keypress_event()
00128 {
00129         int result = 0;
00130 
00131 
00132         return result;
00133 }
00134 
00135 int TrackCanvas::drag_motion()
00136 {
00137         int cursor_x = get_relative_cursor_x();
00138         int cursor_y = get_relative_cursor_y();
00139         Track *over_track = 0;
00140         Edit *over_edit = 0;
00141         PluginSet *over_pluginset = 0;
00142         Plugin *over_plugin = 0;
00143         int redraw = 0;
00144 
00145 
00146         if(drag_popup)
00147         {
00148                 drag_popup->cursor_motion_event();
00149         }
00150 
00151 
00152 // there's no point in drawing highlights has until drag operation has been set
00153         if (!mwindow->session->current_operation)
00154                 return 0;
00155 
00156         if(get_cursor_over_window() &&
00157                 cursor_x >= 0 && 
00158                 cursor_y >= 0 && 
00159                 cursor_x < get_w() && 
00160                 cursor_y < get_h())
00161         {
00162 // Find the edit and track the cursor is over
00163                 for(Track *track = mwindow->edl->tracks->first; track; track = track->next)
00164                 {
00165                         int64_t track_x, track_y, track_w, track_h;
00166                         track_dimensions(track, track_x, track_y, track_w, track_h);
00167 
00168                         if(cursor_y >= track_y && 
00169                                 cursor_y < track_y + track_h)
00170                         {
00171                                 over_track = track;
00172                                 for(Edit *edit = track->edits->first; edit; edit = edit->next)
00173                                 {
00174                                         int64_t edit_x, edit_y, edit_w, edit_h;
00175                                         edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
00176 
00177                                         if(cursor_x >= edit_x && 
00178                                                 cursor_y >= edit_y && 
00179                                                 cursor_x < edit_x + edit_w && 
00180                                                 cursor_y < edit_y + edit_h)
00181                                         {
00182                                                 over_edit = edit;
00183                                                 break;
00184                                         }
00185                                 }
00186 
00187                                 for(int i = 0; i < track->plugin_set.total; i++)
00188                                 {
00189                                         PluginSet *pluginset = track->plugin_set.values[i];
00190                                         
00191 
00192 
00193                                         for(Plugin *plugin = (Plugin*)pluginset->first;
00194                                                 plugin;
00195                                                 plugin = (Plugin*)plugin->next)
00196                                         {
00197                                                 int64_t plugin_x, plugin_y, plugin_w, plugin_h;
00198                                                 plugin_dimensions(plugin, plugin_x, plugin_y, plugin_w, plugin_h);
00199                                                 
00200                                                 if(cursor_y >= plugin_y &&
00201                                                         cursor_y < plugin_y + plugin_h)
00202                                                 {
00203                                                         over_pluginset = plugin->plugin_set;
00204                                                 
00205                                                         if(cursor_x >= plugin_x &&
00206                                                                 cursor_x < plugin_x + plugin_w)
00207                                                         {
00208                                                                 over_plugin = plugin;
00209                                                                 break;
00210                                                         }
00211                                                 }
00212                                         }
00213                                 }
00214                                 break;
00215                         }
00216                 }
00217         }
00218 
00219         if (!over_track)        // check for pastes from patchbay
00220                 over_track = mwindow->gui->patchbay->is_over_track();
00221 
00222         if(mwindow->session->track_highlighted != over_track) 
00223         {
00224                 mwindow->session->track_highlighted = over_track;
00225                 redraw = 1;
00226         }
00227 
00228         if(mwindow->session->edit_highlighted != over_edit)
00229         {
00230                 mwindow->session->edit_highlighted = over_edit;
00231                 redraw = 1;
00232         }
00233 
00234         if(mwindow->session->pluginset_highlighted != over_pluginset)
00235         {
00236                 mwindow->session->pluginset_highlighted = over_pluginset;
00237                 redraw = 1;
00238         }
00239 
00240         if(mwindow->session->plugin_highlighted != over_plugin)
00241         {
00242                 mwindow->session->plugin_highlighted = over_plugin;
00243                 redraw = 1;
00244         }
00245 
00246         if (mwindow->session->current_operation == DRAG_ASSET ||
00247           mwindow->session->current_operation == DRAG_EDIT)
00248 
00249         {
00250                 redraw = 1;
00251         }
00252 
00253 //printf("TrackCanvas::drag_motion 2 %p\n", mwindow->session->track_highlighted);
00254         if(redraw)
00255         {
00256                 lock_window("TrackCanvas::drag_motion");
00257                 draw_overlays();
00258                 flash();
00259                 unlock_window();
00260         }
00261 
00262         return 0;
00263 }
00264 
00265 int TrackCanvas::drag_start_event()
00266 {
00267         int result = 0;
00268         int redraw = 0;
00269         int rerender = 0;
00270         int new_cursor, update_cursor;
00271 
00272         if(mwindow->session->current_operation != NO_OPERATION) return 0;
00273 
00274         if(is_event_win())
00275         {
00276                 if(do_plugins(get_drag_x(), 
00277                         get_drag_y(), 
00278                         1,
00279                         0,
00280                         redraw,
00281                         rerender))
00282                 {
00283                         result = 1;
00284                 }
00285                 else
00286                 if(do_edits(get_drag_x(),
00287                         get_drag_y(),
00288                         0,
00289                         1,
00290                         redraw,
00291                         rerender,
00292                         new_cursor,
00293                         update_cursor))
00294                 {
00295                         result = 1;
00296                 }
00297         }
00298 
00299         return result;
00300 }
00301 
00302 int TrackCanvas::drag_motion_event()
00303 {
00304         return drag_motion();
00305 }
00306 
00307 int TrackCanvas::cursor_leave_event()
00308 {
00309 // Because drag motion calls get_cursor_over_window we can be sure that
00310 // all highlights get deleted now.
00311 // This ended up blocking keyboard input from the drag operations.
00312         return 0;
00313 //      return drag_motion();
00314 }
00315 
00316 
00317 int TrackCanvas::drag_stop_event()
00318 {
00319         int result = drag_stop();
00320 
00321         if(drag_popup)
00322         {
00323                 delete drag_popup;
00324                 drag_popup = 0;
00325         }
00326         return result;
00327 }
00328 
00329 
00330 int TrackCanvas::drag_stop()
00331 {
00332 // In most cases the editing routine redraws and not the drag_stop
00333         int result = 0, redraw = 0;
00334 
00335         int insertion = 0;           // used in drag and drop mode
00336         switch(mwindow->session->current_operation)
00337         {
00338                 case DRAG_VTRANSITION:
00339                 case DRAG_ATRANSITION:
00340                         if(mwindow->session->edit_highlighted)
00341                         {
00342                                 if((mwindow->session->current_operation == DRAG_ATRANSITION &&
00343                                         mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
00344                                         (mwindow->session->current_operation == DRAG_VTRANSITION &&
00345                                         mwindow->session->track_highlighted->data_type == TRACK_VIDEO))
00346                                 {
00347                                         mwindow->session->current_operation = NO_OPERATION;
00348                                         mwindow->paste_transition();
00349                                         result = 1;
00350                                 }
00351                         }
00352                         redraw = 1;
00353                         break;
00354 
00355 
00356 
00357 
00358 // Behavior for dragged plugins is limited by the fact that a shared plugin
00359 // can only refer to a standalone plugin that exists in the same position in
00360 // time.  Dragging a plugin from one point in time to another can't produce
00361 // a shared plugin to the original plugin.  In this case we relocate the
00362 // plugin instead of sharing it.
00363                 case DRAG_AEFFECT_COPY:
00364                 case DRAG_VEFFECT_COPY:
00365                         if(mwindow->session->track_highlighted &&
00366                                 ((mwindow->session->current_operation == DRAG_AEFFECT_COPY &&
00367                                         mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
00368                                         (mwindow->session->current_operation == DRAG_VEFFECT_COPY &&
00369                                         mwindow->session->track_highlighted->data_type == TRACK_VIDEO)))
00370                         {
00371                                 mwindow->session->current_operation = NO_OPERATION;
00372 
00373 // Insert shared plugin in source
00374                                 if(mwindow->session->track_highlighted != mwindow->session->drag_plugin->track &&
00375                                         !mwindow->session->plugin_highlighted &&
00376                                         !mwindow->session->pluginset_highlighted)
00377                                 {
00378 // Move plugin if different startproject
00379                                         mwindow->move_effect(mwindow->session->drag_plugin,
00380                                                 0,
00381                                                 mwindow->session->track_highlighted,
00382                                                 0);
00383                                         result = 1;
00384                                 }
00385                                 else
00386 // Move source to different location
00387                                 if(mwindow->session->pluginset_highlighted)
00388                                 {
00389 //printf("TrackCanvas::drag_stop 6\n");
00390                                         if(mwindow->session->plugin_highlighted)
00391                                         {
00392                                                 mwindow->move_effect(mwindow->session->drag_plugin,
00393                                                         mwindow->session->plugin_highlighted->plugin_set,
00394                                                         0,
00395                                                         mwindow->session->plugin_highlighted->startproject);
00396                                         }
00397                                         else
00398                                         {
00399                                                 mwindow->move_effect(mwindow->session->drag_plugin,
00400                                                         mwindow->session->pluginset_highlighted,
00401                                                         0,
00402                                                         mwindow->session->pluginset_highlighted->length());
00403                                         }
00404                                         result = 1;
00405                                 }
00406                                 else
00407 // Move to a new plugin set between two edits
00408                                 if(mwindow->session->edit_highlighted)
00409                                 {
00410                                         mwindow->move_effect(mwindow->session->drag_plugin,
00411                                                 0,
00412                                                 mwindow->session->track_highlighted,
00413                                                 mwindow->session->edit_highlighted->startproject);
00414                                         result = 1;
00415                                 }
00416                                 else
00417 // Move to a new plugin set
00418                                 if(mwindow->session->track_highlighted)
00419                                 {
00420                                         mwindow->move_effect(mwindow->session->drag_plugin,
00421                                                 0,
00422                                                 mwindow->session->track_highlighted,
00423                                                 0);
00424                                         result = 1;
00425                                 }
00426                         }
00427                         break;
00428 
00429                 case DRAG_AEFFECT:
00430                 case DRAG_VEFFECT:
00431                         if(mwindow->session->track_highlighted && 
00432                                 ((mwindow->session->current_operation == DRAG_AEFFECT &&
00433                                 mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
00434                                 (mwindow->session->current_operation == DRAG_VEFFECT &&
00435                                 mwindow->session->track_highlighted->data_type == TRACK_VIDEO)))
00436                         {
00437 // Drop all the effects
00438                                 PluginSet *plugin_set = mwindow->session->pluginset_highlighted;
00439                                 Track *track = mwindow->session->track_highlighted;
00440                                 double start = 0;
00441                                 double length = track->get_length();
00442 
00443                                 if(mwindow->session->plugin_highlighted)
00444                                 {
00445                                         start = track->from_units(mwindow->session->plugin_highlighted->startproject);
00446                                         length = track->from_units(mwindow->session->plugin_highlighted->length);
00447                                         if(length <= 0) length = track->get_length();
00448                                 }
00449                                 else
00450                                 if(mwindow->session->pluginset_highlighted)
00451                                 {
00452                                         start = track->from_units(plugin_set->length());
00453                                         length = track->get_length() - start;
00454                                         if(length <= 0) length = track->get_length();
00455                                 }
00456                                 else
00457                                 if(mwindow->edl->local_session->get_selectionend() > 
00458                                         mwindow->edl->local_session->get_selectionstart())
00459                                 {
00460                                         start = mwindow->edl->local_session->get_selectionstart();
00461                                         length = mwindow->edl->local_session->get_selectionend() - 
00462                                                 mwindow->edl->local_session->get_selectionstart();
00463                                 }
00464 // Move to a point between two edits
00465                                 else
00466                                 if(mwindow->session->edit_highlighted)
00467                                 {
00468                                         start = mwindow->session->track_highlighted->from_units(
00469                                                 mwindow->session->edit_highlighted->startproject);
00470                                         length = mwindow->session->track_highlighted->from_units(
00471                                                 mwindow->session->edit_highlighted->length);
00472                                 }
00473 
00474                                 mwindow->insert_effects_canvas(start, length);
00475                                 redraw = 1;
00476                         }
00477                         if (mwindow->session->track_highlighted)
00478                                 result = 1;  // we have to cleanup
00479                         break;
00480 
00481                 case DRAG_ASSET:
00482                         if(mwindow->session->track_highlighted)
00483                         {
00484                                 float asset_length_float;
00485                                 int64_t asset_length_units;
00486                                 int64_t position = 0;
00487                                         
00488                                 if(mwindow->session->current_operation == DRAG_ASSET &&
00489                                         mwindow->session->drag_assets->total)
00490                                 {
00491                                         Asset *asset = mwindow->session->drag_assets->values[0];
00492 
00493                                         // we use video if we are over video and audio if we are over audio
00494                                         if (asset->video_data && mwindow->session->track_highlighted->data_type == TRACK_VIDEO)
00495                                                 asset_length_float = asset->video_length / asset->frame_rate;
00496                                         else if (asset->audio_data && mwindow->session->track_highlighted->data_type == TRACK_AUDIO)
00497                                                 asset_length_float = asset->audio_length / asset->sample_rate;
00498                                         else
00499                                         {
00500                                                 result = 1;
00501                                                 break;  // Do not do anything
00502                                         }
00503                                 }
00504                                 if(mwindow->session->current_operation == DRAG_ASSET &&
00505                                         mwindow->session->drag_clips->total)
00506                                 {
00507                                         EDL *clip = mwindow->session->drag_clips->values[0];
00508                                         asset_length_float = clip->tracks->total_length();
00509                                 }
00510                         
00511                                 asset_length_units = mwindow->session->track_highlighted->to_units(asset_length_float, 0);
00512                                 position = get_drop_position (&insertion, NULL, asset_length_units);
00513                                 if (position == -1)
00514                                 {
00515                                         result = 1;
00516                                         break;          // Do not do anything
00517                                 }
00518                                 
00519                                 double position_f = mwindow->session->track_highlighted->from_units(position);
00520                                 Track *track = mwindow->session->track_highlighted;
00521 
00522                                 if (!insertion)
00523                                 {
00524                                         // FIXME, we should create an mwindow/EDL method that overwrites, without clearing the keyframes and autos
00525                                         // Unfortunately, this is _a lot_ of work to do right
00526                                         mwindow->edl->tracks->clear(position_f, 
00527                                                 position_f + asset_length_float, 0);
00528                                 }
00529                                 mwindow->paste_assets(position_f, track);
00530                                 result = 1;    // need to be one no matter what, since we have track highlited so we have to cleanup....
00531                         }
00532                         break;
00533 
00534                 case DRAG_EDIT:
00535                         mwindow->session->current_operation = NO_OPERATION;
00536                         if(mwindow->session->track_highlighted)
00537                         {
00538                                 if(mwindow->session->track_highlighted->data_type == mwindow->session->drag_edit->track->data_type)
00539                                 {
00540                                         int64_t position = 0;
00541                                 
00542                                         position = get_drop_position (&insertion, mwindow->session->drag_edit, mwindow->session->drag_edit->length);
00543 
00544                                         if (position == -1)
00545                                         {
00546                                                 result = 1;
00547                                                 break;          // Do not do anything
00548                                         }
00549                                         
00550                                         double position_f = mwindow->session->track_highlighted->from_units(position);
00551                                         Track *track = mwindow->session->track_highlighted;
00552                                         mwindow->move_edits(mwindow->session->drag_edits,
00553                                                 track,
00554                                                 position_f,
00555                                                 !insertion);
00556                                 }
00557 
00558                                 result = 1;
00559                         }
00560                         break;
00561         }
00562 
00563 // since we don't have subwindows we have to terminate any drag operation
00564         if(result)
00565         {
00566                 if (mwindow->session->track_highlighted
00567                         || mwindow->session->edit_highlighted
00568                         || mwindow->session->plugin_highlighted
00569                         || mwindow->session->pluginset_highlighted) 
00570                         redraw = 1;
00571                 mwindow->session->track_highlighted = 0;
00572                 mwindow->session->edit_highlighted = 0;
00573                 mwindow->session->plugin_highlighted = 0;
00574                 mwindow->session->pluginset_highlighted = 0;
00575                 mwindow->session->current_operation = NO_OPERATION;
00576         }
00577 
00578 
00579 //printf("TrackCanvas::drag_stop %d %d\n", redraw, mwindow->session->current_operation);
00580         if(redraw)
00581         {
00582                 mwindow->edl->tracks->update_y_pixels(mwindow->theme);
00583                 gui->get_scrollbars();
00584                 draw();
00585                 gui->patchbay->update();
00586                 gui->cursor->update();
00587                 flash();
00588                 flush();
00589         }
00590 
00591         return result;
00592 }
00593 
00594 
00595 int64_t TrackCanvas::get_drop_position (int *is_insertion, Edit *moved_edit, int64_t moved_edit_length)
00596 {
00597         *is_insertion = 0;
00598 
00599         // get the canvas/track position
00600         int cursor_x = get_relative_cursor_x();
00601         double pos = (double)cursor_x * 
00602                 mwindow->edl->local_session->zoom_sample / 
00603                 mwindow->edl->session->sample_rate + 
00604                 (double)mwindow->edl->local_session->view_start * 
00605                 mwindow->edl->local_session->zoom_sample /
00606                 mwindow->edl->session->sample_rate;
00607         // convert to track's units to operate with them
00608         Track *track = mwindow->session->track_highlighted;
00609         // cursor relative position - depending on where we started the drag inside the edit
00610         int64_t cursor_position;
00611         if (moved_edit)  // relative cursor position depends upon grab point
00612                 cursor_position = track->to_units (pos - (mwindow->session->drag_position - moved_edit->track->from_units(moved_edit->startproject)), 1);
00613         else             // for clips and assets acts as they were grabbed in the middle
00614                 cursor_position = track->to_units (pos , 1) - moved_edit_length / 2;
00615            
00616         // we use real cursor position for affinity calculations
00617         int64_t real_cursor_position = track->to_units (pos, 0); 
00618         if (cursor_position < 0) cursor_position = 0;
00619         if (real_cursor_position < 0) real_cursor_position = 0;
00620         int64_t position = -1;
00621         int64_t span_start = 0;
00622         int64_t span_length = 0;
00623         int span_asset = 0;
00624         int last_ignore = 0; // used to make sure we can ignore the last edit if that is what we are dragging
00625 
00626         if (!track->edits->last)
00627         {
00628                 // No edits -> no problems!
00629                 position = cursor_position;
00630         }
00631         else
00632         {
00633                 Edit *fake_edit = new Edit(mwindow->edl, track);
00634                 int last2 = 0; // last2 is a hack that let us make virtual edits at the end so thing works for last edit also
00635                                // we do this by appending two VERY long virtual edits at the end
00636                 
00637                 for (Edit *edit = track->edits->first; edit || last2 < 2; )
00638                 {
00639                 
00640                         if (!edit && last_ignore)
00641                         {
00642                                 span_length += 100000000000000LL;
00643                                 last_ignore = 0;
00644                                 span_asset = 0;
00645                         } else
00646                         if (edit && 
00647                             ((moved_edit && edit == moved_edit && edit->previous && !edit->previous->asset) ||
00648                             (moved_edit && edit->previous == moved_edit  && !edit->asset)))
00649                         {
00650                                 span_length += edit->length;        // our fake edit spans over the edit we are moving
00651                                 last_ignore = 1;
00652                         } else
00653                         { // This is a virtual edit
00654                                 fake_edit->startproject = span_start;
00655                                 fake_edit->length = span_length;
00656                                 int64_t edit_x, edit_y, edit_w, edit_h;
00657                                 edit_dimensions(fake_edit, edit_x, edit_y, edit_w, edit_h);
00658                                 if (labs(edit_x - cursor_x) < HANDLE_W)                 // cursor is close to the beginning of an edit -> insertion
00659                                 {
00660                                         *is_insertion = 1;
00661                                         position = span_start;
00662                                 } else
00663                                 if (labs(edit_x + edit_w - cursor_x) < HANDLE_W)        // cursor is close to the end of an edit -> insertion
00664                                 {
00665                                         *is_insertion = 1;
00666                                         position = span_start + span_length;
00667 
00668                                 }  else
00669                                 if (!span_asset &&              // we have enough empty space to position the edit where user wants 
00670                                         span_start <= cursor_position &&
00671                                         span_start + span_length >= cursor_position + moved_edit_length)
00672                                 {
00673                                         position = cursor_position; 
00674                                 } else
00675                                 if (!span_asset &                               // we are inside an empty edit, but cannot push the edit as far as user wants, so 'resist moving it further'
00676                                         real_cursor_position >= span_start && 
00677                                         real_cursor_position < span_start + span_length && 
00678                                         span_length >= moved_edit_length)
00679                                 {
00680                                         if (llabs(real_cursor_position - span_start) < llabs(real_cursor_position - span_start - span_length))
00681                                                 position = span_start;
00682                                         else
00683                                                 position = span_start + span_length - moved_edit_length;
00684                                 } else
00685                                 if (cursor_x > edit_x && cursor_x <= edit_x + edit_w / 2) // we are inside an nonempty edit, - snap to left
00686                                 {
00687                                         *is_insertion = 1;
00688                                         position = span_start;                          
00689                                 } else
00690                                 if (cursor_x > edit_x + edit_w / 2 && cursor_x <= edit_x + edit_w) // we are inside an nonempty edit, - snap to right
00691                                 {
00692                                         *is_insertion = 1;
00693                                         position = span_start + span_length;                            
00694                                 }                               
00695                                 
00696 
00697                                 if (position != -1) 
00698                                         break;
00699                                 
00700                                 // This is the new edit
00701                                 if (edit)
00702                                 {
00703                                                 span_length = edit->length;             
00704                                                 span_start = edit->startproject;  
00705                                                 last_ignore = 0;
00706                                                 if (!edit->asset || (!moved_edit || moved_edit == edit)) 
00707                                                 {
00708                                                         if (moved_edit && moved_edit == edit)
00709                                                                 last_ignore = 1;
00710                 
00711                                                         span_asset = 0;
00712                                                 } else 
00713                                                         span_asset = 1;
00714                                 } else
00715                                 {
00716                                         span_start = span_length + span_start;
00717                                         span_length = 100000000000000LL;
00718                                         span_asset = 0;
00719                                 };
00720                                 
00721 
00722                         }
00723                         if (edit)
00724                                 edit = edit->next;
00725                         else
00726                                 last2++;
00727                         
00728                 }
00729                 delete fake_edit;
00730 
00731         }
00732         if (real_cursor_position == 0) 
00733         {
00734                 position = 0;
00735                 *is_insertion = 1;
00736         }
00737 //      printf("rcp: %lli, position: %lli, insertion: %i\n", real_cursor_position, position, *is_insertion);
00738         return position;
00739 
00740 
00741 }
00742 
00743 void TrackCanvas::draw(int force, int hide_cursor)
00744 {
00745 // Swap pixmap layers
00746 TRACE("TrackCanvas::draw 1")
00747         if(get_w() != background_pixmap->get_w() ||
00748                 get_h() != background_pixmap->get_h())
00749         {
00750                 delete background_pixmap;
00751                 background_pixmap = new BC_Pixmap(this, get_w(), get_h());
00752         }
00753 
00754 TRACE("TrackCanvas::draw 10")
00755 // Cursor disappears after resize when this is called.
00756 // Cursor doesn't redraw after editing when this isn't called.
00757         if(gui->cursor && hide_cursor) gui->cursor->hide();
00758 TRACE("TrackCanvas::draw 20")
00759         draw_top_background(get_parent(), 0, 0, get_w(), get_h(), background_pixmap);
00760 TRACE("TrackCanvas::draw 30")
00761         draw_resources(force);
00762 TRACE("TrackCanvas::draw 40")
00763         draw_overlays();
00764 UNTRACE
00765 }
00766 
00767 void TrackCanvas::update_cursor()
00768 {
00769         switch(mwindow->edl->session->editing_mode)
00770         {
00771                 case EDITING_ARROW: set_cursor(ARROW_CURSOR); break;
00772                 case EDITING_IBEAM: set_cursor(IBEAM_CURSOR); break;
00773         }
00774 }
00775 
00776 
00777 void TrackCanvas::test_timer()
00778 {
00779         if(resource_timer->get_difference() > 1000 && 
00780                 !hourglass_enabled)
00781         {
00782                 start_hourglass();
00783                 hourglass_enabled = 1;
00784         }
00785 }
00786 
00787 
00788 void TrackCanvas::draw_indexes(Asset *asset)
00789 {
00790 // Don't redraw raw samples
00791         if(asset->index_zoom > mwindow->edl->local_session->zoom_sample)
00792                 return;
00793 
00794         draw_resources(0, 1, asset);
00795 
00796         draw_overlays();
00797         draw_automation();
00798         flash();
00799         flush();
00800 }
00801 
00802 void TrackCanvas::draw_resources(int force, 
00803         int indexes_only, 
00804         Asset *index_asset)
00805 {
00806         if(!mwindow->edl->session->show_assets) return;
00807 
00808         resource_timer->update();
00809 
00810 // Age resource pixmaps for deletion
00811         if(!indexes_only)
00812                 for(int i = 0; i < resource_pixmaps.total; i++)
00813                         resource_pixmaps.values[i]->visible--;
00814 
00815         if(force)
00816                 resource_pixmaps.remove_all_objects();
00817 
00818 
00819 // Search every edit
00820         for(Track *current = mwindow->edl->tracks->first;
00821                 current;
00822                 current = NEXT)
00823         {
00824                 for(Edit *edit = current->edits->first; edit; edit = edit->next)
00825                 {
00826                         if(!edit->asset) continue;
00827                         if(indexes_only)
00828                         {
00829                                 if(edit->track->data_type != TRACK_AUDIO) continue;
00830                                 if(!edit->asset->test_path(index_asset->path)) continue;
00831                         }
00832 
00833                         int64_t edit_x, edit_y, edit_w, edit_h;
00834                         edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
00835 
00836 // Edit is visible
00837                         if(MWindowGUI::visible(edit_x, edit_x + edit_w, 0, get_w()) &&
00838                                 MWindowGUI::visible(edit_y, edit_y + edit_h, 0, get_h()))
00839                         {
00840                                 int64_t pixmap_x, pixmap_w, pixmap_h;
00841 
00842 // Search for existing pixmap containing edit
00843                                 for(int i = 0; i < resource_pixmaps.total; i++)
00844                                 {
00845                                         ResourcePixmap* pixmap = resource_pixmaps.values[i];
00846 // Same pointer can be different edit if editing took place
00847                                         if(pixmap->edit_id == edit->id)
00848                                         {
00849                                                 pixmap->visible = 1;
00850                                                 break;
00851                                         }
00852                                 }
00853 
00854 // Get new size, offset of pixmap needed
00855                                 get_pixmap_size(edit, 
00856                                         edit_x, 
00857                                         edit_w, 
00858                                         pixmap_x, 
00859                                         pixmap_w, 
00860                                         pixmap_h);
00861 
00862 // Draw new data
00863                                 if(pixmap_w && pixmap_h)
00864                                 {
00865 // Create pixmap if it doesn't exist
00866                                         ResourcePixmap* pixmap = create_pixmap(edit, 
00867                                                 edit_x, 
00868                                                 pixmap_x, 
00869                                                 pixmap_w, 
00870                                                 pixmap_h);
00871 // Resize it if it's bigger
00872                                         if(pixmap_w > pixmap->pixmap_w ||
00873                                                 pixmap_h > pixmap->pixmap_h)
00874                                                 pixmap->resize(pixmap_w, pixmap_h);
00875                                         pixmap->draw_data(edit,
00876                                                 edit_x, 
00877                                                 edit_w, 
00878                                                 pixmap_x, 
00879                                                 pixmap_w, 
00880                                                 pixmap_h, 
00881                                                 force,
00882                                                 indexes_only);
00883 // Resize it if it's smaller
00884                                         if(pixmap_w < pixmap->pixmap_w ||
00885                                                 pixmap_h < pixmap->pixmap_h)
00886                                                 pixmap->resize(pixmap_w, pixmap_h);
00887 // Copy pixmap to background canvas
00888                                         background_pixmap->draw_pixmap(pixmap, 
00889                                                 pixmap->pixmap_x, 
00890                                                 current->y_pixel,
00891                                                 pixmap->pixmap_w,
00892                                                 edit_h);
00893                                 }
00894                         }
00895                 }
00896         }
00897 
00898 // Delete unused pixmaps
00899         if(!indexes_only)
00900                 for(int i = resource_pixmaps.total - 1; i >= 0; i--)
00901                         if(resource_pixmaps.values[i]->visible < -5)
00902                         {
00903                                 delete resource_pixmaps.values[i];
00904                                 resource_pixmaps.remove(resource_pixmaps.values[i]);
00905                         }
00906 
00907         if(hourglass_enabled) 
00908         {
00909                 stop_hourglass();
00910                 hourglass_enabled = 0;
00911         }
00912 }
00913 
00914 ResourcePixmap* TrackCanvas::create_pixmap(Edit *edit, 
00915         int64_t edit_x, 
00916         int64_t pixmap_x, 
00917         int64_t pixmap_w, 
00918         int64_t pixmap_h)
00919 {
00920         ResourcePixmap *result = 0;
00921 
00922         for(int i = 0; i < resource_pixmaps.total; i++)
00923         {
00924 //printf("TrackCanvas::create_pixmap 1 %d %d\n", edit->id, resource_pixmaps.values[i]->edit->id);
00925                 if(resource_pixmaps.values[i]->edit_id == edit->id) 
00926                 {
00927                         result = resource_pixmaps.values[i];
00928                         break;
00929                 }
00930         }
00931 
00932         if(!result)
00933         {
00934 //printf("TrackCanvas::create_pixmap 2\n");
00935                 result = new ResourcePixmap(mwindow, 
00936                         this, 
00937                         edit, 
00938                         pixmap_w, 
00939                         pixmap_h);
00940                 resource_pixmaps.append(result);
00941         }
00942 
00943 //      result->resize(pixmap_w, pixmap_h);
00944         return result;
00945 }
00946 
00947 void TrackCanvas::get_pixmap_size(Edit *edit, 
00948         int64_t edit_x, 
00949         int64_t edit_w, 
00950         int64_t &pixmap_x, 
00951         int64_t &pixmap_w,
00952         int64_t &pixmap_h)
00953 {
00954 
00955 // Align x on frame boundaries
00956 
00957 
00958 //      switch(edit->edits->track->data_type)
00959 //      {
00960 //              case TRACK_AUDIO:
00961 
00962                         pixmap_x = edit_x;
00963                         pixmap_w = edit_w;
00964                         if(pixmap_x < 0)
00965                         {
00966                                 pixmap_w -= -edit_x;
00967                                 pixmap_x = 0;
00968                         }
00969 
00970                         if(pixmap_x + pixmap_w > get_w())
00971                         {
00972                                 pixmap_w = get_w() - pixmap_x;
00973                         }
00974 
00975 //                      break;
00976 // 
00977 //              case TRACK_VIDEO:
00978 //              {
00979 //                      int64_t picon_w = (int64_t)(edit->picon_w() + 0.5);
00980 //                      int64_t frame_w = (int64_t)(edit->frame_w() + 0.5);
00981 //                      int64_t pixel_increment = MAX(picon_w, frame_w);
00982 //                      int64_t pixmap_x1 = edit_x;
00983 //                      int64_t pixmap_x2 = edit_x + edit_w;
00984 // 
00985 //                      if(pixmap_x1 < 0)
00986 //                      {
00987 //                              pixmap_x1 = (int64_t)((double)-edit_x / pixel_increment) * 
00988 //                                      pixel_increment + 
00989 //                                      edit_x;
00990 //                      }
00991 // 
00992 //                      if(pixmap_x2 > get_w())
00993 //                      {
00994 //                              pixmap_x2 = (int64_t)((double)(get_w() - edit_x) / pixel_increment + 1) * 
00995 //                                      pixel_increment + 
00996 //                                      edit_x;
00997 //                      }
00998 //                      pixmap_x = pixmap_x1;
00999 //                      pixmap_w = pixmap_x2 - pixmap_x1;
01000 //                      break;
01001 //              }
01002 //      }
01003 
01004         pixmap_h = mwindow->edl->local_session->zoom_track;
01005         if(mwindow->edl->session->show_titles) pixmap_h += mwindow->theme->title_bg_data->get_h();
01006 //printf("get_pixmap_size %d %d %d %d\n", edit_x, edit_w, pixmap_x, pixmap_w);
01007 }
01008 
01009 void TrackCanvas::edit_dimensions(Edit *edit, 
01010         int64_t &x, 
01011         int64_t &y, 
01012         int64_t &w, 
01013         int64_t &h)
01014 {
01015 //      w = Units::round(edit->track->from_units(edit->length) * 
01016 //              mwindow->edl->session->sample_rate / 
01017 //              mwindow->edl->local_session->zoom_sample);
01018 
01019         h = resource_h();
01020 
01021         x = Units::round(edit->track->from_units(edit->startproject) * 
01022                         mwindow->edl->session->sample_rate /
01023                         mwindow->edl->local_session->zoom_sample - 
01024                         mwindow->edl->local_session->view_start);
01025 
01026 // Method for calculating w so when edits are together we never get off by one error due to rounding
01027         int64_t x_next = Units::round(edit->track->from_units(edit->startproject + edit->length) * 
01028                         mwindow->edl->session->sample_rate /
01029                         mwindow->edl->local_session->zoom_sample - 
01030                         mwindow->edl->local_session->view_start);
01031         w = x_next - x;
01032 
01033         y = edit->edits->track->y_pixel;
01034 
01035         if(mwindow->edl->session->show_titles) 
01036                 h += mwindow->theme->title_bg_data->get_h();
01037 }
01038 
01039 void TrackCanvas::track_dimensions(Track *track, int64_t &x, int64_t &y, int64_t &w, int64_t &h)
01040 {
01041         x = 0;
01042         w = get_w();
01043         y = track->y_pixel;
01044         h = track->vertical_span(mwindow->theme);
01045 }
01046 
01047 
01048 void TrackCanvas::draw_paste_destination()
01049 {
01050         int current_atrack = 0;
01051         int current_vtrack = 0;
01052         int current_aedit = 0;
01053         int current_vedit = 0;
01054         int64_t w = 0;
01055         int64_t x;
01056         double position;
01057         int insertion  = 0;
01058 
01059 
01060         if((mwindow->session->current_operation == DRAG_ASSET &&
01061                         (mwindow->session->drag_assets->total ||
01062                         mwindow->session->drag_clips->total)) ||
01063                 (mwindow->session->current_operation == DRAG_EDIT &&
01064                         mwindow->session->drag_edits->total))
01065         {
01066 
01067                 Asset *asset = 0;
01068                 EDL *clip = 0;
01069                 int draw_box = 0;
01070 
01071                 if(mwindow->session->current_operation == DRAG_ASSET &&
01072                         mwindow->session->drag_assets->total)
01073                         asset = mwindow->session->drag_assets->values[0];
01074 
01075                 if(mwindow->session->current_operation == DRAG_ASSET &&
01076                         mwindow->session->drag_clips->total)
01077                         clip = mwindow->session->drag_clips->values[0];
01078 
01079 // Get destination track
01080                 for(Track *dest = mwindow->session->track_highlighted; 
01081                         dest; 
01082                         dest = dest->next)
01083                 {
01084                         if(dest->record)
01085                         {
01086 // Get source width in pixels
01087                                 w = -1;
01088 
01089 // Use start of highlighted edit
01090                                 if(mwindow->session->edit_highlighted)
01091                                         position = mwindow->session->track_highlighted->from_units(
01092                                                 mwindow->session->edit_highlighted->startproject);
01093                                 else
01094 // Use end of highlighted track, disregarding effects
01095                                         position = mwindow->session->track_highlighted->from_units(
01096                                                 mwindow->session->track_highlighted->edits->length());
01097 
01098 
01099                                 if(dest->data_type == TRACK_AUDIO)
01100                                 {
01101                                         if(asset && current_atrack < asset->channels)
01102                                         {
01103                                         
01104                                                 w = Units::to_int64((double)asset->audio_length /
01105                                                         asset->sample_rate *
01106                                                         mwindow->edl->session->sample_rate / 
01107                                                         mwindow->edl->local_session->zoom_sample);
01108                                                 
01109                                         // FIXME: more obvious, get_drop_position should be called only ONCE - for highlighted track
01110                                                 int64_t asset_length;
01111                                                 // we use video if we are over video and audio if we are over audio
01112                                                 if (asset->video_data && mwindow->session->track_highlighted->data_type == TRACK_VIDEO)
01113                                                         asset_length = mwindow->session->track_highlighted->to_units(asset->video_length / asset->frame_rate, 0);
01114                                                 else
01115                                                         asset_length = mwindow->session->track_highlighted->to_units(asset->audio_length / asset->sample_rate, 0);
01116 
01117                                                 position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
01118                                                 if (position < 0) 
01119                                                         w = -1;
01120                                                 else
01121                                                 {
01122                                                         current_atrack++;
01123                                                         draw_box = 1;
01124                                                 }
01125                                         }
01126                                         else
01127                                         if(clip && current_atrack < clip->tracks->total_audio_tracks())
01128                                         {
01129                                                 w = Units::to_int64((double)clip->tracks->total_length() *
01130                                                         mwindow->edl->session->sample_rate / 
01131                                                         mwindow->edl->local_session->zoom_sample);
01132 //printf("draw_paste_destination %d\n", x);
01133                                                 int64_t asset_length = mwindow->session->track_highlighted->to_units((double)clip->tracks->total_length(), 0);
01134                                 
01135                                                 position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
01136                                                 if (position < 0) 
01137                                                         w = -1;
01138                                                 else
01139                                                 {
01140                                                         current_atrack++;
01141                                                         draw_box = 1;
01142                                                 }
01143                                         }
01144                                         else
01145                                         if(mwindow->session->current_operation == DRAG_EDIT &&
01146                                                 current_aedit < mwindow->session->drag_edits->total)
01147                                         {
01148                                                 Edit *edit;
01149                                                 while(current_aedit < mwindow->session->drag_edits->total &&
01150                                                         mwindow->session->drag_edits->values[current_aedit]->track->data_type != TRACK_AUDIO)
01151                                                         current_aedit++;
01152 
01153                                                 if(current_aedit < mwindow->session->drag_edits->total)
01154                                                 {
01155                                                         edit = mwindow->session->drag_edits->values[current_aedit];
01156                                                         w = Units::to_int64(edit->length / mwindow->edl->local_session->zoom_sample);
01157 
01158                                                         position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, mwindow->session->drag_edit, mwindow->session->drag_edit->length));
01159                                                         if (position < 0) 
01160                                                                 w = -1;
01161                                                         else
01162                                                         {
01163                                                                 current_aedit++;
01164                                                                 draw_box = 1;
01165                                                         }
01166 
01167                                                 }
01168                                         }
01169                                 }
01170                                 else
01171                                 if(dest->data_type == TRACK_VIDEO)
01172                                 {
01173 //printf("draw_paste_destination 1\n");
01174                                         if(asset && current_vtrack < asset->layers)
01175                                         {
01176                                                 w = Units::to_int64((double)asset->video_length / 
01177                                                         asset->frame_rate *
01178                                                         mwindow->edl->session->sample_rate /
01179                                                         mwindow->edl->local_session->zoom_sample);
01180                                                 int64_t asset_length = mwindow->session->track_highlighted->to_units((double)asset->video_length / 
01181                                                         asset->frame_rate, 0);
01182                                 
01183                                                 position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
01184                                                 if (position < 0) 
01185                                                         w = -1;
01186                                                 else
01187                                                 {
01188                                                         current_vtrack++;
01189                                                         draw_box = 1;
01190                                                 }
01191                                         }
01192                                         else
01193                                         if(clip && current_vtrack < clip->tracks->total_video_tracks())
01194                                         {
01195                                                 w = Units::to_int64(clip->tracks->total_length() *
01196                                                         mwindow->edl->session->sample_rate / 
01197                                                         mwindow->edl->local_session->zoom_sample);
01198                                                 int64_t asset_length = mwindow->session->track_highlighted->to_units((double)clip->tracks->total_length(), 0);
01199                                 
01200                                                 position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
01201                                                 if (position < 0) 
01202                                                         w = -1;
01203                                                 else
01204                                                 {
01205                                                         current_vtrack++;
01206                                                         draw_box = 1;
01207                                                 }
01208                                         }
01209                                         else
01210                                         if(mwindow->session->current_operation == DRAG_EDIT &&
01211                                                 current_vedit < mwindow->session->drag_edits->total)
01212                                         {
01213                                                 Edit *edit;
01214                                                 while(current_vedit < mwindow->session->drag_edits->total &&
01215                                                         mwindow->session->drag_edits->values[current_vedit]->track->data_type != TRACK_VIDEO)
01216                                                         current_vedit++;
01217 
01218                                                 if(current_vedit < mwindow->session->drag_edits->total)
01219                                                 {
01220                                                         edit = mwindow->session->drag_edits->values[current_vedit];
01221                                                         w = Units::to_int64(edit->track->from_units(edit->length) *
01222                                                                 mwindow->edl->session->sample_rate / 
01223                                                                 mwindow->edl->local_session->zoom_sample);
01224 
01225                                                         position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, mwindow->session->drag_edit, mwindow->session->drag_edit->length));
01226                                                         if (position < 0) 
01227                                                                 w = -1;
01228                                                         else
01229                                                         {
01230                                                                 current_vedit++;
01231                                                                 draw_box = 1;
01232                                                         }
01233                                                 }
01234 
01235                                         }
01236                                 }
01237 
01238                                 if(w >= 0)
01239                                 {
01240 // Get the x coordinate
01241                                         x = Units::to_int64(position * 
01242                                                 mwindow->edl->session->sample_rate /
01243                                                 mwindow->edl->local_session->zoom_sample) - 
01244                                                 mwindow->edl->local_session->view_start;
01245                                         int y = dest->y_pixel;
01246                                         int h = dest->vertical_span(mwindow->theme);
01247 
01248 
01249 //printf("TrackCanvas::draw_paste_destination 2 %d %d %d %d\n", x, y, w, h);
01250                                         if (insertion)
01251                                                 draw_highlight_insertion(x, y, w, h);
01252                                         else
01253                                                 draw_highlight_rectangle(x, y, w, h);
01254                                         
01255 
01256                                 }
01257                         }
01258                 }
01259         }
01260 }
01261 
01262 void TrackCanvas::plugin_dimensions(Plugin *plugin, int64_t &x, int64_t &y, int64_t &w, int64_t &h)
01263 {
01264         x = Units::round(plugin->track->from_units(plugin->startproject) *
01265                 mwindow->edl->session->sample_rate / 
01266                 mwindow->edl->local_session->zoom_sample - 
01267                 mwindow->edl->local_session->view_start);
01268         w = Units::round(plugin->track->from_units(plugin->length) *
01269                 mwindow->edl->session->sample_rate / 
01270                 mwindow->edl->local_session->zoom_sample);
01271         y = plugin->track->y_pixel + 
01272                         mwindow->edl->local_session->zoom_track +
01273                         plugin->plugin_set->get_number() * 
01274                         mwindow->theme->plugin_bg_data->get_h();
01275         if(mwindow->edl->session->show_titles)
01276                 y += mwindow->theme->title_bg_data->get_h();
01277         h = mwindow->theme->plugin_bg_data->get_h();
01278 }
01279 
01280 int TrackCanvas::resource_h()
01281 {
01282         return mwindow->edl->local_session->zoom_track;
01283 }
01284 
01285 void TrackCanvas::draw_highlight_rectangle(int x, int y, int w, int h)
01286 {
01287 
01288 // if we have to draw a highlighted rectangle completely on the left or completely on the right of the viewport, 
01289 // just draw arrows, so user has indication that something is there
01290 // FIXME: get better colors
01291 
01292         if (x + w <= 0)
01293         {
01294                 draw_triangle_left(0, y + h /6, h * 2/3, h * 2/3, BLACK, GREEN, YELLOW, RED, BLUE);
01295                 return;
01296         } else
01297         if (x >= get_w())
01298         {
01299                 draw_triangle_right(get_w() - h * 2/3, y + h /6, h * 2/3, h * 2/3, BLACK, GREEN, YELLOW, RED, BLUE);
01300                 return;
01301         }
01302 
01303 // Fix bug in heroines & cvs version as of 22.8.2005:
01304 // If we grab when zoomed in and zoom out while dragging, when edit gets really narrow strange things start happening
01305         if (w >= 0 && w < 3) {x -= w /2; w = 3;};
01306         if(x < -10)
01307         {
01308                 w += x - -10;
01309                 x = -10;
01310         }
01311         if(y < -10)
01312         {
01313                 h += y - -10;
01314                 y = -10;
01315         }
01316         w = MIN(w, get_w() + 20);
01317         h = MIN(h, get_h() + 20);
01318         set_color(WHITE);
01319         set_inverse();
01320         draw_rectangle(x, y, w, h);
01321         draw_rectangle(x + 1, y + 1, w - 2, h - 2);
01322         set_opaque();
01323 //printf("TrackCanvas::draw_highlight_rectangle %d %d %d %d\n", x, y, w, h);
01324 }
01325 
01326 void TrackCanvas::draw_highlight_insertion(int x, int y, int w, int h)
01327 {
01328 
01329 // if we have to draw a highlighted rectangle completely on the left or completely on the right of the viewport, 
01330 // just draw arrows, so user has indication that something is there
01331 // FIXME: get better colors
01332 
01333 
01334         
01335         int h1 = h / 8;
01336         int h2 = h / 4;
01337         
01338         set_inverse();
01339 
01340 /* these don't look so good
01341 
01342         draw_line(x, y, x, y+h);
01343         draw_line(x - h2 * 2, y + h1*2,   x - h2, y+h1*2);
01344         draw_line(x - h2 * 2, y + h1*2+1, x - h2, y+h1*2+1);
01345         draw_line(x - h2 * 2, y + h1*6,   x - h2, y+h1*6);
01346         draw_line(x - h2 * 2, y + h1*6+1, x - h2, y+h1*6+1);
01347 */
01348         draw_triangle_right(x - h2, y + h1, h2, h2, BLACK, GREEN, YELLOW, RED, BLUE);
01349         draw_triangle_right(x - h2, y + h1*5, h2, h2, BLACK, GREEN, YELLOW, RED, BLUE);
01350 
01351 /*      draw_line(x + h2 * 2, y + h1*2,   x + h2, y+h1*2);
01352         draw_line(x + h2 * 2, y + h1*2+1, x + h2, y+h1*2+1);
01353         draw_line(x + h2 * 2, y + h1*6,   x + h2, y+h1*6);
01354         draw_line(x - h2 * 2, y + h1*6+1, x + h2, y+h1*6+1);
01355 */
01356         draw_triangle_left(x, y + h1, h2, h2, BLACK, GREEN, YELLOW, RED, BLUE);
01357         draw_triangle_left(x, y + h1*5, h2, h2, BLACK, GREEN, YELLOW, RED, BLUE);
01358         
01359 // draw the box centred around x
01360         x -= w / 2;
01361 // Fix bug in heroines & cvs version as of 22.8.2005:
01362 // If we grab when zoomed in and zoom out while dragging, when edit gets really narrow strange things start happening
01363         if (w >= 0 && w < 3) {x -= w /2; w = 3;};
01364         if(x < -10)
01365         {
01366                 w += x - -10;
01367                 x = -10;
01368         }
01369         if(y < -10)
01370         {
01371                 h += y - -10;
01372                 y = -10;
01373         }
01374         w = MIN(w, get_w() + 20);
01375         h = MIN(h, get_h() + 20);
01376         set_color(WHITE);
01377         set_inverse();
01378         draw_rectangle(x, y, w, h);
01379         draw_rectangle(x + 1, y + 1, w - 2, h - 2);
01380         set_opaque();
01381 //printf("TrackCanvas::draw_highlight_insertion %d %d %d %d\n", x, y, w, h);
01382 }
01383 
01384 void TrackCanvas::draw_playback_cursor()
01385 {
01386 // Called before playback_cursor exists
01387 //      if(mwindow->playback_cursor && mwindow->playback_cursor->visible)
01388 //      {
01389 //              mwindow->playback_cursor->visible = 0;
01390 //              mwindow->playback_cursor->draw();
01391 //      }
01392 }
01393 
01394 void TrackCanvas::get_handle_coords(Edit *edit, int64_t &x, int64_t &y, int64_t &w, int64_t &h, int side)
01395 {
01396         int handle_w = mwindow->theme->edithandlein_data[0]->get_w();
01397         int handle_h = mwindow->theme->edithandlein_data[0]->get_h();
01398 
01399         edit_dimensions(edit, x, y, w, h);
01400 
01401         if(mwindow->edl->session->show_titles)
01402         {
01403                 y += mwindow->theme->title_bg_data->get_h();
01404         }
01405         else
01406         {
01407                 y = 0;
01408         }
01409 
01410         if(side == EDIT_OUT)
01411         {
01412                 x += w - handle_w;
01413         }
01414 
01415         h = handle_h;
01416         w = handle_w;
01417 }
01418 
01419 void TrackCanvas::get_transition_coords(int64_t &x, int64_t &y, int64_t &w, int64_t &h)
01420 {
01421 //printf("TrackCanvas::get_transition_coords 1\n");
01422 //      int transition_w = mwindow->theme->transitionhandle_data[0]->get_w();
01423 //      int transition_h = mwindow->theme->transitionhandle_data[0]->get_h();
01424         int transition_w = 30;
01425         int transition_h = 30;
01426 //printf("TrackCanvas::get_transition_coords 1\n");
01427 
01428         if(mwindow->edl->session->show_titles)
01429                 y += mwindow->theme->title_bg_data->get_h();
01430 //printf("TrackCanvas::get_transition_coords 2\n");
01431 
01432         y += (h - mwindow->theme->title_bg_data->get_h()) / 2 - transition_h / 2;
01433         x -= transition_w / 2;
01434 
01435         h = transition_h;
01436         w = transition_w;
01437 }
01438 
01439 void TrackCanvas::draw_highlighting()
01440 {
01441         int64_t x, y, w, h;
01442         int draw_box = 0;
01443 
01444 
01445 
01446         switch(mwindow->session->current_operation)
01447         {
01448                 case DRAG_ATRANSITION:
01449                 case DRAG_VTRANSITION:
01450 //printf("TrackCanvas::draw_highlighting 1 %p %p\n", 
01451 //      mwindow->session->track_highlighted, mwindow->session->edit_highlighted);
01452                         if(mwindow->session->edit_highlighted)
01453                         {
01454 //printf("TrackCanvas::draw_highlighting 2\n");
01455                                 if((mwindow->session->current_operation == DRAG_ATRANSITION && 
01456                                         mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
01457                                         (mwindow->session->current_operation == DRAG_VTRANSITION && 
01458                                         mwindow->session->track_highlighted->data_type == TRACK_VIDEO))
01459                                 {
01460 //printf("TrackCanvas::draw_highlighting 2\n");
01461                                         edit_dimensions(mwindow->session->edit_highlighted, x, y, w, h);
01462 //printf("TrackCanvas::draw_highlighting 2\n");
01463 
01464                                         if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
01465                                                 MWindowGUI::visible(y, y + h, 0, get_h()))
01466                                         {
01467                                                 draw_box = 1;
01468                                                 get_transition_coords(x, y, w, h);
01469                                         }
01470 //printf("TrackCanvas::draw_highlighting 3\n");
01471                                 }
01472                         }
01473                         break;
01474 
01475 
01476 
01477 // Dragging a new effect from the Resource window
01478                 case DRAG_AEFFECT:
01479                 case DRAG_VEFFECT:
01480                         if(mwindow->session->track_highlighted &&
01481                                 ((mwindow->session->current_operation == DRAG_AEFFECT && mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
01482                                         (mwindow->session->current_operation == DRAG_VEFFECT && mwindow->session->track_highlighted->data_type == TRACK_VIDEO)))
01483                         {
01484 // Put it before another plugin
01485                                 if(mwindow->session->plugin_highlighted)
01486                                 {
01487                                         plugin_dimensions(mwindow->session->plugin_highlighted, 
01488                                                 x, 
01489                                                 y, 
01490                                                 w, 
01491                                                 h);
01492 //printf("TrackCanvas::draw_highlighting 1 %d %d\n", x, w);
01493                                 }
01494                                 else
01495 // Put it after a plugin set
01496                                 if(mwindow->session->pluginset_highlighted &&
01497                                         mwindow->session->pluginset_highlighted->last)
01498                                 {
01499                                         plugin_dimensions((Plugin*)mwindow->session->pluginset_highlighted->last, 
01500                                                 x, 
01501                                                 y, 
01502                                                 w, 
01503                                                 h);
01504 //printf("TrackCanvas::draw_highlighting 1 %d %d\n", x, w);
01505                                         int64_t track_x, track_y, track_w, track_h;
01506                                         track_dimensions(mwindow->session->track_highlighted, 
01507                                                 track_x, 
01508                                                 track_y, 
01509                                                 track_w, 
01510                                                 track_h);
01511 
01512                                         x += w;
01513                                         w = Units::round(
01514                                                         mwindow->session->track_highlighted->get_length() *
01515                                                         mwindow->edl->session->sample_rate / 
01516                                                         mwindow->edl->local_session->zoom_sample - 
01517                                                         mwindow->edl->local_session->view_start) -
01518                                                 x;
01519 //printf("TrackCanvas::draw_highlighting 2 %d\n", w);
01520                                         if(w <= 0) w = track_w;
01521                                 }
01522                                 else
01523                                 {
01524                                         track_dimensions(mwindow->session->track_highlighted, 
01525                                                 x, 
01526                                                 y, 
01527                                                 w, 
01528                                                 h);
01529 
01530 //printf("TrackCanvas::draw_highlighting 1 %d %d %d %d\n", x, y, w, h);
01531 // Put it in a new plugin set determined by the selected range
01532                                         if(mwindow->edl->local_session->get_selectionend() > 
01533                                                 mwindow->edl->local_session->get_selectionstart())
01534                                         {
01535                                                 x = Units::to_int64(mwindow->edl->local_session->get_selectionstart() *
01536                                                         mwindow->edl->session->sample_rate / 
01537                                                         mwindow->edl->local_session->zoom_sample -
01538                                                         mwindow->edl->local_session->view_start);
01539                                                 w = Units::to_int64((mwindow->edl->local_session->get_selectionend() - 
01540                                                         mwindow->edl->local_session->get_selectionstart()) *
01541                                                         mwindow->edl->session->sample_rate / 
01542                                                         mwindow->edl->local_session->zoom_sample);
01543                                         }
01544 // Put it in a new plugin set determined by an edit boundary
01545                                         else
01546                                         if(mwindow->session->edit_highlighted)
01547                                         {
01548                                                 int64_t temp_y, temp_h;
01549                                                 edit_dimensions(mwindow->session->edit_highlighted, 
01550                                                         x, 
01551                                                         temp_y, 
01552                                                         w, 
01553                                                         temp_h);
01554                                         }
01555 // Put it at the beginning of the track in a new plugin set
01556                                 }
01557 
01558                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
01559                                         MWindowGUI::visible(y, y + h, 0, get_h()))
01560                                 {
01561 //printf("TrackCanvas::draw_highlighting 1\n");
01562                                         draw_box = 1;
01563                                 }
01564                         }
01565                         break;
01566                 
01567                 case DRAG_ASSET:
01568                         if(mwindow->session->track_highlighted)
01569                         {
01570                                 track_dimensions(mwindow->session->track_highlighted, x, y, w, h);
01571 
01572                                 if(MWindowGUI::visible(y, y + h, 0, get_h()))
01573                                 {
01574                                         draw_paste_destination();
01575                                 }
01576                         }
01577                         break;
01578 
01579 // Dragging an effect from the timeline
01580                 case DRAG_AEFFECT_COPY:
01581                 case DRAG_VEFFECT_COPY:
01582                         if((mwindow->session->plugin_highlighted || mwindow->session->track_highlighted) &&
01583                                 ((mwindow->session->current_operation == DRAG_AEFFECT_COPY && mwindow->session->track_highlighted->data_type == TRACK_AUDIO) ||
01584                                 (mwindow->session->current_operation == DRAG_VEFFECT_COPY && mwindow->session->track_highlighted->data_type == TRACK_VIDEO)))
01585                         {
01586 // Put it before another plugin
01587                                 if(mwindow->session->plugin_highlighted)
01588                                         plugin_dimensions(mwindow->session->plugin_highlighted, x, y, w, h);
01589                                 else
01590 // Put it after a plugin set
01591                                 if(mwindow->session->pluginset_highlighted &&
01592                                         mwindow->session->pluginset_highlighted->last)
01593                                 {
01594                                         plugin_dimensions((Plugin*)mwindow->session->pluginset_highlighted->last, x, y, w, h);
01595                                         x += w;
01596                                 }
01597                                 else
01598                                 if(mwindow->session->track_highlighted)
01599                                 {
01600                                         track_dimensions(mwindow->session->track_highlighted, x, y, w, h);
01601 
01602 // Put it in a new plugin set determined by an edit boundary
01603                                         if(mwindow->session->edit_highlighted)
01604                                         {
01605                                                 int64_t temp_y, temp_h;
01606                                                 edit_dimensions(mwindow->session->edit_highlighted, 
01607                                                         x, 
01608                                                         temp_y, 
01609                                                         w, 
01610                                                         temp_h);
01611                                         }
01612 // Put it in a new plugin set at the start of the track
01613                                 }
01614 
01615 // Calculate length of plugin based on data type of track and units
01616                                 if(mwindow->session->track_highlighted->data_type == TRACK_VIDEO)
01617                                 {
01618                                         w = (int64_t)((double)mwindow->session->drag_plugin->length / 
01619                                                 mwindow->edl->session->frame_rate *
01620                                                 mwindow->edl->session->sample_rate /
01621                                                 mwindow->edl->local_session->zoom_sample);
01622                                 }
01623                                 else
01624                                 {
01625                                         w = (int64_t)mwindow->session->drag_plugin->length /
01626                                                 mwindow->edl->local_session->zoom_sample;
01627                                 }
01628 
01629                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
01630                                         MWindowGUI::visible(y, y + h, 0, get_h()))
01631                                 {
01632                                         draw_box = 1;
01633                                 }
01634                         }
01635                         break;
01636 
01637                 case DRAG_PLUGINKEY:
01638                         if(mwindow->session->plugin_highlighted && 
01639                            mwindow->session->current_operation == DRAG_PLUGINKEY)
01640                         {
01641 // Just highlight the plugin
01642                                 plugin_dimensions(mwindow->session->plugin_highlighted, x, y, w, h);
01643 
01644                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
01645                                         MWindowGUI::visible(y, y + h, 0, get_h()))
01646                                 {
01647                                         draw_box = 1;
01648                                 }
01649                         }
01650                         break;
01651 
01652                 case DRAG_EDIT:
01653                         if(mwindow->session->track_highlighted)
01654                         {
01655                                 track_dimensions(mwindow->session->track_highlighted, x, y, w, h);
01656 
01657                                 if(MWindowGUI::visible(y, y + h, 0, get_h()))
01658                                 {
01659                                         draw_paste_destination();
01660                                 }
01661                         }
01662                         break;
01663         }
01664 
01665 
01666         if(draw_box)
01667         {
01668                 draw_highlight_rectangle(x, y, w, h);
01669         }
01670 }
01671 
01672 void TrackCanvas::draw_plugins()
01673 {
01674         char string[BCTEXTLEN];
01675 
01676         if(!mwindow->edl->session->show_assets) return;
01677 
01678         for(Track *track = mwindow->edl->tracks->first;
01679                 track;
01680                 track = track->next)
01681         {
01682                 if(track->expand_view)
01683                 {
01684                         for(int i = 0; i < track->plugin_set.total; i++)
01685                         {
01686                                 PluginSet *pluginset = track->plugin_set.values[i];
01687 
01688                                 for(Plugin *plugin = (Plugin*)pluginset->first; plugin; plugin = (Plugin*)plugin->next)
01689                                 {
01690                                         int64_t total_x, y, total_w, h;
01691                                         plugin_dimensions(plugin, total_x, y, total_w, h);
01692                                         
01693                                         if(MWindowGUI::visible(total_x, total_x + total_w, 0, get_w()) &&
01694                                                 MWindowGUI::visible(y, y + h, 0, get_h()) &&
01695                                                 plugin->plugin_type != PLUGIN_NONE)
01696                                         {
01697                                                 int x = total_x, w = total_w, left_margin = 5;
01698                                                 if(x < 0)
01699                                                 {
01700                                                         w -= -x;
01701                                                         x = 0;
01702                                                 }
01703                                                 if(w + x > get_w()) w -= (w + x) - get_w();
01704 
01705                                                 draw_3segmenth(x, 
01706                                                         y, 
01707                                                         w, 
01708                                                         total_x,
01709                                                         total_w,
01710                                                         mwindow->theme->plugin_bg_data,
01711                                                         0);
01712                                                 set_color(WHITE);
01713                                                 set_font(MEDIUMFONT_3D);
01714                                                 plugin->calculate_title(string, 0);
01715 
01716 // Truncate string to int64_test visible in background
01717                                                 int len = strlen(string), j;
01718                                                 for(j = len; j >= 0; j--)
01719                                                 {
01720                                                         if(left_margin + get_text_width(MEDIUMFONT_3D, string) > w)
01721                                                         {
01722                                                                 string[j] = 0;
01723                                                         }
01724                                                         else
01725                                                                 break;
01726                                                 }
01727 
01728 // Justify the text on the left boundary of the edit if it is visible.
01729 // Otherwise justify it on the left side of the screen.
01730                                                 int text_x = total_x + left_margin;
01731                                                 text_x = MAX(left_margin, text_x);
01732                                                 draw_text(text_x, 
01733                                                         y + get_text_ascent(MEDIUMFONT_3D) + 2, 
01734                                                         string,
01735                                                         strlen(string),
01736                                                         0);
01737                                         }
01738                                 }
01739                         }
01740                 }
01741         }
01742 }
01743 
01744 
01745 void TrackCanvas::draw_inout_points()
01746 {
01747 }
01748 
01749 
01750 void TrackCanvas::draw_drag_handle()
01751 {
01752         if(mwindow->session->current_operation == DRAG_EDITHANDLE2 ||
01753                 mwindow->session->current_operation == DRAG_PLUGINHANDLE2)
01754         {
01755 //printf("TrackCanvas::draw_drag_handle 1 %ld %ld\n", mwindow->session->drag_sample, mwindow->edl->local_session->view_start);
01756                 int64_t pixel1 = Units::round(mwindow->session->drag_position * 
01757                         mwindow->edl->session->sample_rate /
01758                         mwindow->edl->local_session->zoom_sample - 
01759                         mwindow->edl->local_session->view_start);
01760 //printf("TrackCanvas::draw_drag_handle 2 %d\n", pixel1);
01761                 set_color(GREEN);
01762                 set_inverse();
01763 //printf("TrackCanvas::draw_drag_handle 3\n");
01764                 draw_line(pixel1, 0, pixel1, get_h());
01765                 set_opaque();
01766 //printf("TrackCanvas::draw_drag_handle 4\n");
01767         }
01768 }
01769 
01770 
01771 void TrackCanvas::draw_transitions()
01772 {
01773         int64_t x, y, w, h;
01774 
01775         if(!mwindow->edl->session->show_assets) return;
01776 
01777         for(Track *track = mwindow->edl->tracks->first;
01778                 track;
01779                 track = track->next)
01780         {
01781                 for(Edit *edit = track->edits->first;
01782                         edit;
01783                         edit = edit->next)
01784                 {
01785                         if(edit->transition)
01786                         {
01787                                 int64_t strip_w, strip_x, strip_y;
01788                                 edit_dimensions(edit, x, y, w, h);
01789                                 strip_x = x ;
01790                                 strip_y = y;
01791                                 if(mwindow->edl->session->show_titles)
01792                                         strip_y += mwindow->theme->title_bg_data->get_h();
01793 
01794                                 get_transition_coords(x, y, w, h);
01795                                 strip_w = Units::round(edit->track->from_units(edit->transition->length) * 
01796                                         mwindow->edl->session->sample_rate / 
01797                                         mwindow->edl->local_session->zoom_sample);
01798 
01799                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
01800                                         MWindowGUI::visible(y, y + h, 0, get_h()))
01801                                 {
01802                                         PluginServer *server = mwindow->scan_plugindb(edit->transition->title,
01803                                                 track->data_type);
01804                                         draw_vframe(server->picon, 
01805                                                 x, 
01806                                                 y, 
01807                                                 w, 
01808                                                 h, 
01809                                                 0, 
01810                                                 0, 
01811                                                 server->picon->get_w(), 
01812                                                 server->picon->get_h());
01813                                 }
01814                                 if(MWindowGUI::visible(strip_x, strip_x + strip_w, 0, get_w()) &&
01815                                         MWindowGUI::visible(strip_y, strip_y + h, 0, get_h()))
01816                                 {
01817                                         int x = strip_x, w = strip_w, left_margin = 5;
01818                                         if(x < 0)
01819                                         {
01820                                                 w -= -x;
01821                                                 x = 0;
01822                                         }
01823                                         if(w + x > get_w()) w -= (w + x) - get_w();
01824                                 
01825                                         draw_3segmenth(
01826                                                 x, 
01827                                                 strip_y, 
01828                                                 w, 
01829                                                 strip_x,
01830                                                 strip_w,
01831                                                 mwindow->theme->plugin_bg_data,
01832                                                 0);
01833 
01834                                 }
01835                         }
01836                 }
01837         }
01838 }
01839 
01840 void TrackCanvas::draw_loop_points()
01841 {
01842 //printf("TrackCanvas::draw_loop_points 1\n");
01843         if(mwindow->edl->local_session->loop_playback)
01844         {
01845 //printf("TrackCanvas::draw_loop_points 2\n");
01846                 int64_t x = Units::round(mwindow->edl->local_session->loop_start *
01847                         mwindow->edl->session->sample_rate /
01848                         mwindow->edl->local_session->zoom_sample - 
01849                         mwindow->edl->local_session->view_start);
01850 //printf("TrackCanvas::draw_loop_points 3\n");
01851 
01852                 if(MWindowGUI::visible(x, x + 1, 0, get_w()))
01853                 {
01854                         set_color(GREEN);
01855                         draw_line(x, 0, x, get_h());
01856                 }
01857 //printf("TrackCanvas::draw_loop_points 4\n");
01858 
01859                 x = Units::round(mwindow->edl->local_session->loop_end *
01860                         mwindow->edl->session->sample_rate /
01861                         mwindow->edl->local_session->zoom_sample - 
01862                         mwindow->edl->local_session->view_start);
01863 //printf("TrackCanvas::draw_loop_points 5\n");
01864 
01865                 if(MWindowGUI::visible(x, x + 1, 0, get_w()))
01866                 {
01867                         set_color(GREEN);
01868                         draw_line(x, 0, x, get_h());
01869                 }
01870 //printf("TrackCanvas::draw_loop_points 6\n");
01871         }
01872 //printf("TrackCanvas::draw_loop_points 7\n");
01873 }
01874 
01875 void TrackCanvas::draw_brender_start()
01876 {
01877         if(mwindow->preferences->use_brender)
01878         {
01879                 int64_t x = Units::round(mwindow->edl->session->brender_start *
01880                         mwindow->edl->session->sample_rate /
01881                         mwindow->edl->local_session->zoom_sample - 
01882                         mwindow->edl->local_session->view_start);
01883 
01884                 if(MWindowGUI::visible(x, x + 1, 0, get_w()))
01885                 {
01886                         set_color(RED);
01887                         draw_line(x, 0, x, get_h());
01888                 }
01889         }
01890 }
01891 
01892 static int auto_colors[] = 
01893 {
01894         BLUE,
01895         RED,
01896         GREEN,
01897         BLUE,
01898         RED,
01899         GREEN,
01900         BLUE,
01901         WHITE,
01902         0,
01903         0,
01904         0,
01905         0
01906 };
01907 
01908 // The operations which correspond to each automation type
01909 static int auto_operations[] = 
01910 {
01911         DRAG_MUTE,
01912         DRAG_CAMERA_X,
01913         DRAG_CAMERA_Y,
01914         DRAG_CAMERA_Z,
01915         DRAG_PROJECTOR_X,
01916         DRAG_PROJECTOR_Y,
01917         DRAG_PROJECTOR_Z,
01918         DRAG_FADE,
01919         DRAG_PAN,
01920         DRAG_MODE,
01921         DRAG_MASK,
01922         DRAG_NUDGE
01923 };
01924 
01925 // The buttonpress operations, so nothing changes unless the mouse moves
01926 // a certain amount.  This allows the keyframe to be used to position the
01927 // insertion point without moving itself.
01928 static int pre_auto_operations[] =
01929 {
01930         DRAG_MUTE,
01931         DRAG_CAMERA_X,
01932         DRAG_CAMERA_Y,
01933         DRAG_CAMERA_Z,
01934         DRAG_PROJECTOR_X,
01935         DRAG_PROJECTOR_Y,
01936         DRAG_PROJECTOR_Z,
01937         DRAG_FADE,
01938         DRAG_PAN_PRE,
01939         DRAG_MODE_PRE,
01940         DRAG_MASK_PRE,
01941         DRAG_NUDGE
01942 };
01943 
01944 
01945 int TrackCanvas::do_keyframes(int cursor_x, 
01946         int cursor_y, 
01947         int draw, 
01948         int buttonpress, 
01949         int &new_cursor,
01950         int &update_cursor,
01951         int &rerender)
01952 {
01953 // Note: button 3 (right mouse button) is not eaten to allow
01954 // track context menu to appear
01955         int current_tool = 0;
01956         int result = 0;
01957         EDLSession *session = mwindow->edl->session;
01958 
01959 
01960 /*      if(buttonpress == 3)
01961         {
01962                 update_cursor = 1;
01963                 return 0;
01964         }
01965 
01966 */
01967 
01968         BC_Pixmap *auto_pixmaps[] = 
01969         {
01970                 0,
01971                 0,
01972                 0,
01973                 0,
01974                 0,
01975                 0,
01976                 0,
01977                 0,
01978                 pankeyframe_pixmap,
01979                 modekeyframe_pixmap,
01980                 maskkeyframe_pixmap,
01981                 0,
01982         };
01983 
01984 
01985 
01986         for(Track *track = mwindow->edl->tracks->first;
01987                 track && !result;
01988                 track = track->next)
01989         {
01990                 Auto *auto_keyframe;
01991                 Automation *automation = track->automation;
01992 
01993 
01994 // Handle float autos
01995                 for(int i = 0; i < AUTOMATION_TOTAL && !result; i++)
01996                 {
01997 // Event not trapped and automation visible
01998                         Autos *autos = automation->autos[i];
01999                         if(!result && session->auto_conf->autos[i] && autos)
02000                         {
02001                                 switch(i)
02002                                 {
02003                                         case AUTOMATION_PAN:
02004                                         case AUTOMATION_MODE:
02005                                         case AUTOMATION_MASK:
02006                                                 result = do_autos(track, 
02007                                                         automation->autos[i],
02008                                                         cursor_x, 
02009                                                         cursor_y, 
02010                                                         draw, 
02011                                                         buttonpress,
02012                                                         auto_pixmaps[i],
02013                                                         auto_keyframe);
02014                                                 break;
02015 
02016                                         default:
02017                                                 switch(autos->get_type())
02018                                                 {
02019                                                         case AUTOMATION_TYPE_FLOAT:
02020                                                                 result = do_float_autos(track, 
02021                                                                         autos,
02022                                                                         cursor_x, 
02023                                                                         cursor_y, 
02024                                                                         draw, 
02025                                                                         buttonpress, 
02026                                                                         auto_colors[i],
02027                                                                         auto_keyframe);
02028                                                                 break;
02029 
02030                                                         case AUTOMATION_TYPE_INT:
02031                                                                 result = do_toggle_autos(track, 
02032                                                                         autos,
02033                                                                         cursor_x, 
02034                                                                         cursor_y, 
02035                                                                         draw, 
02036                                                                         buttonpress,
02037                                                                         auto_colors[i],
02038                                                                         auto_keyframe);
02039                                                                 break;
02040                                                 }
02041                                                 break;
02042                                 }
02043                         
02044 
02045 
02046                                 if(result)
02047                                 {
02048                                         if(mwindow->session->current_operation == auto_operations[i])
02049                                                 rerender = 1;
02050                                         if(buttonpress)
02051                                         {
02052                                                 if (buttonpress != 3)
02053                                                 {
02054                                                         if(i == AUTOMATION_FADE) 
02055                                                                 synchronize_autos(0, 
02056                                                                         track, 
02057                                                                         (FloatAuto*)mwindow->session->drag_auto, 
02058                                                                         1);
02059                                                         mwindow->session->current_operation = pre_auto_operations[i];
02060                                                         update_drag_caption();
02061                                                 } else
02062                                                 if (buttonpress == 3) 
02063                                                 {
02064                                                         gui->keyframe_menu->update(automation, autos, auto_keyframe);
02065                                                         gui->keyframe_menu->activate_menu();
02066                                                         rerender = 1; // the position changes
02067 
02068                                                 }
02069                                         }
02070                                 }
02071                         }
02072                 }
02073 
02074 
02075 
02076 
02077                 if(!result && 
02078                         session->auto_conf->plugins &&
02079                         mwindow->edl->session->show_assets)
02080                 {
02081                         Plugin *plugin;
02082                         KeyFrame *keyframe;
02083                         result = do_plugin_autos(track,
02084                                 cursor_x, 
02085                                 cursor_y, 
02086                                 draw, 
02087                                 buttonpress,
02088                                 plugin,
02089                                 keyframe);
02090                         if(result && mwindow->session->current_operation == DRAG_PLUGINKEY)
02091                         {
02092                                 rerender = 1;
02093                         }
02094                         if(result && (buttonpress == 1))
02095                         {
02096                                 mwindow->session->current_operation = DRAG_PLUGINKEY_PRE;
02097                                 update_drag_caption();
02098                                 rerender = 1;
02099                         } else
02100                         if (result && (buttonpress == 3))
02101                         {
02102                                 gui->keyframe_menu->update(plugin, keyframe);
02103                                 gui->keyframe_menu->activate_menu();
02104                                 rerender = 1; // the position changes
02105                         }
02106                 }
02107         }
02108 
02109 // Final pass to trap event
02110         for(int i = 0; i < AUTOMATION_TOTAL; i++)
02111         {
02112                 if(mwindow->session->current_operation == pre_auto_operations[i] ||
02113                         mwindow->session->current_operation == auto_operations[i])
02114                         result = 1;
02115         }
02116 
02117         if(mwindow->session->current_operation == DRAG_PLUGINKEY ||
02118                 mwindow->session->current_operation == DRAG_PLUGINKEY_PRE)
02119         {
02120                 result = 1;
02121         }
02122 
02123         update_cursor = 1;
02124         if(result)
02125         {
02126                 new_cursor = UPRIGHT_ARROW_CURSOR;
02127         }
02128 
02129         return result;
02130 }
02131 
02132 void TrackCanvas::draw_auto(Auto *current, 
02133         int x, 
02134         int y, 
02135         int center_pixel, 
02136         int zoom_track,
02137         int color)
02138 {
02139         int x1, y1, x2, y2;
02140         char string[BCTEXTLEN];
02141 
02142         x1 = x - HANDLE_W / 2;
02143         x2 = x + HANDLE_W / 2;
02144         y1 = center_pixel + y - HANDLE_W / 2;
02145         y2 = center_pixel + y + HANDLE_W / 2;
02146 
02147         if(y1 < center_pixel + -zoom_track / 2) y1 = center_pixel + -zoom_track / 2;
02148         if(y2 > center_pixel + zoom_track / 2) y2 = center_pixel + zoom_track / 2;
02149 
02150         set_color(BLACK);
02151         draw_box(x1 + 1, y1 + 1, x2 - x1, y2 - y1);
02152         set_color(color);
02153         draw_box(x1, y1, x2 - x1, y2 - y1);
02154 }
02155 
02156 void TrackCanvas::draw_floatauto(Auto *current, 
02157         int x, 
02158         int y, 
02159         int in_x, 
02160         int in_y, 
02161         int out_x, 
02162         int out_y, 
02163         int center_pixel, 
02164         int zoom_track,
02165         int color)
02166 {
02167         int x1, y1, x2, y2;
02168         int in_x1, in_y1, in_x2, in_y2;
02169         int out_x1, out_y1, out_x2, out_y2;
02170         char string[BCTEXTLEN];
02171 
02172 // Center
02173         x1 = x - HANDLE_W / 2;
02174         x2 = x + HANDLE_W / 2;
02175         y1 = center_pixel + y - HANDLE_W / 2;
02176         y2 = center_pixel + y + HANDLE_W / 2;
02177 
02178         CLAMP(y1, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
02179         CLAMP(y2, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
02180 
02181         if(y2 - 1 > y1)
02182         {
02183                 set_color(BLACK);
02184                 draw_box(x1 + 1, y1 + 1, x2 - x1, y2 - y1);
02185                 set_color(color);
02186                 draw_box(x1, y1, x2 - x1, y2 - y1);
02187         }
02188 
02189 // In handle
02190         in_x1 = in_x - HANDLE_W / 2;
02191         in_x2 = in_x + HANDLE_W / 2;
02192         in_y1 = center_pixel + in_y - HANDLE_W / 2;
02193         in_y2 = center_pixel + in_y + HANDLE_W / 2;
02194 
02195         CLAMP(in_y1, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
02196         CLAMP(in_y2, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
02197         CLAMP(in_y, -zoom_track / 2, zoom_track / 2);
02198 
02199         if(in_y2 > in_y1)
02200         {
02201                 set_color(BLACK);
02202                 draw_line(x + 1, center_pixel + y + 1, in_x + 1, center_pixel + in_y + 1);
02203                 draw_box(in_x1 + 1, in_y1 + 1, in_x2 - in_x1, in_y2 - in_y1);
02204                 set_color(color);
02205                 draw_line(x, center_pixel + y, in_x, center_pixel + in_y);
02206                 draw_box(in_x1, in_y1, in_x2 - in_x1, in_y2 - in_y1);
02207         }
02208 
02209 
02210 // Out handle
02211         out_x1 = out_x - HANDLE_W / 2;
02212         out_x2 = out_x + HANDLE_W / 2;
02213         out_y1 = center_pixel + out_y - HANDLE_W / 2;
02214         out_y2 = center_pixel + out_y + HANDLE_W / 2;
02215 
02216         CLAMP(out_y1, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
02217         CLAMP(out_y2, center_pixel + -zoom_track / 2, center_pixel + zoom_track / 2);
02218         CLAMP(out_y, -zoom_track / 2, zoom_track / 2);
02219 
02220         if(out_y2 > out_y1)
02221         {
02222                 set_color(BLACK);
02223                 draw_line(x + 1, center_pixel + y + 1, out_x + 1, center_pixel + out_y + 1);
02224                 draw_box(out_x1 + 1, out_y1 + 1, out_x2 - out_x1, out_y2 - out_y1);
02225                 set_color(color);
02226                 draw_line(x, center_pixel + y, out_x, center_pixel + out_y);
02227                 draw_box(out_x1, out_y1, out_x2 - out_x1, out_y2 - out_y1);
02228         }
02229 }
02230 
02231 int TrackCanvas::test_auto(Auto *current, 
02232         int x, 
02233         int y, 
02234         int center_pixel, 
02235         int zoom_track, 
02236         int cursor_x, 
02237         int cursor_y, 
02238         int buttonpress)
02239 {
02240         int x1, y1, x2, y2;
02241         char string[BCTEXTLEN];
02242         int result = 0;
02243 
02244         x1 = x - HANDLE_W / 2;
02245         x2 = x + HANDLE_W / 2;
02246         y1 = center_pixel + y - HANDLE_W / 2;
02247         y2 = center_pixel + y + HANDLE_W / 2;
02248 
02249         if(y1 < center_pixel + -zoom_track / 2) y1 = center_pixel + -zoom_track / 2;
02250         if(y2 > center_pixel + zoom_track / 2) y2 = center_pixel + zoom_track / 2;
02251 
02252         if(cursor_x >= x1 && cursor_x < x2 && cursor_y >= y1 && cursor_y < y2)
02253         {
02254                 if(buttonpress)
02255                 {
02256                         mwindow->session->drag_auto = current;
02257                         mwindow->session->drag_start_percentage = current->value_to_percentage();
02258                         mwindow->session->drag_start_position = current->position;
02259                         mwindow->session->drag_origin_x = cursor_x;
02260                         mwindow->session->drag_origin_y = cursor_y;
02261                 }
02262                 result = 1;
02263         }
02264 
02265         return result;
02266 }
02267 
02268 int TrackCanvas::test_floatauto(Auto *current, 
02269         int x, 
02270         int y, 
02271         int in_x,
02272         int in_y,
02273         int out_x,
02274         int out_y,
02275         int center_pixel, 
02276         int zoom_track, 
02277         int cursor_x, 
02278         int cursor_y, 
02279         int buttonpress)
02280 {
02281         int x1, y1, x2, y2;
02282         int in_x1, in_y1, in_x2, in_y2;
02283         int out_x1, out_y1, out_x2, out_y2;
02284         char string[BCTEXTLEN];
02285         int result = 0;
02286 
02287         x1 = x - HANDLE_W / 2;
02288         x2 = x + HANDLE_W / 2;
02289         y1 = center_pixel + y - HANDLE_W / 2;
02290         y2 = center_pixel + y + HANDLE_W / 2;
02291 
02292         if(y1 < center_pixel + -zoom_track / 2) y1 = center_pixel + -zoom_track / 2;
02293         if(y2 > center_pixel + zoom_track / 2) y2 = center_pixel + zoom_track / 2;
02294 
02295         in_x1 = in_x - HANDLE_W / 2;
02296         in_x2 = in_x + HANDLE_W / 2;
02297         in_y1 = center_pixel + in_y - HANDLE_W / 2;
02298         in_y2 = center_pixel + in_y + HANDLE_W / 2;
02299 
02300         if(in_y1 < center_pixel + -zoom_track / 2) in_y1 = center_pixel + -zoom_track / 2;
02301         if(in_y2 > center_pixel + zoom_track / 2) in_y2 = center_pixel + zoom_track / 2;
02302 
02303         out_x1 = out_x - HANDLE_W / 2;
02304         out_x2 = out_x + HANDLE_W / 2;
02305         out_y1 = center_pixel + out_y - HANDLE_W / 2;
02306         out_y2 = center_pixel + out_y + HANDLE_W / 2;
02307 
02308         if(out_y1 < center_pixel + -zoom_track / 2) out_y1 = center_pixel + -zoom_track / 2;
02309         if(out_y2 > center_pixel + zoom_track / 2) out_y2 = center_pixel + zoom_track / 2;
02310 
02311 
02312 
02313 //printf("TrackCanvas::test_floatauto %d %d %d %d %d %d\n", cursor_x, cursor_y, x1, x2, y1, y2);
02314 // Test value
02315         if(!ctrl_down() &&
02316                 cursor_x >= x1 && 
02317                 cursor_x < x2 && 
02318                 cursor_y >= y1 && 
02319                 cursor_y < y2)
02320         {
02321                 if(buttonpress && (buttonpress != 3))
02322                 {
02323                         mwindow->session->drag_auto = current;
02324                         mwindow->session->drag_start_percentage = current->value_to_percentage();
02325                         mwindow->session->drag_start_position = current->position;
02326                         mwindow->session->drag_origin_x = cursor_x;
02327                         mwindow->session->drag_origin_y = cursor_y;
02328                         mwindow->session->drag_handle = 0;
02329                 }
02330                 result = 1;
02331         }
02332         else
02333 // Test in control
02334         if(ctrl_down() &&
02335                 cursor_x >= in_x1 && 
02336                 cursor_x < in_x2 && 
02337                 cursor_y >= in_y1 && 
02338                 cursor_y < in_y2 &&
02339                 current->position > 0)
02340         {
02341                 if(buttonpress && (buttonpress != 3))
02342                 {
02343                         mwindow->session->drag_auto = current;
02344                         mwindow->session->drag_start_percentage = 
02345                                 current->invalue_to_percentage();
02346                         mwindow->session->drag_start_position = 
02347                                 ((FloatAuto*)current)->control_in_position;
02348                         mwindow->session->drag_origin_x = cursor_x;
02349                         mwindow->session->drag_origin_y = cursor_y;
02350                         mwindow->session->drag_handle = 1;
02351                 }
02352                 result = 1;
02353         }
02354         else
02355 // Test out control
02356         if(ctrl_down() &&
02357                 cursor_x >= out_x1 && 
02358                 cursor_x < out_x2 && 
02359                 cursor_y >= out_y1 && 
02360                 cursor_y < out_y2)
02361         {
02362                 if(buttonpress && (buttonpress != 3))
02363                 {
02364                         mwindow->session->drag_auto = current;
02365                         mwindow->session->drag_start_percentage = 
02366                                 current->outvalue_to_percentage();
02367                         mwindow->session->drag_start_position = 
02368                                 ((FloatAuto*)current)->control_out_position;
02369                         mwindow->session->drag_origin_x = cursor_x;
02370                         mwindow->session->drag_origin_y = cursor_y;
02371                         mwindow->session->drag_handle = 2;
02372                 }
02373                 result = 1;
02374         }
02375 
02376 // if(buttonpress) 
02377 // 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", 
02378 // mwindow->session->drag_handle,
02379 // ctrl_down(),
02380 // cursor_x,
02381 // cursor_y,
02382 // x1, x2, y1, y2);
02383 
02384         return result;
02385 }
02386 
02387 void TrackCanvas::draw_floatline(int center_pixel, 
02388         FloatAuto *previous,
02389         FloatAuto *next,
02390         FloatAutos *autos,
02391         double unit_start,
02392         double zoom_units,
02393         double yscale,
02394         int x1,
02395         int y1,
02396         int x2,
02397         int y2,
02398         int color)
02399 {
02400 // Solve bezier equation for either every pixel or a certain large number of
02401 // points.
02402 
02403 
02404 
02405 // Not using slope intercept
02406         x1 = MAX(0, x1);
02407 
02408 
02409 
02410 
02411         int prev_y;
02412 // Call by reference fails for some reason here
02413         FloatAuto *previous1 = previous, *next1 = next;
02414         float automation_min = mwindow->edl->local_session->automation_min;
02415         float automation_max = mwindow->edl->local_session->automation_max;
02416         float automation_range = automation_max - automation_min;
02417 
02418         for(int x = x1; x < x2; x++)
02419         {
02420                 int64_t position = (int64_t)(unit_start + x * zoom_units);
02421                 float value = autos->get_value(position, PLAY_FORWARD, previous1, next1);
02422 
02423                 int y = center_pixel + 
02424                         (int)(((value - automation_min) / automation_range - 0.5) * -yscale);
02425 
02426                 if(x > x1 && 
02427                         y >= center_pixel - yscale / 2 && 
02428                         y < center_pixel + yscale / 2 - 1)
02429                 {
02430                         set_color(BLACK);
02431                         draw_line(x - 1, prev_y + 1, x, y + 1);
02432                         set_color(color);
02433                         draw_line(x - 1, prev_y, x, y);
02434                 }
02435                 prev_y = y;
02436         }
02437 
02438 
02439 }
02440 
02441 void TrackCanvas::synchronize_autos(float change, 
02442         Track *skip, 
02443         FloatAuto *fauto, 
02444         int fill_gangs)
02445 {
02446 // fill mwindow->session->drag_auto_gang
02447         if (fill_gangs == 1 && skip->gang)
02448         {
02449                 for(Track *current = mwindow->edl->tracks->first;
02450                         current;
02451                         current = NEXT)
02452                 {
02453                         if(current->data_type == skip->data_type &&
02454                                 current->gang && 
02455                                 current->record && 
02456                                 current != skip)
02457                         {
02458                                 FloatAutos *fade_autos = (FloatAutos*)current->automation->autos[AUTOMATION_FADE];
02459                                 double position = skip->from_units(fauto->position);
02460                                 FloatAuto *previous = 0, *next = 0;
02461 
02462                                 float init_value = fade_autos->get_value(fauto->position, PLAY_FORWARD, previous, next);
02463                                 FloatAuto *keyframe;
02464                                 keyframe = (FloatAuto*)fade_autos->get_auto_at_position(position);
02465                                 
02466                                 if (!keyframe)
02467                                 {
02468 // create keyframe at exactly this point in time
02469                                         keyframe = (FloatAuto*)fade_autos->insert_auto(fauto->position);
02470                                         keyframe->value = init_value;
02471                                 } 
02472                                 else
02473                                 { 
02474 // keyframe exists, just change it
02475                                         keyframe->value += change;              
02476                                 } 
02477                                 
02478                                 keyframe->position = fauto->position;
02479                                 keyframe->control_out_position = fauto->control_out_position;
02480                                 keyframe->control_in_position = fauto->control_in_position;
02481                                 keyframe->control_out_value = fauto->control_out_value;
02482                                 keyframe->control_in_value = fauto->control_in_value;
02483 
02484                                 mwindow->session->drag_auto_gang->append((Auto *)keyframe);
02485                         }
02486                 }
02487         } else 
02488 // move the gangs
02489         if (fill_gangs == 0)      
02490         {
02491 // Move the gang!
02492                 for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++)
02493                 {
02494                         FloatAuto *keyframe = (FloatAuto *)mwindow->session->drag_auto_gang->values[i];
02495                         
02496                         keyframe->value += change;
02497                         keyframe->position = fauto->position;
02498                         if(skip->data_type == TRACK_AUDIO)
02499                                 CLAMP(keyframe->value, INFINITYGAIN, MAX_AUDIO_FADE);
02500                         else
02501                                 CLAMP(keyframe->value, 0, MAX_VIDEO_FADE);
02502                         keyframe->control_out_position = fauto->control_out_position;
02503                         keyframe->control_in_position = fauto->control_in_position;
02504                         keyframe->control_out_value = fauto->control_out_value;
02505                         keyframe->control_in_value = fauto->control_in_value;
02506                 } 
02507 
02508         } 
02509         else
02510 // remove the gangs
02511         if (fill_gangs == -1)      
02512         {
02513                 for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++)
02514                 {
02515                         FloatAuto *keyframe = (FloatAuto *)mwindow->session->drag_auto_gang->values[i];
02516                         keyframe->autos->remove_nonsequential(
02517                                         keyframe);
02518                 } 
02519                 mwindow->session->drag_auto_gang->remove_all();
02520         }
02521 }
02522 
02523 
02524 int TrackCanvas::test_floatline(int center_pixel, 
02525                 FloatAutos *autos,
02526                 double unit_start,
02527                 double zoom_units,
02528                 double yscale,
02529                 int x1,
02530                 int x2,
02531                 int cursor_x, 
02532                 int cursor_y, 
02533                 int buttonpress)
02534 {
02535         int result = 0;
02536 
02537 
02538         float automation_min = mwindow->edl->local_session->automation_min;
02539         float automation_max = mwindow->edl->local_session->automation_max;
02540         float automation_range = automation_max - automation_min;
02541         int64_t position = (int64_t)(unit_start + cursor_x * zoom_units);
02542 // Call by reference fails for some reason here
02543         FloatAuto *previous = 0, *next = 0;
02544         float value = autos->get_value(position, PLAY_FORWARD, previous, next);
02545         int y = center_pixel + 
02546                 (int)(((value - automation_min) / automation_range - 0.5) * -yscale);
02547 
02548         if(cursor_x >= x1 && 
02549                 cursor_x < x2 &&
02550                 cursor_y >= y - HANDLE_W / 2 && 
02551                 cursor_y < y + HANDLE_W / 2 &&
02552                 !ctrl_down())
02553         {
02554                 result = 1;
02555 
02556 
02557                 if(buttonpress)
02558                 {
02559 
02560 
02561                         Auto *current;
02562                         current = mwindow->session->drag_auto = autos->insert_auto(position);
02563                         ((FloatAuto*)current)->value = value;
02564                         mwindow->session->drag_start_percentage = current->value_to_percentage();
02565                         mwindow->session->drag_start_position = current->position;
02566                         mwindow->session->drag_origin_x = cursor_x;
02567                         mwindow->session->drag_origin_y = cursor_y;
02568                         mwindow->session->drag_handle = 0;
02569 
02570                 }
02571         }
02572 
02573 
02574         return result;
02575 }
02576 
02577 void TrackCanvas::draw_toggleline(int center_pixel, 
02578         int x1,
02579         int y1,
02580         int x2,
02581         int y2,
02582         int color)
02583 {
02584         set_color(BLACK);
02585         draw_line(x1, center_pixel + y1 + 1, x2, center_pixel + y1 + 1);
02586         set_color(color);
02587         draw_line(x1, center_pixel + y1, x2, center_pixel + y1);
02588 
02589         if(y2 != y1)
02590         {
02591                 set_color(BLACK);
02592                 draw_line(x2 + 1, center_pixel + y1, x2 + 1, center_pixel + y2);
02593                 set_color(color);
02594                 draw_line(x2, center_pixel + y1, x2, center_pixel + y2);
02595         }
02596 }
02597 
02598 int TrackCanvas::test_toggleline(Autos *autos,
02599         int center_pixel, 
02600         int x1,
02601         int y1,
02602         int x2,
02603         int y2, 
02604         int cursor_x, 
02605         int cursor_y, 
02606         int buttonpress)
02607 {
02608         int result = 0;
02609         if(cursor_x >= x1 && cursor_x < x2)
02610         {
02611                 int miny = center_pixel + y1 - HANDLE_W / 2;
02612                 int maxy = center_pixel + y1 + HANDLE_W / 2;
02613                 if(cursor_y >= miny && cursor_y < maxy) 
02614                 {
02615                         result = 1;
02616 
02617                         if(buttonpress)
02618                         {
02619 
02620 
02621                                 Auto *current;
02622                                 double position = (double)(cursor_x +
02623                                                 mwindow->edl->local_session->view_start) * 
02624                                         mwindow->edl->local_session->zoom_sample / 
02625                                         mwindow->edl->session->sample_rate;
02626                                 int64_t unit_position = autos->track->to_units(position, 0);
02627                                 int new_value = (int)((IntAutos*)autos)->get_automation_constant(unit_position, unit_position);
02628 
02629                                 current = mwindow->session->drag_auto = autos->insert_auto(unit_position);
02630                                 ((IntAuto*)current)->value = new_value;
02631                                 mwindow->session->drag_start_percentage = current->value_to_percentage();
02632                                 mwindow->session->drag_start_position = current->position;
02633                                 mwindow->session->drag_origin_x = cursor_x;
02634                                 mwindow->session->drag_origin_y = cursor_y;
02635 
02636                         }
02637                 }
02638         };
02639         return result;
02640 }
02641 
02642 void TrackCanvas::calculate_viewport(Track *track, 
02643         double &view_start,   // Seconds
02644         double &unit_start,
02645         double &view_end,     // Seconds
02646         double &unit_end,
02647         double &yscale,
02648         int &center_pixel,
02649         double &zoom_sample,
02650         double &zoom_units)
02651 {
02652         view_start = (double)mwindow->edl->local_session->view_start * 
02653                 mwindow->edl->local_session->zoom_sample /
02654                 mwindow->edl->session->sample_rate;
02655         unit_start = track->to_doubleunits(view_start);
02656         view_end = (double)(mwindow->edl->local_session->view_start + 
02657                 get_w()) * 
02658                 mwindow->edl->local_session->zoom_sample / 
02659                 mwindow->edl->session->sample_rate;
02660         unit_end = track->to_doubleunits(view_end);
02661         yscale = mwindow->edl->local_session->zoom_track;
02662         center_pixel = (int)(track->y_pixel + yscale / 2) + 
02663                 (mwindow->edl->session->show_titles ? 
02664                         mwindow->theme->title_bg_data->get_h() : 
02665                         0);
02666         zoom_sample = mwindow->edl->local_session->zoom_sample;
02667 
02668         zoom_units = track->to_doubleunits(zoom_sample / mwindow->edl->session->sample_rate);
02669 }
02670 
02671 float TrackCanvas::percentage_to_value(float percentage, 
02672         int is_toggle,
02673         Auto *reference)
02674 {
02675         float result;
02676         if(is_toggle)
02677         {
02678                 if(percentage > 0.5) 
02679                         result = 1;
02680                 else
02681                         result = 0;
02682         }
02683         else
02684         {
02685                 float automation_min = mwindow->edl->local_session->automation_min;
02686                 float automation_max = mwindow->edl->local_session->automation_max;
02687                 float automation_range = automation_max - automation_min;
02688 
02689                 result = percentage * automation_range + automation_min;
02690                 if(reference)
02691                 {
02692                         FloatAuto *ptr = (FloatAuto*)reference;
02693                         result -= ptr->value;
02694                 }
02695         }
02696         return result;
02697 }
02698 
02699 
02700 void TrackCanvas::calculate_auto_position(double *x, 
02701         double *y,
02702         double *in_x,
02703         double *in_y,
02704         double *out_x,
02705         double *out_y,
02706         Auto *current,
02707         double unit_start,
02708         double zoom_units,
02709         double yscale)
02710 {
02711         float automation_min = mwindow->edl->local_session->automation_min;
02712         float automation_max = mwindow->edl->local_session->automation_max;
02713         float automation_range = automation_max - automation_min;
02714         FloatAuto *ptr = (FloatAuto*)current;
02715         *x = (double)(ptr->position - unit_start) / zoom_units;
02716         *y = ((ptr->value - automation_min) /
02717                 automation_range - 0.5) * 
02718                 -yscale;
02719         if(in_x)
02720         {
02721                 *in_x = (double)(ptr->position + 
02722                         ptr->control_in_position - 
02723                         unit_start) /
02724                         zoom_units;
02725         }
02726         if(in_y)
02727         {
02728                 *in_y = (((ptr->value + ptr->control_in_value) -
02729                         automation_min) /
02730                         automation_range - 0.5) *
02731                         -yscale;
02732         }
02733         if(out_x)
02734         {
02735                 *out_x = (double)(ptr->position + 
02736                         ptr->control_out_position - 
02737                         unit_start) /
02738                         zoom_units;
02739         }
02740         if(out_y)
02741         {
02742                 *out_y = (((ptr->value + ptr->control_out_value) -
02743                         automation_min) /
02744                         automation_range - 0.5) *
02745                         -yscale;
02746         }
02747 }
02748 
02749 
02750 
02751 
02752 
02753 int TrackCanvas::do_float_autos(Track *track, 
02754                 Autos *autos, 
02755                 int cursor_x, 
02756                 int cursor_y, 
02757                 int draw, 
02758                 int buttonpress,
02759                 int color,
02760                 Auto * &auto_instance)
02761 {
02762         int result = 0;
02763 
02764         double view_start;
02765         double unit_start;
02766         double view_end;
02767         double unit_end;
02768         double yscale;
02769         int center_pixel;
02770         double zoom_sample;
02771         double zoom_units;
02772         double ax, ay, ax2, ay2;
02773         double in_x2, in_y2, out_x2, out_y2;
02774         int draw_auto;
02775         double slope;
02776         int skip = 0;
02777         
02778         auto_instance = 0;
02779 
02780         calculate_viewport(track, 
02781                 view_start,
02782                 unit_start,
02783                 view_end,
02784                 unit_end,
02785                 yscale,
02786                 center_pixel,
02787                 zoom_sample,
02788                 zoom_units);
02789 
02790 
02791 
02792 // Get first auto before start
02793         Auto *current = 0;
02794         Auto *previous = 0;
02795         for(current = autos->last; 
02796                 current && current->position >= unit_start; 
02797                 current = PREVIOUS)
02798                 ;
02799 
02800         if(current)
02801         {
02802                 calculate_auto_position(&ax, 
02803                         &ay,
02804                         0,
02805                         0,
02806                         0,
02807                         0,
02808                         current,
02809                         unit_start,
02810                         zoom_units,
02811                         yscale);
02812                 current = NEXT;
02813         }
02814         else
02815         {
02816                 current = autos->first ? autos->first : autos->default_auto;
02817                 if(current)
02818                 {
02819                         calculate_auto_position(&ax, 
02820                                 &ay,
02821                                 0,
02822                                 0,
02823                                 0,
02824                                 0,
02825                                 current,
02826                                 unit_start,
02827                                 zoom_units,
02828                                 yscale);
02829                         ax = 0;
02830                 }
02831                 else
02832                 {
02833                         ax = 0;
02834                         ay = 0;
02835                 }
02836         }
02837 
02838 
02839 
02840 
02841 
02842         do
02843         {
02844                 skip = 0;
02845                 draw_auto = 1;
02846 
02847                 if(current)
02848                 {
02849                         calculate_auto_position(&ax2, 
02850                                 &ay2,
02851                                 &in_x2,
02852                                 &in_y2,
02853                                 &out_x2,
02854                                 &out_y2,
02855                                 current,
02856                                 unit_start,
02857                                 zoom_units,
02858                                 yscale);
02859                 }
02860                 else
02861                 {
02862                         ax2 = get_w();
02863                         ay2 = ay;
02864                         skip = 1;
02865                 }
02866 
02867                 slope = (ay2 - ay) / (ax2 - ax);
02868 
02869                 if(ax2 > get_w())
02870                 {
02871                         draw_auto = 0;
02872                         ax2 = get_w();
02873                         ay2 = ay + slope * (get_w() - ax);
02874                 }
02875                 
02876                 if(ax < 0)
02877                 {
02878                         ay = ay + slope * (0 - ax);
02879                         ax = 0;
02880                 }
02881 
02882 
02883 
02884 
02885 
02886 
02887 
02888 
02889 
02890 
02891 
02892 
02893 
02894 
02895 // Draw handle
02896                 if(current && !result)
02897                 {
02898                         if(current != autos->default_auto)
02899                         {
02900                                 if(!draw)
02901                                 {
02902                                         if(track->record)
02903                                                 result = test_floatauto(current, 
02904                                                         (int)ax2, 
02905                                                         (int)ay2, 
02906                                                         (int)in_x2,
02907                                                         (int)in_y2,
02908                                                         (int)out_x2,
02909                                                         (int)out_y2,
02910                                                         (int)center_pixel, 
02911                                                         (int)yscale, 
02912                                                         cursor_x, 
02913                                                         cursor_y, 
02914                                                         buttonpress);
02915                                         if (result) 
02916                                                 auto_instance = current;
02917                                 }
02918                                 else
02919                                 if(draw_auto)
02920                                         draw_floatauto(current, 
02921                                                 (int)ax2, 
02922                                                 (int)ay2, 
02923                                                 (int)in_x2,
02924                                                 (int)in_y2,
02925                                                 (int)out_x2,
02926                                                 (int)out_y2,
02927                                                 (int)center_pixel, 
02928                                                 (int)yscale,
02929                                                 color);
02930                         }
02931                 }
02932 
02933 
02934 
02935 
02936 
02937 // Draw joining line
02938                 if(!draw)
02939                 {
02940                         if(!result)
02941                         {
02942                                 if(track->record && buttonpress != 3)
02943                                 {
02944                                         result = test_floatline(center_pixel, 
02945                                                 (FloatAutos*)autos,
02946                                                 unit_start,
02947                                                 zoom_units,
02948                                                 yscale,
02949                                                 (int)ax,
02950 // Exclude auto coverage from the end of the line.  The auto overlaps
02951                                                 (int)ax2 - HANDLE_W / 2,
02952                                                 cursor_x, 
02953                                                 cursor_y, 
02954                                                 buttonpress);
02955                                 }
02956                         }
02957                 }
02958                 else
02959                         draw_floatline(center_pixel,
02960                                 (FloatAuto*)previous,
02961                                 (FloatAuto*)current,
02962                                 (FloatAutos*)autos,
02963                                 unit_start,
02964                                 zoom_units,
02965                                 yscale,
02966                                 (int)ax, 
02967                                 (int)ay, 
02968                                 (int)ax2, 
02969                                 (int)ay2,
02970                                 color);
02971 
02972 
02973 
02974 
02975 
02976 
02977 
02978                 if(current)
02979                 {
02980                         previous = current;
02981                         current = NEXT;
02982                 }
02983 
02984 
02985 
02986                 ax = ax2;
02987                 ay = ay2;
02988         }while(current && 
02989                 current->position <= unit_end && 
02990                 !result);
02991 
02992 //printf("TrackCanvas::do_float_autos 100\n");
02993 
02994 
02995 
02996 
02997 
02998 
02999 
03000 
03001         if(ax < get_w() && !result)
03002         {
03003                 ax2 = get_w();
03004                 ay2 = ay;
03005                 if(!draw)
03006                 {
03007                         if(track->record && buttonpress != 3)
03008                         {
03009                                 result = test_floatline(center_pixel, 
03010                                         (FloatAutos*)autos,
03011                                         unit_start,
03012                                         zoom_units,
03013                                         yscale,
03014                                         (int)ax,
03015                                         (int)ax2,
03016                                         cursor_x, 
03017                                         cursor_y, 
03018                                         buttonpress);
03019                         }
03020                 }
03021                 else
03022                         draw_floatline(center_pixel, 
03023                                 (FloatAuto*)previous,
03024                                 (FloatAuto*)current,
03025                                 (FloatAutos*)autos,
03026                                 unit_start,
03027                                 zoom_units,
03028                                 yscale,
03029                                 (int)ax, 
03030                                 (int)ay, 
03031                                 (int)ax2, 
03032                                 (int)ay2,
03033                                 color);
03034         }
03035 
03036 
03037 
03038 
03039 
03040 
03041 
03042 
03043         return result;
03044 }
03045 
03046 
03047 int TrackCanvas::do_toggle_autos(Track *track, 
03048                 Autos *autos, 
03049                 int cursor_x, 
03050                 int cursor_y, 
03051                 int draw, 
03052                 int buttonpress,
03053                 int color,
03054                 Auto * &auto_instance)
03055 {
03056         int result = 0;
03057         double view_start;
03058         double unit_start;
03059         double view_end;
03060         double unit_end;
03061         double yscale;
03062         int center_pixel;
03063         double zoom_sample;
03064         double zoom_units;
03065         double ax, ay, ax2, ay2;
03066         
03067         auto_instance = 0;
03068 
03069         calculate_viewport(track, 
03070                 view_start,
03071                 unit_start,
03072                 view_end,
03073                 unit_end,
03074                 yscale,
03075                 center_pixel,
03076                 zoom_sample,
03077                 zoom_units);
03078 
03079 
03080         double high = -yscale * 0.8 / 2;
03081         double low = yscale * 0.8 / 2;
03082 
03083 // Get first auto before start
03084         Auto *current;
03085         for(current = autos->last; current && current->position >= unit_start; current = PREVIOUS)
03086                 ;
03087 
03088         if(current)
03089         {
03090                 ax = 0;
03091                 ay = ((IntAuto*)current)->value > 0 ? high : low;
03092                 current = NEXT;
03093         }
03094         else
03095         {
03096                 current = autos->first ? autos->first : autos->default_auto;
03097                 if(current)
03098                 {
03099                         ax = 0;
03100                         ay = ((IntAuto*)current)->value > 0 ? high : low;
03101                 }
03102                 else
03103                 {
03104                         ax = 0;
03105                         ay = yscale;
03106                 }
03107         }
03108 
03109         do
03110         {
03111                 if(current)
03112                 {
03113                         ax2 = (double)(current->position - unit_start) / zoom_units;
03114                         ay2 = ((IntAuto*)current)->value > 0 ? high : low;
03115                 }
03116                 else
03117                 {
03118                         ax2 = get_w();
03119                         ay2 = ay;
03120                 }
03121 
03122                 if(ax2 > get_w()) ax2 = get_w();
03123 
03124             if(current && !result) 
03125                 {
03126                         if(current != autos->default_auto)
03127                         {
03128                                 if(!draw)
03129                                 {
03130                                         if(track->record)
03131                                         {
03132                                                 result = test_auto(current, 
03133                                                         (int)ax2, 
03134                                                         (int)ay2, 
03135                                                         (int)center_pixel, 
03136                                                         (int)yscale, 
03137                                                         cursor_x, 
03138                                                         cursor_y, 
03139                                                         buttonpress);
03140                                                 if (result)
03141                                                         auto_instance = current;
03142                                         }
03143                                 }
03144                                 else
03145                                         draw_auto(current, 
03146                                                 (int)ax2, 
03147                                                 (int)ay2, 
03148                                                 (int)center_pixel, 
03149                                                 (int)yscale,
03150                                                 color);
03151                         }
03152 
03153                         current = NEXT;
03154                 }
03155 
03156                 if(!draw)
03157                 {
03158                         if(!result)
03159                         {
03160                                 if(track->record && buttonpress != 3)
03161                                 {
03162                                         result = test_toggleline(autos, 
03163                                                 center_pixel, 
03164                                                 (int)ax, 
03165                                                 (int)ay, 
03166                                                 (int)ax2, 
03167                                                 (int)ay2,
03168                                                 cursor_x, 
03169                                                 cursor_y, 
03170                                                 buttonpress);
03171                                 }
03172                         }
03173                 }
03174                 else
03175                         draw_toggleline(center_pixel, 
03176                                 (int)ax, 
03177                                 (int)ay, 
03178                                 (int)ax2, 
03179                                 (int)ay2,
03180                                 color);
03181 
03182                 ax = ax2;
03183                 ay = ay2;
03184         }while(current && current->position <= unit_end && !result);
03185 
03186         if(ax < get_w() && !result)
03187         {
03188                 ax2 = get_w();
03189                 ay2 = ay;
03190                 if(!draw)
03191                 {
03192                         if(track->record && buttonpress != 3)
03193                         {
03194                                 result = test_toggleline(autos,
03195                                         center_pixel, 
03196                                         (int)ax, 
03197                                         (int)ay, 
03198                                         (int)ax2, 
03199                                         (int)ay2,
03200                                         cursor_x, 
03201                                         cursor_y, 
03202                                         buttonpress);
03203                         }
03204                 }
03205                 else
03206                         draw_toggleline(center_pixel, 
03207                                 (int)ax, 
03208                                 (int)ay, 
03209                                 (int)ax2, 
03210                                 (int)ay2,
03211                                 color);
03212         }
03213         return result;
03214 }
03215 
03216 int TrackCanvas::do_autos(Track *track, 
03217                 Autos *autos, 
03218                 int cursor_x, 
03219                 int cursor_y, 
03220                 int draw, 
03221                 int buttonpress,
03222                 BC_Pixmap *pixmap,
03223                 Auto * &auto_instance)
03224 {
03225         int result = 0;
03226 
03227         double view_start;
03228         double unit_start;
03229         double view_end;
03230         double unit_end;
03231         double yscale;
03232         int center_pixel;
03233         double zoom_sample;
03234         double zoom_units;
03235 
03236         calculate_viewport(track, 
03237                 view_start,
03238                 unit_start,
03239                 view_end,
03240                 unit_end,
03241                 yscale,
03242                 center_pixel,
03243                 zoom_sample,
03244                 zoom_units);
03245 
03246         Auto *current;
03247         auto_instance = 0;
03248 
03249         for(current = autos->first; current && !result; current = NEXT)
03250         {
03251                 if(current->position >= unit_start && current->position < unit_end)
03252                 {
03253                         int64_t x, y;
03254                         x = (int64_t)((double)(current->position - unit_start) / 
03255                                 zoom_units - (pixmap->get_w() / 2 + 0.5));
03256                         y = center_pixel - pixmap->get_h() / 2;
03257 
03258                         if(!draw)
03259                         {
03260                                 if(cursor_x >= x && cursor_y >= y &&
03261                                         cursor_x < x + pixmap->get_w() &&
03262                                         cursor_y < y + pixmap->get_h())
03263                                 {
03264                                         result = 1;
03265                                         auto_instance = current;
03266 
03267                                         if(buttonpress && (buttonpress != 3))
03268                                         {
03269                                                 mwindow->session->drag_auto = current;
03270                                                 mwindow->session->drag_start_position = current->position;
03271                                                 mwindow->session->drag_origin_x = cursor_x;
03272                                                 mwindow->session->drag_origin_y = cursor_y;
03273 
03274                                                 double position = autos->track->from_units(current->position);
03275                                                 double center = (mwindow->edl->local_session->get_selectionstart(1) +
03276                                                         mwindow->edl->local_session->get_selectionend(1)) / 
03277                                                         2;
03278 
03279                                                 if(!shift_down())
03280                                                 {
03281                                                         mwindow->edl->local_session->set_selectionstart(position);
03282                                                         mwindow->edl->local_session->set_selectionend(position);
03283                                                 }
03284                                                 else
03285                                                 if(position < center)
03286                                                 {
03287                                                         mwindow->edl->local_session->set_selectionstart(position);
03288                                                 }
03289                                                 else
03290                                                         mwindow->edl->local_session->set_selectionend(position);
03291                                         }
03292                                 }
03293                         }
03294                         else
03295                                 draw_pixmap(pixmap, x, y);
03296                 }
03297         }
03298         return result;
03299 }
03300 
03301 // so this means it is always >0 when keyframe is found 
03302 int TrackCanvas::do_plugin_autos(Track *track, 
03303                 int cursor_x, 
03304                 int cursor_y, 
03305                 int draw, 
03306                 int buttonpress,
03307                 Plugin* &keyframe_plugin,
03308                 KeyFrame* &keyframe_instance)
03309 {
03310         int result = 0;
03311 
03312         double view_start;
03313         double unit_start;
03314         double view_end;
03315         double unit_end;
03316         double yscale;
03317         int center_pixel;
03318         double zoom_sample;
03319         double zoom_units;
03320 
03321         if(!track->expand_view) return 0;
03322 
03323         calculate_viewport(track, 
03324                 view_start,
03325                 unit_start,
03326                 view_end,
03327                 unit_end,
03328                 yscale,
03329                 center_pixel,
03330                 zoom_sample,
03331                 zoom_units);
03332 
03333 
03334 
03335         for(int i = 0; i < track->plugin_set.total && !result; i++)
03336         {
03337                 PluginSet *plugin_set = track->plugin_set.values[i];
03338                 int center_pixel = (int)(track->y_pixel + 
03339                         mwindow->edl->local_session->zoom_track +
03340                         (i + 0.5) * mwindow->theme->plugin_bg_data->get_h() + 
03341                         (mwindow->edl->session->show_titles ? mwindow->theme->title_bg_data->get_h() : 0));
03342 
03343                 for(Plugin *plugin = (Plugin*)plugin_set->first; 
03344                         plugin && !result; 
03345                         plugin = (Plugin*)plugin->next)
03346                 {
03347                         for(KeyFrame *keyframe = (KeyFrame*)plugin->keyframes->first; 
03348                                 keyframe && !result; 
03349                                 keyframe = (KeyFrame*)keyframe->next)
03350                         {
03351 //printf("TrackCanvas::draw_plugin_autos 3 %d\n", keyframe->position);
03352                                 if(keyframe->position >= unit_start && keyframe->position < unit_end)
03353                                 {
03354                                         int64_t x = (int64_t)((keyframe->position - unit_start) / zoom_units);
03355                                         int y = center_pixel - keyframe_pixmap->get_h() / 2;
03356 
03357 //printf("TrackCanvas::draw_plugin_autos 4 %d %d\n", x, center_pixel);
03358                                         if(!draw)
03359                                         {
03360                                                 if(cursor_x >= x && cursor_y >= y &&
03361                                                         cursor_x < x + keyframe_pixmap->get_w() &&
03362                                                         cursor_y < y + keyframe_pixmap->get_h())
03363                                                 {
03364                                                         result = 1;
03365                                                         keyframe_plugin = plugin;
03366                                                         keyframe_instance = keyframe;
03367 
03368                                                         if(buttonpress)
03369                                                         {
03370                                                                 mwindow->session->drag_auto = keyframe;
03371                                                                 mwindow->session->drag_start_position = keyframe->position;
03372                                                                 mwindow->session->drag_origin_x = cursor_x;
03373                                                                 mwindow->session->drag_origin_y = cursor_y;
03374 
03375                                                                 double position = track->from_units(keyframe->position);
03376                                                                 double center = (mwindow->edl->local_session->get_selectionstart(1) +
03377                                                                         mwindow->edl->local_session->get_selectionend(1)) / 
03378                                                                         2;
03379 
03380                                                                 if(!shift_down())
03381                                                                 {
03382                                                                         mwindow->edl->local_session->set_selectionstart(position);
03383                                                                         mwindow->edl->local_session->set_selectionend(position);
03384                                                                 }
03385                                                                 else
03386                                                                 if(position < center)
03387                                                                 {
03388                                                                         mwindow->edl->local_session->set_selectionstart(position);
03389                                                                 }
03390                                                                 else
03391                                                                         mwindow->edl->local_session->set_selectionend(position);
03392                                                         }
03393                                                 }
03394                                         }
03395                                         else
03396                                                 draw_pixmap(keyframe_pixmap, 
03397                                                         x, 
03398                                                         y);
03399                                 }
03400                         }
03401                 }
03402         }
03403 //printf("TrackCanvas::draw_plugin_autos 5\n");
03404         return result;
03405 }
03406 
03407 void TrackCanvas::draw_overlays()
03408 {
03409         int new_cursor, update_cursor, rerender;
03410 //TRACE("TrackCanvas::draw_overlays 1")
03411 
03412 // Move background pixmap to foreground pixmap
03413         draw_pixmap(background_pixmap, 
03414                 0, 
03415                 0,
03416                 get_w(),
03417                 get_h(),
03418                 0,
03419                 0);
03420 //TRACE("TrackCanvas::draw_overlays 10")
03421 
03422 // In/Out points
03423         draw_inout_points();
03424 
03425 //TRACE("TrackCanvas::draw_overlays 11");
03426 // Transitions
03427         if(mwindow->edl->session->auto_conf->transitions) draw_transitions();
03428 
03429 //TRACE("TrackCanvas::draw_overlays 12");
03430 // Plugins
03431         draw_plugins();
03432 
03433 //TRACE("TrackCanvas::draw_overlays 13");
03434 // Loop points
03435         draw_loop_points();
03436         draw_brender_start();
03437 
03438 //TRACE("TrackCanvas::draw_overlays 14");
03439 // Highlighted areas
03440         draw_highlighting();
03441 
03442 //TRACE("TrackCanvas::draw_overlays 15");
03443 // Automation
03444         do_keyframes(0, 
03445                 0, 
03446                 1, 
03447                 0, 
03448                 new_cursor, 
03449                 update_cursor,
03450                 rerender);
03451 
03452 //TRACE("TrackCanvas::draw_overlays 16\n");
03453 // Selection cursor
03454         if(gui->cursor) gui->cursor->restore();
03455 
03456 //TRACE("TrackCanvas::draw_overlays 17\n");
03457 // Handle dragging
03458         draw_drag_handle();
03459 
03460 //TRACE("TrackCanvas::draw_overlays 20");
03461 // Playback cursor
03462         draw_playback_cursor();
03463 
03464 }
03465 
03466 int TrackCanvas::activate()
03467 {
03468         if(!active)
03469         {
03470                 get_top_level()->deactivate();
03471                 active = 1;
03472                 set_active_subwindow(this);
03473                 gui->cursor->activate();
03474         }
03475         return 0;
03476 }
03477 
03478 int TrackCanvas::deactivate()
03479 {
03480         if(active)
03481         {
03482                 active = 0;
03483                 gui->cursor->deactivate();
03484         }
03485         return 0;
03486 }
03487 
03488 
03489 void TrackCanvas::update_drag_handle()
03490 {
03491         double new_position;
03492 
03493         new_position = 
03494                 (double)(get_cursor_x() + mwindow->edl->local_session->view_start) *
03495                 mwindow->edl->local_session->zoom_sample /
03496                 mwindow->edl->session->sample_rate;
03497         new_position = 
03498                 mwindow->edl->align_to_frame(new_position, 0);
03499 
03500 
03501         if(new_position != mwindow->session->drag_position)
03502         {
03503                 mwindow->session->drag_position = new_position;
03504                 gui->mainclock->update(new_position);
03505 // Que the CWindow.  Doesn't do anything if selectionstart and selection end 
03506 // aren't changed.
03507 //              mwindow->cwindow->update(1, 0, 0);
03508         }
03509 }
03510 
03511 int TrackCanvas::update_drag_edit()
03512 {
03513         int result = 0;
03514         
03515         
03516         
03517         return result;
03518 }
03519 
03520 #define UPDATE_DRAG_HEAD(do_clamp) \
03521         int result = 0; \
03522         int x = cursor_x - mwindow->session->drag_origin_x; \
03523         int y = cursor_y - mwindow->session->drag_origin_y; \
03524  \
03525         if(!current->autos->track->record) return 0; \
03526         double view_start; \
03527         double unit_start; \
03528         double view_end; \
03529         double unit_end; \
03530         double yscale; \
03531         int center_pixel; \
03532         double zoom_sample; \
03533         double zoom_units; \
03534  \
03535         calculate_viewport(current->autos->track,  \
03536                 view_start, \
03537                 unit_start, \
03538                 view_end, \
03539                 unit_end, \
03540                 yscale, \
03541                 center_pixel, \
03542                 zoom_sample, \
03543                 zoom_units); \
03544  \
03545         float percentage = (float)(mwindow->session->drag_origin_y - cursor_y) / \
03546                 yscale +  \
03547                 mwindow->session->drag_start_percentage; \
03548         if(do_clamp) CLAMP(percentage, 0, 1); \
03549  \
03550         int64_t position = Units::to_int64(zoom_units * \
03551                 (cursor_x - mwindow->session->drag_origin_x) + \
03552                 mwindow->session->drag_start_position); \
03553  \
03554         if((do_clamp) && position < 0) position = 0;
03555 
03556 
03557 
03558 
03559 
03560 
03561 
03562 
03563 
03564 int TrackCanvas::update_drag_floatauto(int cursor_x, int cursor_y)
03565 {
03566         FloatAuto *current = (FloatAuto*)mwindow->session->drag_auto;
03567 
03568         UPDATE_DRAG_HEAD(mwindow->session->drag_handle == 0);
03569 
03570         float value;
03571         float old_value;
03572 
03573         switch(mwindow->session->drag_handle)
03574         {
03575 // Center
03576                 case 0:
03577 // Snap to nearby values
03578                         old_value = current->value;
03579                         if(shift_down())
03580                         {
03581                                 double value1;
03582                                 double distance1;
03583                                 double value2;
03584                                 double distance2;
03585                                 value = percentage_to_value(percentage, 0, 0);
03586 
03587                                 if(current->previous)
03588                                 {
03589                                         value1 = ((FloatAuto*)current->previous)->value;
03590                                         distance1 = fabs(value - value1);
03591                                         current->value = value1;
03592                                 }
03593 
03594                                 if(current->next)
03595                                 {
03596                                         value2 = ((FloatAuto*)current->next)->value;
03597                                         distance2 = fabs(value - value2);
03598                                         if(!current->previous || distance2 < distance1)
03599                                         {
03600                                                 current->value = value2;
03601                                         }
03602                                 }
03603 
03604                                 if(!current->previous && !current->next)
03605                                 {
03606                                         current->value = ((FloatAutos*)current->autos)->default_;
03607                                 }
03608                                 value = current->value;
03609                         }
03610                         else
03611                                 value = percentage_to_value(percentage, 0, 0);
03612 
03613                         if(value != old_value || position != current->position)
03614                         {
03615                                 result = 1;
03616                                 float change = value - old_value;               
03617                                 current->value = value;
03618                                 current->position = position;
03619                                 synchronize_autos(change, current->autos->track, current, 0);
03620 
03621                                 char string[BCTEXTLEN], string2[BCTEXTLEN];
03622                                 Units::totext(string2, 
03623                                         current->autos->track->from_units(current->position),
03624                                         mwindow->edl->session->time_format,
03625                                         mwindow->edl->session->sample_rate,
03626                                         mwindow->edl->session->frame_rate,
03627                                         mwindow->edl->session->frames_per_foot);
03628                                 sprintf(string, "%s, %.2f", string2, current->value);
03629                                 gui->show_message(string);
03630                         }
03631                         break;
03632 
03633 // In control
03634                 case 1:
03635                         value = percentage_to_value(percentage, 0, current);
03636                         position = MIN(0, position);
03637                         if(value != current->control_in_value || 
03638                                 position != current->control_in_position)
03639                         {
03640                                 result = 1;
03641                                 current->control_in_value = value;
03642                                 current->control_in_position = position;
03643                                 synchronize_autos(0, current->autos->track, current, 0);
03644 
03645                                 char string[BCTEXTLEN], string2[BCTEXTLEN];
03646                                 Units::totext(string2, 
03647                                         current->autos->track->from_units(current->control_in_position),
03648                                         mwindow->edl->session->time_format,
03649                                         mwindow->edl->session->sample_rate,
03650                                         mwindow->edl->session->frame_rate,
03651                                         mwindow->edl->session->frames_per_foot);
03652                                 sprintf(string, "%s, %.2f", string2, current->control_in_value);
03653                                 gui->show_message(string);
03654                         }
03655                         break;
03656 
03657 // Out control
03658                 case 2:
03659                         value = percentage_to_value(percentage, 0, current);
03660                         position = MAX(0, position);
03661                         if(value != current->control_out_value || 
03662                                 position != current->control_out_position)
03663                         {
03664                                 result = 1;
03665                                 current->control_out_value = value;
03666                                 current->control_out_position = position;
03667                                 synchronize_autos(0, current->autos->track, current, 0);
03668 
03669                                 char string[BCTEXTLEN], string2[BCTEXTLEN];
03670                                 Units::totext(string2, 
03671                                         current->autos->track->from_units(
03672                                                 ((FloatAuto*)current)->control_out_position),
03673                                         mwindow->edl->session->time_format,
03674                                         mwindow->edl->session->sample_rate,
03675                                         mwindow->edl->session->frame_rate,
03676                                         mwindow->edl->session->frames_per_foot);
03677                                 sprintf(string, "%s, %.2f", 
03678                                         string2, 
03679                                         ((FloatAuto*)current)->control_out_value);
03680                                 gui->show_message(string);
03681                         }
03682                         break;
03683         }
03684 
03685         return result;
03686 }
03687 
03688 int TrackCanvas::update_drag_toggleauto(int cursor_x, int cursor_y)
03689 {
03690         IntAuto *current = (IntAuto*)mwindow->session->drag_auto;
03691 
03692         UPDATE_DRAG_HEAD(1);
03693 
03694         int value = (int)percentage_to_value(percentage, 1, 0);
03695 
03696         if(value != current->value || position != current->position)
03697         {
03698                 result = 1;
03699                 current->value = value;
03700                 current->position = position;
03701 
03702                 char string[BCTEXTLEN], string2[BCTEXTLEN];
03703                 Units::totext(string2, 
03704                         current->autos->track->from_units(current->position),
03705                         mwindow->edl->session->time_format,
03706                         mwindow->edl->session->sample_rate,
03707                         mwindow->edl->session->frame_rate,
03708                         mwindow->edl->session->frames_per_foot);
03709                 sprintf(string, "%s, %d", string2, current->value);
03710                 gui->show_message(string);
03711         }
03712 
03713         return result;
03714 }
03715 
03716 // Autos which can't change value through dragging.
03717 
03718 int TrackCanvas::update_drag_auto(int cursor_x, int cursor_y)
03719 {
03720         Auto *current = (Auto*)mwindow->session->drag_auto;
03721 
03722         UPDATE_DRAG_HEAD(1)
03723         if(position != current->position)
03724         {
03725                 result = 1;
03726                 current->position = position;
03727 
03728                 char string[BCTEXTLEN];
03729                 Units::totext(string, 
03730                         current->autos->track->from_units(current->position),
03731                         mwindow->edl->session->time_format,
03732                         mwindow->edl->session->sample_rate,
03733                         mwindow->edl->session->frame_rate,
03734                         mwindow->edl->session->frames_per_foot);
03735                 gui->show_message(string);
03736 
03737                 double position_f = current->autos->track->from_units(current->position);
03738                 double center_f = (mwindow->edl->local_session->get_selectionstart(1) +
03739                         mwindow->edl->local_session->get_selectionend(1)) / 
03740                         2;
03741                 if(!shift_down())
03742                 {
03743                         mwindow->edl->local_session->set_selectionstart(position_f);
03744                         mwindow->edl->local_session->set_selectionend(position_f);
03745                 }
03746                 else
03747                 if(position_f < center_f)
03748                 {
03749                         mwindow->edl->local_session->set_selectionstart(position_f);
03750                 }
03751                 else
03752                         mwindow->edl->local_session->set_selectionend(position_f);
03753         }
03754 
03755 
03756         return result;
03757 }
03758 
03759 int TrackCanvas::update_drag_pluginauto(int cursor_x, int cursor_y)
03760 {
03761         KeyFrame *current = (KeyFrame*)mwindow->session->drag_auto;
03762 
03763         UPDATE_DRAG_HEAD(1)
03764         if(position != current->position)
03765         {
03766 //      printf("uida: autos: %p, track: %p ta: %p\n", current->autos, current->autos->track, current->autos->track->automation);
03767                 Track *track = current->autos->track;
03768                 PluginAutos *pluginautos = (PluginAutos *)current->autos;
03769                 PluginSet *pluginset;
03770                 Plugin *plugin;
03771                 // figure out the correct pluginset & correct plugin 
03772                 int found = 0;
03773                 for(int i = 0; i < track->plugin_set.total; i++)
03774                 {
03775                         pluginset = track->plugin_set.values[i];
03776                         for(plugin = (Plugin *)pluginset->first; plugin; plugin = (Plugin *)plugin->next)
03777                         {
03778                                 KeyFrames *keyframes = plugin->keyframes;
03779                                 for(KeyFrame *currentkeyframe = (KeyFrame *)keyframes->first; currentkeyframe; currentkeyframe = (KeyFrame *) currentkeyframe->next)
03780                                 {
03781                                         if (currentkeyframe == current) 
03782                                         {
03783                                                 found = 1;
03784                                                 break;
03785                                         }
03786  
03787                                 }
03788                                 if (found) break;                       
03789                         }
03790                         if (found) break;                       
03791                 }       
03792         
03793                 mwindow->session->plugin_highlighted = plugin;
03794                 mwindow->session->track_highlighted = track;
03795                 result = 1;
03796                 current->position = position;
03797 
03798                 char string[BCTEXTLEN];
03799                 Units::totext(string, 
03800                         current->autos->track->from_units(current->position),
03801                         mwindow->edl->session->time_format,
03802                         mwindow->edl->session->sample_rate,
03803                         mwindow->edl->session->frame_rate,
03804                         mwindow->edl->session->frames_per_foot);
03805                 gui->show_message(string);
03806 
03807                 double position_f = current->autos->track->from_units(current->position);
03808                 double center_f = (mwindow->edl->local_session->get_selectionstart(1) +
03809                         mwindow->edl->local_session->get_selectionend(1)) / 
03810                         2;
03811                 if(!shift_down())
03812                 {
03813                         mwindow->edl->local_session->set_selectionstart(position_f);
03814                         mwindow->edl->local_session->set_selectionend(position_f);
03815                 }
03816                 else
03817                 if(position_f < center_f)
03818                 {
03819                         mwindow->edl->local_session->set_selectionstart(position_f);
03820                 }
03821                 else
03822                         mwindow->edl->local_session->set_selectionend(position_f);
03823         }
03824 
03825 
03826         return result;
03827 }
03828 
03829 void TrackCanvas::update_drag_caption()
03830 {
03831         switch(mwindow->session->current_operation)
03832         {
03833                 case DRAG_FADE:
03834                         
03835                         break;
03836         }
03837 }
03838 
03839 
03840 
03841 int TrackCanvas::cursor_motion_event()
03842 {
03843         int result, cursor_x, cursor_y;
03844         int update_clock = 0;
03845         int update_zoom = 0;
03846         int update_scroll = 0;
03847         int update_overlay = 0;
03848         int update_cursor = 0;
03849         int new_cursor = 0;
03850         int rerender = 0;
03851         double position = 0;
03852 //printf("TrackCanvas::cursor_motion_event 1\n");
03853         result = 0;
03854 
03855 // Default cursor
03856         switch(mwindow->edl->session->editing_mode)
03857         {
03858                 case EDITING_ARROW: new_cursor = ARROW_CURSOR; break;
03859                 case EDITING_IBEAM: new_cursor = IBEAM_CURSOR; break;
03860         }
03861 
03862         switch(mwindow->session->current_operation)
03863         {
03864                 case DRAG_EDITHANDLE1:
03865 // Outside threshold.  Upgrade status
03866                         if(labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W)
03867                         {
03868                                 mwindow->session->current_operation = DRAG_EDITHANDLE2;
03869                                 update_overlay = 1;
03870                         }
03871                         break;
03872 
03873                 case DRAG_EDITHANDLE2:
03874                         update_drag_handle();
03875                         update_overlay = 1;
03876                         break;
03877 
03878                 case DRAG_PLUGINHANDLE1:
03879                         if(labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W)
03880                         {
03881                                 mwindow->session->current_operation = DRAG_PLUGINHANDLE2;
03882                                 update_overlay = 1;
03883                         }
03884                         break;
03885 
03886                 case DRAG_PLUGINHANDLE2:
03887                         update_drag_handle();
03888                         update_overlay = 1;
03889                         break;
03890 
03891 // Rubber band curves
03892                 case DRAG_FADE:
03893                 case DRAG_CZOOM:
03894                 case DRAG_PZOOM:
03895                 case DRAG_CAMERA_X:
03896                 case DRAG_CAMERA_Y:
03897                 case DRAG_CAMERA_Z:
03898                 case DRAG_PROJECTOR_X:
03899                 case DRAG_PROJECTOR_Y:
03900                 case DRAG_PROJECTOR_Z:
03901                         rerender = update_overlay = update_drag_floatauto(get_cursor_x(), get_cursor_y());
03902                         break;
03903 
03904                 case DRAG_PLAY:
03905                         rerender = update_overlay = update_drag_toggleauto(get_cursor_x(), get_cursor_y());
03906                         break;
03907 
03908                 case DRAG_MUTE:
03909                         rerender = update_overlay = update_drag_toggleauto(get_cursor_x(), get_cursor_y());
03910                         break;
03911 
03912 // Keyframe icons are sticky
03913                 case DRAG_PAN_PRE:
03914                 case DRAG_MASK_PRE:
03915                 case DRAG_MODE_PRE:
03916                 case DRAG_PLUGINKEY_PRE:
03917                         if(labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W)
03918                         {
03919                                 mwindow->session->current_operation++;
03920                                 update_overlay = 1;
03921                         }
03922                         break;
03923 
03924                 case DRAG_PAN:
03925                 case DRAG_MASK:
03926                 case DRAG_MODE:
03927                 case DRAG_PLUGINKEY:
03928                         rerender = update_overlay = 
03929                                 update_drag_pluginauto(get_cursor_x(), get_cursor_y());
03930                         break;
03931 
03932                 case SELECT_REGION:
03933                 {
03934                         cursor_x = get_cursor_x();
03935                         cursor_y = get_cursor_y();
03936                         position = (double)(cursor_x + mwindow->edl->local_session->view_start) * 
03937                                 mwindow->edl->local_session->zoom_sample /
03938                                 mwindow->edl->session->sample_rate;
03939 
03940                         position = mwindow->edl->align_to_frame(position, 0);
03941                         position = MAX(position, 0);
03942 
03943                         if(position < selection_midpoint1)
03944                         {
03945                                 mwindow->edl->local_session->set_selectionend(selection_midpoint1);
03946                                 mwindow->edl->local_session->set_selectionstart(position);
03947 // Que the CWindow
03948                                 gui->unlock_window();
03949                                 mwindow->cwindow->update(1, 0, 0, 0, 1);
03950                                 gui->lock_window("TrackCanvas::cursor_motion_event 1");
03951 // Update the faders
03952                                 mwindow->update_plugin_guis();
03953                                 gui->patchbay->update();
03954                         }
03955                         else
03956                         {
03957                                 mwindow->edl->local_session->set_selectionstart(selection_midpoint1);
03958                                 mwindow->edl->local_session->set_selectionend(position);
03959 // Don't que the CWindow
03960                         }
03961 
03962                         gui->cursor->hide();
03963                         gui->cursor->draw();
03964                         flash();
03965                         result = 1;
03966                         update_clock = 1;
03967                         update_zoom = 1;
03968                         update_scroll = 1;
03969                         break;
03970                 }
03971 
03972                 default:
03973                         if(is_event_win() && cursor_inside())
03974                         {
03975 // Update clocks
03976                                 cursor_x = get_cursor_x();
03977                                 position = (double)cursor_x * 
03978                                         (double)mwindow->edl->local_session->zoom_sample / 
03979                                         (double)mwindow->edl->session->sample_rate + 
03980                                         (double)mwindow->edl->local_session->view_start * 
03981                                         (double)mwindow->edl->local_session->zoom_sample / 
03982                                         (double)mwindow->edl->session->sample_rate;
03983                                 position = mwindow->edl->align_to_frame(position, 0);
03984                                 update_clock = 1;
03985 
03986 // Update cursor
03987                                 if(do_transitions(get_cursor_x(), 
03988                                                 get_cursor_y(), 
03989                                                 0, 
03990                                                 new_cursor, 
03991                                                 update_cursor))
03992                                 {
03993                                         break;
03994                                 }
03995                                 else
03996 // Update cursor
03997                                 if(do_keyframes(get_cursor_x(), 
03998                                         get_cursor_y(), 
03999                                         0, 
04000                                         0, 
04001                                         new_cursor,
04002                                         update_cursor,
04003                                         rerender))
04004                                 {
04005                                         break;
04006                                 }
04007                                 else
04008 // Edit boundaries
04009                                 if(do_edit_handles(get_cursor_x(), 
04010                                         get_cursor_y(), 
04011                                         0, 
04012                                         new_cursor,
04013                                         update_cursor))
04014                                 {
04015                                         break;
04016                                 }
04017                                 else
04018 // Plugin boundaries
04019                                 if(do_plugin_handles(get_cursor_x(), 
04020                                         get_cursor_y(), 
04021                                         0, 
04022                                         new_cursor,
04023                                         update_cursor))
04024                                 {
04025                                         break;
04026                                 }
04027                                 else
04028                                 if(do_edits(get_cursor_x(), 
04029                                         get_cursor_y(), 
04030                                         0, 
04031                                         0, 
04032                                         update_overlay, 
04033                                         rerender,
04034                                         new_cursor,
04035                                         update_cursor))
04036                                 {
04037                                         break;
04038                                 }
04039                         }
04040                         break;
04041         }
04042 
04043 //printf("TrackCanvas::cursor_motion_event 1\n");
04044         if(update_cursor && new_cursor != get_cursor())
04045         {
04046                 set_cursor(new_cursor);
04047         }
04048 
04049 //printf("TrackCanvas::cursor_motion_event 1 %d\n", rerender);
04050         if(rerender)
04051         {
04052                 mwindow->restart_brender();
04053                 mwindow->sync_parameters(CHANGE_PARAMS);
04054                 mwindow->update_plugin_guis();
04055                 gui->unlock_window();
04056                 mwindow->cwindow->update(1, 0, 0, 0, 1);
04057                 gui->lock_window("TrackCanvas::cursor_motion_event 2");
04058 // Update faders
04059                 gui->patchbay->update();
04060         }
04061 
04062 
04063         if(update_clock)
04064         {
04065                 if(!mwindow->cwindow->playback_engine->is_playing_back)
04066                         gui->mainclock->update(position);
04067         }
04068 
04069         if(update_zoom)
04070         {
04071                 gui->zoombar->update();
04072         }
04073 
04074         if(update_scroll)
04075         {
04076                 if(!drag_scroll && 
04077                         (cursor_x >= get_w() || cursor_x < 0 || cursor_y >= get_h() || cursor_y < 0))
04078                         start_dragscroll();
04079                 else
04080                 if(drag_scroll &&
04081                         (cursor_x < get_w() && cursor_x >= 0 && cursor_y < get_h() && cursor_y >= 0))
04082                         stop_dragscroll();
04083         }
04084 
04085         if(update_overlay)
04086         {
04087                 draw_overlays();
04088                 flash();
04089         }
04090 
04091 
04092 //printf("TrackCanvas::cursor_motion_event 100\n");
04093         return result;
04094 }
04095 
04096 void TrackCanvas::start_dragscroll()
04097 {
04098         if(!drag_scroll)
04099         {
04100                 drag_scroll = 1;
04101                 set_repeat(BC_WindowBase::get_resources()->scroll_repeat);
04102 //printf("TrackCanvas::start_dragscroll 1\n");
04103         }
04104 }
04105 
04106 void TrackCanvas::stop_dragscroll()
04107 {
04108         if(drag_scroll)
04109         {
04110                 drag_scroll = 0;
04111                 unset_repeat(BC_WindowBase::get_resources()->scroll_repeat);
04112 //printf("TrackCanvas::stop_dragscroll 1\n");
04113         }
04114 }
04115 
04116 int TrackCanvas::repeat_event(int64_t duration)
04117 {
04118         if(!drag_scroll) return 0;
04119         if(duration != BC_WindowBase::get_resources()->scroll_repeat) return 0;
04120 
04121         int sample_movement = 0;
04122         int track_movement = 0;
04123         int64_t x_distance = 0;
04124         int64_t y_distance = 0;
04125         double position = 0;
04126         int result = 0;
04127 
04128         switch(mwindow->session->current_operation)
04129         {
04130                 case SELECT_REGION:
04131 //printf("TrackCanvas::repeat_event 1 %d\n", mwindow->edl->local_session->view_start);
04132                         if(get_cursor_x() > get_w())
04133                         {
04134                                 x_distance = get_cursor_x() - get_w();
04135                                 sample_movement = 1;
04136                         }
04137                         else
04138                         if(get_cursor_x() < 0)
04139                         {
04140                                 x_distance = get_cursor_x();
04141                                 sample_movement = 1;
04142                         }
04143 
04144                         if(get_cursor_y() > get_h())
04145                         {
04146                                 y_distance = get_cursor_y() - get_h();
04147                                 track_movement = 1;
04148                         }
04149                         else
04150                         if(get_cursor_y() < 0)
04151                         {
04152                                 y_distance = get_cursor_y();
04153                                 track_movement = 1;
04154                         }
04155                         result = 1;
04156                         break;
04157         }
04158 
04159 
04160         if(sample_movement)
04161         {
04162                 position = (double)(get_cursor_x() + 
04163                         mwindow->edl->local_session->view_start + 
04164                         x_distance) * 
04165                         mwindow->edl->local_session->zoom_sample /
04166                         mwindow->edl->session->sample_rate;
04167                 position = mwindow->edl->align_to_frame(position, 0);
04168                 position = MAX(position, 0);
04169 
04170 //printf("TrackCanvas::repeat_event 1 %f\n", position);
04171                 switch(mwindow->session->current_operation)
04172                 {
04173                         case SELECT_REGION:
04174                                 if(position < selection_midpoint1)
04175                                 {
04176                                         mwindow->edl->local_session->set_selectionend(selection_midpoint1);
04177                                         mwindow->edl->local_session->set_selectionstart(position);
04178 // Que the CWindow
04179                                         gui->unlock_window();
04180                                         mwindow->cwindow->update(1, 0, 0);
04181                                         gui->lock_window("TrackCanvas::repeat_event");
04182 // Update the faders
04183                                         mwindow->update_plugin_guis();
04184                                         gui->patchbay->update();
04185                                 }
04186                                 else
04187                                 {
04188                                         mwindow->edl->local_session->set_selectionstart(selection_midpoint1);
04189                                         mwindow->edl->local_session->set_selectionend(position);
04190 // Don't que the CWindow
04191                                 }
04192                                 break;
04193                 }
04194 
04195                 mwindow->samplemovement(mwindow->edl->local_session->view_start + 
04196                         x_distance);
04197         }
04198 
04199         if(track_movement)
04200         {
04201                 mwindow->trackmovement(mwindow->edl->local_session->track_start + 
04202                         y_distance);
04203         }
04204 
04205         return result;
04206 }
04207 
04208 int TrackCanvas::button_release_event()
04209 {
04210         int redraw = 0, update_overlay = 0, result = 0;
04211 
04212         switch(mwindow->session->current_operation)
04213         {
04214                 case DRAG_EDITHANDLE2:
04215                         mwindow->session->current_operation = NO_OPERATION;
04216                         drag_scroll = 0;
04217                         result = 1;
04218                         
04219                         end_edithandle_selection();
04220                         break;
04221 
04222                 case DRAG_EDITHANDLE1:
04223                         mwindow->session->current_operation = NO_OPERATION;
04224                         drag_scroll = 0;
04225                         result = 1;
04226                         break;
04227 
04228                 case DRAG_PLUGINHANDLE2:
04229                         mwindow->session->current_operation = NO_OPERATION;
04230                         drag_scroll = 0;
04231                         result = 1;
04232                         
04233                         end_pluginhandle_selection();
04234                         break;
04235 
04236                 case DRAG_PLUGINHANDLE1:
04237                         mwindow->session->current_operation = NO_OPERATION;
04238                         drag_scroll = 0;
04239                         result = 1;
04240                         break;
04241 
04242                 case DRAG_FADE:
04243 // delete the drag_auto_gang first and remove out of order keys
04244                         synchronize_autos(0, 0, 0, -1); 
04245                 case DRAG_CZOOM:
04246                 case DRAG_PZOOM:
04247                 case DRAG_PLAY:
04248                 case DRAG_MUTE:
04249                 case DRAG_MASK:
04250                 case DRAG_MODE:
04251                 case DRAG_PAN:
04252                 case DRAG_CAMERA_X:
04253                 case DRAG_CAMERA_Y:
04254                 case DRAG_CAMERA_Z:
04255                 case DRAG_PROJECTOR_X:
04256                 case DRAG_PROJECTOR_Y:
04257                 case DRAG_PROJECTOR_Z:
04258                 case DRAG_PLUGINKEY:
04259                         mwindow->session->current_operation = NO_OPERATION;
04260                         mwindow->session->drag_handle = 0;
04261 // Remove any out-of-order keyframe
04262                         if(mwindow->session->drag_auto)
04263                         {
04264                                 mwindow->session->drag_auto->autos->remove_nonsequential(
04265                                         mwindow->session->drag_auto);
04266 //                              mwindow->session->drag_auto->autos->optimize();
04267                                 update_overlay = 1;
04268                         }
04269                         mwindow->undo->update_undo(_("keyframe"), LOAD_AUTOMATION);
04270                         result = 1;
04271                         break;
04272 
04273                 case DRAG_EDIT:
04274                 case DRAG_AEFFECT_COPY:
04275                 case DRAG_VEFFECT_COPY:
04276 // Trap in drag stop
04277 
04278                         break;
04279 
04280 
04281                 default:
04282                         if(mwindow->session->current_operation)
04283                         {
04284                                 if(mwindow->session->current_operation == SELECT_REGION)
04285                                 {
04286                                         mwindow->undo->update_undo(_("select"), LOAD_SESSION, 0, 0);
04287                                 }
04288 
04289                                 mwindow->session->current_operation = NO_OPERATION;
04290                                 drag_scroll = 0;
04291 // Traps button release events
04292 //                              result = 1;
04293                         }
04294                         break;
04295         }
04296         if (result) 
04297                 cursor_motion_event();
04298         if(update_overlay)
04299         {
04300                 draw_overlays();
04301                 flash();
04302                 flush();
04303         }
04304         if(redraw)
04305         {
04306                 draw();
04307                 flash();
04308                 flush();
04309         }
04310         return result;
04311 }
04312 
04313 int TrackCanvas::do_edit_handles(int cursor_x, 
04314         int cursor_y, 
04315         int button_press, 
04316         int &new_cursor,
04317         int &update_cursor)
04318 {
04319         Edit *edit_result = 0;
04320         int handle_result = 0;
04321         int result = 0;
04322 
04323         if(!mwindow->edl->session->show_assets) return 0;
04324 
04325         for(Track *track = mwindow->edl->tracks->first;
04326                 track && !result;
04327                 track = track->next)
04328         {
04329                 for(Edit *edit = track->edits->first;
04330                         edit && !result;
04331                         edit = edit->next)
04332                 {
04333                         int64_t edit_x, edit_y, edit_w, edit_h;
04334                         edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
04335 
04336                         if(cursor_x >= edit_x && cursor_x <= edit_x + edit_w &&
04337                                 cursor_y >= edit_y && cursor_y < edit_y + edit_h)
04338                         {
04339                                 if(cursor_x < edit_x + HANDLE_W)
04340                                 {
04341                                         edit_result = edit;
04342                                         handle_result = 0;
04343                                         result = 1;
04344                                 }
04345                                 else
04346                                 if(cursor_x >= edit_x + edit_w - HANDLE_W)
04347                                 {
04348                                         edit_result = edit;
04349                                         handle_result = 1;
04350                                         result = 1;
04351                                 }
04352                                 else
04353                                 {
04354                                         result = 0;
04355                                 }
04356                         }
04357                 }
04358         }
04359 
04360         update_cursor = 1;
04361         if(result)
04362         {
04363                 double position;
04364                 if(handle_result == 0)
04365                 {
04366                         position = edit_result->track->from_units(edit_result->startproject);
04367                         new_cursor = LEFT_CURSOR;
04368                 }
04369                 else
04370                 if(handle_result == 1)
04371                 {
04372                         position = edit_result->track->from_units(edit_result->startproject + edit_result->length);
04373                         new_cursor = RIGHT_CURSOR;
04374                 };
04375 
04376 // Reposition cursor
04377                 if(button_press)
04378                 {
04379                         mwindow->session->drag_edit = edit_result;
04380                         mwindow->session->drag_handle = handle_result;
04381                         mwindow->session->drag_button = get_buttonpress() - 1;
04382                         mwindow->session->drag_position = position;
04383                         mwindow->session->current_operation = DRAG_EDITHANDLE1;
04384                         mwindow->session->drag_origin_x = get_cursor_x();
04385                         mwindow->session->drag_origin_y = get_cursor_y();
04386                         mwindow->session->drag_start = position;
04387 
04388                         int rerender = start_selection(position);
04389                         if(rerender)
04390                         {
04391                                 gui->unlock_window();
04392                                 mwindow->cwindow->update(1, 0, 0);
04393                                 gui->lock_window("TrackCanvas::do_edit_handles");
04394                         }
04395                         gui->timebar->update_highlights();
04396                         gui->zoombar->update();
04397                         gui->cursor->hide();
04398                         gui->cursor->draw();
04399                         draw_overlays();
04400                         flash();
04401                         flush();
04402                 }
04403         }
04404 
04405         return result;
04406 }
04407 
04408 int TrackCanvas::do_plugin_handles(int cursor_x, 
04409         int cursor_y, 
04410         int button_press,
04411         int &new_cursor,
04412         int &update_cursor)
04413 {
04414         Plugin *plugin_result = 0;
04415         int handle_result = 0;
04416         int result = 0;
04417 
04418         if(!mwindow->edl->session->show_assets) return 0;
04419 
04420         for(Track *track = mwindow->edl->tracks->first;
04421                 track && !result;
04422                 track = track->next)
04423         {
04424                 for(int i = 0; i < track->plugin_set.total && !result; i++)
04425                 {
04426                         PluginSet *plugin_set = track->plugin_set.values[i];
04427                         for(Plugin *plugin = (Plugin*)plugin_set->first; 
04428                                 plugin && !result; 
04429                                 plugin = (Plugin*)plugin->next)
04430                         {
04431                                 int64_t plugin_x, plugin_y, plugin_w, plugin_h;
04432                                 plugin_dimensions(plugin, plugin_x, plugin_y, plugin_w, plugin_h);
04433 
04434                                 if(cursor_x >= plugin_x && cursor_x <= plugin_x + plugin_w &&
04435                                         cursor_y >= plugin_y && cursor_y < plugin_y + plugin_h)
04436                                 {
04437                                         if(cursor_x < plugin_x + HANDLE_W)
04438                                         {
04439                                                 plugin_result = plugin;
04440                                                 handle_result = 0;
04441                                                 result = 1;
04442                                         }
04443                                         else
04444                                         if(cursor_x >= plugin_x + plugin_w - HANDLE_W)
04445                                         {
04446                                                 plugin_result = plugin;
04447                                                 handle_result = 1;
04448                                                 result = 1;
04449                                         }
04450                                 }
04451                         }
04452 
04453                         if(result && shift_down())
04454                                 mwindow->session->trim_edits = plugin_set;
04455                 }
04456         }
04457 
04458         update_cursor = 1;
04459         if(result)
04460         {
04461                 double position;
04462                 if(handle_result == 0)
04463                 {
04464                         position = plugin_result->track->from_units(plugin_result->startproject);
04465                         new_cursor = LEFT_CURSOR;
04466                 }
04467                 else
04468                 if(handle_result == 1)
04469                 {
04470                         position = plugin_result->track->from_units(plugin_result->startproject + plugin_result->length);
04471                         new_cursor = RIGHT_CURSOR;
04472                 }
04473                 
04474                 if(button_press)
04475                 {
04476                         mwindow->session->drag_plugin = plugin_result;
04477                         mwindow->session->drag_handle = handle_result;
04478                         mwindow->session->drag_button = get_buttonpress() - 1;
04479                         mwindow->session->drag_position = position;
04480                         mwindow->session->current_operation = DRAG_PLUGINHANDLE1;
04481                         mwindow->session->drag_origin_x = get_cursor_x();
04482                         mwindow->session->drag_origin_y = get_cursor_y();
04483                         mwindow->session->drag_start = position;
04484 
04485                         int rerender = start_selection(position);
04486                         if(rerender) 
04487                         {
04488                                 gui->unlock_window();
04489                                 mwindow->cwindow->update(1, 0, 0);
04490                                 gui->lock_window("TrackCanvas::do_plugin_handles");
04491                         }
04492                         gui->timebar->update_highlights();
04493                         gui->zoombar->update();
04494                         gui->cursor->hide();
04495                         gui->cursor->draw();
04496                         draw_overlays();
04497                         flash();
04498                         flush();
04499                 }
04500         }
04501         
04502         return result;
04503 }
04504 
04505 
04506 int TrackCanvas::do_tracks(int cursor_x, 
04507                 int cursor_y,
04508                 int button_press)
04509 {
04510         int result = 0;
04511 
04512 
04513         if(!mwindow->edl->session->show_assets) return 0;
04514 
04515 
04516         for(Track *track = mwindow->edl->tracks->first;
04517                 track && !result;
04518                 track = track->next)
04519         {
04520                 int64_t track_x, track_y, track_w, track_h;
04521                 track_dimensions(track, track_x, track_y, track_w, track_h);
04522 
04523                 if(button_press && 
04524                         get_buttonpress() == 3 &&
04525                         cursor_y >= track_y && 
04526                         cursor_y < track_y + track_h)
04527                 {
04528                         gui->edit_menu->update(track, 0);
04529                         gui->edit_menu->activate_menu();
04530                         result = 1;
04531                 }
04532         }
04533         return result;
04534 }
04535 
04536 int TrackCanvas::do_edits(int cursor_x, 
04537         int cursor_y, 
04538         int button_press,
04539         int drag_start,
04540         int &redraw,
04541         int &rerender,
04542         int &new_cursor,
04543         int &update_cursor)
04544 {
04545         int result = 0;
04546         int over_edit_handle = 0;
04547 
04548         if(!mwindow->edl->session->show_assets) return 0;
04549 
04550         for(Track *track = mwindow->edl->tracks->first;
04551                 track && !result;
04552                 track = track->next)
04553         {
04554                 for(Edit *edit = track->edits->first;
04555                         edit && !result;
04556                         edit = edit->next)
04557                 {
04558                         int64_t edit_x, edit_y, edit_w, edit_h;
04559                         edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
04560 
04561 // Cursor inside a track
04562 // Cursor inside an edit
04563                         if(cursor_x >= edit_x && cursor_x < edit_x + edit_w &&
04564                                 cursor_y >= edit_y && cursor_y < edit_y + edit_h)
04565                         {
04566 // Select duration of edit
04567                                 if(button_press)
04568                                 {
04569                                         if(get_double_click() && !drag_start)
04570                                         {
04571                                                 mwindow->edl->local_session->set_selectionstart(edit->track->from_units(edit->startproject));
04572                                                 mwindow->edl->local_session->set_selectionend(edit->track->from_units(edit->startproject) + 
04573                                                         edit->track->from_units(edit->length));
04574                                                 if(mwindow->edl->session->cursor_on_frames) 
04575                                                 {
04576                                                         mwindow->edl->local_session->set_selectionstart(
04577                                                                 mwindow->edl->align_to_frame(mwindow->edl->local_session->get_selectionstart(1), 0));
04578                                                         mwindow->edl->local_session->set_selectionend(
04579                                                                 mwindow->edl->align_to_frame(mwindow->edl->local_session->get_selectionend(1), 1));
04580                                                 }
04581                                                 redraw = 1;
04582                                                 rerender = 1;
04583                                                 result = 1;
04584                                         }
04585                                 }
04586                                 else
04587                                 if(drag_start && track->record)
04588                                 {
04589                                         if(mwindow->edl->session->editing_mode == EDITING_ARROW)
04590                                         {
04591 // Need to create drag window
04592                                                 mwindow->session->current_operation = DRAG_EDIT;
04593                                                 mwindow->session->drag_edit = edit;
04594 //printf("TrackCanvas::do_edits 2\n");
04595 
04596 // Drag only one edit
04597                                                 if(ctrl_down())
04598                                                 {
04599                                                         mwindow->session->drag_edits->remove_all();
04600                                                         mwindow->session->drag_edits->append(edit);
04601                                                 }
04602                                                 else
04603 // Construct list of all affected edits
04604                                                 {
04605                                                         mwindow->edl->tracks->get_affected_edits(
04606                                                                 mwindow->session->drag_edits, 
04607                                                                 edit->track->from_units(edit->startproject),
04608                                                                 edit->track);
04609                                                 }
04610                                                 mwindow->session->drag_origin_x = cursor_x;
04611                                                 mwindow->session->drag_origin_y = cursor_y;
04612                                                 // Where the drag started, so we know relative position inside the edit later
04613                                                 mwindow->session->drag_position = (double)cursor_x * 
04614                                                         mwindow->edl->local_session->zoom_sample / 
04615                                                         mwindow->edl->session->sample_rate + 
04616                                                         (double)mwindow->edl->local_session->view_start * 
04617                                                         mwindow->edl->local_session->zoom_sample /
04618                                                         mwindow->edl->session->sample_rate;
04619                                                 
04620                                                 drag_popup = new BC_DragWindow(gui, 
04621                                                         mwindow->theme->get_image("clip_icon"), 
04622                                                         get_abs_cursor_x(0) - mwindow->theme->get_image("clip_icon")->get_w() / 2,
04623                                                         get_abs_cursor_y(0) - mwindow->theme->get_image("clip_icon")->get_h() / 2);
04624 
04625                                                 result = 1;
04626                                         }
04627                                 }
04628                         }
04629                 }
04630         }
04631         return result;
04632 }
04633 
04634 
04635 int TrackCanvas::test_resources(int cursor_x, int cursor_y)
04636 {
04637         return 0;
04638 }
04639 
04640 int TrackCanvas::do_plugins(int cursor_x, 
04641         int cursor_y, 
04642         int drag_start,
04643         int button_press,
04644         int &redraw,
04645         int &rerender)
04646 {
04647         Plugin *plugin = 0;
04648         int result = 0;
04649         int done = 0;
04650         int64_t x, y, w, h;
04651         Track *track = 0;
04652 
04653 
04654         if(!mwindow->edl->session->show_assets) return 0;
04655 
04656 
04657         for(track = mwindow->edl->tracks->first;
04658                 track && !done;
04659                 track = track->next)
04660         {
04661                 if(!track->expand_view) continue;
04662 
04663 
04664                 for(int i = 0; i < track->plugin_set.total && !done; i++)
04665                 {
04666                         // first check if plugins are visible at all
04667                         if (!track->expand_view)
04668                                 continue;
04669                         PluginSet *plugin_set = track->plugin_set.values[i];
04670                         for(plugin = (Plugin*)plugin_set->first;
04671                                 plugin && !done;
04672                                 plugin = (Plugin*)plugin->next)
04673                         {
04674                                 plugin_dimensions(plugin, x, y, w, h);
04675                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
04676                                         MWindowGUI::visible(y, y + h, 0, get_h()))
04677                                 {
04678                                         if(cursor_x >= x && cursor_x < x + w &&
04679                                                 cursor_y >= y && cursor_y < y + h)
04680                                         {
04681                                                 done = 1;
04682                                                 break;
04683                                         }
04684                                 }
04685                         }
04686                 }
04687         }
04688 
04689         if(plugin)
04690         {
04691 // Start plugin popup
04692                 if(button_press)
04693                 {
04694                         if(get_buttonpress() == 3)
04695                         {
04696                                 gui->plugin_menu->update(plugin);
04697                                 gui->plugin_menu->activate_menu();
04698                                 result = 1;
04699                         } 
04700                         else
04701 // Select range of plugin on doubleclick over plugin
04702                         if (get_double_click() && !drag_start)
04703                         {
04704                                 mwindow->edl->local_session->set_selectionstart(plugin->track->from_units(plugin->startproject));
04705                                 mwindow->edl->local_session->set_selectionend(plugin->track->from_units(plugin->startproject) + 
04706                                         plugin->track->from_units(plugin->length));
04707                                 if(mwindow->edl->session->cursor_on_frames) 
04708                                 {
04709                                         mwindow->edl->local_session->set_selectionstart(
04710                                                 mwindow->edl->align_to_frame(mwindow->edl->local_session->get_selectionstart(1), 0));
04711                                         mwindow->edl->local_session->set_selectionend(
04712                                                 mwindow->edl->align_to_frame(mwindow->edl->local_session->get_selectionend(1), 1));
04713                                 }
04714                                 rerender = 1;
04715                                 redraw = 1;
04716                                 result = 1;
04717                         }
04718                 }
04719                 else
04720 // Move plugin
04721                 if(drag_start && plugin->track->record)
04722                 {
04723                         if(mwindow->edl->session->editing_mode == EDITING_ARROW)
04724                         {
04725                                 if(plugin->track->data_type == TRACK_AUDIO)
04726                                         mwindow->session->current_operation = DRAG_AEFFECT_COPY;
04727                                 else
04728                                 if(plugin->track->data_type == TRACK_VIDEO)
04729                                         mwindow->session->current_operation = DRAG_VEFFECT_COPY;
04730 
04731                                 mwindow->session->drag_plugin = plugin;
04732 
04733 
04734 
04735 
04736 
04737 // Create picon
04738                                 switch(plugin->plugin_type)
04739                                 {
04740                                         case PLUGIN_STANDALONE:
04741                                         {
04742                                                 PluginServer *server = mwindow->scan_plugindb(
04743                                                         plugin->title,
04744                                                         plugin->track->data_type);
04745                                                 if (server) 
04746                                                 {
04747                                                         VFrame *frame = server->picon;
04748 //printf("TrackCanvas::test_plugins 7\n");
04749                                                         drag_popup = new BC_DragWindow(gui, 
04750                                                                 frame, 
04751                                                                 get_abs_cursor_x(0) - frame->get_w() / 2,
04752                                                                 get_abs_cursor_y(0) - frame->get_h() / 2);
04753                                                 }
04754                                                 break;
04755                                         }
04756                                         
04757                                         case PLUGIN_SHAREDPLUGIN:
04758                                         case PLUGIN_SHAREDMODULE:
04759                                                 drag_popup = new BC_DragWindow(gui, 
04760                                                         mwindow->theme->get_image("clip_icon"), 
04761                                                         get_abs_cursor_x(0) - mwindow->theme->get_image("clip_icon")->get_w() / 2,
04762                                                         get_abs_cursor_y(0) - mwindow->theme->get_image("clip_icon")->get_h() / 2);
04763                                                 break;
04764                                 }
04765 
04766 
04767                                 result = 1;
04768                         }
04769                 }
04770         }
04771 
04772         return result;
04773 }
04774 
04775 int TrackCanvas::do_transitions(int cursor_x, 
04776         int cursor_y, 
04777         int button_press,
04778         int &new_cursor,
04779         int &update_cursor)
04780 {
04781         Transition *transition = 0;
04782         int result = 0;
04783         int64_t x, y, w, h;
04784 
04785 
04786 
04787         if(!mwindow->edl->session->show_assets ||
04788                 !mwindow->edl->session->auto_conf->transitions) return 0;
04789                                         
04790 
04791 
04792         for(Track *track = mwindow->edl->tracks->first;
04793                 track && !result;
04794                 track = track->next)
04795         {
04796                 for(Edit *edit = track->edits->first;
04797                         edit;
04798                         edit = edit->next)
04799                 {
04800                         if(edit->transition)
04801                         {
04802                                 edit_dimensions(edit, x, y, w, h);
04803                                 get_transition_coords(x, y, w, h);
04804 
04805                                 if(MWindowGUI::visible(x, x + w, 0, get_w()) &&
04806                                         MWindowGUI::visible(y, y + h, 0, get_h()))
04807                                 {
04808                                         if(cursor_x >= x && cursor_x < x + w &&
04809                                                 cursor_y >= y && cursor_y < y + h)
04810                                         {
04811                                                 transition = edit->transition;
04812                                                 result = 1;
04813                                                 break;
04814                                         }
04815                                 }
04816                         }
04817                 }
04818         }
04819         
04820         update_cursor = 1;
04821         if(transition)
04822         {
04823                 if(!button_press)
04824                 {
04825                         new_cursor = UPRIGHT_ARROW_CURSOR;
04826                 }
04827                 else
04828                 if(get_buttonpress() == 3)
04829                 {
04830                         gui->transition_menu->update(transition);
04831                         gui->transition_menu->activate_menu();
04832                 }
04833         }
04834 
04835         return result;
04836 }
04837 
04838 int TrackCanvas::button_press_event()
04839 {
04840         int result = 0;
04841         int cursor_x, cursor_y;
04842         int new_cursor, update_cursor;
04843 
04844         cursor_x = get_cursor_x();
04845         cursor_y = get_cursor_y();
04846         mwindow->session->trim_edits = 0;
04847 
04848         if(is_event_win() && cursor_inside())
04849         {
04850                 double position = (double)cursor_x * 
04851                         mwindow->edl->local_session->zoom_sample /
04852                         mwindow->edl->session->sample_rate + 
04853                         (double)mwindow->edl->local_session->view_start * 
04854                         mwindow->edl->local_session->zoom_sample /
04855                         mwindow->edl->session->sample_rate;
04856 
04857 
04858                 if(!active)
04859                 {
04860                         activate();
04861                 }
04862 
04863                 if(get_buttonpress() == 1)
04864                 {
04865                         gui->unlock_window();
04866                         gui->mbuttons->transport->handle_transport(STOP, 1);
04867                         gui->lock_window("TrackCanvas::button_press_event");
04868                 }
04869 
04870                 int update_overlay = 0, update_cursor = 0, rerender = 0;
04871 
04872                 if(get_buttonpress() == 4)
04873                 {
04874                         if(shift_down())
04875                                 mwindow->expand_sample();
04876                         else
04877                                 mwindow->move_up(get_h() / 10);
04878                         result = 1;
04879                 }
04880                 else
04881                 if(get_buttonpress() == 5)
04882                 {
04883                         if(shift_down())
04884                                 mwindow->zoom_in_sample();
04885                         else
04886                                 mwindow->move_down(get_h() / 10);
04887                         result = 1;
04888                 }
04889                 else
04890                 switch(mwindow->edl->session->editing_mode)
04891                 {
04892 // Test handles and resource boundaries and highlight a track
04893                         case EDITING_ARROW:
04894                         {
04895                                 Edit *edit;
04896                                 int handle;
04897                                 if(mwindow->edl->session->auto_conf->transitions && 
04898                                         do_transitions(cursor_x, 
04899                                                 cursor_y, 
04900                                                 1, 
04901                                                 new_cursor, 
04902                                                 update_cursor))
04903                                 {
04904                                         break;
04905                                 }
04906                                 else
04907                                 if(do_keyframes(cursor_x, 
04908                                         cursor_y, 
04909                                         0, 
04910                                         get_buttonpress(), 
04911                                         new_cursor, 
04912                                         update_cursor,
04913                                         rerender))
04914                                 {
04915                                         break;
04916                                 }
04917                                 else
04918 // Test edit boundaries
04919                                 if(do_edit_handles(cursor_x, 
04920                                         cursor_y, 
04921                                         1, 
04922                                         new_cursor, 
04923                                         update_cursor))
04924                                 {
04925                                         break;
04926                                 }
04927                                 else
04928 // Test plugin boundaries
04929                                 if(do_plugin_handles(cursor_x, 
04930                                         cursor_y, 
04931                                         1, 
04932                                         new_cursor, 
04933                                         update_cursor))
04934                                 {
04935                                         break;
04936                                 }
04937                                 else
04938                                 if(do_edits(cursor_x, cursor_y, 1, 0, update_cursor, rerender, new_cursor, update_cursor))
04939                                 {
04940                                         break;
04941                                 }
04942                                 else
04943                                 if(do_plugins(cursor_x, cursor_y, 0, 1, update_cursor, rerender))
04944                                 {
04945                                         break;
04946                                 }
04947                                 else
04948                                 if(test_resources(cursor_x, cursor_y))
04949                                 {
04950                                         break;
04951                                 }
04952                                 else
04953                                 if(do_tracks(cursor_x, cursor_y, 1))
04954                                 {
04955                                         break;
04956                                 }
04957                                 break;
04958                         }
04959 
04960 // Test handles only and select a region
04961                         case EDITING_IBEAM:
04962                         {
04963 //printf("TrackCanvas::button_press_event %d\n", position);
04964 
04965                                 if(mwindow->edl->session->auto_conf->transitions && 
04966                                         do_transitions(cursor_x, 
04967                                                 cursor_y, 
04968                                                 1, 
04969                                                 new_cursor, 
04970                                                 update_cursor))
04971                                 {
04972                                         break;
04973                                 }
04974                                 else
04975                                 if(do_keyframes(cursor_x, 
04976                                         cursor_y, 
04977                                         0, 
04978                                         get_buttonpress(), 
04979                                         new_cursor, 
04980                                         update_cursor,
04981                                         rerender))
04982                                 {
04983                                         update_overlay = 1;
04984                                         break;
04985                                 }
04986                                 else
04987 // Test edit boundaries
04988                                 if(do_edit_handles(cursor_x, 
04989                                         cursor_y, 
04990                                         1, 
04991                                         new_cursor, 
04992                                         update_cursor))
04993                                 {
04994                                         break;
04995                                 }
04996                                 else
04997 // Test plugin boundaries
04998                                 if(do_plugin_handles(cursor_x, 
04999                                         cursor_y, 
05000                                         1, 
05001                                         new_cursor, 
05002                                         update_cursor))
05003                                 {
05004                                         break;
05005                                 }
05006                                 else
05007                                 if(do_edits(cursor_x, 
05008                                         cursor_y, 
05009                                         1, 
05010                                         0, 
05011                                         update_cursor, 
05012                                         rerender, 
05013                                         new_cursor, 
05014                                         update_cursor))
05015                                 {
05016                                         break;
05017                                 }
05018                                 else
05019                                 if(do_plugins(cursor_x, 
05020                                         cursor_y, 
05021                                         0, 
05022                                         1, 
05023                                         update_cursor, 
05024                                         rerender))
05025                                 {
05026                                         break;
05027                                 }
05028                                 else
05029                                 if(do_tracks(cursor_x, cursor_y, 1))
05030                                 {
05031                                         break;
05032                                 }
05033 // Highlight selection
05034                                 else
05035                                 {
05036                                         rerender = start_selection(position);
05037                                         mwindow->session->current_operation = SELECT_REGION;
05038                                         update_cursor = 1;
05039                                 }
05040 
05041                                 break;
05042                         }
05043                 }
05044 
05045 
05046                 if(rerender)
05047                 {
05048                         gui->unlock_window();
05049                         mwindow->cwindow->update(1, 0, 0, 0, 1);
05050                         gui->lock_window("TrackCanvas::button_press_event 2");
05051 // Update faders
05052                         mwindow->update_plugin_guis();
05053                         gui->patchbay->update();
05054                 }
05055 
05056                 if(update_overlay)
05057                 {
05058                         draw_overlays();
05059                         flash();
05060                 }
05061 
05062                 if(update_cursor)
05063                 {
05064                         gui->timebar->update_highlights();
05065                         gui->cursor->hide();
05066                         gui->cursor->show();
05067                         gui->zoombar->update();
05068                         flash();
05069                         result = 1;
05070                 }
05071 
05072 
05073 
05074         }
05075         return result;
05076 }
05077 
05078 int TrackCanvas::start_selection(double position)
05079 {
05080         int rerender = 0;
05081         position = mwindow->edl->align_to_frame(position, 0);
05082 
05083 // Extend a border
05084         if(shift_down())
05085         {
05086                 double midpoint = (mwindow->edl->local_session->get_selectionstart(1) + 
05087                         mwindow->edl->local_session->get_selectionend(1)) / 2;
05088 
05089                 if(position < midpoint)
05090                 {
05091                         mwindow->edl->local_session->set_selectionstart(position);
05092                         selection_midpoint1 = mwindow->edl->local_session->get_selectionend(1);
05093 // Que the CWindow
05094                         rerender = 1;
05095                 }
05096                 else
05097                 {
05098                         mwindow->edl->local_session->set_selectionend(position);
05099                         selection_midpoint1 = mwindow->edl->local_session->get_selectionstart(1);
05100 // Don't que the CWindow for the end
05101                 }
05102         }
05103         else
05104 // Start a new selection
05105         {
05106 //printf("TrackCanvas::start_selection %f\n", position);
05107                 mwindow->edl->local_session->set_selectionstart(position);
05108                 mwindow->edl->local_session->set_selectionend(position);
05109                 selection_midpoint1 = position;
05110 // Que the CWindow
05111                 rerender = 1;
05112         }
05113         
05114         return rerender;
05115 }
05116 
05117 void TrackCanvas::end_edithandle_selection()
05118 {
05119         mwindow->modify_edithandles();
05120 }
05121 
05122 void TrackCanvas::end_pluginhandle_selection()
05123 {
05124         mwindow->modify_pluginhandles();
05125 }
05126 
05127 
05128 double TrackCanvas::time_visible()
05129 {
05130         return (double)get_w() * 
05131                 mwindow->edl->local_session->zoom_sample / 
05132                 mwindow->edl->session->sample_rate;
05133 }
05134 
05135 
05136 
05137 
05138 
05139 
05140 
05141 
05142 
05143 
05144 
05145 
05146 
05147 
05148 
05149 
05150 
05151 
05152 
05153 
05154 
05155 
05156 
05157 
05158 
05159 
05160 
05161 
05162 
05163 
05164 
05165 
05166 
05167 
05168 
05169 
05170 
05171 
05172 
05173 
05174 
05175 void TrackCanvas::draw_automation()
05176 {
05177 }
05178 
05179 
05180 int TrackCanvas::set_index_file(int flash, Asset *asset)
05181 {
05182         return 0;
05183 }
05184 
05185 
05186 int TrackCanvas::button_release()
05187 {
05188         return 0;
05189 }
05190 
05191 
05192 int TrackCanvas::auto_reposition(int &cursor_x, int &cursor_y, int64_t cursor_position)
05193 {
05194         return 0;
05195 }
05196 
05197 
05198 int TrackCanvas::draw_floating_handle(int flash)
05199 {
05200         return 0;
05201 }
05202 
05203 int TrackCanvas::draw_loop_point(int64_t position, int flash)
05204 {
05205         return 0;
05206 }
05207 
05208 int TrackCanvas::draw_playback_cursor(int pixel, int flash)
05209 {
05210         return 0;
05211 }
05212 
05213 
05214 int TrackCanvas::update_handle_selection(int64_t cursor_position)
05215 {
05216         return 0;
05217 }
05218 
05219 int TrackCanvas::end_translation()
05220 {
05221         return 0;
05222 }
05223 

Generated on Sun Jan 8 13:39:01 2006 for Cinelerra-svn by  doxygen 1.4.4