2 #include "batchrender.h"
4 #include "confirmsave.h"
7 #include "edlsession.h"
9 #include "filesystem.h"
13 #include "mainsession.h"
16 #include "mwindowgui.h"
17 #include "packagedispatcher.h"
18 #include "packagerenderer.h"
19 #include "preferences.h"
22 #include "transportque.h"
29 static char *list_titles[] =
37 static int list_widths[] =
45 BatchRenderMenuItem::BatchRenderMenuItem(MWindow *mwindow)
46 : BC_MenuItem(_("Batch Render..."), "Shift-B", 'B')
49 this->mwindow = mwindow;
52 int BatchRenderMenuItem::handle_event()
54 mwindow->batch_render->start();
65 BatchRenderJob::BatchRenderJob(Preferences *preferences)
67 this->preferences = preferences;
68 asset = Asset_GC(new Asset);
75 void BatchRenderJob::copy_from(BatchRenderJob *src)
77 asset->copy_from(*src->asset, 0);
78 strcpy(edl_path, src->edl_path);
79 strategy = src->strategy;
80 enabled = src->enabled;
84 void BatchRenderJob::load(FileXML *file)
89 file->tag.get_property("EDL_PATH", edl_path);
90 strategy = file->tag.get_property("STRATEGY", strategy);
91 enabled = file->tag.get_property("ENABLED", enabled);
92 elapsed = file->tag.get_property("ELAPSED", elapsed);
95 result = file->read_tag();
98 if(file->tag.title_is("ASSET"))
100 file->tag.get_property("SRC", asset->path);
101 asset->read(file, 0);
102 // The compression parameters are stored in the defaults to reduce
103 // coding maintenance. The defaults must now be stuffed into the XML for
106 defaults.load_string(file->read_text());
107 asset->load_defaults(&defaults,
118 void BatchRenderJob::save(FileXML *file)
120 TRACE("BatchRenderJob::save 1");
121 file->tag.set_property("EDL_PATH", edl_path);
122 TRACE("BatchRenderJob::save 1");
123 file->tag.set_property("STRATEGY", strategy);
124 TRACE("BatchRenderJob::save 1");
125 file->tag.set_property("ENABLED", enabled);
126 TRACE("BatchRenderJob::save 1");
127 file->tag.set_property("ELAPSED", elapsed);
128 TRACE("BatchRenderJob::save 1");
130 TRACE("BatchRenderJob::save 1");
131 file->append_newline();
132 TRACE("BatchRenderJob::save 1");
137 // The compression parameters are stored in the defaults to reduce
138 // coding maintenance. The defaults must now be stuffed into the XML for
141 asset->save_defaults(&defaults,
149 defaults.save_string(string);
150 file->append_text(string);
152 TRACE("BatchRenderJob::save 1");
153 file->tag.set_title("/JOB");
154 TRACE("BatchRenderJob::save 1");
156 TRACE("BatchRenderJob::save 1");
157 file->append_newline();
158 TRACE("BatchRenderJob::save 10");
161 void BatchRenderJob::fix_strategy()
163 strategy = Render::fix_strategy(strategy, preferences->use_renderfarm);
175 BatchRenderThread::BatchRenderThread(MWindow *mwindow)
178 this->mwindow = mwindow;
185 BatchRenderThread::BatchRenderThread()
195 void BatchRenderThread::handle_close_event(int result)
198 TRACE("BatchRenderThread::handle_close_event 1");
199 char path[BCTEXTLEN];
200 TRACE("BatchRenderThread::handle_close_event 1");
202 TRACE("BatchRenderThread::handle_close_event 1");
204 TRACE("BatchRenderThread::handle_close_event 1");
205 save_defaults(mwindow->defaults);
206 TRACE("BatchRenderThread::handle_close_event 1");
208 TRACE("BatchRenderThread::handle_close_event 1");
210 TRACE("BatchRenderThread::handle_close_event 1");
211 jobs.remove_all_objects();
212 TRACE("BatchRenderThread::handle_close_event 100");
215 BC_Window* BatchRenderThread::new_gui()
219 default_job = new BatchRenderJob(mwindow->preferences);
221 char path[BCTEXTLEN];
223 load_jobs(path, mwindow->preferences);
224 load_defaults(mwindow->defaults);
225 this->gui = new BatchRenderGUI(mwindow,
227 mwindow->session->batchrender_x,
228 mwindow->session->batchrender_y,
229 mwindow->session->batchrender_w,
230 mwindow->session->batchrender_h);
231 this->gui->create_objects();
236 void BatchRenderThread::load_jobs(char *path, Preferences *preferences)
241 jobs.remove_all_objects();
243 file.read_from_file(path);
245 file.read_from_file(create_path(path));
249 if(!(result = file.read_tag()))
251 if(file.tag.title_is("JOB"))
254 jobs.append(job = new BatchRenderJob(preferences));
261 void BatchRenderThread::save_jobs(char *path)
265 for(int i = 0; i < jobs.total; i++)
267 file.tag.set_title("JOB");
268 jobs.values[i]->save(&file);
272 file.write_to_file(path);
274 file.write_to_file(create_path(path));
277 void BatchRenderThread::load_defaults(BC_Hash *defaults)
281 default_job->asset->load_defaults(defaults,
288 default_job->fix_strategy();
291 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
293 char string[BCTEXTLEN];
294 sprintf(string, "BATCHRENDER_COLUMN%d", i);
295 column_width[i] = defaults->get(string, list_widths[i]);
299 void BatchRenderThread::save_defaults(BC_Hash *defaults)
303 default_job->asset->save_defaults(defaults,
310 defaults->update("BATCHRENDER_STRATEGY", default_job->strategy);
312 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
314 char string[BCTEXTLEN];
315 sprintf(string, "BATCHRENDER_COLUMN%d", i);
316 defaults->update(string, column_width[i]);
318 // defaults->update("BATCHRENDER_JOB", current_job);
320 mwindow->save_defaults();
325 char* BatchRenderThread::create_path(char *string)
328 sprintf(string, "%s", BCASTDIR);
329 fs.complete_path(string);
330 strcat(string, BATCH_PATH);
334 void BatchRenderThread::new_job()
336 BatchRenderJob *result = new BatchRenderJob(mwindow->preferences);
337 result->copy_from(get_current_job());
339 current_job = jobs.total - 1;
344 void BatchRenderThread::delete_job()
346 if(current_job < jobs.total && current_job >= 0)
348 jobs.remove_object_number(current_job);
349 if(current_job > 0) current_job--;
355 BatchRenderJob* BatchRenderThread::get_current_job()
357 BatchRenderJob *result;
358 if(current_job >= jobs.total || current_job < 0)
360 result = default_job;
364 result = jobs.values[current_job];
370 Asset_GC BatchRenderThread::get_current_asset()
372 return get_current_job()->asset;
375 char* BatchRenderThread::get_current_edl()
377 return get_current_job()->edl_path;
381 // Test EDL files for existence
382 int BatchRenderThread::test_edl_files()
384 for(int i = 0; i < jobs.total; i++)
386 if(jobs.values[i]->enabled)
388 FILE *fd = fopen(jobs.values[i]->edl_path, "r");
391 char string[BCTEXTLEN];
392 sprintf(string, _("EDL %s not found.\n"), jobs.values[i]->edl_path);
395 ErrorBox error_box(PROGRAM_NAME ": Error",
396 mwindow->gui->get_abs_cursor_x(1),
397 mwindow->gui->get_abs_cursor_y(1));
398 error_box.create_objects(string);
399 error_box.run_window();
400 gui->new_batch->enable();
401 gui->delete_batch->enable();
422 void BatchRenderThread::calculate_dest_paths(ArrayList<char*> *paths,
423 Preferences *preferences,
424 ArrayList<PluginServer*> *plugindb)
426 for(int i = 0; i < jobs.total; i++)
428 BatchRenderJob *job = jobs.values[i];
431 PackageDispatcher *packages = new PackageDispatcher;
434 TransportCommand *command = new TransportCommand;
435 FileXML *file = new FileXML;
436 file->read_from_file(job->edl_path);
438 // Use command to calculate range.
439 command->command = NORMAL_FWD;
440 command->get_edl()->load_xml(plugindb,
443 command->change_type = CHANGE_ALL;
444 command->set_playback_range();
445 command->playback_range_adjust_inout();
447 // Create test packages
448 packages->create_packages(mwindow,
453 command->start_position,
454 command->end_position,
457 // Append output paths allocated to total
458 packages->get_package_paths(paths);
460 // Delete package harness
469 void BatchRenderThread::start_rendering(char *config_path,
472 BC_Hash *boot_defaults;
473 Preferences *preferences;
475 ArrayList<PluginServer*> *plugindb;
477 // Initialize stuff which MWindow does.
478 MWindow::init_defaults(boot_defaults, config_path);
479 load_defaults(boot_defaults);
480 preferences = new Preferences;
481 preferences->load_defaults(boot_defaults);
482 MWindow::init_plugins(preferences, plugindb, 0);
484 load_jobs(batch_path, preferences);
485 save_jobs(batch_path);
486 save_defaults(boot_defaults);
488 // Test EDL files for existence
489 if(test_edl_files()) return;
492 // Predict all destination paths
493 ArrayList<char*> paths;
494 calculate_dest_paths(&paths,
498 int result = ConfirmSave::test_files(0, &paths);
499 paths.remove_all_objects();
501 // Abort on any existing file because it's so hard to set this up.
504 render = new Render(0);
505 render->start_batches(&jobs,
511 void BatchRenderThread::start_rendering()
513 if(is_rendering) return;
516 char path[BCTEXTLEN];
519 save_defaults(mwindow->defaults);
520 gui->new_batch->disable();
521 gui->delete_batch->disable();
523 // Test EDL files for existence
524 if(test_edl_files()) return;
526 // Predict all destination paths
527 ArrayList<char*> paths;
528 calculate_dest_paths(&paths,
529 mwindow->preferences,
532 // Test destination files for overwrite
533 int result = ConfirmSave::test_files(mwindow, &paths);
534 paths.remove_all_objects();
540 gui->new_batch->enable();
541 gui->delete_batch->enable();
545 mwindow->render->start_batches(&jobs);
548 void BatchRenderThread::stop_rendering()
550 if(!is_rendering) return;
551 mwindow->render->stop_operation();
555 void BatchRenderThread::update_active(int number)
557 gui->lock_window("BatchRenderThread::update_active");
560 current_job = number;
561 rendering_job = number;
569 gui->unlock_window();
572 void BatchRenderThread::update_done(int number,
576 gui->lock_window("BatchRenderThread::update_done");
579 gui->new_batch->enable();
580 gui->delete_batch->enable();
584 jobs.values[number]->enabled = 0;
585 jobs.values[number]->elapsed = elapsed_time;
586 if(create_list) gui->create_list(1);
588 gui->unlock_window();
591 void BatchRenderThread::move_batch(int src, int dst)
593 BatchRenderJob *src_job = jobs.values[src];
594 if(dst < 0) dst = jobs.total - 1;
598 for(int i = src; i < jobs.total - 1; i++)
599 jobs.values[i] = jobs.values[i + 1];
600 // if(dst > src) dst--;
601 for(int i = jobs.total - 1; i > dst; i--)
602 jobs.values[i] = jobs.values[i - 1];
603 jobs.values[dst] = src_job;
616 BatchRenderGUI::BatchRenderGUI(MWindow *mwindow,
617 BatchRenderThread *thread,
622 : BC_Window(PROGRAM_NAME ": Batch Render",
633 this->mwindow = mwindow;
634 this->thread = thread;
637 BatchRenderGUI::~BatchRenderGUI()
643 void BatchRenderGUI::create_objects()
645 mwindow->theme->get_batchrender_sizes(this, get_w(), get_h());
648 int x = mwindow->theme->batchrender_x1;
650 int x1 = mwindow->theme->batchrender_x1;
651 int x2 = mwindow->theme->batchrender_x2;
652 int x3 = mwindow->theme->batchrender_x3;
657 add_subwindow(output_path_title = new BC_Title(x1, y, _("Output path:")));
659 format_tools = new BatchFormat(mwindow,
661 thread->get_current_asset());
662 format_tools->create_objects(x,
672 &thread->get_current_job()->strategy,
677 x += format_tools->get_w();
684 add_subwindow(edl_path_title = new BC_Title(x, y, _("EDL Path:")));
686 add_subwindow(edl_path_text = new BatchRenderEDLPath(
691 thread->get_current_edl()));
693 x += edl_path_text->get_w();
694 add_subwindow(edl_path_browse = new BrowseButton(
700 thread->get_current_edl(),
702 _("Select an EDL to load:"),
708 add_subwindow(new_batch = new BatchRenderNew(thread,
711 x += new_batch->get_w() + 10;
713 add_subwindow(delete_batch = new BatchRenderDelete(thread,
716 x += delete_batch->get_w() + 10;
718 add_subwindow(savelist_batch = new BatchRenderSaveList(thread,
721 x += savelist_batch->get_w() + 10;
723 add_subwindow(loadlist_batch = new BatchRenderLoadList(thread,
726 x += loadlist_batch->get_w() + 10;
731 add_subwindow(list_title = new BC_Title(x, y, _("Batches to render:")));
733 add_subwindow(batch_list = new BatchRenderList(thread,
737 get_h() - y - BC_GenericButton::calculate_h() - 15));
739 y += batch_list->get_h() + 10;
740 add_subwindow(start_button = new BatchRenderStart(thread,
744 BC_GenericButton::calculate_w(this, _("Stop")) / 2;
745 add_subwindow(stop_button = new BatchRenderStop(thread,
749 BC_GenericButton::calculate_w(this, _("Close")) -
751 add_subwindow(cancel_button = new BatchRenderCancel(thread,
758 int BatchRenderGUI::resize_event(int w, int h)
760 mwindow->session->batchrender_w = w;
761 mwindow->session->batchrender_h = h;
762 mwindow->theme->get_batchrender_sizes(this, w, h);
764 int x = mwindow->theme->batchrender_x1;
766 int x1 = mwindow->theme->batchrender_x1;
767 int x2 = mwindow->theme->batchrender_x2;
768 int x3 = mwindow->theme->batchrender_x3;
772 output_path_title->reposition_window(x1, y);
774 format_tools->reposition_window(x, y);
778 x += format_tools->get_w();
783 edl_path_title->reposition_window(x, y);
785 edl_path_text->reposition_window(x, y, w - x - 40);
786 x += edl_path_text->get_w();
787 edl_path_browse->reposition_window(x, y);
791 // status_title->reposition_window(x, y);
793 // status_text->reposition_window(x, y);
796 // progress_bar->reposition_window(x, y, w - x - 10);
799 new_batch->reposition_window(x, y);
800 x += new_batch->get_w() + 10;
801 delete_batch->reposition_window(x, y);
802 x += delete_batch->get_w() + 10;
806 int y_margin = get_h() - batch_list->get_h();
807 list_title->reposition_window(x, y);
809 batch_list->reposition_window(x, y, w - x - 10, h - y_margin);
811 y += batch_list->get_h() + 10;
812 start_button->reposition_window(x, y);
814 stop_button->get_w() / 2;
815 stop_button->reposition_window(x, y);
817 cancel_button->get_w() -
819 cancel_button->reposition_window(x, y);
823 int BatchRenderGUI::translation_event()
825 mwindow->session->batchrender_x = get_x();
826 mwindow->session->batchrender_y = get_y();
830 int BatchRenderGUI::close_event()
832 // Stop batch rendering
834 thread->stop_rendering();
835 lock_window("BatchRenderGUI::close_event");
840 void BatchRenderGUI::create_list(int update_widget)
842 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
844 list_columns[i].remove_all_objects();
847 for(int i = 0; i < thread->jobs.total; i++)
849 BatchRenderJob *job = thread->jobs.values[i];
850 char string[BCTEXTLEN];
851 BC_ListBoxItem *enabled = new BC_ListBoxItem(job->enabled ?
854 BC_ListBoxItem *item1 = new BC_ListBoxItem(job->asset->path);
855 BC_ListBoxItem *item2 = new BC_ListBoxItem(job->edl_path);
856 BC_ListBoxItem *item3;
858 item3 = new BC_ListBoxItem(
859 Units::totext(string,
863 item3 = new BC_ListBoxItem(_("Unknown"));
864 list_columns[0].append(enabled);
865 list_columns[1].append(item1);
866 list_columns[2].append(item2);
867 list_columns[3].append(item3);
868 if(i == thread->current_job)
870 enabled->set_selected(1);
871 item1->set_selected(1);
872 item2->set_selected(1);
873 item3->set_selected(1);
875 if(i == thread->rendering_job)
877 enabled->set_color(RED);
878 item1->set_color(RED);
879 item2->set_color(RED);
880 item3->set_color(RED);
886 batch_list->update(list_columns,
888 thread->column_width,
890 batch_list->get_xposition(),
891 batch_list->get_yposition(),
892 batch_list->get_highlighted_item(), // Flat index of item cursor is over
893 1, // set all autoplace flags to 1
898 void BatchRenderGUI::change_job()
900 BatchRenderJob *job = thread->get_current_job();
901 format_tools->update(job->asset, &job->strategy);
902 edl_path_text->update(job->edl_path);
912 BatchFormat::BatchFormat(MWindow *mwindow,
915 : FormatTools(mwindow, gui, asset)
918 this->mwindow = mwindow;
921 BatchFormat::~BatchFormat()
926 int BatchFormat::handle_event()
942 BatchRenderEDLPath::BatchRenderEDLPath(BatchRenderThread *thread,
953 this->thread = thread;
957 int BatchRenderEDLPath::handle_event()
959 strcpy(thread->get_current_edl(), get_text());
960 thread->gui->create_list(1);
969 BatchRenderNew::BatchRenderNew(BatchRenderThread *thread,
972 : BC_GenericButton(x, y, _("New"))
974 this->thread = thread;
977 int BatchRenderNew::handle_event()
983 BatchRenderDelete::BatchRenderDelete(BatchRenderThread *thread,
986 : BC_GenericButton(x, y, _("Delete"))
988 this->thread = thread;
991 int BatchRenderDelete::handle_event()
993 thread->delete_job();
999 BatchRenderSaveList::BatchRenderSaveList(BatchRenderThread *thread,
1002 : BC_GenericButton(x, y, _("Save List"))
1004 this->thread = thread;
1005 set_tooltip(_("Save a Batch Render List"));
1007 startup_lock = new Mutex("BatchRenderSaveList::startup_lock");
1010 BatchRenderSaveList::~BatchRenderSaveList()
1012 startup_lock->lock("BatchRenderSaveList::~BrowseButton");
1017 gui->unlock_window();
1019 startup_lock->unlock();
1021 delete startup_lock;
1024 int BatchRenderSaveList::handle_event()
1026 if(Thread::running())
1031 gui->raise_window();
1032 gui->unlock_window();
1036 startup_lock->lock("BatchRenderSaveList::handle_event 1");
1038 startup_lock->lock("BatchRenderSaveList::handle_event 2");
1039 startup_lock->unlock();
1043 void BatchRenderSaveList::run()
1045 char default_path[BCTEXTLEN];
1046 sprintf(default_path, "~");
1047 BC_FileBox filewindow(100,
1049 this->thread->mwindow->defaults->get("DEFAULT_BATCHLOADPATH", default_path),
1050 _("Save Batch Render List"),
1051 _("Enter a Batch Render filename to save as:"),
1059 startup_lock->unlock();
1060 filewindow.create_objects();
1062 int result2 = filewindow.run_window();
1066 this->thread->save_jobs(filewindow.get_submitted_path());
1067 this->thread->mwindow->defaults->update("DEFAULT_BATCHLOADPATH", filewindow.get_submitted_path());
1070 this->thread->gui->flush();
1071 startup_lock->lock("BatchRenderLoadList::run");
1073 startup_lock->unlock();
1076 int BatchRenderSaveList::keypress_event() {
1077 if (get_keypress() == 's' ||
1078 get_keypress() == 'S') return handle_event();
1085 BatchRenderLoadList::BatchRenderLoadList(BatchRenderThread *thread,
1088 : BC_GenericButton(x, y, _("Load List")),
1091 this->thread = thread;
1092 set_tooltip(_("Load a previously saved Batch Render List"));
1094 startup_lock = new Mutex("BatchRenderLoadList::startup_lock");
1097 BatchRenderLoadList::~BatchRenderLoadList()
1099 startup_lock->lock("BatchRenderLoadList::~BrowseButton");
1104 gui->unlock_window();
1106 startup_lock->unlock();
1108 delete startup_lock;
1111 int BatchRenderLoadList::handle_event()
1113 if(Thread::running())
1118 gui->raise_window();
1119 gui->unlock_window();
1123 startup_lock->lock("BatchRenderLoadList::handle_event 1");
1125 startup_lock->lock("BatchRenderLoadList::handle_event 2");
1126 startup_lock->unlock();
1130 void BatchRenderLoadList::run()
1132 char default_path[BCTEXTLEN];
1133 sprintf(default_path, "~");
1134 BC_FileBox filewindow(100,
1136 this->thread->mwindow->defaults->get("DEFAULT_BATCHLOADPATH", default_path),
1137 _("Load Batch Render List"),
1138 _("Enter a Batch Render filename to load from:"),
1146 startup_lock->unlock();
1147 filewindow.create_objects();
1149 int result2 = filewindow.run_window();
1153 this->thread->load_jobs(filewindow.get_submitted_path(),this->thread->mwindow->preferences);
1154 this->thread->gui->create_list(1);
1155 this->thread->mwindow->defaults->update("DEFAULT_BATCHLOADPATH", filewindow.get_submitted_path());
1158 this->thread->gui->flush();
1159 startup_lock->lock("BatchRenderLoadList::run");
1161 startup_lock->unlock();
1164 int BatchRenderLoadList::keypress_event() {
1165 if (get_keypress() == 'o' ||
1166 get_keypress() == 'O') return handle_event();
1170 BatchRenderList::BatchRenderList(BatchRenderThread *thread,
1180 thread->gui->list_columns,
1182 thread->column_width,
1183 BATCHRENDER_COLUMNS,
1190 this->thread = thread;
1192 set_process_drag(0);
1195 int BatchRenderList::handle_event()
1200 int BatchRenderList::selection_changed()
1202 thread->current_job = get_selection_number(0, 0);
1203 thread->gui->change_job();
1204 if(get_cursor_x() < thread->column_width[0])
1206 BatchRenderJob *job = thread->get_current_job();
1207 job->enabled = !job->enabled;
1208 thread->gui->create_list(1);
1213 int BatchRenderList::column_resize_event()
1215 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
1217 thread->column_width[i] = get_column_width(i);
1222 int BatchRenderList::drag_start_event()
1224 if(BC_ListBox::drag_start_event())
1233 int BatchRenderList::drag_motion_event()
1235 if(BC_ListBox::drag_motion_event())
1242 int BatchRenderList::drag_stop_event()
1246 int src = get_selection_number(0, 0);
1247 int dst = get_highlighted_item();
1250 thread->move_batch(src, dst);
1252 BC_ListBox::drag_stop_event();
1268 BatchRenderStart::BatchRenderStart(BatchRenderThread *thread,
1271 : BC_GenericButton(x,
1275 this->thread = thread;
1278 int BatchRenderStart::handle_event()
1280 thread->start_rendering();
1284 BatchRenderStop::BatchRenderStop(BatchRenderThread *thread,
1287 : BC_GenericButton(x,
1291 this->thread = thread;
1294 int BatchRenderStop::handle_event()
1297 thread->stop_rendering();
1298 lock_window("BatchRenderStop::handle_event");
1303 BatchRenderCancel::BatchRenderCancel(BatchRenderThread *thread,
1306 : BC_GenericButton(x,
1310 this->thread = thread;
1313 int BatchRenderCancel::handle_event()
1316 thread->stop_rendering();
1317 lock_window("BatchRenderCancel::handle_event");
1318 thread->gui->set_done(1);
1322 int BatchRenderCancel::keypress_event()
1324 if(get_keypress() == ESC)
1327 thread->stop_rendering();
1328 lock_window("BatchRenderCancel::keypress_event");
1329 thread->gui->set_done(1);
1340 // c-file-style: "linux"