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