remove whitespace at eol
[goodguy/history.git] / cinelerra-5.1 / cinelerra / trackcanvas.C
index 28f149f351ff84f7830e8ed2035e975aa59f5800..9f596c26ae7c2cf91457bf561118b902fe72ebfd 100644 (file)
@@ -38,6 +38,7 @@
 #include "edlsession.h"
 #include "floatauto.h"
 #include "floatautos.h"
+#include "gwindowgui.h"
 #include "indexstate.h"
 #include "intauto.h"
 #include "intautos.h"
@@ -185,7 +186,7 @@ int TrackCanvas::drag_motion(Track **over_track,
        int cursor_y = get_relative_cursor_y();
 
        if( get_cursor_over_window() &&
-               cursor_x >= 0 && cursor_y >= 0 && 
+               cursor_x >= 0 && cursor_y >= 0 &&
                cursor_x < get_w() && cursor_y < get_h() )
        {
 //printf("TrackCanvas::drag_motion %d %d\n", __LINE__, pane->number);
@@ -203,15 +204,24 @@ int TrackCanvas::drag_motion(Track **over_track,
                                {
                                        int64_t edit_x, edit_y, edit_w, edit_h;
                                        edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
-
-                                       if(cursor_x >= edit_x &&
-                                               cursor_y >= edit_y &&
-                                               cursor_x < edit_x + edit_w &&
-                                               cursor_y < edit_y + edit_h)
-                                       {
+                                       if( cursor_y < edit_y || cursor_y >= edit_y + edit_h ) continue;
+                                       if( cursor_x >= edit_x && cursor_x < edit_x + edit_w ) {
                                                *over_edit = edit;
                                                break;
                                        }
+                                       if( edit != track->edits->last ) continue;
+                                       if( mwindow->session->current_operation != DRAG_ATRANSITION &&
+                                           mwindow->session->current_operation != DRAG_VTRANSITION ) continue;
+                                       if( !edit->silence() ) {
+                                               // add silence to allow drag transition past last edit
+                                               //  will be deleted by Edits::optimize if not used
+                                               double length = mwindow->edl->session->default_transition_length;
+                                               int64_t start = edit->startproject+edit->length;
+                                               int64_t units = track->to_units(length, 1);
+                                               track->edits->create_silence(start, start+units);
+                                               continue;
+                                       }
+                                       if( cursor_x >= edit_x ) { *over_edit = edit; break; }
                                }
 
                                for(int i = 0; i < track->plugin_set.total; i++)
@@ -244,7 +254,7 @@ int TrackCanvas::drag_motion(Track **over_track,
        }
 
         if( !*over_track )
-               *over_track = pane->is_over_patchbay();
+               *over_track = pane->over_patchbay();
 
        return 0;
 }
@@ -272,7 +282,7 @@ int TrackCanvas::drag_stop(int *redraw)
                    (cursor_y = get_relative_cursor_y()) >= 0 && cursor_y < get_h() )
                        over_window = 1;
                else {
-                       Track *track = pane->is_over_patchbay();
+                       Track *track = pane->over_patchbay();
                        if( track && mwindow->session->track_highlighted == track )
                                over_window = 1;
                }
@@ -383,7 +393,7 @@ int TrackCanvas::drag_stop(int *redraw)
                                double asset_duration = 0;
                                int64_t asset_length_units = 0;
                                int64_t position = 0;
-                                       
+
                                if(mwindow->session->current_operation == DRAG_ASSET &&
                                        mwindow->session->drag_assets->total) {
                                        Indexable *indexable = mwindow->session->drag_assets->values[0];
@@ -395,8 +405,8 @@ int TrackCanvas::drag_stop(int *redraw)
                                                if (video_length < 0) {
                                                        if(mwindow->edl->session->si_useduration)
                                                                video_length = mwindow->edl->session->si_duration;
-                                                       else    
-                                                               video_length = 1.0 / mwindow->edl->session->frame_rate ; 
+                                                       else
+                                                               video_length = 1.0 / mwindow->edl->session->frame_rate ;
                                                }
                                                asset_duration = video_length / indexable->get_frame_rate();
                                        }
@@ -418,14 +428,14 @@ int TrackCanvas::drag_stop(int *redraw)
                                else {
                                        printf("DRAG_ASSET error: Asset dropped, but both drag_clips and drag_assets total is zero\n");
                                }
-                       
+
                                asset_length_units = mwindow->session->track_highlighted->to_units(asset_duration, 1);
                                position = drop_edit_position (&insertion, NULL, asset_length_units);
                                if( position == -1 ) {
                                        result = 1;
                                        break;          // Do not do anything
                                }
-                               
+
                                double position_f = mwindow->session->track_highlighted->from_units(position);
                                Track *track = mwindow->session->track_highlighted;
 
@@ -433,7 +443,7 @@ int TrackCanvas::drag_stop(int *redraw)
 //                                     // FIXME, we should create an mwindow/EDL method that overwrites, without clearing the keyframes and autos
 //                                     // Unfortunately, this is _a lot_ of work to do right
 //                                     printf("Problematic insertion\n");
-//                                     mwindow->edl->tracks->clear(position_f, 
+//                                     mwindow->edl->tracks->clear(position_f,
 //                                             position_f + asset_duration, 0);
 //                             }
                                mwindow->paste_assets(position_f, track, !insertion);
@@ -454,7 +464,7 @@ int TrackCanvas::drag_stop(int *redraw)
                                                result = 1;
                                                break;          // Do not do anything
                                        }
-                                       
+
                                        double position_f = mwindow->session->track_highlighted->from_units(position);
                                        Track *track = mwindow->session->track_highlighted;
                                        mwindow->move_edits(mwindow->session->drag_edits,
@@ -1088,9 +1098,9 @@ void TrackCanvas::draw_paste_destination()
                                }
 
 // Get the x coordinate
-                               x = Units::to_int64(position * 
+                               x = Units::to_int64(position *
                                        mwindow->edl->session->sample_rate /
-                                       mwindow->edl->local_session->zoom_sample) - 
+                                       mwindow->edl->local_session->zoom_sample) -
                                        mwindow->edl->local_session->view_start[pane->number];
 
                                double paste_position = -1.;
@@ -1842,41 +1852,34 @@ void TrackCanvas::draw_loop_points()
 //printf("TrackCanvas::draw_loop_points 7\n");
 }
 
