Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[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 "cwindow.h"
23 #include "edl.h"
24 #include "keyframe.h"
25 #include "keyframepopup.h"
26 #include "language.h"
27 #include "mainundo.h"
28 #include "mwindow.h"
29 #include "mwindowgui.h"
30 #include "localsession.h"
31 #include "cwindowgui.h" 
32 #include "cpanel.h"
33 #include "patchbay.h"
34 #include "patchgui.h" 
35 #include "apatchgui.h"
36 #include "vpatchgui.h"
37 #include "track.h"
38 #include "maincursor.h"
39 #include "bcwindowbase.h"
40 #include "filexml.h"
41 #include "edlsession.h"
42 #include "autos.h"
43
44 KeyframePopup::KeyframePopup(MWindow *mwindow, MWindowGUI *gui)
45  : BC_PopupMenu(0, 0, 0, "", 0)
46 {
47         this->mwindow = mwindow;
48         this->gui = gui;
49         key_show = 0;
50         key_delete = 0;
51         key_copy = 0;
52         key_smooth = 0;
53         key_linear = 0;
54         key_free = 0;
55         key_mbar = 0;
56         key_mode_displayed = false;
57 }
58
59 KeyframePopup::~KeyframePopup()
60 {
61         if( !key_mode_displayed ) {
62                 delete key_mbar;
63                 delete key_smooth;
64                 delete key_linear;
65                 delete key_free_t;
66                 delete key_free;
67         }
68 }
69
70 void KeyframePopup::create_objects()
71 {
72         add_item(key_show = new KeyframePopupShow(mwindow, this));
73         add_item(key_delete = new KeyframePopupDelete(mwindow, this));
74         add_item(key_copy = new KeyframePopupCopy(mwindow, this));
75         add_item(key_edit = new KeyframePopupEdit(mwindow, this));
76
77         key_mbar   = new BC_MenuItem("-");
78         key_smooth = new KeyframePopupCurveMode(mwindow, this, FloatAuto::SMOOTH);
79         key_linear = new KeyframePopupCurveMode(mwindow, this, FloatAuto::LINEAR);
80         key_free_t = new KeyframePopupCurveMode(mwindow, this, FloatAuto::TFREE );
81         key_free   = new KeyframePopupCurveMode(mwindow, this, FloatAuto::FREE  );
82 }
83
84 int KeyframePopup::update(Plugin *plugin, KeyFrame *keyframe)
85 {
86         this->keyframe_plugin = plugin;
87         this->keyframe_auto = keyframe;
88         this->keyframe_autos = 0;
89         this->keyframe_automation = 0;
90         handle_curve_mode(0, 0);
91         return 0;
92 }
93
94 int KeyframePopup::update(Automation *automation, Autos *autos, Auto *auto_keyframe)
95 {
96         this->keyframe_plugin = 0;
97         this->keyframe_automation = automation;
98         this->keyframe_autos = autos;
99         this->keyframe_auto = auto_keyframe;
100         handle_curve_mode(autos, auto_keyframe);
101
102         /* snap to cursor */
103         double current_position = mwindow->edl->local_session->get_selectionstart(1);
104         double new_position = keyframe_automation->track->from_units(keyframe_auto->position);
105         mwindow->edl->local_session->set_selectionstart(new_position);
106         mwindow->edl->local_session->set_selectionend(new_position);
107         if (current_position != new_position)
108         {
109                 mwindow->edl->local_session->set_selectionstart(new_position);
110                 mwindow->edl->local_session->set_selectionend(new_position);
111                 mwindow->gui->lock_window();
112                 mwindow->gui->update(1, 1, 1, 1, 1, 1, 0);      
113                 mwindow->gui->unlock_window();
114         }
115         return 0;
116 }
117
118 void KeyframePopup::handle_curve_mode(Autos *autos, Auto *auto_keyframe)
119 // determines the type of automation node. if floatauto, adds
120 // menu entries showing the curve mode of the node
121 {
122         if(!key_mode_displayed && autos && autos->get_type() == AUTOMATION_TYPE_FLOAT)
123         { // append additional menu entries showing the curve_mode
124                 add_item(key_mbar);
125                 add_item(key_smooth);
126                 add_item(key_linear);
127                 add_item(key_free_t);
128                 add_item(key_free);
129                 key_mode_displayed = true;
130         }
131         else if(key_mode_displayed && (!autos || autos->get_type() != AUTOMATION_TYPE_FLOAT))
132         { // remove additional menu entries
133                 remove_item(key_free);
134                 remove_item(key_free_t);
135                 remove_item(key_linear);
136                 remove_item(key_smooth);
137                 remove_item(key_mbar);
138                 key_mode_displayed = false;
139         }
140         if(key_mode_displayed && auto_keyframe)
141         { // set checkmarks to display current mode
142                 key_smooth->toggle_mode((FloatAuto*)auto_keyframe);
143                 key_linear->toggle_mode((FloatAuto*)auto_keyframe);
144                 key_free_t->toggle_mode((FloatAuto*)auto_keyframe);
145                 key_free  ->toggle_mode((FloatAuto*)auto_keyframe);
146         }
147 }
148
149 KeyframePopupDelete::KeyframePopupDelete(MWindow *mwindow, KeyframePopup *popup)
150  : BC_MenuItem(_("Delete keyframe"))
151 {
152         this->mwindow = mwindow;
153         this->popup = popup;
154 }
155
156 KeyframePopupDelete::~KeyframePopupDelete()
157 {
158 }
159
160 int KeyframePopupDelete::handle_event()
161 {
162         mwindow->undo->update_undo_before(_("delete keyframe"), 0);
163         delete popup->keyframe_auto;
164         mwindow->undo->update_undo_after(_("delete keyframe"), LOAD_ALL);
165
166         mwindow->save_backup();
167         mwindow->gui->update(0, 1,      // 1 for incremental drawing.  2 for full refresh
168                 0, 0, 0, 0, 0);
169         mwindow->update_plugin_guis();
170         mwindow->restart_brender();
171         mwindow->sync_parameters(CHANGE_EDL);
172
173         return 1;
174 }
175
176 KeyframePopupShow::KeyframePopupShow(MWindow *mwindow, KeyframePopup *popup)
177  : BC_MenuItem(_("Show keyframe settings"))
178 {
179         this->mwindow = mwindow;
180         this->popup = popup;
181 }
182
183 KeyframePopupShow::~KeyframePopupShow()
184 {
185 }
186
187 int KeyframePopupShow::handle_event()
188 {
189         if (popup->keyframe_plugin)
190         {
191                 mwindow->update_plugin_guis();
192                 mwindow->show_plugin(popup->keyframe_plugin);
193         } else
194         if (popup->keyframe_automation)
195         {
196 /*
197
198                 mwindow->cwindow->gui->lock_window();
199                 int show_window = 1;
200                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->projector_autos ||
201                    popup->keyframe_autos == (Autos *)popup->keyframe_automation->pzoom_autos)
202                    
203                 {
204                         mwindow->cwindow->gui->set_operation(CWINDOW_PROJECTOR);        
205                 } else
206                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->camera_autos ||
207                    popup->keyframe_autos == (Autos *)popup->keyframe_automation->czoom_autos)
208                    
209                 {
210                         mwindow->cwindow->gui->set_operation(CWINDOW_CAMERA);   
211                 } else
212                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mode_autos)
213                    
214                 {
215                         // no window to be shown
216                         show_window = 0;
217                         // first find the appropriate patchgui
218                         PatchBay *patchbay = mwindow->gui->patchbay;
219                         PatchGUI *patchgui = 0;
220                         for (int i = 0; i < patchbay->patches.total; i++)
221                                 if (patchbay->patches.values[i]->track == popup->keyframe_automation->track)
222                                         patchgui = patchbay->patches.values[i];         
223                         if (patchgui != 0)
224                         {
225 // FIXME: repositioning of the listbox needs support in guicast
226 //                              int cursor_x = popup->get_relative_cursor_x();
227 //                              int cursor_y = popup->get_relative_cursor_y();
228 //                              vpatchgui->mode->reposition_window(cursor_x, cursor_y);
229
230
231 // Open the popup menu
232                                 VPatchGUI *vpatchgui = (VPatchGUI *)patchgui;
233                                 vpatchgui->mode->activate_menu();
234                         }
235                 } else
236                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mask_autos)
237                    
238                 {
239                         mwindow->cwindow->gui->set_operation(CWINDOW_MASK);     
240                 } else
241                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pan_autos)
242                    
243                 {
244                         // no window to be shown
245                         show_window = 0;
246                         // first find the appropriate patchgui
247                         PatchBay *patchbay = mwindow->gui->patchbay;
248                         PatchGUI *patchgui = 0;
249                         for (int i = 0; i < patchbay->patches.total; i++)
250                                 if (patchbay->patches.values[i]->track == popup->keyframe_automation->track)
251                                         patchgui = patchbay->patches.values[i];         
252                         if (patchgui != 0)
253                         {
254 // Open the popup menu at current mouse position
255                                 APatchGUI *apatchgui = (APatchGUI *)patchgui;
256                                 int cursor_x = popup->get_relative_cursor_x();
257                                 int cursor_y = popup->get_relative_cursor_y();
258                                 apatchgui->pan->activate(cursor_x, cursor_y);
259                         }
260                         
261
262                 } else
263                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->fade_autos)
264                    
265                 {
266                         // no window to be shown, so do nothing
267                         // IDEA: open window for fading
268                         show_window = 0;
269                 } else
270                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mute_autos)
271                    
272                 {
273                         // no window to be shown, so do nothing
274                         // IDEA: directly switch
275                         show_window = 0;
276                 } else;
277                 
278
279 // ensure bringing to front
280                 if (show_window)
281                 {
282                         ((CPanelToolWindow *)(mwindow->cwindow->gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]))->set_shown(0);
283                         ((CPanelToolWindow *)(mwindow->cwindow->gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]))->set_shown(1);
284                 }
285                 mwindow->cwindow->gui->unlock_window();
286
287
288 */
289         }
290         return 1;
291 }
292
293
294
295 KeyframePopupCopy::KeyframePopupCopy(MWindow *mwindow, KeyframePopup *popup)
296  : BC_MenuItem(_("Copy keyframe"))
297 {
298         this->mwindow = mwindow;
299         this->popup = popup;
300 }
301
302 KeyframePopupCopy::~KeyframePopupCopy()
303 {
304 }
305
306 int KeyframePopupCopy::handle_event()
307 {
308 /*
309         FIXME:
310         we want to copy just keyframe under cursor, NOT all keyframes at this frame
311         - very hard to do, so this is good approximation for now...
312 */
313         
314 #if 0
315         if (popup->keyframe_automation)
316         {
317                 FileXML file;
318                 EDL *edl = mwindow->edl;
319                 Track *track = popup->keyframe_automation->track;
320                 int64_t position = popup->keyframe_auto->position;
321                 AutoConf autoconf;
322 // first find out type of our auto
323                 autoconf.set_all(0);
324                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->projector_autos)
325                         autoconf.projector = 1;
326                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pzoom_autos)
327                         autoconf.pzoom = 1;
328                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->camera_autos)
329                         autoconf.camera = 1;
330                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->czoom_autos)
331                         autoconf.czoom = 1;             
332                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mode_autos)
333                         autoconf.mode = 1;
334                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mask_autos)
335                         autoconf.mask = 1;
336                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pan_autos)
337                         autoconf.pan = 1;                  
338                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->fade_autos)
339                         autoconf.fade = 1;
340                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mute_autos)
341                         autoconf.mute = 1;              
342
343
344 // now create a clipboard
345                 file.tag.set_title("AUTO_CLIPBOARD");
346                 file.tag.set_property("LENGTH", 0);
347                 file.tag.set_property("FRAMERATE", edl->session->frame_rate);
348                 file.tag.set_property("SAMPLERATE", edl->session->sample_rate);
349                 file.append_tag();
350                 file.append_newline();
351                 file.append_newline();
352
353 /*              track->copy_automation(position, 
354                         position, 
355                         &file,
356                         0,
357                         0);
358                         */
359                 file.tag.set_title("TRACK");
360 // Video or audio
361                 track->save_header(&file);
362                 file.append_tag();
363                 file.append_newline();
364
365                 track->automation->copy(position, 
366                         position, 
367                         &file,
368                         0,
369                         0,
370                         &autoconf);
371                 
372                 
373                 
374                 file.tag.set_title("/TRACK");
375                 file.append_tag();
376                 file.append_newline();
377                 file.append_newline();
378                 file.append_newline();
379                 file.append_newline();
380
381
382
383                 file.tag.set_title("/AUTO_CLIPBOARD");
384                 file.append_tag();
385                 file.append_newline();
386                 file.terminate_string();
387
388                 mwindow->gui->lock_window();
389                 mwindow->gui->get_clipboard()->to_clipboard(file.string, 
390                         strlen(file.string), 
391                         SECONDARY_SELECTION);
392                 mwindow->gui->unlock_window();
393
394         } else
395 #endif
396                 mwindow->copy_automation();
397         return 1;
398 }
399
400
401
402 KeyframePopupCurveMode::KeyframePopupCurveMode(
403         MWindow *mwindow, 
404         KeyframePopup *popup, 
405         int curve_mode)
406  : BC_MenuItem( get_labeltext(curve_mode))
407 {
408         this->curve_mode = curve_mode;
409         this->mwindow = mwindow;
410         this->popup = popup;
411 }
412
413 KeyframePopupCurveMode::~KeyframePopupCurveMode() { }
414
415
416 const char* KeyframePopupCurveMode::get_labeltext(int mode)
417 {
418         switch(mode) {
419         case FloatAuto::SMOOTH: return _("smooth curve");
420         case FloatAuto::LINEAR: return _("linear segments");
421         case FloatAuto::TFREE:  return _("tangent edit");
422         case FloatAuto::FREE:   return _("disjoint edit");
423         }
424         return "misconfigured";
425 }
426
427
428 void KeyframePopupCurveMode::toggle_mode(FloatAuto *keyframe)
429 {
430         set_checked(curve_mode == keyframe->curve_mode);
431 }
432
433
434 int KeyframePopupCurveMode::handle_event()
435 {
436         if (popup->keyframe_autos && 
437             popup->keyframe_autos->get_type() == AUTOMATION_TYPE_FLOAT)
438         {
439                 mwindow->undo->update_undo_before(_("change keyframe curve mode"), 0);
440                 ((FloatAuto*)popup->keyframe_auto)->
441                         change_curve_mode((FloatAuto::t_mode)curve_mode);
442                 
443                 // if we switched to some "auto" mode, this may imply a
444                 // real change to parameters, so this needs to be undoable...
445                 mwindow->undo->update_undo_after(_("change keyframe curve mode"), LOAD_ALL);
446                 mwindow->save_backup();
447                 
448                 mwindow->gui->update(0, 1, 0,0,0,0,0); // incremental redraw for canvas
449                 mwindow->cwindow->update(0,0, 1, 0,0); // redraw tool window in compositor
450                 mwindow->update_plugin_guis();
451                 mwindow->restart_brender();
452                 mwindow->sync_parameters(CHANGE_EDL);
453         }
454         return 1;
455 }
456
457
458 KeyframePopupEdit::KeyframePopupEdit(MWindow *mwindow, KeyframePopup *popup)
459  : BC_MenuItem(_("Edit Params..."))
460 {
461         this->mwindow = mwindow;
462         this->popup = popup;
463 }
464
465 int KeyframePopupEdit::handle_event()
466 {
467         mwindow->show_keyframe_gui(popup->keyframe_plugin);
468         return 1;
469 }
470
471
472