prevent popup deactivation while button_down
[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
564 //PRINT_TRACE
565         load_jobs(batch_path, preferences);
566         save_jobs(batch_path);
567         save_defaults(boot_defaults);
568
569 //PRINT_TRACE
570 // Test EDL files for existence
571         if(test_edl_files()) return;
572
573 //PRINT_TRACE
574
575 // Predict all destination paths
576         ArrayList<char*> paths;
577         paths.set_array_delete();
578         calculate_dest_paths(&paths, preferences);
579
580 //PRINT_TRACE
581         int result = ConfirmSave::test_files(0, &paths);
582         paths.remove_all_objects();
583 // Abort on any existing file because it's so hard to set this up.
584         if(result) return;
585
586 //PRINT_TRACE
587         render = new Render(0);
588 //PRINT_TRACE
589         render->start_batches(&jobs, 
590                 boot_defaults,
591                 preferences);
592 //PRINT_TRACE
593 }
594
595 void BatchRenderThread::start_rendering()
596 {
597         if(is_rendering) return;
598
599         is_rendering = 1;
600         char path[BCTEXTLEN];
601         path[0] = 0;
602         save_jobs(path);
603         save_defaults(mwindow->defaults);
604         gui->button_disable();
605
606 // Test EDL files for existence
607         if(test_edl_files()) return;
608
609 // Predict all destination paths
610         ArrayList<char*> paths;
611         calculate_dest_paths(&paths,
612                 mwindow->preferences);
613
614 // Test destination files for overwrite
615         int result = ConfirmSave::test_files(mwindow, &paths);
616         paths.remove_all_objects();
617
618 // User cancelled
619         if(result)
620         {
621                 is_rendering = 0;
622                 gui->button_enable();
623                 return;
624         }
625
626         mwindow->render->start_batches(&jobs);
627 }
628
629 void BatchRenderThread::stop_rendering()
630 {
631         if(!is_rendering) return;
632         mwindow->render->stop_operation();
633         is_rendering = 0;
634 }
635
636 void BatchRenderThread::update_active(int number)
637 {
638         gui->lock_window("BatchRenderThread::update_active");
639         if(number >= 0)
640         {
641                 current_job = number;
642                 rendering_job = number;
643         }
644         else
645         {
646                 rendering_job = -1;
647                 is_rendering = 0;
648         }
649         gui->create_list(1);
650         gui->unlock_window();
651 }
652
653 void BatchRenderThread::update_done(int number, 
654         int create_list, 
655         double elapsed_time)
656 {
657         gui->lock_window("BatchRenderThread::update_done");
658         if(number < 0)
659         {
660                 gui->button_enable();
661         }
662         else
663         {
664                 jobs.values[number]->enabled = 0;
665                 jobs.values[number]->elapsed = elapsed_time;
666                 if(create_list) gui->create_list(1);
667         }
668         gui->unlock_window();
669 }
670
671 void BatchRenderThread::move_batch(int src, int dst)
672 {
673         BatchRenderJob *src_job = jobs.values[src];
674         if(dst < 0) dst = jobs.total - 1;
675
676         if(dst != src)
677         {
678                 for(int i = src; i < jobs.total - 1; i++)
679                         jobs.values[i] = jobs.values[i + 1];
680 //              if(dst > src) dst--;
681                 for(int i = jobs.total - 1; i > dst; i--)
682                         jobs.values[i] = jobs.values[i - 1];
683                 jobs.values[dst] = src_job;
684                 gui->create_list(1);
685         }
686 }
687
688
689
690
691
692
693
694 BatchRenderGUI::BatchRenderGUI(MWindow *mwindow, 
695         BatchRenderThread *thread,
696         int x,
697         int y,
698         int w,
699         int h)
700  : BC_Window(_(PROGRAM_NAME ": Batch Render"), 
701         x,
702         y,
703         w, 
704         h, 
705         50, 
706         50, 
707         1,
708         0, 
709         1)
710 {
711         this->mwindow = mwindow;
712         this->thread = thread;
713 }
714
715 BatchRenderGUI::~BatchRenderGUI()
716 {
717         lock_window("BatchRenderGUI::~BatchRenderGUI");
718         delete format_tools;
719         unlock_window();
720 }
721
722
723 void BatchRenderGUI::create_objects()
724 {
725         lock_window("BatchRenderGUI::create_objects");
726         mwindow->theme->get_batchrender_sizes(this, get_w(), get_h());
727         create_list(0);
728
729         int x = mwindow->theme->batchrender_x1;
730         int y = 5;
731         int x1 = mwindow->theme->batchrender_x1;
732         int x2 = mwindow->theme->batchrender_x2;
733         //int x3 = mwindow->theme->batchrender_x3;
734         int y1 = y;
735         int y2;
736
737 // output file
738         add_subwindow(output_path_title = new BC_Title(x1, y, _("Output path:")));
739         y += 20;
740         format_tools = new BatchFormat(mwindow,
741                                         this, 
742                                         thread->get_current_asset());
743         format_tools->set_w(get_w() / 2);
744         format_tools->create_objects(x, 
745                                                 y, 
746                                                 1, 
747                                                 1, 
748                                                 1, 
749                                                 1, 
750                                                 0, 
751                                                 1, 
752                                                 0, 
753                                                 0, 
754                                                 &thread->get_current_job()->strategy, 
755                                                 0);
756
757         x2 = x;
758         y2 = y + 10;
759         x += format_tools->get_w();
760         y = y1;
761         x1 = x;
762         //x3 = x + 80;
763
764 // input EDL
765         x = x1;
766         add_subwindow(edl_path_title = new BC_Title(x, y, _("EDL Path:")));
767         y += 20;
768         add_subwindow(edl_path_text = new BatchRenderEDLPath(
769                 thread, 
770                 x, 
771                 y, 
772                 get_w() - x - 40, 
773                 thread->get_current_edl()));
774
775         x += edl_path_text->get_w();
776         add_subwindow(edl_path_browse = new BrowseButton(
777                 mwindow,
778                 this,
779                 edl_path_text, 
780                 x, 
781                 y, 
782                 thread->get_current_edl(),
783                 _("Input EDL"),
784                 _("Select an EDL to load:"),
785                 0));
786
787         x = x1;
788
789         y += 64;
790         add_subwindow(update_selected_edl = new BatchRenderUpdateEDL(thread,
791                 x,
792                 y));
793         y += update_selected_edl->get_h() + mwindow->theme->widget_border;
794
795         add_subwindow(new_batch = new BatchRenderNew(thread, 
796                 x, 
797                 y));
798         x += new_batch->get_w() + 10;
799
800         add_subwindow(delete_batch = new BatchRenderDelete(thread, 
801                 x, 
802                 y));
803         x = new_batch->get_x();
804         y += new_batch->get_h() + mwindow->theme->widget_border;
805         add_subwindow(use_current_edl = new BatchRenderCurrentEDL(thread,
806                 x,
807                 y));
808         if( !mwindow->edl || !mwindow->edl->path[0] ) use_current_edl->disable();
809
810         x = x2;
811         y = y2;
812         add_subwindow(list_title = new BC_Title(x, y, _("Batches to render:")));
813         y += 20;
814         add_subwindow(batch_list = new BatchRenderList(thread, 
815                 x, 
816                 y,
817                 get_w() - x - 10,
818                 get_h() - y - BC_GenericButton::calculate_h() - 15));
819
820         y += batch_list->get_h() + 10;
821         add_subwindow(start_button = new BatchRenderStart(thread, 
822             x, 
823             y));
824         x = get_w() / 2 -
825                 BC_GenericButton::calculate_w(this, _("Stop")) / 2;
826         add_subwindow(stop_button = new BatchRenderStop(thread, 
827                 x, 
828                 y));
829         x = get_w() - 
830                 BC_GenericButton::calculate_w(this, _("Close")) - 
831                 10;
832         add_subwindow(cancel_button = new BatchRenderCancel(thread, 
833                 x, 
834                 y));
835
836         show_window(1);
837         unlock_window();
838 }
839
840 void BatchRenderGUI::button_disable()
841 {
842         new_batch->disable();
843         delete_batch->disable();
844         use_current_edl->disable();
845         update_selected_edl->disable();
846 }
847
848 void BatchRenderGUI::button_enable()
849 {
850         new_batch->enable();
851         delete_batch->enable();
852         if( mwindow->edl && mwindow->edl->path[0] )
853                 use_current_edl->enable();
854         update_selected_edl->enable();
855 }
856
857 int BatchRenderGUI::resize_event(int w, int h)
858 {
859         mwindow->session->batchrender_w = w;
860         mwindow->session->batchrender_h = h;
861         mwindow->theme->get_batchrender_sizes(this, w, h);
862
863         int x = mwindow->theme->batchrender_x1;
864         int y = 5;
865         int x1 = mwindow->theme->batchrender_x1;
866         int x2 = mwindow->theme->batchrender_x2;
867         //int x3 = mwindow->theme->batchrender_x3;
868         int y1 = y;
869         int y2;
870
871         output_path_title->reposition_window(x1, y);
872         y += 20;
873         format_tools->reposition_window(x, y);
874         x2 = x;
875         y2 = y + 10;
876         y = y1;
877         x += format_tools->get_w();
878         x1 = x;
879         //x3 = x + 80;
880
881         x = x1;
882         edl_path_title->reposition_window(x, y);
883         y += 20;
884         edl_path_text->reposition_window(x, y, w - x - 40);
885         x += edl_path_text->get_w();
886         edl_path_browse->reposition_window(x, y);
887
888         x = x1;
889 //      y += 30;
890 //      status_title->reposition_window(x, y);
891 //      x = x3;
892 //      status_text->reposition_window(x, y);
893 //      x = x1;
894 //      y += 30;
895 //      progress_bar->reposition_window(x, y, w - x - 10);
896
897         y += 30;
898         update_selected_edl->reposition_window(x, y);
899         y += update_selected_edl->get_h() + mwindow->theme->widget_border;
900         new_batch->reposition_window(x, y);
901         x += new_batch->get_w() + 10;
902         delete_batch->reposition_window(x, y);
903         x = new_batch->get_x();
904         y += new_batch->get_h() + mwindow->theme->widget_border;
905         use_current_edl->reposition_window(x, y);
906
907         x = x2;
908         y = y2;
909         int y_margin = get_h() - batch_list->get_h();
910         list_title->reposition_window(x, y);
911         y += 20;
912         batch_list->reposition_window(x, y, w - x - 10, h - y_margin);
913
914         y += batch_list->get_h() + 10;
915         start_button->reposition_window(x, y);
916         x = w / 2 - 
917                 stop_button->get_w() / 2;
918         stop_button->reposition_window(x, y);
919         x = w -
920                 cancel_button->get_w() - 
921                 10;
922         cancel_button->reposition_window(x, y);
923         return 1;
924 }
925
926 int BatchRenderGUI::translation_event()
927 {
928         mwindow->session->batchrender_x = get_x();
929         mwindow->session->batchrender_y = get_y();
930         return 1;
931 }
932
933 int BatchRenderGUI::close_event()
934 {
935 // Stop batch rendering
936         unlock_window();
937         thread->stop_rendering();
938         lock_window("BatchRenderGUI::close_event");
939         set_done(1);
940         return 1;
941 }
942
943 void BatchRenderGUI::create_list(int update_widget)
944 {
945         for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
946         {
947                 list_columns[i].remove_all_objects();
948         }
949
950         for(int i = 0; i < thread->jobs.total; i++)
951         {
952                 BatchRenderJob *job = thread->jobs.values[i];
953                 char string[BCTEXTLEN];
954                 BC_ListBoxItem *enabled = new BC_ListBoxItem(job->enabled ? 
955                         (char*)"X" : 
956                         (char*)" ");
957                 BC_ListBoxItem *item1 = new BC_ListBoxItem(job->asset->path);
958                 BC_ListBoxItem *item2 = new BC_ListBoxItem(job->edl_path);
959                 BC_ListBoxItem *item3;
960                 if(job->elapsed)
961                         item3 = new BC_ListBoxItem(
962                                 Units::totext(string,
963                                         job->elapsed,
964                                         TIME_HMS2));
965                 else
966                         item3 = new BC_ListBoxItem(_("Unknown"));
967                 list_columns[0].append(enabled);
968                 list_columns[1].append(item1);
969                 list_columns[2].append(item2);
970                 list_columns[3].append(item3);
971                 if(i == thread->current_job)
972                 {
973                         enabled->set_selected(1);
974                         item1->set_selected(1);
975                         item2->set_selected(1);
976                         item3->set_selected(1);
977                 }
978                 if(i == thread->rendering_job)
979                 {
980                         enabled->set_color(RED);
981                         item1->set_color(RED);
982                         item2->set_color(RED);
983                         item3->set_color(RED);
984                 }
985         }
986
987         if(update_widget)
988         {
989                 batch_list->update(list_columns,
990                                                 list_titles,
991                                                 thread->column_width,
992                                                 BATCHRENDER_COLUMNS,
993                                                 batch_list->get_xposition(),
994                                                 batch_list->get_yposition(), 
995                                                 batch_list->get_highlighted_item(),  // Flat index of item cursor is over
996                                                 1,     // set all autoplace flags to 1
997                                                 1);
998         }
999 }
1000
1001 void BatchRenderGUI::change_job()
1002 {
1003         BatchRenderJob *job = thread->get_current_job();
1004         format_tools->update(job->asset, &job->strategy);
1005         edl_path_text->update(job->edl_path);
1006 }
1007
1008
1009
1010
1011
1012
1013
1014
1015 BatchFormat::BatchFormat(MWindow *mwindow,
1016                         BatchRenderGUI *gui,
1017                         Asset *asset)
1018  : FormatTools(mwindow, gui, asset)
1019 {
1020         this->gui = gui;
1021         this->mwindow = mwindow;
1022 }
1023
1024 BatchFormat::~BatchFormat()
1025 {
1026 }
1027
1028
1029 int BatchFormat::handle_event()
1030 {
1031         gui->create_list(1);
1032         return 1;
1033 }
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045 BatchRenderEDLPath::BatchRenderEDLPath(BatchRenderThread *thread, 
1046         int x, 
1047         int y, 
1048         int w, 
1049         char *text)
1050  : BC_TextBox(x, 
1051                 y, 
1052                 w, 
1053                 1,
1054                 text)
1055 {
1056         this->thread = thread;
1057 }
1058
1059
1060 int BatchRenderEDLPath::handle_event()
1061 {
1062 // Suggestions
1063         calculate_suggestions(thread->file_entries);
1064
1065         strcpy(thread->get_current_edl(), get_text());
1066         thread->gui->create_list(1);
1067         return 1;
1068 }
1069
1070
1071
1072
1073
1074
1075 BatchRenderNew::BatchRenderNew(BatchRenderThread *thread, 
1076         int x, 
1077         int y)
1078  : BC_GenericButton(x, y, _("New"))
1079 {
1080         this->thread = thread;
1081 }
1082
1083 int BatchRenderNew::handle_event()
1084 {
1085         thread->new_job();
1086         return 1;
1087 }
1088
1089 BatchRenderDelete::BatchRenderDelete(BatchRenderThread *thread, 
1090         int x, 
1091         int y)
1092  : BC_GenericButton(x, y, _("Delete"))
1093 {
1094         this->thread = thread;
1095 }
1096
1097 int BatchRenderDelete::handle_event()
1098 {
1099         thread->delete_job();
1100         return 1;
1101 }
1102
1103
1104
1105
1106
1107
1108 BatchRenderCurrentEDL::BatchRenderCurrentEDL(BatchRenderThread *thread, 
1109         int x, 
1110         int y)
1111  : BC_GenericButton(x, y, _("Use Current EDL"))
1112 {
1113         this->thread = thread;
1114 }
1115
1116 int BatchRenderCurrentEDL::handle_event()
1117 {
1118         thread->use_current_edl();
1119         return 1;
1120 }
1121
1122 BatchRenderUpdateEDL::BatchRenderUpdateEDL(BatchRenderThread *thread, 
1123         int x, 
1124         int y)
1125  : BC_GenericButton(x, y, _("Save to EDL Path"))
1126 {
1127         this->thread = thread;
1128 }
1129
1130 int BatchRenderUpdateEDL::handle_event()
1131 {
1132         thread->update_selected_edl();
1133         return 1;
1134 }
1135
1136
1137
1138
1139 BatchRenderList::BatchRenderList(BatchRenderThread *thread, 
1140         int x, 
1141         int y,
1142         int w,
1143         int h)
1144  : BC_ListBox(x, 
1145         y, 
1146         w, 
1147         h, 
1148         LISTBOX_TEXT,
1149         thread->gui->list_columns,
1150         list_titles,
1151         thread->column_width,
1152         BATCHRENDER_COLUMNS,
1153         0,
1154         0,
1155         LISTBOX_SINGLE,
1156         ICON_LEFT,
1157         1)
1158 {
1159         this->thread = thread;
1160         dragging_item = 0;
1161         set_process_drag(0);
1162 }
1163
1164 int BatchRenderList::handle_event()
1165 {
1166         return 1;
1167 }
1168
1169 int BatchRenderList::selection_changed()
1170 {
1171         thread->current_job = get_selection_number(0, 0);
1172         thread->gui->change_job();
1173         if(get_cursor_x() < thread->column_width[0])
1174         {
1175                 BatchRenderJob *job = thread->get_current_job();
1176                 job->enabled = !job->enabled;
1177                 thread->gui->create_list(1);
1178         }
1179         return 1;
1180 }
1181
1182 int BatchRenderList::column_resize_event()
1183 {
1184         for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
1185         {
1186                 thread->column_width[i] = get_column_width(i);
1187         }
1188         return 1;
1189 }
1190
1191 int BatchRenderList::drag_start_event()
1192 {
1193         if(BC_ListBox::drag_start_event())
1194         {
1195                 dragging_item = 1;
1196                 return 1;
1197         }
1198
1199         return 0;
1200 }
1201
1202 int BatchRenderList::drag_motion_event()
1203 {
1204         if(BC_ListBox::drag_motion_event())
1205         {
1206                 return 1;
1207         }
1208         return 0;
1209 }
1210
1211 int BatchRenderList::drag_stop_event()
1212 {
1213         if(dragging_item)
1214         {
1215                 int src = get_selection_number(0, 0);
1216                 int dst = get_highlighted_item();
1217                 if(src != dst)
1218                 {
1219                         thread->move_batch(src, dst);
1220                 }
1221                 BC_ListBox::drag_stop_event();
1222         }
1223         return 0;
1224 }
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238 BatchRenderStart::BatchRenderStart(BatchRenderThread *thread, 
1239         int x, 
1240         int y)
1241  : BC_GenericButton(x, 
1242         y, 
1243         _("Start"))
1244 {
1245         this->thread = thread;
1246 }
1247
1248 int BatchRenderStart::handle_event()
1249 {
1250         thread->start_rendering();
1251         return 1;
1252 }
1253
1254 BatchRenderStop::BatchRenderStop(BatchRenderThread *thread, 
1255         int x, 
1256         int y)
1257  : BC_GenericButton(x, 
1258         y, 
1259         _("Stop"))
1260 {
1261         this->thread = thread;
1262 }
1263
1264 int BatchRenderStop::handle_event()
1265 {
1266         unlock_window();
1267         thread->stop_rendering();
1268         lock_window("BatchRenderStop::handle_event");
1269         return 1;
1270 }
1271
1272
1273 BatchRenderCancel::BatchRenderCancel(BatchRenderThread *thread, 
1274         int x, 
1275         int y)
1276  : BC_GenericButton(x, 
1277         y, 
1278         _("Close"))
1279 {
1280         this->thread = thread;
1281 }
1282
1283 int BatchRenderCancel::handle_event()
1284 {
1285         unlock_window();
1286         thread->stop_rendering();
1287         lock_window("BatchRenderCancel::handle_event");
1288         thread->gui->set_done(1);
1289         return 1;
1290 }
1291
1292 int BatchRenderCancel::keypress_event()
1293 {
1294         if(get_keypress() == ESC) 
1295         {
1296                 unlock_window();
1297                 thread->stop_rendering();
1298                 lock_window("BatchRenderCancel::keypress_event");
1299                 thread->gui->set_done(1);
1300                 return 1;
1301         }
1302         return 0;
1303 }
1304