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