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;
75 BatchRenderJob::~BatchRenderJob()
77 Garbage::delete_object(asset);
80 void BatchRenderJob::copy_from(BatchRenderJob *src)
82 asset->copy_from(src->asset, 0);
83 strcpy(edl_path, src->edl_path);
84 strategy = src->strategy;
85 enabled = src->enabled;
89 void BatchRenderJob::load(FileXML *file)
94 file->tag.get_property("EDL_PATH", edl_path);
95 strategy = file->tag.get_property("STRATEGY", strategy);
96 enabled = file->tag.get_property("ENABLED", enabled);
97 elapsed = file->tag.get_property("ELAPSED", elapsed);
100 result = file->read_tag();
103 if(file->tag.title_is("ASSET"))
105 file->tag.get_property("SRC", asset->path);
106 asset->read(file, 0);
107 // The compression parameters are stored in the defaults to reduce
108 // coding maintenance. The defaults must now be stuffed into the XML for
111 defaults.load_string(file->read_text());
112 asset->load_defaults(&defaults,
123 void BatchRenderJob::save(FileXML *file)
125 TRACE("BatchRenderJob::save 1");
126 file->tag.set_property("EDL_PATH", edl_path);
127 TRACE("BatchRenderJob::save 1");
128 file->tag.set_property("STRATEGY", strategy);
129 TRACE("BatchRenderJob::save 1");
130 file->tag.set_property("ENABLED", enabled);
131 TRACE("BatchRenderJob::save 1");
132 file->tag.set_property("ELAPSED", elapsed);
133 TRACE("BatchRenderJob::save 1");
135 TRACE("BatchRenderJob::save 1");
136 file->append_newline();
137 TRACE("BatchRenderJob::save 1");
142 // The compression parameters are stored in the defaults to reduce
143 // coding maintenance. The defaults must now be stuffed into the XML for
146 asset->save_defaults(&defaults,
154 defaults.save_string(string);
155 file->append_text(string);
157 TRACE("BatchRenderJob::save 1");
158 file->tag.set_title("/JOB");
159 TRACE("BatchRenderJob::save 1");
161 TRACE("BatchRenderJob::save 1");
162 file->append_newline();
163 TRACE("BatchRenderJob::save 10");
166 void BatchRenderJob::fix_strategy()
168 strategy = Render::fix_strategy(strategy, preferences->use_renderfarm);
180 BatchRenderThread::BatchRenderThread(MWindow *mwindow)
183 this->mwindow = mwindow;
190 BatchRenderThread::BatchRenderThread()
200 void BatchRenderThread::handle_close_event(int result)
203 TRACE("BatchRenderThread::handle_close_event 1");
204 char path[BCTEXTLEN];
205 TRACE("BatchRenderThread::handle_close_event 1");
207 TRACE("BatchRenderThread::handle_close_event 1");
209 TRACE("BatchRenderThread::handle_close_event 1");
210 save_defaults(mwindow->defaults);
211 TRACE("BatchRenderThread::handle_close_event 1");
213 TRACE("BatchRenderThread::handle_close_event 1");
215 TRACE("BatchRenderThread::handle_close_event 1");
216 jobs.remove_all_objects();
217 TRACE("BatchRenderThread::handle_close_event 100");
220 BC_Window* BatchRenderThread::new_gui()
224 default_job = new BatchRenderJob(mwindow->preferences);
226 char path[BCTEXTLEN];
228 load_jobs(path, mwindow->preferences);
229 load_defaults(mwindow->defaults);
230 this->gui = new BatchRenderGUI(mwindow,
232 mwindow->session->batchrender_x,
233 mwindow->session->batchrender_y,
234 mwindow->session->batchrender_w,
235 mwindow->session->batchrender_h);
236 this->gui->create_objects();
241 void BatchRenderThread::load_jobs(char *path, Preferences *preferences)
246 jobs.remove_all_objects();
248 file.read_from_file(path);
250 file.read_from_file(create_path(path));
254 if(!(result = file.read_tag()))
256 if(file.tag.title_is("JOB"))
259 jobs.append(job = new BatchRenderJob(preferences));
266 void BatchRenderThread::save_jobs(char *path)
270 for(int i = 0; i < jobs.total; i++)
272 file.tag.set_title("JOB");
273 jobs.values[i]->save(&file);
277 file.write_to_file(path);
279 file.write_to_file(create_path(path));
282 void BatchRenderThread::load_defaults(BC_Hash *defaults)
286 default_job->asset->load_defaults(defaults,
293 default_job->fix_strategy();
296 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
298 char string[BCTEXTLEN];
299 sprintf(string, "BATCHRENDER_COLUMN%d", i);
300 column_width[i] = defaults->get(string, list_widths[i]);
304 void BatchRenderThread::save_defaults(BC_Hash *defaults)
308 default_job->asset->save_defaults(defaults,
315 defaults->update("BATCHRENDER_STRATEGY", default_job->strategy);
317 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
319 char string[BCTEXTLEN];
320 sprintf(string, "BATCHRENDER_COLUMN%d", i);
321 defaults->update(string, column_width[i]);
323 // defaults->update("BATCHRENDER_JOB", current_job);
325 mwindow->save_defaults();
330 char* BatchRenderThread::create_path(char *string)
333 sprintf(string, "%s", BCASTDIR);
334 fs.complete_path(string);
335 strcat(string, BATCH_PATH);
339 void BatchRenderThread::new_job()
341 BatchRenderJob *result = new BatchRenderJob(mwindow->preferences);
342 result->copy_from(get_current_job());
344 current_job = jobs.total - 1;
349 void BatchRenderThread::delete_job()
351 if(current_job < jobs.total && current_job >= 0)
353 jobs.remove_object_number(current_job);
354 if(current_job > 0) current_job--;
360 BatchRenderJob* BatchRenderThread::get_current_job()
362 BatchRenderJob *result;
363 if(current_job >= jobs.total || current_job < 0)
365 result = default_job;
369 result = jobs.values[current_job];
375 Asset* BatchRenderThread::get_current_asset()
377 return get_current_job()->asset;
380 char* BatchRenderThread::get_current_edl()
382 return get_current_job()->edl_path;
386 // Test EDL files for existence
387 int BatchRenderThread::test_edl_files()
389 for(int i = 0; i < jobs.total; i++)
391 if(jobs.values[i]->enabled)
393 FILE *fd = fopen(jobs.values[i]->edl_path, "r");
396 char string[BCTEXTLEN];
397 sprintf(string, _("EDL %s not found.\n"), jobs.values[i]->edl_path);
400 ErrorBox error_box(PROGRAM_NAME ": Error",
401 mwindow->gui->get_abs_cursor_x(1),
402 mwindow->gui->get_abs_cursor_y(1));
403 error_box.create_objects(string);
404 error_box.run_window();
405 gui->new_batch->enable();
406 gui->delete_batch->enable();
427 void BatchRenderThread::calculate_dest_paths(ArrayList<char*> *paths,
428 Preferences *preferences,
429 ArrayList<PluginServer*> *plugindb)
431 for(int i = 0; i < jobs.total; i++)
433 BatchRenderJob *job = jobs.values[i];
436 PackageDispatcher *packages = new PackageDispatcher;
439 TransportCommand *command = new TransportCommand;
440 FileXML *file = new FileXML;
441 file->read_from_file(job->edl_path);
443 // Use command to calculate range.
444 command->command = NORMAL_FWD;
445 command->get_edl()->load_xml(plugindb,
448 command->change_type = CHANGE_ALL;
449 command->set_playback_range();
450 command->playback_range_adjust_inout();
452 // Create test packages
453 packages->create_packages(mwindow,
458 command->start_position,
459 command->end_position,
462 // Append output paths allocated to total
463 packages->get_package_paths(paths);
465 // Delete package harness
474 void BatchRenderThread::start_rendering(char *config_path,
477 BC_Hash *boot_defaults;
478 Preferences *preferences;
480 ArrayList<PluginServer*> *plugindb;
482 // Initialize stuff which MWindow does.
483 MWindow::init_defaults(boot_defaults, config_path);
484 load_defaults(boot_defaults);
485 preferences = new Preferences;
486 preferences->load_defaults(boot_defaults);
487 MWindow::init_plugins(preferences, plugindb, 0);
489 load_jobs(batch_path, preferences);
490 save_jobs(batch_path);
491 save_defaults(boot_defaults);
493 // Test EDL files for existence
494 if(test_edl_files()) return;
497 // Predict all destination paths
498 ArrayList<char*> paths;
499 calculate_dest_paths(&paths,
503 int result = ConfirmSave::test_files(0, &paths);
504 paths.remove_all_objects();
506 // Abort on any existing file because it's so hard to set this up.
509 render = new Render(0);
510 render->start_batches(&jobs,
516 void BatchRenderThread::start_rendering()
518 if(is_rendering) return;
521 char path[BCTEXTLEN];
524 save_defaults(mwindow->defaults);
525 gui->new_batch->disable();
526 gui->delete_batch->disable();
528 // Test EDL files for existence
529 if(test_edl_files()) return;
531 // Predict all destination paths
532 ArrayList<char*> paths;
533 calculate_dest_paths(&paths,
534 mwindow->preferences,
537 // Test destination files for overwrite
538 int result = ConfirmSave::test_files(mwindow, &paths);
539 paths.remove_all_objects();
545 gui->new_batch->enable();
546 gui->delete_batch->enable();
550 mwindow->render->start_batches(&jobs);
553 void BatchRenderThread::stop_rendering()
555 if(!is_rendering) return;
556 mwindow->render->stop_operation();
560 void BatchRenderThread::update_active(int number)
562 gui->lock_window("BatchRenderThread::update_active");
565 current_job = number;
566 rendering_job = number;
574 gui->unlock_window();
577 void BatchRenderThread::update_done(int number,
581 gui->lock_window("BatchRenderThread::update_done");
584 gui->new_batch->enable();
585 gui->delete_batch->enable();
589 jobs.values[number]->enabled = 0;
590 jobs.values[number]->elapsed = elapsed_time;
591 if(create_list) gui->create_list(1);
593 gui->unlock_window();
596 void BatchRenderThread::move_batch(int src, int dst)
598 BatchRenderJob *src_job = jobs.values[src];
599 if(dst < 0) dst = jobs.total - 1;
603 for(int i = src; i < jobs.total - 1; i++)
604 jobs.values[i] = jobs.values[i + 1];
605 // if(dst > src) dst--;
606 for(int i = jobs.total - 1; i > dst; i--)
607 jobs.values[i] = jobs.values[i - 1];
608 jobs.values[dst] = src_job;
621 BatchRenderGUI::BatchRenderGUI(MWindow *mwindow,
622 BatchRenderThread *thread,
627 : BC_Window(PROGRAM_NAME ": Batch Render",
638 this->mwindow = mwindow;
639 this->thread = thread;
642 BatchRenderGUI::~BatchRenderGUI()
648 void BatchRenderGUI::create_objects()
650 mwindow->theme->get_batchrender_sizes(this, get_w(), get_h());
653 int x = mwindow->theme->batchrender_x1;
655 int x1 = mwindow->theme->batchrender_x1;
656 int x2 = mwindow->theme->batchrender_x2;
657 int x3 = mwindow->theme->batchrender_x3;
662 add_subwindow(output_path_title = new BC_Title(x1, y, _("Output path:")));
664 format_tools = new BatchFormat(mwindow,
666 thread->get_current_asset());
667 format_tools->create_objects(x,
677 &thread->get_current_job()->strategy,
682 x += format_tools->get_w();
689 add_subwindow(edl_path_title = new BC_Title(x, y, _("EDL Path:")));
691 add_subwindow(edl_path_text = new BatchRenderEDLPath(
696 thread->get_current_edl()));
698 x += edl_path_text->get_w();
699 add_subwindow(edl_path_browse = new BrowseButton(
705 thread->get_current_edl(),
707 _("Select an EDL to load:"),
713 add_subwindow(new_batch = new BatchRenderNew(thread,
716 x += new_batch->get_w() + 10;
718 add_subwindow(delete_batch = new BatchRenderDelete(thread,
721 x += delete_batch->get_w() + 10;
723 add_subwindow(savelist_batch = new BatchRenderSaveList(thread,
726 x += savelist_batch->get_w() + 10;
728 add_subwindow(loadlist_batch = new BatchRenderLoadList(thread,
731 x += loadlist_batch->get_w() + 10;
736 add_subwindow(list_title = new BC_Title(x, y, _("Batches to render:")));
738 add_subwindow(batch_list = new BatchRenderList(thread,
742 get_h() - y - BC_GenericButton::calculate_h() - 15));
744 y += batch_list->get_h() + 10;
745 add_subwindow(start_button = new BatchRenderStart(thread,
749 BC_GenericButton::calculate_w(this, _("Stop")) / 2;
750 add_subwindow(stop_button = new BatchRenderStop(thread,
754 BC_GenericButton::calculate_w(this, _("Close")) -
756 add_subwindow(cancel_button = new BatchRenderCancel(thread,
763 int BatchRenderGUI::resize_event(int w, int h)
765 mwindow->session->batchrender_w = w;
766 mwindow->session->batchrender_h = h;
767 mwindow->theme->get_batchrender_sizes(this, w, h);
769 int x = mwindow->theme->batchrender_x1;
771 int x1 = mwindow->theme->batchrender_x1;
772 int x2 = mwindow->theme->batchrender_x2;
773 int x3 = mwindow->theme->batchrender_x3;
777 output_path_title->reposition_window(x1, y);
779 format_tools->reposition_window(x, y);
783 x += format_tools->get_w();
788 edl_path_title->reposition_window(x, y);
790 edl_path_text->reposition_window(x, y, w - x - 40);
791 x += edl_path_text->get_w();
792 edl_path_browse->reposition_window(x, y);
796 // status_title->reposition_window(x, y);
798 // status_text->reposition_window(x, y);
801 // progress_bar->reposition_window(x, y, w - x - 10);
804 new_batch->reposition_window(x, y);
805 x += new_batch->get_w() + 10;
806 delete_batch->reposition_window(x, y);
807 x += delete_batch->get_w() + 10;
811 int y_margin = get_h() - batch_list->get_h();
812 list_title->reposition_window(x, y);
814 batch_list->reposition_window(x, y, w - x - 10, h - y_margin);
816 y += batch_list->get_h() + 10;
817 start_button->reposition_window(x, y);
819 stop_button->get_w() / 2;
820 stop_button->reposition_window(x, y);
822 cancel_button->get_w() -
824 cancel_button->reposition_window(x, y);
828 int BatchRenderGUI::translation_event()
830 mwindow->session->batchrender_x = get_x();
831 mwindow->session->batchrender_y = get_y();
835 int BatchRenderGUI::close_event()
837 // Stop batch rendering
839 thread->stop_rendering();
840 lock_window("BatchRenderGUI::close_event");
845 void BatchRenderGUI::create_list(int update_widget)
847 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
849 list_columns[i].remove_all_objects();
852 for(int i = 0; i < thread->jobs.total; i++)
854 BatchRenderJob *job = thread->jobs.values[i];
855 char string[BCTEXTLEN];
856 BC_ListBoxItem *enabled = new BC_ListBoxItem(job->enabled ?
859 BC_ListBoxItem *item1 = new BC_ListBoxItem(job->asset->path);
860 BC_ListBoxItem *item2 = new BC_ListBoxItem(job->edl_path);
861 BC_ListBoxItem *item3;
863 item3 = new BC_ListBoxItem(
864 Units::totext(string,
868 item3 = new BC_ListBoxItem(_("Unknown"));
869 list_columns[0].append(enabled);
870 list_columns[1].append(item1);
871 list_columns[2].append(item2);
872 list_columns[3].append(item3);
873 if(i == thread->current_job)
875 enabled->set_selected(1);
876 item1->set_selected(1);
877 item2->set_selected(1);
878 item3->set_selected(1);
880 if(i == thread->rendering_job)
882 enabled->set_color(RED);
883 item1->set_color(RED);
884 item2->set_color(RED);
885 item3->set_color(RED);
891 batch_list->update(list_columns,
893 thread->column_width,
895 batch_list->get_xposition(),
896 batch_list->get_yposition(),
897 batch_list->get_highlighted_item(), // Flat index of item cursor is over
898 1, // set all autoplace flags to 1
903 void BatchRenderGUI::change_job()
905 BatchRenderJob *job = thread->get_current_job();
906 format_tools->update(job->asset, &job->strategy);
907 edl_path_text->update(job->edl_path);
917 BatchFormat::BatchFormat(MWindow *mwindow,
920 : FormatTools(mwindow, gui, asset)
923 this->mwindow = mwindow;
926 BatchFormat::~BatchFormat()
931 int BatchFormat::handle_event()
947 BatchRenderEDLPath::BatchRenderEDLPath(BatchRenderThread *thread,
958 this->thread = thread;
962 int BatchRenderEDLPath::handle_event()
964 strcpy(thread->get_current_edl(), get_text());
965 thread->gui->create_list(1);
974 BatchRenderNew::BatchRenderNew(BatchRenderThread *thread,
977 : BC_GenericButton(x, y, _("New"))
979 this->thread = thread;
982 int BatchRenderNew::handle_event()
988 BatchRenderDelete::BatchRenderDelete(BatchRenderThread *thread,
991 : BC_GenericButton(x, y, _("Delete"))
993 this->thread = thread;
996 int BatchRenderDelete::handle_event()
998 thread->delete_job();
1004 BatchRenderSaveList::BatchRenderSaveList(BatchRenderThread *thread,
1007 : BC_GenericButton(x, y, _("Save List"))
1009 this->thread = thread;
1010 set_tooltip(_("Save a Batch Render List"));
1012 startup_lock = new Mutex("BatchRenderSaveList::startup_lock");
1015 BatchRenderSaveList::~BatchRenderSaveList()
1017 startup_lock->lock("BatchRenderSaveList::~BrowseButton");
1022 gui->unlock_window();
1024 startup_lock->unlock();
1026 delete startup_lock;
1029 int BatchRenderSaveList::handle_event()
1031 if(Thread::running())
1036 gui->raise_window();
1037 gui->unlock_window();
1041 startup_lock->lock("BatchRenderSaveList::handle_event 1");
1043 startup_lock->lock("BatchRenderSaveList::handle_event 2");
1044 startup_lock->unlock();
1048 void BatchRenderSaveList::run()
1050 char default_path[BCTEXTLEN];
1051 sprintf(default_path, "~");
1052 BC_FileBox filewindow(100,
1054 this->thread->mwindow->defaults->get("DEFAULT_BATCHLOADPATH", default_path),
1055 _("Save Batch Render List"),
1056 _("Enter a Batch Render filename to save as:"),
1064 startup_lock->unlock();
1065 filewindow.create_objects();
1067 int result2 = filewindow.run_window();
1071 this->thread->save_jobs(filewindow.get_submitted_path());
1072 this->thread->mwindow->defaults->update("DEFAULT_BATCHLOADPATH", filewindow.get_submitted_path());
1075 this->thread->gui->flush();
1076 startup_lock->lock("BatchRenderLoadList::run");
1078 startup_lock->unlock();
1081 int BatchRenderSaveList::keypress_event() {
1082 if (get_keypress() == 's' ||
1083 get_keypress() == 'S') return handle_event();
1090 BatchRenderLoadList::BatchRenderLoadList(BatchRenderThread *thread,
1093 : BC_GenericButton(x, y, _("Load List")),
1096 this->thread = thread;
1097 set_tooltip(_("Load a previously saved Batch Render List"));
1099 startup_lock = new Mutex("BatchRenderLoadList::startup_lock");
1102 BatchRenderLoadList::~BatchRenderLoadList()
1104 startup_lock->lock("BatchRenderLoadList::~BrowseButton");
1109 gui->unlock_window();
1111 startup_lock->unlock();
1113 delete startup_lock;
1116 int BatchRenderLoadList::handle_event()
1118 if(Thread::running())
1123 gui->raise_window();
1124 gui->unlock_window();
1128 startup_lock->lock("BatchRenderLoadList::handle_event 1");
1130 startup_lock->lock("BatchRenderLoadList::handle_event 2");
1131 startup_lock->unlock();
1135 void BatchRenderLoadList::run()
1137 char default_path[BCTEXTLEN];
1138 sprintf(default_path, "~");
1139 BC_FileBox filewindow(100,
1141 this->thread->mwindow->defaults->get("DEFAULT_BATCHLOADPATH", default_path),
1142 _("Load Batch Render List"),
1143 _("Enter a Batch Render filename to load from:"),
1151 startup_lock->unlock();
1152 filewindow.create_objects();
1154 int result2 = filewindow.run_window();
1158 this->thread->load_jobs(filewindow.get_submitted_path(),this->thread->mwindow->preferences);
1159 this->thread->gui->create_list(1);
1160 this->thread->mwindow->defaults->update("DEFAULT_BATCHLOADPATH", filewindow.get_submitted_path());
1163 this->thread->gui->flush();
1164 startup_lock->lock("BatchRenderLoadList::run");
1166 startup_lock->unlock();
1169 int BatchRenderLoadList::keypress_event() {
1170 if (get_keypress() == 'o' ||
1171 get_keypress() == 'O') return handle_event();
1175 BatchRenderList::BatchRenderList(BatchRenderThread *thread,
1185 thread->gui->list_columns,
1187 thread->column_width,
1188 BATCHRENDER_COLUMNS,
1195 this->thread = thread;
1197 set_process_drag(0);
1200 int BatchRenderList::handle_event()
1205 int BatchRenderList::selection_changed()
1207 thread->current_job = get_selection_number(0, 0);
1208 thread->gui->change_job();
1209 if(get_cursor_x() < thread->column_width[0])
1211 BatchRenderJob *job = thread->get_current_job();
1212 job->enabled = !job->enabled;
1213 thread->gui->create_list(1);
1218 int BatchRenderList::column_resize_event()
1220 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
1222 thread->column_width[i] = get_column_width(i);
1227 int BatchRenderList::drag_start_event()
1229 if(BC_ListBox::drag_start_event())
1238 int BatchRenderList::drag_motion_event()
1240 if(BC_ListBox::drag_motion_event())
1247 int BatchRenderList::drag_stop_event()
1251 int src = get_selection_number(0, 0);
1252 int dst = get_highlighted_item();
1255 thread->move_batch(src, dst);
1257 BC_ListBox::drag_stop_event();
1273 BatchRenderStart::BatchRenderStart(BatchRenderThread *thread,
1276 : BC_GenericButton(x,
1280 this->thread = thread;
1283 int BatchRenderStart::handle_event()
1285 thread->start_rendering();
1289 BatchRenderStop::BatchRenderStop(BatchRenderThread *thread,
1292 : BC_GenericButton(x,
1296 this->thread = thread;
1299 int BatchRenderStop::handle_event()
1302 thread->stop_rendering();
1303 lock_window("BatchRenderStop::handle_event");
1308 BatchRenderCancel::BatchRenderCancel(BatchRenderThread *thread,
1311 : BC_GenericButton(x,
1315 this->thread = thread;
1318 int BatchRenderCancel::handle_event()
1321 thread->stop_rendering();
1322 lock_window("BatchRenderCancel::handle_event");
1323 thread->gui->set_done(1);
1327 int BatchRenderCancel::keypress_event()
1329 if(get_keypress() == ESC)
1332 thread->stop_rendering();
1333 lock_window("BatchRenderCancel::keypress_event");
1334 thread->gui->set_done(1);