#include "file.h"
#include "filesystem.h"
#include "filexml.h"
+#include "indexable.h"
#include "keyframe.h"
#include "keys.h"
#include "labels.h"
#include "language.h"
+#include "localsession.h"
#include "mainerror.h"
#include "mainundo.h"
#include "mainsession.h"
#include "transportque.h"
#include "vframe.h"
-// Farmed is not present if not preferences->use_renderfarm
+#include "dvdcreate.h"
+#include "bdcreate.h"
+
int BatchRenderThread::column_widths[] = { 42, 42, 42, 222, 222, 150 };
const char *BatchRenderThread::column_titles[] = {
N_("Enabled"), N_("Labeled"), N_("Farmed"), N_("Output"), N_("EDL"), N_("Elapsed")
int BatchRenderMenuItem::handle_event()
{
- mwindow->batch_render->start();
+ mwindow->batch_render->start(1, 1);
return 1;
}
-
-BatchRenderJob::BatchRenderJob(Preferences *preferences, int labeled, int farmed)
+BatchRenderJob::BatchRenderJob(const char *tag,
+ Preferences *preferences, int labeled, int farmed)
{
+ this->tag = tag;
this->preferences = preferences;
this->labeled = labeled;
this->farmed = farmed >= 0 ? farmed : preferences->use_renderfarm;
elapsed = 0;
}
+BatchRenderJob::BatchRenderJob(Preferences *preferences, int labeled, int farmed)
+ : BatchRenderJob("JOB", preferences, labeled, farmed)
+{
+}
+
BatchRenderJob::~BatchRenderJob()
{
asset->Garbage::remove_user();
elapsed = 0;
}
+BatchRenderJob *BatchRenderJob::copy()
+{
+ BatchRenderJob *t = new BatchRenderJob(tag, preferences, labeled, farmed);
+ t->copy_from(this);
+ return t;
+}
+
void BatchRenderJob::load(FileXML *file)
{
int result = 0;
enabled = file->tag.get_property("ENABLED", enabled);
farmed = file->tag.get_property("FARMED", farmed);
- labeled = file->tag.get_property("STRATEGY", labeled);
+ labeled = file->tag.get_property("LABELED", labeled);
edl_path[0] = 0;
file->tag.get_property("EDL_PATH", edl_path);
elapsed = file->tag.get_property("ELAPSED", elapsed);
void BatchRenderJob::save(FileXML *file)
{
+ char end_tag[BCSTRLEN]; end_tag[0] = '/';
+ strcpy(&end_tag[1], file->tag.get_title());
file->tag.set_property("ENABLED", enabled);
file->tag.set_property("FARMED", farmed);
file->tag.set_property("LABELED", labeled);
defaults.save_string(string);
file->append_text(string);
free(string);
- file->tag.set_title("/JOB");
+ file->tag.set_title(end_tag);
file->append_tag();
file->append_newline();
}
+char *BatchRenderJob::create_script(EDL *edl, ArrayList<Indexable *> *idxbls)
+{
+ return 0;
+}
+
int BatchRenderJob::get_strategy()
{
-// if set, overrides farmed, labeled
- int use_renderfarm = farmed && preferences->use_renderfarm ? 1 : 0;
- return Render::get_strategy(use_renderfarm, labeled);
+ return Render::get_strategy(farmed, labeled);
}
warn = 1;
render = 0;
batch_path[0] = 0;
-}
-
-BatchRenderThread::BatchRenderThread()
- : BC_DialogThread()
-{
- mwindow = 0;
- current_job = 0;
- rendering_job = -1;
- is_rendering = 0;
- default_job = 0;
- boot_defaults = 0;
- preferences = 0;
- warn = 1;
- render = 0;
- batch_path[0] = 0;
+ do_farmed = 0;
+ do_labeled = 0;
}
BatchRenderThread::~BatchRenderThread()
close_window();
delete boot_defaults;
delete preferences;
+ delete default_job;
delete render;
}
jobs.remove_all_objects();
}
+void BatchRenderThread::start(int do_farmed, int do_labeled)
+{
+ this->do_farmed = do_farmed;
+ this->do_labeled = do_labeled;
+ BC_DialogThread::start();
+}
+
void BatchRenderThread::handle_close_event(int result)
{
// Save settings
{
current_start = 0.0;
current_end = 0.0;
- default_job = new BatchRenderJob(mwindow->preferences);
+ default_job = new BatchRenderJob(mwindow->preferences, 0, -1);
load_jobs(batch_path, mwindow->preferences);
load_defaults(mwindow->defaults);
this->gui = new BatchRenderGUI(mwindow, this,
warn = file.tag.get_property("WARN", 1);
}
else if( file.tag.title_is("JOB") ) {
- BatchRenderJob *job = new BatchRenderJob(preferences);
+ BatchRenderJob *job = new BatchRenderJob(preferences, 0,0);
+ jobs.append(job);
+ job->load(&file);
+ }
+ else if( file.tag.title_is("DVD_JOB") ) {
+ DVD_BatchRenderJob *job = new DVD_BatchRenderJob(preferences, 0,0,0,0);
+ jobs.append(job);
+ job->load(&file);
+ }
+ else if( file.tag.title_is("BD_JOB") ) {
+ BD_BatchRenderJob *job = new BD_BatchRenderJob(preferences, 0,0);
jobs.append(job);
job->load(&file);
}
file.append_newline();
for( int i = 0; i < jobs.total; i++ ) {
- file.tag.set_title("JOB");
- jobs.values[i]->save(&file);
+ file.tag.set_title(jobs[i]->tag);
+ jobs[i]->save(&file);
}
file.tag.set_title("/JOBS");
file.append_tag();
for( int i = 0; i < BATCHRENDER_COLUMNS; i++ ) {
char string[BCTEXTLEN];
sprintf(string, "BATCHRENDER_COLUMN%d", i);
- list_width[i] = defaults->get(string, column_widths[i]);
+ list_width[i] = defaults->get(string, xS(column_widths[i]));
}
}
void BatchRenderThread::new_job()
{
- BatchRenderJob *result = new BatchRenderJob(mwindow->preferences);
- result->copy_from(get_current_job());
+ BatchRenderJob *result = get_current_job()->copy();
jobs.append(result);
current_job = jobs.total - 1;
gui->create_list(1);
return get_current_job()->edl_path;
}
+int BatchRenderThread::test_errmsg(BatchRenderWarnJobs &err_jobs, const char *msg, int *warn)
+{
+ int count = err_jobs.size();
+ if( !count ) return 0;
+ fprintf(stderr, msg, count);
+ char string[BCTEXTLEN], *sp = string, *ep = sp+sizeof(string)-1;
+ sp += snprintf(sp,ep-sp, msg,count);
+ for( int i=0; i<count; ++i ) {
+ int no = err_jobs[i].no;
+ const char *path = err_jobs[i].path;
+ fprintf(stderr, "%d: %s\n", no, path);
+ sp += snprintf(sp,ep-sp, "%d: %s\n", no, path);
+ }
+ sp += snprintf(sp,ep-sp, _("press cancel to abandon batch render"));
+ mwindow->show_warning(warn, string);
+ if( mwindow->wait_warning() ) {
+ gui->button_enable();
+ }
+ return 1;
+}
// Test EDL files for existence
int BatchRenderThread::test_edl_files()
{
- int not_equiv = 0, ret = 0;
+ int ret = 0;
const char *path = 0;
+ BatchRenderWarnJobs not_equiv;
+ BatchRenderWarnJobs empty_jobs;
+ BatchRenderWarnJobs no_labels;
+ BatchRenderWarnJobs no_rendering;
for( int i=0; !ret && i<jobs.size(); ++i ) {
if( !jobs.values[i]->enabled ) continue;
- const char *path = jobs.values[i]->edl_path;
+ path = jobs[i]->edl_path;
int is_script = *path == '@' ? 1 : 0;
if( is_script ) ++path;
FILE *fp = fopen(path, "r");
if( fp ) {
- if( warn && mwindow && !is_script ) {
- fseek(fp, 0, SEEK_END);
- int64_t sz = ftell(fp);
- fseek(fp, 0, SEEK_SET);
- char *bfr = new char[sz+1];
- int64_t len = fread(bfr, 1, sz+1, fp);
- if( len == sz ) {
- FileXML file;
- XMLBuffer data(bfr, len, 0);
- file.set_shared_input(&data);
+ if( mwindow && !is_script ) {
+ char *bfr = 0; size_t sz = 0;
+ struct stat st;
+ if( !fstat(fileno(fp), &st) ) {
+ sz = st.st_size;
+ bfr = new char[sz+1];
+ if( fread(bfr, 1, sz+1, fp) != sz )
+ ret = 1;
+ else
+ bfr[sz] = 0;
+ }
+ if( !ret ) {
EDL *edl = new EDL; edl->create_objects();
- edl->load_xml(&file, LOAD_ALL);
+ XMLBuffer data(bfr, sz, 0);
+ { FileXML file;
+ file.set_shared_input(&data);
+ edl->load_xml(&file, LOAD_ALL); }
double pos = edl->equivalent_output(mwindow->edl);
- if( pos >= 0 ) ++not_equiv;
+ if( pos >= 0 )
+ not_equiv.add(i+1, path);
+ double length = edl->tracks->total_playable_length();
+ double start = edl->local_session->get_selectionstart(1);
+ if( start >= length )
+ empty_jobs.add(i+1, path);
+ if( jobs[i]->labeled && !edl->labels->first)
+ no_labels.add(i+1,path);
+ Asset *asset = jobs[i]->asset;
+ if( !asset->audio_data && !asset->video_data )
+ no_rendering.add(i+1,path);
edl->remove_user();
}
- else
- ret = 1;
delete [] bfr;
}
fclose(fp);
fprintf(stderr, "%s", string);
}
is_rendering = 0;
- }
- else if( warn && mwindow && not_equiv > 0 ) {
- fprintf(stderr, _("%d job EDLs do not match session edl\n"), not_equiv);
- char string[BCTEXTLEN], *sp = string;
- sp += sprintf(sp, _("%d job EDLs do not match session edl\n"),not_equiv);
- sp += sprintf(sp, _("press cancel to abandon batch render"));
- mwindow->show_warning(&warn, string);
- if( mwindow->wait_warning() ) {
- gui->button_enable();
- is_rendering = 0;
- ret = 1;
- }
- gui->warning->update(warn);
+ ret = 1;
}
+ if( !ret && warn && mwindow ) {
+ ret = test_errmsg(not_equiv, _("%d job EDLs do not match session edl\n"), &warn);
+ if( !warn ) gui->warning->update(0);
+ }
+ if( !ret && mwindow )
+ ret = test_errmsg(empty_jobs, _("%d job EDLs begin position beyond end of media\n"), 0);
+ if( !ret && mwindow )
+ ret = test_errmsg(no_rendering, _("%d job EDLs no audio or video in render asset format\n"), 0);
+ if( !ret && mwindow )
+ ret = test_errmsg(no_labels, _("%d job EDLs render file per label and no labels\n"), 0);
+ if( ret )
+ is_rendering = 0;
return ret;
}
command->playback_range_adjust_inout();
// Create test packages
- packages->create_packages(mwindow,
- command->get_edl(),
- preferences,
- job->get_strategy(),
- job->asset,
- command->start_position,
- command->end_position,
- 0);
+ int result = packages->create_packages(mwindow, command->get_edl(),
+ preferences, job->get_strategy(), job->asset,
+ command->start_position, command->end_position, 0);
+ if( !result )
+ packages->get_package_paths(paths);
// Append output paths allocated to total
- packages->get_package_paths(paths);
// Delete package harness
delete packages;
//PRINT_TRACE
// Initialize stuff which MWindow does.
signals->initialize("/tmp/cinelerra_batch%d.dmp");
+ boot_defaults = 0;
MWindow::init_defaults(boot_defaults, config_path);
load_defaults(boot_defaults);
preferences = new Preferences;
BatchRenderGUI::BatchRenderGUI(MWindow *mwindow,
BatchRenderThread *thread, int x, int y, int w, int h)
: BC_Window(_(PROGRAM_NAME ": Batch Render"),
- x, y, w, h, 730, 400, 1, 0, 1)
+ x, y, w, h, xS(730), yS(400), 1, 0, 1)
{
this->mwindow = mwindow;
this->thread = thread;
void BatchRenderGUI::create_objects()
{
+ int xs10 = xS(10), xs30 = xS(30), xs40 = xS(40);
+ int ys5 = yS(5), ys10 = yS(10), ys15 = yS(15);
lock_window("BatchRenderGUI::create_objects");
mwindow->theme->get_batchrender_sizes(this, get_w(), get_h());
create_list(0);
int x = mwindow->theme->batchrender_x1;
- int y = 5;
- int x1 = x, x2 = get_w()/2 + 10; // mwindow->theme->batchrender_x2;
- int y1 = 5, y2 = 5;
+ int y = ys5;
+ int x1 = x, x2 = get_w()/2 + xs30; // mwindow->theme->batchrender_x2;
+ int y1 = ys5, y2 = ys5;
// output file
add_subwindow(output_path_title = new BC_Title(x1, y1, _("Output path:")));
y1 += output_path_title->get_h() + mwindow->theme->widget_border;
format_tools = new BatchFormat(mwindow, this, thread->get_current_asset());
- format_tools->set_w(get_w() / 2);
+ format_tools->set_w(x2 - xs40);
BatchRenderJob *current_job = thread->get_current_job();
format_tools->create_objects(x1, y1, 1, 1, 1, 1, 0, 1, 0, 0,
- ¤t_job->labeled, 0);
- if( mwindow->preferences->use_renderfarm ) {
+ thread->do_labeled ? ¤t_job->labeled : 0, 0);
+ if( thread->do_labeled < 0 )
+ format_tools->labeled_files->disable();
+ if( thread->do_farmed ) {
use_renderfarm = new BatchRenderUseFarm(thread, x1, y1,
¤t_job->farmed);
add_subwindow(use_renderfarm);
- y1 += use_renderfarm->get_h() + 10;
+ y1 += use_renderfarm->get_h() + ys10;
+ if( thread->do_farmed < 0 )
+ use_renderfarm->disable();
}
+
// input EDL
add_subwindow(edl_path_title = new BC_Title(x2, y2, _("EDL Path:")));
y2 += edl_path_title->get_h() + mwindow->theme->widget_border;
x = x2; y = y2;
add_subwindow(edl_path_text = new BatchRenderEDLPath( thread,
- x, y, get_w()-x - 40, thread->get_current_edl()));
+ x, y, get_w()-x - xs40, thread->get_current_edl()));
x = x2 + edl_path_text->get_w();
add_subwindow(edl_path_browse = new BrowseButton(
mwindow->theme, this, edl_path_text, x, y, thread->get_current_edl(),
add_subwindow(batch_path = new BC_Title(x1, y, thread->batch_path, MEDIUMFONT));
y += list_title->get_h() + mwindow->theme->widget_border;
y1 = get_h();
- y1 -= 15 + BC_GenericButton::calculate_h() + mwindow->theme->widget_border;
+ y1 -= ys15 + BC_GenericButton::calculate_h() + mwindow->theme->widget_border;
add_subwindow(batch_list = new BatchRenderList(thread, x, y,
- get_w() - x - 10, y1 - y));
+ get_w() - x - xs10, y1 - y));
y += batch_list->get_h() + mwindow->theme->widget_border;
add_subwindow(start_button = new BatchRenderStart(thread, x, y));
x = get_w() / 2 - BC_GenericButton::calculate_w(this, _("Stop")) / 2;
add_subwindow(stop_button = new BatchRenderStop(thread, x, y));
- x = get_w() - BC_GenericButton::calculate_w(this, _("Close")) - 10;
+ x = get_w() - BC_GenericButton::calculate_w(this, _("Close")) - xs10;
add_subwindow(cancel_button = new BatchRenderCancel(thread, x, y));
show_window(1);
int BatchRenderGUI::resize_event(int w, int h)
{
+ int xs10 = xS(10), xs40 = xS(40);
+ int ys5 = yS(5), ys15 = yS(15);
mwindow->session->batchrender_w = w;
mwindow->session->batchrender_h = h;
mwindow->theme->get_batchrender_sizes(this, w, h);
int x = mwindow->theme->batchrender_x1;
- int y = 5;
- int x1 = x, x2 = get_w()/2 + 10; // mwindow->theme->batchrender_x2;
- int y1 = 5, y2 = 5;
+ int y = ys5;
+ int x1 = x, x2 = get_w()/2 + xs10; // mwindow->theme->batchrender_x2;
+ int y1 = ys5, y2 = ys5;
// output file
output_path_title->reposition_window(x1, y1);
y1 += output_path_title->get_h() + mwindow->theme->widget_border;
format_tools->reposition_window(x1, y1);
- if( use_renderfarm )
+ if( thread->do_farmed )
use_renderfarm->reposition_window(x1, y1);
// input EDL
x = x2, y = y2;
edl_path_title->reposition_window(x, y);
y += edl_path_title->get_h() + mwindow->theme->widget_border;
- edl_path_text->reposition_window(x, y, w - x - 40);
+ edl_path_text->reposition_window(x, y, w - x - xs40);
x += edl_path_text->get_w();
edl_path_browse->reposition_window(x, y);
y2 = y + edl_path_browse->get_h() + mwindow->theme->widget_border;
y += loadlist_batch->get_h() + mwindow->theme->widget_border;
warning->reposition_window(x2, y);
- y1 = 15 + BC_GenericButton::calculate_h() + mwindow->theme->widget_border;
+ y1 = ys15 + BC_GenericButton::calculate_h() + mwindow->theme->widget_border;
y2 = get_h() - y1 - batch_list->get_h();
y2 -= list_title->get_h() + mwindow->theme->widget_border;
x = mwindow->theme->batchrender_x1; y = y2;
list_title->reposition_window(x, y);
y += list_title->get_h() + mwindow->theme->widget_border;
- batch_list->reposition_window(x, y, w - x - 10, h - y - y1);
+ batch_list->reposition_window(x, y, w - x - xs10, h - y - y1);
y += batch_list->get_h() + mwindow->theme->widget_border;
start_button->reposition_window(x, y);
x = w / 2 - stop_button->get_w() / 2;
stop_button->reposition_window(x, y);
- x = w - cancel_button->get_w() - 10;
+ x = w - cancel_button->get_w() - xs10;
cancel_button->reposition_window(x, y);
return 1;
}
list_columns = 0;
list_titles[list_columns] = _(column_titles[ENABLED_COL]);
list_width[list_columns++] = thread->list_width[ENABLED_COL];
- list_titles[list_columns] = _(column_titles[LABELED_COL]);
- list_width[list_columns++] = thread->list_width[LABELED_COL];
- if( mwindow->preferences->use_renderfarm ) {
+ if( thread->do_labeled > 0 ) {
+ list_titles[list_columns] = _(column_titles[LABELED_COL]);
+ list_width[list_columns++] = thread->list_width[LABELED_COL];
+ }
+ if( thread->do_farmed > 0 ) {
list_titles[list_columns] = _(column_titles[FARMED_COL]);
list_width[list_columns++] = thread->list_width[FARMED_COL];
}
BatchRenderJob *job = thread->jobs.values[i];
char string[BCTEXTLEN];
BC_ListBoxItem *enabled = new BC_ListBoxItem(job->enabled ? "X" : " ");
- BC_ListBoxItem *labeled = new BC_ListBoxItem(job->labeled ? "X" : " ");
- BC_ListBoxItem *farmed = !mwindow->preferences->use_renderfarm ? 0 :
- new BC_ListBoxItem(job->farmed ? "X" : " ");
+ BC_ListBoxItem *labeled = thread->do_labeled > 0 ?
+ new BC_ListBoxItem(job->labeled ? "X" : " ") : 0;
+ BC_ListBoxItem *farmed = thread->do_farmed > 0 ?
+ new BC_ListBoxItem(job->farmed ? "X" : " ") : 0;
BC_ListBoxItem *out_path = new BC_ListBoxItem(job->asset->path);
BC_ListBoxItem *edl_path = new BC_ListBoxItem(job->edl_path);
BC_ListBoxItem *elapsed = new BC_ListBoxItem(!job->elapsed ? _("Unknown") :
Units::totext(string, job->elapsed, TIME_HMS2));
int col = 0;
list_items[col++].append(enabled);
- list_items[col++].append(labeled);
+ if( labeled ) list_items[col++].append(labeled);
if( farmed ) list_items[col++].append(farmed);
list_items[col++].append(out_path);
list_items[col++].append(edl_path);
list_items[col].append(elapsed);
if( i == thread->current_job ) {
enabled->set_selected(1);
- labeled->set_selected(1);
+ if( labeled ) labeled->set_selected(1);
if( farmed ) farmed->set_selected(1);
out_path->set_selected(1);
edl_path->set_selected(1);
}
if( i == thread->rendering_job ) {
enabled->set_color(RED);
- labeled->set_color(RED);
+ if( labeled ) labeled->set_color(RED);
if( farmed ) farmed->set_color(RED);
out_path->set_color(RED);
edl_path->set_color(RED);
void BatchRenderGUI::change_job()
{
BatchRenderJob *job = thread->get_current_job();
- format_tools->update(job->asset, &job->labeled);
- if( use_renderfarm ) use_renderfarm->update(&job->farmed);
+ format_tools->update(job->asset, thread->do_labeled ? &job->labeled : 0);
+ if( thread->do_farmed ) use_renderfarm->update(&job->farmed);
edl_path_text->update(job->edl_path);
}
char default_path[BCTEXTLEN];
sprintf(default_path, "~");
thread->mwindow->defaults->get("DEFAULT_BATCHLOADPATH", default_path);
- BC_FileBox filewindow(100, 100, default_path, _("Save Batch Render List"),
+ BC_FileBox filewindow(xS(100), yS(100), default_path,
+ _("Save Batch Render List"),
_("Enter a Batch Render filename to save as:"),
0, 0, 0, 0);
gui = &filewindow;
int result2 = filewindow.run_window();
if( !result2 ) {
strcpy(thread->batch_path, filewindow.get_submitted_path());
+ thread->gui->lock_window("BatchRenderSaveList::run");
thread->gui->batch_path->update(thread->batch_path);
+ thread->gui->unlock_window();
thread->mwindow->defaults->update("DEFAULT_BATCHLOADPATH", thread->batch_path);
thread->save_jobs(thread->batch_path);
}
char default_path[BCTEXTLEN];
sprintf(default_path, "~");
thread->mwindow->defaults->get("DEFAULT_BATCHLOADPATH", default_path);
- BC_FileBox filewindow(100, 100, default_path, _("Load Batch Render List"),
+ BC_FileBox filewindow(xS(100), yS(100), default_path, _("Load Batch Render List"),
_("Enter a Batch Render filename to load from:"),
0, 0, 0, 0);
gui = &filewindow;
int col_x = 0, changed = 1;
if( cursor_x < (col_x += thread->list_width[ENABLED_COL]) )
job->enabled = !job->enabled;
- else if( cursor_x < (col_x += thread->list_width[LABELED_COL]) )
+ else if( thread->do_labeled > 0 &&
+ cursor_x < (col_x += thread->list_width[LABELED_COL]) )
job->labeled = job->edl_path[0] != '@' ? !job->labeled : 0;
- else if( thread->gui->use_renderfarm &&
+ else if( thread->do_farmed > 0 &&
cursor_x < (col_x += thread->list_width[FARMED_COL]) )
job->farmed = job->edl_path[0] != '@' ? !job->farmed : 0;
else
int BatchRenderList::column_resize_event()
{
- for( int i = 0; i < BATCHRENDER_COLUMNS; i++ ) {
- thread->list_width[i] = get_column_width(i);
- }
+ int col = 0;
+ thread->list_width[ENABLED_COL] = get_column_width(col++);
+ if( thread->do_labeled > 0 )
+ thread->list_width[LABELED_COL] = get_column_width(col++);
+ if( thread->do_farmed > 0 )
+ thread->list_width[FARMED_COL] = get_column_width(col++);
+ thread->list_width[OUTPUT_COL] = get_column_width(col++);
+ thread->list_width[EDL_COL] = get_column_width(col++);
+ thread->list_width[ELAPSED_COL] = get_column_width(col);
return 1;
}