2 #include "batchrender.h"
4 #include "confirmsave.h"
7 #include "edlsession.h"
9 #include "filesystem.h"
13 #include "mainsession.h"
15 #include "mwindowgui.h"
16 #include "packagedispatcher.h"
17 #include "packagerenderer.h"
18 #include "preferences.h"
21 #include "transportque.h"
28 static char *list_titles[] =
36 static int list_widths[] =
44 BatchRenderMenuItem::BatchRenderMenuItem(MWindow *mwindow)
45 : BC_MenuItem(_("Batch Render..."), "Shift-B", 'B')
48 this->mwindow = mwindow;
51 int BatchRenderMenuItem::handle_event()
53 mwindow->batch_render->start();
64 BatchRenderJob::BatchRenderJob(Preferences *preferences)
66 this->preferences = preferences;
74 BatchRenderJob::~BatchRenderJob()
79 void BatchRenderJob::copy_from(BatchRenderJob *src)
81 asset->copy_from(src->asset, 0);
82 strcpy(edl_path, src->edl_path);
83 strategy = src->strategy;
84 enabled = src->enabled;
88 void BatchRenderJob::load(FileXML *file)
93 file->tag.get_property("EDL_PATH", edl_path);
94 strategy = file->tag.get_property("STRATEGY", strategy);
95 enabled = file->tag.get_property("ENABLED", enabled);
96 elapsed = file->tag.get_property("ELAPSED", elapsed);
99 result = file->read_tag();
102 if(file->tag.title_is("ASSET"))
104 file->tag.get_property("SRC", asset->path);
105 asset->read(file, 0);
106 // The compression parameters are stored in the defaults to reduce
107 // coding maintenance. The defaults must now be stuffed into the XML for
110 defaults.load_string(file->read_text());
111 asset->load_defaults(&defaults,
122 void BatchRenderJob::save(FileXML *file)
124 TRACE("BatchRenderJob::save 1");
125 file->tag.set_property("EDL_PATH", edl_path);
126 TRACE("BatchRenderJob::save 1");
127 file->tag.set_property("STRATEGY", strategy);
128 TRACE("BatchRenderJob::save 1");
129 file->tag.set_property("ENABLED", enabled);
130 TRACE("BatchRenderJob::save 1");
131 file->tag.set_property("ELAPSED", elapsed);
132 TRACE("BatchRenderJob::save 1");
134 TRACE("BatchRenderJob::save 1");
135 file->append_newline();
136 TRACE("BatchRenderJob::save 1");
141 // The compression parameters are stored in the defaults to reduce
142 // coding maintenance. The defaults must now be stuffed into the XML for
145 asset->save_defaults(&defaults,
153 defaults.save_string(string);
154 file->append_text(string);
156 TRACE("BatchRenderJob::save 1");
157 file->tag.set_title("/JOB");
158 TRACE("BatchRenderJob::save 1");
160 TRACE("BatchRenderJob::save 1");
161 file->append_newline();
162 TRACE("BatchRenderJob::save 10");
165 void BatchRenderJob::fix_strategy()
167 strategy = Render::fix_strategy(strategy, preferences->use_renderfarm);
179 BatchRenderThread::BatchRenderThread(MWindow *mwindow)
182 this->mwindow = mwindow;
189 BatchRenderThread::BatchRenderThread()
199 void BatchRenderThread::handle_close_event(int result)
202 TRACE("BatchRenderThread::handle_close_event 1");
203 char path[BCTEXTLEN];
204 TRACE("BatchRenderThread::handle_close_event 1");
206 TRACE("BatchRenderThread::handle_close_event 1");
208 TRACE("BatchRenderThread::handle_close_event 1");
209 save_defaults(mwindow->defaults);
210 TRACE("BatchRenderThread::handle_close_event 1");
212 TRACE("BatchRenderThread::handle_close_event 1");
214 TRACE("BatchRenderThread::handle_close_event 1");
215 jobs.remove_all_objects();
216 TRACE("BatchRenderThread::handle_close_event 100");
219 BC_Window* BatchRenderThread::new_gui()
223 default_job = new BatchRenderJob(mwindow->preferences);
225 char path[BCTEXTLEN];
227 load_jobs(path, mwindow->preferences);
228 load_defaults(mwindow->defaults);
229 this->gui = new BatchRenderGUI(mwindow,
231 mwindow->session->batchrender_x,
232 mwindow->session->batchrender_y,
233 mwindow->session->batchrender_w,
234 mwindow->session->batchrender_h);
235 this->gui->create_objects();
240 void BatchRenderThread::load_jobs(char *path, Preferences *preferences)
245 jobs.remove_all_objects();
247 file.read_from_file(path);
249 file.read_from_file(create_path(path));
253 if(!(result = file.read_tag()))
255 if(file.tag.title_is("JOB"))
258 jobs.append(job = new BatchRenderJob(preferences));
265 void BatchRenderThread::save_jobs(char *path)
269 for(int i = 0; i < jobs.total; i++)
271 file.tag.set_title("JOB");
272 jobs.values[i]->save(&file);
276 file.write_to_file(path);
278 file.write_to_file(create_path(path));
281 void BatchRenderThread::load_defaults(Defaults *defaults)
285 default_job->asset->load_defaults(defaults,
292 default_job->fix_strategy();
295 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
297 char string[BCTEXTLEN];
298 sprintf(string, "BATCHRENDER_COLUMN%d", i);
299 column_width[i] = defaults->get(string, list_widths[i]);
303 void BatchRenderThread::save_defaults(Defaults *defaults)
307 default_job->asset->save_defaults(defaults,
314 defaults->update("BATCHRENDER_STRATEGY", default_job->strategy);
316 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
318 char string[BCTEXTLEN];
319 sprintf(string, "BATCHRENDER_COLUMN%d", i);
320 defaults->update(string, column_width[i]);
322 // defaults->update("BATCHRENDER_JOB", current_job);
324 mwindow->save_defaults();
329 char* BatchRenderThread::create_path(char *string)
332 sprintf(string, "%s", BCASTDIR);
333 fs.complete_path(string);
334 strcat(string, BATCH_PATH);
338 void BatchRenderThread::new_job()
340 BatchRenderJob *result = new BatchRenderJob(mwindow->preferences);
341 result->copy_from(get_current_job());
343 current_job = jobs.total - 1;
348 void BatchRenderThread::delete_job()
350 if(current_job < jobs.total && current_job >= 0)
352 jobs.remove_object_number(current_job);
353 if(current_job > 0) current_job--;
359 BatchRenderJob* BatchRenderThread::get_current_job()
361 BatchRenderJob *result;
362 if(current_job >= jobs.total || current_job < 0)
364 result = default_job;
368 result = jobs.values[current_job];
374 Asset* BatchRenderThread::get_current_asset()
376 return get_current_job()->asset;
379 char* BatchRenderThread::get_current_edl()
381 return get_current_job()->edl_path;
385 // Test EDL files for existence
386 int BatchRenderThread::test_edl_files()
388 for(int i = 0; i < jobs.total; i++)
390 if(jobs.values[i]->enabled)
392 FILE *fd = fopen(jobs.values[i]->edl_path, "r");
395 char string[BCTEXTLEN];
396 sprintf(string, _("EDL %s not found.\n"), jobs.values[i]->edl_path);
399 ErrorBox error_box(PROGRAM_NAME ": Error",
400 mwindow->gui->get_abs_cursor_x(1),
401 mwindow->gui->get_abs_cursor_y(1));
402 error_box.create_objects(string);
403 error_box.run_window();
404 gui->new_batch->enable();
405 gui->delete_batch->enable();
426 void BatchRenderThread::calculate_dest_paths(ArrayList<char*> *paths,
427 Preferences *preferences,
428 ArrayList<PluginServer*> *plugindb)
430 for(int i = 0; i < jobs.total; i++)
432 BatchRenderJob *job = jobs.values[i];
435 PackageDispatcher *packages = new PackageDispatcher;
438 TransportCommand *command = new TransportCommand;
439 FileXML *file = new FileXML;
440 file->read_from_file(job->edl_path);
442 // Use command to calculate range.
443 command->command = NORMAL_FWD;
444 command->get_edl()->load_xml(plugindb,
447 command->change_type = CHANGE_ALL;
448 command->set_playback_range();
449 command->adjust_playback_range();
451 // Create test packages
452 packages->create_packages(mwindow,
457 command->start_position,
458 command->end_position,
461 // Append output paths allocated to total
462 for(int j = 0; j < packages->get_total_packages(); j++)
464 RenderPackage *package = packages->get_package(j);
465 paths->append(strdup(package->path));
468 // Delete package harness
477 void BatchRenderThread::start_rendering(char *config_path,
480 Defaults *boot_defaults;
481 Preferences *preferences;
483 ArrayList<PluginServer*> *plugindb;
485 // Initialize stuff which MWindow does.
486 MWindow::init_defaults(boot_defaults, config_path);
487 load_defaults(boot_defaults);
488 preferences = new Preferences;
489 preferences->load_defaults(boot_defaults);
490 MWindow::init_plugins(preferences, plugindb, 0);
492 load_jobs(batch_path, preferences);
493 save_jobs(batch_path);
494 save_defaults(boot_defaults);
496 // Test EDL files for existence
497 if(test_edl_files()) return;
500 // Predict all destination paths
501 ArrayList<char*> paths;
502 calculate_dest_paths(&paths,
506 int result = ConfirmSave::test_files(0, &paths);
507 // Abort on any existing file because it's so hard to set this up.
510 render = new Render(0);
511 render->start_batches(&jobs,
517 void BatchRenderThread::start_rendering()
519 if(is_rendering) return;
522 char path[BCTEXTLEN];
525 save_defaults(mwindow->defaults);
526 gui->new_batch->disable();
527 gui->delete_batch->disable();
529 // Test EDL files for existence
530 if(test_edl_files()) return;
532 // Predict all destination paths
533 ArrayList<char*> paths;
534 calculate_dest_paths(&paths,
535 mwindow->preferences,
538 // Test destination files for overwrite
539 int result = ConfirmSave::test_files(mwindow, &paths);
540 paths.remove_all_objects();
546 gui->new_batch->enable();
547 gui->delete_batch->enable();
551 mwindow->render->start_batches(&jobs);
554 void BatchRenderThread::stop_rendering()
556 if(!is_rendering) return;
557 mwindow->render->stop_operation();
561 void BatchRenderThread::update_active(int number)
563 gui->lock_window("BatchRenderThread::update_active");
566 current_job = number;
567 rendering_job = number;
575 gui->unlock_window();
578 void BatchRenderThread::update_done(int number,
582 gui->lock_window("BatchRenderThread::update_done");
585 gui->new_batch->enable();
586 gui->delete_batch->enable();
590 jobs.values[number]->enabled = 0;
591 jobs.values[number]->elapsed = elapsed_time;
592 if(create_list) gui->create_list(1);
594 gui->unlock_window();
597 void BatchRenderThread::move_batch(int src, int dst)
599 BatchRenderJob *src_job = jobs.values[src];
600 if(dst < 0) dst = jobs.total - 1;
604 for(int i = src; i < jobs.total - 1; i++)
605 jobs.values[i] = jobs.values[i + 1];
606 // if(dst > src) dst--;
607 for(int i = jobs.total - 1; i > dst; i--)
608 jobs.values[i] = jobs.values[i - 1];
609 jobs.values[dst] = src_job;
622 BatchRenderGUI::BatchRenderGUI(MWindow *mwindow,
623 BatchRenderThread *thread,
628 : BC_Window(PROGRAM_NAME ": Batch Render",
639 this->mwindow = mwindow;
640 this->thread = thread;
643 BatchRenderGUI::~BatchRenderGUI()
649 void BatchRenderGUI::create_objects()
651 mwindow->theme->get_batchrender_sizes(this, get_w(), get_h());
654 int x = mwindow->theme->batchrender_x1;
656 int x1 = mwindow->theme->batchrender_x1;
657 int x2 = mwindow->theme->batchrender_x2;
658 int x3 = mwindow->theme->batchrender_x3;
663 add_subwindow(output_path_title = new BC_Title(x1, y, _("Output path:")));
665 format_tools = new BatchFormat(mwindow,
667 thread->get_current_asset());
668 format_tools->create_objects(x,
678 &thread->get_current_job()->strategy,
683 x += format_tools->get_w();
690 add_subwindow(edl_path_title = new BC_Title(x, y, _("EDL Path:")));
692 add_subwindow(edl_path_text = new BatchRenderEDLPath(
697 thread->get_current_edl()));
699 x += edl_path_text->get_w();
700 add_subwindow(edl_path_browse = new BrowseButton(
706 thread->get_current_edl(),
708 _("Select an EDL to load:"),
714 add_subwindow(new_batch = new BatchRenderNew(thread,
717 x += new_batch->get_w() + 10;
719 add_subwindow(delete_batch = new BatchRenderDelete(thread,
722 x += delete_batch->get_w() + 10;
726 add_subwindow(list_title = new BC_Title(x, y, _("Batches to render:")));
728 add_subwindow(batch_list = new BatchRenderList(thread,
732 get_h() - y - BC_GenericButton::calculate_h() - 15));
734 y += batch_list->get_h() + 10;
735 add_subwindow(start_button = new BatchRenderStart(thread,
739 BC_GenericButton::calculate_w(this, _("Stop")) / 2;
740 add_subwindow(stop_button = new BatchRenderStop(thread,
744 BC_GenericButton::calculate_w(this, _("Cancel")) -
746 add_subwindow(cancel_button = new BatchRenderCancel(thread,
753 int BatchRenderGUI::resize_event(int w, int h)
755 mwindow->session->batchrender_w = w;
756 mwindow->session->batchrender_h = h;
757 mwindow->theme->get_batchrender_sizes(this, w, h);
759 int x = mwindow->theme->batchrender_x1;
761 int x1 = mwindow->theme->batchrender_x1;
762 int x2 = mwindow->theme->batchrender_x2;
763 int x3 = mwindow->theme->batchrender_x3;
767 output_path_title->reposition_window(x1, y);
769 format_tools->reposition_window(x, y);
773 x += format_tools->get_w();
778 edl_path_title->reposition_window(x, y);
780 edl_path_text->reposition_window(x, y, w - x - 40);
781 x += edl_path_text->get_w();
782 edl_path_browse->reposition_window(x, y);
786 // status_title->reposition_window(x, y);
788 // status_text->reposition_window(x, y);
791 // progress_bar->reposition_window(x, y, w - x - 10);
794 new_batch->reposition_window(x, y);
795 x += new_batch->get_w() + 10;
796 delete_batch->reposition_window(x, y);
797 x += delete_batch->get_w() + 10;
801 int y_margin = get_h() - batch_list->get_h();
802 list_title->reposition_window(x, y);
804 batch_list->reposition_window(x, y, w - x - 10, h - y_margin);
806 y += batch_list->get_h() + 10;
807 start_button->reposition_window(x, y);
809 stop_button->get_w() / 2;
810 stop_button->reposition_window(x, y);
812 cancel_button->get_w() -
814 cancel_button->reposition_window(x, y);
818 int BatchRenderGUI::translation_event()
820 mwindow->session->batchrender_x = get_x();
821 mwindow->session->batchrender_y = get_y();
825 int BatchRenderGUI::close_event()
827 // Stop batch rendering
829 thread->stop_rendering();
830 lock_window("BatchRenderGUI::close_event");
835 void BatchRenderGUI::create_list(int update_widget)
837 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
839 list_columns[i].remove_all_objects();
842 for(int i = 0; i < thread->jobs.total; i++)
844 BatchRenderJob *job = thread->jobs.values[i];
845 char string[BCTEXTLEN];
846 BC_ListBoxItem *enabled = new BC_ListBoxItem(job->enabled ?
849 BC_ListBoxItem *item1 = new BC_ListBoxItem(job->asset->path);
850 BC_ListBoxItem *item2 = new BC_ListBoxItem(job->edl_path);
851 BC_ListBoxItem *item3;
853 item3 = new BC_ListBoxItem(
854 Units::totext(string,
858 item3 = new BC_ListBoxItem(_("Unknown"));
859 list_columns[0].append(enabled);
860 list_columns[1].append(item1);
861 list_columns[2].append(item2);
862 list_columns[3].append(item3);
863 if(i == thread->current_job)
865 enabled->set_selected(1);
866 item1->set_selected(1);
867 item2->set_selected(1);
868 item3->set_selected(1);
870 if(i == thread->rendering_job)
872 enabled->set_color(RED);
873 item1->set_color(RED);
874 item2->set_color(RED);
875 item3->set_color(RED);
881 batch_list->update(list_columns,
883 thread->column_width,
885 batch_list->get_xposition(),
886 batch_list->get_yposition(),
887 batch_list->get_highlighted_item(), // Flat index of item cursor is over
888 1, // set all autoplace flags to 1
893 void BatchRenderGUI::change_job()
895 BatchRenderJob *job = thread->get_current_job();
896 format_tools->update(job->asset, &job->strategy);
897 edl_path_text->update(job->edl_path);
907 BatchFormat::BatchFormat(MWindow *mwindow,
910 : FormatTools(mwindow, gui, asset)
913 this->mwindow = mwindow;
916 BatchFormat::~BatchFormat()
921 int BatchFormat::handle_event()
937 BatchRenderEDLPath::BatchRenderEDLPath(BatchRenderThread *thread,
948 this->thread = thread;
952 int BatchRenderEDLPath::handle_event()
954 strcpy(thread->get_current_edl(), get_text());
955 thread->gui->create_list(1);
964 BatchRenderNew::BatchRenderNew(BatchRenderThread *thread,
967 : BC_GenericButton(x, y, _("New"))
969 this->thread = thread;
972 int BatchRenderNew::handle_event()
978 BatchRenderDelete::BatchRenderDelete(BatchRenderThread *thread,
981 : BC_GenericButton(x, y, _("Delete"))
983 this->thread = thread;
986 int BatchRenderDelete::handle_event()
988 thread->delete_job();
997 BatchRenderList::BatchRenderList(BatchRenderThread *thread,
1007 thread->gui->list_columns,
1009 thread->column_width,
1010 BATCHRENDER_COLUMNS,
1017 this->thread = thread;
1019 set_process_drag(0);
1022 int BatchRenderList::handle_event()
1027 int BatchRenderList::selection_changed()
1029 thread->current_job = get_selection_number(0, 0);
1030 thread->gui->change_job();
1031 if(get_cursor_x() < thread->column_width[0])
1033 BatchRenderJob *job = thread->get_current_job();
1034 job->enabled = !job->enabled;
1035 thread->gui->create_list(1);
1040 int BatchRenderList::column_resize_event()
1042 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
1044 thread->column_width[i] = get_column_width(i);
1049 int BatchRenderList::drag_start_event()
1051 if(BC_ListBox::drag_start_event())
1060 int BatchRenderList::drag_motion_event()
1062 if(BC_ListBox::drag_motion_event())
1069 int BatchRenderList::drag_stop_event()
1073 int src = get_selection_number(0, 0);
1074 int dst = get_highlighted_item();
1077 thread->move_batch(src, dst);
1079 BC_ListBox::drag_stop_event();
1095 BatchRenderStart::BatchRenderStart(BatchRenderThread *thread,
1098 : BC_GenericButton(x,
1102 this->thread = thread;
1105 int BatchRenderStart::handle_event()
1107 thread->start_rendering();
1111 BatchRenderStop::BatchRenderStop(BatchRenderThread *thread,
1114 : BC_GenericButton(x,
1118 this->thread = thread;
1121 int BatchRenderStop::handle_event()
1124 thread->stop_rendering();
1125 lock_window("BatchRenderStop::handle_event");
1130 BatchRenderCancel::BatchRenderCancel(BatchRenderThread *thread,
1133 : BC_GenericButton(x,
1137 this->thread = thread;
1140 int BatchRenderCancel::handle_event()
1143 thread->stop_rendering();
1144 lock_window("BatchRenderCancel::handle_event");
1145 thread->gui->set_done(1);
1149 int BatchRenderCancel::keypress_event()
1151 if(get_keypress() == ESC)
1154 thread->stop_rendering();
1155 lock_window("BatchRenderCancel::keypress_event");
1156 thread->gui->set_done(1);