Enabled $Id$ expansion.
[synfig.git] / synfig-core / trunk / src / synfig / main.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file synfig/main.cpp
3 **      \brief \writeme
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === H E A D E R S ======================================================= */
24
25 //#define SYNFIG_NO_ANGLE
26
27 #ifdef USING_PCH
28 #       include "pch.h"
29 #else
30 #ifdef HAVE_CONFIG_H
31 #       include <config.h>
32 #endif
33
34 #include <iostream>
35 #include "version.h"
36 #include "general.h"
37 #include "module.h"
38 #include <cstdlib>
39 #include <ltdl.h>
40 #include <stdexcept>
41 #include "target.h"
42 #include <ETL/stringf>
43 #include "listimporter.h"
44 #include "color.h"
45 #include "vector.h"
46 #include <fstream>
47 #include "layer.h"
48 #include "valuenode.h"
49
50 #include "main.h"
51 #include "loadcanvas.h"
52
53 #include "guid.h"
54
55 #include "mutex.h"
56
57 #ifdef DEATH_TIME
58 #include <time.h>
59 #endif
60
61 #ifdef HAVE_SIGNAL_H
62 #include <signal.h>
63 #endif
64
65 #endif
66
67 using namespace std;
68 using namespace etl;
69 using namespace synfig;
70
71 /* === M A C R O S ========================================================= */
72
73 #define MODULE_LIST_FILENAME    "synfig_modules.cfg"
74
75 /* === S T A T I C S ======================================================= */
76
77 static etl::reference_counter synfig_ref_count_(0);
78
79 /* === P R O C E D U R E S ================================================= */
80
81 /* === M E T H O D S ======================================================= */
82
83
84
85
86
87
88
89
90 const char *
91 synfig::get_version()
92 {
93 #ifdef VERSION
94         return VERSION;
95 #else
96         return "Unknown";
97 #endif
98 }
99
100 const char *
101 synfig::get_build_date()
102 {
103         return __DATE__;
104 }
105
106 const char *
107 synfig::get_build_time()
108 {
109         return __TIME__;
110 }
111
112 extern const char *get_build_time();
113
114 bool
115 synfig::check_version_(int version,int vec_size, int color_size,int canvas_size,int layer_size)
116 {
117         bool ret=true;
118
119         CHECK_EXPIRE_TIME();
120
121         if(version!=SYNFIG_LIBRARY_VERSION)
122         {
123                 synfig::error(_("API Version mismatch (LIB:%d, PROG:%d)"),SYNFIG_LIBRARY_VERSION,version);
124                 ret=false;
125         }
126         if(vec_size!=sizeof(Vector))
127         {
128                 synfig::error(_("Size of Vector mismatch (app:%d, lib:%d)"),vec_size,sizeof(Vector));
129                 ret=false;
130         }
131         if(color_size!=sizeof(Color))
132         {
133                 synfig::error(_("Size of Color mismatch (app:%d, lib:%d)"),color_size,sizeof(Color));
134                 ret=false;
135         }
136         if(canvas_size!=sizeof(Canvas))
137         {
138                 synfig::error(_("Size of Canvas mismatch (app:%d, lib:%d)"),canvas_size,sizeof(Canvas));
139                 ret=false;
140         }
141         if(layer_size!=sizeof(Layer))
142         {
143                 synfig::error(_("Size of Layer mismatch (app:%d, lib:%d)"),layer_size,sizeof(Layer));
144                 ret=false;
145         }
146
147         return ret;
148 }
149
150 static void broken_pipe_signal (int sig)  {
151         synfig::warning("Broken Pipe...");
152 }
153
154 bool retrieve_modules_to_load(String filename,std::list<String> &modules_to_load)
155 {
156         if(filename=="standard")
157         {
158                 return false;
159 /*
160                 if(find(modules_to_load.begin(),modules_to_load.end(),"trgt_bmp")==modules_to_load.end())
161                         modules_to_load.push_back("trgt_bmp");
162                 if(find(modules_to_load.begin(),modules_to_load.end(),"trgt_gif")==modules_to_load.end())
163                         modules_to_load.push_back("trgt_gif");
164                 if(find(modules_to_load.begin(),modules_to_load.end(),"trgt_dv")==modules_to_load.end())
165                         modules_to_load.push_back("trgt_dv");
166                 if(find(modules_to_load.begin(),modules_to_load.end(),"mod_ffmpeg")==modules_to_load.end())
167                         modules_to_load.push_back("mod_ffmpeg");
168                 if(find(modules_to_load.begin(),modules_to_load.end(),"mod_imagemagick")==modules_to_load.end())
169                         modules_to_load.push_back("mod_imagemagick");
170                 if(find(modules_to_load.begin(),modules_to_load.end(),"lyr_std")==modules_to_load.end())
171                         modules_to_load.push_back("lyr_std");
172                 if(find(modules_to_load.begin(),modules_to_load.end(),"lyr_freetype")==modules_to_load.end())
173                         modules_to_load.push_back("lyr_freetype");
174 #ifdef HAVE_LIBPNG
175                 if(find(modules_to_load.begin(),modules_to_load.end(),"trgt_png")==modules_to_load.end())
176                         modules_to_load.push_back("trgt_png");
177 #endif
178 #ifdef HAVE_OPENEXR
179                 if(find(modules_to_load.begin(),modules_to_load.end(),"mod_openexr")==modules_to_load.end())
180                         modules_to_load.push_back("mod_openexr");
181 #endif
182 */
183         }
184         else
185         {
186                 std::ifstream file(filename.c_str());
187                 if(!file)
188                 {
189                 //      warning("Cannot open "+filename);
190                         return false;
191                 }
192                 while(file)
193                 {
194                         String modulename;
195                         getline(file,modulename);
196                         if(!modulename.empty() && find(modules_to_load.begin(),modules_to_load.end(),modulename)==modules_to_load.end())
197                                 modules_to_load.push_back(modulename);
198                 }
199         }
200
201
202
203         return true;
204 }
205
206
207
208
209
210 synfig::Main::Main(const synfig::String& basepath,ProgressCallback *cb):
211         ref_count_(synfig_ref_count_)
212 {
213         if(ref_count_.count())
214                 return;
215
216         synfig_ref_count_.reset();
217         ref_count_=synfig_ref_count_;
218
219         // Add initialization after this point
220
221
222         CHECK_EXPIRE_TIME();
223
224         String prefix=basepath+"/..";
225         int i;
226 #ifdef _DEBUG
227         std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
228 #endif
229
230 #if defined(HAVE_SIGNAL_H) && defined(SIGPIPE)
231         signal(SIGPIPE, broken_pipe_signal);
232 #endif
233
234         //_config_search_path=new vector"string.h"();
235
236         // Init the subsystems
237         if(cb)cb->amount_complete(0, 100);
238         if(cb)cb->task(_("Starting Subsystem \"Modules\""));
239         if(!Module::subsys_init(prefix))
240                 throw std::runtime_error(_("Unable to initialize subsystem \"Module\""));
241
242         if(cb)cb->task(_("Starting Subsystem \"Layers\""));
243         if(!Layer::subsys_init())
244         {
245                 Module::subsys_stop();
246                 throw std::runtime_error(_("Unable to initialize subsystem \"Layers\""));
247         }
248
249         if(cb)cb->task(_("Starting Subsystem \"Targets\""));
250         if(!Target::subsys_init())
251         {
252                 Layer::subsys_stop();
253                 Module::subsys_stop();
254                 throw std::runtime_error(_("Unable to initialize subsystem \"Targets\""));
255         }
256
257         if(cb)cb->task(_("Starting Subsystem \"Importers\""));
258         if(!Importer::subsys_init())
259         {
260                 Target::subsys_stop();
261                 Layer::subsys_stop();
262                 Module::subsys_stop();
263                 throw std::runtime_error(_("Unable to initialize subsystem \"Importers\""));
264         }
265
266         if(cb)cb->task(_("Starting Subsystem \"ValueNodes\""));
267         if(!ValueNode::subsys_init())
268         {
269                 Importer::subsys_stop();
270                 Target::subsys_stop();
271                 Layer::subsys_stop();
272                 Module::subsys_stop();
273                 throw std::runtime_error(_("Unable to initialize subsystem \"ValueNodes\""));
274         }
275
276         // Load up the list importer
277         Importer::book()[String("lst")]=ListImporter::create;
278
279
280
281         // Load up the modules
282         std::list<String> modules_to_load;
283         std::vector<String> locations;
284
285         if(!getenv("SYNFIG_MODULE_LIST"))
286         {
287                 locations.push_back("standard");
288                 locations.push_back("./"MODULE_LIST_FILENAME);  //1
289                 locations.push_back("../etc/"MODULE_LIST_FILENAME);     //1
290                 locations.push_back("~/.synfig/"MODULE_LIST_FILENAME); //2
291                 locations.push_back(prefix+"/etc/"+MODULE_LIST_FILENAME); //3
292                 locations.push_back("/usr/local/etc/"MODULE_LIST_FILENAME);
293         #ifdef SYSCONFDIR
294                 locations.push_back(SYSCONFDIR"/"MODULE_LIST_FILENAME);
295         #endif
296         #ifdef __APPLE__
297                 locations.push_back("/Library/Frameworks/synfig.framework/Resources/"MODULE_LIST_FILENAME);
298                 locations.push_back("/Library/Synfig/"MODULE_LIST_FILENAME);
299                 locations.push_back("~/Library/Synfig/"MODULE_LIST_FILENAME);
300         #endif
301         #ifdef WIN32
302                 locations.push_back("C:\\Program Files\\Synfig\\etc\\"MODULE_LIST_FILENAME);
303         #endif
304         }
305         else
306         {
307                 locations.push_back(getenv("SYNFIG_MODULE_LIST"));
308         }
309 /*
310         const char *locations[]=
311         {
312                 "standard",     //0
313                 "./"MODULE_LIST_FILENAME,       //1
314                 "../etc/"MODULE_LIST_FILENAME,  //1
315                 "~/.synfig/"MODULE_LIST_FILENAME, //2
316                 "/usr/local/lib/synfig/modules/"MODULE_LIST_FILENAME, //3
317                 "/usr/local/etc/"MODULE_LIST_FILENAME,
318 #ifdef SYSCONFDIR
319                 SYSCONFDIR"/"MODULE_LIST_FILENAME,
320 #endif
321 #ifdef __APPLE__
322                 "/Library/Frameworks/synfig.framework/Resources/"MODULE_LIST_FILENAME,
323                 "/Library/SYNFIG/"MODULE_LIST_FILENAME,
324                 "~/Library/SYNFIG/"MODULE_LIST_FILENAME,
325 #endif
326 #ifdef WIN32
327                 "C:\\Program Files\\SYNFIG\\etc\\"MODULE_LIST_FILENAME,
328 #endif
329         };
330 */
331
332         for(i=0;i<locations.size();i++)
333                 if(retrieve_modules_to_load(locations[i],modules_to_load))
334                         if(cb)cb->task(strprintf(_("Loading modules from %s"),locations[i].c_str()));
335
336         std::list<String>::iterator iter;
337
338         for(i=0,iter=modules_to_load.begin();iter!=modules_to_load.end();++iter,i++)
339         {
340                 Module::Register(*iter,cb);
341                 if(cb)cb->amount_complete((i+1)*100,modules_to_load.size()*100);
342         }
343
344 //      load_modules(cb);
345
346         CHECK_EXPIRE_TIME();
347
348
349         if(cb)cb->amount_complete(100, 100);
350         if(cb)cb->task(_("DONE"));
351 }
352
353 synfig::Main::~Main()
354 {
355         ref_count_.detach();
356         if(!synfig_ref_count_.unique())
357                 return;
358         synfig_ref_count_.detach();
359
360         // Add deinitialization after this point
361
362         if(get_open_canvas_map().size())
363         {
364                 synfig::warning("Canvases still open!");
365                 std::map<synfig::String, etl::loose_handle<Canvas> >::iterator iter;
366                 for(iter=get_open_canvas_map().begin();iter!=get_open_canvas_map().end();++iter)
367                 {
368                         synfig::warning("%s: count()=%d",iter->first.c_str(), iter->second.count());
369                 }
370         }
371
372         ValueNode::subsys_stop();
373         Importer::subsys_stop();
374         Target::subsys_stop();
375         Layer::subsys_stop();
376
377         /*! \fixme For some reason, uncommenting the next
378         **      line will cause things to crash. This needs to be
379         **      looked into at some point. */
380         //Module::subsys_stop();
381
382 #if defined(HAVE_SIGNAL_H) && defined(SIGPIPE)
383         signal(SIGPIPE, SIG_DFL);
384 #endif
385 }
386
387
388
389
390
391
392
393
394
395 void
396 synfig::error(const char *format,...)
397 {
398         va_list args;
399         va_start(args,format);
400         error(vstrprintf(format,args));
401 }
402
403 void
404 synfig::error(const String &str)
405 {
406         static Mutex mutex; Mutex::Lock lock(mutex);
407         cerr<<"synfig("<<getpid()<<"): "<<_("error")<<": "+str<<endl;
408 }
409
410 void
411 synfig::warning(const char *format,...)
412 {
413         va_list args;
414         va_start(args,format);
415         warning(vstrprintf(format,args));
416 }
417
418 void
419 synfig::warning(const String &str)
420 {
421         static Mutex mutex; Mutex::Lock lock(mutex);
422         cerr<<"synfig("<<getpid()<<"): "<<_("warning")<<": "+str<<endl;
423 }
424
425 void
426 synfig::info(const char *format,...)
427 {
428         va_list args;
429         va_start(args,format);
430         info(vstrprintf(format,args));
431 }
432
433 void
434 synfig::info(const String &str)
435 {
436         static Mutex mutex; Mutex::Lock lock(mutex);
437         cerr<<"synfig("<<getpid()<<"): "<<_("info")<<": "+str<<endl;
438 }