dca01ad3a6806633a1344d8a073598f3a72fa4c8
[goodguy/history.git] / cinelerra-5.1 / cinelerra / vpatchgui.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2014 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 "autoconf.h"
23 #include "automation.h"
24 #include "edl.h"
25 #include "edlsession.h"
26 #include "floatauto.h"
27 #include "floatautos.h"
28 #include "gwindowgui.h"
29 #include "intauto.h"
30 #include "intautos.h"
31 #include "language.h"
32 #include "localsession.h"
33 #include "mainsession.h"
34 #include "mainundo.h"
35 #include "mwindow.h"
36 #include "mwindowgui.h"
37 #include "overlayframe.inc"
38 #include "patchbay.h"
39 #include "theme.h"
40 #include "trackcanvas.h"
41 #include "vpatchgui.h"
42 #include "vtrack.h"
43
44 #include <string.h>
45
46
47
48
49
50 VPatchGUI::VPatchGUI(MWindow *mwindow, PatchBay *patchbay, VTrack *track, int x, int y)
51  : PatchGUI(mwindow, patchbay, track, x, y)
52 {
53         data_type = TRACK_VIDEO;
54         this->vtrack = track;
55         mode = 0;
56         fade = 0;
57 }
58
59 VPatchGUI::~VPatchGUI()
60 {
61         if(fade) delete fade;
62         if(mode) delete mode;
63 }
64
65 void VPatchGUI::create_objects()
66 {
67         update(x, y);
68 }
69
70 int VPatchGUI::reposition(int x, int y)
71 {
72         //int x1 = 0;
73         int y1 = PatchGUI::reposition(x, y);
74
75         if(fade) fade->reposition_window(fade->get_x(),
76                 y1 + y);
77
78         y1 += mwindow->theme->fade_h;
79
80         if(mode) mode->reposition_window(mode->get_x(),
81                 y1 + y);
82
83         if(nudge) nudge->reposition_window(nudge->get_x(),
84                 y1 + y);
85
86
87         y1 += mwindow->theme->mode_h;
88
89         return y1;
90 }
91
92 int VPatchGUI::update(int x, int y)
93 {
94         int h = track->vertical_span(mwindow->theme);
95         int x1 = 0;
96         int y1 = PatchGUI::update(x, y);
97
98         if(fade)
99         {
100                 if(h - y1 < mwindow->theme->fade_h)
101                 {
102                         delete fade;
103                         fade = 0;
104                 }
105                 else
106                 {
107                         fade->update(fade->get_w(), mwindow->get_float_auto(this, AUTOMATION_FADE)->get_value(),
108                                      mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_VIDEO_FADE],
109                                      mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_VIDEO_FADE]);
110                 }
111         }
112         else
113         if(h - y1 >= mwindow->theme->fade_h)
114         {
115                 patchbay->add_subwindow(fade = new VFadePatch(mwindow,
116                         this,
117                         x1 + x,
118                         y1 + y,
119                         patchbay->get_w() - 10));
120         }
121         y1 += mwindow->theme->fade_h;
122
123         if(mode)
124         {
125                 if(h - y1 < mwindow->theme->mode_h)
126                 {
127                         delete mode;
128                         mode = 0;
129                         delete nudge;
130                         nudge = 0;
131                 }
132                 else
133                 {
134                         mode->update(mwindow->get_int_auto(this, AUTOMATION_MODE)->value);
135                         nudge->update();
136                 }
137         }
138         else
139         if(h - y1 >= mwindow->theme->mode_h)
140         {
141                 patchbay->add_subwindow(mode = new VModePatch(mwindow,
142                         this,
143                         x1 + x,
144                         y1 + y));
145                 mode->create_objects();
146                 x1 += mode->get_w() + 10;
147                 patchbay->add_subwindow(nudge = new NudgePatch(mwindow,
148                         this,
149                         x1 + x,
150                         y1 + y,
151                         patchbay->get_w() - x1 - 10));
152         }
153
154
155
156
157
158         y1 += mwindow->theme->mode_h;
159
160         return y1;
161 }
162
163
164
165 void VPatchGUI::synchronize_fade(float value_change)
166 {
167         if(fade && !change_source)
168         {
169                 fade->update(Units::to_int64(fade->get_value() + value_change));
170                 fade->update_edl();
171         }
172 }
173
174
175 VFadePatch::VFadePatch(MWindow *mwindow, VPatchGUI *patch, int x, int y, int w)
176  : BC_ISlider(x, y, 0, w, w,
177                 mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_VIDEO_FADE],
178                 mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_VIDEO_FADE],
179                 (int64_t)mwindow->get_float_auto(patch,AUTOMATION_FADE)->get_value())
180 {
181         this->mwindow = mwindow;
182         this->patch = patch;
183 }
184
185 float VFadePatch::update_edl()
186 {
187         FloatAuto *current;
188         double position = mwindow->edl->local_session->get_selectionstart(1);
189         Autos *fade_autos = patch->vtrack->automation->autos[AUTOMATION_FADE];
190         int need_undo = !fade_autos->auto_exists_for_editing(position);
191
192         mwindow->undo->update_undo_before(_("fade"), need_undo ? 0 : this);
193
194         current = (FloatAuto*)fade_autos->get_auto_for_editing(position);
195
196         float result = get_value() - current->get_value();
197         current->set_value(get_value());
198
199         mwindow->undo->update_undo_after(_("fade"), LOAD_AUTOMATION);
200
201         return result;
202 }
203
204 int VFadePatch::handle_event()
205 {
206         if(shift_down())
207         {
208                 update(100);
209                 set_tooltip(get_caption());
210         }
211
212         patch->change_source = 1;
213
214         float change = update_edl();
215
216         if(patch->track->gang && patch->track->record)
217                 patch->patchbay->synchronize_faders(change, TRACK_VIDEO, patch->track);
218
219         patch->change_source = 0;
220
221
222         mwindow->gui->unlock_window();
223         mwindow->restart_brender();
224         mwindow->sync_parameters(CHANGE_PARAMS);
225         mwindow->gui->lock_window("VFadePatch::handle_event");
226         if(mwindow->edl->session->auto_conf->autos[AUTOMATION_FADE])
227         {
228                 mwindow->gui->draw_overlays(1);
229         }
230         return 1;
231 }
232
233
234 VKeyFadePatch::VKeyFadePatch(MWindow *mwindow, VPatchGUI *patch, int x, int y)
235  : BC_SubWindow(x,y, patch->patchbay->get_w(),20,
236         GWindowGUI::auto_colors[AUTOMATION_FADE])
237 {
238         this->mwindow = mwindow;
239         this->patch = patch;
240 }
241
242 void VKeyFadePatch::create_objects()
243 {
244         vkey_fade_value = new VKeyFadeValue(this);
245         add_subwindow(vkey_fade_value);
246         vkey_fade_value->activate();
247         show_window();
248 }
249
250 VKeyFadeValue::VKeyFadeValue(VKeyFadePatch *vkey_fade_patch)
251  : VFadePatch(vkey_fade_patch->mwindow, vkey_fade_patch->patch,
252         0,0, vkey_fade_patch->get_w())
253 {
254         this->vkey_fade_patch = vkey_fade_patch;
255 }
256
257 int VKeyFadeValue::button_release_event()
258 {
259         VFadePatch::button_release_event();
260         return 0;
261 }
262
263 int VKeyFadeValue::handle_event()
264 {
265         VPatchGUI *patch = vkey_fade_patch->patch;
266         int ret = VFadePatch::handle_event();
267         VFadePatch *fade = patch->fade;
268         if( fade )
269                 fade->update(get_value());
270         return ret;
271 }
272
273
274
275
276
277 VModePatch::VModePatch(MWindow *mwindow, VPatchGUI *patch, int x, int y)
278  : BC_PopupMenu(x, y, patch->patchbay->mode_icons[0]->get_w() + 20,
279         "", 1, mwindow->theme->get_image_set("mode_popup", 0), 10)
280 {
281         this->mwindow = mwindow;
282         this->patch = patch;
283         this->mode = mwindow->get_int_auto(patch, AUTOMATION_MODE)->value;
284         set_icon(patch->patchbay->mode_to_icon(this->mode));
285         set_tooltip(_("Overlay mode"));
286 }
287
288 VModePatch::VModePatch(MWindow *mwindow, VPatchGUI *patch)
289  : BC_PopupMenu(0, 0, 0, "", 0)
290 {
291         this->mwindow = mwindow;
292         this->patch = patch;
293         this->mode = mwindow->get_int_auto(patch, AUTOMATION_MODE)->value;
294 }
295
296
297 int VModePatch::handle_event()
298 {
299 // Set menu items
300 //      for(int i = 0; i < total_items(); i++)
301 //      {
302 //              VModePatchItem *item = (VModePatchItem*)get_item(i);
303 //              if(item->mode == mode)
304 //                      item->set_checked(1);
305 //              else
306 //                      item->set_checked(0);
307 //      }
308         update(mode);
309
310 // Set keyframe
311         IntAuto *current;
312         double position = mwindow->edl->local_session->get_selectionstart(1);
313         Autos *mode_autos = patch->vtrack->automation->autos[AUTOMATION_MODE];
314         int need_undo = !mode_autos->auto_exists_for_editing(position);
315
316         mwindow->undo->update_undo_before(_("mode"), need_undo ? 0 : this);
317
318         current = (IntAuto*)mode_autos->get_auto_for_editing(position);
319         current->value = mode;
320
321         mwindow->undo->update_undo_after(_("mode"), LOAD_AUTOMATION);
322
323         mwindow->sync_parameters(CHANGE_PARAMS);
324
325         if(mwindow->edl->session->auto_conf->autos[AUTOMATION_MODE])
326         {
327                 mwindow->gui->draw_overlays(1);
328         }
329         mwindow->session->changes_made = 1;
330         return 1;
331 }
332
333 void VModePatch::create_objects()
334 {
335         VModePatchItem *mode_item;
336         VModePatchSubMenu *submenu;
337         add_item(mode_item = new VModePatchItem(this, mode_to_text(TRANSFER_NORMAL),  TRANSFER_NORMAL));
338         add_item(mode_item = new VModePatchItem(this, _("Arithmetic..."), -1));
339         mode_item->add_submenu(submenu = new VModePatchSubMenu(mode_item));
340         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_ADDITION), TRANSFER_ADDITION));
341         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SUBTRACT), TRANSFER_SUBTRACT));
342         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DIVIDE),   TRANSFER_DIVIDE));
343         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_MULTIPLY), TRANSFER_MULTIPLY));
344         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_REPLACE),  TRANSFER_REPLACE));
345         add_item(mode_item = new VModePatchItem(this, _("PorterDuff..."), -1));
346         mode_item->add_submenu(submenu = new VModePatchSubMenu(mode_item));
347         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST),      TRANSFER_DST));
348         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST_ATOP), TRANSFER_DST_ATOP));
349         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST_IN),   TRANSFER_DST_IN));
350         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST_OUT),  TRANSFER_DST_OUT));
351         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST_OVER), TRANSFER_DST_OVER));
352         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC),      TRANSFER_SRC));
353         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC_ATOP), TRANSFER_SRC_ATOP));
354         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC_IN),   TRANSFER_SRC_IN));
355         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC_OUT),  TRANSFER_SRC_OUT));
356         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC_OVER), TRANSFER_SRC_OVER));
357         add_item(mode_item = new VModePatchItem(this, _("Logical..."), -1));
358         mode_item->add_submenu(submenu = new VModePatchSubMenu(mode_item));
359         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_MIN),      TRANSFER_MIN));
360         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_MAX),      TRANSFER_MAX));
361         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DARKEN),   TRANSFER_DARKEN));
362         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_LIGHTEN),  TRANSFER_LIGHTEN));
363         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_AND),      TRANSFER_AND));
364         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_OR),       TRANSFER_OR));
365         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_XOR),      TRANSFER_XOR));
366         add_item(mode_item = new VModePatchItem(this, _("Graphic Art..."), -1));
367         mode_item->add_submenu(submenu = new VModePatchSubMenu(mode_item));
368         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_OVERLAY),  TRANSFER_OVERLAY));
369         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SCREEN),   TRANSFER_SCREEN));
370         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_BURN),     TRANSFER_BURN));
371         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DODGE),    TRANSFER_DODGE));
372         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DIFFERENCE),TRANSFER_DIFFERENCE));
373         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_HARDLIGHT),TRANSFER_HARDLIGHT));
374         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SOFTLIGHT),TRANSFER_SOFTLIGHT));
375 }
376
377 void VModePatch::update(int mode)
378 {
379         set_icon(patch->patchbay->mode_to_icon(mode));
380         for(int i = 0; i < total_items(); i++)
381         {
382                 VModePatchItem *item = (VModePatchItem*)get_item(i);
383                 item->set_checked(item->mode == mode);
384                 VModePatchSubMenu *submenu = (VModePatchSubMenu *)item->get_submenu();
385                 if( !submenu ) continue;
386                 int n = submenu->total_items();
387                 for( int j=0; j<n; ++j ) {
388                         VModePatchItem *subitem = (VModePatchItem*)submenu->get_item(j);
389                         subitem->set_checked(subitem->mode == mode);
390                 }
391         }
392 }
393
394
395 const char* VModePatch::mode_to_text(int mode)
396 {
397         switch(mode) {
398         case TRANSFER_NORMAL:           return _("Normal");
399         case TRANSFER_ADDITION:         return _("Addition");
400         case TRANSFER_SUBTRACT:         return _("Subtract");
401         case TRANSFER_MULTIPLY:         return _("Multiply");
402         case TRANSFER_DIVIDE:           return _("Divide");
403         case TRANSFER_REPLACE:          return _("Replace");
404         case TRANSFER_MAX:              return _("Max");
405         case TRANSFER_MIN:              return _("Min");
406         case TRANSFER_DARKEN:           return _("Darken");
407         case TRANSFER_LIGHTEN:          return _("Lighten");
408         case TRANSFER_DST:              return _("Dst");
409         case TRANSFER_DST_ATOP:         return _("DstAtop");
410         case TRANSFER_DST_IN:           return _("DstIn");
411         case TRANSFER_DST_OUT:          return _("DstOut");
412         case TRANSFER_DST_OVER:         return _("DstOver");
413         case TRANSFER_SRC:              return _("Src");
414         case TRANSFER_SRC_ATOP:         return _("SrcAtop");
415         case TRANSFER_SRC_IN:           return _("SrcIn");
416         case TRANSFER_SRC_OUT:          return _("SrcOut");
417         case TRANSFER_SRC_OVER:         return _("SrcOver");
418         case TRANSFER_AND:              return _("AND");
419         case TRANSFER_OR:               return _("OR");
420         case TRANSFER_XOR:              return _("XOR");
421         case TRANSFER_OVERLAY:          return _("Overlay");
422         case TRANSFER_SCREEN:           return _("Screen");
423         case TRANSFER_BURN:             return _("Burn");
424         case TRANSFER_DODGE:            return _("Dodge");
425         case TRANSFER_HARDLIGHT:        return _("Hardlight");
426         case TRANSFER_SOFTLIGHT:        return _("Softlight");
427         case TRANSFER_DIFFERENCE:       return _("Difference");
428         }
429         return _("Normal");
430 }
431
432
433
434 VModePatchItem::VModePatchItem(VModePatch *popup, const char *text, int mode)
435  : BC_MenuItem(text)
436 {
437         this->popup = popup;
438         this->mode = mode;
439         if(this->mode == popup->mode) set_checked(1);
440 }
441
442 int VModePatchItem::handle_event()
443 {
444         if( mode >= 0 ) {
445                 popup->mode = mode;
446 //              popup->set_icon(popup->patch->patchbay->mode_to_icon(mode));
447                 popup->handle_event();
448         }
449         return 1;
450 }
451
452 VModePatchSubMenu::VModePatchSubMenu(VModePatchItem *mode_item)
453 {
454         this->mode_item = mode_item;
455 }
456 VModePatchSubMenu::~VModePatchSubMenu()
457 {
458 }
459
460 VModeSubMenuItem::VModeSubMenuItem(VModePatchSubMenu *submenu, const char *text, int mode)
461  : BC_MenuItem(text)
462 {
463         this->submenu = submenu;
464         this->mode = mode;
465         VModePatch *popup = submenu->mode_item->popup;
466         if(this->mode == popup->mode) set_checked(1);
467 }
468 VModeSubMenuItem::~VModeSubMenuItem()
469 {
470 }
471
472 int VModeSubMenuItem::handle_event()
473 {
474         VModePatch *popup = submenu->mode_item->popup;
475         popup->mode = mode;
476 //      popup->set_icon(popup->patch->patchbay->mode_to_icon(mode));
477         popup->handle_event();
478         return 1;
479 }
480
481
482 VKeyModePatch::VKeyModePatch(MWindow *mwindow, VPatchGUI *patch)
483  : VModePatch(mwindow, patch)
484 {
485 }
486
487 int VKeyModePatch::button_release_event()
488 {
489         VModePatch::button_release_event();
490         return 0;
491 }
492
493 int VKeyModePatch::handle_event()
494 {
495         int ret = VModePatch::handle_event();
496         VModePatch *mode = patch->mode;
497         if( mode )
498                 mode->update(this->mode);
499         return ret;
500 }
501
502
503