Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[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 "intauto.h"
29 #include "intautos.h"
30 #include "language.h"
31 #include "localsession.h"
32 #include "mainsession.h"
33 #include "mainundo.h"
34 #include "mwindow.h"
35 #include "mwindowgui.h"
36 #include "overlayframe.inc"
37 #include "patchbay.h"
38 #include "theme.h"
39 #include "trackcanvas.h"
40 #include "vpatchgui.h"
41 #include "vtrack.h"
42
43 #include <string.h>
44
45
46
47
48
49 VPatchGUI::VPatchGUI(MWindow *mwindow, PatchBay *patchbay, VTrack *track, int x, int y)
50  : PatchGUI(mwindow, patchbay, track, x, y)
51 {
52         data_type = TRACK_VIDEO;
53         this->vtrack = track;
54         mode = 0;
55         fade = 0;
56 }
57
58 VPatchGUI::~VPatchGUI()
59 {
60         if(fade) delete fade;
61         if(mode) delete mode;
62 }
63
64 void VPatchGUI::create_objects()
65 {
66         update(x, y);
67 }
68
69 int VPatchGUI::reposition(int x, int y)
70 {
71         //int x1 = 0;
72         int y1 = PatchGUI::reposition(x, y);
73
74         if(fade) fade->reposition_window(fade->get_x(),
75                 y1 + y);
76
77         y1 += mwindow->theme->fade_h;
78
79         if(mode) mode->reposition_window(mode->get_x(),
80                 y1 + y);
81
82         if(nudge) nudge->reposition_window(nudge->get_x(),
83                 y1 + y);
84
85
86         y1 += mwindow->theme->mode_h;
87
88         return y1;
89 }
90
91 int VPatchGUI::update(int x, int y)
92 {
93         int h = track->vertical_span(mwindow->theme);
94         int x1 = 0;
95         int y1 = PatchGUI::update(x, y);
96
97         if(fade)
98         {
99                 if(h - y1 < mwindow->theme->fade_h)
100                 {
101                         delete fade;
102                         fade = 0;
103                 }
104                 else
105                 {
106                         FloatAuto *previous = 0, *next = 0;
107                         double unit_position = mwindow->edl->local_session->get_selectionstart(1);
108                         unit_position = mwindow->edl->align_to_frame(unit_position, 0);
109                         unit_position = vtrack->to_units(unit_position, 0);
110                         int value = (int)((FloatAutos*)vtrack->automation->autos[AUTOMATION_FADE])->get_value(
111                                 (int64_t)unit_position, PLAY_FORWARD, previous, next);
112                         fade->update(fade->get_w(), value,
113                                      mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_VIDEO_FADE],
114                                      mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_VIDEO_FADE]);
115 //                      fade->update((int)fade->get_keyframe(mwindow, this)->value);
116                 }
117         }
118         else
119         if(h - y1 >= mwindow->theme->fade_h)
120         {
121                 patchbay->add_subwindow(fade = new VFadePatch(mwindow,
122                         this,
123                         x1 + x,
124                         y1 + y,
125                         patchbay->get_w() - 10));
126         }
127         y1 += mwindow->theme->fade_h;
128
129         if(mode)
130         {
131                 if(h - y1 < mwindow->theme->mode_h)
132                 {
133                         delete mode;
134                         mode = 0;
135                         delete nudge;
136                         nudge = 0;
137                 }
138                 else
139                 {
140                         mode->update(mode->get_keyframe(mwindow, this)->value);
141                         nudge->update();
142                 }
143         }
144         else
145         if(h - y1 >= mwindow->theme->mode_h)
146         {
147                 patchbay->add_subwindow(mode = new VModePatch(mwindow,
148                         this,
149                         x1 + x,
150                         y1 + y));
151                 mode->create_objects();
152                 x1 += mode->get_w() + 10;
153                 patchbay->add_subwindow(nudge = new NudgePatch(mwindow,
154                         this,
155                         x1 + x,
156                         y1 + y,
157                         patchbay->get_w() - x1 - 10));
158         }
159
160
161
162
163
164         y1 += mwindow->theme->mode_h;
165
166         return y1;
167 }
168
169
170
171 void VPatchGUI::synchronize_fade(float value_change)
172 {
173         if(fade && !change_source)
174         {
175                 fade->update(Units::to_int64(fade->get_value() + value_change));
176                 fade->update_edl();
177         }
178 }
179
180
181 VFadePatch::VFadePatch(MWindow *mwindow, VPatchGUI *patch, int x, int y, int w)
182  : BC_ISlider(x,
183                         y,
184                         0,
185                         w,
186                         w,
187                         mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_VIDEO_FADE],
188                         mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_VIDEO_FADE],
189                         (int64_t)get_keyframe(mwindow, patch)->get_value())
190 {
191         this->mwindow = mwindow;
192         this->patch = patch;
193 }
194
195 float VFadePatch::update_edl()
196 {
197         FloatAuto *current;
198         double position = mwindow->edl->local_session->get_selectionstart(1);
199         Autos *fade_autos = patch->vtrack->automation->autos[AUTOMATION_FADE];
200         int need_undo = !fade_autos->auto_exists_for_editing(position);
201
202         mwindow->undo->update_undo_before(_("fade"), need_undo ? 0 : this);
203
204         current = (FloatAuto*)fade_autos->get_auto_for_editing(position);
205
206         float result = get_value() - current->get_value();
207         current->set_value(get_value());
208
209         mwindow->undo->update_undo_after(_("fade"), LOAD_AUTOMATION);
210
211         return result;
212 }
213
214 int VFadePatch::handle_event()
215 {
216         if(shift_down())
217         {
218                 update(100);
219                 set_tooltip(get_caption());
220         }
221
222         patch->change_source = 1;
223
224         float change = update_edl();
225
226         if(patch->track->gang && patch->track->record)
227                 patch->patchbay->synchronize_faders(change, TRACK_VIDEO, patch->track);
228
229         patch->change_source = 0;
230
231
232         mwindow->gui->unlock_window();
233         mwindow->restart_brender();
234         mwindow->sync_parameters(CHANGE_PARAMS);
235         mwindow->gui->lock_window("VFadePatch::handle_event");
236         if(mwindow->edl->session->auto_conf->autos[AUTOMATION_FADE])
237         {
238                 mwindow->gui->draw_overlays(1);
239         }
240         return 1;
241 }
242
243 FloatAuto* VFadePatch::get_keyframe(MWindow *mwindow, VPatchGUI *patch)
244 {
245         double unit_position = mwindow->edl->local_session->get_selectionstart(1);
246         unit_position = mwindow->edl->align_to_frame(unit_position, 0);
247         unit_position = patch->vtrack->to_units(unit_position, 0);
248         Auto *current = 0;
249
250         return (FloatAuto*)patch->vtrack->automation->autos[AUTOMATION_FADE]->get_prev_auto(
251                 (int64_t)unit_position,
252                 PLAY_FORWARD,
253                 current);
254 }
255
256
257
258
259 VModePatch::VModePatch(MWindow *mwindow, VPatchGUI *patch, int x, int y)
260  : BC_PopupMenu(x,
261         y,
262         patch->patchbay->mode_icons[0]->get_w() + 20,
263         "",
264         1,
265         mwindow->theme->get_image_set("mode_popup", 0),
266         10)
267 {
268         this->mwindow = mwindow;
269         this->patch = patch;
270         this->mode = get_keyframe(mwindow, patch)->value;
271         set_icon(patch->patchbay->mode_to_icon(this->mode));
272         set_tooltip(_("Overlay mode"));
273 }
274
275 int VModePatch::handle_event()
276 {
277 // Set menu items
278 //      for(int i = 0; i < total_items(); i++)
279 //      {
280 //              VModePatchItem *item = (VModePatchItem*)get_item(i);
281 //              if(item->mode == mode)
282 //                      item->set_checked(1);
283 //              else
284 //                      item->set_checked(0);
285 //      }
286         update(mode);
287
288 // Set keyframe
289         IntAuto *current;
290         double position = mwindow->edl->local_session->get_selectionstart(1);
291         Autos *mode_autos = patch->vtrack->automation->autos[AUTOMATION_MODE];
292         int need_undo = !mode_autos->auto_exists_for_editing(position);
293
294         mwindow->undo->update_undo_before(_("mode"), need_undo ? 0 : this);
295
296         current = (IntAuto*)mode_autos->get_auto_for_editing(position);
297         current->value = mode;
298
299         mwindow->undo->update_undo_after(_("mode"), LOAD_AUTOMATION);
300
301         mwindow->sync_parameters(CHANGE_PARAMS);
302
303         if(mwindow->edl->session->auto_conf->autos[AUTOMATION_MODE])
304         {
305                 mwindow->gui->draw_overlays(1);
306         }
307         mwindow->session->changes_made = 1;
308         return 1;
309 }
310
311 IntAuto* VModePatch::get_keyframe(MWindow *mwindow, VPatchGUI *patch)
312 {
313         Auto *current = 0;
314         double unit_position = mwindow->edl->local_session->get_selectionstart(1);
315         unit_position = mwindow->edl->align_to_frame(unit_position, 0);
316         unit_position = patch->vtrack->to_units(unit_position, 0);
317
318         return (IntAuto*)patch->vtrack->automation->autos[AUTOMATION_MODE]->get_prev_auto(
319                 (int64_t)unit_position,
320                 PLAY_FORWARD,
321                 current);
322 }
323
324
325 void VModePatch::create_objects()
326 {
327         for( int mode=0; mode<TRANSFER_TYPES; ++mode )
328                 add_item(new VModePatchItem(this, mode_to_text(mode), mode));
329 }
330
331 void VModePatch::update(int mode)
332 {
333         set_icon(patch->patchbay->mode_to_icon(mode));
334         for(int i = 0; i < total_items(); i++)
335         {
336                 VModePatchItem *item = (VModePatchItem*)get_item(i);
337                 item->set_checked(item->mode == mode);
338         }
339 }
340
341
342 const char* VModePatch::mode_to_text(int mode)
343 {
344         switch(mode) {
345                 case TRANSFER_NORMAL:           return _("Normal");
346                 case TRANSFER_ADDITION:         return _("Addition");
347                 case TRANSFER_SUBTRACT:         return _("Subtract");
348                 case TRANSFER_MULTIPLY:         return _("Multiply");
349                 case TRANSFER_DIVIDE:           return _("Divide");
350                 case TRANSFER_REPLACE:          return _("Replace");
351                 case TRANSFER_MAX:              return _("Max");
352                 case TRANSFER_MIN:              return _("Min");
353                 case TRANSFER_AVERAGE:          return _("Average");
354                 case TRANSFER_DARKEN:           return _("Darken");
355                 case TRANSFER_LIGHTEN:          return _("Lighten");
356                 case TRANSFER_DST:              return _("Dst");
357                 case TRANSFER_DST_ATOP:         return _("DstAtop");
358                 case TRANSFER_DST_IN:           return _("DstIn");
359                 case TRANSFER_DST_OUT:          return _("DstOut");
360                 case TRANSFER_DST_OVER:         return _("DstOver");
361                 case TRANSFER_SRC:              return _("Src");
362                 case TRANSFER_SRC_ATOP:         return _("SrcAtop");
363                 case TRANSFER_SRC_IN:           return _("SrcIn");
364                 case TRANSFER_SRC_OUT:          return _("SrcOut");
365                 case TRANSFER_SRC_OVER:         return _("SrcOver");
366                 case TRANSFER_OR:               return _("Or");
367                 case TRANSFER_XOR:              return _("Xor");
368         }
369         return _("Normal");
370 }
371
372
373
374 VModePatchItem::VModePatchItem(VModePatch *popup, const char *text, int mode)
375  : BC_MenuItem(text)
376 {
377         this->popup = popup;
378         this->mode = mode;
379         if(this->mode == popup->mode) set_checked(1);
380 }
381
382 int VModePatchItem::handle_event()
383 {
384         popup->mode = mode;
385 //      popup->set_icon(popup->patch->patchbay->mode_to_icon(mode));
386         popup->handle_event();
387         return 1;
388 }