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