confirm prefs update, fix bg_pixmap sz, plugin layout tweaks
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / render.C
index 7bfb1f768beee8bf890ea537f187264684522a8b..57e724aeda3b5ae5f691feb6836c924542ade1ec 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * CINELERRA
  * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
 /*
  * CINELERRA
  * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
@@ -50,6 +49,7 @@
 #include "language.h"
 #include "loadmode.h"
 #include "localsession.h"
 #include "language.h"
 #include "loadmode.h"
 #include "localsession.h"
+#include "mainerror.h"
 #include "mainprogress.h"
 #include "mainsession.h"
 #include "mainundo.h"
 #include "mainprogress.h"
 #include "mainsession.h"
 #include "mainundo.h"
@@ -96,15 +96,6 @@ int RenderItem::handle_event()
        return 1;
 }
 
        return 1;
 }
 
-
-
-
-
-
-
-
-
-
 RenderProgress::RenderProgress(MWindow *mwindow, Render *render)
  : Thread(1, 0, 0)
 {
 RenderProgress::RenderProgress(MWindow *mwindow, Render *render)
  : Thread(1, 0, 0)
 {
@@ -124,14 +115,12 @@ RenderProgress::~RenderProgress()
 void RenderProgress::run()
 {
        Thread::disable_cancel();
 void RenderProgress::run()
 {
        Thread::disable_cancel();
-       while(1)
-       {
-               if(render->total_rendered != last_value)
-               {
+       for( ;; ) {
+               if( render->total_rendered != last_value ) {
                        render->progress->update(render->total_rendered);
                        last_value = render->total_rendered;
 
                        render->progress->update(render->total_rendered);
                        last_value = render->total_rendered;
 
-                       if(mwindow) mwindow->preferences_thread->update_rates();
+                       if( mwindow ) mwindow->preferences_thread->update_rates();
                }
 
                Thread::enable_cancel();
                }
 
                Thread::enable_cancel();
@@ -167,11 +156,8 @@ int MainPackageRenderer::get_result()
 
 void MainPackageRenderer::set_result(int value)
 {
 
 void MainPackageRenderer::set_result(int value)
 {
-       if(value)
+       if( value )
                render->result = value;
                render->result = value;
-
-
-
 }
 
 void MainPackageRenderer::set_progress(int64_t value)
 }
 
 void MainPackageRenderer::set_progress(int64_t value)
@@ -186,7 +172,7 @@ void MainPackageRenderer::set_progress(int64_t value)
 //printf("MainPackageRenderer::set_progress %d %ld %f\n", __LINE__, (long)value, frames_per_second);
 
 // If non interactive, print progress out
 //printf("MainPackageRenderer::set_progress %d %ld %f\n", __LINE__, (long)value, frames_per_second);
 
 // If non interactive, print progress out
-       if(!render->progress)
+       if( !render->progress )
                render->show_progress();
 
        render->counter_lock->unlock();
                render->show_progress();
 
        render->counter_lock->unlock();
@@ -201,6 +187,18 @@ int MainPackageRenderer::progress_cancelled()
                render->batch_cancelled;
 }
 
                render->batch_cancelled;
 }
 
+void RenderAssets::clear()
+{
+       for( int i=size(); --i>=0; get(i)->remove_user() );
+       remove_all();
+}
+RenderAssets::RenderAssets()
+{
+}
+RenderAssets::~RenderAssets()
+{
+        clear();
+}
 
 Render::Render(MWindow *mwindow)
  : BC_DialogThread()
 
 Render::Render(MWindow *mwindow)
  : BC_DialogThread()
@@ -224,6 +222,7 @@ Render::Render(MWindow *mwindow)
 
 Render::~Render()
 {
 
 Render::~Render()
 {
+       stop_operation();
        close_window();
        delete package_lock;
        delete counter_lock;
        close_window();
        delete package_lock;
        delete counter_lock;
@@ -256,8 +255,7 @@ void Render::start_interactive()
 
 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs)
 {
 
 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs)
 {
-       if(!thread->running())
-       {
+       if( !thread->running() ) {
                mode = Render::BATCH;
                batch_cancelled = 0;
                this->jobs = jobs;
                mode = Render::BATCH;
                batch_cancelled = 0;
                this->jobs = jobs;
@@ -297,9 +295,9 @@ BC_Window* Render::new_gui()
        batch_cancelled = 0;
        result = 0;
 
        batch_cancelled = 0;
        result = 0;
 
-       if(mode == Render::INTERACTIVE) {
+       if( mode == Render::INTERACTIVE ) {
 // Fix the asset for rendering
 // Fix the asset for rendering
-               if(!asset) asset = new Asset;
+               if( !asset ) asset = new Asset;
                load_defaults(asset);
                check_asset(mwindow->edl, *asset);
                int px = mwindow->gui->get_pop_cursor_x(1);
                load_defaults(asset);
                check_asset(mwindow->edl, *asset);
                int px = mwindow->gui->get_pop_cursor_x(1);
@@ -314,7 +312,7 @@ BC_Window* Render::new_gui()
 
 void Render::handle_done_event(int result)
 {
 
 void Render::handle_done_event(int result)
 {
-       if(!result) {
+       if( !result ) {
                mwindow->edl->session->render_beep = beep;
                // add to recentlist only on OK
                render_window->render_format->path_recent->
                mwindow->edl->session->render_beep = beep;
                // add to recentlist only on OK
                render_window->render_format->path_recent->
@@ -334,15 +332,24 @@ void Render::handle_close_event(int result)
                err_msg = _("zero render range");
                result = 1;
        }
                err_msg = _("zero render range");
                result = 1;
        }
+       if( !result && !asset->audio_data && !asset->video_data ) {
+               err_msg = _("no audio or video in render asset format\n");
+               result = 1;
+       }
+       EDL *edl = mwindow->edl;
+       if( !result && use_labels && !edl->labels->first ) {
+               eprintf(_("render file per label and no labels\n"));
+               result = 1;
+       }
        if( !result && asset->video_data ) {
        if( !result && asset->video_data ) {
-               double frame_rate = mwindow->edl->session->frame_rate;
+               double frame_rate = edl->session->frame_rate;
                if( frame_rate > 0 && render_range+1e-3 < 1./frame_rate ) {
                        err_msg = _("Video data and range less than 1 frame");
                        result = 1;
                }
        }
        if( !result && asset->audio_data ) {
                if( frame_rate > 0 && render_range+1e-3 < 1./frame_rate ) {
                        err_msg = _("Video data and range less than 1 frame");
                        result = 1;
                }
        }
        if( !result && asset->audio_data ) {
-               double sample_rate = mwindow->edl->session->sample_rate;
+               double sample_rate = edl->session->sample_rate;
                if( sample_rate > 0 && render_range+1e-6 < 1./sample_rate ) {
                        err_msg = _("Audio data and range less than 1 sample");
                        result = 1;
                if( sample_rate > 0 && render_range+1e-6 < 1./sample_rate ) {
                        err_msg = _("Audio data and range less than 1 sample");
                        result = 1;
@@ -350,7 +357,7 @@ void Render::handle_close_event(int result)
        }
        if( !result && File::is_image_render(asset->format) ) {
                if( asset->video_data ) {
        }
        if( !result && File::is_image_render(asset->format) ) {
                if( asset->video_data ) {
-                       double frames = render_range * mwindow->edl->session->frame_rate;
+                       double frames = render_range * edl->session->frame_rate;
                        if( !EQUIV(frames, 1.) ) {
                                err_msg = _("Image format and not 1 frame");
                                result = 1;
                        if( !EQUIV(frames, 1.) ) {
                                err_msg = _("Image format and not 1 frame");
                                result = 1;
@@ -361,6 +368,7 @@ void Render::handle_close_event(int result)
                        result = 1;
                }
        }
                        result = 1;
                }
        }
+
        if( err_msg ) {
                int cx, cy;
                mwindow->gui->get_abs_cursor(cx, cy, 1);
        if( err_msg ) {
                int cx, cy;
                mwindow->gui->get_abs_cursor(cx, cy, 1);
@@ -370,7 +378,7 @@ void Render::handle_close_event(int result)
                error_box.run_window();
        }
 
                error_box.run_window();
        }
 
-       if(!result) {
+       if( !result ) {
 // Check the asset format for errors.
                FormatCheck format_check(asset);
                if( format_check.check_format() )
 // Check the asset format for errors.
                FormatCheck format_check(asset);
                if( format_check.check_format() )
@@ -385,9 +393,9 @@ void Render::handle_close_event(int result)
 //PRINT_TRACE
 
        if( !result ) {
 //PRINT_TRACE
 
        if( !result ) {
-               if(debug) printf("Render::handle_close_event %d\n", __LINE__);
-               if(!result) start_render();
-               if(debug) printf("Render::handle_close_event %d\n", __LINE__);
+               if( debug ) printf("Render::handle_close_event %d\n", __LINE__);
+               if( !result ) start_render();
+               if( debug ) printf("Render::handle_close_event %d\n", __LINE__);
        }
 //PRINT_TRACE
 }
        }
 //PRINT_TRACE
 }
@@ -396,8 +404,7 @@ void Render::handle_close_event(int result)
 
 void Render::stop_operation()
 {
 
 void Render::stop_operation()
 {
-       if(thread->Thread::running())
-       {
+       if( thread->Thread::running() ) {
                batch_cancelled = 1;
 // Wait for completion
                completion->lock("Render::stop_operation");
                batch_cancelled = 1;
 // Wait for completion
                completion->lock("Render::stop_operation");
@@ -407,38 +414,33 @@ void Render::stop_operation()
 
 int Render::check_asset(EDL *edl, Asset &asset)
 {
 
 int Render::check_asset(EDL *edl, Asset &asset)
 {
-       if(asset.video_data &&
+       if( asset.video_data &&
                edl->tracks->playable_video_tracks() &&
                edl->tracks->playable_video_tracks() &&
-               File::renders_video(&asset))
-       {
+               File::renders_video(&asset) ) {
                asset.video_data = 1;
                asset.layers = 1;
                asset.width = edl->session->output_w;
                asset.height = edl->session->output_h;
                asset.interlace_mode = edl->session->interlace_mode;
        }
                asset.video_data = 1;
                asset.layers = 1;
                asset.width = edl->session->output_w;
                asset.height = edl->session->output_h;
                asset.interlace_mode = edl->session->interlace_mode;
        }
-       else
-       {
+       else {
                asset.video_data = 0;
                asset.layers = 0;
        }
 
                asset.video_data = 0;
                asset.layers = 0;
        }
 
-       if(asset.audio_data &&
+       if( asset.audio_data &&
                edl->tracks->playable_audio_tracks() &&
                edl->tracks->playable_audio_tracks() &&
-               File::renders_audio(&asset))
-       {
+               File::renders_audio(&asset) ) {
                asset.audio_data = 1;
                asset.channels = edl->session->audio_channels;
        }
                asset.audio_data = 1;
                asset.channels = edl->session->audio_channels;
        }
-       else
-       {
+       else {
                asset.audio_data = 0;
                asset.channels = 0;
        }
 
                asset.audio_data = 0;
                asset.channels = 0;
        }
 
-       if(!asset.audio_data &&
-               !asset.video_data)
-       {
+       if( !asset.audio_data &&
+               !asset.video_data ) {
                return 1;
        }
        return 0;
                return 1;
        }
        return 0;
@@ -459,21 +461,21 @@ void Render::start_progress()
 {
        char filename[BCTEXTLEN];
        char string[BCTEXTLEN];
 {
        char filename[BCTEXTLEN];
        char string[BCTEXTLEN];
-       FileSystem fs;
-
        progress_max = packages->get_progress_max();
 
        progress_timer->update();
        last_eta = 0;
        progress_max = packages->get_progress_max();
 
        progress_timer->update();
        last_eta = 0;
-       if(mwindow)
-       {
+       if( mwindow ) {
 // Generate the progress box
 // Generate the progress box
+               FileSystem fs;
                fs.extract_name(filename, default_asset->path);
                sprintf(string, _("Rendering %s..."), filename);
 
 // Don't bother with the filename since renderfarm defeats the meaning
                fs.extract_name(filename, default_asset->path);
                sprintf(string, _("Rendering %s..."), filename);
 
 // Don't bother with the filename since renderfarm defeats the meaning
+               mwindow->gui->lock_window("Render::start_progress");
                progress = mwindow->mainprogress->start_progress(_("Rendering..."),
                        progress_max);
                progress = mwindow->mainprogress->start_progress(_("Rendering..."),
                        progress_max);
+               mwindow->gui->unlock_window();
                render_progress = new RenderProgress(mwindow, this);
                render_progress->start();
        }
                render_progress = new RenderProgress(mwindow, this);
                render_progress->start();
        }
@@ -481,8 +483,7 @@ void Render::start_progress()
 
 void Render::stop_progress()
 {
 
 void Render::stop_progress()
 {
-       if(progress)
-       {
+       if( progress ) {
                char string[BCTEXTLEN], string2[BCTEXTLEN];
                delete render_progress;
                progress->get_time(string);
                char string[BCTEXTLEN], string2[BCTEXTLEN];
                delete render_progress;
                progress->get_time(string);
@@ -491,7 +492,7 @@ void Render::stop_progress()
                delete progress;
 
                sprintf(string2, _("Rendering took %s"), string);
                delete progress;
 
                sprintf(string2, _("Rendering took %s"), string);
-               mwindow->gui->lock_window("");
+               mwindow->gui->lock_window("Render::stop_progress");
                mwindow->gui->show_message(string2);
                mwindow->gui->update_default_message();
                mwindow->gui->stop_hourglass();
                mwindow->gui->show_message(string2);
                mwindow->gui->update_default_message();
                mwindow->gui->stop_hourglass();
@@ -503,7 +504,7 @@ void Render::stop_progress()
 void Render::show_progress()
 {
        int64_t current_eta = progress_timer->get_scaled_difference(1000);
 void Render::show_progress()
 {
        int64_t current_eta = progress_timer->get_scaled_difference(1000);
-       if (current_eta - last_eta < 1000 ) return;
+       if( current_eta - last_eta < 1000  ) return;
        double eta = !total_rendered ? 0 :
                current_eta / 1000. * (progress_max / (double)total_rendered - 1.);
        char string[BCTEXTLEN];  Units::totext(string, eta, TIME_HMS2);
        double eta = !total_rendered ? 0 :
                current_eta / 1000. * (progress_max / (double)total_rendered - 1.);
        char string[BCTEXTLEN];  Units::totext(string, eta, TIME_HMS2);
@@ -535,8 +536,7 @@ void Render::create_filename(char *path,
        int len = strlen(default_path);
        char printf_string[BCTEXTLEN];
 
        int len = strlen(default_path);
        char printf_string[BCTEXTLEN];
 
-       for(i = 0, j = 0; i < number_start; i++, j++)
-       {
+       for( i=0, j=0; i<number_start; ++i, ++j ) {
                printf_string[j] = default_path[i];
        }
 
                printf_string[j] = default_path[i];
        }
 
@@ -546,8 +546,7 @@ void Render::create_filename(char *path,
        i += total_digits;
 
 // Copy remainder of string
        i += total_digits;
 
 // Copy remainder of string
-       for( ; i < len; i++, j++)
-       {
+       for( ; i<len; ++i, ++j ) {
                printf_string[j] = default_path[i];
        }
        printf_string[j] = 0;
                printf_string[j] = default_path[i];
        }
        printf_string[j] = 0;
@@ -573,17 +572,15 @@ void Render::get_starting_number(char *path,
        ptr2 = strrchr(path, '/');
 
 // Search for first 0 after last /.
        ptr2 = strrchr(path, '/');
 
 // Search for first 0 after last /.
-       if(ptr2)
+       if( ptr2 )
                ptr = strchr(ptr2, '0');
 
                ptr = strchr(ptr2, '0');
 
-       if(ptr && isdigit(*ptr))
-       {
+       if( ptr && isdigit(*ptr) ) {
                number_start = ptr - path;
 
 // Store the first number
                char *ptr2 = number_text;
                number_start = ptr - path;
 
 // Store the first number
                char *ptr2 = number_text;
-               while(isdigit(*ptr))
-                       *ptr2++ = *ptr++;
+               while( isdigit(*ptr) ) *ptr2++ = *ptr++;
                *ptr2++ = 0;
                current_number = atol(number_text);
                total_digits = strlen(number_text);
                *ptr2++ = 0;
                current_number = atol(number_text);
                total_digits = strlen(number_text);
@@ -591,8 +588,7 @@ void Render::get_starting_number(char *path,
 
 
 // No number found or number not long enough
 
 
 // No number found or number not long enough
-       if(total_digits < min_digits)
-       {
+       if( total_digits < min_digits ) {
                current_number = 1;
                number_start = len;
                total_digits = min_digits;
                current_number = 1;
                number_start = len;
                total_digits = min_digits;
@@ -647,6 +643,11 @@ int Render::save_defaults(Asset *asset)
        return 0;
 }
 
        return 0;
 }
 
+void Render::update_assets()
+{
+       if( packages )
+               packages->get_asset_list(assets);
+}
 
 static void run_script(const char *script, const char *arg)
 {
 
 static void run_script(const char *script, const char *arg)
 {
@@ -661,6 +662,7 @@ RenderThread::RenderThread(MWindow *mwindow, Render *render)
 {
        this->mwindow = mwindow;
        this->render = render;
 {
        this->mwindow = mwindow;
        this->render = render;
+       render_frames = 0;
 }
 
 RenderThread::~RenderThread()
 }
 
 RenderThread::~RenderThread()
@@ -672,14 +674,10 @@ void RenderThread::render_single(int test_overwrite, Asset *asset, EDL *edl,
        int strategy, int range_type)
 {
 // Total length in seconds
        int strategy, int range_type)
 {
 // Total length in seconds
-       double total_length;
+       double total_length = 0;
        RenderFarmServer *farm_server = 0;
        RenderFarmServer *farm_server = 0;
-       FileSystem fs;
-       const int debug = 0;
 
        render->in_progress = 1;
 
        render->in_progress = 1;
-
-
        render->default_asset = asset;
        render->progress = 0;
        render->result = 0;
        render->default_asset = asset;
        render->progress = 0;
        render->result = 0;
@@ -724,146 +722,94 @@ void RenderThread::render_single(int test_overwrite, Asset *asset, EDL *edl,
        render->result = render->check_asset(command->get_edl(),
                *render->default_asset);
 
        render->result = render->check_asset(command->get_edl(),
                *render->default_asset);
 
-       if(!render->result)
-       {
+       if( !render->result ) {
 // Get total range to render
                render->total_start = command->start_position;
                render->total_end = command->end_position;
                total_length = render->total_end - render->total_start;
 
 // Nothing to render
 // Get total range to render
                render->total_start = command->start_position;
                render->total_end = command->end_position;
                total_length = render->total_end - render->total_start;
 
 // Nothing to render
-               if(EQUIV(total_length, 0))
-               {
+               if( EQUIV(total_length, 0) ) {
                        render->result = 1;
                }
        }
 
                        render->result = 1;
                }
        }
 
+       render_frames = render->default_asset->frame_rate * total_length;
+
 // Generate packages
 // Generate packages
-       if(!render->result)
-       {
+       if( !render->result ) {
 // Stop background rendering
 // Stop background rendering
-               if(mwindow) mwindow->stop_brender();
+               if( mwindow ) mwindow->stop_brender();
 
 
+               FileSystem fs;
                fs.complete_path(render->default_asset->path);
 
                fs.complete_path(render->default_asset->path);
 
-               render->result = render->packages->create_packages(mwindow,
-                       command->get_edl(),
-                       render->preferences,
-                       strategy,
-                       render->default_asset,
-                       render->total_start,
-                       render->total_end,
-                       test_overwrite);
+               render->result = render->packages->create_packages(mwindow, command->get_edl(),
+                       render->preferences, strategy, render->default_asset,
+                       render->total_start, render->total_end, test_overwrite);
        }
 
        render->total_rendered = 0;
 
        }
 
        render->total_rendered = 0;
 
-       if(!render->result)
-       {
+       if( !render->result &&
+           ( strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM ) ) {
 // Start dispatching external jobs
 // Start dispatching external jobs
-               if(mwindow)
-               {
+               if( mwindow ) {
                        mwindow->gui->lock_window("Render::render 1");
                        mwindow->gui->show_message(_("Starting render farm"));
                        mwindow->gui->start_hourglass();
                        mwindow->gui->unlock_window();
                }
                        mwindow->gui->lock_window("Render::render 1");
                        mwindow->gui->show_message(_("Starting render farm"));
                        mwindow->gui->start_hourglass();
                        mwindow->gui->unlock_window();
                }
-               else
-               {
+               else {
                        printf("Render::render: starting render farm\n");
                }
 
                        printf("Render::render: starting render farm\n");
                }
 
-               if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
-               {
-                       farm_server = new RenderFarmServer(mwindow,
-                               render->packages,
-                               render->preferences,
-                               1,
-                               &render->result,
-                               &render->total_rendered,
-                               render->counter_lock,
-                               render->default_asset,
-                               command->get_edl(),
-                               0);
-                       render->result = farm_server->start_clients();
-
-                       if(render->result)
-                       {
-                               if(mwindow)
-                               {
-                                       mwindow->gui->lock_window("Render::render 2");
-                                       mwindow->gui->show_message(_("Failed to start render farm"),
-                                               mwindow->theme->message_error);
-                                       mwindow->gui->stop_hourglass();
-                                       mwindow->gui->unlock_window();
-                               }
-                               else
-                               {
-                                       printf("Render::render: Failed to start render farm\n");
-                               }
+               farm_server = new RenderFarmServer(mwindow, render->packages,
+                       render->preferences, 1, &render->result,
+                       &render->total_rendered, render->counter_lock,
+                       render->default_asset, command->get_edl(), 0);
+               render->result = farm_server->start_clients();
+
+               if( render->result ) {
+                       if( mwindow ) {
+                               mwindow->gui->lock_window("Render::render 2");
+                               mwindow->gui->show_message(_("Failed to start render farm"),
+                                       mwindow->theme->message_error);
+                               mwindow->gui->stop_hourglass();
+                               mwindow->gui->unlock_window();
+                       }
+                       else {
+                               printf("Render::render: Failed to start render farm\n");
                        }
                }
        }
 
 // Perform local rendering
 
                        }
                }
        }
 
 // Perform local rendering
 
-
-       if(!render->result)
-       {
+       render->assets.clear();
+       if( !render->result ) {
                render->start_progress();
 
                render->start_progress();
 
-
-
-
                MainPackageRenderer package_renderer(render);
                render->result = package_renderer.initialize(mwindow,
                                command->get_edl(),   // Copy of master EDL
                                render->preferences,
                                render->default_asset);
 
                MainPackageRenderer package_renderer(render);
                render->result = package_renderer.initialize(mwindow,
                                command->get_edl(),   // Copy of master EDL
                                render->preferences,
                                render->default_asset);
 
-
-
-
-
-
-
-               while(!render->result)
-               {
+               while( !render->result ) {
+                       int fps = strategy == SINGLE_PASS_FARM ?
+                               package_renderer.frames_per_second : 0;
 // Get unfinished job
 // Get unfinished job
-                       RenderPackage *package;
-
-                       if(strategy == SINGLE_PASS_FARM)
-                       {
-                               package = render->packages->get_package(
-                                       package_renderer.frames_per_second,
-                                       -1,
-                                       1);
-                       }
-                       else
-                       {
-                               package = render->packages->get_package(0, -1, 1);
-                       }
-
+                       RenderPackage *package = render->packages->get_package(fps, -1, 1);
 // Exit point
 // Exit point
-                       if(!package)
-                       {
-                               break;
-                       }
+                       if( !package ) break;
 
 
-                       if(package_renderer.render_package(package))
+                       if( package_renderer.render_package(package) )
                                render->result = 1;
                                render->result = 1;
-
-
                } // file_number
 
                } // file_number
 
-
-
 printf("Render::render_single: Session finished.\n");
 
 printf("Render::render_single: Session finished.\n");
 
-
-
-
-
                if( strategy == SINGLE_PASS_FARM ||
                    strategy == FILE_PER_LABEL_FARM ) {
                        if( !render->progress ) {
                if( strategy == SINGLE_PASS_FARM ||
                    strategy == FILE_PER_LABEL_FARM ) {
                        if( !render->progress ) {
@@ -876,95 +822,55 @@ printf("Render::render_single: Session finished.\n");
                        render->result |= render->packages->packages_are_done();
                }
 
                        render->result |= render->packages->packages_are_done();
                }
 
-if(debug) printf("Render::render %d\n", __LINE__);
-
 // Notify of error
 // Notify of error
-               if(render->result &&
-                       (!render->progress || !render->progress->is_cancelled()) &&
-                       !render->batch_cancelled)
-               {
-if(debug) printf("Render::render %d\n", __LINE__);
-                       if(mwindow)
-                       {
-if(debug) printf("Render::render %d\n", __LINE__);
+               if( render->result && !render->batch_cancelled &&
+                   (!render->progress || !render->progress->is_cancelled()) ) {
+                       if( mwindow ) {
                                int cx, cy;
                                mwindow->gui->get_abs_cursor(cx, cy, 1);
                                ErrorBox error_box(_(PROGRAM_NAME ": Error"), cx, cy);
                                error_box.create_objects(_("Error rendering data."));
                                error_box.raise_window();
                                error_box.run_window();
                                int cx, cy;
                                mwindow->gui->get_abs_cursor(cx, cy, 1);
                                ErrorBox error_box(_(PROGRAM_NAME ": Error"), cx, cy);
                                error_box.create_objects(_("Error rendering data."));
                                error_box.raise_window();
                                error_box.run_window();
-if(debug) printf("Render::render %d\n", __LINE__);
                        }
                        }
-                       else
-                       {
+                       else {
                                printf("Render::render: Error rendering data\n");
                        }
                }
                                printf("Render::render: Error rendering data\n");
                        }
                }
-if(debug) printf("Render::render %d\n", __LINE__);
 
 // Delete the progress box
                render->stop_progress();
 
 // Delete the progress box
                render->stop_progress();
-
-if(debug) printf("Render::render %d\n", __LINE__);
+               render->update_assets();
        }
 
        }
 
-
 // Paste all packages into timeline if desired
 
 // Paste all packages into timeline if desired
 
-       if(!render->result &&
-               render->load_mode != LOADMODE_NOTHING &&
-               mwindow &&
-               render->mode != Render::BATCH)
-       {
-if(debug) printf("Render::render %d\n", __LINE__);
+       if( !render->result && mwindow &&
+           render->load_mode != LOADMODE_NOTHING &&
+           render->mode != Render::BATCH ) {
                mwindow->gui->lock_window("Render::render 3");
                mwindow->gui->lock_window("Render::render 3");
-if(debug) printf("Render::render %d\n", __LINE__);
 
                mwindow->undo->update_undo_before();
 
                mwindow->undo->update_undo_before();
-
-if(debug) printf("Render::render %d\n", __LINE__);
-
-
-               ArrayList<Indexable*> *assets = render->packages->get_asset_list();
-if(debug) printf("Render::render %d\n", __LINE__);
-               if(render->load_mode == LOADMODE_PASTE)
+               if( render->load_mode == LOADMODE_PASTE )
                        mwindow->clear(0);
                        mwindow->clear(0);
-if(debug) printf("Render::render %d\n", __LINE__);
-               mwindow->load_assets(assets, -1, render->load_mode, 0, 0,
+               mwindow->load_assets(&render->assets,
+                       -1, render->load_mode, 0, 0,
                        mwindow->edl->session->labels_follow_edits,
                        mwindow->edl->session->plugins_follow_edits,
                        mwindow->edl->session->autos_follow_edits,
                        0); // overwrite
                        mwindow->edl->session->labels_follow_edits,
                        mwindow->edl->session->plugins_follow_edits,
                        mwindow->edl->session->autos_follow_edits,
                        0); // overwrite
-if(debug) printf("Render::render %d\n", __LINE__);
-               for(int i = 0; i < assets->size(); i++)
-                       assets->get(i)->Garbage::remove_user();
-               delete assets;
-if(debug) printf("Render::render %d\n", __LINE__);
-
-
                mwindow->save_backup();
                mwindow->save_backup();
-if(debug) printf("Render::render %d\n", __LINE__);
                mwindow->undo->update_undo_after(_("render"), LOAD_ALL);
                mwindow->undo->update_undo_after(_("render"), LOAD_ALL);
-if(debug) printf("Render::render %d\n", __LINE__);
                mwindow->update_plugin_guis();
                mwindow->update_plugin_guis();
-if(debug) printf("Render::render %d\n", __LINE__);
                mwindow->gui->update(1, FORCE_REDRAW, 1, 1, 1, 1, 0);
                mwindow->gui->update(1, FORCE_REDRAW, 1, 1, 1, 1, 0);
-if(debug) printf("Render::render %d\n", __LINE__);
                mwindow->sync_parameters(CHANGE_ALL);
                mwindow->sync_parameters(CHANGE_ALL);
-if(debug) printf("Render::render %d\n", __LINE__);
                mwindow->gui->unlock_window();
 
                mwindow->gui->unlock_window();
 
-
                mwindow->awindow->gui->async_update_assets();
                mwindow->awindow->gui->async_update_assets();
-
-if(debug) printf("Render::render %d\n", __LINE__);
        }
 
        }
 
-if(debug) printf("Render::render %d\n", __LINE__);
-
 // Disable hourglass
 // Disable hourglass
-       if(mwindow)
-       {
+       if( mwindow ) {
                mwindow->gui->lock_window("Render::render 3");
                mwindow->gui->stop_hourglass();
                mwindow->gui->unlock_window();
                mwindow->gui->lock_window("Render::render 3");
                mwindow->gui->stop_hourglass();
                mwindow->gui->unlock_window();
@@ -972,9 +878,9 @@ if(debug) printf("Render::render %d\n", __LINE__);
 
 //printf("Render::render 110\n");
 // Need to restart because brender always stops before render.
 
 //printf("Render::render 110\n");
 // Need to restart because brender always stops before render.
-       if(mwindow)
+       if( mwindow )
                mwindow->restart_brender();
                mwindow->restart_brender();
-       if(farm_server) delete farm_server;
+       if( farm_server ) delete farm_server;
        delete command;
        delete audio_cache;
        delete video_cache;
        delete command;
        delete audio_cache;
        delete video_cache;
@@ -983,102 +889,85 @@ if(debug) printf("Render::render %d\n", __LINE__);
 
        render->packages = 0;
        render->in_progress = 0;
 
        render->packages = 0;
        render->in_progress = 0;
-if(debug) printf("Render::render %d\n", __LINE__);
 }
 
 void RenderThread::run()
 {
 }
 
 void RenderThread::run()
 {
+       char *script = 0;
+       Timer render_timer;
+
        if( mwindow )
                render->preferences->copy_from(mwindow->preferences);
 
        if( mwindow )
                render->preferences->copy_from(mwindow->preferences);
 
-       if(render->mode == Render::INTERACTIVE)
-       {
+       if( render->mode == Render::INTERACTIVE ) {
                render_single(1, render->asset, mwindow->edl,
                        render->get_strategy(), render->range_type);
        }
        else
                render_single(1, render->asset, mwindow->edl,
                        render->get_strategy(), render->range_type);
        }
        else
-       if(render->mode == Render::BATCH)
-       {
-// PRINT_TRACE
-// printf("RenderThread::run %d %d %d\n",
-// __LINE__,
-// render->jobs->total,
-// render->result);
-               for(int i = 0; i < render->jobs->total && !render->result; i++)
-               {
-//PRINT_TRACE
+       if( render->mode == Render::BATCH ) {
+               for( int i=0; i<render->jobs->total && !render->result; ++i ) {
                        BatchRenderJob *job = render->jobs->values[i];
                        BatchRenderJob *job = render->jobs->values[i];
-//PRINT_TRACE
-                       if(job->enabled)
-                       {
-                               if( *job->edl_path == '@' )
-                               {
-                                       run_script(job->edl_path+1, job->asset->path);
-                               }
-
-                               if(mwindow)
-                               {
-                                       mwindow->batch_render->update_active(i);
-                               }
-                               else
-                               {
-                                       printf("Render::run: %s\n", job->edl_path);
-                               }
-
-//PRINT_TRACE
-
-                               FileXML *file = new FileXML;
-                               EDL *edl = new EDL;
-                               edl->create_objects();
-                               file->read_from_file(job->edl_path);
-                               edl->load_xml(file, LOAD_ALL);
-//PRINT_TRACE
-                               render_single(0, job->asset, edl, job->get_strategy(), RANGE_BACKCOMPAT);
-
-//PRINT_TRACE
-                               edl->Garbage::remove_user();
-                               delete file;
-                               if(!render->result)
-                               {
-                                       if(mwindow)
-                                               mwindow->batch_render->update_done(i, 1, render->elapsed_time);
-                                       else
-                                       {
-                                               char string[BCTEXTLEN];
-                                               render->elapsed_time =
-                                                       (double)render->progress_timer->get_scaled_difference(1);
-                                               Units::totext(string,
-                                                       render->elapsed_time,
-                                                       TIME_HMS2);
-                                               printf("Render::run: done in %s\n", string);
-                                       }
+                       if( !job->enabled ) continue;
+                       if( mwindow )
+                               mwindow->batch_render->update_active(i);
+                       else
+                               printf("Render::run: %s\n", job->edl_path);
+
+                       FileXML *file = new FileXML;
+                       EDL *edl = new EDL;
+                       edl->create_objects();
+                       file->read_from_file(job->edl_path);
+                       edl->load_xml(file, LOAD_ALL);
+                       delete file;
+
+                       render_single(0, job->asset, edl, job->get_strategy(), RANGE_BACKCOMPAT);
+                       if( !render->result ) {
+                               if( !i )
+                                       script = job->create_script(edl, &render->assets);
+                               if( mwindow )
+                                       mwindow->batch_render->update_done(i, 1, render->elapsed_time);
+                               else {
+                                       char string[BCTEXTLEN];
+                                       render->elapsed_time =
+                                               (double)render->progress_timer->get_scaled_difference(1);
+                                       Units::totext(string, render->elapsed_time, TIME_HMS2);
+                                       printf("Render::run: done in %s\n", string);
                                }
                                }
+                       }
+                       else {
+                               if( mwindow )
+                                       mwindow->batch_render->update_active(-1);
                                else
                                else
-                               {
-                                       if(mwindow)
-                                               mwindow->batch_render->update_active(-1);
-                                       else
-                                               printf("Render::run: failed\n");
-                               }
+                                       printf("Render::run: failed\n");
                        }
                        }
-//PRINT_TRACE
                }
                }
-
-               if(mwindow)
-               {
+               if( mwindow ) {
                        mwindow->batch_render->update_active(-1);
                        mwindow->batch_render->update_done(-1, 0, 0);
                }
        }
        render->completion->unlock();
 
                        mwindow->batch_render->update_active(-1);
                        mwindow->batch_render->update_done(-1, 0, 0);
                }
        }
        render->completion->unlock();
 
+       if( !render->result ) {
+               double render_time = render_timer.get_difference() / 1000.0;
+               double render_rate = render_time > 0 ? render_frames / render_time : 0;
+               printf("** rendered %jd frames in %0.3f secs, %0.3f fps\n",
+                       render_frames, render_time, render_rate);
+       }
+
        if( render->mode == Render::INTERACTIVE && render->beep )
                mwindow->beep(3000., 1.5, 0.5);
        if( render->mode == Render::INTERACTIVE && render->beep )
                mwindow->beep(3000., 1.5, 0.5);
+
+       if( script ) {
+               if( !render->result )
+                       run_script(script, 0);
+               delete [] script;
+       }
 }
 
 
 }
 
 
-#define WIDTH 480
-#define HEIGHT 480
+#define WIDTH xS(480)
+#define HEIGHT yS(480)
 
 
 RenderWindow::RenderWindow(MWindow *mwindow,
 
 
 RenderWindow::RenderWindow(MWindow *mwindow,
@@ -1121,13 +1010,15 @@ void RenderWindow::load_profile(int profile_slot)
 
 void RenderWindow::create_objects()
 {
 
 void RenderWindow::create_objects()
 {
-       int x = 10, y = 10;
+       int xs10 = xS(10), xs20 = xS(20);
+       int ys10 = yS(10), ys20 = yS(20), ys25 = yS(25), ys30 = yS(30);
+       int x = xs10, y = ys10;
        lock_window("RenderWindow::create_objects");
        lock_window("RenderWindow::create_objects");
-       add_subwindow(new BC_Title(x, y,
-               (char*)(render->use_labels ?
+       add_subwindow(file_format = new BC_Title(x, y,
+               (render->use_labels ?
                        _("Select the first file to render to:") :
                        _("Select a file to render to:"))));
                        _("Select the first file to render to:") :
                        _("Select a file to render to:"))));
-       y += 25;
+       y += ys25;
 
        render_format = new RenderFormat(mwindow, this, asset);
        render_format->create_objects(x, y,
 
        render_format = new RenderFormat(mwindow, this, asset);
        render_format->create_objects(x, y,
@@ -1140,38 +1031,38 @@ void RenderWindow::create_objects()
        if( is_image )
                render->range_type = RANGE_1FRAME;
 
        if( is_image )
                render->range_type = RANGE_1FRAME;
 
-       int x1 = x + title->get_w() + 20, y1 = y;
+       int x1 = x + title->get_w() + xs20, y1 = y;
        add_subwindow(rangeproject = new RenderRangeProject(this,
                render->range_type == RANGE_PROJECT, x1, y));
        int x2 = x1 + rangeproject->get_w();
        add_subwindow(rangeproject = new RenderRangeProject(this,
                render->range_type == RANGE_PROJECT, x1, y));
        int x2 = x1 + rangeproject->get_w();
-       y += 20;
+       y += ys20;
        add_subwindow(rangeselection = new RenderRangeSelection(this,
                render->range_type == RANGE_SELECTION, x1, y));
        int x3 = x1 + rangeselection->get_w();
        if( x2 < x3 ) x2 = x3;
        add_subwindow(rangeselection = new RenderRangeSelection(this,
                render->range_type == RANGE_SELECTION, x1, y));
        int x3 = x1 + rangeselection->get_w();
        if( x2 < x3 ) x2 = x3;
-       y += 20;
+       y += ys20;
        add_subwindow(rangeinout = new RenderRangeInOut(this,
                render->range_type == RANGE_INOUT, x1, y));
        x3 = x1 + rangeinout->get_w();
        if( x2 < x3 ) x2 = x3;
        add_subwindow(rangeinout = new RenderRangeInOut(this,
                render->range_type == RANGE_INOUT, x1, y));
        x3 = x1 + rangeinout->get_w();
        if( x2 < x3 ) x2 = x3;
-       y += 20;
+       y += ys20;
        add_subwindow(range1frame = new RenderRange1Frame(this,
                render->range_type == RANGE_1FRAME, x1, y));
        x3 = x1 + range1frame->get_w();
        if( x2 < x3 ) x2 = x3;
        add_subwindow(range1frame = new RenderRange1Frame(this,
                render->range_type == RANGE_1FRAME, x1, y));
        x3 = x1 + range1frame->get_w();
        if( x2 < x3 ) x2 = x3;
-       y += 30;
+       y += ys30;
        if( is_image )
                enable_render_range(0);
 
        if( is_image )
                enable_render_range(0);
 
-       x1 = x2 + 20;
+       x1 = x2 + xs20;
        render->beep = mwindow->edl->session->render_beep;
        add_subwindow(beep_on_done = new RenderBeepOnDone(this, x1, y1));
 
        renderprofile = new RenderProfile(mwindow, this, x, y, 1);
        renderprofile->create_objects();
        render->beep = mwindow->edl->session->render_beep;
        add_subwindow(beep_on_done = new RenderBeepOnDone(this, x1, y1));
 
        renderprofile = new RenderProfile(mwindow, this, x, y, 1);
        renderprofile->create_objects();
-       y += 70;
+       y += yS(70);
 
 
-       loadmode = new LoadMode(mwindow, this, x, y, &render->load_mode, 1);
+       loadmode = new LoadMode(mwindow, this, x, y, &render->load_mode);
        loadmode->create_objects();
 
        add_subwindow(new BC_OKButton(this));
        loadmode->create_objects();
 
        add_subwindow(new BC_OKButton(this));
@@ -1302,7 +1193,6 @@ void RenderFormat::update_format()
        FormatTools::update_format();
        RenderWindow *render_window = (RenderWindow *)window;
        if( render_window->is_hidden() ) return;
        FormatTools::update_format();
        RenderWindow *render_window = (RenderWindow *)window;
        if( render_window->is_hidden() ) return;
-
        int is_image = File::is_image_render(asset->format);
        if( is_image ) {
                render_window->update_range_type(RANGE_1FRAME);
        int is_image = File::is_image_render(asset->format);
        if( is_image ) {
                render_window->update_range_type(RANGE_1FRAME);
@@ -1311,6 +1201,15 @@ void RenderFormat::update_format()
        else
                render_window->enable_render_range(1);
 }
        else
                render_window->enable_render_range(1);
 }
+int RenderFormat::handle_event()
+{
+       RenderWindow *render_window = (RenderWindow *)window;
+       render_window->file_format->update(
+               (render_window->render->use_labels ?
+                       _("Select the first file to render to:") :
+                       _("Select a file to render to:")));
+       return 1;
+}
 
 RenderBeepOnDone::RenderBeepOnDone(RenderWindow *rwindow, int x, int y)
  : BC_CheckBox(x, y, rwindow->render->beep, _("Beep on done"))
 
 RenderBeepOnDone::RenderBeepOnDone(RenderWindow *rwindow, int x, int y)
  : BC_CheckBox(x, y, rwindow->render->beep, _("Beep on done"))