--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "asset.h"
+#include "batchrender.h"
+#include "bcdisplayinfo.h"
+#include "bcsignals.h"
+#include "confirmsave.h"
+#include "cstrdup.h"
+#include "bchash.h"
+#include "edits.h"
+#include "edit.h"
+#include "edl.h"
+#include "edlsession.h"
+#include "errorbox.h"
+#include "filesystem.h"
+#include "filexml.h"
+#include "keyframe.h"
+#include "keys.h"
+#include "labels.h"
+#include "language.h"
+#include "mainerror.h"
+#include "mainundo.h"
+#include "mainsession.h"
+#include "mutex.h"
+#include "mwindow.h"
+#include "mwindowgui.h"
+#include "packagedispatcher.h"
+#include "packagerenderer.h"
+#include "plugin.h"
+#include "pluginset.h"
+#include "preferences.h"
+#include "render.h"
+#include "theme.h"
+#include "tracks.h"
+#include "transportque.h"
+#include "vframe.h"
+
+
+static const char *list_titles[] =
+{
+ _("Enabled"),
+ _("Output"),
+ _("EDL"),
+ _("Elapsed")
+};
+
+static int list_widths[] =
+{
+ 50,
+ 100,
+ 200,
+ 100
+};
+
+BatchRenderMenuItem::BatchRenderMenuItem(MWindow *mwindow)
+ : BC_MenuItem(_("Batch Render..."), _("Shift-B"), 'B')
+{
+ set_shift(1);
+ this->mwindow = mwindow;
+}
+
+int BatchRenderMenuItem::handle_event()
+{
+ mwindow->batch_render->start();
+ return 1;
+}
+
+
+
+
+
+
+
+
+BatchRenderJob::BatchRenderJob(Preferences *preferences)
+{
+ this->preferences = preferences;
+ asset = new Asset;
+ edl_path[0] = 0;
+ strategy = 0;
+ enabled = 1;
+ elapsed = 0;
+}
+
+BatchRenderJob::~BatchRenderJob()
+{
+ asset->Garbage::remove_user();
+}
+
+void BatchRenderJob::copy_from(BatchRenderJob *src)
+{
+ asset->copy_from(src->asset, 0);
+ strcpy(edl_path, src->edl_path);
+ strategy = src->strategy;
+ enabled = src->enabled;
+ elapsed = 0;
+}
+
+void BatchRenderJob::load(FileXML *file)
+{
+ int result = 0;
+
+ edl_path[0] = 0;
+ file->tag.get_property("EDL_PATH", edl_path);
+ strategy = file->tag.get_property("STRATEGY", strategy);
+ enabled = file->tag.get_property("ENABLED", enabled);
+ elapsed = file->tag.get_property("ELAPSED", elapsed);
+ fix_strategy();
+
+ result = file->read_tag();
+ if(!result)
+ {
+ if(file->tag.title_is("ASSET"))
+ {
+ file->tag.get_property("SRC", asset->path);
+ asset->read(file, 0);
+// The compression parameters are stored in the defaults to reduce
+// coding maintenance. The defaults must now be stuffed into the XML for
+// unique storage.
+ BC_Hash defaults;
+ defaults.load_string(file->read_text());
+ asset->load_defaults(&defaults,
+ "",
+ 0,
+ 1,
+ 0,
+ 0,
+ 0);
+ }
+ }
+}
+
+void BatchRenderJob::save(FileXML *file)
+{
+ file->tag.set_property("EDL_PATH", edl_path);
+ file->tag.set_property("STRATEGY", strategy);
+ file->tag.set_property("ENABLED", enabled);
+ file->tag.set_property("ELAPSED", elapsed);
+ file->append_tag();
+ file->append_newline();
+ asset->write(file,
+ 0,
+ "");
+
+// The compression parameters are stored in the defaults to reduce
+// coding maintenance. The defaults must now be stuffed into the XML for
+// unique storage.
+ BC_Hash defaults;
+ asset->save_defaults(&defaults,
+ "",
+ 0,
+ 1,
+ 0,
+ 0,
+ 0);
+ char *string;
+ defaults.save_string(string);
+ file->append_text(string);
+ free(string);
+ file->tag.set_title("/JOB");
+ file->append_tag();
+ file->append_newline();
+}
+
+void BatchRenderJob::fix_strategy()
+{
+ strategy = Render::fix_strategy(strategy, preferences->use_renderfarm);
+}
+
+
+
+
+
+
+
+
+
+
+BatchRenderThread::BatchRenderThread(MWindow *mwindow)
+ : BC_DialogThread()
+{
+ this->mwindow = mwindow;
+ current_job = 0;
+ rendering_job = -1;
+ is_rendering = 0;
+ default_job = 0;
+ boot_defaults = 0;
+ preferences = 0;
+ render = 0;
+ file_entries = 0;
+}
+
+BatchRenderThread::BatchRenderThread()
+ : BC_DialogThread()
+{
+ mwindow = 0;
+ current_job = 0;
+ rendering_job = -1;
+ is_rendering = 0;
+ default_job = 0;
+ boot_defaults = 0;
+ preferences = 0;
+ render = 0;
+ file_entries = 0;
+}
+
+BatchRenderThread::~BatchRenderThread()
+{
+ close_window();
+ delete boot_defaults;
+ delete preferences;
+ delete render;
+ if( file_entries ) {
+ file_entries->remove_all_objects();
+ delete file_entries;
+ }
+}
+
+void BatchRenderThread::handle_close_event(int result)
+{
+// Save settings
+ char path[BCTEXTLEN];
+ path[0] = 0;
+ save_jobs(path);
+ save_defaults(mwindow->defaults);
+ delete default_job;
+ default_job = 0;
+ jobs.remove_all_objects();
+ if(file_entries)
+ {
+ file_entries->remove_all_objects();
+ delete file_entries;
+ file_entries = 0;
+ }
+}
+
+BC_Window* BatchRenderThread::new_gui()
+{
+ current_start = 0.0;
+ current_end = 0.0;
+ default_job = new BatchRenderJob(mwindow->preferences);
+
+
+ if(!file_entries)
+ {
+ file_entries = new ArrayList<BC_ListBoxItem*>;
+ FileSystem fs;
+ char string[BCTEXTLEN];
+ // Load current directory
+ fs.update(getcwd(string, BCTEXTLEN));
+ for(int i = 0; i < fs.total_files(); i++)
+ {
+ file_entries->append(
+ new BC_ListBoxItem(
+ fs.get_entry(i)->get_name()));
+ }
+ }
+
+ char path[BCTEXTLEN];
+ path[0] = 0;
+ load_jobs(path, mwindow->preferences);
+ load_defaults(mwindow->defaults);
+ this->gui = new BatchRenderGUI(mwindow,
+ this,
+ mwindow->session->batchrender_x,
+ mwindow->session->batchrender_y,
+ mwindow->session->batchrender_w,
+ mwindow->session->batchrender_h);
+ this->gui->create_objects();
+ return this->gui;
+}
+
+
+void BatchRenderThread::load_jobs(char *path, Preferences *preferences)
+{
+ FileXML file;
+ int result = 0;
+
+ jobs.remove_all_objects();
+ if(path[0])
+ file.read_from_file(path);
+ else
+ file.read_from_file(create_path(path));
+
+ while(!result)
+ {
+ if(!(result = file.read_tag()))
+ {
+ if(file.tag.title_is("JOB"))
+ {
+ BatchRenderJob *job;
+ jobs.append(job = new BatchRenderJob(preferences));
+ job->load(&file);
+ }
+ }
+ }
+}
+
+void BatchRenderThread::save_jobs(char *path)
+{
+ FileXML file;
+
+ for(int i = 0; i < jobs.total; i++)
+ {
+ file.tag.set_title("JOB");
+ jobs.values[i]->save(&file);
+ }
+
+ if(path[0])
+ file.write_to_file(path);
+ else
+ file.write_to_file(create_path(path));
+}
+
+void BatchRenderThread::load_defaults(BC_Hash *defaults)
+{
+ if(default_job)
+ {
+ default_job->asset->load_defaults(defaults,
+ "BATCHRENDER_",
+ 1,
+ 1,
+ 1,
+ 1,
+ 1);
+ default_job->fix_strategy();
+ }
+
+ for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
+ {
+ char string[BCTEXTLEN];
+ sprintf(string, "BATCHRENDER_COLUMN%d", i);
+ column_width[i] = defaults->get(string, list_widths[i]);
+ }
+}
+
+void BatchRenderThread::save_defaults(BC_Hash *defaults)
+{
+ if(default_job)
+ {
+ default_job->asset->save_defaults(defaults,
+ "BATCHRENDER_",
+ 1,
+ 1,
+ 1,
+ 1,
+ 1);
+ defaults->update("BATCHRENDER_STRATEGY", default_job->strategy);
+ }
+ for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
+ {
+ char string[BCTEXTLEN];
+ sprintf(string, "BATCHRENDER_COLUMN%d", i);
+ defaults->update(string, column_width[i]);
+ }
+// defaults->update("BATCHRENDER_JOB", current_job);
+ if(mwindow)
+ mwindow->save_defaults();
+ else
+ defaults->save();
+}
+
+char* BatchRenderThread::create_path(char *string)
+{
+ FileSystem fs;
+ sprintf(string, "%s", BCASTDIR);
+ fs.complete_path(string);
+ strcat(string, BATCH_PATH);
+ return string;
+}
+
+void BatchRenderThread::new_job()
+{
+ BatchRenderJob *result = new BatchRenderJob(mwindow->preferences);
+ result->copy_from(get_current_job());
+ jobs.append(result);
+ current_job = jobs.total - 1;
+ gui->create_list(1);
+ gui->change_job();
+}
+
+void BatchRenderThread::delete_job()
+{
+ if(current_job < jobs.total && current_job >= 0)
+ {
+ jobs.remove_object_number(current_job);
+ if(current_job > 0) current_job--;
+ gui->create_list(1);
+ gui->change_job();
+ }
+}
+
+void BatchRenderThread::use_current_edl()
+{
+// printf("BatchRenderThread::use_current_edl %d %p %s\n",
+// __LINE__,
+// mwindow->edl->path,
+// mwindow->edl->path);
+
+ strcpy(get_current_edl(), mwindow->edl->path);
+ gui->create_list(1);
+ gui->edl_path_text->update(get_current_edl());
+}
+
+void BatchRenderThread::update_selected_edl()
+{
+ FileXML xml_file;
+ char *path = get_current_edl();
+ EDL *edl = mwindow->edl;
+ edl->save_xml(&xml_file, path, 0, 0);
+ xml_file.terminate_string();
+ if( xml_file.write_to_file(path) ) {
+ char msg[BCTEXTLEN];
+ sprintf(msg, _("Unable to save: %s"), path);
+ MainError::show_error(msg);
+ }
+}
+
+BatchRenderJob* BatchRenderThread::get_current_job()
+{
+ BatchRenderJob *result;
+ if(current_job >= jobs.total || current_job < 0)
+ {
+ result = default_job;
+ }
+ else
+ {
+ result = jobs.values[current_job];
+ }
+ return result;
+}
+
+
+Asset* BatchRenderThread::get_current_asset()
+{
+ return get_current_job()->asset;
+}
+
+char* BatchRenderThread::get_current_edl()
+{
+ return get_current_job()->edl_path;
+}
+
+
+// Test EDL files for existence
+int BatchRenderThread::test_edl_files()
+{
+ for(int i = 0; i < jobs.total; i++)
+ {
+ if(jobs.values[i]->enabled)
+ {
+ const char *path = jobs.values[i]->edl_path;
+ if( *path == '@' ) ++path;
+ FILE *fd = fopen(path, "r");
+ if(!fd)
+ {
+ char string[BCTEXTLEN];
+ sprintf(string, _("EDL %s not found.\n"), jobs.values[i]->edl_path);
+ if(mwindow)
+ {
+ ErrorBox error_box(_(PROGRAM_NAME ": Error"),
+ mwindow->gui->get_abs_cursor_x(1),
+ mwindow->gui->get_abs_cursor_y(1));
+ error_box.create_objects(string);
+ error_box.run_window();
+ gui->button_enable();
+ }
+ else
+ {
+ fprintf(stderr,
+ "%s",
+ string);
+ }
+
+ is_rendering = 0;
+ return 1;
+ }
+ else
+ {
+ fclose(fd);
+ }
+ }
+ }
+ return 0;
+}
+
+void BatchRenderThread::calculate_dest_paths(ArrayList<char*> *paths,
+ Preferences *preferences)
+{
+ for(int i = 0; i < jobs.total; i++)
+ {
+ BatchRenderJob *job = jobs.values[i];
+ if(job->enabled && *job->edl_path != '@')
+ {
+ PackageDispatcher *packages = new PackageDispatcher;
+
+// Load EDL
+ TransportCommand *command = new TransportCommand;
+ FileXML *file = new FileXML;
+ file->read_from_file(job->edl_path);
+
+// Use command to calculate range.
+ command->command = NORMAL_FWD;
+ command->get_edl()->load_xml(file,
+ LOAD_ALL);
+ command->change_type = CHANGE_ALL;
+ command->set_playback_range();
+ command->playback_range_adjust_inout();
+
+// Create test packages
+ packages->create_packages(mwindow,
+ command->get_edl(),
+ preferences,
+ job->strategy,
+ job->asset,
+ command->start_position,
+ command->end_position,
+ 0);
+
+// Append output paths allocated to total
+ packages->get_package_paths(paths);
+
+// Delete package harness
+ delete packages;
+ delete command;
+ delete file;
+ }
+ }
+}
+
+
+void BatchRenderThread::start_rendering(char *config_path,
+ char *batch_path)
+{
+ BC_Hash *boot_defaults;
+ Preferences *preferences;
+ Render *render;
+ BC_Signals *signals = new BC_Signals;
+ // XXX the above stuff is leaked,
+//PRINT_TRACE
+// Initialize stuff which MWindow does.
+ signals->initialize();
+ MWindow::init_defaults(boot_defaults, config_path);
+ load_defaults(boot_defaults);
+ preferences = new Preferences;
+ preferences->load_defaults(boot_defaults);
+ MWindow::init_plugins(0, preferences);
+ char font_path[BCTEXTLEN];
+ strcpy(font_path, preferences->plugin_dir);
+ strcat(font_path, "/" FONT_SEARCHPATH);
+ BC_Resources::init_fontconfig(font_path);
+ BC_WindowBase::get_resources()->vframe_shm = 1;
+
+//PRINT_TRACE
+ load_jobs(batch_path, preferences);
+ save_jobs(batch_path);
+ save_defaults(boot_defaults);
+
+//PRINT_TRACE
+// Test EDL files for existence
+ if(test_edl_files()) return;
+
+//PRINT_TRACE
+
+// Predict all destination paths
+ ArrayList<char*> paths;
+ paths.set_array_delete();
+ calculate_dest_paths(&paths, preferences);
+
+//PRINT_TRACE
+ int result = ConfirmSave::test_files(0, &paths);
+ paths.remove_all_objects();
+// Abort on any existing file because it's so hard to set this up.
+ if(result) return;
+
+//PRINT_TRACE
+ render = new Render(0);
+//PRINT_TRACE
+ render->start_batches(&jobs,
+ boot_defaults,
+ preferences);
+//PRINT_TRACE
+}
+
+void BatchRenderThread::start_rendering()
+{
+ if(is_rendering) return;
+
+ is_rendering = 1;
+ char path[BCTEXTLEN];
+ path[0] = 0;
+ save_jobs(path);
+ save_defaults(mwindow->defaults);
+ gui->button_disable();
+
+// Test EDL files for existence
+ if(test_edl_files()) return;
+
+// Predict all destination paths
+ ArrayList<char*> paths;
+ calculate_dest_paths(&paths,
+ mwindow->preferences);
+
+// Test destination files for overwrite
+ int result = ConfirmSave::test_files(mwindow, &paths);
+ paths.remove_all_objects();
+
+// User cancelled
+ if(result)
+ {
+ is_rendering = 0;
+ gui->button_enable();
+ return;
+ }
+
+ mwindow->render->start_batches(&jobs);
+}
+
+void BatchRenderThread::stop_rendering()
+{
+ if(!is_rendering) return;
+ mwindow->render->stop_operation();
+ is_rendering = 0;
+}
+
+void BatchRenderThread::update_active(int number)
+{
+ gui->lock_window("BatchRenderThread::update_active");
+ if(number >= 0)
+ {
+ current_job = number;
+ rendering_job = number;
+ }
+ else
+ {
+ rendering_job = -1;
+ is_rendering = 0;
+ }
+ gui->create_list(1);
+ gui->unlock_window();
+}
+
+void BatchRenderThread::update_done(int number,
+ int create_list,
+ double elapsed_time)
+{
+ gui->lock_window("BatchRenderThread::update_done");
+ if(number < 0)
+ {
+ gui->button_enable();
+ }
+ else
+ {
+ jobs.values[number]->enabled = 0;
+ jobs.values[number]->elapsed = elapsed_time;
+ if(create_list) gui->create_list(1);
+ }
+ gui->unlock_window();
+}
+
+void BatchRenderThread::move_batch(int src, int dst)
+{
+ BatchRenderJob *src_job = jobs.values[src];
+ if(dst < 0) dst = jobs.total - 1;
+
+ if(dst != src)
+ {
+ for(int i = src; i < jobs.total - 1; i++)
+ jobs.values[i] = jobs.values[i + 1];
+// if(dst > src) dst--;
+ for(int i = jobs.total - 1; i > dst; i--)
+ jobs.values[i] = jobs.values[i - 1];
+ jobs.values[dst] = src_job;
+ gui->create_list(1);
+ }
+}
+
+
+
+
+
+
+
+BatchRenderGUI::BatchRenderGUI(MWindow *mwindow,
+ BatchRenderThread *thread,
+ int x,
+ int y,
+ int w,
+ int h)
+ : BC_Window(_(PROGRAM_NAME ": Batch Render"),
+ x,
+ y,
+ w,
+ h,
+ 50,
+ 50,
+ 1,
+ 0,
+ 1)
+{
+ this->mwindow = mwindow;
+ this->thread = thread;
+}
+
+BatchRenderGUI::~BatchRenderGUI()
+{
+ lock_window("BatchRenderGUI::~BatchRenderGUI");
+ delete format_tools;
+ unlock_window();
+}
+
+
+void BatchRenderGUI::create_objects()
+{
+ 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 = mwindow->theme->batchrender_x1;
+ int x2 = mwindow->theme->batchrender_x2;
+ //int x3 = mwindow->theme->batchrender_x3;
+ int y1 = y;
+ int y2;
+
+// output file
+ add_subwindow(output_path_title = new BC_Title(x1, y, _("Output path:")));
+ y += 20;
+ format_tools = new BatchFormat(mwindow,
+ this,
+ thread->get_current_asset());
+ format_tools->set_w(get_w() / 2);
+ format_tools->create_objects(x,
+ y,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ 1,
+ 0,
+ 0,
+ &thread->get_current_job()->strategy,
+ 0);
+
+ x2 = x;
+ y2 = y + 10;
+ x += format_tools->get_w();
+ y = y1;
+ x1 = x;
+ //x3 = x + 80;
+
+// input EDL
+ x = x1;
+ add_subwindow(edl_path_title = new BC_Title(x, y, _("EDL Path:")));
+ y += 20;
+ add_subwindow(edl_path_text = new BatchRenderEDLPath(
+ thread,
+ x,
+ y,
+ get_w() - x - 40,
+ thread->get_current_edl()));
+
+ x += edl_path_text->get_w();
+ add_subwindow(edl_path_browse = new BrowseButton(
+ mwindow, this, edl_path_text, x, y, thread->get_current_edl(),
+ _("Input EDL"), _("Select an EDL to load:"), 0));
+
+ x = x1;
+ y += 64;
+ update_selected_edl = new BatchRenderUpdateEDL(thread, x, y);
+ add_subwindow(update_selected_edl);
+ y += update_selected_edl->get_h() + mwindow->theme->widget_border;
+
+ add_subwindow(new_batch = new BatchRenderNew(thread,
+ x,
+ y));
+ x += new_batch->get_w() + 10;
+
+ add_subwindow(delete_batch = new BatchRenderDelete(thread,
+ x,
+ y));
+ x = new_batch->get_x();
+ y += new_batch->get_h() + mwindow->theme->widget_border;
+ use_current_edl = new BatchRenderCurrentEDL(thread, x, y);
+ add_subwindow(use_current_edl);
+ if( !mwindow->edl || !mwindow->edl->path[0] ) use_current_edl->disable();
+
+ savelist_batch = new BatchRenderSaveList(thread, x, y);
+ add_subwindow(savelist_batch);
+ x += savelist_batch->get_w() + 10;
+
+ loadlist_batch = new BatchRenderLoadList(thread, x, y);
+ add_subwindow(loadlist_batch);
+ x += loadlist_batch->get_w() + 10;
+
+ x = x2;
+ y = y2;
+ add_subwindow(list_title = new BC_Title(x, y, _("Batches to render:")));
+ y += 20;
+ add_subwindow(batch_list = new BatchRenderList(thread,
+ x,
+ y,
+ get_w() - x - 10,
+ get_h() - y - BC_GenericButton::calculate_h() - 15));
+
+ y += batch_list->get_h() + 10;
+ 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;
+ add_subwindow(cancel_button = new BatchRenderCancel(thread,
+ x,
+ y));
+
+ show_window(1);
+ unlock_window();
+}
+
+void BatchRenderGUI::button_disable()
+{
+ new_batch->disable();
+ delete_batch->disable();
+ use_current_edl->disable();
+ update_selected_edl->disable();
+}
+
+void BatchRenderGUI::button_enable()
+{
+ new_batch->enable();
+ delete_batch->enable();
+ if( mwindow->edl && mwindow->edl->path[0] )
+ use_current_edl->enable();
+ update_selected_edl->enable();
+}
+
+int BatchRenderGUI::resize_event(int w, int h)
+{
+ 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 = mwindow->theme->batchrender_x1;
+ int x2 = mwindow->theme->batchrender_x2;
+ //int x3 = mwindow->theme->batchrender_x3;
+ int y1 = y;
+ int y2;
+
+ output_path_title->reposition_window(x1, y);
+ y += 20;
+ format_tools->reposition_window(x, y);
+ x2 = x;
+ y2 = y + 10;
+ y = y1;
+ x += format_tools->get_w();
+ x1 = x;
+ //x3 = x + 80;
+
+ x = x1;
+ edl_path_title->reposition_window(x, y);
+ y += 20;
+ edl_path_text->reposition_window(x, y, w - x - 40);
+ x += edl_path_text->get_w();
+ edl_path_browse->reposition_window(x, y);
+
+ x = x1;
+// y += 30;
+// status_title->reposition_window(x, y);
+// x = x3;
+// status_text->reposition_window(x, y);
+// x = x1;
+// y += 30;
+// progress_bar->reposition_window(x, y, w - x - 10);
+
+ y += 30;
+ update_selected_edl->reposition_window(x, y);
+ y += update_selected_edl->get_h() + mwindow->theme->widget_border;
+ new_batch->reposition_window(x, y);
+ x += new_batch->get_w() + 10;
+ delete_batch->reposition_window(x, y);
+ x = new_batch->get_x();
+ y += new_batch->get_h() + mwindow->theme->widget_border;
+ use_current_edl->reposition_window(x, y);
+
+ x = x2;
+ y = y2;
+ int y_margin = get_h() - batch_list->get_h();
+ list_title->reposition_window(x, y);
+ y += 20;
+ batch_list->reposition_window(x, y, w - x - 10, h - y_margin);
+
+ y += batch_list->get_h() + 10;
+ 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;
+ cancel_button->reposition_window(x, y);
+ return 1;
+}
+
+int BatchRenderGUI::translation_event()
+{
+ mwindow->session->batchrender_x = get_x();
+ mwindow->session->batchrender_y = get_y();
+ return 1;
+}
+
+int BatchRenderGUI::close_event()
+{
+// Stop batch rendering
+ unlock_window();
+ thread->stop_rendering();
+ lock_window("BatchRenderGUI::close_event");
+ set_done(1);
+ return 1;
+}
+
+void BatchRenderGUI::create_list(int update_widget)
+{
+ for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
+ {
+ list_columns[i].remove_all_objects();
+ }
+
+ for(int i = 0; i < thread->jobs.total; i++)
+ {
+ BatchRenderJob *job = thread->jobs.values[i];
+ char string[BCTEXTLEN];
+ BC_ListBoxItem *enabled = new BC_ListBoxItem(job->enabled ?
+ (char*)"X" :
+ (char*)" ");
+ BC_ListBoxItem *item1 = new BC_ListBoxItem(job->asset->path);
+ BC_ListBoxItem *item2 = new BC_ListBoxItem(job->edl_path);
+ BC_ListBoxItem *item3;
+ if(job->elapsed)
+ item3 = new BC_ListBoxItem(
+ Units::totext(string,
+ job->elapsed,
+ TIME_HMS2));
+ else
+ item3 = new BC_ListBoxItem(_("Unknown"));
+ list_columns[0].append(enabled);
+ list_columns[1].append(item1);
+ list_columns[2].append(item2);
+ list_columns[3].append(item3);
+ if(i == thread->current_job)
+ {
+ enabled->set_selected(1);
+ item1->set_selected(1);
+ item2->set_selected(1);
+ item3->set_selected(1);
+ }
+ if(i == thread->rendering_job)
+ {
+ enabled->set_color(RED);
+ item1->set_color(RED);
+ item2->set_color(RED);
+ item3->set_color(RED);
+ }
+ }
+
+ if(update_widget)
+ {
+ batch_list->update(list_columns,
+ list_titles,
+ thread->column_width,
+ BATCHRENDER_COLUMNS,
+ batch_list->get_xposition(),
+ batch_list->get_yposition(),
+ batch_list->get_highlighted_item(), // Flat index of item cursor is over
+ 1, // set all autoplace flags to 1
+ 1);
+ }
+}
+
+void BatchRenderGUI::change_job()
+{
+ BatchRenderJob *job = thread->get_current_job();
+ format_tools->update(job->asset, &job->strategy);
+ edl_path_text->update(job->edl_path);
+}
+
+
+
+
+
+
+
+
+BatchFormat::BatchFormat(MWindow *mwindow,
+ BatchRenderGUI *gui,
+ Asset *asset)
+ : FormatTools(mwindow, gui, asset)
+{
+ this->gui = gui;
+ this->mwindow = mwindow;
+}
+
+BatchFormat::~BatchFormat()
+{
+}
+
+
+int BatchFormat::handle_event()
+{
+ gui->create_list(1);
+ return 1;
+}
+
+
+
+
+
+
+
+
+
+
+
+BatchRenderEDLPath::BatchRenderEDLPath(BatchRenderThread *thread,
+ int x,
+ int y,
+ int w,
+ char *text)
+ : BC_TextBox(x,
+ y,
+ w,
+ 1,
+ text)
+{
+ this->thread = thread;
+}
+
+
+int BatchRenderEDLPath::handle_event()
+{
+// Suggestions
+ calculate_suggestions(thread->file_entries);
+
+ strcpy(thread->get_current_edl(), get_text());
+ thread->gui->create_list(1);
+ return 1;
+}
+
+
+
+
+
+
+BatchRenderNew::BatchRenderNew(BatchRenderThread *thread,
+ int x,
+ int y)
+ : BC_GenericButton(x, y, _("New"))
+{
+ this->thread = thread;
+}
+
+int BatchRenderNew::handle_event()
+{
+ thread->new_job();
+ return 1;
+}
+
+BatchRenderDelete::BatchRenderDelete(BatchRenderThread *thread,
+ int x,
+ int y)
+ : BC_GenericButton(x, y, _("Delete"))
+{
+ this->thread = thread;
+}
+
+int BatchRenderDelete::handle_event()
+{
+ thread->delete_job();
+ return 1;
+}
+
+
+
+BatchRenderSaveList::BatchRenderSaveList(BatchRenderThread *thread,
+ int x,
+ int y)
+ : BC_GenericButton(x, y, _("Save List"))
+{
+ this->thread = thread;
+ set_tooltip(_("Save a Batch Render List"));
+ gui = 0;
+ startup_lock = new Mutex("BatchRenderSaveList::startup_lock");
+}
+
+BatchRenderSaveList::~BatchRenderSaveList()
+{
+ startup_lock->lock("BatchRenderSaveList::~BrowseButton");
+ if(gui)
+ {
+ gui->lock_window();
+ gui->set_done(1);
+ gui->unlock_window();
+ }
+ startup_lock->unlock();
+ Thread::join();
+ delete startup_lock;
+}
+
+int BatchRenderSaveList::handle_event()
+{
+ if(Thread::running())
+ {
+ if(gui)
+ {
+ gui->lock_window();
+ gui->raise_window();
+ gui->unlock_window();
+ }
+ return 1;
+ }
+ startup_lock->lock("BatchRenderSaveList::handle_event 1");
+ Thread::start();
+ startup_lock->lock("BatchRenderSaveList::handle_event 2");
+ startup_lock->unlock();
+ return 1;
+}
+
+void BatchRenderSaveList::run()
+{
+ char default_path[BCTEXTLEN];
+ sprintf(default_path, "~");
+ BC_FileBox filewindow(100,
+ 100,
+ this->thread->mwindow->defaults->get("DEFAULT_BATCHLOADPATH", default_path),
+ _("Save Batch Render List"),
+ _("Enter a Batch Render filename to save as:"),
+ 0,
+ 0,
+ 0,
+ 0);
+
+ gui = &filewindow;
+
+ startup_lock->unlock();
+ filewindow.create_objects();
+
+ int result2 = filewindow.run_window();
+
+ if(!result2)
+ {
+ this->thread->save_jobs(filewindow.get_submitted_path());
+ this->thread->mwindow->defaults->update("DEFAULT_BATCHLOADPATH", filewindow.get_submitted_path());
+ }
+
+ this->thread->gui->flush();
+ startup_lock->lock("BatchRenderLoadList::run");
+ gui = 0;
+ startup_lock->unlock();
+}
+
+int BatchRenderSaveList::keypress_event() {
+ if (get_keypress() == 's' ||
+ get_keypress() == 'S') return handle_event();
+ return 0;
+}
+
+
+
+
+BatchRenderLoadList::BatchRenderLoadList(BatchRenderThread *thread,
+ int x,
+ int y)
+ : BC_GenericButton(x, y, _("Load List")),
+ Thread()
+{
+ this->thread = thread;
+ set_tooltip(_("Load a previously saved Batch Render List"));
+ gui = 0;
+ startup_lock = new Mutex("BatchRenderLoadList::startup_lock");
+}
+
+BatchRenderLoadList::~BatchRenderLoadList()
+{
+ startup_lock->lock("BatchRenderLoadList::~BrowseButton");
+ if(gui)
+ {
+ gui->lock_window();
+ gui->set_done(1);
+ gui->unlock_window();
+ }
+ startup_lock->unlock();
+ Thread::join();
+ delete startup_lock;
+}
+
+int BatchRenderLoadList::handle_event()
+{
+ if(Thread::running())
+ {
+ if(gui)
+ {
+ gui->lock_window();
+ gui->raise_window();
+ gui->unlock_window();
+ }
+ return 1;
+ }
+ startup_lock->lock("BatchRenderLoadList::handle_event 1");
+ Thread::start();
+ startup_lock->lock("BatchRenderLoadList::handle_event 2");
+ startup_lock->unlock();
+ return 1;
+}
+
+void BatchRenderLoadList::run()
+{
+ char default_path[BCTEXTLEN];
+ sprintf(default_path, "~");
+ BC_FileBox filewindow(100,
+ 100,
+ this->thread->mwindow->defaults->get("DEFAULT_BATCHLOADPATH", default_path),
+ _("Load Batch Render List"),
+ _("Enter a Batch Render filename to load from:"),
+ 0,
+ 0,
+ 0,
+ 0);
+
+ gui = &filewindow;
+
+ startup_lock->unlock();
+ filewindow.create_objects();
+
+ int result2 = filewindow.run_window();
+
+ if(!result2)
+ {
+ this->thread->load_jobs(filewindow.get_submitted_path(),this->thread->mwindow->preferences);
+ this->thread->gui->create_list(1);
+ this->thread->mwindow->defaults->update("DEFAULT_BATCHLOADPATH", filewindow.get_submitted_path());
+ }
+
+ this->thread->gui->flush();
+ startup_lock->lock("BatchRenderLoadList::run");
+ gui = 0;
+ startup_lock->unlock();
+}
+
+int BatchRenderLoadList::keypress_event() {
+ if (get_keypress() == 'o' ||
+ get_keypress() == 'O') return handle_event();
+ return 0;
+}
+
+BatchRenderCurrentEDL::BatchRenderCurrentEDL(BatchRenderThread *thread,
+ int x,
+ int y)
+ : BC_GenericButton(x, y, _("Use Current EDL"))
+{
+ this->thread = thread;
+}
+
+int BatchRenderCurrentEDL::handle_event()
+{
+ thread->use_current_edl();
+ return 1;
+}
+
+BatchRenderUpdateEDL::BatchRenderUpdateEDL(BatchRenderThread *thread,
+ int x,
+ int y)
+ : BC_GenericButton(x, y, _("Save to EDL Path"))
+{
+ this->thread = thread;
+}
+
+int BatchRenderUpdateEDL::handle_event()
+{
+ thread->update_selected_edl();
+ return 1;
+}
+
+
+
+
+BatchRenderList::BatchRenderList(BatchRenderThread *thread,
+ int x,
+ int y,
+ int w,
+ int h)
+ : BC_ListBox(x,
+ y,
+ w,
+ h,
+ LISTBOX_TEXT,
+ thread->gui->list_columns,
+ list_titles,
+ thread->column_width,
+ BATCHRENDER_COLUMNS,
+ 0,
+ 0,
+ LISTBOX_SINGLE,
+ ICON_LEFT,
+ 1)
+{
+ this->thread = thread;
+ dragging_item = 0;
+ set_process_drag(0);
+}
+
+int BatchRenderList::handle_event()
+{
+ return 1;
+}
+
+int BatchRenderList::selection_changed()
+{
+ thread->current_job = get_selection_number(0, 0);
+ thread->gui->change_job();
+ if(get_cursor_x() < thread->column_width[0])
+ {
+ BatchRenderJob *job = thread->get_current_job();
+ job->enabled = !job->enabled;
+ thread->gui->create_list(1);
+ }
+ return 1;
+}
+
+int BatchRenderList::column_resize_event()
+{
+ for(int i = 0; i < BATCHRENDER_COLUMNS; i++)
+ {
+ thread->column_width[i] = get_column_width(i);
+ }
+ return 1;
+}
+
+int BatchRenderList::drag_start_event()
+{
+ if(BC_ListBox::drag_start_event())
+ {
+ dragging_item = 1;
+ return 1;
+ }
+
+ return 0;
+}
+
+int BatchRenderList::drag_motion_event()
+{
+ if(BC_ListBox::drag_motion_event())
+ {
+ return 1;
+ }
+ return 0;
+}
+
+int BatchRenderList::drag_stop_event()
+{
+ if(dragging_item)
+ {
+ int src = get_selection_number(0, 0);
+ int dst = get_highlighted_item();
+ if(src != dst)
+ {
+ thread->move_batch(src, dst);
+ }
+ BC_ListBox::drag_stop_event();
+ }
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+BatchRenderStart::BatchRenderStart(BatchRenderThread *thread,
+ int x,
+ int y)
+ : BC_GenericButton(x,
+ y,
+ _("Start"))
+{
+ this->thread = thread;
+}
+
+int BatchRenderStart::handle_event()
+{
+ thread->start_rendering();
+ return 1;
+}
+
+BatchRenderStop::BatchRenderStop(BatchRenderThread *thread,
+ int x,
+ int y)
+ : BC_GenericButton(x,
+ y,
+ _("Stop"))
+{
+ this->thread = thread;
+}
+
+int BatchRenderStop::handle_event()
+{
+ unlock_window();
+ thread->stop_rendering();
+ lock_window("BatchRenderStop::handle_event");
+ return 1;
+}
+
+
+BatchRenderCancel::BatchRenderCancel(BatchRenderThread *thread,
+ int x,
+ int y)
+ : BC_GenericButton(x,
+ y,
+ _("Close"))
+{
+ this->thread = thread;
+}
+
+int BatchRenderCancel::handle_event()
+{
+ unlock_window();
+ thread->stop_rendering();
+ lock_window("BatchRenderCancel::handle_event");
+ thread->gui->set_done(1);
+ return 1;
+}
+
+int BatchRenderCancel::keypress_event()
+{
+ if(get_keypress() == ESC)
+ {
+ unlock_window();
+ thread->stop_rendering();
+ lock_window("BatchRenderCancel::keypress_event");
+ thread->gui->set_done(1);
+ return 1;
+ }
+ return 0;
+}
+