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