initial commit
[goodguy/history.git] / cinelerra-5.0 / plugins / svg / svgwin.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "bcdisplayinfo.h"
23 #include "clip.h"
24 #include "svgwin.h"
25 #include "string.h"
26 #include "filexml.h"
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sys/types.h>
30 #include <fcntl.h>
31 #include <sys/stat.h>
32
33 struct fifo_struct {
34         int pid;
35         int action;  // 1 = update from client, 2 = client closes
36       };
37
38
39 #include <libintl.h>
40 #define _(String) gettext(String)
41 #define gettext_noop(String) String
42 #define N_(String) gettext_noop (String)
43
44 #include "empty_svg.h"
45
46
47
48
49
50
51 SvgWin::SvgWin(SvgMain *client)
52  : PluginClientWindow(client, 300, 280, 300, 280, 1)
53
54         this->client = client; 
55         this->editing = 0;
56 }
57
58 SvgWin::~SvgWin()
59 {
60 }
61
62 void SvgWin::create_objects()
63 {
64         int x = 10, y = 10;
65
66 //      add_tool(new BC_Title(x, y, _("In X:")));
67         y += 20;
68 //      in_x = new SvgCoord(this, client, x, y, &client->config.in_x);
69 //      in_x->create_objects();
70         y += 30;
71
72 //      add_tool(new BC_Title(x, y, _("In Y:")));
73         y += 20;
74 //      in_y = new SvgCoord(this, client, x, y, &client->config.in_y);
75 //      in_y->create_objects();
76         y += 30;
77
78 //      add_tool(new BC_Title(x, y, _("In W:")));
79         y += 20;
80 //      in_w = new SvgCoord(this, client, x, y, &client->config.in_w);
81 //      in_w->create_objects();
82         y += 30;
83
84 //      add_tool(new BC_Title(x, y, _("In H:")));
85         y += 20;
86 //      in_h = new SvgCoord(this, client, x, y, &client->config.in_h);
87 //      in_h->create_objects();
88         y += 30;
89
90
91         x += 150;
92         y = 10;
93         add_tool(new BC_Title(x, y, _("Out X:")));
94         y += 20;
95         out_x = new SvgCoord(this, client, x, y, &client->config.out_x);
96         out_x->create_objects();
97         y += 30;
98
99         add_tool(new BC_Title(x, y, _("Out Y:")));
100         y += 20;
101         out_y = new SvgCoord(this, client, x, y, &client->config.out_y);
102         out_y->create_objects();
103         y += 30;
104
105 /*      add_tool(new BC_Title(x, y, _("Out W:")));
106         y += 20;
107         out_w = new SvgCoord(this, client, x, y, &client->config.out_w);
108         out_w->create_objects();
109         y += 30;
110
111         add_tool(new BC_Title(x, y, _("Out H:")));
112         y += 20;
113         out_h = new SvgCoord(this, client, x, y, &client->config.out_h);
114         out_h->create_objects();
115         y += 30;
116 */
117         x -= 150;
118         add_tool(new_svg_button = new NewSvgButton(client, this, x, y));
119         add_tool(edit_svg_button = new EditSvgButton(client, this, x+190, y));
120         add_tool(svg_file_title = new BC_Title(x, y+26, client->config.svg_file));
121
122         x +=150;
123
124         show_window();
125         flush();
126 }
127
128 int SvgWin::close_event()
129 {
130         set_done(1);
131         return 1;
132 }
133
134 SvgCoord::SvgCoord(SvgWin *win, 
135         SvgMain *client, 
136         int x, 
137         int y,
138         float *value)
139  : BC_TumbleTextBox(win,
140         *value,
141         (float)0,
142         (float)3000,
143         x, 
144         y, 
145         100)
146 {
147 //printf("SvgWidth::SvgWidth %f\n", client->config.w);
148         this->client = client;
149         this->win = win;
150         this->value = value;
151 }
152
153 SvgCoord::~SvgCoord()
154 {
155 }
156
157 int SvgCoord::handle_event()
158 {
159         *value = atof(get_text());
160         client->send_configure_change();
161         return 1;
162 }
163
164 NewSvgButton::NewSvgButton(SvgMain *client, SvgWin *window, int x, int y)
165  : BC_GenericButton(x, y, _("New/Open SVG..."))
166 {
167         this->client = client;
168         this->window = window;
169         quit_now = 0;
170 }
171 int NewSvgButton::handle_event()
172 {
173         window->editing_lock.lock();
174         if (!window->editing) 
175         {
176                 window->editing = 1;
177                 window->editing_lock.unlock();
178                 quit_now = 0;
179                 start();
180         } else
181         {
182                 // FIXME - display an error
183                 window->editing_lock.unlock();
184         }
185
186         return 1;
187 }
188
189 void NewSvgButton::run()
190 {
191 // ======================================= get path from user
192         int result;
193 //printf("NewSvgButton::run 1\n");
194         result = 1;
195         char filename[1024];
196         strncpy(filename, client->config.svg_file, sizeof(filename));
197 // Loop until file is chosen
198         do {
199                 char directory[1024];
200                 strncpy(directory, client->config.svg_file, sizeof(directory));
201                 char *cp = strrchr(directory, '/');
202                 if( cp ) *cp = 0;
203                 if( !directory[0] ) {
204                         char *cp = getenv("HOME");
205                         if( !cp ) strncpy(directory, cp, sizeof(directory));
206                 }
207                 NewSvgWindow *new_window = new NewSvgWindow(client, window, directory);
208                 new_window->create_objects();
209                 new_window->update_filter("*.svg");
210                 result = new_window->run_window();
211                 const char *filepath = new_window->get_path(0);
212                 if( result || !filepath || !*filepath ) {
213                         window->editing_lock.lock();
214                         window->editing = 0;
215                         window->editing_lock.unlock();
216                         return;              // cancel or no filename given
217                 }
218                 strcpy(filename, filepath);
219                 delete new_window;
220
221 // Extend the filename with .svg
222                 if(strlen(filename) < 4 || 
223                         strcasecmp(&filename[strlen(filename) - 4], ".svg")) {
224                         strcat(filename, ".svg");
225                 }
226
227                 if( !access(filename, R_OK) )
228                         result = 0;
229                 else {
230                         FILE *out = fopen(filename,"w");
231                         if( out ) {
232                                 unsigned long size = sizeof(empty_svg) - 4;
233                                 fwrite(empty_svg+4, size,  1, out);
234                                 fclose(out);
235                                 result = 0;
236                         }
237                 }
238         } while(result);        // file doesn't exist so repeat
239         
240
241         strcpy(client->config.svg_file, filename);
242         client->send_configure_change();
243
244 // save it
245         if(quit_now) window->set_done(0);
246         window->editing_lock.lock();
247         window->editing = 0;
248         window->editing_lock.unlock();
249
250         return;
251 }
252
253 EditSvgButton::EditSvgButton(SvgMain *client, SvgWin *window, int x, int y)
254  : BC_GenericButton(x, y, _("Edit"))
255 {
256         this->client = client;
257         this->window = window;
258         quit_now = 0;
259 }
260
261 EditSvgButton::~EditSvgButton() {
262         struct fifo_struct fifo_buf;
263         fifo_buf.pid = getpid();
264         fifo_buf.action = 3;
265         quit_now = 1;
266         write (fh_fifo, &fifo_buf, sizeof(fifo_buf)); // break the thread out of reading from fifo
267 }
268
269 int EditSvgButton::handle_event()
270 {
271         
272         window->editing_lock.lock();
273         if (!window->editing && client->config.svg_file[0] != 0) 
274         {
275                 window->editing = 1;
276                 window->editing_lock.unlock();
277                 start();
278         } else
279         {
280                 // FIXME - display an error
281                 window->editing_lock.unlock();
282         }
283         return 1;
284 }
285
286 void EditSvgButton::run()
287 {
288 // ======================================= get path from user
289         Timer pausetimer;
290         //long delay;
291         //int result;
292         //struct stat st_png;
293         //char filename[1024];
294         char filename_png[1024];
295         char filename_fifo[1024];
296         struct fifo_struct fifo_buf;
297         SvgInkscapeThread *inkscape_thread = new SvgInkscapeThread(client, window);
298         
299         strcpy(filename_png, client->config.svg_file);
300         strcat(filename_png, ".png");
301         remove(filename_png);
302         strcpy(filename_fifo, filename_png);
303         strcat(filename_fifo, ".fifo"); 
304         if (mkfifo(filename_fifo, S_IRWXU) != 0) {
305                 perror("Error while creating fifo file");
306         } 
307         fh_fifo = open(filename_fifo, O_RDWR);
308         fifo_buf.action = 0;
309         inkscape_thread->fh_fifo = fh_fifo;
310         inkscape_thread->start();
311         while (inkscape_thread->running() && (!quit_now)) { 
312                 Timer::delay(200); // poll file every 200ms
313                 read(fh_fifo, &fifo_buf, sizeof(fifo_buf));
314
315                 if (fifo_buf.action == 1) {
316                         client->send_configure_change();
317                 } else if (fifo_buf.action == 2) {
318                         printf(_("Inkscape has exited\n"));
319                 } else if (fifo_buf.action == 3) {
320                         printf(_("Plugin window has closed\n"));
321                         delete inkscape_thread;
322                         close(fh_fifo);
323                         return;
324                 }
325         }
326         remove(filename_fifo); // fifo destroyed on last close
327         inkscape_thread->join();
328         close(fh_fifo);
329         window->editing_lock.lock();
330         window->editing = 0;
331         window->editing_lock.unlock();
332
333         client->send_configure_change();
334 }
335
336 SvgInkscapeThread::SvgInkscapeThread(SvgMain *client, SvgWin *window)
337  : Thread(1)
338 {
339         this->client = client;
340         this->window = window;
341 }
342
343 SvgInkscapeThread::~SvgInkscapeThread()
344 {
345         // what do we do? kill inkscape?
346         cancel();
347 }
348
349 void SvgInkscapeThread::run()
350 {
351 // Runs the inkscape
352         char command[1024];
353         sprintf(command, "inkscape --with-gui %s", client->config.svg_file);
354         printf(_("Running external SVG editor: %s\n"), command);
355
356         enable_cancel();
357         system(command);
358         printf(_("External SVG editor finished\n"));
359         struct fifo_struct fifo_buf;
360         fifo_buf.pid = getpid();
361         fifo_buf.action = 2;
362         write (fh_fifo, &fifo_buf, sizeof(fifo_buf));
363         disable_cancel();
364
365         return;
366 }
367
368
369
370 NewSvgWindow::NewSvgWindow(SvgMain *client, SvgWin *window, char *init_directory)
371  : BC_FileBox(0,
372         BC_WindowBase::get_resources()->filebox_h / 2,
373         init_directory, 
374         _("SVG Plugin: Pick SVG file"), 
375         _("Open an existing SVG file or create a new one"))
376
377         this->window = window; 
378 }
379
380 NewSvgWindow::~NewSvgWindow() {}
381
382
383
384
385
386
387