3 * Copyright (C) 2010 Adam Williams <broadcast at earthling dot net>
4 * Copyright (C) 2003-2016 Cinelerra CV contributors
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "aboutprefs.h"
23 #include "arraylist.h"
24 #include "batchrender.h"
25 #include "bcsignals.h"
30 #include "filesystem.h"
33 #include "loadfile.inc"
37 #include "mwindowgui.h"
38 #include "pluginserver.h"
39 #include "preferences.h"
40 #include "renderfarmclient.h"
42 #include "versioninfo.h"
48 #include <sys/resource.h>
51 #if 0 // track allocators
53 #define BT_BUF_SIZE 100
56 void *buffer[BT_BUF_SIZE];
57 int nptrs = backtrace(buffer, BT_BUF_SIZE);
58 char **trace = backtrace_symbols(buffer, nptrs);
60 for( int i=0; i<nptrs; ) printf("%s ", trace[i++]);
64 #define STRB ;leaker()
68 #define STRC(v) printf("==new %p from %p sz %jd\n", v, __builtin_return_address(0), n)STRB
69 #define STRD(v) printf("==del %p from %p\n", v, __builtin_return_address(0))
70 void *operator new(size_t n) { void *vp = malloc(n); STRC(vp); bzero(vp,n); return vp; }
71 void operator delete(void *t) { STRD(t); free(t); }
72 void operator delete(void *t,size_t n) { STRD(t); free(t); }
73 void *operator new[](size_t n) { void *vp = malloc(n); STRC(vp); bzero(vp,n); return vp; }
74 void operator delete[](void *t) { STRD(t); free(t); }
75 void operator delete[](void *t,size_t n) { STRD(t); free(t); }
91 class CommandLineThread : public Thread
94 CommandLineThread(ArrayList<char*> *filenames,
97 this->filenames = filenames;
98 this->mwindow = mwindow;
109 mwindow->gui->lock_window("main");
111 mwindow->load_filenames(filenames,
112 LOADMODE_REPLACE, LOADMODE_EDL_CLIP);
114 if( filenames->size() == 1 )
115 mwindow->gui->mainmenu->add_load(filenames->get(0));
117 mwindow->gui->unlock_window();
122 ArrayList<char*> *filenames;
127 static float get_layout_scale()
129 char config_path[BCTEXTLEN];
130 sprintf(config_path,"%s/%s", File::get_config_path(), CONFIG_FILE);
131 FILE *fp = fopen(config_path,"r");
134 char line[BCTEXTLEN];
135 line[BCTEXTLEN-1] = 0;
136 while( fgets(line, BCTEXTLEN-1, fp) ) {
137 if( !strncmp(line, "LAYOUT_SCALE ",12+1) ) {
138 scale = atof(line+12);
146 /*******************************************************************
148 * Cinelerra-GG is a professional video editor for Linux. It is timeline
149 * based, supports hundreds of (de)coders, LADSPA and LV2 audio plugins,
150 * FFMPEG audio/video plugins, plus built-in audio/video plugins.
151 * Screen sizes up to 8K, any frame rate, extensive compositing features,
152 * title generator and more.
154 ********************************************************************/
155 int main(int argc, char *argv[])
157 // handle command line arguments first
159 ArrayList<char*> filenames;
160 filenames.set_array_delete();
163 time_t st; time(&st);
165 localtime_r(&st, <m);
167 int tzofs = ltm.tm_hour - gtm.tm_hour;
168 cin_timezone = tzofs * 60*60;
170 int operation = DO_GUI;
171 int deamon_port = DEAMON_PORT;
172 char deamon_path[BCTEXTLEN];
173 char config_path[BCTEXTLEN];
174 char batch_path[BCTEXTLEN];
176 int load_perpetual = 1;
181 const char *lang = getenv("LANGUAGE");
182 if( lang ) lang = cstrdup(lang);
183 File::init_cin_env_vars();
184 const char *locale_path = File::get_locale_path();
185 const char *cin = File::get_cin();
187 bindtextdomain(cin, locale_path);
189 setlocale(LC_MESSAGES, "");
191 #ifdef X_HAVE_UTF8_STRING
192 char *loc = setlocale(LC_CTYPE, "");
194 strcpy(BC_Resources::encoding, nl_langinfo(CODESET));
195 BC_Resources::locale_utf8 = !strcmp(BC_Resources::encoding, "UTF-8");
197 // Extract from locale language & region
200 if( (p = strchr(loc, '.')) != 0 && (p - loc) < (int)sizeof(locbuf)-1 ) {
201 strncpy(locbuf, loc, p - loc);
204 else if( strlen(loc) < sizeof(locbuf)-1 )
207 // Locale 'C' does not give useful language info - assume en
208 if( !locbuf[0] || locbuf[0] == 'C' )
209 strcpy(locbuf, "en");
211 if( (p = strchr(locbuf, '_')) && p - locbuf < LEN_LANG ) {
213 strcpy(BC_Resources::language, locbuf);
214 if( strlen(p) < LEN_LANG )
215 strcpy(BC_Resources::region, p);
217 else if( strlen(locbuf) < LEN_LANG )
218 strcpy(BC_Resources::language, locbuf);
221 printf(_(PROGRAM_NAME ": Could not set locale.\n"));
223 setlocale(LC_CTYPE, "");
228 int start_remote_control = 0;
230 for( int i = 1; i < argc; i++ ) {
231 if( !strcmp(argv[i], "-h") ) {
232 operation = DO_USAGE;
234 else if( !strcmp(argv[i], "-z") ) {
235 start_remote_control = 1;
237 else if( !strcmp(argv[i], "-r") ) {
238 operation = DO_BATCHRENDER;
240 if( argv[i + 1][0] != '-' ) {
241 strcpy(batch_path, argv[i + 1]);
246 else if( !strcmp(argv[i], "-c") ) {
248 strcpy(config_path, argv[i + 1]);
252 fprintf(stderr, _("%s: -c needs a filename.\n"), argv[0]);
255 else if( !strcmp(argv[i], "-d") || !strcmp(argv[i], "-f") ) {
256 operation = !strcmp(argv[i], "-d") ? DO_DEAMON : DO_DEAMON_FG;
258 if( atol(argv[i + 1]) > 0 ) {
259 deamon_port = atol(argv[i + 1]);
264 else if( !strcmp(argv[i], "-b") ) {
265 operation = DO_BRENDER;
267 fprintf(stderr, _("-b may not be used by the user.\n"));
271 strcpy(deamon_path, argv[i + 1]);
273 else if( !strcmp(argv[i], "-n") ) {
275 nice_value = atol(argv[i + 1]);
279 else if( !strcmp(argv[i], "-x") ) {
282 else if( !strcmp(argv[i], "-S") ) {
287 new_filename = new char[BCTEXTLEN];
288 strcpy(new_filename, argv[i]);
289 fs.complete_path(new_filename);
290 filenames.append(new_filename);
294 float scale = operation == DO_GUI ?
295 get_layout_scale() : 1;
297 BC_WindowBase::init_resources(scale);
299 if( operation == DO_GUI ||
300 operation == DO_DEAMON || operation == DO_DEAMON_FG ||
301 operation == DO_USAGE || operation == DO_BATCHRENDER) {
304 #define REPOMAINTXT ""
306 #ifndef COPYRIGHTTEXT1
307 #define COPYRIGHTTEXT1 ""
309 #ifndef COPYRIGHTTEXT2
310 #define COPYRIGHTTEXT2 ""
312 #ifndef COPYRIGHTTEXT3
313 #define COPYRIGHTTEXT3 ""
316 fprintf(stderr, "%s %s - %s\n%s",
317 PROGRAM_NAME,CINELERRA_VERSION, AboutPrefs::build_timestamp,
318 REPOMAINTXT COPYRIGHTTEXT1 COPYRIGHTTEXT2);
319 fprintf(stderr, "%s", COPYRIGHTTEXT3);
320 fprintf(stderr, "%s", COPYRIGHTTEXT4);
321 fprintf(stderr,"\n");
322 fprintf(stderr, "%s \n", AboutPrefs::ffmpeg_version);
323 fprintf(stderr,"\n");
324 fprintf(stderr, "%s is free software, covered by the GNU General Public License,\n"
325 "and you are welcome to change it and/or distribute copies of it under\n"
326 "certain conditions. There is absolutely no warranty for %s.\n\n",
327 PROGRAM_NAME, PROGRAM_NAME);
330 switch( operation ) {
332 printf(_("\nUsage:\n"));
333 printf(_("%s [-f] [-c configuration] [-d port] [-n nice] [-r batch file] [filenames]\n\n"), argv[0]);
334 printf(_("-d = Run in the background as renderfarm client. The port (400) is optional.\n"));
335 printf(_("-f = Run in the foreground as renderfarm client. Substitute for -d.\n"));
336 printf(_("-n = Nice value if running as renderfarm client. (19)\n"));
337 printf(_("-c = Configuration file to use instead of %s/%s.\n"),
338 File::get_config_path(), CONFIG_FILE);
339 printf(_("-r = batch render the contents of the batch file (%s/%s) with no GUI. batch file is optional.\n"),
340 File::get_config_path(), BATCH_PATH);
341 printf(_("-S = do not reload perpetual session\n"));
342 printf(_("-x = reload from backup\n"));
343 printf(_("filenames = files to load\n\n\n"));
349 if( operation == DO_DEAMON ) {
353 // Redhat 9 requires _exit instead of exit here.
358 RenderFarmClient client(deamon_port,
365 // Same thing without detachment
367 RenderFarmClient client(0,
374 case DO_BATCHRENDER: {
375 BatchRenderThread *thread = new BatchRenderThread(0);
376 thread->start_rendering(config_path,
381 int restart = 0, done = 0;
383 BC_WindowBase::get_resources()->vframe_shm = 0;
385 mwindow.create_objects(1, !filenames.total, config_path);
386 CommandLineThread *thread = 0;
388 mwindow.load_undo_data();
390 // load the initial files on seperate tracks
391 // use a new thread so it doesn't block the GUI
392 if( filenames.total ) {
393 thread = new CommandLineThread(&filenames, &mwindow);
399 mwindow.gui->lock_window("main");
400 mwindow.load_backup();
401 mwindow.gui->unlock_window();
403 if( start_remote_control ) {
404 start_remote_control = 0;
405 mwindow.gui->remote_control->activate();
412 restart = mwindow.restart();
414 mwindow.save_backup();
416 start_remote_control =
417 mwindow.gui->remote_control->is_active();
421 mwindow.save_defaults();
422 mwindow.save_undo_data();
424 filenames.remove_all_objects();
429 if( lang ) // reset to cmdline state
430 setenv("LANGUAGE", lang, 1);
432 unsetenv("LANGUAGE");
433 char exe_path[BCTEXTLEN];
434 int len = readlink("/proc/self/exe", exe_path, sizeof(exe_path)-1);
437 char *av[4] = { 0, }; int ac = 0;
439 if( load_backup ) av[ac++] = (char*) "-x";
440 if( start_remote_control ) av[ac++] = (char*) "-z";
449 filenames.remove_all_objects();
452 BC_WindowBase::finit_resources();
454 time_t et; time(&et);
456 printf("Session time: %ld:%02ld:%02ld\n", dt/3600, dt%3600/60, dt%60);
458 getrusage(RUSAGE_SELF, &ru);
459 long usr_ms = ru.ru_utime.tv_sec*1000 + ru.ru_utime.tv_usec/1000;
460 long us = usr_ms/1000; int ums = usr_ms%1000;
461 long sys_ms = ru.ru_stime.tv_sec*1000 + ru.ru_stime.tv_usec/1000;
462 long ss = sys_ms/1000; int sms = sys_ms%1000;
463 printf("Cpu time: user: %ld:%02ld:%02ld.%03d sys: %ld:%02ld:%02ld.%03d\n",
464 us/3600, us%3600/60, us%60, ums, ss/3600, ss%3600/60, ss%60, sms);