4 * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
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.
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.
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
23 #include "batchrender.h"
24 #include "bcdisplayinfo.h"
25 #include "bcsignals.h"
26 #include "confirmsave.h"
32 #include "edlsession.h"
34 #include "filesystem.h"
41 #include "mainerror.h"
43 #include "mainsession.h"
45 #include "mwindowgui.h"
46 #include "packagedispatcher.h"
47 #include "packagerenderer.h"
49 #include "pluginset.h"
50 #include "preferences.h"
54 #include "transportque.h"
61 #include <sys/statfs.h>
65 static const char *list_titles[] =
73 static int list_widths[] =
81 BatchRenderMenuItem::BatchRenderMenuItem(MWindow *mwindow)
82 : BC_MenuItem(_("Batch Render..."), _("Shift-B"), 'B')
85 this->mwindow = mwindow;
88 int BatchRenderMenuItem::handle_event()
90 mwindow->batch_render->start();
101 BatchRenderJob::BatchRenderJob(Preferences *preferences)
103 this->preferences = preferences;
111 BatchRenderJob::~BatchRenderJob()
113 asset->Garbage::remove_user();
116 void BatchRenderJob::copy_from(BatchRenderJob *src)
118 asset->copy_from(src->asset, 0);
119 strcpy(edl_path, src->edl_path);
120 strategy = src->strategy;
121 enabled = src->enabled;
125 void BatchRenderJob::load(FileXML *file)
130 file->tag.get_property("EDL_PATH", edl_path);
131 strategy = file->tag.get_property("STRATEGY", strategy);
132 enabled = file->tag.get_property("ENABLED", enabled);
133 elapsed = file->tag.get_property("ELAPSED", elapsed);
136 result = file->read_tag();
139 if(file->tag.title_is("ASSET"))
141 file->tag.get_property("SRC", asset->path);
142 asset->read(file, 0);
143 // The compression parameters are stored in the defaults to reduce
144 // coding maintenance. The defaults must now be stuffed into the XML for
147 defaults.load_string(file->read_text());
148 asset->load_defaults(&defaults,
159 void BatchRenderJob::save(FileXML *file)
161 file->tag.set_property("EDL_PATH", edl_path);
162 file->tag.set_property("STRATEGY", strategy);
163 file->tag.set_property("ENABLED", enabled);
164 file->tag.set_property("ELAPSED", elapsed);
166 file->append_newline();
171 // The compression parameters are stored in the defaults to reduce
172 // coding maintenance. The defaults must now be stuffed into the XML for
175 asset->save_defaults(&defaults,
183 defaults.save_string(string);
184 file->append_text(string);
186 file->tag.set_title("/JOB");
188 file->append_newline();
191 void BatchRenderJob::fix_strategy()
193 strategy = Render::fix_strategy(strategy, preferences->use_renderfarm);
205 BatchRenderThread::BatchRenderThread(MWindow *mwindow)
208 this->mwindow = mwindow;
216 BatchRenderThread::BatchRenderThread()
227 void BatchRenderThread::handle_close_event(int result)
230 char path[BCTEXTLEN];
233 save_defaults(mwindow->defaults);
236 jobs.remove_all_objects();
239 file_entries->remove_all_objects();
245 BC_Window* BatchRenderThread::new_gui()
249 default_job = new BatchRenderJob(mwindow->preferences);
254 file_entries = new ArrayList<BC_ListBoxItem*>;
256 char string[BCTEXTLEN];
257 // Load current directory
258 fs.update(getcwd(string, BCTEXTLEN));
259 for(int i = 0; i < fs.total_files(); i++)
261 file_entries->append(
263 fs.get_entry(i)->get_name()));
267 char path[BCTEXTLEN];
269 load_jobs(path, mwindow->preferences);
270 load_defaults(mwindow->defaults);
271 this->gui = new BatchRenderGUI(mwindow,
273 mwindow->session->batchrender_x,
274 mwindow->session->batchrender_y,
275 mwindow->session->batchrender_w,
276 mwindow->session->batchrender_h);
277 this->gui->create_objects();
282 void BatchRenderThread::load_jobs(char *path, Preferences *preferences)
287 jobs.remove_all_objects();
289 file.read_from_file(path);
291 file.read_from_file(create_path(path));
295 if(!(result = file.read_tag()))
297 if(file.tag.title_is("JOB"))
300 jobs.append(job = new BatchRenderJob(preferences));
307 void BatchRenderThread::save_jobs(char *path)
311 for(int i = 0; i < jobs.total; i++)
313 file.tag.set_title("JOB");
314 jobs.values[i]->save(&file);
318 file.write_to_file(path);
320 file.write_to_file(create_path(path));
323 void BatchRenderThread::load_defaults(BC_Hash *defaults)
327 default_job->asset->load_defaults(defaults,
334 default_job->fix_strategy();
337 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
339 char string[BCTEXTLEN];
340 sprintf(string, "BATCHRENDER_COLUMN%d", i);
341 column_width[i] = defaults->get(string, list_widths[i]);
345 void BatchRenderThread::save_defaults(BC_Hash *defaults)
349 default_job->asset->save_defaults(defaults,
356 defaults->update("BATCHRENDER_STRATEGY", default_job->strategy);
358 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
360 char string[BCTEXTLEN];
361 sprintf(string, "BATCHRENDER_COLUMN%d", i);
362 defaults->update(string, column_width[i]);
364 // defaults->update("BATCHRENDER_JOB", current_job);
366 mwindow->save_defaults();
371 char* BatchRenderThread::create_path(char *string)
374 sprintf(string, "%s", BCASTDIR);
375 fs.complete_path(string);
376 strcat(string, BATCH_PATH);
380 void BatchRenderThread::new_job()
382 BatchRenderJob *result = new BatchRenderJob(mwindow->preferences);
383 result->copy_from(get_current_job());
385 current_job = jobs.total - 1;
390 void BatchRenderThread::delete_job()
392 if(current_job < jobs.total && current_job >= 0)
394 jobs.remove_object_number(current_job);
395 if(current_job > 0) current_job--;
401 void BatchRenderThread::use_current_edl()
403 // printf("BatchRenderThread::use_current_edl %d %p %s\n",
405 // mwindow->edl->path,
406 // mwindow->edl->path);
408 strcpy(get_current_edl(), mwindow->edl->path);
410 gui->edl_path_text->update(get_current_edl());
413 void BatchRenderThread::update_selected_edl()
416 char *path = get_current_edl();
417 EDL *edl = mwindow->edl;
418 edl->save_xml(&xml_file, path, 0, 0);
419 xml_file.terminate_string();
420 if( xml_file.write_to_file(path) ) {
422 sprintf(msg, _("Unable to save: %s"), path);
423 MainError::show_error(msg);
427 BatchRenderJob* BatchRenderThread::get_current_job()
429 BatchRenderJob *result;
430 if(current_job >= jobs.total || current_job < 0)
432 result = default_job;
436 result = jobs.values[current_job];
442 Asset* BatchRenderThread::get_current_asset()
444 return get_current_job()->asset;
447 char* BatchRenderThread::get_current_edl()
449 return get_current_job()->edl_path;
453 // Test EDL files for existence
454 int BatchRenderThread::test_edl_files()
456 for(int i = 0; i < jobs.total; i++)
458 if(jobs.values[i]->enabled)
460 const char *path = jobs.values[i]->edl_path;
461 if( *path == '@' ) ++path;
462 FILE *fd = fopen(path, "r");
465 char string[BCTEXTLEN];
466 sprintf(string, _("EDL %s not found.\n"), jobs.values[i]->edl_path);
469 ErrorBox error_box(_(PROGRAM_NAME ": Error"),
470 mwindow->gui->get_abs_cursor_x(1),
471 mwindow->gui->get_abs_cursor_y(1));
472 error_box.create_objects(string);
473 error_box.run_window();
474 gui->button_enable();
495 void BatchRenderThread::calculate_dest_paths(ArrayList<char*> *paths,
496 Preferences *preferences)
498 for(int i = 0; i < jobs.total; i++)
500 BatchRenderJob *job = jobs.values[i];
501 if(job->enabled && *job->edl_path != '@')
503 PackageDispatcher *packages = new PackageDispatcher;
506 TransportCommand *command = new TransportCommand;
507 FileXML *file = new FileXML;
508 file->read_from_file(job->edl_path);
510 // Use command to calculate range.
511 command->command = NORMAL_FWD;
512 command->get_edl()->load_xml(file,
514 command->change_type = CHANGE_ALL;
515 command->set_playback_range();
516 command->adjust_playback_range();
518 // Create test packages
519 packages->create_packages(mwindow,
524 command->start_position,
525 command->end_position,
528 // Append output paths allocated to total
529 for(int j = 0; j < packages->get_total_packages(); j++)
531 RenderPackage *package = packages->get_package(j);
532 paths->append(cstrdup(package->path));
535 // Delete package harness
544 void BatchRenderThread::start_rendering(char *config_path,
547 BC_Hash *boot_defaults;
548 Preferences *preferences;
550 BC_Signals *signals = new BC_Signals;
551 // XXX the above stuff is leaked,
553 // Initialize stuff which MWindow does.
554 signals->initialize();
555 MWindow::init_defaults(boot_defaults, config_path);
556 load_defaults(boot_defaults);
557 preferences = new Preferences;
558 preferences->load_defaults(boot_defaults);
559 MWindow::init_plugins(0, preferences);
560 char font_path[BCTEXTLEN];
561 strcpy(font_path, preferences->plugin_dir);
562 strcat(font_path, "/fonts");
563 BC_Resources::init_fontconfig(font_path);
564 BC_WindowBase::get_resources()->vframe_shm = 1;
565 MWindow::init_fileserver(preferences);
568 load_jobs(batch_path, preferences);
569 save_jobs(batch_path);
570 save_defaults(boot_defaults);
573 // Test EDL files for existence
574 if(test_edl_files()) return;
578 // Predict all destination paths
579 ArrayList<char*> paths;
580 paths.set_array_delete();
581 calculate_dest_paths(&paths, preferences);
584 int result = ConfirmSave::test_files(0, &paths);
585 paths.remove_all_objects();
586 // Abort on any existing file because it's so hard to set this up.
590 render = new Render(0);
592 render->start_batches(&jobs,
598 void BatchRenderThread::start_rendering()
600 if(is_rendering) return;
603 char path[BCTEXTLEN];
606 save_defaults(mwindow->defaults);
607 gui->button_disable();
609 // Test EDL files for existence
610 if(test_edl_files()) return;
612 // Predict all destination paths
613 ArrayList<char*> paths;
614 calculate_dest_paths(&paths,
615 mwindow->preferences);
617 // Test destination files for overwrite
618 int result = ConfirmSave::test_files(mwindow, &paths);
619 paths.remove_all_objects();
625 gui->button_enable();
629 mwindow->render->start_batches(&jobs);
632 void BatchRenderThread::stop_rendering()
634 if(!is_rendering) return;
635 mwindow->render->stop_operation();
639 void BatchRenderThread::update_active(int number)
641 gui->lock_window("BatchRenderThread::update_active");
644 current_job = number;
645 rendering_job = number;
653 gui->unlock_window();
656 void BatchRenderThread::update_done(int number,
660 gui->lock_window("BatchRenderThread::update_done");
663 gui->button_enable();
667 jobs.values[number]->enabled = 0;
668 jobs.values[number]->elapsed = elapsed_time;
669 if(create_list) gui->create_list(1);
671 gui->unlock_window();
674 void BatchRenderThread::move_batch(int src, int dst)
676 BatchRenderJob *src_job = jobs.values[src];
677 if(dst < 0) dst = jobs.total - 1;
681 for(int i = src; i < jobs.total - 1; i++)
682 jobs.values[i] = jobs.values[i + 1];
683 // if(dst > src) dst--;
684 for(int i = jobs.total - 1; i > dst; i--)
685 jobs.values[i] = jobs.values[i - 1];
686 jobs.values[dst] = src_job;
697 BatchRenderGUI::BatchRenderGUI(MWindow *mwindow,
698 BatchRenderThread *thread,
703 : BC_Window(_(PROGRAM_NAME ": Batch Render"),
714 this->mwindow = mwindow;
715 this->thread = thread;
718 BatchRenderGUI::~BatchRenderGUI()
720 lock_window("BatchRenderGUI::~BatchRenderGUI");
726 void BatchRenderGUI::create_objects()
728 lock_window("BatchRenderGUI::create_objects");
729 mwindow->theme->get_batchrender_sizes(this, get_w(), get_h());
732 int x = mwindow->theme->batchrender_x1;
734 int x1 = mwindow->theme->batchrender_x1;
735 int x2 = mwindow->theme->batchrender_x2;
736 //int x3 = mwindow->theme->batchrender_x3;
741 add_subwindow(output_path_title = new BC_Title(x1, y, _("Output path:")));
743 format_tools = new BatchFormat(mwindow,
745 thread->get_current_asset());
746 format_tools->set_w(get_w() / 2);
747 format_tools->create_objects(x,
757 &thread->get_current_job()->strategy,
762 x += format_tools->get_w();
769 add_subwindow(edl_path_title = new BC_Title(x, y, _("EDL Path:")));
771 add_subwindow(edl_path_text = new BatchRenderEDLPath(
776 thread->get_current_edl()));
778 x += edl_path_text->get_w();
779 add_subwindow(edl_path_browse = new BrowseButton(
785 thread->get_current_edl(),
787 _("Select an EDL to load:"),
793 add_subwindow(update_selected_edl = new BatchRenderUpdateEDL(thread,
796 y += update_selected_edl->get_h() + mwindow->theme->widget_border;
798 add_subwindow(new_batch = new BatchRenderNew(thread,
801 x += new_batch->get_w() + 10;
803 add_subwindow(delete_batch = new BatchRenderDelete(thread,
806 x = new_batch->get_x();
807 y += new_batch->get_h() + mwindow->theme->widget_border;
808 add_subwindow(use_current_edl = new BatchRenderCurrentEDL(thread,
811 if( !mwindow->edl || !mwindow->edl->path[0] ) use_current_edl->disable();
815 add_subwindow(list_title = new BC_Title(x, y, _("Batches to render:")));
817 add_subwindow(batch_list = new BatchRenderList(thread,
821 get_h() - y - BC_GenericButton::calculate_h() - 15));
823 y += batch_list->get_h() + 10;
824 add_subwindow(start_button = new BatchRenderStart(thread,
828 BC_GenericButton::calculate_w(this, _("Stop")) / 2;
829 add_subwindow(stop_button = new BatchRenderStop(thread,
833 BC_GenericButton::calculate_w(this, _("Close")) -
835 add_subwindow(cancel_button = new BatchRenderCancel(thread,
843 void BatchRenderGUI::button_disable()
845 new_batch->disable();
846 delete_batch->disable();
847 use_current_edl->disable();
848 update_selected_edl->disable();
851 void BatchRenderGUI::button_enable()
854 delete_batch->enable();
855 if( mwindow->edl && mwindow->edl->path[0] )
856 use_current_edl->enable();
857 update_selected_edl->enable();
860 int BatchRenderGUI::resize_event(int w, int h)
862 mwindow->session->batchrender_w = w;
863 mwindow->session->batchrender_h = h;
864 mwindow->theme->get_batchrender_sizes(this, w, h);
866 int x = mwindow->theme->batchrender_x1;
868 int x1 = mwindow->theme->batchrender_x1;
869 int x2 = mwindow->theme->batchrender_x2;
870 //int x3 = mwindow->theme->batchrender_x3;
874 output_path_title->reposition_window(x1, y);
876 format_tools->reposition_window(x, y);
880 x += format_tools->get_w();
885 edl_path_title->reposition_window(x, y);
887 edl_path_text->reposition_window(x, y, w - x - 40);
888 x += edl_path_text->get_w();
889 edl_path_browse->reposition_window(x, y);
893 // status_title->reposition_window(x, y);
895 // status_text->reposition_window(x, y);
898 // progress_bar->reposition_window(x, y, w - x - 10);
901 update_selected_edl->reposition_window(x, y);
902 y += update_selected_edl->get_h() + mwindow->theme->widget_border;
903 new_batch->reposition_window(x, y);
904 x += new_batch->get_w() + 10;
905 delete_batch->reposition_window(x, y);
906 x = new_batch->get_x();
907 y += new_batch->get_h() + mwindow->theme->widget_border;
908 use_current_edl->reposition_window(x, y);
912 int y_margin = get_h() - batch_list->get_h();
913 list_title->reposition_window(x, y);
915 batch_list->reposition_window(x, y, w - x - 10, h - y_margin);
917 y += batch_list->get_h() + 10;
918 start_button->reposition_window(x, y);
920 stop_button->get_w() / 2;
921 stop_button->reposition_window(x, y);
923 cancel_button->get_w() -
925 cancel_button->reposition_window(x, y);
929 int BatchRenderGUI::translation_event()
931 mwindow->session->batchrender_x = get_x();
932 mwindow->session->batchrender_y = get_y();
936 int BatchRenderGUI::close_event()
938 // Stop batch rendering
940 thread->stop_rendering();
941 lock_window("BatchRenderGUI::close_event");
946 void BatchRenderGUI::create_list(int update_widget)
948 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
950 list_columns[i].remove_all_objects();
953 for(int i = 0; i < thread->jobs.total; i++)
955 BatchRenderJob *job = thread->jobs.values[i];
956 char string[BCTEXTLEN];
957 BC_ListBoxItem *enabled = new BC_ListBoxItem(job->enabled ?
960 BC_ListBoxItem *item1 = new BC_ListBoxItem(job->asset->path);
961 BC_ListBoxItem *item2 = new BC_ListBoxItem(job->edl_path);
962 BC_ListBoxItem *item3;
964 item3 = new BC_ListBoxItem(
965 Units::totext(string,
969 item3 = new BC_ListBoxItem(_("Unknown"));
970 list_columns[0].append(enabled);
971 list_columns[1].append(item1);
972 list_columns[2].append(item2);
973 list_columns[3].append(item3);
974 if(i == thread->current_job)
976 enabled->set_selected(1);
977 item1->set_selected(1);
978 item2->set_selected(1);
979 item3->set_selected(1);
981 if(i == thread->rendering_job)
983 enabled->set_color(RED);
984 item1->set_color(RED);
985 item2->set_color(RED);
986 item3->set_color(RED);
992 batch_list->update(list_columns,
994 thread->column_width,
996 batch_list->get_xposition(),
997 batch_list->get_yposition(),
998 batch_list->get_highlighted_item(), // Flat index of item cursor is over
999 1, // set all autoplace flags to 1
1004 void BatchRenderGUI::change_job()
1006 BatchRenderJob *job = thread->get_current_job();
1007 format_tools->update(job->asset, &job->strategy);
1008 edl_path_text->update(job->edl_path);
1018 BatchFormat::BatchFormat(MWindow *mwindow,
1019 BatchRenderGUI *gui,
1021 : FormatTools(mwindow, gui, asset)
1024 this->mwindow = mwindow;
1027 BatchFormat::~BatchFormat()
1032 int BatchFormat::handle_event()
1034 gui->create_list(1);
1048 BatchRenderEDLPath::BatchRenderEDLPath(BatchRenderThread *thread,
1059 this->thread = thread;
1063 int BatchRenderEDLPath::handle_event()
1066 calculate_suggestions(thread->file_entries);
1068 strcpy(thread->get_current_edl(), get_text());
1069 thread->gui->create_list(1);
1078 BatchRenderNew::BatchRenderNew(BatchRenderThread *thread,
1081 : BC_GenericButton(x, y, _("New"))
1083 this->thread = thread;
1086 int BatchRenderNew::handle_event()
1092 BatchRenderDelete::BatchRenderDelete(BatchRenderThread *thread,
1095 : BC_GenericButton(x, y, _("Delete"))
1097 this->thread = thread;
1100 int BatchRenderDelete::handle_event()
1102 thread->delete_job();
1111 BatchRenderCurrentEDL::BatchRenderCurrentEDL(BatchRenderThread *thread,
1114 : BC_GenericButton(x, y, _("Use Current EDL"))
1116 this->thread = thread;
1119 int BatchRenderCurrentEDL::handle_event()
1121 thread->use_current_edl();
1125 BatchRenderUpdateEDL::BatchRenderUpdateEDL(BatchRenderThread *thread,
1128 : BC_GenericButton(x, y, _("Save to EDL Path"))
1130 this->thread = thread;
1133 int BatchRenderUpdateEDL::handle_event()
1135 thread->update_selected_edl();
1142 BatchRenderList::BatchRenderList(BatchRenderThread *thread,
1152 thread->gui->list_columns,
1154 thread->column_width,
1155 BATCHRENDER_COLUMNS,
1162 this->thread = thread;
1164 set_process_drag(0);
1167 int BatchRenderList::handle_event()
1172 int BatchRenderList::selection_changed()
1174 thread->current_job = get_selection_number(0, 0);
1175 thread->gui->change_job();
1176 if(get_cursor_x() < thread->column_width[0])
1178 BatchRenderJob *job = thread->get_current_job();
1179 job->enabled = !job->enabled;
1180 thread->gui->create_list(1);
1185 int BatchRenderList::column_resize_event()
1187 for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
1189 thread->column_width[i] = get_column_width(i);
1194 int BatchRenderList::drag_start_event()
1196 if(BC_ListBox::drag_start_event())
1205 int BatchRenderList::drag_motion_event()
1207 if(BC_ListBox::drag_motion_event())
1214 int BatchRenderList::drag_stop_event()
1218 int src = get_selection_number(0, 0);
1219 int dst = get_highlighted_item();
1222 thread->move_batch(src, dst);
1224 BC_ListBox::drag_stop_event();
1241 BatchRenderStart::BatchRenderStart(BatchRenderThread *thread,
1244 : BC_GenericButton(x,
1248 this->thread = thread;
1251 int BatchRenderStart::handle_event()
1253 thread->start_rendering();
1257 BatchRenderStop::BatchRenderStop(BatchRenderThread *thread,
1260 : BC_GenericButton(x,
1264 this->thread = thread;
1267 int BatchRenderStop::handle_event()
1270 thread->stop_rendering();
1271 lock_window("BatchRenderStop::handle_event");
1276 BatchRenderCancel::BatchRenderCancel(BatchRenderThread *thread,
1279 : BC_GenericButton(x,
1283 this->thread = thread;
1286 int BatchRenderCancel::handle_event()
1289 thread->stop_rendering();
1290 lock_window("BatchRenderCancel::handle_event");
1291 thread->gui->set_done(1);
1295 int BatchRenderCancel::keypress_event()
1297 if(get_keypress() == ESC)
1300 thread->stop_rendering();
1301 lock_window("BatchRenderCancel::keypress_event");
1302 thread->gui->set_done(1);
1314 const int64_t CreateDVD_Thread::DVD_SIZE = 4700000000;
1315 const int CreateDVD_Thread::DVD_STREAMS = 1;
1316 const int CreateDVD_Thread::DVD_WIDTH = 720;
1317 const int CreateDVD_Thread::DVD_HEIGHT = 480;
1318 const double CreateDVD_Thread::DVD_ASPECT_WIDTH = 4.;
1319 const double CreateDVD_Thread::DVD_ASPECT_HEIGHT = 3.;
1320 const double CreateDVD_Thread::DVD_WIDE_ASPECT_WIDTH = 16.;
1321 const double CreateDVD_Thread::DVD_WIDE_ASPECT_HEIGHT = 9.;
1322 const double CreateDVD_Thread::DVD_FRAMERATE = 30000. / 1001.;
1323 const int CreateDVD_Thread::DVD_MAX_BITRATE = 8000000;
1324 const int CreateDVD_Thread::DVD_CHANNELS = 2;
1325 const int CreateDVD_Thread::DVD_WIDE_CHANNELS = 6;
1326 const double CreateDVD_Thread::DVD_SAMPLERATE = 48000;
1327 const double CreateDVD_Thread::DVD_KAUDIO_RATE = 224;
1330 CreateDVD_MenuItem::CreateDVD_MenuItem(MWindow *mwindow)
1331 : BC_MenuItem(_("DVD Render..."), _("Shift-D"), 'D')
1334 this->mwindow = mwindow;
1337 int CreateDVD_MenuItem::handle_event()
1339 mwindow->create_dvd->start();
1344 CreateDVD_Thread::CreateDVD_Thread(MWindow *mwindow)
1347 this->mwindow = mwindow;
1349 this->use_deinterlace = 0;
1350 this->use_inverse_telecine = 0;
1351 this->use_scale = 0;
1352 this->use_resize_tracks = 0;
1353 this->use_histogram = 0;
1354 this->use_wide_audio = 0;
1355 this->use_wide_aspect = 0;
1356 this->use_label_chapters = 0;
1357 this->use_ffmpeg = 0;
1360 CreateDVD_Thread::~CreateDVD_Thread()
1364 int CreateDVD_Thread::create_dvd_jobs(ArrayList<BatchRenderJob*> *jobs,
1365 const char *tmp_path, const char *asset_title)
1367 EDL *edl = mwindow->edl;
1368 if( !edl || !edl->session ) {
1369 char msg[BCTEXTLEN];
1370 sprintf(msg, _("No EDL/Session"));
1371 MainError::show_error(msg);
1374 EDLSession *session = edl->session;
1376 double total_length = edl->tracks->total_length();
1377 if( total_length <= 0 ) {
1378 char msg[BCTEXTLEN];
1379 sprintf(msg, _("No content: %s"), asset_title);
1380 MainError::show_error(msg);
1384 char asset_dir[BCTEXTLEN];
1385 sprintf(asset_dir, "%s/%s", tmp_path, asset_title);
1387 if( mkdir(asset_dir, 0777) ) {
1388 char err[BCTEXTLEN], msg[BCTEXTLEN];
1389 strerror_r(errno, err, sizeof(err));
1390 sprintf(msg, _("Unable to create directory: %s\n-- %s"), asset_dir, err);
1391 MainError::show_error(msg);
1395 double old_samplerate = session->sample_rate;
1396 double old_framerate = session->frame_rate;
1398 session->video_channels = DVD_STREAMS;
1399 session->video_tracks = DVD_STREAMS;
1400 session->frame_rate = DVD_FRAMERATE;
1401 session->output_w = DVD_WIDTH;
1402 session->output_h = DVD_HEIGHT;
1403 session->aspect_w = use_wide_aspect ? DVD_WIDE_ASPECT_WIDTH : DVD_ASPECT_WIDTH;
1404 session->aspect_h = use_wide_aspect ? DVD_WIDE_ASPECT_HEIGHT : DVD_ASPECT_HEIGHT;
1405 session->sample_rate = DVD_SAMPLERATE;
1406 session->audio_channels = session->audio_tracks =
1407 use_wide_audio ? DVD_WIDE_CHANNELS : DVD_CHANNELS;
1409 char script_filename[BCTEXTLEN];
1410 sprintf(script_filename, "%s/dvd.sh", asset_dir);
1411 int fd = open(script_filename, O_WRONLY+O_CREAT+O_TRUNC, 0755);
1412 FILE *fp = fdopen(fd, "w");
1414 char err[BCTEXTLEN], msg[BCTEXTLEN];
1415 strerror_r(errno, err, sizeof(err));
1416 sprintf(msg, _("Unable to save: %s\n-- %s"), script_filename, err);
1417 MainError::show_error(msg);
1420 fprintf(fp,"#!/bin/bash\n");
1421 fprintf(fp,"echo \"running %s\" $# $*\n", script_filename);
1424 fprintf(fp,"mplex -f 8 -o $1/dvd.mpg $1/dvd.m2v $1/dvd.ac3\n");
1427 fprintf(fp,"rm -rf $1/iso\n");
1428 fprintf(fp,"mkdir -p $1/iso\n");
1430 fprintf(fp,"dvdauthor -x - <<eof\n");
1431 fprintf(fp,"<dvdauthor dest=\"$1/iso\">\n");
1432 fprintf(fp," <vmgm>\n");
1433 fprintf(fp," <fpc> jump title 1; </fpc>\n");
1434 fprintf(fp," </vmgm>\n");
1435 fprintf(fp," <titleset>\n");
1436 fprintf(fp," <titles>\n");
1437 fprintf(fp," <video format=\"ntsc\" aspect=\"%d:%d\" resolution=\"%dx%d\"/>\n",
1438 (int)session->aspect_w, (int)session->aspect_h,
1439 session->output_w, session->output_h);
1440 fprintf(fp," <audio format=\"ac3\" lang=\"en\"/>\n");
1441 fprintf(fp," <pgc>\n");
1442 fprintf(fp," <vob file=\"$1/dvd.mpg\" chapters=\"");
1443 if( use_label_chapters && edl->labels ) {
1444 Label *label = edl->labels->first;
1446 int secs = label->position;
1447 int mins = secs / 60;
1448 int frms = (label->position-secs) * session->frame_rate;
1449 fprintf(fp,"%d:%02d:%02d.%d", mins/60, mins%60, secs%60, frms);
1450 if( (label=label->next) != 0 ) fprintf(fp, ",");
1455 for( int secs=0 ; secs<total_length; secs+=10*60 ) {
1457 fprintf(fp,"%d:%02d:00,", mins/60, mins%60);
1459 fprintf(fp,"%d:%02d:00", mins/60, mins%60);
1461 fprintf(fp,"\"/>\n");
1462 fprintf(fp," </pgc>\n");
1463 fprintf(fp," </titles>\n");
1464 fprintf(fp," </titleset>\n");
1465 fprintf(fp,"</dvdauthor>\n");
1466 fprintf(fp,"eof\n");
1468 fprintf(fp,"echo To burn dvd, load blank media and run:\n");
1469 fprintf(fp,"echo growisofs -dvd-compat -Z /dev/dvd -dvd-video $1/iso\n");
1473 if( use_wide_audio ) {
1474 session->audio_channels = session->audio_tracks = DVD_WIDE_CHANNELS;
1475 session->achannel_positions[0] = 90;
1476 session->achannel_positions[1] = 150;
1477 session->achannel_positions[2] = 30;
1478 session->achannel_positions[3] = 210;
1479 session->achannel_positions[4] = 330;
1480 session->achannel_positions[5] = 270;
1481 if( edl->tracks->recordable_audio_tracks() == DVD_WIDE_CHANNELS )
1482 mwindow->remap_audio(MWindow::AUDIO_1_TO_1);
1485 session->audio_channels = session->audio_tracks = DVD_CHANNELS;
1486 session->achannel_positions[0] = 180;
1487 session->achannel_positions[1] = 0;
1488 if( edl->tracks->recordable_audio_tracks() == DVD_WIDE_CHANNELS )
1489 mwindow->remap_audio(MWindow::AUDIO_5_1_TO_2);
1492 double new_samplerate = session->sample_rate;
1493 double new_framerate = session->frame_rate;
1495 edl->resample(old_samplerate, new_samplerate, TRACK_AUDIO);
1496 edl->resample(old_framerate, new_framerate, TRACK_VIDEO);
1498 int64_t aud_size = ((DVD_KAUDIO_RATE * total_length)/8 + 1000-1) * 1000;
1499 int64_t vid_size = DVD_SIZE*0.96 - aud_size;
1500 int vid_bitrate = (vid_size * 8) / total_length;
1501 vid_bitrate /= 1000; vid_bitrate *= 1000;
1502 if( vid_bitrate > DVD_MAX_BITRATE ) vid_bitrate = DVD_MAX_BITRATE;
1504 char xml_filename[BCTEXTLEN];
1505 sprintf(xml_filename, "%s/dvd.xml", asset_dir);
1507 edl->save_xml(&xml_file, xml_filename, 0, 0);
1508 xml_file.terminate_string();
1509 if( xml_file.write_to_file(xml_filename) ) {
1510 char msg[BCTEXTLEN];
1511 sprintf(msg, _("Unable to save: %s"), xml_filename);
1512 MainError::show_error(msg);
1516 BatchRenderJob *job = new BatchRenderJob(mwindow->preferences);
1518 strcpy(&job->edl_path[0], xml_filename);
1519 Asset *asset = job->asset;
1521 asset->layers = DVD_STREAMS;
1522 asset->frame_rate = session->frame_rate;
1523 asset->width = session->output_w;
1524 asset->height = session->output_h;
1525 asset->aspect_ratio = session->aspect_w / session->aspect_h;
1528 char option_path[BCTEXTLEN];
1529 sprintf(&asset->path[0],"%s/dvd.mpg", asset_dir);
1530 asset->format = FILE_FFMPEG;
1531 strcpy(asset->fformat, "dvd");
1533 asset->audio_data = 1;
1534 strcpy(asset->acodec, "dvd.dvd");
1535 FFMPEG::set_option_path(option_path, "audio/%s", asset->acodec);
1536 FFMPEG::load_options(option_path, asset->ff_audio_options,
1537 sizeof(asset->ff_audio_options));
1538 asset->ff_audio_bitrate = DVD_KAUDIO_RATE * 1000;
1540 asset->video_data = 1;
1541 strcpy(asset->vcodec, "dvd.dvd");
1542 FFMPEG::set_option_path(option_path, "video/%s", asset->vcodec);
1543 FFMPEG::load_options(option_path, asset->ff_video_options,
1544 sizeof(asset->ff_video_options));
1545 asset->ff_video_bitrate = vid_bitrate;
1546 asset->ff_video_quality = 0;
1548 int len = strlen(asset->ff_video_options);
1549 char *cp = asset->ff_video_options + len;
1550 snprintf(cp, sizeof(asset->ff_video_options)-len-1,
1551 "aspect %.5f\n", asset->aspect_ratio);
1554 sprintf(&asset->path[0],"%s/dvd.m2v", asset_dir);
1555 asset->video_data = 1;
1556 asset->format = FILE_VMPEG;
1557 asset->vmpeg_cmodel = BC_YUV420P;
1558 asset->vmpeg_fix_bitrate = 1;
1559 asset->vmpeg_bitrate = vid_bitrate;
1560 asset->vmpeg_quantization = 15;
1561 asset->vmpeg_iframe_distance = 15;
1562 asset->vmpeg_progressive = 0;
1563 asset->vmpeg_denoise = 0;
1564 asset->vmpeg_seq_codes = 0;
1565 asset->vmpeg_derivative = 2;
1566 asset->vmpeg_preset = 8;
1567 asset->vmpeg_field_order = 0;
1568 asset->vmpeg_pframe_distance = 0;
1569 job = new BatchRenderJob(mwindow->preferences);
1571 strcpy(&job->edl_path[0], xml_filename);
1574 sprintf(&asset->path[0],"%s/dvd.ac3", asset_dir);
1575 asset->audio_data = 1;
1576 asset->format = FILE_AC3;
1577 asset->channels = session->audio_channels;
1578 asset->sample_rate = session->sample_rate;
1580 asset->byte_order = 0;
1584 asset->ac3_bitrate = DVD_KAUDIO_RATE;
1587 job = new BatchRenderJob(mwindow->preferences);
1589 job->edl_path[0] = '@';
1590 strcpy(&job->edl_path[1], script_filename);
1591 strcpy(&job->asset->path[0], asset_dir);
1596 void CreateDVD_Thread::handle_close_event(int result)
1598 if( result ) return;
1599 mwindow->batch_render->load_defaults(mwindow->defaults);
1600 mwindow->undo->update_undo_before();
1601 KeyFrame keyframe; char data[BCTEXTLEN];
1602 if( use_deinterlace ) {
1603 sprintf(data,"<DEINTERLACE MODE=1>");
1604 keyframe.set_data(data);
1605 insert_video_plugin("Deinterlace", &keyframe);
1607 if( use_inverse_telecine ) {
1608 sprintf(data,"<IVTC FRAME_OFFSET=0 FIRST_FIELD=0 "
1609 "AUTOMATIC=1 AUTO_THRESHOLD=2.0e+00 PATTERN=2>");
1610 keyframe.set_data(data);
1611 insert_video_plugin("Inverse Telecine", &keyframe);
1614 sprintf(data,"<SCALE TYPE=1 X_FACTOR=1 Y_FACTOR=1 "
1615 "WIDTH=%d HEIGHT=%d CONSTRAIN=0>", DVD_WIDTH, DVD_HEIGHT);
1616 keyframe.set_data(data);
1617 insert_video_plugin("Scale", &keyframe);
1619 if( use_resize_tracks )
1621 if( use_histogram ) {
1623 sprintf(data, "<HISTOGRAM OUTPUT_MIN_0=0 OUTPUT_MAX_0=1 "
1624 "OUTPUT_MIN_1=0 OUTPUT_MAX_1=1 "
1625 "OUTPUT_MIN_2=0 OUTPUT_MAX_2=1 "
1626 "OUTPUT_MIN_3=0 OUTPUT_MAX_3=1 "
1627 "AUTOMATIC=0 THRESHOLD=9.0-01 PLOT=0 SPLIT=0>"
1628 "<POINTS></POINTS><POINTS></POINTS><POINTS></POINTS>"
1629 "<POINTS><POINT X=6.0e-02 Y=0>"
1630 "<POINT X=9.4e-01 Y=1></POINTS>");
1632 sprintf(data, "<HISTOGRAM AUTOMATIC=0 THRESHOLD=1.0e-01 "
1633 "PLOT=0 SPLIT=0 W=440 H=500 PARADE=0 MODE=3 "
1634 "LOW_OUTPUT_0=0 HIGH_OUTPUT_0=1 LOW_INPUT_0=0 HIGH_INPUT_0=1 GAMMA_0=1 "
1635 "LOW_OUTPUT_1=0 HIGH_OUTPUT_1=1 LOW_INPUT_1=0 HIGH_INPUT_1=1 GAMMA_1=1 "
1636 "LOW_OUTPUT_2=0 HIGH_OUTPUT_2=1 LOW_INPUT_2=0 HIGH_INPUT_2=1 GAMMA_2=1 "
1637 "LOW_OUTPUT_3=0 HIGH_OUTPUT_3=1 LOW_INPUT_3=0.06 HIGH_INPUT_3=0.94 "
1640 keyframe.set_data(data);
1641 insert_video_plugin("Histogram", &keyframe);
1643 create_dvd_jobs(&mwindow->batch_render->jobs, tmp_path, asset_title);
1644 mwindow->save_backup();
1645 mwindow->undo->update_undo_after(_("create dvd"), LOAD_ALL);
1646 mwindow->resync_guis();
1647 mwindow->batch_render->handle_close_event(0);
1648 mwindow->batch_render->start();
1651 BC_Window* CreateDVD_Thread::new_gui()
1653 memset(tmp_path,0,sizeof(tmp_path));
1654 strcpy(tmp_path,"/tmp");
1655 memset(asset_title,0,sizeof(asset_title));
1656 time_t dt; time(&dt);
1657 struct tm dtm; localtime_r(&dt, &dtm);
1658 sprintf(asset_title, "dvd_%02d%02d%02d-%02d%02d%02d",
1659 dtm.tm_year+1900, dtm.tm_mon+1, dtm.tm_mday,
1660 dtm.tm_hour, dtm.tm_min, dtm.tm_sec);
1661 use_deinterlace = 0;
1662 use_inverse_telecine = 0;
1664 use_resize_tracks = 0;
1667 use_wide_aspect = 0;
1668 use_label_chapters = 0;
1671 int scr_x = mwindow->gui->get_screen_x(0, -1);
1672 int scr_w = mwindow->gui->get_screen_w(0, -1);
1673 int scr_h = mwindow->gui->get_screen_h(0, -1);
1674 int w = 500, h = 250;
1675 int x = scr_x + scr_w/2 - w/2, y = scr_h/2 - h/2;
1677 gui = new CreateDVD_GUI(this, x, y, w, h);
1678 gui->create_objects();
1683 CreateDVD_OK::CreateDVD_OK(CreateDVD_GUI *gui, int x, int y)
1687 set_tooltip(_("end setup, start batch render"));
1690 CreateDVD_OK::~CreateDVD_OK()
1694 int CreateDVD_OK::button_press_event()
1696 if(get_buttonpress() == 1 && is_event_win() && cursor_inside()) {
1703 int CreateDVD_OK::keypress_event()
1709 CreateDVD_Cancel::CreateDVD_Cancel(CreateDVD_GUI *gui, int x, int y)
1710 : BC_CancelButton(x, y)
1715 CreateDVD_Cancel::~CreateDVD_Cancel()
1719 int CreateDVD_Cancel::button_press_event()
1721 if(get_buttonpress() == 1 && is_event_win() && cursor_inside()) {
1729 CreateDVD_DiskSpace::CreateDVD_DiskSpace(CreateDVD_GUI *gui, int x, int y)
1730 : BC_Title(x, y, "", MEDIUMFONT, GREEN)
1735 CreateDVD_DiskSpace::~CreateDVD_DiskSpace()
1739 int64_t CreateDVD_DiskSpace::tmp_path_space()
1741 const char *path = gui->tmp_path->get_text();
1742 if( access(path,R_OK+W_OK) ) return 0;
1744 if( statfs(path, &sfs) ) return 0;
1745 return (int64_t)sfs.f_bsize * sfs.f_bfree;
1748 void CreateDVD_DiskSpace::update()
1750 // gui->disk_space->set_color(get_bg_color());
1751 int64_t disk_space = tmp_path_space();
1752 int color = disk_space<gui->needed_disk_space ? RED : GREEN;
1753 static const char *suffix[] = { "", "KB", "MB", "GB", "TB", "PB" };
1755 for( int64_t space=disk_space; i<5 && (space/=1000)>0; disk_space=space, ++i );
1756 char text[BCTEXTLEN];
1757 sprintf(text, "%s" _LDv(3) "%s", _("disk space: "), disk_space, suffix[i]);
1758 gui->disk_space->BC_Title::update(text);
1759 gui->disk_space->set_color(color);
1762 CreateDVD_TmpPath::CreateDVD_TmpPath(CreateDVD_GUI *gui, int x, int y, int w)
1763 : BC_TextBox(x, y, w, 1, -sizeof(gui->thread->tmp_path),
1764 gui->thread->tmp_path, 1, MEDIUMFONT)
1769 CreateDVD_TmpPath::~CreateDVD_TmpPath()
1773 int CreateDVD_TmpPath::handle_event()
1775 gui->disk_space->update();
1780 CreateDVD_AssetTitle::CreateDVD_AssetTitle(CreateDVD_GUI *gui, int x, int y, int w)
1781 : BC_TextBox(x, y, w, 1, 0, gui->thread->asset_title, 1, MEDIUMFONT)
1786 CreateDVD_AssetTitle::~CreateDVD_AssetTitle()
1791 CreateDVD_Deinterlace::CreateDVD_Deinterlace(CreateDVD_GUI *gui, int x, int y)
1792 : BC_CheckBox(x, y, &gui->thread->use_deinterlace, _("Deinterlace"))
1797 CreateDVD_Deinterlace::~CreateDVD_Deinterlace()
1801 int CreateDVD_Deinterlace::handle_event()
1804 gui->need_inverse_telecine->set_value(0);
1805 gui->thread->use_inverse_telecine = 0;
1807 return BC_CheckBox::handle_event();
1811 CreateDVD_InverseTelecine::CreateDVD_InverseTelecine(CreateDVD_GUI *gui, int x, int y)
1812 : BC_CheckBox(x, y, &gui->thread->use_inverse_telecine, _("Inverse Telecine"))
1817 CreateDVD_InverseTelecine::~CreateDVD_InverseTelecine()
1821 int CreateDVD_InverseTelecine::handle_event()
1824 gui->need_deinterlace->set_value(0);
1825 gui->thread->use_deinterlace = 0;
1827 return BC_CheckBox::handle_event();
1831 CreateDVD_Scale::CreateDVD_Scale(CreateDVD_GUI *gui, int x, int y)
1832 : BC_CheckBox(x, y, &gui->thread->use_scale, _("Scale"))
1837 CreateDVD_Scale::~CreateDVD_Scale()
1842 CreateDVD_ResizeTracks::CreateDVD_ResizeTracks(CreateDVD_GUI *gui, int x, int y)
1843 : BC_CheckBox(x, y, &gui->thread->use_resize_tracks, _("Resize Tracks"))
1848 CreateDVD_ResizeTracks::~CreateDVD_ResizeTracks()
1853 CreateDVD_Histogram::CreateDVD_Histogram(CreateDVD_GUI *gui, int x, int y)
1854 : BC_CheckBox(x, y, &gui->thread->use_histogram, _("Histogram"))
1859 CreateDVD_Histogram::~CreateDVD_Histogram()
1863 CreateDVD_LabelChapters::CreateDVD_LabelChapters(CreateDVD_GUI *gui, int x, int y)
1864 : BC_CheckBox(x, y, &gui->thread->use_label_chapters, _("Chapters at Labels"))
1869 CreateDVD_LabelChapters::~CreateDVD_LabelChapters()
1873 CreateDVD_WideAudio::CreateDVD_WideAudio(CreateDVD_GUI *gui, int x, int y)
1874 : BC_CheckBox(x, y, &gui->thread->use_wide_audio, _("Audio 5.1"))
1879 CreateDVD_WideAudio::~CreateDVD_WideAudio()
1883 CreateDVD_WideAspect::CreateDVD_WideAspect(CreateDVD_GUI *gui, int x, int y)
1884 : BC_CheckBox(x, y, &gui->thread->use_wide_aspect, _("Aspect 16x9"))
1889 CreateDVD_WideAspect::~CreateDVD_WideAspect()
1893 CreateDVD_UseFFMpeg::CreateDVD_UseFFMpeg(CreateDVD_GUI *gui, int x, int y)
1894 : BC_CheckBox(x, y, &gui->thread->use_ffmpeg, _("Use FFMPEG"))
1899 CreateDVD_UseFFMpeg::~CreateDVD_UseFFMpeg()
1906 CreateDVD_GUI::CreateDVD_GUI(CreateDVD_Thread *thread, int x, int y, int w, int h)
1907 : BC_Window(_(PROGRAM_NAME ": Create DVD"), x, y, w, h, 50, 50, 1, 0, 1)
1909 this->thread = thread;
1910 at_x = at_y = tmp_x = tmp_y = 0;
1911 ok_x = ok_y = ok_w = ok_h = 0;
1912 cancel_x = cancel_y = cancel_w = cancel_h = 0;
1916 needed_disk_space = 15e9;
1917 need_deinterlace = 0;
1918 need_inverse_telecine = 0;
1920 need_resize_tracks = 0;
1922 need_wide_audio = 0;
1923 need_wide_aspect = 0;
1924 need_label_chapters = 0;
1929 CreateDVD_GUI::~CreateDVD_GUI()
1933 void CreateDVD_GUI::create_objects()
1935 lock_window("CreateDVD_GUI::create_objects");
1936 int pady = BC_TextBox::calculate_h(this, MEDIUMFONT, 0, 1) + 5;
1937 int padx = BC_Title::calculate_w(this, (char*)"X", MEDIUMFONT);
1938 int x = padx/2, y = pady/2;
1939 BC_Title *title = new BC_Title(x, y, _("Title:"), MEDIUMFONT, YELLOW);
1940 add_subwindow(title);
1941 at_x = x + title->get_w(); at_y = y;
1942 asset_title = new CreateDVD_AssetTitle(this, at_x, at_y, get_w()-at_x-10);
1943 add_subwindow(asset_title);
1944 y += title->get_h() + pady/2;
1945 title = new BC_Title(x, y, _("tmp path:"), MEDIUMFONT, YELLOW);
1946 add_subwindow(title);
1947 tmp_x = x + title->get_w(); tmp_y = y;
1948 tmp_path = new CreateDVD_TmpPath(this, tmp_x, tmp_y, get_w()-tmp_x-10);
1949 add_subwindow(tmp_path);
1950 y += title->get_h() + pady/2;
1951 disk_space = new CreateDVD_DiskSpace(this, x, y);
1952 add_subwindow(disk_space);
1953 disk_space->update();
1954 y += disk_space->get_h() + pady/2;
1955 need_deinterlace = new CreateDVD_Deinterlace(this, x, y);
1956 add_subwindow(need_deinterlace);
1957 int x1 = x + 150, x2 = x1 + 150;
1958 need_inverse_telecine = new CreateDVD_InverseTelecine(this, x1, y);
1959 add_subwindow(need_inverse_telecine);
1960 need_use_ffmpeg = new CreateDVD_UseFFMpeg(this, x2, y);
1961 add_subwindow(need_use_ffmpeg);
1962 y += need_deinterlace->get_h() + pady/2;
1963 need_scale = new CreateDVD_Scale(this, x, y);
1964 add_subwindow(need_scale);
1965 need_wide_audio = new CreateDVD_WideAudio(this, x1, y);
1966 add_subwindow(need_wide_audio);
1967 need_resize_tracks = new CreateDVD_ResizeTracks(this, x2, y);
1968 add_subwindow(need_resize_tracks);
1969 y += need_scale->get_h() + pady/2;
1970 need_histogram = new CreateDVD_Histogram(this, x, y);
1971 add_subwindow(need_histogram);
1972 need_wide_aspect = new CreateDVD_WideAspect(this, x1, y);
1973 add_subwindow(need_wide_aspect);
1974 need_label_chapters = new CreateDVD_LabelChapters(this, x2, y);
1975 add_subwindow(need_label_chapters);
1976 ok_w = BC_OKButton::calculate_w();
1977 ok_h = BC_OKButton::calculate_h();
1979 ok_y = get_h() - ok_h - 10;
1980 ok = new CreateDVD_OK(this, ok_x, ok_y);
1982 cancel_w = BC_CancelButton::calculate_w();
1983 cancel_h = BC_CancelButton::calculate_h();
1984 cancel_x = get_w() - cancel_w - 10,
1985 cancel_y = get_h() - cancel_h - 10;
1986 cancel = new CreateDVD_Cancel(this, cancel_x, cancel_y);
1987 add_subwindow(cancel);
1992 int CreateDVD_GUI::resize_event(int w, int h)
1994 asset_title->reposition_window(at_x, at_y, get_w()-at_x-10);
1995 tmp_path->reposition_window(tmp_x, tmp_y, get_w()-tmp_x-10);
1996 ok_y = h - ok_h - 10;
1997 ok->reposition_window(ok_x, ok_y);
1998 cancel_x = w - cancel_w - 10,
1999 cancel_y = h - cancel_h - 10;
2000 cancel->reposition_window(cancel_x, cancel_y);
2004 int CreateDVD_GUI::translation_event()
2009 int CreateDVD_GUI::close_event()
2015 int CreateDVD_Thread::
2016 insert_video_plugin(const char *title, KeyFrame *default_keyframe)
2018 Tracks *tracks = mwindow->edl->tracks;
2019 for( Track *vtrk=tracks->first; vtrk; vtrk=vtrk->next ) {
2020 if( vtrk->data_type != TRACK_VIDEO ) continue;
2021 if( !vtrk->record ) continue;
2022 vtrk->expand_view = 1;
2023 PluginSet *plugin_set = new PluginSet(mwindow->edl, vtrk);
2024 vtrk->plugin_set.append(plugin_set);
2025 Edits *edits = vtrk->edits;
2026 for( Edit *edit=edits->first; edit; edit=edit->next ) {
2027 plugin_set->insert_plugin(title,
2028 edit->startproject, edit->length,
2029 PLUGIN_STANDALONE, 0, default_keyframe, 0);
2036 int CreateDVD_Thread::
2039 Tracks *tracks = mwindow->edl->tracks;
2040 int max_w = 0, max_h = 0;
2041 for( Track *vtrk=tracks->first; vtrk; vtrk=vtrk->next ) {
2042 if( vtrk->data_type != TRACK_VIDEO ) continue;
2043 if( !vtrk->record ) continue;
2044 Edits *edits = vtrk->edits;
2045 for( Edit *edit=edits->first; edit; edit=edit->next ) {
2046 Indexable *indexable = edit->get_source();
2047 int w = indexable->get_w();
2048 if( w > max_w ) max_w = w;
2049 int h = indexable->get_h();
2050 if( h > max_h ) max_h = h;
2053 for( Track *vtrk=tracks->first; vtrk; vtrk=vtrk->next ) {
2054 if( vtrk->data_type != TRACK_VIDEO ) continue;
2055 if( !vtrk->record ) continue;
2056 vtrk->track_w = max_w;
2057 vtrk->track_h = max_h;
2062 int CreateDVD_Thread::
2065 if( !mwindow->edl ) return 1;
2066 Tracks *tracks = mwindow->edl->tracks;
2067 int max_w = 0, max_h = 0;
2068 int has_deinterlace = 0, has_scale = 0;
2069 for( Track *trk=tracks->first; trk; trk=trk->next ) {
2070 if( !trk->record ) continue;
2071 Edits *edits = trk->edits;
2072 switch( trk->data_type ) {
2074 for( Edit *edit=edits->first; edit; edit=edit->next ) {
2075 Indexable *indexable = edit->get_source();
2076 int w = indexable->get_w();
2077 if( w > max_w ) max_w = w;
2078 if( w != DVD_WIDTH ) use_scale = 1;
2079 int h = indexable->get_h();
2080 if( h > max_h ) max_h = h;
2081 if( h != DVD_HEIGHT ) use_scale = 1;
2083 for( int i=0; i<trk->plugin_set.size(); ++i ) {
2084 for(Plugin *plugin = (Plugin*)trk->plugin_set[i]->first;
2086 plugin = (Plugin*)plugin->next) {
2087 if( !strcmp(plugin->title, "Deinterlace") )
2088 has_deinterlace = 1;
2089 if( !strcmp(plugin->title, "Scale") )
2096 if( has_scale ) use_scale = 0;
2097 for( Track *trk=tracks->first; trk && !use_resize_tracks; trk=trk->next ) {
2098 if( !trk->record ) continue;
2099 switch( trk->data_type ) {
2101 if( trk->track_w != max_w ) use_resize_tracks = 1;
2102 if( trk->track_h != max_h ) use_resize_tracks = 1;
2106 if( !has_deinterlace && max_h > 2*DVD_HEIGHT ) use_deinterlace = 1;
2107 Labels *labels = mwindow->edl->labels;
2108 use_label_chapters = labels && labels->first ? 1 : 0;
2110 MWindow::create_aspect_ratio(w, h, max_w, max_h);
2111 if( w == DVD_WIDE_ASPECT_WIDTH && h == DVD_WIDE_ASPECT_HEIGHT )
2112 use_wide_aspect = 1;
2113 if( tracks->recordable_audio_tracks() == DVD_WIDE_CHANNELS )