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()
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)
57 last_load = that.last_load;
58 strcpy(svg_file, that.svg_file);
61 void SvgConfig::interpolate(SvgConfig &prev,
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)
95 PLUGIN_CONSTRUCTOR_MACRO
100 PLUGIN_DESTRUCTOR_MACRO
102 if(temp_frame) delete temp_frame;
104 if(overlayer) delete overlayer;
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);
120 defaults = new Defaults(directory);
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);
150 LOAD_CONFIGURATION_MACRO(SvgMain, SvgConfig)
152 void SvgMain::save_data(KeyFrame *keyframe)
156 // cause data to be stored directly in text
157 output.set_shared_string(keyframe->data, MESSAGESIZE);
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);
172 output.terminate_string();
173 // data is now in *text
176 void SvgMain::read_data(KeyFrame *keyframe)
180 input.set_shared_string(keyframe->data, strlen(keyframe->data));
186 result = input.read_tag();
190 if(input.tag.title_is("SVG"))
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);
213 int SvgMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
216 char filename_png[1024], filename_lock[1024];
217 struct stat st_svg, st_png;
219 VFrame *input, *output;
224 need_reconfigure |= load_configuration();
226 if (config.svg_file[0] == 0) {
227 output->copy_from(input);
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);
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)) {
245 need_reconfigure = 0;
251 // printf("PROCESSING: %s %li\n", filename_png, config.last_load);
253 if (result = stat (config.svg_file, &st_svg))
255 printf(_("Error calling stat() on svg file: %s\n"), config.svg_file);
257 if (force_png_render || result_stat_png ||
258 st_png.st_mtime < st_svg.st_mtime)
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);
266 stat(filename_png, &st_png);
267 force_png_render = 0;
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);
289 lockf(fh_lockfile, F_ULOCK, 0);
291 // printf("Cinelerra unlocking\n");
293 config.last_load = st_png.st_mtime; // we just updated
295 tmp2 = new VFrame(pngdata);
296 temp_frame = new VFrame(0,
299 output_ptr->get_color_model());
301 cmodel_transfer(temp_frame->get_rows(),
317 tmp2->get_color_model(),
318 temp_frame->get_color_model(),
321 temp_frame->get_w());
327 //printf("SvgMain::process_realtime 2 %p\n", input);
332 overlayer = new OverlayFrame(smp + 1);
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",
352 output->copy_from(input);
353 overlayer->overlay(output,
357 config.in_x + config.in_w,
358 config.in_y + config.in_h,
361 config.out_x + config.out_w,
362 config.out_y + config.out_h,
365 get_interpolation_type());
373 SHOW_GUI_MACRO(SvgMain, SvgThread)
375 RAISE_WINDOW_MACRO(SvgMain)
377 SET_STRING_MACRO(SvgMain)
379 void SvgMain::update_gui()
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();