r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / svg / svg.C
blob70adb133ab8ac28dbd77a14e9a5b0aa3e7c4d996
1 #include "clip.h"
2 #include "filexml.h"
3 #include "picon_png.h"
4 #include "svg.h"
5 #include "svgwin.h"
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <string.h>
9 #include <errno.h>
11 #include <libintl.h>
12 #define _(String) gettext(String)
13 #define gettext_noop(String) String
14 #define N_(String) gettext_noop (String)
16 #include "empty_svg.h"
18 REGISTER_PLUGIN(SvgMain)
20 SvgConfig::SvgConfig()
22         in_x = 0;
23         in_y = 0;
24         in_w = 720;
25         in_h = 480;
26         out_x = 0;
27         out_y = 0;
28         out_w = 720;
29         out_h = 480;
30         last_load = 0;
31         strcpy(svg_file, "");
34 int SvgConfig::equivalent(SvgConfig &that)
36         return EQUIV(in_x, that.in_x) && 
37                 EQUIV(in_y, that.in_y) && 
38                 EQUIV(in_w, that.in_w) && 
39                 EQUIV(in_h, that.in_h) &&
40                 EQUIV(out_x, that.out_x) && 
41                 EQUIV(out_y, that.out_y) && 
42                 EQUIV(out_w, that.out_w) &&
43                 EQUIV(out_h, that.out_h) &&
44                 !strcmp(svg_file, that.svg_file);
47 void SvgConfig::copy_from(SvgConfig &that)
49         in_x = that.in_x;
50         in_y = that.in_y;
51         in_w = that.in_w;
52         in_h = that.in_h;
53         out_x = that.out_x;
54         out_y = that.out_y;
55         out_w = that.out_w;
56         out_h = that.out_h;
57         last_load = that.last_load;
58         strcpy(svg_file, that.svg_file);
61 void SvgConfig::interpolate(SvgConfig &prev, 
62         SvgConfig &next, 
63         long prev_frame, 
64         long next_frame, 
65         long current_frame)
67         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
68         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
70         this->in_x = prev.in_x * prev_scale + next.in_x * next_scale;
71         this->in_y = prev.in_y * prev_scale + next.in_y * next_scale;
72         this->in_w = prev.in_w * prev_scale + next.in_w * next_scale;
73         this->in_h = prev.in_h * prev_scale + next.in_h * next_scale;
74         this->out_x = prev.out_x * prev_scale + next.out_x * next_scale;
75         this->out_y = prev.out_y * prev_scale + next.out_y * next_scale;
76         this->out_w = prev.out_w * prev_scale + next.out_w * next_scale;
77         this->out_h = prev.out_h * prev_scale + next.out_h * next_scale;
78         strcpy(this->svg_file, prev.svg_file);
88 SvgMain::SvgMain(PluginServer *server)
89  : PluginVClient(server)
91         temp_frame = 0;
92         overlayer = 0;
93         need_reconfigure = 0;
94         force_png_render = 1;
95         PLUGIN_CONSTRUCTOR_MACRO
98 SvgMain::~SvgMain()
100         PLUGIN_DESTRUCTOR_MACRO
102         if(temp_frame) delete temp_frame;
103         temp_frame = 0;
104         if(overlayer) delete overlayer;
105         overlayer = 0;
108 char* SvgMain::plugin_title() { return _("SVG via Sodipodi"); }
109 int SvgMain::is_realtime() { return 1; }
111 NEW_PICON_MACRO(SvgMain)
113 int SvgMain::load_defaults()
115         char directory[1024], string[1024];
116 // set the default directory
117         sprintf(directory, "%ssvg.rc", BCASTDIR);
119 // load the defaults
120         defaults = new Defaults(directory);
121         defaults->load();
124         config.in_x = defaults->get("IN_X", config.in_x);
125         config.in_y = defaults->get("IN_Y", config.in_y);
126         config.in_w = defaults->get("IN_W", config.in_w);
127         config.in_h = defaults->get("IN_H", config.in_h);
128         config.out_x = defaults->get("OUT_X", config.out_x);
129         config.out_y = defaults->get("OUT_Y", config.out_y);
130         config.out_w = defaults->get("OUT_W", config.out_w);
131         config.out_h = defaults->get("OUT_H", config.out_h);
132         strcpy(config.svg_file, "");
133 //      defaults->get("SVG_FILE", config.svg_file);
136 int SvgMain::save_defaults()
138         defaults->update("IN_X", config.in_x);
139         defaults->update("IN_Y", config.in_y);
140         defaults->update("IN_W", config.in_w);
141         defaults->update("IN_H", config.in_h);
142         defaults->update("OUT_X", config.out_x);
143         defaults->update("OUT_Y", config.out_y);
144         defaults->update("OUT_W", config.out_w);
145         defaults->update("OUT_H", config.out_h);
146         defaults->update("SVG_FILE", config.svg_file);
147         defaults->save();
150 LOAD_CONFIGURATION_MACRO(SvgMain, SvgConfig)
152 void SvgMain::save_data(KeyFrame *keyframe)
154         FileXML output;
156 // cause data to be stored directly in text
157         output.set_shared_string(keyframe->data, MESSAGESIZE);
159 // Store data
160         output.tag.set_title("SVG");
161         output.tag.set_property("IN_X", config.in_x);
162         output.tag.set_property("IN_Y", config.in_y);
163         output.tag.set_property("IN_W", config.in_w);
164         output.tag.set_property("IN_H", config.in_h);
165         output.tag.set_property("OUT_X", config.out_x);
166         output.tag.set_property("OUT_Y", config.out_y);
167         output.tag.set_property("OUT_W", config.out_w);
168         output.tag.set_property("OUT_H", config.out_h);
169         output.tag.set_property("SVG_FILE", config.svg_file);
170         output.append_tag();
172         output.terminate_string();
173 // data is now in *text
176 void SvgMain::read_data(KeyFrame *keyframe)
178         FileXML input;
180         input.set_shared_string(keyframe->data, strlen(keyframe->data));
182         int result = 0;
184         while(!result)
185         {
186                 result = input.read_tag();
188                 if(!result)
189                 {
190                         if(input.tag.title_is("SVG"))
191                         {
192                                 config.in_x = input.tag.get_property("IN_X", config.in_x);
193                                 config.in_y = input.tag.get_property("IN_Y", config.in_y);
194                                 config.in_w = input.tag.get_property("IN_W", config.in_w);
195                                 config.in_h = input.tag.get_property("IN_H", config.in_h);
196                                 config.out_x =  input.tag.get_property("OUT_X", config.out_x);
197                                 config.out_y =  input.tag.get_property("OUT_Y", config.out_y);
198                                 config.out_w =  input.tag.get_property("OUT_W", config.out_w);
199                                 config.out_h =  input.tag.get_property("OUT_H", config.out_h);
200                                 input.tag.get_property("SVG_FILE", config.svg_file);
201                         }
202                 }
203         }
213 int SvgMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
215         int fh_lockfile;
216         char filename_png[1024], filename_lock[1024];
217         struct stat st_svg, st_png;
218         int result_stat_png;
219         VFrame *input, *output;
220         input = input_ptr;
221         output = output_ptr;
223         
224         need_reconfigure |= load_configuration();
226         if (config.svg_file[0] == 0) {
227                 output->copy_from(input);
228                 return(0);
229         }
231         
232         strcpy(filename_png, config.svg_file);
233         strcat(filename_png, ".png");
234         // get the time of the last PNG change
235         result_stat_png = stat (filename_png, &st_png);
236         
239 //      printf("PNg mtime: %li, last_load: %li\n", st_png.st_mtime, config.last_load);
240         if (need_reconfigure || result_stat_png || (st_png.st_mtime > config.last_load)) {
241                 if (temp_frame)
242                         delete temp_frame;
243                 temp_frame = 0;
244         }
245         need_reconfigure = 0;
246         
247         if(!temp_frame) 
248         {
249                 int result;
250                 VFrame *tmp2;
251 //              printf("PROCESSING: %s %li\n", filename_png, config.last_load);
253                 if (result = stat (config.svg_file, &st_svg)) 
254                 {
255                         printf(_("Error calling stat() on svg file: %s\n"), config.svg_file); 
256                 }
257                 if (force_png_render || result_stat_png || 
258                         st_png.st_mtime < st_svg.st_mtime) 
259                 {
260                         char command[1024];
261                         sprintf(command,
262                                 "sodipodi --export-png=%s --export-width=%i --export-height=%i %s",
263                                 filename_png, (int)config.in_w, (int)config.in_h, config.svg_file);
264                         printf(_("Running command %s\n"), command);
265                         system(command);
266                         stat(filename_png, &st_png);
267                         force_png_render = 0;
268                 }
270                 // advisory lock, so we wait for sodipodi to finish
271                 strcpy(filename_lock, filename_png);
272                 strcat(filename_lock, ".lock");
273 //              printf("Cinelerra locking %s\n", filename_lock);
274                 fh_lockfile = open (filename_lock, O_CREAT | O_RDWR);
275                 int res = lockf(fh_lockfile, F_LOCK, 10);    // Blocking call - will wait for sodipodi to finish!
276 //              printf("Cinelerra: filehandle: %i, cineres: %i, errno: %i\n", fh_lockfile, res, errno);
277 //              perror("Cineerror");
278                 int fh = open(filename_png, O_RDONLY);
279                 unsigned char *pngdata;
280                 // get the size again
281                 result_stat_png = fstat (fh, &st_png);
283                 pngdata = (unsigned char*) malloc(st_png.st_size + 4);
284                 *((int32_t *)pngdata) = st_png.st_size; 
285 //              printf("PNG size: %i\n", st_png.st_size);
286                 result = read(fh, pngdata+4, st_png.st_size);
287                 close(fh);
288                 // unlock the file
289                 lockf(fh_lockfile, F_ULOCK, 0);
290                 close(fh_lockfile);
291 //              printf("Cinelerra unlocking\n");
293                 config.last_load = st_png.st_mtime; // we just updated
294                 
295                 tmp2 = new VFrame(pngdata);
296                 temp_frame = new VFrame(0, 
297                                         tmp2->get_w(),
298                                         tmp2->get_h(),
299                                         output_ptr->get_color_model());
300                 free (pngdata);
301                 cmodel_transfer(temp_frame->get_rows(),
302                         tmp2->get_rows(),
303                         0,
304                         0,
305                         0,
306                         0,
307                         0,
308                         0,
309                         0,
310                         0,
311                         tmp2->get_w(),
312                         tmp2->get_h(),
313                         0,
314                         0,
315                         temp_frame->get_w(),
316                         temp_frame->get_h(),
317                         tmp2->get_color_model(),
318                         temp_frame->get_color_model(),
319                         0,
320                         tmp2->get_w(),
321                         temp_frame->get_w());
323                 delete tmp2;
325         }
327 //printf("SvgMain::process_realtime 2 %p\n", input);
330         if(!overlayer)
331         {
332                 overlayer = new OverlayFrame(smp + 1);
333         }
335 //      output->clear_frame();
338 // printf("SvgMain::process_realtime 3 output=%p input=%p config.w=%f config.h=%f"
339 //      "%f %f %f %f -> %f %f %f %f\n", 
340 //      output,
341 //      input,
342 //      config.w, 
343 //      config.h,
344 //      in_x1, 
345 //      in_y1, 
346 //      in_x2, 
347 //      in_y2,
348 //      out_x1, 
349 //      out_y1, 
350 //      out_x2, 
351 //      out_y2);
352                 output->copy_from(input);
353                 overlayer->overlay(output, 
354                         temp_frame,
355                         config.in_x, 
356                         config.in_y, 
357                         config.in_x + config.in_w,
358                         config.in_y + config.in_h,
359                         config.out_x, 
360                         config.out_y, 
361                         config.out_x + config.out_w,
362                         config.out_y + config.out_h,
363                         1,
364                         TRANSFER_NORMAL,
365                         get_interpolation_type());
367         return(0);
373 SHOW_GUI_MACRO(SvgMain, SvgThread)
374                                                               
375 RAISE_WINDOW_MACRO(SvgMain)
377 SET_STRING_MACRO(SvgMain)
379 void SvgMain::update_gui()
381         if(thread)
382         {
383                 load_configuration();
384                 thread->window->lock_window();
385 //              thread->window->in_x->update(config.in_x);
386 //              thread->window->in_y->update(config.in_y);
387 //              thread->window->in_w->update(config.in_w);
388 //              thread->window->in_h->update(config.in_h);
389                 thread->window->out_x->update(config.out_x);
390                 thread->window->out_y->update(config.out_y);
391                 thread->window->out_w->update(config.out_w);
392                 thread->window->out_h->update(config.out_h);
393                 thread->window->svg_file_title->update(config.svg_file);
394                 thread->window->unlock_window();
395         }