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