plug leaks, leaker tweaks, lang for effect info, c41 spiffs, wm probe tweaks
[goodguy/history.git] / cinelerra-5.1 / cinelerra / main.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2010 Adam Williams <broadcast at earthling dot net>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21 #include "arraylist.h"
22 #include "batchrender.h"
23 #include "bcsignals.h"
24 #include "edl.h"
25 #include "file.h"
26 #include "filexml.h"
27 #include "filesystem.h"
28 #include "language.h"
29 #include "langinfo.h"
30 #include "loadfile.inc"
31 #include "mainmenu.h"
32 #include "mutex.h"
33 #include "mwindow.h"
34 #include "mwindowgui.h"
35 #include "pluginserver.h"
36 #include "preferences.h"
37 #include "renderfarmclient.h"
38 #include "units.h"
39 #include "versioninfo.h"
40
41 #include <locale.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #ifdef LEAKER
46 #define STRC(v) printf("==new %p from %p sz %jd\n", v, __builtin_return_address(0), n)
47 #define STRD(v) printf("==del %p from %p\n", v, __builtin_return_address(0))
48 void *operator new(size_t n) { void *vp = malloc(n); STRC(vp); bzero(vp,n); return vp; }
49 void operator delete(void *t) { STRD(t); free(t); }
50 void operator delete(void *t,size_t n) { STRD(t); free(t); }
51 void *operator new[](size_t n) { void *vp = malloc(n); STRC(vp); bzero(vp,n); return vp; }
52 void operator delete[](void *t) { STRD(t); free(t); }
53 void operator delete[](void *t,size_t n) { STRD(t); free(t); }
54 #endif
55
56 enum
57 {
58         DO_GUI,
59         DO_DEAMON,
60         DO_DEAMON_FG,
61         DO_BRENDER,
62         DO_USAGE,
63         DO_BATCHRENDER
64 };
65
66 #include "thread.h"
67
68
69 class CommandLineThread : public Thread
70 {
71 public:
72         CommandLineThread(ArrayList<char*> *filenames,
73                 MWindow *mwindow)
74         {
75                 this->filenames = filenames;
76                 this->mwindow = mwindow;
77         }
78
79
80         ~CommandLineThread()
81         {
82         }
83
84         void run()
85         {
86 //PRINT_TRACE
87                 mwindow->gui->lock_window("main");
88 //PRINT_TRACE
89                 mwindow->load_filenames(filenames, LOADMODE_REPLACE);
90 //PRINT_TRACE
91                 if(filenames->size() == 1)
92                         mwindow->gui->mainmenu->add_load(filenames->get(0));
93 //PRINT_TRACE
94                 mwindow->gui->unlock_window();
95 //PRINT_TRACE
96         }
97
98         MWindow *mwindow;
99         ArrayList<char*> *filenames;
100 };
101
102
103 int main(int argc, char *argv[])
104 {
105 // handle command line arguments first
106         srand(time(0));
107         ArrayList<char*> filenames;
108         FileSystem fs;
109
110
111         int operation = DO_GUI;
112         int deamon_port = DEAMON_PORT;
113         char deamon_path[BCTEXTLEN];
114         char config_path[BCTEXTLEN];
115         char batch_path[BCTEXTLEN];
116         int nice_value = 20;
117         config_path[0] = 0;
118         batch_path[0] = 0;
119         deamon_path[0] = 0;
120         EDL::id_lock = new Mutex("EDL::id_lock");
121         Units::init();
122
123         File::init_cin_path();
124         const char *locale_path = File::get_locale_path();
125         const char *cin = File::get_cin();
126
127         bindtextdomain(cin, locale_path);
128         textdomain(cin);
129         setlocale(LC_MESSAGES, "");
130
131 #ifdef X_HAVE_UTF8_STRING
132         char *loc = setlocale(LC_CTYPE, "");
133         if( loc ) {
134                 strcpy(BC_Resources::encoding, nl_langinfo(CODESET));
135                 BC_Resources::locale_utf8 = !strcmp(BC_Resources::encoding, "UTF-8");
136
137                 // Extract from locale language & region
138                 char locbuf[32], *p;
139                 locbuf[0] = 0;
140                 if((p = strchr(loc, '.')) != 0 && (p - loc) < (int)sizeof(locbuf)-1) {
141                         strncpy(locbuf, loc, p - loc);
142                         locbuf[p - loc] = 0;
143                 }
144                 else if(strlen(loc) < sizeof(locbuf)-1)
145                         strcpy(locbuf, loc);
146
147                 // Locale 'C' does not give useful language info - assume en
148                 if(!locbuf[0] || locbuf[0] == 'C')
149                         strcpy(locbuf, "en");
150
151                 if((p = strchr(locbuf, '_')) && p - locbuf < LEN_LANG) {
152                         *p++ = 0;
153                         strcpy(BC_Resources::language, locbuf);
154                         if(strlen(p) < LEN_LANG)
155                                 strcpy(BC_Resources::region, p);
156                 }
157                 else if(strlen(locbuf) < LEN_LANG)
158                         strcpy(BC_Resources::language, locbuf);
159         }
160         else
161                 printf(_(PROGRAM_NAME ": Could not set locale.\n"));
162 #else
163         setlocale(LC_CTYPE, "");
164 #endif
165         tzset();
166
167         int load_backup = 0;
168         int start_remote_control = 0;
169
170         for(int i = 1; i < argc; i++)
171         {
172                 if(!strcmp(argv[i], "-h"))
173                 {
174                         operation = DO_USAGE;
175                 }
176                 else
177                 if(!strcmp(argv[i], "-z"))
178                 {
179                         start_remote_control = 1;
180                 }
181                 else
182                 if(!strcmp(argv[i], "-r"))
183                 {
184                         operation = DO_BATCHRENDER;
185                         if(argc > i + 1)
186                         {
187                                 if(argv[i + 1][0] != '-')
188                                 {
189                                         strcpy(batch_path, argv[i + 1]);
190                                         i++;
191                                 }
192                         }
193                 }
194                 else
195                 if(!strcmp(argv[i], "-c"))
196                 {
197                         if(argc > i + 1)
198                         {
199                                 strcpy(config_path, argv[i + 1]);
200                                 i++;
201                         }
202                         else
203                         {
204                                 fprintf(stderr, _("%s: -c needs a filename.\n"), argv[0]);
205                         }
206                 }
207                 else
208                 if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "-f"))
209                 {
210                         if(!strcmp(argv[i], "-d"))
211                                 operation = DO_DEAMON;
212                         else
213                                 operation = DO_DEAMON_FG;
214
215                         if(argc > i + 1)
216                         {
217                                 if(atol(argv[i + 1]) > 0)
218                                 {
219                                         deamon_port = atol(argv[i + 1]);
220                                         i++;
221                                 }
222                         }
223                 }
224                 else
225                 if(!strcmp(argv[i], "-b"))
226                 {
227                         operation = DO_BRENDER;
228                         if(i > argc - 2)
229                         {
230                                 fprintf(stderr, _("-b may not be used by the user.\n"));
231                                 exit(1);
232                         }
233                         else
234                                 strcpy(deamon_path, argv[i + 1]);
235                 }
236                 else
237                 if(!strcmp(argv[i], "-n"))
238                 {
239                         if(argc > i + 1)
240                         {
241                                 nice_value = atol(argv[i + 1]);
242                                 i++;
243                         }
244                 }
245                 else
246                 if(!strcmp(argv[i], "-x"))
247                 {
248                         load_backup = 1;
249                 }
250                 else
251                 {
252                         char *new_filename;
253                         new_filename = new char[BCTEXTLEN];
254                         strcpy(new_filename, argv[i]);
255                         fs.complete_path(new_filename);
256                         filenames.append(new_filename);
257                 }
258         }
259
260
261
262         if(operation == DO_GUI ||
263                 operation == DO_DEAMON ||
264                 operation == DO_DEAMON_FG ||
265                 operation == DO_USAGE ||
266                 operation == DO_BATCHRENDER) {
267
268                 fprintf(stderr, PROGRAM_NAME " " CINELERRA_VERSION);
269 #ifndef REPOMAINTXT
270 #define REPOMAINTXT ""
271 #endif
272 #ifndef COPYRIGHTTEXT1
273 #define COPYRIGHTTEXT1 ""
274 #endif
275 #ifndef COPYRIGHTTEXT2
276 #define COPYRIGHTTEXT2 ""
277 #endif
278 #ifndef COMPILEDATE
279 #define COMPILEDATE ""
280 #endif
281                 fprintf(stderr, REPOMAINTXT COPYRIGHTTEXT1 COPYRIGHTTEXT2 COMPILEDATE
282                         PROGRAM_NAME " is free software, covered by the GNU General Public License,\n"
283                         "and you are welcome to change it and/or distribute copies of it under\n"
284                         "certain conditions. There is absolutely no warranty for " PROGRAM_NAME ".\n\n");
285         }
286
287         switch(operation)
288         {
289                 case DO_USAGE:
290                         printf(_("\nUsage:\n"));
291                         printf(_("%s [-f] [-c configuration] [-d port] [-n nice] [-r batch file] [filenames]\n\n"), argv[0]);
292                         printf(_("-d = Run in the background as renderfarm client.  The port (400) is optional.\n"));
293                         printf(_("-f = Run in the foreground as renderfarm client.  Substitute for -d.\n"));
294                         printf(_("-n = Nice value if running as renderfarm client. (20)\n"));
295                         printf(_("-c = Configuration file to use instead of %s/%s.\n"),
296                                 File::get_config_path(), CONFIG_FILE);
297                         printf(_("-r = batch render the contents of the batch file (%s/%s) with no GUI.  batch file is optional.\n"),
298                                 File::get_config_path(), BATCH_PATH);
299                         printf(_("filenames = files to load\n\n\n"));
300                         exit(0);
301                         break;
302
303                 case DO_DEAMON:
304                 case DO_DEAMON_FG:
305                 {
306                         if(operation == DO_DEAMON)
307                         {
308                                 int pid = fork();
309
310                                 if(pid)
311                                 {
312 // Redhat 9 requires _exit instead of exit here.
313                                         _exit(0);
314                                 }
315                         }
316
317                         RenderFarmClient client(deamon_port,
318                                 0,
319                                 nice_value,
320                                 config_path);
321                         client.main_loop();
322                         break;
323                 }
324
325 // Same thing without detachment
326                 case DO_BRENDER:
327                 {
328                         RenderFarmClient client(0,
329                                 deamon_path,
330                                 20,
331                                 config_path);
332                         client.main_loop();
333                         break;
334                 }
335
336                 case DO_BATCHRENDER:
337                 {
338                         BatchRenderThread *thread = new BatchRenderThread;
339                         thread->start_rendering(config_path,
340                                 batch_path);
341                         break;
342                 }
343
344                 case DO_GUI:
345                 {
346                         int restart = 0, done = 0;
347                         while( !done ) {
348                                 BC_WindowBase::get_resources()->vframe_shm = 0;
349                                 MWindow mwindow;
350                                 mwindow.create_objects(1, !filenames.total, config_path);
351                                 CommandLineThread *thread  = 0;
352 //SET_TRACE
353 // load the initial files on seperate tracks
354 // use a new thread so it doesn't block the GUI
355                                 if( filenames.total ) {
356                                         thread  = new CommandLineThread(&filenames, &mwindow);
357                                         thread->start();
358 //PRINT_TRACE
359                                 }
360                                 if( load_backup ) {
361                                         load_backup = 0;
362                                         mwindow.gui->lock_window("main");
363                                         mwindow.load_backup();
364                                         mwindow.gui->unlock_window();
365                                 }
366                                 if( start_remote_control ) {
367                                         start_remote_control = 0;
368                                         mwindow.gui->remote_control->activate();
369                                 }
370 // run the program
371 //PRINT_TRACE
372                                 mwindow.start();
373                                 mwindow.run();
374 //PRINT_TRACE
375                                 restart = mwindow.restart();
376                                 if( restart ) {
377                                         mwindow.save_backup();
378                                         load_backup = 1;
379                                         start_remote_control =
380                                                 mwindow.gui->remote_control->is_active();
381                                 }
382                                 if( restart <= 0 )
383                                         done = 1;
384
385                                 mwindow.save_defaults();
386 //PRINT_TRACE
387                                 filenames.remove_all_objects();
388                                 delete thread;
389                         }
390
391                         if( restart < 0 ) {
392                                 char exe_path[BCTEXTLEN];
393                                 int len = readlink("/proc/self/exe", exe_path, sizeof(exe_path)-1);
394                                 if( len < 0 ) break;
395                                 exe_path[len] = 0;
396                                 char *av[4] = { 0, };  int ac = 0;
397                                 av[ac++] = exe_path;
398                                 if( load_backup ) av[ac++] = (char*) "-x";
399                                 if( start_remote_control ) av[ac++] = (char*) "-z";
400                                 av[ac++] = 0;
401                                 execv(exe_path, av);
402                         }
403                 }
404 //SET_TRACE
405 DISABLE_BUFFER
406                 break;
407         }
408
409         filenames.remove_all_objects();
410         delete EDL::id_lock;  EDL::id_lock = 0;
411         Units::finit();
412
413         return 0;
414 }
415