-void TrackCanvas::draw_brender_start()
+void TrackCanvas::draw_brender_range()
 {
        if(mwindow->preferences->use_brender)
        {
-               int64_t x = Units::round(mwindow->edl->session->brender_start *
+               int64_t x1 = Units::round(mwindow->edl->session->brender_start *
+                       mwindow->edl->session->sample_rate /
+                       mwindow->edl->local_session->zoom_sample -
+                       mwindow->edl->local_session->view_start[pane->number]);
+               if(MWindowGUI::visible(x1, x1 + 1, 0, get_w()))
+               {
+                       set_color(RED);
+                       draw_line(x1, 0, x1, get_h());
+               }
+               int64_t x2 = Units::round(mwindow->edl->session->brender_end *
                        mwindow->edl->session->sample_rate /
                        mwindow->edl->local_session->zoom_sample -
                        mwindow->edl->local_session->view_start[pane->number]);
 
-               if(MWindowGUI::visible(x, x + 1, 0, get_w()))
+               if(MWindowGUI::visible(x2, x2 + 1, 0, get_w()))
                {
                        set_color(RED);
-                       draw_line(x, 0, x, get_h());
+                       draw_line(x2, 0, x2, get_h());
                }
        }
 }
 
-static int auto_colors[AUTOMATION_TOTAL] =
-{
-       BLUE,
-       RED,
-       GREEN,
-       BLUE,
-       RED,
-       GREEN,
-       BLUE,
-       WHITE,
-       0,
-       0,
-       0,
-       WHITE
-};
-
 // The operations which correspond to each automation type
-static int auto_operations[AUTOMATION_TOTAL] =
+int TrackCanvas::auto_operations[AUTOMATION_TOTAL] =
 {
        DRAG_MUTE,
        DRAG_CAMERA_X,
@@ -1976,25 +1979,25 @@ int TrackCanvas::do_keyframes(int cursor_x,
                                                int grouptype = automation.autogrouptype(i, track);
                                                if(draw) // Do dropshadow
                                                        result = do_float_autos(track, autos,
-                                                               cursor_x, cursor_y, draw, 
+                                                               cursor_x, cursor_y, draw,
                                                                buttonpress, 1, 1, MDGREY,
                                                                auto_keyframe, grouptype);
 
                                                result = do_float_autos(track, autos,
-                                                       cursor_x, cursor_y, draw, 
-                                                       buttonpress, 0, 0, auto_colors[i],
+                                                       cursor_x, cursor_y, draw, buttonpress,
+                                                       0, 0, GWindowGUI::auto_colors[i],
                                                        auto_keyframe, grouptype);
                                                break; }
 
                                        case Autos::AUTOMATION_TYPE_INT: {
                                                if(draw) // Do dropshadow
                                                        result = do_int_autos(track, autos,
-                                                               cursor_x, cursor_y, draw, 
+                                                               cursor_x, cursor_y, draw,
                                                                buttonpress, 1, 1, MDGREY,
                                                                auto_keyframe);
                                                result = do_int_autos(track, autos,
-                                                       cursor_x, cursor_y, draw, 
-                                                       buttonpress, 0, 0, auto_colors[i],
+                                                       cursor_x, cursor_y, draw, buttonpress,
+                                                       0, 0, GWindowGUI::auto_colors[i],
                                                        auto_keyframe);
                                                break; }
                                        }
@@ -2014,7 +2017,7 @@ int TrackCanvas::do_keyframes(int cursor_x,
                                        {
                                                if (buttonpress != 3)
                                                {
-                                                       if(i == AUTOMATION_FADE)
+                                                       if(i == AUTOMATION_FADE || i == AUTOMATION_SPEED)
                                                                synchronize_autos(0,
                                                                        track,
                                                                        (FloatAuto*)mwindow->session->drag_auto,
@@ -2031,6 +2034,12 @@ int TrackCanvas::do_keyframes(int cursor_x,
                                                        gui->keyframe_menu->activate_menu();
                                                        rerender = 1; // the position changes
                                                }
+                                               else if( autos )
+                                               {
+                                                       gui->keyframe_hide->update(autos);
+                                                       gui->keyframe_hide->activate_menu();
+                                                       rerender = 1; // the position changes
+                                               }
                                                if(buttonpress == 1 && ctrl_down() &&
                                                   AUTOMATION_TYPE_FLOAT == autos->get_type())
                                                        rerender = 1; // special case: curve mode changed
@@ -2085,6 +2094,45 @@ int TrackCanvas::do_keyframes(int cursor_x,
        return result;
 }
 
+void TrackCanvas::draw_keyframe_reticle()
+{
+       int keyframe_hairline = mwindow->preferences->keyframe_reticle;
+       if( keyframe_hairline == HAIRLINE_NEVER ) return;
+
+       int current_op = mwindow->session->current_operation, dragging = 0;
+       for( int i=0; !dragging && i<AUTOMATION_TOTAL; ++i )
+               if( current_op == auto_operations[i] ) dragging = 1;
+
+       if( keyframe_hairline == HAIRLINE_DRAGGING && dragging ) {
+               if( mwindow->session->drag_auto && get_buttonpress() == 1 ) {
+                       draw_hairline(mwindow->session->drag_auto, RED);
+                       return;
+               }
+       }
+
+       if( keyframe_hairline == HAIRLINE_ALWAYS || ( get_buttonpress() == 2 &&
+           keyframe_hairline == HAIRLINE_DRAGGING && dragging ) ) {
+               for( Track *track = mwindow->edl->tracks->first; track;
+                    track=track->next ) {
+                       Automation *automation = track->automation;
+                       for( int i=0; i<AUTOMATION_TOTAL; ++i ) {
+                               if( !mwindow->edl->session->auto_conf->autos[i] ) continue;
+                               // automation visible
+                               Autos *autos = automation->autos[i];
+                               if( !autos ) continue;
+                               for( Auto *auto_keyframe=autos->first; auto_keyframe;
+                                    auto_keyframe = auto_keyframe->next ) {
+                                       draw_hairline(auto_keyframe, GREEN);
+                               }
+                       }
+
+                       if( dragging && mwindow->session->drag_auto ) {
+                               draw_hairline(mwindow->session->drag_auto, RED);
+                       }
+               }
+       }
+}
+
 void TrackCanvas::draw_auto(Auto *current,
        int x,
        int y,
@@ -2152,14 +2200,14 @@ void TrackCanvas::draw_cropped_line(int x1,
 }
 
 
-void TrackCanvas::draw_floatauto(FloatAuto *current, 
-       int x, 
-       int y, 
-       int in_x, 
-       int in_y, 
-       int out_x, 
-       int out_y, 
-       int center_pixel, 
+void TrackCanvas::draw_floatauto(FloatAuto *current,
+       int x,
+       int y,
+       int in_x,
+       int in_y,
+       int out_x,
+       int out_y,
+       int center_pixel,
        int zoom_track,
        int color)
 {
@@ -2180,7 +2228,7 @@ void TrackCanvas::draw_floatauto(FloatAuto *current,
                draw_box(x1, y1, x2 - x1, y2 - y1);
        }
 
-// show bezier control points (only) if this 
+// show bezier control points (only) if this
 // floatauto doesn't adjust it's tangents automatically
        if(current->curve_mode != FloatAuto::FREE &&
           current->curve_mode != FloatAuto::TFREE)
@@ -2208,22 +2256,22 @@ inline void TrackCanvas::draw_floatauto_ctrlpoint(
 
        y    += center_pixel;
        cp_y += center_pixel;
-       
+
        // drawing the tangent as a dashed line...
        int const dash = HANDLE_W;
        int const gap  = HANDLE_W / 2;
        float sx = 3 * (cp_x - x) / 4.;
        float ex = 0;
-       
+
        // q is the x displacement for a unit line of slope
        float q = (sx > 0 ? 1 : -1) / sqrt(1 + slope * slope);
-       
+
        float dist = 1/q * sx;
        if( dist > dash )
                ex = sx - q * dash;
-       
+
        set_color(color);
-       do {    
+       do {
                float sy = slope * sx, ey = slope * ex;
                draw_line(quantize(sx + x), quantize(sy + y), quantize(ex + x), quantize(ey + y));
                sx = ex - q * gap;
@@ -2306,13 +2354,12 @@ inline float test_curve_line( int x0, int y0, int ctrl_x, int ctrl_y,
 }
 
 
-inline 
+inline
 float levered_position(float position, float ref_pos)
 {
-       if( 1e-6 > fabs(ref_pos) || isnan(ref_pos)) 
+       if( 1e-6 > fabs(ref_pos) || isnan(ref_pos))
                return 0.0;
-       else 
-               return ref_pos / position;
+       return ref_pos / position;
 }
 
 
@@ -2324,16 +2371,15 @@ float TrackCanvas::value_to_percentage(float auto_value, int autogrouptype)
        float automation_min = mwindow->edl->local_session->automation_mins[autogrouptype];
        float automation_max = mwindow->edl->local_session->automation_maxs[autogrouptype];
        float automation_range = automation_max - automation_min;
-       if(0 == automation_range || isnan(auto_value) || isinf(auto_value))
+       if( 0 >= automation_range || isnan(auto_value) || isinf(auto_value) )
                return 0;
-       else
-               return (auto_value - automation_min) / automation_range;
+       return (auto_value - automation_min) / automation_range;
 }
 
 
 
 int TrackCanvas::test_floatauto(FloatAuto *current, int x, int y, int in_x,
-       int in_y, int out_x, int out_y, int center_pixel, int zoom_track, 
+       int in_y, int out_x, int out_y, int center_pixel, int zoom_track,
        int cursor_x, int cursor_y, int buttonpress, int autogrouptype)
 {
        int result = 0;
@@ -2384,7 +2430,7 @@ int TrackCanvas::test_floatauto(FloatAuto *current, int x, int y, int in_x,
                if( WITHIN(x1,x2,y1,y2))
                {       // cursor hits node
                        result = 1;
-                       
+
                        if(buttonpress && (buttonpress != 3))
                        {
                                INIT_DRAG(current->position, value_to_percentage(current->get_value(), autogrouptype))
@@ -2401,13 +2447,13 @@ int TrackCanvas::test_floatauto(FloatAuto *current, int x, int y, int in_x,
                                // could be ctrl-click or ctrl-drag
                                // click would cycle through tangent modes
                                ((FloatAuto*)current)->toggle_curve_mode();
-                               
+
                                // drag will start dragging the tangent, if applicable
                                INIT_DRAG(current->position, value_to_percentage(current->get_value(), autogrouptype))
                                mwindow->session->drag_handle = 0;
                        }
                }
-                       
+
                float lever = 0.0; // we use the tangent as a draggable lever. 1.0 is at the ctrl point
 
 // Test in control
@@ -2456,8 +2502,8 @@ int TrackCanvas::test_floatauto(FloatAuto *current, int x, int y, int in_x,
 #undef WITHIN
 #undef INIT_DRAG
 
-// if(buttonpress) 
-// 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", 
+// if(buttonpress)
+// 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",
 // mwindow->session->drag_handle,
 // ctrl_down(),
 // cursor_x,
@@ -2508,7 +2554,7 @@ void TrackCanvas::draw_floatline(int center_pixel,
 
 // Not using slope intercept
        x1 = MAX(0, x1);
-       int prev_y = y1;
+       int prev_y = y1 + center_pixel;
 
 
 // Call by reference fails for some reason here
@@ -2531,6 +2577,7 @@ void TrackCanvas::draw_floatline(int center_pixel,
 // (int)(center_pixel - yscale / 2),
 // (int)(center_pixel + yscale / 2 - 1));
 
+//printf("draw_line(%d,%d,  %d,%d)\n", x - 1, prev_y  , x, y);
                        draw_line(x - 1, prev_y  , x, y   );
                }
                prev_y = y;
@@ -2580,7 +2627,10 @@ int TrackCanvas::test_floatline(int center_pixel,
                {
                        Auto *current;
                        mwindow->undo->update_undo_before();
-                       current = mwindow->session->drag_auto = autos->insert_auto(position1);
+                       double position = autos->track->from_units(position1);
+                       position = mwindow->edl->align_to_frame(position, 0);
+                       int64_t new_position = autos->track->to_units(position,0);
+                       current = mwindow->session->drag_auto = autos->insert_auto(new_position);
                        ((FloatAuto*)current)->set_value(value);
                        mwindow->session->drag_start_percentage = value_to_percentage(value, autogrouptype);
                        mwindow->session->drag_start_position = current->position;
@@ -2596,71 +2646,62 @@ int TrackCanvas::test_floatline(int center_pixel,
 
 
 void TrackCanvas::synchronize_autos(float change,
-       Track *skip,
-       FloatAuto *fauto,
-       int fill_gangs)
+               Track *skip, FloatAuto *fauto, int fill_gangs)
 {
 // Handles the special case of modifying a fadeauto
 // when there are ganged faders on several tracks
 // (skip and fauto may be NULL if fill_gangs==-1)
-       if (fill_gangs == 1 && skip->gang)
-       {
-               for(Track *current = mwindow->edl->tracks->first;
-                       current;
-                       current = NEXT)
-               {
-                       if(current->data_type == skip->data_type &&
-                               current->gang &&
-                               current->record &&
-                               current != skip)
-                       {
-                               FloatAutos *fade_autos = (FloatAutos*)current->automation->autos[AUTOMATION_FADE];
-                               double position = skip->from_units(fauto->position);
-                               FloatAuto *previous = 0, *next = 0;
-
-                               float init_value = fade_autos->get_value(fauto->position, PLAY_FORWARD, previous, next);
-                               FloatAuto *keyframe;
-                               keyframe = (FloatAuto*)fade_autos->get_auto_at_position(position);
 
-                               if (!keyframe)
-                               {
+       if( fill_gangs > 0 && skip->gang ) {
+               double position = skip->from_units(fauto->position);
+               int autoidx = fauto->autos->autoidx;
+
+               for(Track *current = mwindow->edl->tracks->first; current; current = NEXT) {
+                       if( (current->data_type == skip->data_type || get_double_click()) &&
+                           current->gang && current->record && current != skip ) {
+                               int64_t current_position = current->to_units(position, 1);
+                               FloatAutos *fade_autos = (FloatAutos*)current->automation->autos[autoidx];
+                               float auto_min = mwindow->edl->local_session->automation_mins[fade_autos->autogrouptype];
+                               float auto_max = mwindow->edl->local_session->automation_maxs[fade_autos->autogrouptype];
+                               FloatAuto *previous = 0, *next = 0;
+                               FloatAuto *keyframe = (FloatAuto*)fade_autos->get_auto_at_position(current_position);
+                               if( !keyframe ) {
 // create keyframe on neighbouring track at the point in time given by fauto
-                                       keyframe = (FloatAuto*)fade_autos->insert_auto(fauto->position);
-                                       keyframe->set_value(init_value + change);
+                                       float init_value = fade_autos->get_value(current_position, PLAY_FORWARD, previous, next);
+                                       float new_value = init_value + change;
+                                       CLAMP(new_value, auto_min, auto_max);
+                                       keyframe = (FloatAuto*)fade_autos->insert_auto(current_position);
+                                       keyframe->set_value(new_value);
                                }
-                               else
-                               {
+                               else {
 // keyframe exists, just change it
-                                       keyframe->adjust_to_new_coordinates(fauto->position, keyframe->get_value() + change);
+                                       float new_value = keyframe->get_value() + change;
+                                       CLAMP(new_value, auto_min, auto_max);
+                                       keyframe->adjust_to_new_coordinates(current_position, new_value);
 // need to (re)set the position, as the existing node could be on a "equivalent" position (within half a frame)
                                }
 
                                mwindow->session->drag_auto_gang->append((Auto *)keyframe);
                        }
                }
-       } else
-// move the gangs
-       if (fill_gangs == 0)
-       {
-// Move the gang!
-               for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++)
-               {
+       }
+       else if( !fill_gangs ) {
+               double position = skip->from_units(fauto->position);
+// Move the gangs
+               for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++) {
                        FloatAuto *keyframe = (FloatAuto *)mwindow->session->drag_auto_gang->values[i];
-
+                       int64_t keyframe_position = keyframe->autos->track->to_units(position, 1);
                        float new_value = keyframe->get_value() + change;
                        CLAMP(new_value,
                              mwindow->edl->local_session->automation_mins[keyframe->autos->autogrouptype],
                              mwindow->edl->local_session->automation_maxs[keyframe->autos->autogrouptype]);
-                       keyframe->adjust_to_new_coordinates(fauto->position, new_value);
+                       keyframe->adjust_to_new_coordinates(keyframe_position, new_value);
                }
 
        }
-       else
+       else {
 // remove the gangs
-       if (fill_gangs == -1)
-       {
-               for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++)
-               {
+               for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++) {
                        FloatAuto *keyframe = (FloatAuto *)mwindow->session->drag_auto_gang->values[i];
                        keyframe->autos->remove_nonsequential(
                                        keyframe);
@@ -2864,10 +2905,10 @@ int TrackCanvas::do_float_autos(Track *track, Autos *autos, int cursor_x, int cu
                 autos->first ? autos->first : autos->default_auto;
 
        double ax = 0, ay = 0, ax2 = 0, ay2 = 0;
-       if( first_auto )
+       if( first_auto ) {
                calculate_auto_position(&ax, &ay, 0, 0, 0, 0,
                        first_auto, unit_start, zoom_units, yscale, autogrouptype);
-
+       }
        if( current )
                current = NEXT;
        else {
@@ -2950,7 +2991,7 @@ int TrackCanvas::do_float_autos(Track *track, Autos *autos, int cursor_x, int cu
                                (int)ax, (int)ax2, cursor_x, cursor_y,
                                buttonpress, autogrouptype);
                }
-               if( draw ) 
+               if( draw )
                        draw_floatline(center_pixel,
                                (FloatAuto*)previous, (FloatAuto*)current,
                                (FloatAutos*)autos, unit_start, zoom_units, yscale,
@@ -3332,6 +3373,28 @@ int TrackCanvas::do_plugin_autos(Track *track, int cursor_x, int cursor_y,
        return result;
 }
 
+int TrackCanvas::draw_hairline(Auto *auto_keyframe, int color)
+{
+       Track *track = auto_keyframe->autos->track;
+       int autogrouptype = auto_keyframe->autos->get_type();
+
+       int center_pixel;
+       double view_start, unit_start;
+       double view_end, unit_end, yscale;
+       double zoom_sample, zoom_units;
+
+       calculate_viewport(track, view_start, unit_start, view_end, unit_end,
+                       yscale, center_pixel, zoom_sample, zoom_units);
+
+       double ax = 0, ay = 0;
+       calculate_auto_position(&ax, &ay, 0, 0, 0, 0,
+               auto_keyframe, unit_start, zoom_units, yscale, autogrouptype);
+
+       set_color(color);
+       draw_line(ax, 0, ax, get_h());
+       return 0;
+}
+
 void TrackCanvas::draw_overlays()
 {
        int new_cursor, update_cursor, rerender;
@@ -3356,7 +3419,7 @@ void TrackCanvas::draw_overlays()
 
 // Loop points
        draw_loop_points();
-       draw_brender_start();
+       draw_brender_range();
 
 // Highlighted areas
        draw_highlighting();
@@ -3373,6 +3436,8 @@ void TrackCanvas::draw_overlays()
 // Playback cursor
        draw_playback_cursor();
 
+       draw_keyframe_reticle();
+
        show_window(0);
 }
 
@@ -3485,36 +3550,22 @@ int TrackCanvas::get_drag_values(float *percentage,
 
 
 #define UPDATE_DRAG_HEAD(do_clamp) \
-       int result = 0; \
+       int result = 0, center_pixel; \
        if(!current->autos->track->record) return 0; \
-       double view_start; \
-       double unit_start; \
-       double view_end; \
-       double unit_end; \
-       double yscale; \
-       int center_pixel; \
-       double zoom_sample; \
-       double zoom_units; \
+       double view_start, unit_start, view_end, unit_end; \
+       double yscale, zoom_sample, zoom_units; \
  \
        calculate_viewport(current->autos->track,  \
-               view_start, \
-               unit_start, \
-               view_end, \
-               unit_end, \
-               yscale, \
-               center_pixel, \
-               zoom_sample, \
-               zoom_units); \
+               view_start, unit_start, view_end, unit_end, \
+               yscale, center_pixel, zoom_sample, zoom_units); \
  \
        float percentage = (float)(mwindow->session->drag_origin_y - cursor_y) / \
-               yscale +  \
-               mwindow->session->drag_start_percentage; \
+               yscale +  mwindow->session->drag_start_percentage; \
        if(do_clamp) CLAMP(percentage, 0, 1); \
  \
        int64_t position = Units::to_int64(zoom_units * \
                (cursor_x - mwindow->session->drag_origin_x) + \
                mwindow->session->drag_start_position); \
- \
        if((do_clamp) && position < 0) position = 0;
 
 
@@ -3523,119 +3574,99 @@ int TrackCanvas::update_drag_floatauto(int cursor_x, int cursor_y)
        FloatAuto *current = (FloatAuto*)mwindow->session->drag_auto;
 
        UPDATE_DRAG_HEAD(mwindow->session->drag_handle == 0);
-       int x = cursor_x - mwindow->session->drag_origin_x; \
-       int y = cursor_y - mwindow->session->drag_origin_y; \
-
-       float value;
-       float old_value;
+       int x = cursor_x - mwindow->session->drag_origin_x;
+       int y = cursor_y - mwindow->session->drag_origin_y;
+       float value, old_value;
+
+       if( mwindow->session->drag_handle == 0 && (ctrl_down() && !shift_down()) ) {
+// not really editing the node, rather start editing the curve
+// tangent is editable and drag movement is significant
+               if( (FloatAuto::FREE == current->curve_mode ||
+                    FloatAuto::TFREE==current->curve_mode) &&
+                   (fabs(x) > HANDLE_W / 2 || fabs(y) > HANDLE_W / 2))
+                       mwindow->session->drag_handle = x < 0 ? 1 : 2;
+       }
 
-       switch(mwindow->session->drag_handle)
-       {
-// Center
-               case 0:
-                       if(ctrl_down())
-                       // not really editing the node, rather start editing the curve
-                       {
-                               // tangent is editable and drag movement is significant
-                               if( (FloatAuto::FREE == current->curve_mode ||
-                                    FloatAuto::TFREE==current->curve_mode) &&                                          
-                                   (fabs(x) > HANDLE_W / 2 || fabs(y) > HANDLE_W / 2))
-                                       mwindow->session->drag_handle = x < 0 ? 1 : 2;
-                               break;
-                       }
+       switch(mwindow->session->drag_handle) {
+       case 0: // Center
 // Snap to nearby values
-                       old_value = current->get_value();
-                       if(shift_down())
-                       {
-                               double value1;
-                               double distance1;
-                               double value2;
-                               double distance2;
+               old_value = current->get_value();
+               if(shift_down()) {
+                       double value1, value2, distance1, distance2;
 
-                               if(current->previous)
-                               {
-                                       int autogrouptype = current->previous->autos->autogrouptype;
-                                       value = percentage_to_value(percentage, 0, 0, autogrouptype);
-                                       value1 = ((FloatAuto*)current->previous)->get_value();
-                                       distance1 = fabs(value - value1);
-                                       current->set_value(value1);
-                               }
-
-                               if(current->next)
-                               {
-                                       int autogrouptype = current->next->autos->autogrouptype;
-                                       value = percentage_to_value(percentage, 0, 0, autogrouptype);
-                                       value2 = ((FloatAuto*)current->next)->get_value();
-                                       distance2 = fabs(value - value2);
-                                       if(!current->previous || distance2 < distance1)
-                                       {
-                                               current->set_value(value2);
-                                       }
-                               }
+                       if(current->previous) {
+                               int autogrouptype = current->previous->autos->autogrouptype;
+                               value = percentage_to_value(percentage, 0, 0, autogrouptype);
+                               value1 = ((FloatAuto*)current->previous)->get_value();
+                               distance1 = fabs(value - value1);
+                               current->set_value(value1);
+                       }
 
-                               if(!current->previous && !current->next)
-                               {
-                                       current->set_value( ((FloatAutos*)current->autos)->default_);
+                       if(current->next) {
+                               int autogrouptype = current->next->autos->autogrouptype;
+                               value = percentage_to_value(percentage, 0, 0, autogrouptype);
+                               value2 = ((FloatAuto*)current->next)->get_value();
+                               distance2 = fabs(value - value2);
+                               if(!current->previous || distance2 < distance1) {
+                                       current->set_value(value2);
                                }
-                               value = current->get_value();
                        }
-                       else
-                       {
-                               int autogrouptype = current->autos->autogrouptype;
-                               value = percentage_to_value(percentage, 0, 0, autogrouptype);
+
+                       if(!current->previous && !current->next) {
+                               current->set_value( ((FloatAutos*)current->autos)->default_);
                        }
+                       value = current->get_value();
+               }
+               else {
+                       int autogrouptype = current->autos->autogrouptype;
+                       value = percentage_to_value(percentage, 0, 0, autogrouptype);
+               }
 
-                       if(alt_down())
+               if(alt_down() && !shift_down())
 // ALT constrains movement: fixed position, only changing the value
-                               position = mwindow->session->drag_start_position;
+                       position = mwindow->session->drag_start_position;
 
-                       if(value != old_value || position != current->position)
-                       {
-                               result = 1;
-                               float change = value - old_value;               
-                               current->adjust_to_new_coordinates(position, value);
-                               synchronize_autos(change, current->autos->track, current, 0);
-                               show_message(current, 1,", %.2f", current->get_value());
-                       }
-                       break;
+               if(value != old_value || position != current->position) {
+                       result = 1;
+                       float change = value - old_value;
+                       current->adjust_to_new_coordinates(position, value);
+                       synchronize_autos(change, current->autos->track, current, 0);
+                       show_message(current, 1,", %.2f", current->get_value());
+               }
+               break;
 
 // In control
-               case 1:
+       case 1: {
+               int autogrouptype = current->autos->autogrouptype;
+               value = percentage_to_value(percentage, 0, current, autogrouptype);
+               if(value != current->get_control_in_value())
                {
-                       int autogrouptype = current->autos->autogrouptype;
-                       value = percentage_to_value(percentage, 0, current, autogrouptype);
-                       if(value != current->get_control_in_value())
-                       {
-                               result = 1;
-                               // note: (position,value) need not be at the location of the ctrl point,
-                               // but could be somewhere in between on the curve (or even outward or
-                               // on the opposit side). We set the new control point such as
-                               // to point the curve through (position,value)
-                               current->set_control_in_value(
-                                       value * levered_position(position - current->position,
-                                                                current->get_control_in_position()));
-                               synchronize_autos(0, current->autos->track, current, 0);
-                               show_message(current, 1,", %.2f", current->get_control_in_value());
-                       }
+                       result = 1;
+                       // note: (position,value) need not be at the location of the ctrl point,
+                       // but could be somewhere in between on the curve (or even outward or
+                       // on the opposit side). We set the new control point such as
+                       // to point the curve through (position,value)
+                       current->set_control_in_value(
+                               value * levered_position(position - current->position,
+                                                        current->get_control_in_position()));
+                       synchronize_autos(0, current->autos->track, current, 0);
+                       show_message(current, 1,", %.2f", current->get_control_in_value());
                }
-                       break;
+               break; }
 
 // Out control
-               case 2:
-               {
-                       int autogrouptype = current->autos->autogrouptype;
-                       value = percentage_to_value(percentage, 0, current, autogrouptype);
-                       if(value != current->get_control_out_value())
-                       {
-                               result = 1;
-                               current->set_control_out_value(
-                                       value * levered_position(position - current->position,
-                                                                current->get_control_out_position()));
-                               synchronize_autos(0, current->autos->track, current, 0);
-                               show_message(current, 1,", %.2f", current->get_control_out_value());
-                       }
+       case 2: {
+               int autogrouptype = current->autos->autogrouptype;
+               value = percentage_to_value(percentage, 0, current, autogrouptype);
+               if(value != current->get_control_out_value()) {
+                       result = 1;
+                       current->set_control_out_value(
+                               value * levered_position(position - current->position,
+                                                        current->get_control_out_position()));
+                       synchronize_autos(0, current->autos->track, current, 0);
+                       show_message(current, 1,", %.2f", current->get_control_out_value());
                }
-                       break;
+               break; }
        }
 
        return result;
@@ -3674,7 +3705,7 @@ int TrackCanvas::update_drag_auto(int cursor_x, int cursor_y)
 
                double position_f = current->autos->track->from_units(current->position);
                double center_f = (mwindow->edl->local_session->get_selectionstart(1) +
-                       mwindow->edl->local_session->get_selectionend(1)) / 
+                       mwindow->edl->local_session->get_selectionend(1)) /
                        2;
                if(!shift_down())
                {
@@ -3706,7 +3737,7 @@ int TrackCanvas::update_drag_pluginauto(int cursor_x, int cursor_y)
                //PluginAutos *pluginautos = (PluginAutos *)current->autos;
                PluginSet *pluginset;
                Plugin *plugin = 0;
-// figure out the correct pluginset & correct plugin 
+// figure out the correct pluginset & correct plugin
                int found = 0;
                for(int i = 0; i < track->plugin_set.total; i++)
                {
@@ -3718,16 +3749,16 @@ int TrackCanvas::update_drag_pluginauto(int cursor_x, int cursor_y)
                                        currentkeyframe;
                                        currentkeyframe = (KeyFrame *) currentkeyframe->next)
                                {
-                                       if (currentkeyframe == current) 
+                                       if (currentkeyframe == current)
                                        {
                                                found = 1;
                                                break;
                                        }
+
                                }
-                               if (found) break;                       
+                               if (found) break;
                        }
-                       if (found) break;                       
+                       if (found) break;
                }
 
                mwindow->session->plugin_highlighted = plugin;
@@ -3738,7 +3769,7 @@ int TrackCanvas::update_drag_pluginauto(int cursor_x, int cursor_y)
 
                double position_f = current->autos->track->from_units(current->position);
                double center_f = (mwindow->edl->local_session->get_selectionstart(1) +
-                       mwindow->edl->local_session->get_selectionend(1)) / 
+                       mwindow->edl->local_session->get_selectionend(1)) /
                        2;
                if(!shift_down())
                {
@@ -3763,7 +3794,7 @@ void TrackCanvas::update_drag_caption()
        switch(mwindow->session->current_operation)
        {
                case DRAG_FADE:
-                       
+
                        break;
        }
 }
@@ -4687,8 +4718,7 @@ int TrackCanvas::button_press_event()
                        switch(mwindow->edl->session->editing_mode) {
 // Test handles and resource boundaries and highlight a track
                        case EDITING_ARROW: {
-                               if( mwindow->edl->session->auto_conf->transitions &&
-                                       do_transitions(cursor_x, cursor_y,
+                               if( do_transitions(cursor_x, cursor_y,
                                                1, new_cursor, update_cursor) ) break;
 
                                if( do_keyframes(cursor_x, cursor_y,
@@ -4727,8 +4757,7 @@ int TrackCanvas::button_press_event()
                                        mwindow->edl->session->sample_rate;
 //printf("TrackCanvas::button_press_event %d\n", position);
 
-                               if(mwindow->edl->session->auto_conf->transitions &&
-                                       do_transitions(cursor_x, cursor_y,
+                               if( do_transitions(cursor_x, cursor_y,
                                                1, new_cursor, update_cursor)) break;
                                if(do_keyframes(cursor_x, cursor_y,
                                        0, get_buttonpress(), new_cursor,
@@ -4750,6 +4779,7 @@ int TrackCanvas::button_press_event()
 
                                if( do_tracks(cursor_x, cursor_y, 1) ) break;
 // Highlight selection
+                               if( get_buttonpress() != LEFT_BUTTON ) break;
                                rerender = start_selection(position);
                                mwindow->session->current_operation = SELECT_REGION;
                                update_cursor = 1;
@@ -4769,17 +4799,17 @@ int TrackCanvas::button_press_event()
                if( update_overlay ) {
                        gui->draw_overlays(1);
                }
-
-               if( update_cursor > 0 ) {
+               if( update_cursor < 0 ) {
+// double_click edit
+                       gui->swindow->update_selection();
+               }
+               if( update_cursor ) {
                        gui->update_timebar(0);
                        gui->hide_cursor(0);
                        gui->show_cursor(1);
                        gui->zoombar->update();
                        gui->flash_canvas(1);
                }
-               else if(update_cursor < 0) {
-                       gui->swindow->update_selection();
-               }
        }
        return result;
 }
@@ -4793,7 +4823,7 @@ int TrackCanvas::start_selection(double position)
 // Extend a border
        if(shift_down())
        {
-               double midpoint = (mwindow->edl->local_session->get_selectionstart(1) + 
+               double midpoint = (mwindow->edl->local_session->get_selectionstart(1) +
                        mwindow->edl->local_session->get_selectionend(1)) / 2;
 
                if(position < midpoint)
@@ -4820,7 +4850,7 @@ int TrackCanvas::start_selection(double position)
 // Que the CWindow
                rerender = 1;
        }
-       
+
        return rerender;
 }
 
@@ -4837,8 +4867,8 @@ void TrackCanvas::end_pluginhandle_selection()
 
 double TrackCanvas::time_visible()
 {
-       return (double)get_w() * 
-               mwindow->edl->local_session->zoom_sample / 
+       return (double)get_w() *
+               mwindow->edl->local_session->zoom_sample /
                mwindow->edl->session->sample_rate;
 }
 
@@ -4852,7 +4882,7 @@ void TrackCanvas::show_message(Auto *current, int show_curve_type, const char *f
                        FloatAuto::curve_name(((FloatAuto*)current)->curve_mode));
        }
        char string2[BCTEXTLEN];
-       Units::totext(string2, 
+       Units::totext(string2,
                current->autos->track->from_units(current->position),
                mwindow->edl->session->time_format,
                mwindow->edl->session->sample_rate,
@@ -4880,7 +4910,7 @@ void TrackCanvas::show_message(Auto *current, int show_curve_type, const char *f
 //             else
 //                     return gui->pane[BOTTOM_LEFT_PANE]->patchbay;
 //     }
-// 
+//
 //     return 0;
 // }