r665: Merged the official release 2.0.
[cinelerra_cv.git] / cinelerra / render.C
blob0cb10bf6e694e805377fee611dd1c3d72a449b18
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 "theme.h"
45 #include "timebar.h"
46 #include "tracks.h"
47 #include "transportque.h"
48 #include "vedit.h"
49 #include "vframe.h"
50 #include "videoconfig.h"
51 #include "vrender.h"
53 #include <ctype.h>
54 #include <string.h>
58 RenderItem::RenderItem(MWindow *mwindow)
59  : BC_MenuItem(_("Render..."), "Shift+R", 'R')
61         this->mwindow = mwindow;
62         set_shift(1);
65 int RenderItem::handle_event() 
67         mwindow->render->start_interactive();
68         return 1;
80 RenderProgress::RenderProgress(MWindow *mwindow, Render *render)
81  : Thread()
83         this->mwindow = mwindow;
84         this->render = render;
85         last_value = 0;
86         Thread::set_synchronous(1);
89 RenderProgress::~RenderProgress()
91         Thread::cancel();
92         Thread::join();
96 void RenderProgress::run()
98         Thread::disable_cancel();
99         while(1)
100         {
101                 if(render->total_rendered != last_value)
102                 {
103                         render->progress->update(render->total_rendered);
104                         last_value = render->total_rendered;
105                 }
107                 Thread::enable_cancel();
108                 sleep(1);
109                 Thread::disable_cancel();
110         }
122 MainPackageRenderer::MainPackageRenderer(Render *render)
123  : PackageRenderer()
125         this->render = render;
130 MainPackageRenderer::~MainPackageRenderer()
135 int MainPackageRenderer::get_master()
137         return 1;
140 int MainPackageRenderer::get_result()
142         return render->result;
145 void MainPackageRenderer::set_result(int value)
147         if(value)
148                 render->result = value;
151 void MainPackageRenderer::set_progress(int64_t value)
153         render->counter_lock->lock("MainPackageRenderer::set_progress");
154         render->total_rendered += value;
156 // If non interactive, print progress out
157         if(!render->progress)
158         {
159                 int64_t current_eta = render->progress_timer->get_scaled_difference(1000);
160                 if(current_eta - render->last_eta > 1000)
161                 {
162                         double eta = 0;
165                         if(render->total_rendered)
166                         {
167                                 eta = current_eta /
168                                         1000 *
169                                         render->progress_max /
170                                         render->total_rendered -
171                                         current_eta /
172                                         1000;
173                         }
175                         char string[BCTEXTLEN];
176                         Units::totext(string, 
177                                 eta,
178                                 TIME_HMS2);
180                         printf("\r%d%% ETA: %s      ", (int)(100 * 
181                                 (float)render->total_rendered / 
182                                         render->progress_max),
183                                 string);
184                         fflush(stdout);
185                         render->last_eta = current_eta;
186                 }
187         }
189         render->counter_lock->unlock();
192 int MainPackageRenderer::progress_cancelled()
194         return (render->progress && render->progress->is_cancelled()) || 
195                 render->batch_cancelled;
209 Render::Render(MWindow *mwindow)
210  : Thread(0, 0, 0)
212         this->mwindow = mwindow;
213         if(mwindow) plugindb = mwindow->plugindb;
214         in_progress = 0;
215         progress = 0;
216         preferences = 0;
217         elapsed_time = 0.0;
218         package_lock = new Mutex("Render::package_lock");
219         counter_lock = new Mutex("Render::counter_lock");
220         completion = new Condition(0, "Render::completion");
221         progress_timer = new Timer;
224 Render::~Render()
226         delete package_lock;
227         delete counter_lock;
228         delete completion;
229         if(preferences) delete preferences;
230         delete progress_timer;
233 void Render::start_interactive()
235         if(!Thread::running())
236         {
237                 mode = Render::INTERACTIVE;
238                 this->jobs = 0;
239                 batch_cancelled = 0;
240                 completion->reset();
241                 Thread::start();
242         }
243         else
244         {
245                 // raise the window if rendering hasn't started yet
246                 if (render_window && ! in_progress) {
247                         render_window->raise_window();
248                 }
249                 else {
250                         ErrorBox error_box(PROGRAM_NAME ": Error",
251                                            mwindow->gui->get_abs_cursor_x(1),
252                                            mwindow->gui->get_abs_cursor_y(1));
253                         error_box.create_objects("Already rendering");
254                         error_box.run_window();
255                 }
256         }
259 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs)
261         batch_cancelled = 0;
262         if(!Thread::running())
263         {
264                 mode = Render::BATCH;
265                 this->jobs = jobs;
266                 completion->reset();
267                 Thread::start();
268         }
269         else
270         {
271                 ErrorBox error_box(PROGRAM_NAME ": Error",
272                         mwindow->gui->get_abs_cursor_x(1),
273                         mwindow->gui->get_abs_cursor_y(1));
274                 error_box.create_objects("Already rendering");
275                 error_box.run_window();
276         }
279 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs,
280         Defaults *boot_defaults,
281         Preferences *preferences,
282         ArrayList<PluginServer*> *plugindb)
284         mode = Render::BATCH;
285         batch_cancelled = 0;
286         this->jobs = jobs;
287         this->preferences = preferences;
288         this->plugindb = plugindb;
290         completion->reset();
291         run();
292         this->preferences = 0;
295 void Render::stop_operation()
297         if(Thread::running())
298         {
299                 batch_cancelled = 1;
300 // Wait for completion
301                 completion->lock("Render::stop_operation");
302                 completion->reset();
303         }
307 void Render::run()
309         int format_error;
312         result = 0;
314         if(mode == Render::INTERACTIVE)
315         {
316 // Fix the asset for rendering
317                 Asset *asset = new Asset;
318                 load_defaults(asset);
319                 check_asset(mwindow->edl, *asset);
321 // Get format from user
322                 if(!result)
323                 {
324                         do
325                         {
326                                 format_error = 0;
327                                 result = 0;
329                                 {
330                                         render_window = new RenderWindow(mwindow, this, asset);
331                                         render_window->create_objects();
332                                         result = render_window->run_window();
333                                         if (! result) {
334                                                 // add to recentlist only on OK
335                                                 render_window->format_tools->path_recent->add_item(FILE_FORMAT_PREFIX(asset->format), asset->path);
336                                         }
337                                         delete render_window;
338                                         render_window = 0;
339                                 }
341                                 if(!result)
342                                 {
343 // Check the asset format for errors.
344                                         FormatCheck format_check(asset);
345                                         format_error = format_check.check_format();
346                                 }
347                         }while(format_error && !result);
348                 }
350                 save_defaults(asset);
351                 mwindow->save_defaults();
353                 if(!result) render(1, asset, mwindow->edl, strategy);
355                 delete asset;
356         }
357         else
358         if(mode == Render::BATCH)
359         {
360                 for(int i = 0; i < jobs->total && !result; i++)
361                 {
362                         BatchRenderJob *job = jobs->values[i];
363                         if(job->enabled)
364                         {
365                                 if(mwindow)
366                                 {
367                                         mwindow->batch_render->update_active(i);
368                                 }
369                                 else
370                                 {
371                                         printf("Render::run: %s\n", job->edl_path);
372                                 }
375                                 FileXML *file = new FileXML;
376                                 EDL *edl = new EDL;
377                                 edl->create_objects();
378                                 file->read_from_file(job->edl_path);
379                                 if(!plugindb && mwindow)
380                                         plugindb = mwindow->plugindb;
381                                 edl->load_xml(plugindb, file, LOAD_ALL);
383                                 render(0, job->asset, edl, job->strategy);
385                                 delete edl;
386                                 delete file;
387                                 if(!result)
388                                 {
389                                         if(mwindow)
390                                                 mwindow->batch_render->update_done(i, 1, elapsed_time);
391                                         else
392                                         {
393                                                 char string[BCTEXTLEN];
394                                                 elapsed_time = 
395                                                         (double)progress_timer->get_scaled_difference(1);
396                                                 Units::totext(string,
397                                                         elapsed_time,
398                                                         TIME_HMS2);
399                                                 printf("Render::run: done in %s\n", string);
400                                         }
401                                 }
402                                 else
403                                 {
404                                         if(mwindow)
405                                                 mwindow->batch_render->update_active(-1);
406                                         else
407                                                 printf("Render::run: failed\n");
408                                 }
409                         }
410                 }
412                 if(mwindow)
413                 {
414                         mwindow->batch_render->update_active(-1);
415                         mwindow->batch_render->update_done(-1, 0, 0);
416                 }
417         }
422 int Render::check_asset(EDL *edl, Asset &asset)
424         if(asset.video_data && 
425                 edl->tracks->playable_video_tracks() &&
426                 File::supports_video(asset.format))
427         {
428                 asset.video_data = 1;
429                 asset.layers = 1;
430                 asset.width = edl->session->output_w;
431                 asset.height = edl->session->output_h;
432                 asset.interlace_mode = edl->session->interlace_mode;
433                 asset.tcstart = (int64_t) (edl->session->get_frame_offset() +
434                         edl->local_session->get_selectionstart() *
435                                 edl->session->frame_rate);
436                 asset.tcend = (int64_t) (edl->session->get_frame_offset() +
437                         edl->local_session->get_selectionend() *
438                                 edl->session->frame_rate);
439         }
440         else
441         {
442                 asset.video_data = 0;
443                 asset.layers = 0;
444                 asset.tcstart = 0;
445                 asset.tcend = 0;
446         }
448         if(asset.audio_data && 
449                 edl->tracks->playable_audio_tracks() &&
450                 File::supports_audio(asset.format))
451         {
452                 asset.audio_data = 1;
453                 asset.channels = edl->session->audio_channels;
454                 if(asset.format == FILE_MOV) asset.byte_order = 0;
455                 asset.tcstart = (int64_t) (edl->session->get_frame_offset() +
456                         edl->local_session->get_selectionstart() *
457                                 edl->session->sample_rate);
458                 asset.tcend = (int64_t) (edl->session->get_frame_offset() +
459                         edl->local_session->get_selectionend() *
460                                 edl->session->sample_rate);
461         }
462         else
463         {
464                 asset.audio_data = 0;
465                 asset.channels = 0;
466                 asset.tcstart = 0;
467                 asset.tcend = 0;
468         }
470         if(!asset.audio_data &&
471                 !asset.video_data)
472         {
473                 return 1;
474         }
475         return 0;
478 int Render::fix_strategy(int strategy, int use_renderfarm)
480         if(use_renderfarm)
481         {
482                 if(strategy == FILE_PER_LABEL)
483                         strategy = FILE_PER_LABEL_FARM;
484                 else
485                 if(strategy == SINGLE_PASS)
486                         strategy = SINGLE_PASS_FARM;
487         }
488         else
489         {
490                 if(strategy == FILE_PER_LABEL_FARM)
491                         strategy = FILE_PER_LABEL;
492                 else
493                 if(strategy == SINGLE_PASS_FARM)
494                         strategy = SINGLE_PASS;
495         }
496         return strategy;
499 void Render::start_progress()
501         char filename[BCTEXTLEN];
502         char string[BCTEXTLEN];
503         FileSystem fs;
505         progress_max = Units::to_int64(default_asset->sample_rate * 
506                         (total_end - total_start)) +
507                 Units::to_int64(preferences->render_preroll * 
508                         packages->total_allocated * 
509                         default_asset->sample_rate);
510         progress_timer->update();
511         last_eta = 0;
512         if(mwindow)
513         {
514 // Generate the progress box
515                 fs.extract_name(filename, default_asset->path);
516                 sprintf(string, _("Rendering %s..."), filename);
518 // Don't bother with the filename since renderfarm defeats the meaning
519                 progress = mwindow->mainprogress->start_progress(_("Rendering..."), 
520                         progress_max);
521                 render_progress = new RenderProgress(mwindow, this);
522                 render_progress->start();
523         }
526 void Render::stop_progress()
528         if(progress)
529         {
530                 char string[BCTEXTLEN], string2[BCTEXTLEN];
531                 delete render_progress;
532                 progress->get_time(string);
533                 elapsed_time = progress->get_time();
534                 progress->stop_progress();
535                 delete progress;
537                 sprintf(string2, _("Rendering took %s"), string);
538                 mwindow->gui->lock_window("");
539                 mwindow->gui->show_message(string2);
540                 mwindow->gui->stop_hourglass();
541                 mwindow->gui->unlock_window();
542         }
543         progress = 0;
548 int Render::render(int test_overwrite, 
549         Asset *asset,
550         EDL *edl,
551         int strategy)
553         char string[BCTEXTLEN];
554 // Total length in seconds
555         double total_length;
556         int last_audio_buffer;
557         RenderFarmServer *farm_server = 0;
558         FileSystem fs;
559         int total_digits;      // Total number of digits including padding the user specified.
560         int number_start;      // Character in the filename path at which the number begins
561         int current_number;    // The number the being injected into the filename.
562 // Pointer from file
563 // (VFrame*)(VFrame array [])(Channel [])
564         VFrame ***video_output;
565 // Pointer to output buffers
566         VFrame *video_output_ptr[MAX_CHANNELS];
567         double *audio_output_ptr[MAX_CHANNELS];
568         int done = 0;
569         in_progress = 1;
572         this->default_asset = asset;
573         progress = 0;
574         result = 0;
576         if(mwindow)
577         {
578                 if(!preferences)
579                         preferences = new Preferences;
581                 preferences->copy_from(mwindow->preferences);
582         }
585 // Create rendering command
586         command = new TransportCommand;
587         command->command = NORMAL_FWD;
588         command->get_edl()->copy_all(edl);
589         command->change_type = CHANGE_ALL;
590 // Get highlighted playback range
591         command->set_playback_range();
592 // Adjust playback range with in/out points
593         command->adjust_playback_range();
594         packages = new PackageDispatcher;
597 // Configure preview monitor
598         VideoOutConfig vconfig;
599         PlaybackConfig *playback_config = new PlaybackConfig;
600         for(int i = 0; i < MAX_CHANNELS; i++)
601         {
602                 vconfig.do_channel[i] = (i < command->get_edl()->session->video_channels);
603                 playback_config->vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
604                 playback_config->aconfig->do_channel[i] = (i < command->get_edl()->session->audio_channels);
605         }
607 // Create caches
608         audio_cache = new CICache(command->get_edl(), preferences, plugindb);
609         video_cache = new CICache(command->get_edl(), preferences, plugindb);
611         default_asset->frame_rate = command->get_edl()->session->frame_rate;
612         default_asset->sample_rate = command->get_edl()->session->sample_rate;
614 // Conform asset to EDL.  Find out if any tracks are playable.
615         result = check_asset(command->get_edl(), *default_asset);
617         if(!result)
618         {
619 // Get total range to render
620                 total_start = command->start_position;
621                 total_end = command->end_position;
622                 total_length = total_end - total_start;
624 // Nothing to render
625                 if(EQUIV(total_length, 0))
626                 {
627                         result = 1;
628                 }
629         }
637 // Generate packages
638         if(!result)
639         {
640 // Stop background rendering
641                 if(mwindow) mwindow->stop_brender();
643                 fs.complete_path(default_asset->path);
644                 strategy = Render::fix_strategy(strategy, preferences->use_renderfarm);
646                 result = packages->create_packages(mwindow,
647                         command->get_edl(),
648                         preferences,
649                         strategy, 
650                         default_asset, 
651                         total_start, 
652                         total_end,
653                         test_overwrite);
654         }
665         done = 0;
666         total_rendered = 0;
667         frames_per_second = 0;
669         if(!result)
670         {
671 // Start dispatching external jobs
672                 if(mwindow)
673                 {
674                         mwindow->gui->lock_window("Render::render 1");
675                         mwindow->gui->show_message(_("Starting render farm"));
676                         mwindow->gui->start_hourglass();
677                         mwindow->gui->unlock_window();
678                 }
679                 else
680                 {
681                         printf("Render::render: starting render farm\n");
682                 }
684                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
685                 {
686                         farm_server = new RenderFarmServer(plugindb, 
687                                 packages,
688                                 preferences, 
689                                 1,
690                                 &result,
691                                 &total_rendered,
692                                 counter_lock,
693                                 default_asset,
694                                 command->get_edl(),
695                                 0);
696                         result = farm_server->start_clients();
698                         if(result)
699                         {
700                                 if(mwindow)
701                                 {
702                                         mwindow->gui->lock_window("Render::render 2");
703                                         mwindow->gui->show_message(_("Failed to start render farm"),
704                                                 mwindow->theme->message_error);
705                                         mwindow->gui->stop_hourglass();
706                                         mwindow->gui->unlock_window();
707                                 }
708                                 else
709                                 {
710                                         printf("Render::render: Failed to start render farm\n");
711                                 }
712                         }
713                 }
714         }
719 // Perform local rendering
722         if(!result)
723         {
724                 start_progress();
725         
729                 MainPackageRenderer package_renderer(this);
730                 result = package_renderer.initialize(mwindow,
731                                 command->get_edl(),   // Copy of master EDL
732                                 preferences, 
733                                 default_asset,
734                                 plugindb);
742                 while(!result)
743                 {
744 // Get unfinished job
745                         RenderPackage *package;
747                         if(strategy == SINGLE_PASS_FARM)
748                         {
749                                 package = packages->get_package(frames_per_second, -1, 1);
750                         }
751                         else
752                         {
753                                 package = packages->get_package(0, -1, 1);
754                         }
756 // Exit point
757                         if(!package) 
758                         {
759                                 done = 1;
760                                 break;
761                         }
765                         Timer timer;
766                         timer.update();
768                         if(package_renderer.render_package(package))
769                                 result = 1;
771 // Result is also set directly by the RenderFarm.
773                         frames_per_second = (double)(package->video_end - package->video_start) / 
774                                 (double)(timer.get_difference() / 1000);
777                 } // file_number
781 //printf("Render::run: Session finished.\n");
784 //printf("Render::render 80\n");
788                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
789                 {
790                         farm_server->wait_clients();
791                 }
793 //printf("Render::render 90\n");
795 // Notify of error
796                 if(result && 
797                         (!progress || !progress->is_cancelled()) &&
798                         !batch_cancelled)
799                 {
800                         if(mwindow)
801                         {
802                                 ErrorBox error_box(PROGRAM_NAME ": Error",
803                                         mwindow->gui->get_abs_cursor_x(1),
804                                         mwindow->gui->get_abs_cursor_y(1));
805                                 error_box.create_objects(_("Error rendering data."));
806                                 error_box.run_window();
807                         }
808                         else
809                         {
810                                 printf("Render::render: Error rendering data\n");
811                         }
812                 }
814 // Delete the progress box
815                 stop_progress();
817 //printf("Render::render 100\n");
822         }
825 // Paste all packages into timeline if desired
827         if(!result && 
828                 load_mode != LOAD_NOTHING && 
829                 mwindow &&
830                 mode != Render::BATCH)
831         {
832                 mwindow->gui->lock_window("Render::render 3");
837                 ArrayList<Asset*> *assets = packages->get_asset_list();
838                 if(load_mode == LOAD_PASTE)
839                         mwindow->clear(0);
840                 mwindow->load_assets(assets, 
841                         -1, 
842                         load_mode,
843                         0,
844                         0,
845                         mwindow->edl->session->labels_follow_edits,
846                         mwindow->edl->session->plugins_follow_edits);
847                 assets->remove_all_objects();
848                 delete assets;
851                 mwindow->save_backup();
852                 mwindow->undo->update_undo(_("render"), LOAD_ALL);
853                 mwindow->update_plugin_guis();
854                 mwindow->gui->update(1, 
855                         2,
856                         1,
857                         1,
858                         1,
859                         1,
860                         0);
861                 mwindow->sync_parameters(CHANGE_ALL);
862                 mwindow->gui->unlock_window();
863         }
866 // Disable hourglass
867         if(mwindow)
868         {
869                 mwindow->gui->lock_window("Render::render 3");
870                 mwindow->gui->stop_hourglass();
871                 mwindow->gui->unlock_window();
872         }
874 //printf("Render::render 110\n");
875 // Need to restart because brender always stops before render.
876         if(mwindow)
877                 mwindow->restart_brender();
878         if(farm_server) delete farm_server;
879         delete command;
880         delete playback_config;
881         delete audio_cache;
882         delete video_cache;
883 // Must delete packages after server
884         delete packages;
885         in_progress = 0;
886         completion->unlock();
887 //printf("Render::render 120\n");
889         return result;
893 void Render::create_filename(char *path, 
894         char *default_path, 
895         int current_number,
896         int total_digits,
897         int number_start)
899         int i, j, k;
900         int len = strlen(default_path);
901         char printf_string[BCTEXTLEN];
902         int found_number = 0;
904         for(i = 0, j = 0; i < number_start; i++, j++)
905         {
906                 printf_string[j] = default_path[i];
907         }
909 // Found the number
910         sprintf(&printf_string[j], "%%0%dd", total_digits);
911         j = strlen(printf_string);
912         i += total_digits;
914 // Copy remainder of string
915         for( ; i < len; i++, j++)
916         {
917                 printf_string[j] = default_path[i];
918         }
919         printf_string[j] = 0;
920 // Print the printf argument to the path
921         sprintf(path, printf_string, current_number);
924 void Render::get_starting_number(char *path, 
925         int &current_number,
926         int &number_start, 
927         int &total_digits,
928         int min_digits)
930         int i, j;
931         int len = strlen(path);
932         char number_text[BCTEXTLEN];
933         char *ptr = 0;
934         char *ptr2 = 0;
936         total_digits = 0;
937         number_start = 0;
939 // Search for last /
940         ptr2 = strrchr(path, '/');
942 // Search for first 0 after last /.
943         if(ptr2)
944                 ptr = strchr(ptr2, '0');
946         if(ptr && isdigit(*ptr))
947         {
948                 number_start = ptr - path;
950 // Store the first number
951                 char *ptr2 = number_text;
952                 while(isdigit(*ptr))
953                         *ptr2++ = *ptr++;
954                 *ptr2++ = 0;
955                 current_number = atol(number_text);
956                 total_digits = strlen(number_text);
957         }
960 // No number found or number not long enough
961         if(total_digits < min_digits)
962         {
963                 current_number = 1;
964                 number_start = len;
965                 total_digits = min_digits;
966         }
975 int Render::load_defaults(Asset *asset)
977         strategy = mwindow->defaults->get("RENDER_STRATEGY", SINGLE_PASS);
978         load_mode = mwindow->defaults->get("RENDER_LOADMODE", LOAD_NEW_TRACKS);
981         asset->load_defaults(mwindow->defaults, 
982                 "RENDER_", 
983                 1,
984                 1,
985                 1,
986                 1,
987                 1);
990         return 0;
993 int Render::save_defaults(Asset *asset)
995         mwindow->defaults->update("RENDER_STRATEGY", strategy);
996         mwindow->defaults->update("RENDER_LOADMODE", load_mode);
1001         asset->save_defaults(mwindow->defaults, 
1002                 "RENDER_",
1003                 1,
1004                 1,
1005                 1,
1006                 1,
1007                 1);
1009         return 0;
1015 #define WIDTH 410
1016 #define HEIGHT 360
1019 RenderWindow::RenderWindow(MWindow *mwindow, Render *render, Asset *asset)
1020  : BC_Window(PROGRAM_NAME ": Render", 
1021         mwindow->gui->get_root_w(0, 1) / 2 - WIDTH / 2,
1022         mwindow->gui->get_root_h(1) / 2 - HEIGHT / 2,
1023         WIDTH, 
1024         HEIGHT,
1025         (int)BC_INFINITY,
1026         (int)BC_INFINITY,
1027         0,
1028         0,
1029         1)
1031         this->mwindow = mwindow;
1032         this->render = render;
1033         this->asset = asset;
1036 RenderWindow::~RenderWindow()
1038         delete format_tools;
1039         delete loadmode;
1044 int RenderWindow::create_objects()
1046         int x = 5, y = 5;
1047         add_subwindow(new BC_Title(x, 
1048                 y, 
1049                 (char*)((render->strategy == FILE_PER_LABEL || 
1050                                 render->strategy == FILE_PER_LABEL_FARM) ? 
1051                         _("Select the first file to render to:") : 
1052                         _("Select a file to render to:"))));
1053         y += 25;
1055         format_tools = new FormatTools(mwindow,
1056                                         this, 
1057                                         asset);
1058         format_tools->create_objects(x, 
1059                 y, 
1060                 1, 
1061                 1, 
1062                 1, 
1063                 1, 
1064                 0,
1065                 1,
1066                 0,
1067                 0,
1068                 &render->strategy,
1069                 0);
1071         loadmode = new LoadMode(mwindow, this, x, y, &render->load_mode, 1);
1072         loadmode->create_objects();
1074         add_subwindow(new BC_OKButton(this));
1075         add_subwindow(new BC_CancelButton(this));
1076         show_window();
1077         return 0;