41fe8d9c187e9f16292485fa28d2d33691d58e03
[goodguy/history.git] / cinelerra-5.1 / cinelerra / keyframepopup.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "apatchgui.h"
23 #include "atrack.h"
24 #include "autoconf.h"
25 #include "autos.h"
26 #include "bcwindowbase.h"
27 #include "cpanel.h"
28 #include "cwindowgui.h"
29 #include "cwindow.h"
30 #include "edl.h"
31 #include "edlsession.h"
32 #include "filexml.h"
33 #include "floatauto.h"
34 #include "gwindow.h"
35 #include "gwindowgui.h"
36 #include "intauto.h"
37 #include "keyframe.h"
38 #include "keyframepopup.h"
39 #include "language.h"
40 #include "localsession.h"
41 #include "maincursor.h"
42 #include "mainmenu.h"
43 #include "mainundo.h"
44 #include "mwindowgui.h"
45 #include "mwindow.h"
46 #include "patchbay.h"
47 #include "patchgui.h"
48 #include "timelinepane.h"
49 #include "track.h"
50 #include "vtrack.h"
51
52 KeyframePopup::KeyframePopup(MWindow *mwindow, MWindowGUI *gui)
53  : BC_PopupMenu(0, 0, 0, "", 0)
54 {
55         this->mwindow = mwindow;
56         this->gui = gui;
57         key_hide = 0;
58         key_show = 0;
59         key_delete = 0;
60         key_copy = 0;
61         key_smooth = 0;
62         key_linear = 0;
63         key_free = 0;
64         key_mbar = 0;
65         key_mode_displayed = false;
66         key_edit_displayed = false;
67 }
68
69 KeyframePopup::~KeyframePopup()
70 {
71         if( !key_mode_displayed ) {
72                 delete key_mbar;
73                 delete key_smooth;
74                 delete key_linear;
75                 delete key_free_t;
76                 delete key_free;
77         }
78         if( !key_edit_displayed ) {
79                 delete key_edit;
80         }
81 }
82
83 void KeyframePopup::create_objects()
84 {
85         add_item(key_show = new KeyframePopupShow(mwindow, this));
86         add_item(key_hide = new KeyframePopupHide(mwindow, this));
87         add_item(key_delete = new KeyframePopupDelete(mwindow, this));
88         add_item(key_copy = new KeyframePopupCopy(mwindow, this));
89
90         key_edit   = new KeyframePopupEdit(mwindow, this);
91         key_mbar   = new BC_MenuItem("-");
92         key_smooth = new KeyframePopupCurveMode(mwindow, this, FloatAuto::SMOOTH);
93         key_linear = new KeyframePopupCurveMode(mwindow, this, FloatAuto::LINEAR);
94         key_free_t = new KeyframePopupCurveMode(mwindow, this, FloatAuto::TFREE );
95         key_free   = new KeyframePopupCurveMode(mwindow, this, FloatAuto::FREE  );
96 }
97
98 int KeyframePopup::update(Plugin *plugin, KeyFrame *keyframe)
99 {
100         key_show->set_text(_("Show Plugin Settings"));
101         this->keyframe_plugin = plugin;
102         this->keyframe_auto = keyframe;
103         this->keyframe_autos = 0;
104         this->keyframe_automation = 0;
105         handle_curve_mode(0, 0);
106         return 0;
107 }
108
109 int KeyframePopup::update(Automation *automation, Autos *autos, Auto *auto_keyframe)
110 {
111         key_show->set_text(_(GWindowGUI::auto_text[autos->autoidx]));
112         this->keyframe_plugin = 0;
113         this->keyframe_automation = automation;
114         this->keyframe_autos = autos;
115         this->keyframe_auto = auto_keyframe;
116         handle_curve_mode(autos, auto_keyframe);
117
118         /* snap to cursor */
119         double current_position = mwindow->edl->local_session->get_selectionstart(1);
120         double new_position = keyframe_automation->track->from_units(keyframe_auto->position);
121         mwindow->edl->local_session->set_selectionstart(new_position);
122         mwindow->edl->local_session->set_selectionend(new_position);
123         if (current_position != new_position)
124         {
125                 mwindow->edl->local_session->set_selectionstart(new_position);
126                 mwindow->edl->local_session->set_selectionend(new_position);
127                 mwindow->gui->lock_window();
128                 mwindow->gui->update(1, 1, 1, 1, 1, 1, 0);
129                 mwindow->gui->unlock_window();
130         }
131         return 0;
132 }
133
134 void KeyframePopup::handle_curve_mode(Autos *autos, Auto *auto_keyframe)
135 // determines the type of automation node. if floatauto, adds
136 // menu entries showing the curve mode of the node
137 {
138         deactivate();
139         if( !key_edit_displayed && keyframe_plugin ) {
140                 add_item(key_edit);
141                 key_edit_displayed = true;
142         }
143         else if( key_edit_displayed && !keyframe_plugin ) {
144                 remove_item(key_edit);
145                 key_edit_displayed = false;
146         }
147
148         if(!key_mode_displayed && autos && autos->get_type() == AUTOMATION_TYPE_FLOAT)
149         { // append additional menu entries showing the curve_mode
150                 add_item(key_mbar);
151                 add_item(key_smooth);
152                 add_item(key_linear);
153                 add_item(key_free_t);
154                 add_item(key_free);
155                 key_mode_displayed = true;
156         }
157         else if(key_mode_displayed && (!autos || autos->get_type() != AUTOMATION_TYPE_FLOAT))
158         { // remove additional menu entries
159                 remove_item(key_free);
160                 remove_item(key_free_t);
161                 remove_item(key_linear);
162                 remove_item(key_smooth);
163                 remove_item(key_mbar);
164                 key_mode_displayed = false;
165         }
166         if(key_mode_displayed && auto_keyframe)
167         { // set checkmarks to display current mode
168                 key_smooth->toggle_mode((FloatAuto*)auto_keyframe);
169                 key_linear->toggle_mode((FloatAuto*)auto_keyframe);
170                 key_free_t->toggle_mode((FloatAuto*)auto_keyframe);
171                 key_free  ->toggle_mode((FloatAuto*)auto_keyframe);
172         }
173         activate();
174 }
175
176 KeyframePopupDelete::KeyframePopupDelete(MWindow *mwindow, KeyframePopup *popup)
177  : BC_MenuItem(_("Delete keyframe"))
178 {
179         this->mwindow = mwindow;
180         this->popup = popup;
181 }
182
183 KeyframePopupDelete::~KeyframePopupDelete()
184 {
185 }
186
187 int KeyframePopupDelete::handle_event()
188 {
189         mwindow->undo->update_undo_before(_("delete keyframe"), 0);
190         delete popup->keyframe_auto;
191         mwindow->undo->update_undo_after(_("delete keyframe"), LOAD_ALL);
192
193         mwindow->save_backup();
194         mwindow->gui->update(0, 1,      // 1 for incremental drawing.  2 for full refresh
195                 0, 0, 0, 0, 0);
196         mwindow->update_plugin_guis();
197         mwindow->restart_brender();
198         mwindow->sync_parameters(CHANGE_EDL);
199
200         return 1;
201 }
202
203 KeyframePopupHide::KeyframePopupHide(MWindow *mwindow, KeyframePopup *popup)
204  : BC_MenuItem(_("Hide keyframe type"))
205 {
206         this->mwindow = mwindow;
207         this->popup = popup;
208 }
209
210 KeyframePopupHide::~KeyframePopupHide()
211 {
212 }
213
214 int KeyframePopupHide::handle_event()
215 {
216         if( popup->keyframe_autos )
217                 mwindow->set_auto_visibility(popup->keyframe_autos, 0);
218         return 1;
219 }
220
221 KeyframePopupShow::KeyframePopupShow(MWindow *mwindow, KeyframePopup *popup)
222  : BC_MenuItem(_("Show keyframe settings"))
223 {
224         this->mwindow = mwindow;
225         this->popup = popup;
226 }
227
228 KeyframePopupShow::~KeyframePopupShow()
229 {
230 }
231
232 PatchGUI *KeyframePopupShow::get_patchgui(Track *track)
233 {
234         PatchGUI *patchgui = 0;
235         TimelinePane **panes = mwindow->gui->pane;
236         for( int i=0; i<TOTAL_PANES && !patchgui; ++i ) {
237                 if( !panes[i] ) continue;
238                 PatchBay *patchbay = panes[i]->patchbay;
239                 if( !patchbay ) continue;
240                 for( int j=0; j<patchbay->patches.total && !patchgui; ++j ) {
241                         if( patchbay->patches.values[j]->track == track )
242                                 patchgui = patchbay->patches.values[j];
243                 }
244         }
245         return patchgui;
246 }
247
248 int KeyframePopupShow::handle_event()
249 {
250         MWindowGUI *mgui = mwindow->gui;
251         CWindowGUI *cgui = mwindow->cwindow->gui;
252         int cx = mgui->get_relative_cursor_x()+15, cy = mgui->get_relative_cursor_y()-15;
253         delete mgui->keyvalue_popup;
254         mgui->keyvalue_popup = 0;
255
256         if( popup->keyframe_plugin ) {
257                 mwindow->update_plugin_guis();
258                 mwindow->show_plugin(popup->keyframe_plugin);
259         }
260         else if( popup->keyframe_automation ) {
261                 cgui->lock_window();
262                 int show_window = 1;
263
264                 switch( popup->keyframe_autos->autoidx ) {
265                 case AUTOMATION_CAMERA_X:
266                 case AUTOMATION_CAMERA_Y:
267                 case AUTOMATION_CAMERA_Z: {
268                         cgui->set_operation(CWINDOW_CAMERA);
269                         break; }
270
271                 case AUTOMATION_PROJECTOR_X:
272                 case AUTOMATION_PROJECTOR_Y:
273                 case AUTOMATION_PROJECTOR_Z: {
274                         cgui->set_operation(CWINDOW_PROJECTOR);
275                         break; }
276
277                 case AUTOMATION_MASK: {
278                         cgui->set_operation(CWINDOW_MASK);
279                         break; }
280
281                 default: {
282                         show_window = 0;
283                         PatchGUI *patchgui = get_patchgui(popup->keyframe_automation->track);
284                         if( !patchgui ) break;
285
286                         switch( popup->keyframe_autos->autoidx ) {
287                         case AUTOMATION_MODE: {
288                                 VKeyModePatch *mode = new VKeyModePatch(mwindow, (VPatchGUI *)patchgui);
289                                 mgui->add_subwindow(mode);
290                                 mode->create_objects();
291                                 mode->activate_menu();
292                                 mgui->keyvalue_popup = mode;
293                         break; }
294
295                         case AUTOMATION_PAN: {
296                                 AKeyPanPatch *pan = new AKeyPanPatch(mwindow, (APatchGUI *)patchgui);
297                                 mgui->add_subwindow(pan);
298                                 pan->create_objects();
299                                 pan->activate(cx, cy);
300                                 mgui->keyvalue_popup = pan;
301                         break; }
302
303                         case AUTOMATION_FADE: {
304                                 switch( patchgui->data_type ) {
305                                 case TRACK_AUDIO: {
306                                         AKeyFadePatch *fade = new AKeyFadePatch(mwindow, (APatchGUI *)patchgui, cx, cy);
307                                         mgui->add_subwindow(fade);
308                                         fade->create_objects();
309                                         mgui->keyvalue_popup = fade;
310                                         break; }
311                                 case TRACK_VIDEO: {
312                                         VKeyFadePatch *fade = new VKeyFadePatch(mwindow, (VPatchGUI *)patchgui, cx, cy);
313                                         mgui->add_subwindow(fade);
314                                         fade->create_objects();
315                                         mgui->keyvalue_popup = fade;
316                                         break; }
317                                 }
318                                 break; }
319
320                         case AUTOMATION_SPEED: {
321                                 KeySpeedPatch *speed = new KeySpeedPatch(mwindow, patchgui, cx, cy);
322                                 mgui->add_subwindow(speed);
323                                 speed->create_objects();
324                                 mgui->keyvalue_popup = speed;
325                                 break; }
326
327                         case AUTOMATION_MUTE: {
328                                 KeyMutePatch *mute = new KeyMutePatch(mwindow, (APatchGUI *)patchgui, cx, cy);
329                                 mgui->add_subwindow(mute);
330                                 mute->create_objects();
331                                 mgui->keyvalue_popup = mute;
332                                 break; }
333                         }
334                         break; }
335                 }
336
337 // ensure bringing to front
338                 if( show_window ) {
339                         mwindow->show_cwindow();
340                         CPanelToolWindow *panel_tool_window =
341                                 (CPanelToolWindow *)cgui->composite_panel->operation[CWINDOW_TOOL_WINDOW];
342                         panel_tool_window->set_shown(0);
343                         panel_tool_window->set_shown(1);
344                 }
345                 cgui->unlock_window();
346         }
347         return 1;
348 }
349
350
351
352 KeyframePopupCopy::KeyframePopupCopy(MWindow *mwindow, KeyframePopup *popup)
353  : BC_MenuItem(_("Copy keyframe"))
354 {
355         this->mwindow = mwindow;
356         this->popup = popup;
357 }
358
359 KeyframePopupCopy::~KeyframePopupCopy()
360 {
361 }
362
363 int KeyframePopupCopy::handle_event()
364 {
365 /*
366         FIXME:
367         we want to copy just keyframe under cursor, NOT all keyframes at this frame
368         - very hard to do, so this is good approximation for now...
369 */
370
371 #if 0
372         if (popup->keyframe_automation)
373         {
374                 FileXML file;
375                 EDL *edl = mwindow->edl;
376                 Track *track = popup->keyframe_automation->track;
377                 int64_t position = popup->keyframe_auto->position;
378                 AutoConf autoconf;
379 // first find out type of our auto
380                 autoconf.set_all(0);
381                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->projector_autos)
382                         autoconf.projector = 1;
383                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pzoom_autos)
384                         autoconf.pzoom = 1;
385                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->camera_autos)
386                         autoconf.camera = 1;
387                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->czoom_autos)
388                         autoconf.czoom = 1;
389                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mode_autos)
390                         autoconf.mode = 1;
391                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mask_autos)
392                         autoconf.mask = 1;
393                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pan_autos)
394                         autoconf.pan = 1;
395                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->fade_autos)
396                         autoconf.fade = 1;
397                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mute_autos)
398                         autoconf.mute = 1;
399
400
401 // now create a clipboard
402                 file.tag.set_title("AUTO_CLIPBOARD");
403                 file.tag.set_property("LENGTH", 0);
404                 file.tag.set_property("FRAMERATE", edl->session->frame_rate);
405                 file.tag.set_property("SAMPLERATE", edl->session->sample_rate);
406                 file.append_tag();
407                 file.append_newline();
408                 file.append_newline();
409
410 /*              track->copy_automation(position,
411                         position,
412                         &file,
413                         0,
414                         0);
415                         */
416                 file.tag.set_title("TRACK");
417 // Video or audio
418                 track->save_header(&file);
419                 file.append_tag();
420                 file.append_newline();
421
422                 track->automation->copy(position,
423                         position,
424                         &file,
425                         0,
426                         0,
427                         &autoconf);
428                 file.tag.set_title("/TRACK");
429                 file.append_tag();
430                 file.append_newline();
431                 file.append_newline();
432                 file.append_newline();
433                 file.append_newline();
434
435                 file.tag.set_title("/AUTO_CLIPBOARD");
436                 file.append_tag();
437                 file.append_newline();
438                 file.terminate_string();
439
440                 mwindow->gui->lock_window();
441                 mwindow->gui->get_clipboard()->to_clipboard(file.string,
442                         strlen(file.string),
443                         SECONDARY_SELECTION);
444                 mwindow->gui->unlock_window();
445
446         } else
447 #endif
448                 mwindow->copy_automation();
449         return 1;
450 }
451
452
453
454 KeyframePopupCurveMode::KeyframePopupCurveMode(
455         MWindow *mwindow,
456         KeyframePopup *popup,
457         int curve_mode)
458  : BC_MenuItem( get_labeltext(curve_mode))
459 {
460         this->curve_mode = curve_mode;
461         this->mwindow = mwindow;
462         this->popup = popup;
463 }
464
465 KeyframePopupCurveMode::~KeyframePopupCurveMode() { }
466
467
468 const char* KeyframePopupCurveMode::get_labeltext(int mode)
469 {
470         switch(mode) {
471         case FloatAuto::SMOOTH: return _("smooth curve");
472         case FloatAuto::LINEAR: return _("linear segments");
473         case FloatAuto::TFREE:  return _("tangent edit");
474         case FloatAuto::FREE:   return _("disjoint edit");
475         }
476         return _("misconfigured");
477 }
478
479
480 void KeyframePopupCurveMode::toggle_mode(FloatAuto *keyframe)
481 {
482         set_checked(curve_mode == keyframe->curve_mode);
483 }
484
485
486 int KeyframePopupCurveMode::handle_event()
487 {
488         if (popup->keyframe_autos &&
489             popup->keyframe_autos->get_type() == AUTOMATION_TYPE_FLOAT)
490         {
491                 mwindow->undo->update_undo_before(_("change keyframe curve mode"), 0);
492                 ((FloatAuto*)popup->keyframe_auto)->
493                         change_curve_mode((FloatAuto::t_mode)curve_mode);
494
495                 // if we switched to some "auto" mode, this may imply a
496                 // real change to parameters, so this needs to be undoable...
497                 mwindow->undo->update_undo_after(_("change keyframe curve mode"), LOAD_ALL);
498                 mwindow->save_backup();
499
500                 mwindow->gui->update(0, 1, 0,0,0,0,0); // incremental redraw for canvas
501                 mwindow->cwindow->update(0,0, 1, 0,0); // redraw tool window in compositor
502                 mwindow->update_plugin_guis();
503                 mwindow->restart_brender();
504                 mwindow->sync_parameters(CHANGE_EDL);
505         }
506         return 1;
507 }
508
509
510 KeyframePopupEdit::KeyframePopupEdit(MWindow *mwindow, KeyframePopup *popup)
511  : BC_MenuItem(_("Edit Params..."))
512 {
513         this->mwindow = mwindow;
514         this->popup = popup;
515 }
516
517 int KeyframePopupEdit::handle_event()
518 {
519         mwindow->show_keyframe_gui(popup->keyframe_plugin);
520         return 1;
521 }
522
523
524 KeyframeHidePopup::KeyframeHidePopup(MWindow *mwindow, MWindowGUI *gui)
525  : BC_PopupMenu(0, 0, 0, "", 0)
526 {
527         this->mwindow = mwindow;
528         this->gui = gui;
529         this->keyframe_autos = 0;
530 }
531
532 KeyframeHidePopup::~KeyframeHidePopup()
533 {
534 }
535
536 void KeyframeHidePopup::create_objects()
537 {
538         add_item(new KeyframeHideItem(mwindow, this));
539 }
540
541 int KeyframeHidePopup::update(Autos *autos)
542 {
543         this->keyframe_autos = autos;
544         return 0;
545 }
546
547 KeyframeHideItem::KeyframeHideItem(MWindow *mwindow, KeyframeHidePopup *popup)
548  : BC_MenuItem(_("Hide keyframe type"))
549 {
550         this->mwindow = mwindow;
551         this->popup = popup;
552 }
553
554
555 int KeyframeHideItem::handle_event()
556 {
557         if( popup->keyframe_autos )
558                 mwindow->set_auto_visibility(popup->keyframe_autos, 0);
559         return 1;
560 }
561
562
563
564 KeyMutePatch::KeyMutePatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
565  : BC_SubWindow(x, y, 100, 20, GWindowGUI::auto_colors[AUTOMATION_MUTE])
566 {
567         this->mwindow = mwindow;
568         this->patch = patch;
569 }
570
571 void KeyMutePatch::create_objects()
572 {
573         key_mute_checkbox = new KeyMuteValue(this);
574         add_subwindow(key_mute_checkbox);
575         key_mute_checkbox->activate();
576         show_window();
577 }
578
579 KeyMuteValue::KeyMuteValue(KeyMutePatch *key_mute_patch)
580  : BC_CheckBox(0,0, key_mute_patch->mwindow->
581         get_int_auto(key_mute_patch->patch, AUTOMATION_MUTE)->value,
582         _("Mute"), MEDIUMFONT, RED)
583 {
584         this->key_mute_patch = key_mute_patch;
585 }
586
587 int KeyMuteValue::button_release_event()
588 {
589         BC_CheckBox::button_release_event();
590         return 0;
591 }
592
593 void KeyMuteValue::update_edl()
594 {
595         MWindow *mwindow = key_mute_patch->mwindow;
596         PatchGUI *patch = key_mute_patch->patch;
597         double position = mwindow->edl->local_session->get_selectionstart(1);
598         Autos *mute_autos = patch->track->automation->autos[AUTOMATION_MUTE];
599         int need_undo = !mute_autos->auto_exists_for_editing(position);
600         mwindow->undo->update_undo_before(_("mute"), need_undo ? 0 : this);
601         IntAuto *current = (IntAuto*)mute_autos->get_auto_for_editing(position);
602         current->value = this->get_value();
603         mwindow->undo->update_undo_after(_("mute"), LOAD_AUTOMATION);
604 }
605
606 int KeyMuteValue::handle_event()
607 {
608         MWindow *mwindow = key_mute_patch->mwindow;
609         PatchGUI *patch = key_mute_patch->patch;
610         patch->change_source = 1;
611         update_edl();
612         patch->change_source = 0;
613         mwindow->sync_parameters(CHANGE_PARAMS);
614         if(mwindow->edl->session->auto_conf->autos[AUTOMATION_MUTE]) {
615                 mwindow->gui->update_patchbay();
616                 mwindow->gui->draw_overlays(1);
617         }
618         return 1;
619 }
620
621 KeySpeedPatch::KeySpeedPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
622  : BC_SubWindow(x,y, 200,20, GWindowGUI::auto_colors[AUTOMATION_SPEED])
623 {
624         this->mwindow = mwindow;
625         this->patch = patch;
626 }
627
628 void KeySpeedPatch::create_objects()
629 {
630         key_speed_slider = new KeySpeedValue(this);
631         add_subwindow(key_speed_slider);
632         key_speed_slider->activate();
633         show_window();
634 }
635
636 KeySpeedValue::KeySpeedValue(KeySpeedPatch *key_speed_patch)
637  : BC_FSlider(0,0, 0, key_speed_patch->get_w(), key_speed_patch->get_w(),
638         key_speed_patch->mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_SPEED],
639         key_speed_patch->mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_SPEED],
640         key_speed_patch->mwindow->get_float_auto(key_speed_patch->patch, AUTOMATION_SPEED)->get_value())
641 {
642         this->key_speed_patch = key_speed_patch;
643         set_precision(0.01);
644 }
645
646 KeySpeedValue::~KeySpeedValue()
647 {
648 }
649
650 int KeySpeedValue::button_release_event()
651 {
652         BC_FSlider::button_release_event();
653         return 0;
654 }
655
656 void KeySpeedValue::update_edl()
657 {
658         MWindow *mwindow = key_speed_patch->mwindow;
659         PatchGUI *patch = key_speed_patch->patch;
660         double position = mwindow->edl->local_session->get_selectionstart(1);
661         Autos *speed_autos = patch->track->automation->autos[AUTOMATION_SPEED];
662         int need_undo = !speed_autos->auto_exists_for_editing(position);
663         mwindow->undo->update_undo_before(_("speed"), need_undo ? 0 : this);
664         FloatAuto *current = (FloatAuto*)speed_autos->get_auto_for_editing(position);
665         current->set_value(get_value());
666         mwindow->undo->update_undo_after(_("speed"), LOAD_AUTOMATION);
667 }
668
669 int KeySpeedValue::handle_event()
670 {
671         MWindow *mwindow = key_speed_patch->mwindow;
672         PatchGUI *patch = key_speed_patch->patch;
673         if( shift_down() ) {
674                 update(1.0);
675                 set_tooltip(get_caption());
676         }
677
678         patch->change_source = 1;
679         update_edl();
680         patch->change_source = 0;
681         mwindow->sync_parameters(CHANGE_PARAMS);
682         if(mwindow->edl->session->auto_conf->autos[AUTOMATION_SPEED]) {
683                 mwindow->gui->draw_overlays(1);
684         }
685         return 1;
686 }
687