add shell menu btns, add manual
[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         char env_path[BCTEXTLEN];
129         int nice_value = 20;
130         int start_remote_control = 0;
131         config_path[0] = 0;
132         batch_path[0] = 0;
133         deamon_path[0] = 0;
134         EDL::id_lock = new Mutex("EDL::id_lock");
135
136
137         get_exe_path(exe_path);
138         snprintf(env_path, sizeof(env_path), "CINELERRA_PATH=%s", exe_path);
139         putenv(env_path);
140         sprintf(locale_path, "%s%s", exe_path, LOCALEDIR);
141
142
143 // detect an UTF-8 locale and try to use a non-Unicode locale instead
144 // <---Beginning of dirty hack
145 // This hack will be removed as soon as Cinelerra is UTF-8 compliant
146 //    char *s, *language;
147
148 // Query user locale
149 //    if ((s = getenv("LC_ALL"))  ||
150 //              (s = getenv("LC_MESSAGES")) ||
151 //              (s = getenv("LC_CTYPE")) ||
152 //              (s = getenv ("LANG")))
153 //    {
154 // Test if user locale is set to Unicode
155 //        if (strstr(s, ".UTF-8"))
156 //        {
157 // extract language  from language-charset@variant
158 //          language = strtok (s, ".@");
159 // set language as the default locale
160 //          setenv("LANG", language, 1);
161 //        }
162 //    }
163 // End of dirty hack --->
164
165         bindtextdomain (PACKAGE, locale_path);
166         textdomain (PACKAGE);
167         setlocale (LC_MESSAGES, "");
168 #ifdef X_HAVE_UTF8_STRING
169         char *loc = setlocale(LC_CTYPE, "");
170         if( loc ) {
171                 strcpy(BC_Resources::encoding, nl_langinfo(CODESET));
172                 BC_Resources::locale_utf8 = !strcmp(BC_Resources::encoding, "UTF-8");
173
174                 // Extract from locale language & region
175                 char locbuf[32], *p;
176                 locbuf[0] = 0;
177                 if((p = strchr(loc, '.')) != 0 && (p - loc) < (int)sizeof(locbuf)-1) {
178                         strncpy(locbuf, loc, p - loc);
179                         locbuf[p - loc] = 0;
180                 }
181                 else if(strlen(loc) < sizeof(locbuf)-1)
182                         strcpy(locbuf, loc);
183
184                 // Locale 'C' does not give useful language info - assume en
185                 if(!locbuf[0] || locbuf[0] == 'C')
186                         strcpy(locbuf, "en");
187
188                 if((p = strchr(locbuf, '_')) && p - locbuf < LEN_LANG) {
189                         *p++ = 0;
190                         strcpy(BC_Resources::language, locbuf);
191                         if(strlen(p) < LEN_LANG)
192                                 strcpy(BC_Resources::region, p);
193                 }
194                 else if(strlen(locbuf) < LEN_LANG)
195                         strcpy(BC_Resources::language, locbuf);
196         }
197         else
198                 printf(_(PROGRAM_NAME ": Could not set locale.\n"));
199 #else
200         setlocale(LC_CTYPE, "");
201 #endif
202         tzset();
203
204
205
206
207
208
209         for(int i = 1; i < argc; i++)
210         {
211                 if(!strcmp(argv[i], "-h"))
212                 {
213                         operation = DO_USAGE;
214                 }
215                 else
216                 if(!strcmp(argv[i], "-z"))
217                 {
218                         start_remote_control = 1;
219                 }
220                 else
221                 if(!strcmp(argv[i], "-r"))
222                 {
223                         operation = DO_BATCHRENDER;
224                         if(argc > i + 1)
225                         {
226                                 if(argv[i + 1][0] != '-')
227                                 {
228                                         strcpy(batch_path, argv[i + 1]);
229                                         i++;
230                                 }
231                         }
232                 }
233                 else
234                 if(!strcmp(argv[i], "-c"))
235                 {
236                         if(argc > i + 1)
237                         {
238                                 strcpy(config_path, argv[i + 1]);
239                                 i++;
240                         }
241                         else
242                         {
243                                 fprintf(stderr, _("%s: -c needs a filename.\n"), argv[0]);
244                         }
245                 }
246                 else
247                 if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "-f"))
248                 {
249                         if(!strcmp(argv[i], "-d"))
250                                 operation = DO_DEAMON;
251                         else
252                                 operation = DO_DEAMON_FG;
253
254                         if(argc > i + 1)
255                         {
256                                 if(atol(argv[i + 1]) > 0)
257                                 {
258                                         deamon_port = atol(argv[i + 1]);
259                                         i++;
260                                 }
261                         }
262                 }
263                 else
264                 if(!strcmp(argv[i], "-b"))
265                 {
266                         operation = DO_BRENDER;
267                         if(i > argc - 2)
268                         {
269                                 fprintf(stderr, _("-b may not be used by the user.\n"));
270                                 exit(1);
271                         }
272                         else
273                                 strcpy(deamon_path, argv[i + 1]);
274                 }
275                 else
276                 if(!strcmp(argv[i], "-n"))
277                 {
278                         if(argc > i + 1)
279                         {
280                                 nice_value = atol(argv[i + 1]);
281                                 i++;
282                         }
283                 }
284                 else
285                 {
286                         char *new_filename;
287                         new_filename = new char[BCTEXTLEN];
288                         strcpy(new_filename, argv[i]);
289             fs.complete_path(new_filename);
290
291                         filenames.append(new_filename);
292                 }
293         }
294
295
296
297
298         if(operation == DO_GUI ||
299                 operation == DO_DEAMON ||
300                 operation == DO_DEAMON_FG ||
301                 operation == DO_USAGE ||
302                 operation == DO_BATCHRENDER)
303         fprintf(stderr,
304                 _(PROGRAM_NAME " " CINELERRA_VERSION " " "(C)%d Adam Williams\n\n"
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                                 mwindow.run();
408 //PRINT_TRACE
409                                 if( mwindow.reload() )
410                                         start_remote_control =
411                                                 mwindow.gui->remote_control->is_active();
412                                 else
413                                         done = 1;
414                                 if( !done ) {
415                                         mwindow.save_backup();
416                                         load_backup = 1;
417                                 }
418
419                                 mwindow.save_defaults();
420 //PRINT_TRACE
421                                 filenames.remove_all_objects();
422                         }
423 //SET_TRACE
424 DISABLE_BUFFER
425                         break;
426                 }
427         }
428
429         return 0;
430 }
431