r860: Merge 2.1:
[cinelerra_cv.git] / plugins / freezeframe / freezeframe.C
blob31ba23e35739c9552df8e840f456c2b4b976fc12
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         y += 30;
84         add_tool(line_double = new FreezeFrameToggle(client, 
85                 &client->config.line_double,
86                 x, 
87                 y,
88                 _("Line double")));
89         show_window();
90         flush();
91         return 0;
94 WINDOW_CLOSE_EVENT(FreezeFrameWindow)
99 PLUGIN_THREAD_OBJECT(FreezeFrameMain, FreezeFrameThread, FreezeFrameWindow)
105 FreezeFrameToggle::FreezeFrameToggle(FreezeFrameMain *client, 
106         int *value, 
107         int x, 
108         int y,
109         char *text)
110  : BC_CheckBox(x, y, *value, text)
112         this->client = client;
113         this->value = value;
115 FreezeFrameToggle::~FreezeFrameToggle()
118 int FreezeFrameToggle::handle_event()
120         *value = get_value();
121         client->send_configure_change();
122         return 1;
136 FreezeFrameMain::FreezeFrameMain(PluginServer *server)
137  : PluginVClient(server)
139         PLUGIN_CONSTRUCTOR_MACRO
140         first_frame = 0;
141         first_frame_position = -1;
144 FreezeFrameMain::~FreezeFrameMain()
146         PLUGIN_DESTRUCTOR_MACRO
147         if(first_frame) delete first_frame;
150 char* FreezeFrameMain::plugin_title() { return N_("Freeze Frame"); }
151 int FreezeFrameMain::is_synthesis() { return 1; }
152 int FreezeFrameMain::is_realtime() { return 1; }
155 SHOW_GUI_MACRO(FreezeFrameMain, FreezeFrameThread)
157 RAISE_WINDOW_MACRO(FreezeFrameMain)
159 SET_STRING_MACRO(FreezeFrameMain)
161 NEW_PICON_MACRO(FreezeFrameMain)
163 int FreezeFrameMain::load_configuration()
165         KeyFrame *prev_keyframe = get_prev_keyframe(get_source_position());
166         int64_t prev_position = edl_to_local(prev_keyframe->position);
167         if(prev_position < get_source_start()) prev_position = get_source_start();
168         read_data(prev_keyframe);
169 // Invalidate stored frame
170         if(config.enabled) first_frame_position = prev_position;
171         return 0;
174 void FreezeFrameMain::update_gui()
176         if(thread)
177         {
178                 load_configuration();
179                 thread->window->lock_window();
180                 thread->window->enabled->update(config.enabled);
181                 thread->window->line_double->update(config.line_double);
182                 thread->window->unlock_window();
183         }
186 void FreezeFrameMain::save_data(KeyFrame *keyframe)
188         FileXML output;
190 // cause data to be stored directly in text
191         output.set_shared_string(keyframe->data, MESSAGESIZE);
192         output.tag.set_title("FREEZEFRAME");
193         output.append_tag();
194         if(config.enabled)
195         {
196                 output.tag.set_title("ENABLED");
197                 output.append_tag();
198         }
199         if(config.line_double)
200         {
201                 output.tag.set_title("LINE_DOUBLE");
202                 output.append_tag();
203         }
204         output.terminate_string();
205 // data is now in *text
208 void FreezeFrameMain::read_data(KeyFrame *keyframe)
210         FileXML input;
212         input.set_shared_string(keyframe->data, strlen(keyframe->data));
214         int result = 0;
215         config.enabled = 0;
216         config.line_double = 0;
218         while(!result)
219         {
220                 result = input.read_tag();
222                 if(!result)
223                 {
224                         if(input.tag.title_is("ENABLED"))
225                         {
226                                 config.enabled = 1;
227                         }
228                         if(input.tag.title_is("LINE_DOUBLE"))
229                         {
230                                 config.line_double = 1;
231                         }
232                 }
233         }
236 int FreezeFrameMain::load_defaults()
238         char directory[BCTEXTLEN], string[BCTEXTLEN];
239 // set the default directory
240         sprintf(directory, "%sfreezeframe.rc", BCASTDIR);
242 // load the defaults
243         defaults = new BC_Hash(directory);
244         defaults->load();
246         config.enabled = defaults->get("ENABLED", config.enabled);
247         config.line_double = defaults->get("LINE_DOUBLE", config.line_double);
248         return 0;
251 int FreezeFrameMain::save_defaults()
253         defaults->update("ENABLED", config.enabled);
254         defaults->update("LINE_DOUBLE", config.line_double);
255         defaults->save();
256         return 0;
264 int FreezeFrameMain::process_buffer(VFrame *frame,
265                 int64_t start_position,
266                 double frame_rate)
268         int64_t previous_first_frame = first_frame_position;
269         load_configuration();
271 // Just entered frozen range
272         if(!first_frame && config.enabled)
273         {
274                 if(!first_frame)
275                         first_frame = new VFrame(0, 
276                                 frame->get_w(), 
277                                 frame->get_h(),
278                                 frame->get_color_model());
279                 read_frame(first_frame, 
280                                 0, 
281                                 first_frame_position,
282                                 frame_rate);
283                 frame->copy_from(first_frame);
284         }
285         else
286 // Still not frozen
287         if(!first_frame && !config.enabled)
288         {
289                 read_frame(frame, 
290                         0, 
291                         start_position,
292                         frame_rate);
293         }
294         else
295 // Just left frozen range
296         if(first_frame && !config.enabled)
297         {
298                 delete first_frame;
299                 first_frame = 0;
300                 read_frame(frame, 
301                         0, 
302                         start_position,
303                         frame_rate);
304         }
305         else
306 // Still frozen
307         if(first_frame && config.enabled)
308         {
309 // Had a keyframe in frozen range.  Load new first frame
310                 if(previous_first_frame != first_frame_position)
311                 {
312                         read_frame(first_frame, 
313                                 0, 
314                                 first_frame_position,
315                                 frame_rate);
316                 }
317                 frame->copy_from(first_frame);
318         }
321 // Line double to support interlacing
322         if(config.line_double && config.enabled)
323         {
324                 for(int i = 0; i < frame->get_h() - 1; i += 2)
325                 {
326                         memcpy(frame->get_rows()[i + 1], 
327                                 frame->get_rows()[i], 
328                                 frame->get_bytes_per_line());
329                 }
330         }
334         return 0;