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