r807: Minor fix...
[cinelerra_cv/mob.git] / cinelerra / render.C
blob5c0d1501a2a1020cc4172f2abe3a6daaaf8cccd0
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.raise_window();
255                         error_box.run_window();
256                 }
257         }
260 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs)
262         batch_cancelled = 0;
263         if(!Thread::running())
264         {
265                 mode = Render::BATCH;
266                 this->jobs = jobs;
267                 completion->reset();
268                 Thread::start();
269         }
270         else
271         {
272                 ErrorBox error_box(PROGRAM_NAME ": Error",
273                         mwindow->gui->get_abs_cursor_x(1),
274                         mwindow->gui->get_abs_cursor_y(1));
275                 error_box.create_objects("Already rendering");
276                 error_box.raise_window();
277                 error_box.run_window();
278         }
281 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs,
282         Defaults *boot_defaults,
283         Preferences *preferences,
284         ArrayList<PluginServer*> *plugindb)
286         mode = Render::BATCH;
287         batch_cancelled = 0;
288         this->jobs = jobs;
289         this->preferences = preferences;
290         this->plugindb = plugindb;
292         completion->reset();
293         run();
294         this->preferences = 0;
297 void Render::stop_operation()
299         if(Thread::running())
300         {
301                 batch_cancelled = 1;
302 // Wait for completion
303                 completion->lock("Render::stop_operation");
304                 completion->reset();
305         }
309 void Render::run()
311         int format_error;
314         result = 0;
316         if(mode == Render::INTERACTIVE)
317         {
318 // Fix the asset for rendering
319                 Asset *asset = new Asset;
320                 load_defaults(asset);
321                 check_asset(mwindow->edl, *asset);
323 // Get format from user
324                 if(!result)
325                 {
326                         do
327                         {
328                                 format_error = 0;
329                                 result = 0;
331                                 {
332                                         render_window = new RenderWindow(mwindow, this, asset);
333                                         render_window->create_objects();
334                                         result = render_window->run_window();
335                                         if (! result) {
336                                                 // add to recentlist only on OK
337                                                 render_window->format_tools->path_recent->add_item(FILE_FORMAT_PREFIX(asset->format), asset->path);
338                                         }
339                                         delete render_window;
340                                         render_window = 0;
341                                 }
343                                 if(!result)
344                                 {
345 // Check the asset format for errors.
346                                         FormatCheck format_check(asset);
347                                         format_error = format_check.check_format();
348                                 }
349                         }while(format_error && !result);
350                 }
352                 save_defaults(asset);
353                 mwindow->save_defaults();
355                 if(!result) render(1, asset, mwindow->edl, strategy);
357                 delete asset;
358         }
359         else
360         if(mode == Render::BATCH)
361         {
362                 for(int i = 0; i < jobs->total && !result; i++)
363                 {
364                         BatchRenderJob *job = jobs->values[i];
365                         if(job->enabled)
366                         {
367                                 if(mwindow)
368                                 {
369                                         mwindow->batch_render->update_active(i);
370                                 }
371                                 else
372                                 {
373                                         printf("Render::run: %s\n", job->edl_path);
374                                 }
377                                 FileXML *file = new FileXML;
378                                 EDL *edl = new EDL;
379                                 edl->create_objects();
380                                 file->read_from_file(job->edl_path);
381                                 if(!plugindb && mwindow)
382                                         plugindb = mwindow->plugindb;
383                                 edl->load_xml(plugindb, file, LOAD_ALL);
385                                 render(0, job->asset, edl, job->strategy);
387                                 delete edl;
388                                 delete file;
389                                 if(!result)
390                                 {
391                                         if(mwindow)
392                                                 mwindow->batch_render->update_done(i, 1, elapsed_time);
393                                         else
394                                         {
395                                                 char string[BCTEXTLEN];
396                                                 elapsed_time = 
397                                                         (double)progress_timer->get_scaled_difference(1);
398                                                 Units::totext(string,
399                                                         elapsed_time,
400                                                         TIME_HMS2);
401                                                 printf("Render::run: done in %s\n", string);
402                                         }
403                                 }
404                                 else
405                                 {
406                                         if(mwindow)
407                                                 mwindow->batch_render->update_active(-1);
408                                         else
409                                                 printf("Render::run: failed\n");
410                                 }
411                         }
412                 }
414                 if(mwindow)
415                 {
416                         mwindow->batch_render->update_active(-1);
417                         mwindow->batch_render->update_done(-1, 0, 0);
418                 }
419         }
424 int Render::check_asset(EDL *edl, Asset &asset)
426         if(asset.video_data && 
427                 edl->tracks->playable_video_tracks() &&
428                 File::supports_video(asset.format))
429         {
430                 asset.video_data = 1;
431                 asset.layers = 1;
432                 asset.width = edl->session->output_w;
433                 asset.height = edl->session->output_h;
434                 asset.interlace_mode = edl->session->interlace_mode;
435                 asset.tcstart = (int64_t) (edl->session->get_frame_offset() +
436                         edl->local_session->get_selectionstart() *
437                                 edl->session->frame_rate);
438                 asset.tcend = (int64_t) (edl->session->get_frame_offset() +
439                         edl->local_session->get_selectionend() *
440                                 edl->session->frame_rate);
441         }
442         else
443         {
444                 asset.video_data = 0;
445                 asset.layers = 0;
446                 asset.tcstart = 0;
447                 asset.tcend = 0;
448         }
450         if(asset.audio_data && 
451                 edl->tracks->playable_audio_tracks() &&
452                 File::supports_audio(asset.format))
453         {
454                 asset.audio_data = 1;
455                 asset.channels = edl->session->audio_channels;
456                 if(asset.format == FILE_MOV) asset.byte_order = 0;
457                 asset.tcstart = (int64_t) (edl->session->get_frame_offset() +
458                         edl->local_session->get_selectionstart() *
459                                 edl->session->sample_rate);
460                 asset.tcend = (int64_t) (edl->session->get_frame_offset() +
461                         edl->local_session->get_selectionend() *
462                                 edl->session->sample_rate);
463         }
464         else
465         {
466                 asset.audio_data = 0;
467                 asset.channels = 0;
468                 asset.tcstart = 0;
469                 asset.tcend = 0;
470         }
472         if(!asset.audio_data &&
473                 !asset.video_data)
474         {
475                 return 1;
476         }
477         return 0;
480 int Render::fix_strategy(int strategy, int use_renderfarm)
482         if(use_renderfarm)
483         {
484                 if(strategy == FILE_PER_LABEL)
485                         strategy = FILE_PER_LABEL_FARM;
486                 else
487                 if(strategy == SINGLE_PASS)
488                         strategy = SINGLE_PASS_FARM;
489         }
490         else
491         {
492                 if(strategy == FILE_PER_LABEL_FARM)
493                         strategy = FILE_PER_LABEL;
494                 else
495                 if(strategy == SINGLE_PASS_FARM)
496                         strategy = SINGLE_PASS;
497         }
498         return strategy;
501 void Render::start_progress()
503         char filename[BCTEXTLEN];
504         char string[BCTEXTLEN];
505         FileSystem fs;
507         progress_max = packages->get_progress_max();
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);
539                 mwindow->gui->stop_hourglass();
540                 mwindow->gui->unlock_window();
541         }
542         progress = 0;
547 int Render::render(int test_overwrite, 
548         Asset *asset,
549         EDL *edl,
550         int strategy)
552         char string[BCTEXTLEN];
553 // Total length in seconds
554         double total_length;
555         int last_audio_buffer;
556         RenderFarmServer *farm_server = 0;
557         FileSystem fs;
558         int total_digits;      // Total number of digits including padding the user specified.
559         int number_start;      // Character in the filename path at which the number begins
560         int current_number;    // The number the being injected into the filename.
561 // Pointer from file
562 // (VFrame*)(VFrame array [])(Channel [])
563         VFrame ***video_output;
564 // Pointer to output buffers
565         VFrame *video_output_ptr[MAX_CHANNELS];
566         double *audio_output_ptr[MAX_CHANNELS];
567         int done = 0;
568         in_progress = 1;
571         this->default_asset = asset;
572         progress = 0;
573         result = 0;
575         if(mwindow)
576         {
577                 if(!preferences)
578                         preferences = new Preferences;
580                 preferences->copy_from(mwindow->preferences);
581         }
584 // Create rendering command
585         command = new TransportCommand;
586         command->command = NORMAL_FWD;
587         command->get_edl()->copy_all(edl);
588         command->change_type = CHANGE_ALL;
589 // Get highlighted playback range
590         command->set_playback_range();
591 // Adjust playback range with in/out points
592         command->adjust_playback_range();
593         packages = new PackageDispatcher;
596 // Configure preview monitor
597         VideoOutConfig vconfig;
598         PlaybackConfig *playback_config = new PlaybackConfig;
599         for(int i = 0; i < MAX_CHANNELS; i++)
600         {
601                 vconfig.do_channel[i] = (i < command->get_edl()->session->video_channels);
602                 playback_config->vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
603                 playback_config->aconfig->do_channel[i] = (i < command->get_edl()->session->audio_channels);
604         }
606 // Create caches
607         audio_cache = new CICache(command->get_edl(), preferences, plugindb);
608         video_cache = new CICache(command->get_edl(), preferences, plugindb);
610         default_asset->frame_rate = command->get_edl()->session->frame_rate;
611         default_asset->sample_rate = command->get_edl()->session->sample_rate;
613 // Conform asset to EDL.  Find out if any tracks are playable.
614         result = check_asset(command->get_edl(), *default_asset);
616         if(!result)
617         {
618 // Get total range to render
619                 total_start = command->start_position;
620                 total_end = command->end_position;
621                 total_length = total_end - total_start;
623 // Nothing to render
624                 if(EQUIV(total_length, 0))
625                 {
626                         result = 1;
627                 }
628         }
636 // Generate packages
637         if(!result)
638         {
639 // Stop background rendering
640                 if(mwindow) mwindow->stop_brender();
642                 fs.complete_path(default_asset->path);
643                 strategy = Render::fix_strategy(strategy, preferences->use_renderfarm);
645                 result = packages->create_packages(mwindow,
646                         command->get_edl(),
647                         preferences,
648                         strategy, 
649                         default_asset, 
650                         total_start, 
651                         total_end,
652                         test_overwrite);
653         }
664         done = 0;
665         total_rendered = 0;
666         frames_per_second = 0;
668         if(!result)
669         {
670 // Start dispatching external jobs
671                 if(mwindow)
672                 {
673                         mwindow->gui->lock_window("Render::render 1");
674                         mwindow->gui->show_message(_("Starting render farm"));
675                         mwindow->gui->start_hourglass();
676                         mwindow->gui->unlock_window();
677                 }
678                 else
679                 {
680                         printf("Render::render: starting render farm\n");
681                 }
683                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
684                 {
685                         farm_server = new RenderFarmServer(plugindb, 
686                                 packages,
687                                 preferences, 
688                                 1,
689                                 &result,
690                                 &total_rendered,
691                                 counter_lock,
692                                 default_asset,
693                                 command->get_edl(),
694                                 0);
695                         result = farm_server->start_clients();
697                         if(result)
698                         {
699                                 if(mwindow)
700                                 {
701                                         mwindow->gui->lock_window("Render::render 2");
702                                         mwindow->gui->show_message(_("Failed to start render farm"),
703                                                 mwindow->theme->message_error);
704                                         mwindow->gui->stop_hourglass();
705                                         mwindow->gui->unlock_window();
706                                 }
707                                 else
708                                 {
709                                         printf("Render::render: Failed to start render farm\n");
710                                 }
711                         }
712                 }
713         }
718 // Perform local rendering
721         if(!result)
722         {
723                 start_progress();
724         
728                 MainPackageRenderer package_renderer(this);
729                 result = package_renderer.initialize(mwindow,
730                                 command->get_edl(),   // Copy of master EDL
731                                 preferences, 
732                                 default_asset,
733                                 plugindb);
741                 while(!result)
742                 {
743 // Get unfinished job
744                         RenderPackage *package;
746                         if(strategy == SINGLE_PASS_FARM)
747                         {
748                                 package = packages->get_package(frames_per_second, -1, 1);
749                         }
750                         else
751                         {
752                                 package = packages->get_package(0, -1, 1);
753                         }
755 // Exit point
756                         if(!package) 
757                         {
758                                 done = 1;
759                                 break;
760                         }
764                         Timer timer;
765                         timer.update();
767                         if(package_renderer.render_package(package))
768                                 result = 1;
770 // Result is also set directly by the RenderFarm.
772                         frames_per_second = (double)(package->video_end - package->video_start) / 
773                                 (double)(timer.get_difference() / 1000);
776                 } // file_number
780 //printf("Render::run: Session finished.\n");
783 //printf("Render::render 80\n");
787                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
788                 {
789                         farm_server->wait_clients();
790                         result |= packages->packages_are_done();
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.raise_window();
807                                 error_box.run_window();
808                         }
809                         else
810                         {
811                                 printf("Render::render: Error rendering data\n");
812                         }
813                 }
815 // Delete the progress box
816                 stop_progress();
818 //printf("Render::render 100\n");
823         }
826 // Paste all packages into timeline if desired
828         if(!result && 
829                 load_mode != LOAD_NOTHING && 
830                 mwindow &&
831                 mode != Render::BATCH)
832         {
833                 mwindow->gui->lock_window("Render::render 3");
838                 ArrayList<Asset*> *assets = packages->get_asset_list();
839                 if(load_mode == LOAD_PASTE)
840                         mwindow->clear(0);
841                 mwindow->load_assets(assets, 
842                         -1, 
843                         load_mode,
844                         0,
845                         0,
846                         mwindow->edl->session->labels_follow_edits,
847                         mwindow->edl->session->plugins_follow_edits);
848                 assets->remove_all_objects();
849                 delete assets;
852                 mwindow->save_backup();
853                 mwindow->undo->update_undo(_("render"), LOAD_ALL);
854                 mwindow->update_plugin_guis();
855                 mwindow->gui->update(1, 
856                         2,
857                         1,
858                         1,
859                         1,
860                         1,
861                         0);
862                 mwindow->sync_parameters(CHANGE_ALL);
863                 mwindow->gui->unlock_window();
864         }
867 // Disable hourglass
868         if(mwindow)
869         {
870                 mwindow->gui->lock_window("Render::render 3");
871                 mwindow->gui->stop_hourglass();
872                 mwindow->gui->unlock_window();
873         }
875 //printf("Render::render 110\n");
876 // Need to restart because brender always stops before render.
877         if(mwindow)
878                 mwindow->restart_brender();
879         if(farm_server) delete farm_server;
880         delete command;
881         delete playback_config;
882         delete audio_cache;
883         delete video_cache;
884 // Must delete packages after server
885         delete packages;
886         in_progress = 0;
887         completion->unlock();
888 //printf("Render::render 120\n");
890         return result;
894 void Render::create_filename(char *path, 
895         char *default_path, 
896         int current_number,
897         int total_digits,
898         int number_start)
900         int i, j, k;
901         int len = strlen(default_path);
902         char printf_string[BCTEXTLEN];
903         int found_number = 0;
905         for(i = 0, j = 0; i < number_start; i++, j++)
906         {
907                 printf_string[j] = default_path[i];
908         }
910 // Found the number
911         sprintf(&printf_string[j], "%%0%dd", total_digits);
912         j = strlen(printf_string);
913         i += total_digits;
915 // Copy remainder of string
916         for( ; i < len; i++, j++)
917         {
918                 printf_string[j] = default_path[i];
919         }
920         printf_string[j] = 0;
921 // Print the printf argument to the path
922         sprintf(path, printf_string, current_number);
925 void Render::get_starting_number(char *path, 
926         int &current_number,
927         int &number_start, 
928         int &total_digits,
929         int min_digits)
931         int i, j;
932         int len = strlen(path);
933         char number_text[BCTEXTLEN];
934         char *ptr = 0;
935         char *ptr2 = 0;
937         total_digits = 0;
938         number_start = 0;
940 // Search for last /
941         ptr2 = strrchr(path, '/');
943 // Search for first 0 after last /.
944         if(ptr2)
945                 ptr = strchr(ptr2, '0');
947         if(ptr && isdigit(*ptr))
948         {
949                 number_start = ptr - path;
951 // Store the first number
952                 char *ptr2 = number_text;
953                 while(isdigit(*ptr))
954                         *ptr2++ = *ptr++;
955                 *ptr2++ = 0;
956                 current_number = atol(number_text);
957                 total_digits = strlen(number_text);
958         }
961 // No number found or number not long enough
962         if(total_digits < min_digits)
963         {
964                 current_number = 1;
965                 number_start = len;
966                 total_digits = min_digits;
967         }
976 int Render::load_defaults(Asset *asset)
978         strategy = mwindow->defaults->get("RENDER_STRATEGY", SINGLE_PASS);
979         load_mode = mwindow->defaults->get("RENDER_LOADMODE", LOAD_NEW_TRACKS);
982         asset->load_defaults(mwindow->defaults, 
983                 "RENDER_", 
984                 1,
985                 1,
986                 1,
987                 1,
988                 1);
991         return 0;
994 int Render::save_defaults(Asset *asset)
996         mwindow->defaults->update("RENDER_STRATEGY", strategy);
997         mwindow->defaults->update("RENDER_LOADMODE", load_mode);
1002         asset->save_defaults(mwindow->defaults, 
1003                 "RENDER_",
1004                 1,
1005                 1,
1006                 1,
1007                 1,
1008                 1);
1010         return 0;
1016 #define WIDTH 410
1017 #define HEIGHT 360
1020 RenderWindow::RenderWindow(MWindow *mwindow, Render *render, Asset *asset)
1021  : BC_Window(PROGRAM_NAME ": Render", 
1022         mwindow->gui->get_root_w(0, 1) / 2 - WIDTH / 2,
1023         mwindow->gui->get_root_h(1) / 2 - HEIGHT / 2,
1024         WIDTH, 
1025         HEIGHT,
1026         (int)BC_INFINITY,
1027         (int)BC_INFINITY,
1028         0,
1029         0,
1030         1)
1032         this->mwindow = mwindow;
1033         this->render = render;
1034         this->asset = asset;
1037 RenderWindow::~RenderWindow()
1039         delete format_tools;
1040         delete loadmode;
1045 int RenderWindow::create_objects()
1047         int x = 5, y = 5;
1048         add_subwindow(new BC_Title(x, 
1049                 y, 
1050                 (char*)((render->strategy == FILE_PER_LABEL || 
1051                                 render->strategy == FILE_PER_LABEL_FARM) ? 
1052                         _("Select the first file to render to:") : 
1053                         _("Select a file to render to:"))));
1054         y += 25;
1056         format_tools = new FormatTools(mwindow,
1057                                         this, 
1058                                         asset);
1059         format_tools->create_objects(x, 
1060                 y, 
1061                 1, 
1062                 1, 
1063                 1, 
1064                 1, 
1065                 0,
1066                 1,
1067                 0,
1068                 0,
1069                 &render->strategy,
1070                 0);
1072         loadmode = new LoadMode(mwindow, this, x, y, &render->load_mode, 1);
1073         loadmode->create_objects();
1075         add_subwindow(new BC_OKButton(this));
1076         add_subwindow(new BC_CancelButton(this));
1077         show_window();
1078         return 0;