r602: Fix baver's code... don't insert timecode when show_tc is not set
[cinelerra_cv/mob.git] / cinelerra / render.C
blobf0df0874164834117dfb0e798c454638158bfab3
1 #include "arender.h"
2 #include "asset.h"
3 #include "auto.h"
4 #include "batchrender.h"
5 #include "bcprogressbox.h"
6 #include "cache.h"
7 #include "clip.h"
8 #include "compresspopup.h"
9 #include "condition.h"
10 #include "confirmsave.h"
11 #include "cwindowgui.h"
12 #include "cwindow.h"
13 #include "defaults.h"
14 #include "edits.h"
15 #include "edl.h"
16 #include "edlsession.h"
17 #include "errorbox.h"
18 #include "file.h"
19 #include "filesystem.h"
20 #include "filexml.h"
21 #include "formatcheck.h"
22 #include "formatpopup.h"
23 #include "formattools.h"
24 #include "labels.h"
25 #include "language.h"
26 #include "loadmode.h"
27 #include "localsession.h"
28 #include "mainprogress.h"
29 #include "mainsession.h"
30 #include "mainundo.h"
31 #include "module.h"
32 #include "mutex.h"
33 #include "mwindowgui.h"
34 #include "mwindow.h"
35 #include "packagedispatcher.h"
36 #include "packagerenderer.h"
37 #include "patchbay.h"
38 #include "playabletracks.h"
39 #include "preferences.h"
40 #include "quicktime.h"
41 #include "renderfarm.h"
42 #include "render.h"
43 #include "statusbar.h"
44 #include "timebar.h"
45 #include "tracks.h"
46 #include "transportque.h"
47 #include "vedit.h"
48 #include "vframe.h"
49 #include "videoconfig.h"
50 #include "vrender.h"
52 #include <ctype.h>
53 #include <string.h>
57 RenderItem::RenderItem(MWindow *mwindow)
58  : BC_MenuItem(_("Render..."), "Shift+R", 'R')
60         this->mwindow = mwindow;
61         set_shift(1);
64 int RenderItem::handle_event() 
66         mwindow->render->start_interactive();
67         return 1;
79 RenderProgress::RenderProgress(MWindow *mwindow, Render *render)
80  : Thread()
82         this->mwindow = mwindow;
83         this->render = render;
84         last_value = 0;
85         Thread::set_synchronous(1);
88 RenderProgress::~RenderProgress()
90         Thread::cancel();
91         Thread::join();
95 void RenderProgress::run()
97         Thread::disable_cancel();
98         while(1)
99         {
100                 if(render->total_rendered != last_value)
101                 {
102                         render->progress->update(render->total_rendered);
103                         last_value = render->total_rendered;
104                 }
106                 Thread::enable_cancel();
107                 sleep(1);
108                 Thread::disable_cancel();
109         }
121 MainPackageRenderer::MainPackageRenderer(Render *render)
122  : PackageRenderer()
124         this->render = render;
129 MainPackageRenderer::~MainPackageRenderer()
134 int MainPackageRenderer::get_master()
136         return 1;
139 int MainPackageRenderer::get_result()
141         return render->result;
144 void MainPackageRenderer::set_result(int value)
146         if(value)
147                 render->result = value;
150 void MainPackageRenderer::set_progress(int64_t value)
152         render->counter_lock->lock("MainPackageRenderer::set_progress");
153         render->total_rendered += value;
155 // If non interactive, print progress out
156         if(!render->progress)
157         {
158                 int64_t current_eta = render->progress_timer->get_scaled_difference(1000);
159                 if(current_eta - render->last_eta > 1000)
160                 {
161                         double eta = 0;
164                         if(render->total_rendered)
165                         {
166                                 eta = current_eta /
167                                         1000 *
168                                         render->progress_max /
169                                         render->total_rendered -
170                                         current_eta /
171                                         1000;
172                         }
174                         char string[BCTEXTLEN];
175                         Units::totext(string, 
176                                 eta,
177                                 TIME_HMS2);
179                         printf("%d%% ETA: %s      \r", (int)(100 * 
180                                 (float)render->total_rendered / 
181                                         render->progress_max),
182                                 string);
183                         fflush(stdout);
184                         render->last_eta = current_eta;
185                 }
186         }
188         render->counter_lock->unlock();
191 int MainPackageRenderer::progress_cancelled()
193         return (render->progress && render->progress->is_cancelled()) || 
194                 render->batch_cancelled;
208 Render::Render(MWindow *mwindow)
209  : Thread(0, 0, 0)
211         this->mwindow = mwindow;
212         if(mwindow) plugindb = mwindow->plugindb;
213         in_progress = 0;
214         progress = 0;
215         preferences = 0;
216         elapsed_time = 0.0;
217         package_lock = new Mutex("Render::package_lock");
218         counter_lock = new Mutex("Render::counter_lock");
219         completion = new Condition(0, "Render::completion");
220         progress_timer = new Timer;
223 Render::~Render()
225         delete package_lock;
226         delete counter_lock;
227         delete completion;
228         if(preferences) delete preferences;
229         delete progress_timer;
232 void Render::start_interactive()
234         if(!Thread::running())
235         {
236                 mode = Render::INTERACTIVE;
237                 this->jobs = 0;
238                 batch_cancelled = 0;
239                 completion->reset();
240                 Thread::start();
241         }
242         else
243         {
244                 // raise the window if rendering hasn't started yet
245                 if (render_window && ! in_progress) {
246                         render_window->raise_window();
247                 }
248                 else {
249                         ErrorBox error_box(PROGRAM_NAME ": Error",
250                                            mwindow->gui->get_abs_cursor_x(1),
251                                            mwindow->gui->get_abs_cursor_y(1));
252                         error_box.create_objects("Already rendering");
253                         error_box.run_window();
254                 }
255         }
258 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs)
260         batch_cancelled = 0;
261         if(!Thread::running())
262         {
263                 mode = Render::BATCH;
264                 this->jobs = jobs;
265                 completion->reset();
266                 Thread::start();
267         }
268         else
269         {
270                 ErrorBox error_box(PROGRAM_NAME ": Error",
271                         mwindow->gui->get_abs_cursor_x(1),
272                         mwindow->gui->get_abs_cursor_y(1));
273                 error_box.create_objects("Already rendering");
274                 error_box.run_window();
275         }
278 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs,
279         Defaults *boot_defaults,
280         Preferences *preferences,
281         ArrayList<PluginServer*> *plugindb)
283         mode = Render::BATCH;
284         batch_cancelled = 0;
285         this->jobs = jobs;
286         this->preferences = preferences;
287         this->plugindb = plugindb;
289         completion->reset();
290         run();
291         this->preferences = 0;
294 void Render::stop_operation()
296         if(Thread::running())
297         {
298                 batch_cancelled = 1;
299 // Wait for completion
300                 completion->lock("Render::stop_operation");
301                 completion->reset();
302         }
306 void Render::run()
308         int format_error;
311         result = 0;
313         if(mode == Render::INTERACTIVE)
314         {
315 // Fix the asset for rendering
316                 Asset *asset = new Asset;
317                 load_defaults(asset);
318                 check_asset(mwindow->edl, *asset);
320 // Get format from user
321                 if(!result)
322                 {
323                         do
324                         {
325                                 format_error = 0;
326                                 result = 0;
328                                 {
329                                         render_window = new RenderWindow(mwindow, this, asset);
330                                         render_window->create_objects();
331                                         result = render_window->run_window();
332                                         if (! result) {
333                                                 // add to recentlist only on OK
334                                                 render_window->format_tools->path_recent->add_item(FILE_FORMAT_PREFIX(asset->format), asset->path);
335                                         }
336                                         delete render_window;
337                                         render_window = 0;
338                                 }
340                                 if(!result)
341                                 {
342 // Check the asset format for errors.
343                                         FormatCheck format_check(asset);
344                                         format_error = format_check.check_format();
345                                 }
346                         }while(format_error && !result);
347                 }
349                 save_defaults(asset);
350                 mwindow->save_defaults();
352                 if(!result) render(1, asset, mwindow->edl, strategy);
354                 delete asset;
355         }
356         else
357         if(mode == Render::BATCH)
358         {
359                 for(int i = 0; i < jobs->total && !result; i++)
360                 {
361                         BatchRenderJob *job = jobs->values[i];
362                         if(job->enabled)
363                         {
364                                 if(mwindow)
365                                 {
366                                         mwindow->batch_render->update_active(i);
367                                 }
368                                 else
369                                 {
370                                         printf("Render::run: %s\n", job->edl_path);
371                                 }
374                                 FileXML *file = new FileXML;
375                                 EDL *edl = new EDL;
376                                 edl->create_objects();
377                                 file->read_from_file(job->edl_path);
378                                 if(!plugindb && mwindow)
379                                         plugindb = mwindow->plugindb;
380                                 edl->load_xml(plugindb, file, LOAD_ALL);
382                                 render(0, job->asset, edl, job->strategy);
384                                 delete edl;
385                                 delete file;
386                                 if(!result)
387                                 {
388                                         if(mwindow)
389                                                 mwindow->batch_render->update_done(i, 1, elapsed_time);
390                                         else
391                                         {
392                                                 char string[BCTEXTLEN];
393                                                 elapsed_time = 
394                                                         (double)progress_timer->get_scaled_difference(1);
395                                                 Units::totext(string,
396                                                         elapsed_time,
397                                                         TIME_HMS2);
398                                                 printf("Render::run: done in %s\n", string);
399                                         }
400                                 }
401                                 else
402                                 {
403                                         if(mwindow)
404                                                 mwindow->batch_render->update_active(-1);
405                                         else
406                                                 printf("Render::run: failed\n");
407                                 }
408                         }
409                 }
411                 if(mwindow)
412                 {
413                         mwindow->batch_render->update_active(-1);
414                         mwindow->batch_render->update_done(-1, 0, 0);
415                 }
416         }
421 int Render::check_asset(EDL *edl, Asset &asset)
423         if(asset.video_data && 
424                 edl->tracks->playable_video_tracks() &&
425                 File::supports_video(asset.format))
426         {
427                 asset.video_data = 1;
428                 asset.layers = 1;
429                 asset.width = edl->session->output_w;
430                 asset.height = edl->session->output_h;
431                 asset.interlace_mode = edl->session->interlace_mode;
432                 asset.tcstart = (int64_t) (edl->session->get_frame_offset() +
433                         edl->local_session->get_selectionstart() *
434                                 edl->session->frame_rate);
435                 asset.tcend = (int64_t) (edl->session->get_frame_offset() +
436                         edl->local_session->get_selectionend() *
437                                 edl->session->frame_rate);
438         }
439         else
440         {
441                 asset.video_data = 0;
442                 asset.layers = 0;
443                 asset.tcstart = 0;
444                 asset.tcend = 0;
445         }
447         if(asset.audio_data && 
448                 edl->tracks->playable_audio_tracks() &&
449                 File::supports_audio(asset.format))
450         {
451                 asset.audio_data = 1;
452                 asset.channels = edl->session->audio_channels;
453                 if(asset.format == FILE_MOV) asset.byte_order = 0;
454                 asset.tcstart = (int64_t) (edl->session->get_frame_offset() +
455                         edl->local_session->get_selectionstart() *
456                                 edl->session->sample_rate);
457                 asset.tcend = (int64_t) (edl->session->get_frame_offset() +
458                         edl->local_session->get_selectionend() *
459                                 edl->session->sample_rate);
460         }
461         else
462         {
463                 asset.audio_data = 0;
464                 asset.channels = 0;
465                 asset.tcstart = 0;
466                 asset.tcend = 0;
467         }
469         if(!asset.audio_data &&
470                 !asset.video_data)
471         {
472                 return 1;
473         }
474         return 0;
477 int Render::fix_strategy(int strategy, int use_renderfarm)
479         if(use_renderfarm)
480         {
481                 if(strategy == FILE_PER_LABEL)
482                         strategy = FILE_PER_LABEL_FARM;
483                 else
484                 if(strategy == SINGLE_PASS)
485                         strategy = SINGLE_PASS_FARM;
486         }
487         else
488         {
489                 if(strategy == FILE_PER_LABEL_FARM)
490                         strategy = FILE_PER_LABEL;
491                 else
492                 if(strategy == SINGLE_PASS_FARM)
493                         strategy = SINGLE_PASS;
494         }
495         return strategy;
498 void Render::start_progress()
500         char filename[BCTEXTLEN];
501         char string[BCTEXTLEN];
502         FileSystem fs;
504         progress_max = Units::to_int64(default_asset->sample_rate * 
505                         (total_end - total_start)) +
506                 Units::to_int64(preferences->render_preroll * 
507                         packages->total_allocated * 
508                         default_asset->sample_rate);
509         progress_timer->update();
510         last_eta = 0;
511         if(mwindow)
512         {
513 // Generate the progress box
514                 fs.extract_name(filename, default_asset->path);
515                 sprintf(string, _("Rendering %s..."), filename);
517 // Don't bother with the filename since renderfarm defeats the meaning
518                 progress = mwindow->mainprogress->start_progress(_("Rendering..."), 
519                         progress_max);
520                 render_progress = new RenderProgress(mwindow, this);
521                 render_progress->start();
522         }
525 void Render::stop_progress()
527         if(progress)
528         {
529                 char string[BCTEXTLEN], string2[BCTEXTLEN];
530                 delete render_progress;
531                 progress->get_time(string);
532                 elapsed_time = progress->get_time();
533                 progress->stop_progress();
534                 delete progress;
536                 sprintf(string2, _("Rendering took %s"), string);
537                 mwindow->gui->lock_window();
538                 mwindow->gui->show_message(string2, BLACK);
539                 mwindow->gui->unlock_window();
540         }
541         progress = 0;
546 int Render::render(int test_overwrite, 
547         Asset *asset,
548         EDL *edl,
549         int strategy)
551         char string[BCTEXTLEN];
552 // Total length in seconds
553         double total_length;
554         int last_audio_buffer;
555         RenderFarmServer *farm_server = 0;
556         FileSystem fs;
557         int total_digits;      // Total number of digits including padding the user specified.
558         int number_start;      // Character in the filename path at which the number begins
559         int current_number;    // The number the being injected into the filename.
560 // Pointer from file
561 // (VFrame*)(VFrame array [])(Channel [])
562         VFrame ***video_output;
563 // Pointer to output buffers
564         VFrame *video_output_ptr[MAX_CHANNELS];
565         double *audio_output_ptr[MAX_CHANNELS];
566         int done = 0;
567         in_progress = 1;
570         this->default_asset = asset;
571         progress = 0;
572         result = 0;
574         if(mwindow)
575         {
576                 if(!preferences)
577                         preferences = new Preferences;
579                 preferences->copy_from(mwindow->preferences);
580         }
583 // Create rendering command
584         command = new TransportCommand;
585         command->command = NORMAL_FWD;
586         command->get_edl()->copy_all(edl);
587         command->change_type = CHANGE_ALL;
588 // Get highlighted playback range
589         command->set_playback_range();
590 // Adjust playback range with in/out points
591         command->adjust_playback_range();
592         packages = new PackageDispatcher;
595 // Configure preview monitor
596         VideoOutConfig vconfig;
597         PlaybackConfig *playback_config = new PlaybackConfig;
598         for(int i = 0; i < MAX_CHANNELS; i++)
599         {
600                 vconfig.do_channel[i] = (i < command->get_edl()->session->video_channels);
601                 playback_config->vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
602                 playback_config->aconfig->do_channel[i] = (i < command->get_edl()->session->audio_channels);
603         }
605 // Create caches
606         audio_cache = new CICache(command->get_edl(), preferences, plugindb);
607         video_cache = new CICache(command->get_edl(), preferences, plugindb);
609         default_asset->frame_rate = command->get_edl()->session->frame_rate;
610         default_asset->sample_rate = command->get_edl()->session->sample_rate;
612 // Conform asset to EDL.  Find out if any tracks are playable.
613         result = check_asset(command->get_edl(), *default_asset);
615         if(!result)
616         {
617 // Get total range to render
618                 total_start = command->start_position;
619                 total_end = command->end_position;
620                 total_length = total_end - total_start;
622 // Nothing to render
623                 if(EQUIV(total_length, 0))
624                 {
625                         result = 1;
626                 }
627         }
635 // Generate packages
636         if(!result)
637         {
638 // Stop background rendering
639                 if(mwindow) mwindow->stop_brender();
641                 fs.complete_path(default_asset->path);
642                 strategy = Render::fix_strategy(strategy, preferences->use_renderfarm);
644                 result = packages->create_packages(mwindow,
645                         command->get_edl(),
646                         preferences,
647                         strategy, 
648                         default_asset, 
649                         total_start, 
650                         total_end,
651                         test_overwrite);
652         }
663         done = 0;
664         total_rendered = 0;
665         frames_per_second = 0;
667         if(!result)
668         {
669 // Start dispatching external jobs
670                 if(mwindow)
671                 {
672                         mwindow->gui->lock_window();
673                         mwindow->gui->show_message(_("Starting render farm"), BLACK);
674                         mwindow->gui->unlock_window();
675                 }
676                 else
677                 {
678                         printf("Render::render: starting render farm\n");
679                 }
681                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
682                 {
683                         farm_server = new RenderFarmServer(plugindb, 
684                                 packages,
685                                 preferences, 
686                                 1,
687                                 &result,
688                                 &total_rendered,
689                                 counter_lock,
690                                 default_asset,
691                                 command->get_edl(),
692                                 0);
693                         result = farm_server->start_clients();
695                         if(result)
696                         {
697                                 if(mwindow)
698                                 {
699                                         mwindow->gui->lock_window();
700                                         mwindow->gui->show_message(_("Failed to start render farm"), BLACK);
701                                         mwindow->gui->unlock_window();
702                                 }
703                                 else
704                                 {
705                                         printf("Render::render: Failed to start render farm\n");
706                                 }
707                         }
708                 }
709         }
714 // Perform local rendering
717         if(!result)
718         {
719                 start_progress();
720         
724                 MainPackageRenderer package_renderer(this);
725                 result = package_renderer.initialize(mwindow,
726                                 command->get_edl(),   // Copy of master EDL
727                                 preferences, 
728                                 default_asset,
729                                 plugindb);
737                 while(!result)
738                 {
739 // Get unfinished job
740                         RenderPackage *package;
742                         if(strategy == SINGLE_PASS_FARM)
743                         {
744                                 package = packages->get_package(frames_per_second, -1, 1);
745                         }
746                         else
747                         {
748                                 package = packages->get_package(0, -1, 1);
749                         }
751 // Exit point
752                         if(!package) 
753                         {
754                                 done = 1;
755                                 break;
756                         }
760                         Timer timer;
761                         timer.update();
763                         if(package_renderer.render_package(package))
764                                 result = 1;
766 // Result is also set directly by the RenderFarm.
768                         frames_per_second = (double)(package->video_end - package->video_start) / 
769                                 (double)(timer.get_difference() / 1000);
772                 } // file_number
776 //printf("Render::run: Session finished.\n");
779 //printf("Render::render 80\n");
783                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
784                 {
785                         farm_server->wait_clients();
786                 }
788 //printf("Render::render 90\n");
790 // Notify of error
791                 if(result && 
792                         (!progress || !progress->is_cancelled()) &&
793                         !batch_cancelled)
794                 {
795                         if(mwindow)
796                         {
797                                 ErrorBox error_box(PROGRAM_NAME ": Error",
798                                         mwindow->gui->get_abs_cursor_x(1),
799                                         mwindow->gui->get_abs_cursor_y(1));
800                                 error_box.create_objects(_("Error rendering data."));
801                                 error_box.run_window();
802                         }
803                         else
804                         {
805                                 printf("Render::render: Error rendering data\n");
806                         }
807                 }
809 // Delete the progress box
810                 stop_progress();
812 //printf("Render::render 100\n");
817         } // !result
820 // Paste all packages into timeline if desired
822         if(!result && 
823                 load_mode != LOAD_NOTHING && 
824                 mwindow &&
825                 mode != Render::BATCH)
826         {
827                 mwindow->gui->lock_window();
830                 mwindow->undo->update_undo_before(_("render"), LOAD_ALL);
833                 ArrayList<Asset*> *assets = packages->get_asset_list();
834                 if(load_mode == LOAD_PASTE)
835                         mwindow->clear(0);
836                 mwindow->load_assets(assets, 
837                         -1, 
838                         load_mode,
839                         0,
840                         0,
841                         mwindow->edl->session->labels_follow_edits,
842                         mwindow->edl->session->plugins_follow_edits);
843                 assets->remove_all_objects();
844                 delete assets;
847                 mwindow->save_backup();
848                 mwindow->undo->update_undo_after();
849                 mwindow->update_plugin_guis();
850                 mwindow->gui->update(1, 
851                         2,
852                         1,
853                         1,
854                         1,
855                         1,
856                         0);
857                 mwindow->sync_parameters(CHANGE_ALL);
858                 mwindow->gui->unlock_window();
859         }
861 //printf("Render::render 110\n");
862 // Need to restart because brender always stops before render.
863         if(mwindow)
864                 mwindow->restart_brender();
865         if(farm_server) delete farm_server;
866         delete command;
867         delete playback_config;
868         delete audio_cache;
869         delete video_cache;
870 // Must delete packages after server
871         delete packages;
872         in_progress = 0;
873         completion->unlock();
874 //printf("Render::render 120\n");
876         return result;
880 void Render::create_filename(char *path, 
881         char *default_path, 
882         int current_number,
883         int total_digits,
884         int number_start)
886         int i, j, k;
887         int len = strlen(default_path);
888         char printf_string[BCTEXTLEN];
889         int found_number = 0;
891         for(i = 0, j = 0; i < number_start; i++, j++)
892         {
893                 printf_string[j] = default_path[i];
894         }
896 // Found the number
897         sprintf(&printf_string[j], "%%0%dd", total_digits);
898         j = strlen(printf_string);
899         i += total_digits;
901 // Copy remainder of string
902         for( ; i < len; i++, j++)
903         {
904                 printf_string[j] = default_path[i];
905         }
906         printf_string[j] = 0;
907 // Print the printf argument to the path
908         sprintf(path, printf_string, current_number);
911 void Render::get_starting_number(char *path, 
912         int &current_number,
913         int &number_start, 
914         int &total_digits,
915         int min_digits)
917         int i, j;
918         int len = strlen(path);
919         char number_text[BCTEXTLEN];
920         char *ptr = 0;
921         char *ptr2 = 0;
923         total_digits = 0;
924         number_start = 0;
926 // Search for last /
927         ptr2 = strrchr(path, '/');
929 // Search for first 0 after last /.
930         if(ptr2)
931                 ptr = strchr(ptr2, '0');
933         if(ptr && isdigit(*ptr))
934         {
935                 number_start = ptr - path;
937 // Store the first number
938                 char *ptr2 = number_text;
939                 while(isdigit(*ptr))
940                         *ptr2++ = *ptr++;
941                 *ptr2++ = 0;
942                 current_number = atol(number_text);
943                 total_digits = strlen(number_text);
944         }
947 // No number found or number not long enough
948         if(total_digits < min_digits)
949         {
950                 current_number = 1;
951                 number_start = len;
952                 total_digits = min_digits;
953         }
962 int Render::load_defaults(Asset *asset)
964         strategy = mwindow->defaults->get("RENDER_STRATEGY", SINGLE_PASS);
965         load_mode = mwindow->defaults->get("RENDER_LOADMODE", LOAD_NEW_TRACKS);
968         asset->load_defaults(mwindow->defaults, 
969                 "RENDER_", 
970                 1,
971                 1,
972                 1,
973                 1,
974                 1);
977         return 0;
980 int Render::save_defaults(Asset *asset)
982         mwindow->defaults->update("RENDER_STRATEGY", strategy);
983         mwindow->defaults->update("RENDER_LOADMODE", load_mode);
988         asset->save_defaults(mwindow->defaults, 
989                 "RENDER_",
990                 1,
991                 1,
992                 1,
993                 1,
994                 1);
996         return 0;
1002 #define WIDTH 410
1003 #define HEIGHT 360
1006 RenderWindow::RenderWindow(MWindow *mwindow, Render *render, Asset *asset)
1007  : BC_Window(PROGRAM_NAME ": Render", 
1008         mwindow->gui->get_root_w(0, 1) / 2 - WIDTH / 2,
1009         mwindow->gui->get_root_h(1) / 2 - HEIGHT / 2,
1010         WIDTH, 
1011         HEIGHT,
1012         (int)BC_INFINITY,
1013         (int)BC_INFINITY,
1014         0,
1015         0,
1016         1)
1018         this->mwindow = mwindow;
1019         this->render = render;
1020         this->asset = asset;
1023 RenderWindow::~RenderWindow()
1025         delete format_tools;
1026         delete loadmode;
1031 int RenderWindow::create_objects()
1033         int x = 5, y = 5;
1034         add_subwindow(new BC_Title(x, 
1035                 y, 
1036                 (char*)((render->strategy == FILE_PER_LABEL || 
1037                                 render->strategy == FILE_PER_LABEL_FARM) ? 
1038                         _("Select the first file to render to:") : 
1039                         _("Select a file to render to:"))));
1040         y += 25;
1042         format_tools = new FormatTools(mwindow,
1043                                         this, 
1044                                         asset);
1045         format_tools->create_objects(x, 
1046                 y, 
1047                 1, 
1048                 1, 
1049                 1, 
1050                 1, 
1051                 0,
1052                 1,
1053                 0,
1054                 0,
1055                 &render->strategy,
1056                 0);
1058         loadmode = new LoadMode(mwindow, this, x, y, &render->load_mode, 1);
1059         loadmode->create_objects();
1061         add_subwindow(new BC_OKButton(this));
1062         add_subwindow(new BC_CancelButton(this));
1063         show_window();
1064         return 0;