69b395f6c86e17b31ea728ef1baad28edd07ee2e
[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         xS(260),
188         yS(135),
189         xS(260),
190         yS(135),
191         0)
192 {
193         this->plugin = plugin;
194 }
195
196 void SwapFramesWindow::create_objects()
197 {
198         int xs10 = xS(10);
199         int ys5 = yS(5), ys10 = yS(10), ys35 = yS(35);
200         int x = xs10, y = ys10;
201         add_subwindow(on = new SwapFramesOn(plugin, x, y));
202         y += on->get_h() + ys5;
203         BC_Bar *bar;
204         add_subwindow(bar = new BC_Bar(x, y, get_w() - x * xS(2)));
205         y += bar->get_h() + ys5;
206         add_subwindow(swap_even = new SwapFramesEven(plugin,
207                 this,
208                 x,
209                 y));
210         y += swap_even->get_h() + ys5;
211         add_subwindow(swap_odd = new SwapFramesOdd(plugin,
212                 this,
213                 x,
214                 y));
215
216         y += ys35;
217         add_subwindow(reset = new SwapFramesReset(plugin, this, x, y));
218
219         show_window();
220 }
221
222 // for Reset button
223 void SwapFramesWindow::update()
224 {
225         on->update(plugin->config.swap_even);
226         swap_even->update(plugin->config.swap_even);
227         swap_odd->update(!plugin->config.swap_even);
228 }
229
230
231
232
233
234
235
236
237
238
239
240 SwapFrames::SwapFrames(PluginServer *server)
241  : PluginVClient(server)
242 {
243
244         buffer = 0;
245         buffer_position = -1;
246         prev_frame = -1;
247 }
248
249 SwapFrames::~SwapFrames()
250 {
251
252         delete buffer;
253 }
254
255 const char* SwapFrames::plugin_title() { return N_("Swap Frames"); }
256 int SwapFrames::is_realtime() { return 1; }
257
258 NEW_WINDOW_MACRO(SwapFrames, SwapFramesWindow)
259 LOAD_CONFIGURATION_MACRO(SwapFrames, SwapFramesConfig)
260
261 void SwapFrames::update_gui()
262 {
263         if(thread)
264         {
265                 thread->window->lock_window();
266                 if(load_configuration())
267                 {
268                         ((SwapFramesWindow*)thread->window)->on->update(config.on);
269                         ((SwapFramesWindow*)thread->window)->swap_even->update(config.swap_even);
270                         ((SwapFramesWindow*)thread->window)->swap_odd->update(!config.swap_even);
271                 }
272                 thread->window->unlock_window();
273         }
274 }
275
276
277 void SwapFrames::save_data(KeyFrame *keyframe)
278 {
279         FileXML output;
280         output.set_shared_output(keyframe->xbuf);
281         output.tag.set_title("SWAPFRAMES");
282         output.tag.set_property("ON", config.on);
283         output.tag.set_property("SWAP_EVEN", config.swap_even);
284         output.append_tag();
285         output.tag.set_title("/SWAPFRAMES");
286         output.append_tag();
287         output.append_newline();
288         output.terminate_string();
289 }
290
291 void SwapFrames::read_data(KeyFrame *keyframe)
292 {
293         FileXML input;
294         input.set_shared_input(keyframe->xbuf);
295         while(!input.read_tag())
296         {
297                 if(input.tag.title_is("SWAPFRAMES"))
298                 {
299                         config.on = input.tag.get_property("ON", config.on);
300                         config.swap_even = input.tag.get_property("SWAP_EVEN", config.swap_even);
301                 }
302         }
303 }
304
305
306 int SwapFrames::process_buffer(VFrame *frame,
307         int64_t start_position,
308         double frame_rate)
309 {
310         load_configuration();
311         int64_t new_position = start_position;
312
313         if(config.on)
314         {
315                 if(config.swap_even)
316                 {
317                         if(new_position % 2)
318                                 new_position--;
319                         else
320                                 new_position++;
321                 }
322                 else
323                 {
324                         if(new_position % 2)
325                                 new_position++;
326                         else
327                                 new_position--;
328                 }
329         }
330
331 // Recall a frame
332 //printf("SwapFrames::process_buffer %d new_position=%lld\n", __LINE__, new_position);
333         if(buffer && buffer_position == new_position)
334         {
335 //printf("SwapFrames::process_buffer %d\n", __LINE__);
336                 frame->copy_from(buffer);
337         }
338         else
339 // Skipped a frame
340         if(new_position > prev_frame + 1)
341         {
342 //printf("SwapFrames::process_buffer %d\n", __LINE__);
343                 if(!buffer)
344                         buffer = new VFrame(frame->get_w(), frame->get_h(),
345                                 frame->get_color_model(), 0);
346                 buffer_position = new_position - 1;
347                 read_frame(buffer,
348                         0,
349                         buffer_position,
350                         frame_rate,
351                         0);
352                 read_frame(frame,
353                         0,
354                         new_position,
355                         frame_rate,
356                         get_use_opengl());
357                 prev_frame = new_position;
358         }
359 // Read new frame
360         else
361         {
362 //printf("SwapFrames::process_buffer %d\n", __LINE__);
363                 read_frame(frame,
364                         0,
365                         new_position,
366                         frame_rate,
367                         get_use_opengl());
368                 prev_frame = new_position;
369         }
370
371
372         return 0;
373 }
374