fix trace locks hang, drag handle rework-again, 12 reset btns on plugins, booby on
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / swapframes / swapframes.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 "bcdisplayinfo.h"
23 #include "clip.h"
24 #include "bchash.h"
25 #include "filexml.h"
26 #include "guicast.h"
27 #include "language.h"
28 #include "bccolors.h"
29 #include "pluginvclient.h"
30 #include "swapframes.h"
31 #include "vframe.h"
32
33 #include <stdint.h>
34 #include <string.h>
35
36
37
38
39 REGISTER_PLUGIN(SwapFrames)
40
41
42
43
44
45
46
47 SwapFramesConfig::SwapFramesConfig()
48 {
49         reset();
50 }
51
52 void SwapFramesConfig::reset()
53 {
54         on = 1;
55         swap_even = 1;
56 }
57
58 void SwapFramesConfig::copy_from(SwapFramesConfig &src)
59 {
60         on = src.on;
61         swap_even = src.swap_even;
62 }
63
64 int SwapFramesConfig::equivalent(SwapFramesConfig &src)
65 {
66         return on == src.on &&
67                 swap_even == src.swap_even;
68 }
69
70 void SwapFramesConfig::interpolate(SwapFramesConfig &prev,
71         SwapFramesConfig &next,
72         int64_t prev_frame,
73         int64_t next_frame,
74         int64_t current_frame)
75 {
76         on = prev.on;
77         swap_even = prev.swap_even;
78 }
79
80
81
82
83
84
85
86
87
88
89 SwapFramesOn::SwapFramesOn(SwapFrames *plugin,
90         int x, int y)
91  : BC_CheckBox(x,
92         y,
93         plugin->config.on,
94         _("Enabled"))
95 {
96         this->plugin = plugin;
97 }
98
99 int SwapFramesOn::handle_event()
100 {
101         plugin->config.on = get_value();
102         plugin->send_configure_change();
103         return 1;
104 }
105
106
107
108
109
110
111 SwapFramesEven::SwapFramesEven(SwapFrames *plugin,
112         SwapFramesWindow *gui,
113         int x,
114         int y)
115  : BC_Radial(x,
116         y,
117         plugin->config.swap_even,
118         _("Swap 0-1, 2-3, 4-5..."))
119 {
120         this->plugin = plugin;
121         this->gui = gui;
122 }
123
124 int SwapFramesEven::handle_event()
125 {
126         plugin->config.swap_even = 1;
127         gui->swap_odd->update(0);
128         plugin->send_configure_change();
129         return 1;
130 }
131
132
133
134
135
136
137 SwapFramesOdd::SwapFramesOdd(SwapFrames *plugin,
138         SwapFramesWindow *gui,
139         int x,
140         int y)
141  : BC_Radial(x,
142         y,
143         !plugin->config.swap_even,
144         _("Swap 1-2, 3-4, 5-6..."))
145 {
146         this->plugin = plugin;
147         this->gui = gui;
148 }
149
150 int SwapFramesOdd::handle_event()
151 {
152         plugin->config.swap_even = 0;
153         gui->swap_even->update(0);
154         plugin->send_configure_change();
155         return 1;
156 }
157
158
159
160
161
162
163
164 SwapFramesReset::SwapFramesReset(SwapFrames *plugin, SwapFramesWindow *gui, int x, int y)
165  : BC_GenericButton(x, y, _("Reset"))
166 {
167         this->plugin = plugin;
168         this->gui = gui;
169 }
170 SwapFramesReset::~SwapFramesReset()
171 {
172 }
173 int SwapFramesReset::handle_event()
174 {
175         plugin->config.reset();
176         gui->update();
177         plugin->send_configure_change();
178         return 1;
179 }
180
181
182
183
184
185 SwapFramesWindow::SwapFramesWindow(SwapFrames *plugin)
186  : PluginClientWindow(plugin,
187         260,
188         135,
189         260,
190         135,
191         0)
192 {
193         this->plugin = plugin;
194 }
195
196 void SwapFramesWindow::create_objects()
197 {
198         int x = 10, y = 10;
199         add_subwindow(on = new SwapFramesOn(plugin, x, y));
200         y += on->get_h() + 5;
201         BC_Bar *bar;
202         add_subwindow(bar = new BC_Bar(x, y, get_w() - x * 2));
203         y += bar->get_h() + 5;
204         add_subwindow(swap_even = new SwapFramesEven(plugin,
205                 this,
206                 x,
207                 y));
208         y += swap_even->get_h() + 5;
209         add_subwindow(swap_odd = new SwapFramesOdd(plugin,
210                 this,
211                 x,
212                 y));
213
214         y += 35;
215         add_subwindow(reset = new SwapFramesReset(plugin, this, x, y));
216
217         show_window();
218 }
219
220 // for Reset button
221 void SwapFramesWindow::update()
222 {
223         on->update(plugin->config.swap_even);
224         swap_even->update(plugin->config.swap_even);
225         swap_odd->update(!plugin->config.swap_even);
226 }
227
228
229
230
231
232
233
234
235
236
237
238 SwapFrames::SwapFrames(PluginServer *server)
239  : PluginVClient(server)
240 {
241
242         buffer = 0;
243         buffer_position = -1;
244         prev_frame = -1;
245 }
246
247 SwapFrames::~SwapFrames()
248 {
249
250         delete buffer;
251 }
252
253 const char* SwapFrames::plugin_title() { return N_("Swap Frames"); }
254 int SwapFrames::is_realtime() { return 1; }
255
256 NEW_WINDOW_MACRO(SwapFrames, SwapFramesWindow)
257 LOAD_CONFIGURATION_MACRO(SwapFrames, SwapFramesConfig)
258
259 void SwapFrames::update_gui()
260 {
261         if(thread)
262         {
263                 thread->window->lock_window();
264                 if(load_configuration())
265                 {
266                         ((SwapFramesWindow*)thread->window)->on->update(config.on);
267                         ((SwapFramesWindow*)thread->window)->swap_even->update(config.swap_even);
268                         ((SwapFramesWindow*)thread->window)->swap_odd->update(!config.swap_even);
269                 }
270                 thread->window->unlock_window();
271         }
272 }
273
274
275 void SwapFrames::save_data(KeyFrame *keyframe)
276 {
277         FileXML output;
278         output.set_shared_output(keyframe->xbuf);
279         output.tag.set_title("SWAPFRAMES");
280         output.tag.set_property("ON", config.on);
281         output.tag.set_property("SWAP_EVEN", config.swap_even);
282         output.append_tag();
283         output.tag.set_title("/SWAPFRAMES");
284         output.append_tag();
285         output.append_newline();
286         output.terminate_string();
287 }
288
289 void SwapFrames::read_data(KeyFrame *keyframe)
290 {
291         FileXML input;
292         input.set_shared_input(keyframe->xbuf);
293         while(!input.read_tag())
294         {
295                 if(input.tag.title_is("SWAPFRAMES"))
296                 {
297                         config.on = input.tag.get_property("ON", config.on);
298                         config.swap_even = input.tag.get_property("SWAP_EVEN", config.swap_even);
299                 }
300         }
301 }
302
303
304 int SwapFrames::process_buffer(VFrame *frame,
305         int64_t start_position,
306         double frame_rate)
307 {
308         load_configuration();
309         int64_t new_position = start_position;
310
311         if(config.on)
312         {
313                 if(config.swap_even)
314                 {
315                         if(new_position % 2)
316                                 new_position--;
317                         else
318                                 new_position++;
319                 }
320                 else
321                 {
322                         if(new_position % 2)
323                                 new_position++;
324                         else
325                                 new_position--;
326                 }
327         }
328
329 // Recall a frame
330 //printf("SwapFrames::process_buffer %d new_position=%lld\n", __LINE__, new_position);
331         if(buffer && buffer_position == new_position)
332         {
333 //printf("SwapFrames::process_buffer %d\n", __LINE__);
334                 frame->copy_from(buffer);
335         }
336         else
337 // Skipped a frame
338         if(new_position > prev_frame + 1)
339         {
340 //printf("SwapFrames::process_buffer %d\n", __LINE__);
341                 if(!buffer)
342                         buffer = new VFrame(frame->get_w(), frame->get_h(),
343                                 frame->get_color_model(), 0);
344                 buffer_position = new_position - 1;
345                 read_frame(buffer,
346                         0,
347                         buffer_position,
348                         frame_rate,
349                         0);
350                 read_frame(frame,
351                         0,
352                         new_position,
353                         frame_rate,
354                         get_use_opengl());
355                 prev_frame = new_position;
356         }
357 // Read new frame
358         else
359         {
360 //printf("SwapFrames::process_buffer %d\n", __LINE__);
361                 read_frame(frame,
362                         0,
363                         new_position,
364                         frame_rate,
365                         get_use_opengl());
366                 prev_frame = new_position;
367         }
368
369
370         return 0;
371 }
372