dynamic keyframes, textbox rework, andrea ffmpeg.opts, perpetual chkpt undo, lv2...
[goodguy/history.git] / cinelerra-5.1 / plugins / reversevideo / reversevideo.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 "bchash.h"
24 #include "bcsignals.h"
25 #include "filexml.h"
26 #include "guicast.h"
27 #include "language.h"
28 #include "pluginvclient.h"
29 #include "transportque.h"
30
31 #include <string.h>
32
33 class ReverseVideo;
34
35 class ReverseVideoConfig
36 {
37 public:
38         ReverseVideoConfig();
39         int enabled;
40 };
41
42
43 class ReverseVideoEnabled : public BC_CheckBox
44 {
45 public:
46         ReverseVideoEnabled(ReverseVideo *plugin,
47                 int x,
48                 int y);
49         int handle_event();
50         ReverseVideo *plugin;
51 };
52
53 class ReverseVideoWindow : public PluginClientWindow
54 {
55 public:
56         ReverseVideoWindow(ReverseVideo *plugin);
57         ~ReverseVideoWindow();
58         void create_objects();
59
60         ReverseVideo *plugin;
61         ReverseVideoEnabled *enabled;
62 };
63
64
65 class ReverseVideo : public PluginVClient
66 {
67 public:
68         ReverseVideo(PluginServer *server);
69         ~ReverseVideo();
70
71         PLUGIN_CLASS_MEMBERS(ReverseVideoConfig)
72
73         void save_data(KeyFrame *keyframe);
74         void read_data(KeyFrame *keyframe);
75         void update_gui();
76         int is_realtime();
77         int process_buffer(VFrame *frame,
78                         int64_t start_position,
79                         double frame_rate);
80
81         int64_t input_position;
82 };
83
84
85
86
87
88
89
90 REGISTER_PLUGIN(ReverseVideo);
91
92
93
94 ReverseVideoConfig::ReverseVideoConfig()
95 {
96         enabled = 1;
97 }
98
99
100
101
102
103 ReverseVideoWindow::ReverseVideoWindow(ReverseVideo *plugin)
104  : PluginClientWindow(plugin,
105         210,
106         160,
107         200,
108         160,
109         0)
110 {
111         this->plugin = plugin;
112 }
113
114 ReverseVideoWindow::~ReverseVideoWindow()
115 {
116 }
117
118 void ReverseVideoWindow::create_objects()
119 {
120         int x = 10, y = 10;
121
122         add_subwindow(enabled = new ReverseVideoEnabled(plugin,
123                 x,
124                 y));
125         show_window();
126         flush();
127 }
128
129
130
131
132
133
134
135
136
137
138
139
140 ReverseVideoEnabled::ReverseVideoEnabled(ReverseVideo *plugin,
141         int x,
142         int y)
143  : BC_CheckBox(x,
144         y,
145         plugin->config.enabled,
146         _("Enabled"))
147 {
148         this->plugin = plugin;
149 }
150
151 int ReverseVideoEnabled::handle_event()
152 {
153         plugin->config.enabled = get_value();
154         plugin->send_configure_change();
155         return 1;
156 }
157
158
159
160
161
162
163
164
165
166 ReverseVideo::ReverseVideo(PluginServer *server)
167  : PluginVClient(server)
168 {
169
170 }
171
172
173 ReverseVideo::~ReverseVideo()
174 {
175
176 }
177
178 const char* ReverseVideo::plugin_title() { return N_("Reverse video"); }
179 int ReverseVideo::is_realtime() { return 1; }
180
181
182 NEW_WINDOW_MACRO(ReverseVideo, ReverseVideoWindow)
183
184
185 int ReverseVideo::process_buffer(VFrame *frame,
186                 int64_t start_position,
187                 double frame_rate)
188 {
189         load_configuration();
190
191         if(config.enabled)
192                 read_frame(frame,
193                         0,
194                         input_position,
195                         frame_rate,
196                         0);
197         else
198                 read_frame(frame,
199                         0,
200                         start_position,
201                         frame_rate,
202                         0);
203         return 0;
204 }
205
206
207
208
209 int ReverseVideo::load_configuration()
210 {
211         KeyFrame *prev_keyframe, *next_keyframe;
212         next_keyframe = get_next_keyframe(get_source_position());
213         prev_keyframe = get_prev_keyframe(get_source_position());
214 // Previous keyframe stays in config object.
215         read_data(prev_keyframe);
216
217         int64_t prev_position = edl_to_local(prev_keyframe->position);
218         int64_t next_position = edl_to_local(next_keyframe->position);
219
220         if(prev_position == 0 && next_position == 0)
221         {
222                 next_position = prev_position = get_source_start();
223         }
224
225 // Get range to flip in requested rate
226         int64_t range_start = prev_position;
227         int64_t range_end = next_position;
228
229 // Between keyframe and edge of range or no keyframes
230         if(range_start == range_end)
231         {
232 // Between first keyframe and start of effect
233                 if(get_source_position() >= get_source_start() &&
234                         get_source_position() < range_start)
235                 {
236                         range_start = get_source_start();
237                 }
238                 else
239 // Between last keyframe and end of effect
240                 if(get_source_position() >= range_start &&
241                         get_source_position() < get_source_start() + get_total_len())
242                 {
243                         range_end = get_source_start() + get_total_len();
244                 }
245                 else
246                 {
247 // Should never get here
248                         ;
249                 }
250         }
251
252
253 // Convert start position to new direction
254         if(get_direction() == PLAY_FORWARD)
255         {
256 //printf("ReverseVideo::load_configuration %d %ld %ld %ld %ld %ld\n",
257 //      __LINE__,
258 //      get_source_position(),
259 //      get_source_start(),
260 //      get_total_len(),
261 //      range_start,
262 //      range_end);
263                 input_position = get_source_position() - range_start;
264                 input_position = range_end - input_position - 1;
265         }
266         else
267         {
268                 input_position = range_end - get_source_position();
269                 input_position = range_start + input_position + 1;
270         }
271 // printf("ReverseVideo::load_configuration 2 start=%lld end=%lld current=%lld input=%lld\n",
272 // range_start,
273 // range_end,
274 // get_source_position(),
275 // input_position);
276
277         return 0;
278 }
279
280
281 void ReverseVideo::save_data(KeyFrame *keyframe)
282 {
283         FileXML output;
284
285 // cause data to be stored directly in text
286         output.set_shared_output(keyframe->xbuf);
287         output.tag.set_title("REVERSEVIDEO");
288         output.tag.set_property("ENABLED", config.enabled);
289         output.append_tag();
290         output.tag.set_title("/REVERSEVIDEO");
291         output.append_tag();
292         output.append_newline();
293         output.terminate_string();
294 }
295
296 void ReverseVideo::read_data(KeyFrame *keyframe)
297 {
298         FileXML input;
299
300         input.set_shared_input(keyframe->xbuf);
301
302         while(!input.read_tag())
303         {
304                 if(input.tag.title_is("REVERSEVIDEO"))
305                 {
306                         config.enabled = input.tag.get_property("ENABLED", config.enabled);
307                 }
308         }
309 }
310
311 void ReverseVideo::update_gui()
312 {
313         if(thread)
314         {
315                 load_configuration();
316                 thread->window->lock_window();
317                 ((ReverseVideoWindow*)thread->window)->enabled->update(config.enabled);
318                 thread->window->unlock_window();
319         }
320 }
321
322
323
324
325