r858: Merge 2.1:
[cinelerra_cv.git] / cinelerra / render.C
blobea4cc2680a472e6566e98b7a8d962d498e0f93f9
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                 playback_config->aconfig->do_channel[i] = (i < command->get_edl()->session->audio_channels);
619         }
621 // Create caches
622         audio_cache = new CICache(preferences, plugindb);
623         video_cache = new CICache(preferences, plugindb);
625         default_asset->frame_rate = command->get_edl()->session->frame_rate;
626         default_asset->sample_rate = command->get_edl()->session->sample_rate;
628 // Conform asset to EDL.  Find out if any tracks are playable.
629         result = check_asset(command->get_edl(), *default_asset);
631         if(!result)
632         {
633 // Get total range to render
634                 total_start = command->start_position;
635                 total_end = command->end_position;
636                 total_length = total_end - total_start;
638 // Nothing to render
639                 if(EQUIV(total_length, 0))
640                 {
641                         result = 1;
642                 }
643         }
651 // Generate packages
652         if(!result)
653         {
654 // Stop background rendering
655                 if(mwindow) mwindow->stop_brender();
657                 fs.complete_path(default_asset->path);
658                 strategy = Render::fix_strategy(strategy, preferences->use_renderfarm);
660                 result = packages->create_packages(mwindow,
661                         command->get_edl(),
662                         preferences,
663                         strategy, 
664                         default_asset, 
665                         total_start, 
666                         total_end,
667                         test_overwrite);
668         }
679         done = 0;
680         total_rendered = 0;
681         frames_per_second = 0;
683         if(!result)
684         {
685 // Start dispatching external jobs
686                 if(mwindow)
687                 {
688                         mwindow->gui->lock_window("Render::render 1");
689                         mwindow->gui->show_message(_("Starting render farm"));
690                         mwindow->gui->start_hourglass();
691                         mwindow->gui->unlock_window();
692                 }
693                 else
694                 {
695                         printf("Render::render: starting render farm\n");
696                 }
698                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
699                 {
700                         farm_server = new RenderFarmServer(plugindb, 
701                                 packages,
702                                 preferences, 
703                                 1,
704                                 &result,
705                                 &total_rendered,
706                                 counter_lock,
707                                 default_asset,
708                                 command->get_edl(),
709                                 0);
710                         result = farm_server->start_clients();
712                         if(result)
713                         {
714                                 if(mwindow)
715                                 {
716                                         mwindow->gui->lock_window("Render::render 2");
717                                         mwindow->gui->show_message(_("Failed to start render farm"),
718                                                 mwindow->theme->message_error);
719                                         mwindow->gui->stop_hourglass();
720                                         mwindow->gui->unlock_window();
721                                 }
722                                 else
723                                 {
724                                         printf("Render::render: Failed to start render farm\n");
725                                 }
726                         }
727                 }
728         }
733 // Perform local rendering
736         if(!result)
737         {
738                 start_progress();
739         
743                 MainPackageRenderer package_renderer(this);
744                 result = package_renderer.initialize(mwindow,
745                                 command->get_edl(),   // Copy of master EDL
746                                 preferences, 
747                                 default_asset,
748                                 plugindb);
756                 while(!result)
757                 {
758 // Get unfinished job
759                         RenderPackage *package;
761                         if(strategy == SINGLE_PASS_FARM)
762                         {
763                                 package = packages->get_package(frames_per_second, -1, 1);
764                         }
765                         else
766                         {
767                                 package = packages->get_package(0, -1, 1);
768                         }
770 // Exit point
771                         if(!package) 
772                         {
773                                 done = 1;
774                                 break;
775                         }
779                         Timer timer;
780                         timer.update();
782                         if(package_renderer.render_package(package))
783                                 result = 1;
785 // Result is also set directly by the RenderFarm.
787                         frames_per_second = (double)(package->video_end - package->video_start) / 
788                                 (double)(timer.get_difference() / 1000);
791                 } // file_number
795 printf("Render::run: Session finished.\n");
801                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
802                 {
803                         farm_server->wait_clients();
804                         result |= packages->packages_are_done();
805                 }
807 printf("Render::render 90\n");
809 // Notify of error
810                 if(result && 
811                         (!progress || !progress->is_cancelled()) &&
812                         !batch_cancelled)
813                 {
814                         if(mwindow)
815                         {
816                                 ErrorBox error_box(PROGRAM_NAME ": Error",
817                                         mwindow->gui->get_abs_cursor_x(1),
818                                         mwindow->gui->get_abs_cursor_y(1));
819                                 error_box.create_objects(_("Error rendering data."));
820                                 error_box.raise_window();
821                                 error_box.run_window();
822                         }
823                         else
824                         {
825                                 printf("Render::render: Error rendering data\n");
826                         }
827                 }
829 // Delete the progress box
830                 stop_progress();
832 //printf("Render::render 100\n");
837         }
840 // Paste all packages into timeline if desired
842         if(!result && 
843                 load_mode != LOAD_NOTHING && 
844                 mwindow &&
845                 mode != Render::BATCH)
846         {
847                 mwindow->gui->lock_window("Render::render 3");
852                 ArrayList<Asset*> *assets = packages->get_asset_list();
853                 if(load_mode == LOAD_PASTE)
854                         mwindow->clear(0);
855                 mwindow->load_assets(assets, 
856                         -1, 
857                         load_mode,
858                         0,
859                         0,
860                         mwindow->edl->session->labels_follow_edits,
861                         mwindow->edl->session->plugins_follow_edits);
862                 assets->remove_all_objects();
863                 delete assets;
866                 mwindow->save_backup();
867                 mwindow->undo->update_undo(_("render"), LOAD_ALL);
868                 mwindow->update_plugin_guis();
869                 mwindow->gui->update(1, 
870                         2,
871                         1,
872                         1,
873                         1,
874                         1,
875                         0);
876                 mwindow->sync_parameters(CHANGE_ALL);
877                 mwindow->gui->unlock_window();
878         }
881 // Disable hourglass
882         if(mwindow)
883         {
884                 mwindow->gui->lock_window("Render::render 3");
885                 mwindow->gui->stop_hourglass();
886                 mwindow->gui->unlock_window();
887         }
889 //printf("Render::render 110\n");
890 // Need to restart because brender always stops before render.
891         if(mwindow)
892                 mwindow->restart_brender();
893         if(farm_server) delete farm_server;
894         delete command;
895         delete playback_config;
896         delete audio_cache;
897         delete video_cache;
898 // Must delete packages after server
899         delete packages;
900         in_progress = 0;
901         completion->unlock();
902 //printf("Render::render 120\n");
904         return result;
908 void Render::create_filename(char *path, 
909         char *default_path, 
910         int current_number,
911         int total_digits,
912         int number_start)
914         int i, j, k;
915         int len = strlen(default_path);
916         char printf_string[BCTEXTLEN];
917         int found_number = 0;
919         for(i = 0, j = 0; i < number_start; i++, j++)
920         {
921                 printf_string[j] = default_path[i];
922         }
924 // Found the number
925         sprintf(&printf_string[j], "%%0%dd", total_digits);
926         j = strlen(printf_string);
927         i += total_digits;
929 // Copy remainder of string
930         for( ; i < len; i++, j++)
931         {
932                 printf_string[j] = default_path[i];
933         }
934         printf_string[j] = 0;
935 // Print the printf argument to the path
936         sprintf(path, printf_string, current_number);
939 void Render::get_starting_number(char *path, 
940         int &current_number,
941         int &number_start, 
942         int &total_digits,
943         int min_digits)
945         int i, j;
946         int len = strlen(path);
947         char number_text[BCTEXTLEN];
948         char *ptr = 0;
949         char *ptr2 = 0;
951         total_digits = 0;
952         number_start = 0;
954 // Search for last /
955         ptr2 = strrchr(path, '/');
957 // Search for first 0 after last /.
958         if(ptr2)
959                 ptr = strchr(ptr2, '0');
961         if(ptr && isdigit(*ptr))
962         {
963                 number_start = ptr - path;
965 // Store the first number
966                 char *ptr2 = number_text;
967                 while(isdigit(*ptr))
968                         *ptr2++ = *ptr++;
969                 *ptr2++ = 0;
970                 current_number = atol(number_text);
971                 total_digits = strlen(number_text);
972         }
975 // No number found or number not long enough
976         if(total_digits < min_digits)
977         {
978                 current_number = 1;
979                 number_start = len;
980                 total_digits = min_digits;
981         }
990 int Render::load_defaults(Asset *asset)
992         strategy = mwindow->defaults->get("RENDER_STRATEGY", SINGLE_PASS);
993         load_mode = mwindow->defaults->get("RENDER_LOADMODE", LOAD_NEW_TRACKS);
996         asset->load_defaults(mwindow->defaults, 
997                 "RENDER_", 
998                 1,
999                 1,
1000                 1,
1001                 1,
1002                 1);
1005         return 0;
1008 int Render::save_defaults(Asset *asset)
1010         mwindow->defaults->update("RENDER_STRATEGY", strategy);
1011         mwindow->defaults->update("RENDER_LOADMODE", load_mode);
1016         asset->save_defaults(mwindow->defaults, 
1017                 "RENDER_",
1018                 1,
1019                 1,
1020                 1,
1021                 1,
1022                 1);
1024         return 0;
1030 #define WIDTH 410
1031 #define HEIGHT 360
1034 RenderWindow::RenderWindow(MWindow *mwindow, Render *render, Asset *asset)
1035  : BC_Window(PROGRAM_NAME ": Render", 
1036         mwindow->gui->get_root_w(0, 1) / 2 - WIDTH / 2,
1037         mwindow->gui->get_root_h(1) / 2 - HEIGHT / 2,
1038         WIDTH, 
1039         HEIGHT,
1040         (int)BC_INFINITY,
1041         (int)BC_INFINITY,
1042         0,
1043         0,
1044         1)
1046         this->mwindow = mwindow;
1047         this->render = render;
1048         this->asset = asset;
1051 RenderWindow::~RenderWindow()
1053         delete format_tools;
1054         delete loadmode;
1059 int RenderWindow::create_objects()
1061         int x = 5, y = 5;
1062         add_subwindow(new BC_Title(x, 
1063                 y, 
1064                 (char*)((render->strategy == FILE_PER_LABEL || 
1065                                 render->strategy == FILE_PER_LABEL_FARM) ? 
1066                         _("Select the first file to render to:") : 
1067                         _("Select a file to render to:"))));
1068         y += 25;
1070         format_tools = new FormatTools(mwindow,
1071                                         this, 
1072                                         asset);
1073         format_tools->create_objects(x, 
1074                 y, 
1075                 1, 
1076                 1, 
1077                 1, 
1078                 1, 
1079                 0,
1080                 1,
1081                 0,
1082                 0,
1083                 &render->strategy,
1084                 0);
1086         loadmode = new LoadMode(mwindow, this, x, y, &render->load_mode, 1);
1087         loadmode->create_objects();
1089         add_subwindow(new BC_OKButton(this));
1090         add_subwindow(new BC_CancelButton(this));
1091         show_window();
1092         return 0;