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