Condense the xml-cleanup into a short feature-branch
[cinelerra_cv/mob.git] / plugins / freezeframe / freezeframe.C
blobb9add26748675b5447d34391fed13153c5e693d0
1 #include "bcdisplayinfo.h"
2 #include "bchash.h"
3 #include "filexml.h"
4 #include "freezeframe.h"
5 #include "language.h"
6 #include "picon_png.h"
10 #include <string.h>
13 REGISTER_PLUGIN(FreezeFrameMain)
19 FreezeFrameConfig::FreezeFrameConfig()
21         enabled = 0;
22         line_double = 0;
25 void FreezeFrameConfig::copy_from(FreezeFrameConfig &that)
27         enabled = that.enabled;
28         line_double = that.line_double;
31 int FreezeFrameConfig::equivalent(FreezeFrameConfig &that)
33         return enabled == that.enabled &&
34                 line_double == that.line_double;
37 void FreezeFrameConfig::interpolate(FreezeFrameConfig &prev, 
38         FreezeFrameConfig &next, 
39         long prev_frame, 
40         long next_frame, 
41         long current_frame)
43         this->enabled = prev.enabled;
44         this->line_double = prev.line_double;
56 FreezeFrameWindow::FreezeFrameWindow(FreezeFrameMain *client, int x, int y)
57  : BC_Window(client->get_gui_string(),
58         x,
59         y,
60         200,
61         100,
62         200,
63         100,
64         0,
65         0,
66         1)
68         this->client = client; 
71 FreezeFrameWindow::~FreezeFrameWindow()
75 int FreezeFrameWindow::create_objects()
77         int x = 10, y = 10;
78         add_tool(enabled = new FreezeFrameToggle(client, 
79                 &client->config.enabled,
80                 x, 
81                 y,
82                 _("Enabled")));
83 // Try using extra effect for the line double since it doesn't
84 // change the overhead.
85 //      y += 30;
86 //      add_tool(line_double = new FreezeFrameToggle(client, 
87 //              &client->config.line_double,
88 //              x, 
89 //              y,
90 //              _("Line double")));
91         show_window();
92         flush();
93         return 0;
96 WINDOW_CLOSE_EVENT(FreezeFrameWindow)
101 PLUGIN_THREAD_OBJECT(FreezeFrameMain, FreezeFrameThread, FreezeFrameWindow)
107 FreezeFrameToggle::FreezeFrameToggle(FreezeFrameMain *client, 
108         int *value, 
109         int x, 
110         int y,
111         char *text)
112  : BC_CheckBox(x, y, *value, text)
114         this->client = client;
115         this->value = value;
117 FreezeFrameToggle::~FreezeFrameToggle()
120 int FreezeFrameToggle::handle_event()
122         *value = get_value();
123         client->send_configure_change();
124         return 1;
138 FreezeFrameMain::FreezeFrameMain(PluginServer *server)
139  : PluginVClient(server)
141         PLUGIN_CONSTRUCTOR_MACRO
142         first_frame = 0;
143         first_frame_position = -1;
146 FreezeFrameMain::~FreezeFrameMain()
148         PLUGIN_DESTRUCTOR_MACRO
149         if(first_frame) delete first_frame;
152 char* FreezeFrameMain::plugin_title() { return N_("Freeze Frame"); }
153 int FreezeFrameMain::is_synthesis() { return 1; }
154 int FreezeFrameMain::is_realtime() { return 1; }
157 SHOW_GUI_MACRO(FreezeFrameMain, FreezeFrameThread)
159 RAISE_WINDOW_MACRO(FreezeFrameMain)
161 SET_STRING_MACRO(FreezeFrameMain)
163 NEW_PICON_MACRO(FreezeFrameMain)
165 int FreezeFrameMain::load_configuration()
167         KeyFrame *prev_keyframe = get_prev_keyframe(get_source_position());
168         int64_t prev_position = edl_to_local(prev_keyframe->position);
169         if(prev_position < get_source_start()) prev_position = get_source_start();
170         read_data(prev_keyframe);
171 // Invalidate stored frame
172         if(config.enabled) first_frame_position = prev_position;
173         return 0;
176 void FreezeFrameMain::update_gui()
178         if(thread)
179         {
180                 load_configuration();
181                 thread->window->lock_window();
182                 thread->window->enabled->update(config.enabled);
183 //              thread->window->line_double->update(config.line_double);
184                 thread->window->unlock_window();
185         }
188 void FreezeFrameMain::save_data(KeyFrame *keyframe)
190         FileXML output;
192 // cause data to be stored directly in text
193         output.set_shared_string(keyframe->data, MESSAGESIZE);
194         output.tag.set_title("FREEZEFRAME");
195         output.append_tag();
196         if(config.enabled)
197         {
198                 output.tag.set_title("ENABLED");
199                 output.append_tag();
200                 output.tag.set_title("/ENABLED");
201                 output.append_tag();
202         }
203         if(config.line_double)
204         {
205                 output.tag.set_title("LINE_DOUBLE");
206                 output.append_tag();
207                 output.tag.set_title("/LINE_DOUBLE");
208                 output.append_tag();
209         }
210         output.tag.set_title("/FREEZEFRAME");
211         output.append_tag();
212         output.terminate_string();
213 // data is now in *text
216 void FreezeFrameMain::read_data(KeyFrame *keyframe)
218         FileXML input;
220         input.set_shared_string(keyframe->data, strlen(keyframe->data));
222         int result = 0;
223         config.enabled = 0;
224         config.line_double = 0;
226         while(!result)
227         {
228                 result = input.read_tag();
230                 if(!result)
231                 {
232                         if(input.tag.title_is("ENABLED"))
233                         {
234                                 config.enabled = 1;
235                         }
236                         if(input.tag.title_is("LINE_DOUBLE"))
237                         {
238                                 config.line_double = 1;
239                         }
240                 }
241         }
244 int FreezeFrameMain::load_defaults()
246         char directory[BCTEXTLEN], string[BCTEXTLEN];
247 // set the default directory
248         sprintf(directory, "%sfreezeframe.rc", BCASTDIR);
250 // load the defaults
251         defaults = new BC_Hash(directory);
252         defaults->load();
254         config.enabled = defaults->get("ENABLED", config.enabled);
255         config.line_double = defaults->get("LINE_DOUBLE", config.line_double);
256         return 0;
259 int FreezeFrameMain::save_defaults()
261         defaults->update("ENABLED", config.enabled);
262         defaults->update("LINE_DOUBLE", config.line_double);
263         defaults->save();
264         return 0;
272 int FreezeFrameMain::process_buffer(VFrame *frame,
273                 int64_t start_position,
274                 double frame_rate)
276         int64_t previous_first_frame = first_frame_position;
277         load_configuration();
279 // Just entered frozen range
280         if(!first_frame && config.enabled)
281         {
282                 if(!first_frame)
283                         first_frame = new VFrame(0, 
284                                 frame->get_w(), 
285                                 frame->get_h(),
286                                 frame->get_color_model());
287 printf("FreezeFrameMain::process_buffer 1 %lld\n", first_frame_position);
288                 read_frame(first_frame, 
289                                 0, 
290                                 first_frame_position,
291                                 frame_rate,
292                                 get_use_opengl());
293                 if(get_use_opengl()) return run_opengl();
294                 frame->copy_from(first_frame);
295         }
296         else
297 // Still not frozen
298         if(!first_frame && !config.enabled)
299         {
300                 read_frame(frame, 
301                         0, 
302                         start_position,
303                         frame_rate,
304                         get_use_opengl());
305         }
306         else
307 // Just left frozen range
308         if(first_frame && !config.enabled)
309         {
310                 delete first_frame;
311                 first_frame = 0;
312                 read_frame(frame, 
313                         0, 
314                         start_position,
315                         frame_rate,
316                         get_use_opengl());
317         }
318         else
319 // Still frozen
320         if(first_frame && config.enabled)
321         {
322 // Had a keyframe in frozen range.  Load new first frame
323                 if(previous_first_frame != first_frame_position)
324                 {
325                         read_frame(first_frame, 
326                                 0, 
327                                 first_frame_position,
328                                 frame_rate,
329                                 get_use_opengl());
330                 }
331                 if(get_use_opengl()) return run_opengl();
332                 frame->copy_from(first_frame);
333         }
336 // Line double to support interlacing
337 //      if(config.line_double && config.enabled)
338 //      {
339 //              for(int i = 0; i < frame->get_h() - 1; i += 2)
340 //              {
341 //                      memcpy(frame->get_rows()[i + 1], 
342 //                              frame->get_rows()[i], 
343 //                              frame->get_bytes_per_line());
344 //              }
345 //      }
349         return 0;
352 int FreezeFrameMain::handle_opengl()
354 #ifdef HAVE_GL
355         get_output()->enable_opengl();
356         get_output()->init_screen();
357         first_frame->to_texture();
358         first_frame->bind_texture(0);
359         first_frame->draw_texture();
360         get_output()->set_opengl_state(VFrame::SCREEN);
361 #endif
362         return 0;