r860: Merge 2.1:
[cinelerra_cv.git] / cinelerra / render.C
blobc94fd199245dd1b698feae6cd435c75790bc8f5c
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 "bchash.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         BC_Hash *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 printf("Render::run 1\n");
320                 Asset *asset = new Asset;
321                 load_defaults(asset);
322 printf("Render::run 2\n");
323                 check_asset(mwindow->edl, *asset);
324 printf("Render::run 3\n");
326 // Get format from user
327                 if(!result)
328                 {
329 printf("Render::run 4\n");
330                         do
331                         {
332                                 format_error = 0;
333                                 result = 0;
335                                 {
336 printf("Render::run 5\n");
337                                         RenderWindow window(mwindow, this, asset);
338 printf("Render::run 6\n");
339                                         window.create_objects();
340 printf("Render::run 7\n");
341                                         result = window.run_window();
342 printf("Render::run 8\n");
343                                         if (! result) {
344                                                 // add to recentlist only on OK
345                                                 window.format_tools->path_recent->add_item(FILE_FORMAT_PREFIX(asset->format), asset->path);
346                                         }
347                                 }
349                                 if(!result)
350                                 {
351 printf("Render::run 8.1\n");
352 // Check the asset format for errors.
353                                         FormatCheck format_check(asset);
354 printf("Render::run 8.2\n");
355                                         format_error = format_check.check_format();
356 printf("Render::run 8.3\n");
357                                 }
358                         }while(format_error && !result);
359                 }
360 printf("Render::run 9\n");
362                 save_defaults(asset);
363                 mwindow->save_defaults();
364 printf("Render::run 10\n");
366                 if(!result) render(1, asset, mwindow->edl, strategy);
367 printf("Render::run 11\n");
369                 Garbage::delete_object(asset);
370 printf("Render::run 12\n");
371         }
372         else
373         if(mode == Render::BATCH)
374         {
375                 for(int i = 0; i < jobs->total && !result; i++)
376                 {
377                         BatchRenderJob *job = jobs->values[i];
378                         if(job->enabled)
379                         {
380                                 if(mwindow)
381                                 {
382                                         mwindow->batch_render->update_active(i);
383                                 }
384                                 else
385                                 {
386                                         printf("Render::run: %s\n", job->edl_path);
387                                 }
390                                 FileXML *file = new FileXML;
391                                 EDL *edl = new EDL;
392                                 edl->create_objects();
393                                 file->read_from_file(job->edl_path);
394                                 if(!plugindb && mwindow)
395                                         plugindb = mwindow->plugindb;
396                                 edl->load_xml(plugindb, file, LOAD_ALL);
398                                 check_asset(edl, *job->asset);
399                                 render(0, job->asset, edl, job->strategy);
401                                 delete edl;
402                                 delete file;
403                                 if(!result)
404                                 {
405                                         if(mwindow)
406                                                 mwindow->batch_render->update_done(i, 1, elapsed_time);
407                                         else
408                                         {
409                                                 char string[BCTEXTLEN];
410                                                 elapsed_time = 
411                                                         (double)progress_timer->get_scaled_difference(1);
412                                                 Units::totext(string,
413                                                         elapsed_time,
414                                                         TIME_HMS2);
415                                                 printf("Render::run: done in %s\n", string);
416                                         }
417                                 }
418                                 else
419                                 {
420                                         if(mwindow)
421                                                 mwindow->batch_render->update_active(-1);
422                                         else
423                                                 printf("Render::run: failed\n");
424                                 }
425                         }
426                 }
428                 if(mwindow)
429                 {
430                         mwindow->batch_render->update_active(-1);
431                         mwindow->batch_render->update_done(-1, 0, 0);
432                 }
433         }
434 printf("Render::run 100\n");
439 int Render::check_asset(EDL *edl, Asset &asset)
441         if(asset.video_data && 
442                 edl->tracks->playable_video_tracks() &&
443                 File::supports_video(asset.format))
444         {
445                 asset.video_data = 1;
446                 asset.layers = 1;
447                 asset.width = edl->session->output_w;
448                 asset.height = edl->session->output_h;
449                 asset.interlace_mode = edl->session->interlace_mode;
450                 asset.tcstart = (int64_t) (edl->session->get_frame_offset() +
451                         edl->local_session->get_selectionstart() *
452                                 edl->session->frame_rate);
453                 asset.tcend = (int64_t) (edl->session->get_frame_offset() +
454                         edl->local_session->get_selectionend() *
455                                 edl->session->frame_rate);
456         }
457         else
458         {
459                 asset.video_data = 0;
460                 asset.layers = 0;
461                 asset.tcstart = 0;
462                 asset.tcend = 0;
463         }
465         if(asset.audio_data && 
466                 edl->tracks->playable_audio_tracks() &&
467                 File::supports_audio(asset.format))
468         {
469                 asset.audio_data = 1;
470                 asset.channels = edl->session->audio_channels;
471                 if(asset.format == FILE_MOV) asset.byte_order = 0;
472                 asset.tcstart = (int64_t) (edl->session->get_frame_offset() +
473                         edl->local_session->get_selectionstart() *
474                                 edl->session->sample_rate);
475                 asset.tcend = (int64_t) (edl->session->get_frame_offset() +
476                         edl->local_session->get_selectionend() *
477                                 edl->session->sample_rate);
478         }
479         else
480         {
481                 asset.audio_data = 0;
482                 asset.channels = 0;
483                 asset.tcstart = 0;
484                 asset.tcend = 0;
485         }
487         if(!asset.audio_data &&
488                 !asset.video_data)
489         {
490                 return 1;
491         }
492         return 0;
495 int Render::fix_strategy(int strategy, int use_renderfarm)
497         if(use_renderfarm)
498         {
499                 if(strategy == FILE_PER_LABEL)
500                         strategy = FILE_PER_LABEL_FARM;
501                 else
502                 if(strategy == SINGLE_PASS)
503                         strategy = SINGLE_PASS_FARM;
504         }
505         else
506         {
507                 if(strategy == FILE_PER_LABEL_FARM)
508                         strategy = FILE_PER_LABEL;
509                 else
510                 if(strategy == SINGLE_PASS_FARM)
511                         strategy = SINGLE_PASS;
512         }
513         return strategy;
516 void Render::start_progress()
518         char filename[BCTEXTLEN];
519         char string[BCTEXTLEN];
520         FileSystem fs;
522         progress_max = packages->get_progress_max();
524         progress_timer->update();
525         last_eta = 0;
526         if(mwindow)
527         {
528 // Generate the progress box
529                 fs.extract_name(filename, default_asset->path);
530                 sprintf(string, _("Rendering %s..."), filename);
532 // Don't bother with the filename since renderfarm defeats the meaning
533                 progress = mwindow->mainprogress->start_progress(_("Rendering..."), 
534                         progress_max);
535                 render_progress = new RenderProgress(mwindow, this);
536                 render_progress->start();
537         }
540 void Render::stop_progress()
542         if(progress)
543         {
544                 char string[BCTEXTLEN], string2[BCTEXTLEN];
545                 delete render_progress;
546                 progress->get_time(string);
547                 elapsed_time = progress->get_time();
548                 progress->stop_progress();
549                 delete progress;
551                 sprintf(string2, _("Rendering took %s"), string);
552                 mwindow->gui->lock_window("");
553                 mwindow->gui->show_message(string2);
554                 mwindow->gui->stop_hourglass();
555                 mwindow->gui->unlock_window();
556         }
557         progress = 0;
562 int Render::render(int test_overwrite, 
563         Asset *asset,
564         EDL *edl,
565         int strategy)
567         char string[BCTEXTLEN];
568 // Total length in seconds
569         double total_length;
570         int last_audio_buffer;
571         RenderFarmServer *farm_server = 0;
572         FileSystem fs;
573         int total_digits;      // Total number of digits including padding the user specified.
574         int number_start;      // Character in the filename path at which the number begins
575         int current_number;    // The number the being injected into the filename.
576 // Pointer from file
577 // (VFrame*)(VFrame array [])(Channel [])
578         VFrame ***video_output;
579 // Pointer to output buffers
580         VFrame *video_output_ptr[MAX_CHANNELS];
581         double *audio_output_ptr[MAX_CHANNELS];
582         int done = 0;
583         in_progress = 1;
586         this->default_asset = asset;
587         progress = 0;
588         result = 0;
590         if(mwindow)
591         {
592                 if(!preferences)
593                         preferences = new Preferences;
595                 preferences->copy_from(mwindow->preferences);
596         }
599 // Create rendering command
600         command = new TransportCommand;
601         command->command = NORMAL_FWD;
602         command->get_edl()->copy_all(edl);
603         command->change_type = CHANGE_ALL;
604 // Get highlighted playback range
605         command->set_playback_range();
606 // Adjust playback range with in/out points
607         command->adjust_playback_range();
608         packages = new PackageDispatcher;
611 // Configure preview monitor
612         VideoOutConfig vconfig;
613         PlaybackConfig *playback_config = new PlaybackConfig;
614         for(int i = 0; i < MAX_CHANNELS; i++)
615         {
616                 vconfig.do_channel[i] = (i < command->get_edl()->session->video_channels);
617                 playback_config->vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
618         }
620 // Create caches
621         audio_cache = new CICache(preferences, plugindb);
622         video_cache = new CICache(preferences, plugindb);
624         default_asset->frame_rate = command->get_edl()->session->frame_rate;
625         default_asset->sample_rate = command->get_edl()->session->sample_rate;
627 // Conform asset to EDL.  Find out if any tracks are playable.
628         result = check_asset(command->get_edl(), *default_asset);
630         if(!result)
631         {
632 // Get total range to render
633                 total_start = command->start_position;
634                 total_end = command->end_position;
635                 total_length = total_end - total_start;
637 // Nothing to render
638                 if(EQUIV(total_length, 0))
639                 {
640                         result = 1;
641                 }
642         }
650 // Generate packages
651         if(!result)
652         {
653 // Stop background rendering
654                 if(mwindow) mwindow->stop_brender();
656                 fs.complete_path(default_asset->path);
657                 strategy = Render::fix_strategy(strategy, preferences->use_renderfarm);
659                 result = packages->create_packages(mwindow,
660                         command->get_edl(),
661                         preferences,
662                         strategy, 
663                         default_asset, 
664                         total_start, 
665                         total_end,
666                         test_overwrite);
667         }
678         done = 0;
679         total_rendered = 0;
680         frames_per_second = 0;
682         if(!result)
683         {
684 // Start dispatching external jobs
685                 if(mwindow)
686                 {
687                         mwindow->gui->lock_window("Render::render 1");
688                         mwindow->gui->show_message(_("Starting render farm"));
689                         mwindow->gui->start_hourglass();
690                         mwindow->gui->unlock_window();
691                 }
692                 else
693                 {
694                         printf("Render::render: starting render farm\n");
695                 }
697                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
698                 {
699                         farm_server = new RenderFarmServer(plugindb, 
700                                 packages,
701                                 preferences, 
702                                 1,
703                                 &result,
704                                 &total_rendered,
705                                 counter_lock,
706                                 default_asset,
707                                 command->get_edl(),
708                                 0);
709                         result = farm_server->start_clients();
711                         if(result)
712                         {
713                                 if(mwindow)
714                                 {
715                                         mwindow->gui->lock_window("Render::render 2");
716                                         mwindow->gui->show_message(_("Failed to start render farm"),
717                                                 mwindow->theme->message_error);
718                                         mwindow->gui->stop_hourglass();
719                                         mwindow->gui->unlock_window();
720                                 }
721                                 else
722                                 {
723                                         printf("Render::render: Failed to start render farm\n");
724                                 }
725                         }
726                 }
727         }
732 // Perform local rendering
735         if(!result)
736         {
737                 start_progress();
738         
742                 MainPackageRenderer package_renderer(this);
743                 result = package_renderer.initialize(mwindow,
744                                 command->get_edl(),   // Copy of master EDL
745                                 preferences, 
746                                 default_asset,
747                                 plugindb);
755                 while(!result)
756                 {
757 // Get unfinished job
758                         RenderPackage *package;
760                         if(strategy == SINGLE_PASS_FARM)
761                         {
762                                 package = packages->get_package(frames_per_second, -1, 1);
763                         }
764                         else
765                         {
766                                 package = packages->get_package(0, -1, 1);
767                         }
769 // Exit point
770                         if(!package) 
771                         {
772                                 done = 1;
773                                 break;
774                         }
778                         Timer timer;
779                         timer.update();
781                         if(package_renderer.render_package(package))
782                                 result = 1;
784 // Result is also set directly by the RenderFarm.
786                         frames_per_second = (double)(package->video_end - package->video_start) / 
787                                 (double)(timer.get_difference() / 1000);
790                 } // file_number
794 printf("Render::run: Session finished.\n");
800                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
801                 {
802                         farm_server->wait_clients();
803                         result |= packages->packages_are_done();
804                 }
806 printf("Render::render 90\n");
808 // Notify of error
809                 if(result && 
810                         (!progress || !progress->is_cancelled()) &&
811                         !batch_cancelled)
812                 {
813                         if(mwindow)
814                         {
815                                 ErrorBox error_box(PROGRAM_NAME ": Error",
816                                         mwindow->gui->get_abs_cursor_x(1),
817                                         mwindow->gui->get_abs_cursor_y(1));
818                                 error_box.create_objects(_("Error rendering data."));
819                                 error_box.raise_window();
820                                 error_box.run_window();
821                         }
822                         else
823                         {
824                                 printf("Render::render: Error rendering data\n");
825                         }
826                 }
828 // Delete the progress box
829                 stop_progress();
831 //printf("Render::render 100\n");
836         }
839 // Paste all packages into timeline if desired
841         if(!result && 
842                 load_mode != LOAD_NOTHING && 
843                 mwindow &&
844                 mode != Render::BATCH)
845         {
846                 mwindow->gui->lock_window("Render::render 3");
851                 ArrayList<Asset*> *assets = packages->get_asset_list();
852                 if(load_mode == LOAD_PASTE)
853                         mwindow->clear(0);
854                 mwindow->load_assets(assets, 
855                         -1, 
856                         load_mode,
857                         0,
858                         0,
859                         mwindow->edl->session->labels_follow_edits,
860                         mwindow->edl->session->plugins_follow_edits);
861                 assets->remove_all_objects();
862                 delete assets;
865                 mwindow->save_backup();
866                 mwindow->undo->update_undo(_("render"), LOAD_ALL);
867                 mwindow->update_plugin_guis();
868                 mwindow->gui->update(1, 
869                         2,
870                         1,
871                         1,
872                         1,
873                         1,
874                         0);
875                 mwindow->sync_parameters(CHANGE_ALL);
876                 mwindow->gui->unlock_window();
877         }
880 // Disable hourglass
881         if(mwindow)
882         {
883                 mwindow->gui->lock_window("Render::render 3");
884                 mwindow->gui->stop_hourglass();
885                 mwindow->gui->unlock_window();
886         }
888 //printf("Render::render 110\n");
889 // Need to restart because brender always stops before render.
890         if(mwindow)
891                 mwindow->restart_brender();
892         if(farm_server) delete farm_server;
893         delete command;
894         delete playback_config;
895         delete audio_cache;
896         delete video_cache;
897 // Must delete packages after server
898         delete packages;
899         in_progress = 0;
900         completion->unlock();
901 //printf("Render::render 120\n");
903         return result;
907 void Render::create_filename(char *path, 
908         char *default_path, 
909         int current_number,
910         int total_digits,
911         int number_start)
913         int i, j, k;
914         int len = strlen(default_path);
915         char printf_string[BCTEXTLEN];
916         int found_number = 0;
918         for(i = 0, j = 0; i < number_start; i++, j++)
919         {
920                 printf_string[j] = default_path[i];
921         }
923 // Found the number
924         sprintf(&printf_string[j], "%%0%dd", total_digits);
925         j = strlen(printf_string);
926         i += total_digits;
928 // Copy remainder of string
929         for( ; i < len; i++, j++)
930         {
931                 printf_string[j] = default_path[i];
932         }
933         printf_string[j] = 0;
934 // Print the printf argument to the path
935         sprintf(path, printf_string, current_number);
938 void Render::get_starting_number(char *path, 
939         int &current_number,
940         int &number_start, 
941         int &total_digits,
942         int min_digits)
944         int i, j;
945         int len = strlen(path);
946         char number_text[BCTEXTLEN];
947         char *ptr = 0;
948         char *ptr2 = 0;
950         total_digits = 0;
951         number_start = 0;
953 // Search for last /
954         ptr2 = strrchr(path, '/');
956 // Search for first 0 after last /.
957         if(ptr2)
958                 ptr = strchr(ptr2, '0');
960         if(ptr && isdigit(*ptr))
961         {
962                 number_start = ptr - path;
964 // Store the first number
965                 char *ptr2 = number_text;
966                 while(isdigit(*ptr))
967                         *ptr2++ = *ptr++;
968                 *ptr2++ = 0;
969                 current_number = atol(number_text);
970                 total_digits = strlen(number_text);
971         }
974 // No number found or number not long enough
975         if(total_digits < min_digits)
976         {
977                 current_number = 1;
978                 number_start = len;
979                 total_digits = min_digits;
980         }
989 int Render::load_defaults(Asset *asset)
991         strategy = mwindow->defaults->get("RENDER_STRATEGY", SINGLE_PASS);
992         load_mode = mwindow->defaults->get("RENDER_LOADMODE", LOAD_NEW_TRACKS);
995         asset->load_defaults(mwindow->defaults, 
996                 "RENDER_", 
997                 1,
998                 1,
999                 1,
1000                 1,
1001                 1);
1004         return 0;
1007 int Render::save_defaults(Asset *asset)
1009         mwindow->defaults->update("RENDER_STRATEGY", strategy);
1010         mwindow->defaults->update("RENDER_LOADMODE", load_mode);
1015         asset->save_defaults(mwindow->defaults, 
1016                 "RENDER_",
1017                 1,
1018                 1,
1019                 1,
1020                 1,
1021                 1);
1023         return 0;
1029 #define WIDTH 410
1030 #define HEIGHT 360
1033 RenderWindow::RenderWindow(MWindow *mwindow, Render *render, Asset *asset)
1034  : BC_Window(PROGRAM_NAME ": Render", 
1035         mwindow->gui->get_root_w(0, 1) / 2 - WIDTH / 2,
1036         mwindow->gui->get_root_h(1) / 2 - HEIGHT / 2,
1037         WIDTH, 
1038         HEIGHT,
1039         (int)BC_INFINITY,
1040         (int)BC_INFINITY,
1041         0,
1042         0,
1043         1)
1045         this->mwindow = mwindow;
1046         this->render = render;
1047         this->asset = asset;
1050 RenderWindow::~RenderWindow()
1052         delete format_tools;
1053         delete loadmode;
1058 int RenderWindow::create_objects()
1060         int x = 5, y = 5;
1061         add_subwindow(new BC_Title(x, 
1062                 y, 
1063                 (char*)((render->strategy == FILE_PER_LABEL || 
1064                                 render->strategy == FILE_PER_LABEL_FARM) ? 
1065                         _("Select the first file to render to:") : 
1066                         _("Select a file to render to:"))));
1067         y += 25;
1069         format_tools = new FormatTools(mwindow,
1070                                         this, 
1071                                         asset);
1072         format_tools->create_objects(x, 
1073                 y, 
1074                 1, 
1075                 1, 
1076                 1, 
1077                 1, 
1078                 0,
1079                 1,
1080                 0,
1081                 0,
1082                 &render->strategy,
1083                 0);
1085         loadmode = new LoadMode(mwindow, this, x, y, &render->load_mode, 1);
1086         loadmode->create_objects();
1088         add_subwindow(new BC_OKButton(this));
1089         add_subwindow(new BC_CancelButton(this));
1090         show_window();
1091         return 0;