r864: Merge 2.1:
[cinelerra_cv.git] / plugins / svg / svgwin.C
blobdba269c704a88135880e3be13cd0b5704a0fa7ac
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "svgwin.h"
4 #include "string.h"
5 #include "filexml.h"
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <sys/types.h>
9 #include <fcntl.h>
10 #include <sys/stat.h>
12 struct fifo_struct {
13         int pid;
14         int action;  // 1 = update from client, 2 = client closes
15       };
18 #include <libintl.h>
19 #define _(String) gettext(String)
20 #define gettext_noop(String) String
21 #define N_(String) gettext_noop (String)
23 #include "empty_svg.h"
27 PLUGIN_THREAD_OBJECT(SvgMain, SvgThread, SvgWin)
34 SvgWin::SvgWin(SvgMain *client, int x, int y)
35  : BC_Window(client->gui_string, 
36         x,
37         y,
38         300, 
39         280, 
40         300, 
41         280, 
42         0, 
43         0,
44         1)
45
46         this->client = client; 
47         this->editing = 0;
50 SvgWin::~SvgWin()
54 int SvgWin::create_objects()
56         int x = 10, y = 10;
58 //      add_tool(new BC_Title(x, y, _("In X:")));
59         y += 20;
60 //      in_x = new SvgCoord(this, client, x, y, &client->config.in_x);
61 //      in_x->create_objects();
62         y += 30;
64 //      add_tool(new BC_Title(x, y, _("In Y:")));
65         y += 20;
66 //      in_y = new SvgCoord(this, client, x, y, &client->config.in_y);
67 //      in_y->create_objects();
68         y += 30;
70 //      add_tool(new BC_Title(x, y, _("In W:")));
71         y += 20;
72 //      in_w = new SvgCoord(this, client, x, y, &client->config.in_w);
73 //      in_w->create_objects();
74         y += 30;
76 //      add_tool(new BC_Title(x, y, _("In H:")));
77         y += 20;
78 //      in_h = new SvgCoord(this, client, x, y, &client->config.in_h);
79 //      in_h->create_objects();
80         y += 30;
83         x += 150;
84         y = 10;
85         add_tool(new BC_Title(x, y, _("Out X:")));
86         y += 20;
87         out_x = new SvgCoord(this, client, x, y, &client->config.out_x);
88         out_x->create_objects();
89         y += 30;
91         add_tool(new BC_Title(x, y, _("Out Y:")));
92         y += 20;
93         out_y = new SvgCoord(this, client, x, y, &client->config.out_y);
94         out_y->create_objects();
95         y += 30;
97 /*      add_tool(new BC_Title(x, y, _("Out W:")));
98         y += 20;
99         out_w = new SvgCoord(this, client, x, y, &client->config.out_w);
100         out_w->create_objects();
101         y += 30;
103         add_tool(new BC_Title(x, y, _("Out H:")));
104         y += 20;
105         out_h = new SvgCoord(this, client, x, y, &client->config.out_h);
106         out_h->create_objects();
107         y += 30;
109         x -= 150;
110         add_tool(new_svg_button = new NewSvgButton(client, this, x, y));
111         add_tool(edit_svg_button = new EditSvgButton(client, this, x+190, y));
112         add_tool(svg_file_title = new BC_Title(x, y+26, client->config.svg_file));
114         x +=150;
116         show_window();
117         flush();
118         return 0;
121 int SvgWin::close_event()
123         set_done(1);
124         return 1;
127 SvgCoord::SvgCoord(SvgWin *win, 
128         SvgMain *client, 
129         int x, 
130         int y,
131         float *value)
132  : BC_TumbleTextBox(win,
133         *value,
134         (float)0,
135         (float)3000,
136         x, 
137         y, 
138         100)
140 //printf("SvgWidth::SvgWidth %f\n", client->config.w);
141         this->client = client;
142         this->win = win;
143         this->value = value;
146 SvgCoord::~SvgCoord()
150 int SvgCoord::handle_event()
152         *value = atof(get_text());
154         client->send_configure_change();
155         return 1;
158 NewSvgButton::NewSvgButton(SvgMain *client, SvgWin *window, int x, int y)
159  : BC_GenericButton(x, y, _("New/Open SVG..."))
161         this->client = client;
162         this->window = window;
163         quit_now = 0;
165 int NewSvgButton::handle_event()
167         window->editing_lock.lock();
168         if (!window->editing) 
169         {
170                 window->editing = 1;
171                 window->editing_lock.unlock();
172                 quit_now = 0;
173                 start();
174         } else
175         {
176                 // FIXME - display an error
177                 window->editing_lock.unlock();
178         }
180         return 1;
183 void NewSvgButton::run()
185 // ======================================= get path from user
186         int result;
187 //printf("NewSvgButton::run 1\n");
188         char directory[1024], filename[1024];
192         sprintf(directory, "~");
193         client->defaults->get("DIRECTORY", directory);
194         result = 1;
195 // Loop until file is chosen
196         do{
197                 NewSvgWindow *new_window;
199                 new_window = new NewSvgWindow(client, window, directory);
200                 new_window->create_objects();
201                 new_window->update_filter("*.svg");
202                 result = new_window->run_window();
203                 client->defaults->update("DIRECTORY", new_window->get_path(0));
204                 strcpy(filename, new_window->get_path(0));
205                 delete new_window;
207 // Extend the filename with .svg
208                 if(strlen(filename) < 4 || 
209                         strcasecmp(&filename[strlen(filename) - 4], ".svg"))
210                 {
211                         strcat(filename, ".svg");
212                 }
214 // ======================================= try to save it
215                 if((filename[0] == 0) || (result == 1)) {
216                         window->editing_lock.lock();
217                         window->editing = 0;
218                         window->editing_lock.unlock();
219                         return;              // no filename given
220                 }
221                 FILE *in;
222                 if(in = fopen(filename, "rb"))
223                 {
224                         fclose(in);
225                         // file exists
226                         result = 0; 
227                 } else
228                 {
229                         // create fresh file
230                         in = fopen(filename, "w+");
231                         unsigned long size;
232                         size = (((unsigned long)empty_svg[0]) << 24) +
233                                 (((unsigned long)empty_svg[1]) << 16) +
234                                 (((unsigned long)empty_svg[2]) << 8) +
235                                 ((unsigned long)empty_svg[3]);
236                         printf("in: %p size: %li\n", in, size);
237                         // FIXME this is not cool on different arhitectures
238                         
239                         fwrite(empty_svg+4, size,  1, in);
240                         fclose(in);
241                         result = 0;
242                 }
243         } while(result);        // file doesn't exist so repeat
244         
246         window->svg_file_title->update(filename);
247         window->flush();
248         strcpy(client->config.svg_file, filename);
249         client->need_reconfigure = 1;
250         client->force_raw_render = 1;
251         client->send_configure_change();
253 // save it
254         if(quit_now) window->set_done(0);
255         window->editing_lock.lock();
256         window->editing = 0;
257         window->editing_lock.unlock();
259         return;
262 EditSvgButton::EditSvgButton(SvgMain *client, SvgWin *window, int x, int y)
263  : BC_GenericButton(x, y, _("Edit"))
265         this->client = client;
266         this->window = window;
267         quit_now = 0;
270 EditSvgButton::~EditSvgButton() {
271         struct fifo_struct fifo_buf;
272         fifo_buf.pid = getpid();
273         fifo_buf.action = 3;
274         quit_now = 1;
275         write (fh_fifo, &fifo_buf, sizeof(fifo_buf)); // break the thread out of reading from fifo
278 int EditSvgButton::handle_event()
280         
281         window->editing_lock.lock();
282         if (!window->editing && client->config.svg_file[0] != 0) 
283         {
284                 window->editing = 1;
285                 window->editing_lock.unlock();
286                 start();
287         } else
288         {
289                 // FIXME - display an error
290                 window->editing_lock.unlock();
291         }
292         return 1;
295 void EditSvgButton::run()
297 // ======================================= get path from user
298         Timer pausetimer;
299         long delay;
300         int result;
301         time_t last_update;
302         struct stat st_raw;
303         char filename_raw[1024];
304         char filename_fifo[1024];
305         struct fifo_struct fifo_buf;
306         SvgInkscapeThread *inkscape_thread = new SvgInkscapeThread(client, window);
307         
308         strcpy(filename_raw, client->config.svg_file);
309         strcat(filename_raw, ".raw");
310         result = stat (filename_raw, &st_raw);
311         last_update = st_raw.st_mtime;
312         if (result) 
313                 last_update = 0;        
315         strcpy(filename_fifo, filename_raw);
316         strcat(filename_fifo, ".fifo"); 
317         if (mkfifo(filename_fifo, S_IRWXU) != 0) {
318                 perror("Error while creating fifo file");
319         } 
320         fh_fifo = open(filename_fifo, O_RDWR);
321         fifo_buf.action = 0;
322         inkscape_thread->fh_fifo = fh_fifo;
323         inkscape_thread->start();
324         while (inkscape_thread->running() && (!quit_now)) { 
325 //              pausetimer.delay(200); // poll file every 200ms
326                 read(fh_fifo, &fifo_buf, sizeof(fifo_buf));
328                 if (fifo_buf.action == 1) {
329                         result = stat (filename_raw, &st_raw);
330                         // Check if PNG is newer then what we have in memory
331 //                      printf("action1\n");
332 //                      if (last_update < st_raw.st_mtime) { // FIXME this seems to work odd sometimes when fast-refreshing
333 //                              printf("newer pict\n");
334                                 // UPDATE IMAGE
335                                 client->config.last_load = 1;
336                                 client->send_configure_change();
337                                 last_update = st_raw.st_mtime;
338 //                      }
339                 } else 
340                 if (fifo_buf.action == 2) {
341                         printf(_("Inkscape has exited\n"));
342                 } else
343                 if (fifo_buf.action == 3) {
344                         printf(_("Plugin window has closed\n"));
345                         delete inkscape_thread;
346                         close(fh_fifo);
347                         return;
348                 }
349         }
350         inkscape_thread->join();
351         close(fh_fifo);
352         window->editing_lock.lock();
353         window->editing = 0;
354         window->editing_lock.unlock();
358 SvgInkscapeThread::SvgInkscapeThread(SvgMain *client, SvgWin *window)
359  : Thread(1)
361         this->client = client;
362         this->window = window;
365 SvgInkscapeThread::~SvgInkscapeThread()
367         // what do we do? kill inkscape?
368         cancel();
371 void SvgInkscapeThread::run()
373 // Runs the inkscape
374         char command[1024];
375         char filename_raw[1024];
376         strcpy(filename_raw, client->config.svg_file);
377         strcat(filename_raw, ".raw");
379         sprintf(command, "inkscape --cinelerra-export-file=%s %s",
380                 filename_raw, client->config.svg_file);
381         printf(_("Running external SVG editor: %s\n"), command);                
382         enable_cancel();
383         system(command);
384         printf(_("External SVG editor finished\n"));
385         {
386                 struct fifo_struct fifo_buf;
387                 fifo_buf.pid = getpid();
388                 fifo_buf.action = 2;
389                 write (fh_fifo, &fifo_buf, sizeof(fifo_buf));
390         }
391         disable_cancel();
392         return;
397 NewSvgWindow::NewSvgWindow(SvgMain *client, SvgWin *window, char *init_directory)
398  : BC_FileBox(0,
399         BC_WindowBase::get_resources()->filebox_h / 2,
400         init_directory, 
401         _("SVG Plugin: Pick SVG file"), 
402         _("Open an existing SVG file or create a new one"))
404         this->window = window; 
407 NewSvgWindow::~NewSvgWindow() {}