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