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