add bluray support, add dialog close fixes, scale fix
[goodguy/history.git] / cinelerra-5.0 / cinelerra / batchrender.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
5  * 
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.
10  * 
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.
15  * 
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
19  * 
20  */
21
22 #include "asset.h"
23 #include "batchrender.h"
24 #include "bcdisplayinfo.h"
25 #include "bcsignals.h"
26 #include "confirmsave.h"
27 #include "cstrdup.h"
28 #include "bchash.h"
29 #include "edits.h"
30 #include "edit.h"
31 #include "edl.h"
32 #include "edlsession.h"
33 #include "errorbox.h"
34 #include "filesystem.h"
35 #include "filexml.h"
36 #include "format.inc"
37 #include "keyframe.h"
38 #include "keys.h"
39 #include "labels.h"
40 #include "language.h"
41 #include "mainerror.h"
42 #include "mainundo.h"
43 #include "mainsession.h"
44 #include "mwindow.h"
45 #include "mwindowgui.h"
46 #include "packagedispatcher.h"
47 #include "packagerenderer.h"
48 #include "plugin.h"
49 #include "pluginset.h"
50 #include "preferences.h"
51 #include "render.h"
52 #include "theme.h"
53 #include "tracks.h"
54 #include "transportque.h"
55 #include "vframe.h"
56
57
58 static const char *list_titles[] = 
59 {
60         _("Enabled"), 
61         _("Output"),
62         _("EDL"),
63         _("Elapsed")
64 };
65
66 static int list_widths[] =
67 {
68         50,
69         100,
70         200,
71         100
72 };
73
74 BatchRenderMenuItem::BatchRenderMenuItem(MWindow *mwindow)
75  : BC_MenuItem(_("Batch Render..."), _("Shift-B"), 'B')
76 {
77         set_shift(1); 
78         this->mwindow = mwindow;
79 }
80
81 int BatchRenderMenuItem::handle_event()
82 {
83         mwindow->batch_render->start();
84         return 1;
85 }
86
87
88
89
90
91
92
93
94 BatchRenderJob::BatchRenderJob(Preferences *preferences)
95 {
96         this->preferences = preferences;
97         asset = new Asset;
98         edl_path[0] = 0;
99         strategy = 0;
100         enabled = 1;
101         elapsed = 0;
102 }
103
104 BatchRenderJob::~BatchRenderJob()
105 {
106         asset->Garbage::remove_user();
107 }
108
109 void BatchRenderJob::copy_from(BatchRenderJob *src)
110 {
111         asset->copy_from(src->asset, 0);
112         strcpy(edl_path, src->edl_path);
113         strategy = src->strategy;
114         enabled = src->enabled;
115         elapsed = 0;
116 }
117
118 void BatchRenderJob::load(FileXML *file)
119 {
120         int result = 0;
121
122         edl_path[0] = 0;
123         file->tag.get_property("EDL_PATH", edl_path);
124         strategy = file->tag.get_property("STRATEGY", strategy);
125         enabled = file->tag.get_property("ENABLED", enabled);
126         elapsed = file->tag.get_property("ELAPSED", elapsed);
127         fix_strategy();
128
129         result = file->read_tag();
130         if(!result)
131         {
132                 if(file->tag.title_is("ASSET"))
133                 {
134                         file->tag.get_property("SRC", asset->path);
135                         asset->read(file, 0);
136 // The compression parameters are stored in the defaults to reduce
137 // coding maintenance.  The defaults must now be stuffed into the XML for
138 // unique storage.
139                         BC_Hash defaults;
140                         defaults.load_string(file->read_text());
141                         asset->load_defaults(&defaults,
142                                 "",
143                                 0,
144                                 1,
145                                 0,
146                                 0,
147                                 0);
148                 }
149         }
150 }
151
152 void BatchRenderJob::save(FileXML *file)
153 {
154         file->tag.set_property("EDL_PATH", edl_path);
155         file->tag.set_property("STRATEGY", strategy);
156         file->tag.set_property("ENABLED", enabled);
157         file->tag.set_property("ELAPSED", elapsed);
158         file->append_tag();
159         file->append_newline();
160         asset->write(file,
161                 0,
162                 "");
163
164 // The compression parameters are stored in the defaults to reduce
165 // coding maintenance.  The defaults must now be stuffed into the XML for
166 // unique storage.
167         BC_Hash defaults;
168         asset->save_defaults(&defaults, 
169                 "",
170                 0,
171                 1,
172                 0,
173                 0,
174                 0);
175         char *string;
176         defaults.save_string(string);
177         file->append_text(string);
178         free(string);
179         file->tag.set_title("/JOB");
180         file->append_tag();
181         file->append_newline();
182 }
183
184 void BatchRenderJob::fix_strategy()
185 {
186         strategy = Render::fix_strategy(strategy, preferences->use_renderfarm);
187 }
188
189
190
191
192
193
194
195
196
197
198 BatchRenderThread::BatchRenderThread(MWindow *mwindow)
199  : BC_DialogThread()
200 {
201         this->mwindow = mwindow;
202         current_job = 0;
203         rendering_job = -1;
204         is_rendering = 0;
205         default_job = 0;
206         file_entries = 0;
207 }
208
209 BatchRenderThread::BatchRenderThread()
210  : BC_DialogThread()
211 {
212         mwindow = 0;
213         current_job = 0;
214         rendering_job = -1;
215         is_rendering = 0;
216         default_job = 0;
217         file_entries = 0;
218 }
219
220 BatchRenderThread::~BatchRenderThread()
221 {
222         close_window();
223 }
224
225 void BatchRenderThread::handle_close_event(int result)
226 {
227 // Save settings
228         char path[BCTEXTLEN];
229         path[0] = 0;
230         save_jobs(path);
231         save_defaults(mwindow->defaults);
232         delete default_job;
233         default_job = 0;
234         jobs.remove_all_objects();
235         if(file_entries)
236         {
237                 file_entries->remove_all_objects();
238                 delete file_entries;
239                 file_entries = 0;
240         }
241 }
242
243 BC_Window* BatchRenderThread::new_gui()
244 {
245         current_start = 0.0;
246         current_end = 0.0;
247         default_job = new BatchRenderJob(mwindow->preferences);
248         
249         
250         if(!file_entries)
251         {
252                 file_entries = new ArrayList<BC_ListBoxItem*>;
253                 FileSystem fs;
254                 char string[BCTEXTLEN];
255         // Load current directory
256                 fs.update(getcwd(string, BCTEXTLEN));
257                 for(int i = 0; i < fs.total_files(); i++)
258                 {
259                         file_entries->append(
260                                 new BC_ListBoxItem(
261                                         fs.get_entry(i)->get_name()));
262                 }
263         }
264
265         char path[BCTEXTLEN];
266         path[0] = 0;
267         load_jobs(path, mwindow->preferences);
268         load_defaults(mwindow->defaults);
269         this->gui = new BatchRenderGUI(mwindow, 
270                 this,
271                 mwindow->session->batchrender_x,
272                 mwindow->session->batchrender_y,
273                 mwindow->session->batchrender_w,
274                 mwindow->session->batchrender_h);
275         this->gui->create_objects();
276         return this->gui;
277 }
278
279
280 void BatchRenderThread::load_jobs(char *path, Preferences *preferences)
281 {
282         FileXML file;
283         int result = 0;
284
285         jobs.remove_all_objects();
286         if(path[0])
287                 file.read_from_file(path);
288         else
289                 file.read_from_file(create_path(path));
290
291         while(!result)
292         {
293                 if(!(result = file.read_tag()))
294                 {
295                         if(file.tag.title_is("JOB"))
296                         {
297                                 BatchRenderJob *job;
298                                 jobs.append(job = new BatchRenderJob(preferences));
299                                 job->load(&file);
300                         }
301                 }
302         }
303 }
304
305 void BatchRenderThread::save_jobs(char *path)
306 {
307         FileXML file;
308
309         for(int i = 0; i < jobs.total; i++)
310         {
311                 file.tag.set_title("JOB");
312                 jobs.values[i]->save(&file);
313         }
314
315         if(path[0])
316                 file.write_to_file(path);
317         else
318                 file.write_to_file(create_path(path));
319 }
320
321 void BatchRenderThread::load_defaults(BC_Hash *defaults)
322 {
323         if(default_job)
324         {
325                 default_job->asset->load_defaults(defaults,
326                         "BATCHRENDER_",
327                         1,
328                         1,
329                         1,
330                         1,
331                         1);
332                 default_job->fix_strategy();
333         }
334
335         for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
336         {
337                 char string[BCTEXTLEN];
338                 sprintf(string, "BATCHRENDER_COLUMN%d", i);
339                 column_width[i] = defaults->get(string, list_widths[i]);
340         }
341 }
342
343 void BatchRenderThread::save_defaults(BC_Hash *defaults)
344 {
345         if(default_job)
346         {
347                 default_job->asset->save_defaults(defaults,
348                         "BATCHRENDER_",
349                         1,
350                         1,
351                         1,
352                         1,
353                         1);
354                 defaults->update("BATCHRENDER_STRATEGY", default_job->strategy);
355         }
356         for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
357         {
358                 char string[BCTEXTLEN];
359                 sprintf(string, "BATCHRENDER_COLUMN%d", i);
360                 defaults->update(string, column_width[i]);
361         }
362 //      defaults->update("BATCHRENDER_JOB", current_job);
363         if(mwindow)
364                 mwindow->save_defaults();
365         else
366                 defaults->save();
367 }
368
369 char* BatchRenderThread::create_path(char *string)
370 {
371         FileSystem fs;
372         sprintf(string, "%s", BCASTDIR);
373         fs.complete_path(string);
374         strcat(string, BATCH_PATH);
375         return string;
376 }
377
378 void BatchRenderThread::new_job()
379 {
380         BatchRenderJob *result = new BatchRenderJob(mwindow->preferences);
381         result->copy_from(get_current_job());
382         jobs.append(result);
383         current_job = jobs.total - 1;
384         gui->create_list(1);
385         gui->change_job();
386 }
387
388 void BatchRenderThread::delete_job()
389 {
390         if(current_job < jobs.total && current_job >= 0)
391         {
392                 jobs.remove_object_number(current_job);
393                 if(current_job > 0) current_job--;
394                 gui->create_list(1);
395                 gui->change_job();
396         }
397 }
398
399 void BatchRenderThread::use_current_edl()
400 {
401 // printf("BatchRenderThread::use_current_edl %d %p %s\n", 
402 // __LINE__, 
403 // mwindow->edl->path, 
404 // mwindow->edl->path);
405
406         strcpy(get_current_edl(), mwindow->edl->path);
407         gui->create_list(1);
408         gui->edl_path_text->update(get_current_edl());
409 }
410
411 void BatchRenderThread::update_selected_edl()
412 {
413         FileXML xml_file;
414         char *path = get_current_edl();
415         EDL *edl = mwindow->edl;
416         edl->save_xml(&xml_file, path, 0, 0);
417         xml_file.terminate_string();
418         if( xml_file.write_to_file(path) ) {
419                 char msg[BCTEXTLEN];
420                 sprintf(msg, _("Unable to save: %s"), path);
421                 MainError::show_error(msg);
422         }
423 }
424
425 BatchRenderJob* BatchRenderThread::get_current_job()
426 {
427         BatchRenderJob *result;
428         if(current_job >= jobs.total || current_job < 0)
429         {
430                 result = default_job;
431         }
432         else
433         {
434                 result = jobs.values[current_job];
435         }
436         return result;
437 }
438
439
440 Asset* BatchRenderThread::get_current_asset()
441 {
442         return get_current_job()->asset;
443 }
444
445 char* BatchRenderThread::get_current_edl()
446 {
447         return get_current_job()->edl_path;
448 }
449
450
451 // Test EDL files for existence
452 int BatchRenderThread::test_edl_files()
453 {
454         for(int i = 0; i < jobs.total; i++)
455         {
456                 if(jobs.values[i]->enabled)
457                 {
458                         const char *path = jobs.values[i]->edl_path;
459                         if( *path == '@' ) ++path;
460                         FILE *fd = fopen(path, "r");
461                         if(!fd)
462                         {
463                                 char string[BCTEXTLEN];
464                                 sprintf(string, _("EDL %s not found.\n"), jobs.values[i]->edl_path);
465                                 if(mwindow)
466                                 {
467                                         ErrorBox error_box(_(PROGRAM_NAME ": Error"),
468                                                 mwindow->gui->get_abs_cursor_x(1),
469                                                 mwindow->gui->get_abs_cursor_y(1));
470                                         error_box.create_objects(string);
471                                         error_box.run_window();
472                                         gui->button_enable();
473                                 }
474                                 else
475                                 {
476                                         fprintf(stderr, 
477                                                 "%s",
478                                                 string);
479                                 }
480
481                                 is_rendering = 0;
482                                 return 1;
483                         }
484                         else
485                         {
486                                 fclose(fd);
487                         }
488                 }
489         }
490         return 0;
491 }
492
493 void BatchRenderThread::calculate_dest_paths(ArrayList<char*> *paths,
494         Preferences *preferences)
495 {
496         for(int i = 0; i < jobs.total; i++)
497         {
498                 BatchRenderJob *job = jobs.values[i];
499                 if(job->enabled && *job->edl_path != '@')
500                 {
501                         PackageDispatcher *packages = new PackageDispatcher;
502
503 // Load EDL
504                         TransportCommand *command = new TransportCommand;
505                         FileXML *file = new FileXML;
506                         file->read_from_file(job->edl_path);
507
508 // Use command to calculate range.
509                         command->command = NORMAL_FWD;
510                         command->get_edl()->load_xml(file, 
511                                 LOAD_ALL);
512                         command->change_type = CHANGE_ALL;
513                         command->set_playback_range();
514                         command->adjust_playback_range();
515
516 // Create test packages
517                         packages->create_packages(mwindow,
518                                 command->get_edl(),
519                                 preferences,
520                                 job->strategy, 
521                                 job->asset, 
522                                 command->start_position, 
523                                 command->end_position,
524                                 0);
525
526 // Append output paths allocated to total
527                         for(int j = 0; j < packages->get_total_packages(); j++)
528                         {
529                                 RenderPackage *package = packages->get_package(j);
530                                 paths->append(cstrdup(package->path));
531                         }
532
533 // Delete package harness
534                         delete packages;
535                         delete command;
536                         delete file;
537                 }
538         }
539 }
540
541
542 void BatchRenderThread::start_rendering(char *config_path,
543         char *batch_path)
544 {
545         BC_Hash *boot_defaults;
546         Preferences *preferences;
547         Render *render;
548         BC_Signals *signals = new BC_Signals;
549         // XXX the above stuff is leaked,
550 //PRINT_TRACE
551 // Initialize stuff which MWindow does.
552         signals->initialize();
553         MWindow::init_defaults(boot_defaults, config_path);
554         load_defaults(boot_defaults);
555         preferences = new Preferences;
556         preferences->load_defaults(boot_defaults);
557         MWindow::init_plugins(0, preferences);
558         char font_path[BCTEXTLEN];
559         strcpy(font_path, preferences->plugin_dir);
560         strcat(font_path, "/fonts");
561         BC_Resources::init_fontconfig(font_path);
562         BC_WindowBase::get_resources()->vframe_shm = 1;
563         MWindow::init_fileserver(preferences);
564
565 //PRINT_TRACE
566         load_jobs(batch_path, preferences);
567         save_jobs(batch_path);
568         save_defaults(boot_defaults);
569
570 //PRINT_TRACE
571 // Test EDL files for existence
572         if(test_edl_files()) return;
573
574 //PRINT_TRACE
575
576 // Predict all destination paths
577         ArrayList<char*> paths;
578         paths.set_array_delete();
579         calculate_dest_paths(&paths, preferences);
580
581 //PRINT_TRACE
582         int result = ConfirmSave::test_files(0, &paths);
583         paths.remove_all_objects();
584 // Abort on any existing file because it's so hard to set this up.
585         if(result) return;
586
587 //PRINT_TRACE
588         render = new Render(0);
589 //PRINT_TRACE
590         render->start_batches(&jobs, 
591                 boot_defaults,
592                 preferences);
593 //PRINT_TRACE
594 }
595
596 void BatchRenderThread::start_rendering()
597 {
598         if(is_rendering) return;
599
600         is_rendering = 1;
601         char path[BCTEXTLEN];
602         path[0] = 0;
603         save_jobs(path);
604         save_defaults(mwindow->defaults);
605         gui->button_disable();
606
607 // Test EDL files for existence
608         if(test_edl_files()) return;
609
610 // Predict all destination paths
611         ArrayList<char*> paths;
612         calculate_dest_paths(&paths,
613                 mwindow->preferences);
614
615 // Test destination files for overwrite
616         int result = ConfirmSave::test_files(mwindow, &paths);
617         paths.remove_all_objects();
618
619 // User cancelled
620         if(result)
621         {
622                 is_rendering = 0;
623                 gui->button_enable();
624                 return;
625         }
626
627         mwindow->render->start_batches(&jobs);
628 }
629
630 void BatchRenderThread::stop_rendering()
631 {
632         if(!is_rendering) return;
633         mwindow->render->stop_operation();
634         is_rendering = 0;
635 }
636
637 void BatchRenderThread::update_active(int number)
638 {
639         gui->lock_window("BatchRenderThread::update_active");
640         if(number >= 0)
641         {
642                 current_job = number;
643                 rendering_job = number;
644         }
645         else
646         {
647                 rendering_job = -1;
648                 is_rendering = 0;
649         }
650         gui->create_list(1);
651         gui->unlock_window();
652 }
653
654 void BatchRenderThread::update_done(int number, 
655         int create_list, 
656         double elapsed_time)
657 {
658         gui->lock_window("BatchRenderThread::update_done");
659         if(number < 0)
660         {
661                 gui->button_enable();
662         }
663         else
664         {
665                 jobs.values[number]->enabled = 0;
666                 jobs.values[number]->elapsed = elapsed_time;
667                 if(create_list) gui->create_list(1);
668         }
669         gui->unlock_window();
670 }
671
672 void BatchRenderThread::move_batch(int src, int dst)
673 {
674         BatchRenderJob *src_job = jobs.values[src];
675         if(dst < 0) dst = jobs.total - 1;
676
677         if(dst != src)
678         {
679                 for(int i = src; i < jobs.total - 1; i++)
680                         jobs.values[i] = jobs.values[i + 1];
681 //              if(dst > src) dst--;
682                 for(int i = jobs.total - 1; i > dst; i--)
683                         jobs.values[i] = jobs.values[i - 1];
684                 jobs.values[dst] = src_job;
685                 gui->create_list(1);
686         }
687 }
688
689
690
691
692
693
694
695 BatchRenderGUI::BatchRenderGUI(MWindow *mwindow, 
696         BatchRenderThread *thread,
697         int x,
698         int y,
699         int w,
700         int h)
701  : BC_Window(_(PROGRAM_NAME ": Batch Render"), 
702         x,
703         y,
704         w, 
705         h, 
706         50, 
707         50, 
708         1,
709         0, 
710         1)
711 {
712         this->mwindow = mwindow;
713         this->thread = thread;
714 }
715
716 BatchRenderGUI::~BatchRenderGUI()
717 {
718         lock_window("BatchRenderGUI::~BatchRenderGUI");
719         delete format_tools;
720         unlock_window();
721 }
722
723
724 void BatchRenderGUI::create_objects()
725 {
726         lock_window("BatchRenderGUI::create_objects");
727         mwindow->theme->get_batchrender_sizes(this, get_w(), get_h());
728         create_list(0);
729
730         int x = mwindow->theme->batchrender_x1;
731         int y = 5;
732         int x1 = mwindow->theme->batchrender_x1;
733         int x2 = mwindow->theme->batchrender_x2;
734         //int x3 = mwindow->theme->batchrender_x3;
735         int y1 = y;
736         int y2;
737
738 // output file
739         add_subwindow(output_path_title = new BC_Title(x1, y, _("Output path:")));
740         y += 20;
741         format_tools = new BatchFormat(mwindow,
742                                         this, 
743                                         thread->get_current_asset());
744         format_tools->set_w(get_w() / 2);
745         format_tools->create_objects(x, 
746                                                 y, 
747                                                 1, 
748                                                 1, 
749                                                 1, 
750                                                 1, 
751                                                 0, 
752                                                 1, 
753                                                 0, 
754                                                 0, 
755                                                 &thread->get_current_job()->strategy, 
756                                                 0);
757
758         x2 = x;
759         y2 = y + 10;
760         x += format_tools->get_w();
761         y = y1;
762         x1 = x;
763         //x3 = x + 80;
764
765 // input EDL
766         x = x1;
767         add_subwindow(edl_path_title = new BC_Title(x, y, _("EDL Path:")));
768         y += 20;
769         add_subwindow(edl_path_text = new BatchRenderEDLPath(
770                 thread, 
771                 x, 
772                 y, 
773                 get_w() - x - 40, 
774                 thread->get_current_edl()));
775
776         x += edl_path_text->get_w();
777         add_subwindow(edl_path_browse = new BrowseButton(
778                 mwindow,
779                 this,
780                 edl_path_text, 
781                 x, 
782                 y, 
783                 thread->get_current_edl(),
784                 _("Input EDL"),
785                 _("Select an EDL to load:"),
786                 0));
787
788         x = x1;
789
790         y += 64;
791         add_subwindow(update_selected_edl = new BatchRenderUpdateEDL(thread,
792                 x,
793                 y));
794         y += update_selected_edl->get_h() + mwindow->theme->widget_border;
795
796         add_subwindow(new_batch = new BatchRenderNew(thread, 
797                 x, 
798                 y));
799         x += new_batch->get_w() + 10;
800
801         add_subwindow(delete_batch = new BatchRenderDelete(thread, 
802                 x, 
803                 y));
804         x = new_batch->get_x();
805         y += new_batch->get_h() + mwindow->theme->widget_border;
806         add_subwindow(use_current_edl = new BatchRenderCurrentEDL(thread,
807                 x,
808                 y));
809         if( !mwindow->edl || !mwindow->edl->path[0] ) use_current_edl->disable();
810
811         x = x2;
812         y = y2;
813         add_subwindow(list_title = new BC_Title(x, y, _("Batches to render:")));
814         y += 20;
815         add_subwindow(batch_list = new BatchRenderList(thread, 
816                 x, 
817                 y,
818                 get_w() - x - 10,
819                 get_h() - y - BC_GenericButton::calculate_h() - 15));
820
821         y += batch_list->get_h() + 10;
822         add_subwindow(start_button = new BatchRenderStart(thread, 
823             x, 
824             y));
825         x = get_w() / 2 -
826                 BC_GenericButton::calculate_w(this, _("Stop")) / 2;
827         add_subwindow(stop_button = new BatchRenderStop(thread, 
828                 x, 
829                 y));
830         x = get_w() - 
831                 BC_GenericButton::calculate_w(this, _("Close")) - 
832                 10;
833         add_subwindow(cancel_button = new BatchRenderCancel(thread, 
834                 x, 
835                 y));
836
837         show_window(1);
838         unlock_window();
839 }
840
841 void BatchRenderGUI::button_disable()
842 {
843         new_batch->disable();
844         delete_batch->disable();
845         use_current_edl->disable();
846         update_selected_edl->disable();
847 }
848
849 void BatchRenderGUI::button_enable()
850 {
851         new_batch->enable();
852         delete_batch->enable();
853         if( mwindow->edl && mwindow->edl->path[0] )
854                 use_current_edl->enable();
855         update_selected_edl->enable();
856 }
857
858 int BatchRenderGUI::resize_event(int w, int h)
859 {
860         mwindow->session->batchrender_w = w;
861         mwindow->session->batchrender_h = h;
862         mwindow->theme->get_batchrender_sizes(this, w, h);
863
864         int x = mwindow->theme->batchrender_x1;
865         int y = 5;
866         int x1 = mwindow->theme->batchrender_x1;
867         int x2 = mwindow->theme->batchrender_x2;
868         //int x3 = mwindow->theme->batchrender_x3;
869         int y1 = y;
870         int y2;
871
872         output_path_title->reposition_window(x1, y);
873         y += 20;
874         format_tools->reposition_window(x, y);
875         x2 = x;
876         y2 = y + 10;
877         y = y1;
878         x += format_tools->get_w();
879         x1 = x;
880         //x3 = x + 80;
881
882         x = x1;
883         edl_path_title->reposition_window(x, y);
884         y += 20;
885         edl_path_text->reposition_window(x, y, w - x - 40);
886         x += edl_path_text->get_w();
887         edl_path_browse->reposition_window(x, y);
888
889         x = x1;
890 //      y += 30;
891 //      status_title->reposition_window(x, y);
892 //      x = x3;
893 //      status_text->reposition_window(x, y);
894 //      x = x1;
895 //      y += 30;
896 //      progress_bar->reposition_window(x, y, w - x - 10);
897
898         y += 30;
899         update_selected_edl->reposition_window(x, y);
900         y += update_selected_edl->get_h() + mwindow->theme->widget_border;
901         new_batch->reposition_window(x, y);
902         x += new_batch->get_w() + 10;
903         delete_batch->reposition_window(x, y);
904         x = new_batch->get_x();
905         y += new_batch->get_h() + mwindow->theme->widget_border;
906         use_current_edl->reposition_window(x, y);
907
908         x = x2;
909         y = y2;
910         int y_margin = get_h() - batch_list->get_h();
911         list_title->reposition_window(x, y);
912         y += 20;
913         batch_list->reposition_window(x, y, w - x - 10, h - y_margin);
914
915         y += batch_list->get_h() + 10;
916         start_button->reposition_window(x, y);
917         x = w / 2 - 
918                 stop_button->get_w() / 2;
919         stop_button->reposition_window(x, y);
920         x = w -
921                 cancel_button->get_w() - 
922                 10;
923         cancel_button->reposition_window(x, y);
924         return 1;
925 }
926
927 int BatchRenderGUI::translation_event()
928 {
929         mwindow->session->batchrender_x = get_x();
930         mwindow->session->batchrender_y = get_y();
931         return 1;
932 }
933
934 int BatchRenderGUI::close_event()
935 {
936 // Stop batch rendering
937         unlock_window();
938         thread->stop_rendering();
939         lock_window("BatchRenderGUI::close_event");
940         set_done(1);
941         return 1;
942 }
943
944 void BatchRenderGUI::create_list(int update_widget)
945 {
946         for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
947         {
948                 list_columns[i].remove_all_objects();
949         }
950
951         for(int i = 0; i < thread->jobs.total; i++)
952         {
953                 BatchRenderJob *job = thread->jobs.values[i];
954                 char string[BCTEXTLEN];
955                 BC_ListBoxItem *enabled = new BC_ListBoxItem(job->enabled ? 
956                         (char*)"X" : 
957                         (char*)" ");
958                 BC_ListBoxItem *item1 = new BC_ListBoxItem(job->asset->path);
959                 BC_ListBoxItem *item2 = new BC_ListBoxItem(job->edl_path);
960                 BC_ListBoxItem *item3;
961                 if(job->elapsed)
962                         item3 = new BC_ListBoxItem(
963                                 Units::totext(string,
964                                         job->elapsed,
965                                         TIME_HMS2));
966                 else
967                         item3 = new BC_ListBoxItem(_("Unknown"));
968                 list_columns[0].append(enabled);
969                 list_columns[1].append(item1);
970                 list_columns[2].append(item2);
971                 list_columns[3].append(item3);
972                 if(i == thread->current_job)
973                 {
974                         enabled->set_selected(1);
975                         item1->set_selected(1);
976                         item2->set_selected(1);
977                         item3->set_selected(1);
978                 }
979                 if(i == thread->rendering_job)
980                 {
981                         enabled->set_color(RED);
982                         item1->set_color(RED);
983                         item2->set_color(RED);
984                         item3->set_color(RED);
985                 }
986         }
987
988         if(update_widget)
989         {
990                 batch_list->update(list_columns,
991                                                 list_titles,
992                                                 thread->column_width,
993                                                 BATCHRENDER_COLUMNS,
994                                                 batch_list->get_xposition(),
995                                                 batch_list->get_yposition(), 
996                                                 batch_list->get_highlighted_item(),  // Flat index of item cursor is over
997                                                 1,     // set all autoplace flags to 1
998                                                 1);
999         }
1000 }
1001
1002 void BatchRenderGUI::change_job()
1003 {
1004         BatchRenderJob *job = thread->get_current_job();
1005         format_tools->update(job->asset, &job->strategy);
1006         edl_path_text->update(job->edl_path);
1007 }
1008
1009
1010
1011
1012
1013
1014
1015
1016 BatchFormat::BatchFormat(MWindow *mwindow,
1017                         BatchRenderGUI *gui,
1018                         Asset *asset)
1019  : FormatTools(mwindow, gui, asset)
1020 {
1021         this->gui = gui;
1022         this->mwindow = mwindow;
1023 }
1024
1025 BatchFormat::~BatchFormat()
1026 {
1027 }
1028
1029
1030 int BatchFormat::handle_event()
1031 {
1032         gui->create_list(1);
1033         return 1;
1034 }
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046 BatchRenderEDLPath::BatchRenderEDLPath(BatchRenderThread *thread, 
1047         int x, 
1048         int y, 
1049         int w, 
1050         char *text)
1051  : BC_TextBox(x, 
1052                 y, 
1053                 w, 
1054                 1,
1055                 text)
1056 {
1057         this->thread = thread;
1058 }
1059
1060
1061 int BatchRenderEDLPath::handle_event()
1062 {
1063 // Suggestions
1064         calculate_suggestions(thread->file_entries);
1065
1066         strcpy(thread->get_current_edl(), get_text());
1067         thread->gui->create_list(1);
1068         return 1;
1069 }
1070
1071
1072
1073
1074
1075
1076 BatchRenderNew::BatchRenderNew(BatchRenderThread *thread, 
1077         int x, 
1078         int y)
1079  : BC_GenericButton(x, y, _("New"))
1080 {
1081         this->thread = thread;
1082 }
1083
1084 int BatchRenderNew::handle_event()
1085 {
1086         thread->new_job();
1087         return 1;
1088 }
1089
1090 BatchRenderDelete::BatchRenderDelete(BatchRenderThread *thread, 
1091         int x, 
1092         int y)
1093  : BC_GenericButton(x, y, _("Delete"))
1094 {
1095         this->thread = thread;
1096 }
1097
1098 int BatchRenderDelete::handle_event()
1099 {
1100         thread->delete_job();
1101         return 1;
1102 }
1103
1104
1105
1106
1107
1108
1109 BatchRenderCurrentEDL::BatchRenderCurrentEDL(BatchRenderThread *thread, 
1110         int x, 
1111         int y)
1112  : BC_GenericButton(x, y, _("Use Current EDL"))
1113 {
1114         this->thread = thread;
1115 }
1116
1117 int BatchRenderCurrentEDL::handle_event()
1118 {
1119         thread->use_current_edl();
1120         return 1;
1121 }
1122
1123 BatchRenderUpdateEDL::BatchRenderUpdateEDL(BatchRenderThread *thread, 
1124         int x, 
1125         int y)
1126  : BC_GenericButton(x, y, _("Save to EDL Path"))
1127 {
1128         this->thread = thread;
1129 }
1130
1131 int BatchRenderUpdateEDL::handle_event()
1132 {
1133         thread->update_selected_edl();
1134         return 1;
1135 }
1136
1137
1138
1139
1140 BatchRenderList::BatchRenderList(BatchRenderThread *thread, 
1141         int x, 
1142         int y,
1143         int w,
1144         int h)
1145  : BC_ListBox(x, 
1146         y, 
1147         w, 
1148         h, 
1149         LISTBOX_TEXT,
1150         thread->gui->list_columns,
1151         list_titles,
1152         thread->column_width,
1153         BATCHRENDER_COLUMNS,
1154         0,
1155         0,
1156         LISTBOX_SINGLE,
1157         ICON_LEFT,
1158         1)
1159 {
1160         this->thread = thread;
1161         dragging_item = 0;
1162         set_process_drag(0);
1163 }
1164
1165 int BatchRenderList::handle_event()
1166 {
1167         return 1;
1168 }
1169
1170 int BatchRenderList::selection_changed()
1171 {
1172         thread->current_job = get_selection_number(0, 0);
1173         thread->gui->change_job();
1174         if(get_cursor_x() < thread->column_width[0])
1175         {
1176                 BatchRenderJob *job = thread->get_current_job();
1177                 job->enabled = !job->enabled;
1178                 thread->gui->create_list(1);
1179         }
1180         return 1;
1181 }
1182
1183 int BatchRenderList::column_resize_event()
1184 {
1185         for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
1186         {
1187                 thread->column_width[i] = get_column_width(i);
1188         }
1189         return 1;
1190 }
1191
1192 int BatchRenderList::drag_start_event()
1193 {
1194         if(BC_ListBox::drag_start_event())
1195         {
1196                 dragging_item = 1;
1197                 return 1;
1198         }
1199
1200         return 0;
1201 }
1202
1203 int BatchRenderList::drag_motion_event()
1204 {
1205         if(BC_ListBox::drag_motion_event())
1206         {
1207                 return 1;
1208         }
1209         return 0;
1210 }
1211
1212 int BatchRenderList::drag_stop_event()
1213 {
1214         if(dragging_item)
1215         {
1216                 int src = get_selection_number(0, 0);
1217                 int dst = get_highlighted_item();
1218                 if(src != dst)
1219                 {
1220                         thread->move_batch(src, dst);
1221                 }
1222                 BC_ListBox::drag_stop_event();
1223         }
1224         return 0;
1225 }
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239 BatchRenderStart::BatchRenderStart(BatchRenderThread *thread, 
1240         int x, 
1241         int y)
1242  : BC_GenericButton(x, 
1243         y, 
1244         _("Start"))
1245 {
1246         this->thread = thread;
1247 }
1248
1249 int BatchRenderStart::handle_event()
1250 {
1251         thread->start_rendering();
1252         return 1;
1253 }
1254
1255 BatchRenderStop::BatchRenderStop(BatchRenderThread *thread, 
1256         int x, 
1257         int y)
1258  : BC_GenericButton(x, 
1259         y, 
1260         _("Stop"))
1261 {
1262         this->thread = thread;
1263 }
1264
1265 int BatchRenderStop::handle_event()
1266 {
1267         unlock_window();
1268         thread->stop_rendering();
1269         lock_window("BatchRenderStop::handle_event");
1270         return 1;
1271 }
1272
1273
1274 BatchRenderCancel::BatchRenderCancel(BatchRenderThread *thread, 
1275         int x, 
1276         int y)
1277  : BC_GenericButton(x, 
1278         y, 
1279         _("Close"))
1280 {
1281         this->thread = thread;
1282 }
1283
1284 int BatchRenderCancel::handle_event()
1285 {
1286         unlock_window();
1287         thread->stop_rendering();
1288         lock_window("BatchRenderCancel::handle_event");
1289         thread->gui->set_done(1);
1290         return 1;
1291 }
1292
1293 int BatchRenderCancel::keypress_event()
1294 {
1295         if(get_keypress() == ESC) 
1296         {
1297                 unlock_window();
1298                 thread->stop_rendering();
1299                 lock_window("BatchRenderCancel::keypress_event");
1300                 thread->gui->set_done(1);
1301                 return 1;
1302         }
1303         return 0;
1304 }
1305