d4dabf3de9316c72d5b9ba6ae3b8b052e59864f9
[goodguy/history.git] / cinelerra-5.0 / cinelerra / render.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "arender.h"
23 #include "asset.h"
24 #include "auto.h"
25 #include "awindow.h"
26 #include "awindowgui.h"
27 #include "batchrender.h"
28 #include "bcprogressbox.h"
29 #include "bcsignals.h"
30 #include "cache.h"
31 #include "clip.h"
32 #include "compresspopup.h"
33 #include "condition.h"
34 #include "confirmsave.h"
35 #include "cwindowgui.h"
36 #include "cwindow.h"
37 #include "bchash.h"
38 #include "edits.h"
39 #include "edl.h"
40 #include "edlsession.h"
41 #include "errorbox.h"
42 #include "file.h"
43 #include "filesystem.h"
44 #include "filexml.h"
45 #include "formatcheck.h"
46 #include "formatpopup.h"
47 #include "formattools.h"
48 #include "indexable.h"
49 #include "labels.h"
50 #include "language.h"
51 #include "loadmode.h"
52 #include "localsession.h"
53 #include "mainprogress.h"
54 #include "mainsession.h"
55 #include "mainundo.h"
56 #include "module.h"
57 #include "mutex.h"
58 #include "mwindowgui.h"
59 #include "mwindow.h"
60 #include "packagedispatcher.h"
61 #include "packagerenderer.h"
62 #include "patchbay.h"
63 #include "playabletracks.h"
64 #include "preferences.h"
65 #include "preferencesthread.h"
66 #include "quicktime.h"
67 #include "renderfarm.h"
68 #include "render.h"
69 #include "statusbar.h"
70 #include "theme.h"
71 #include "timebar.h"
72 #include "tracks.h"
73 #include "transportque.h"
74 #include "vedit.h"
75 #include "vframe.h"
76 #include "videoconfig.h"
77 #include "vrender.h"
78
79 #include <ctype.h>
80 #include <string.h>
81
82
83
84 RenderItem::RenderItem(MWindow *mwindow)
85  : BC_MenuItem(_("Render..."), _("Shift+R"), 'R')
86 {
87         this->mwindow = mwindow;
88         set_shift(1);
89 }
90
91 int RenderItem::handle_event() 
92 {
93         mwindow->gui->unlock_window();
94         mwindow->render->start_interactive();
95         mwindow->gui->lock_window("RenderItem::handle_event");
96         return 1;
97 }
98
99
100
101
102
103
104
105
106
107
108 RenderProgress::RenderProgress(MWindow *mwindow, Render *render)
109  : Thread(1, 0, 0)
110 {
111         this->mwindow = mwindow;
112         this->render = render;
113         last_value = 0;
114         Thread::set_synchronous(1);
115 }
116
117 RenderProgress::~RenderProgress()
118 {
119         Thread::cancel();
120         Thread::join();
121 }
122
123
124 void RenderProgress::run()
125 {
126         Thread::disable_cancel();
127         while(1)
128         {
129                 if(render->total_rendered != last_value)
130                 {
131                         render->progress->update(render->total_rendered);
132                         last_value = render->total_rendered;
133                         
134                         if(mwindow) mwindow->preferences_thread->update_rates();
135                 }
136
137                 Thread::enable_cancel();
138                 sleep(1);
139                 Thread::disable_cancel();
140         }
141 }
142
143
144
145
146
147
148
149
150
151
152 MainPackageRenderer::MainPackageRenderer(Render *render)
153  : PackageRenderer()
154 {
155         this->render = render;
156 }
157
158
159
160 MainPackageRenderer::~MainPackageRenderer()
161 {
162 }
163
164
165 int MainPackageRenderer::get_master()
166 {
167         return 1;
168 }
169
170 int MainPackageRenderer::get_result()
171 {
172         return render->result;
173 }
174
175 void MainPackageRenderer::set_result(int value)
176 {
177         if(value)
178                 render->result = value;
179         
180         
181         
182 }
183
184 void MainPackageRenderer::set_progress(int64_t value)
185 {
186         render->counter_lock->lock("MainPackageRenderer::set_progress");
187 // Increase total rendered for all nodes
188         render->total_rendered += value;
189
190 // Update frames per second for master node
191         render->preferences->set_rate(frames_per_second, -1);
192
193 //printf("MainPackageRenderer::set_progress %d %ld %f\n", __LINE__, (long)value, frames_per_second);
194
195 // If non interactive, print progress out
196         if(!render->progress)
197         {
198                 int64_t current_eta = render->progress_timer->get_scaled_difference(1000);
199                 if(current_eta - render->last_eta > 1000)
200                 {
201                         double eta = 0;
202
203
204                         if(render->total_rendered)
205                         {
206                                 eta = current_eta /
207                                         1000 *
208                                         render->progress_max /
209                                         render->total_rendered -
210                                         current_eta /
211                                         1000;
212                         }
213
214                         char string[BCTEXTLEN];
215                         Units::totext(string, 
216                                 eta,
217                                 TIME_HMS2);
218
219                         printf(_("\r%d%% ETA: %s      "), (int)(100 * 
220                                 (float)render->total_rendered / 
221                                         render->progress_max),
222                                 string);
223                         fflush(stdout);
224                         render->last_eta = current_eta;
225                 }
226         }
227
228         render->counter_lock->unlock();
229
230 // This locks the preferences
231         if(mwindow) mwindow->preferences->copy_rates_from(preferences);
232 }
233
234 int MainPackageRenderer::progress_cancelled()
235 {
236         return (render->progress && render->progress->is_cancelled()) || 
237                 render->batch_cancelled;
238 }
239
240
241
242
243
244
245
246
247
248
249
250
251 Render::Render(MWindow *mwindow)
252  : BC_DialogThread()
253 {
254         this->mwindow = mwindow;
255         in_progress = 0;
256         progress = 0;
257         preferences = 0;
258         elapsed_time = 0.0;
259         package_lock = new Mutex("Render::package_lock");
260         counter_lock = new Mutex("Render::counter_lock");
261         completion = new Condition(0, "Render::completion");
262         progress_timer = new Timer;
263         thread = new RenderThread(mwindow, this);
264         asset = 0;
265         result = 0;
266 }
267
268 Render::~Render()
269 {
270         close_window();
271         delete package_lock;
272         delete counter_lock;
273         delete completion;
274 // May be owned by someone else.  This is owned by mwindow, so we don't care
275 // about deletion.
276 //      delete preferences;
277         delete progress_timer;
278         if( asset ) asset->Garbage::remove_user();
279         delete thread;
280 }
281
282 void Render::start_interactive()
283 {
284         if(!thread->running())
285         {
286                 mode = Render::INTERACTIVE;
287                 BC_DialogThread::start();
288         }
289         else
290         {
291                 ErrorBox error_box(_(PROGRAM_NAME ": Error"),
292                         mwindow->gui->get_abs_cursor_x(1),
293                         mwindow->gui->get_abs_cursor_y(1));
294                 error_box.create_objects(_("Already rendering"));
295                 error_box.raise_window();
296                 error_box.run_window();
297         }
298 }
299
300
301 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs)
302 {
303         if(!thread->running())
304         {
305                 mode = Render::BATCH;
306                 batch_cancelled = 0;
307                 this->jobs = jobs;
308                 completion->reset();
309                 start_render();
310         }
311 }
312
313 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs,
314         BC_Hash *boot_defaults,
315         Preferences *preferences)
316 {
317         mode = Render::BATCH;
318         batch_cancelled = 0;
319         this->jobs = jobs;
320         this->preferences = preferences;
321
322         completion->reset();
323 PRINT_TRACE
324         thread->run();
325 PRINT_TRACE
326         this->preferences = 0;
327 }
328
329
330 BC_Window* Render::new_gui()
331 {
332         this->jobs = 0;
333         batch_cancelled = 0;
334         format_error = 0;
335         result = 0;
336         completion->reset();
337         RenderWindow *window = 0;
338         
339         if(mode == Render::INTERACTIVE)
340         {
341 // Fix the asset for rendering
342                 if(!asset) asset = new Asset;
343                 load_defaults(asset);
344                 check_asset(mwindow->edl, *asset);
345
346 // Get format from user
347                 window = new RenderWindow(mwindow, 
348                         this, 
349                         asset,
350                         mwindow->gui->get_abs_cursor_x(1),
351                         mwindow->gui->get_abs_cursor_y(1));
352                 window->create_objects();
353         }
354         else
355         {
356                 ;
357         }
358
359         return window;
360 }
361
362
363 void Render::handle_close_event(int result)
364 {
365         int format_error = 0;
366         const int debug = 0;
367
368         if(!result)
369         {
370                 if(debug) printf("Render::handle_close_event %d\n", __LINE__);
371 // Check the asset format for errors.
372                 FormatCheck format_check(asset);
373                 if(debug) printf("Render::handle_close_event %d\n", __LINE__);
374                 format_error = format_check.check_format();
375                 if(debug) printf("Render::handle_close_event %d\n", __LINE__);
376         }
377
378 //PRINT_TRACE
379
380         save_defaults(asset);
381 //PRINT_TRACE
382         mwindow->save_defaults();
383 //PRINT_TRACE
384
385         if(!format_error && !result)
386         {
387                 if(debug) printf("Render::handle_close_event %d\n", __LINE__);
388                 if(!result) start_render();
389                 if(debug) printf("Render::handle_close_event %d\n", __LINE__);
390         }
391 //PRINT_TRACE
392 }
393
394
395
396 void Render::stop_operation()
397 {
398         if(thread->Thread::running())
399         {
400                 batch_cancelled = 1;
401 // Wait for completion
402                 completion->lock("Render::stop_operation");
403                 completion->reset();
404         }
405 }
406
407
408
409
410 int Render::check_asset(EDL *edl, Asset &asset)
411 {
412         if(asset.video_data && 
413                 edl->tracks->playable_video_tracks() &&
414                 File::supports_video(asset.format))
415         {
416                 asset.video_data = 1;
417                 asset.layers = 1;
418                 asset.width = edl->session->output_w;
419                 asset.height = edl->session->output_h;
420         }
421         else
422         {
423                 asset.video_data = 0;
424                 asset.layers = 0;
425         }
426
427         if(asset.audio_data && 
428                 edl->tracks->playable_audio_tracks() &&
429                 File::supports_audio(asset.format))
430         {
431                 asset.audio_data = 1;
432                 asset.channels = edl->session->audio_channels;
433                 if(asset.format == FILE_MOV) asset.byte_order = 0;
434         }
435         else
436         {
437                 asset.audio_data = 0;
438                 asset.channels = 0;
439         }
440
441         if(!asset.audio_data &&
442                 !asset.video_data)
443         {
444                 return 1;
445         }
446         return 0;
447 }
448
449 int Render::fix_strategy(int strategy, int use_renderfarm)
450 {
451         if(use_renderfarm)
452         {
453                 if(strategy == FILE_PER_LABEL)
454                         strategy = FILE_PER_LABEL_FARM;
455                 else
456                 if(strategy == SINGLE_PASS)
457                         strategy = SINGLE_PASS_FARM;
458         }
459         else
460         {
461                 if(strategy == FILE_PER_LABEL_FARM)
462                         strategy = FILE_PER_LABEL;
463                 else
464                 if(strategy == SINGLE_PASS_FARM)
465                         strategy = SINGLE_PASS;
466         }
467         return strategy;
468 }
469
470 void Render::start_progress()
471 {
472         char filename[BCTEXTLEN];
473         char string[BCTEXTLEN];
474         FileSystem fs;
475
476         progress_max = Units::to_int64(default_asset->sample_rate * 
477                         (total_end - total_start)) +
478                 Units::to_int64(preferences->render_preroll * 
479                         packages->total_allocated * 
480                         default_asset->sample_rate);
481         progress_timer->update();
482         last_eta = 0;
483         if(mwindow)
484         {
485 // Generate the progress box
486                 fs.extract_name(filename, default_asset->path);
487                 sprintf(string, _("Rendering %s..."), filename);
488
489 // Don't bother with the filename since renderfarm defeats the meaning
490                 progress = mwindow->mainprogress->start_progress(_("Rendering..."), 
491                         progress_max);
492                 render_progress = new RenderProgress(mwindow, this);
493                 render_progress->start();
494         }
495 }
496
497 void Render::stop_progress()
498 {
499         if(progress)
500         {
501                 char string[BCTEXTLEN], string2[BCTEXTLEN];
502                 delete render_progress;
503                 progress->get_time(string);
504                 elapsed_time = progress->get_time();
505                 progress->stop_progress();
506                 delete progress;
507
508                 sprintf(string2, _("Rendering took %s"), string);
509                 mwindow->gui->lock_window("");
510                 mwindow->gui->show_message(string2);
511                 mwindow->gui->stop_hourglass();
512                 mwindow->gui->unlock_window();
513         }
514         progress = 0;
515 }
516
517
518
519 void Render::start_render()
520 {
521         in_progress = 0;
522         elapsed_time = 0.0;
523         result = 0;
524         thread->start();
525 }
526
527
528 void Render::create_filename(char *path, 
529         char *default_path, 
530         int current_number,
531         int total_digits,
532         int number_start)
533 {
534         int i, j;
535         int len = strlen(default_path);
536         char printf_string[BCTEXTLEN];
537
538         for(i = 0, j = 0; i < number_start; i++, j++)
539         {
540                 printf_string[j] = default_path[i];
541         }
542
543 // Found the number
544         sprintf(&printf_string[j], "%%0%dd", total_digits);
545         j = strlen(printf_string);
546         i += total_digits;
547
548 // Copy remainder of string
549         for( ; i < len; i++, j++)
550         {
551                 printf_string[j] = default_path[i];
552         }
553         printf_string[j] = 0;
554 // Print the printf argument to the path
555         sprintf(path, printf_string, current_number);
556 }
557
558 void Render::get_starting_number(char *path, 
559         int &current_number,
560         int &number_start, 
561         int &total_digits,
562         int min_digits)
563 {
564         int len = strlen(path);
565         char number_text[BCTEXTLEN];
566         char *ptr = 0;
567         char *ptr2 = 0;
568
569         total_digits = 0;
570         number_start = 0;
571
572 // Search for last /
573         ptr2 = strrchr(path, '/');
574
575 // Search for first 0 after last /.
576         if(ptr2)
577                 ptr = strchr(ptr2, '0');
578
579         if(ptr && isdigit(*ptr))
580         {
581                 number_start = ptr - path;
582
583 // Store the first number
584                 char *ptr2 = number_text;
585                 while(isdigit(*ptr))
586                         *ptr2++ = *ptr++;
587                 *ptr2++ = 0;
588                 current_number = atol(number_text);
589                 total_digits = strlen(number_text);
590         }
591
592
593 // No number found or number not long enough
594         if(total_digits < min_digits)
595         {
596                 current_number = 1;
597                 number_start = len;
598                 total_digits = min_digits;
599         }
600 }
601
602
603
604
605
606
607
608 int Render::load_defaults(Asset *asset)
609 {
610         strategy = mwindow->defaults->get("RENDER_STRATEGY", SINGLE_PASS);
611         load_mode = mwindow->defaults->get("RENDER_LOADMODE", LOADMODE_NEW_TRACKS);
612
613
614         asset->load_defaults(mwindow->defaults, 
615                 "RENDER_", 
616                 1,
617                 1,
618                 1,
619                 1,
620                 1);
621
622
623         return 0;
624 }
625
626 int Render::save_defaults(Asset *asset)
627 {
628         mwindow->defaults->update("RENDER_STRATEGY", strategy);
629         mwindow->defaults->update("RENDER_LOADMODE", load_mode);
630
631
632
633
634         asset->save_defaults(mwindow->defaults, 
635                 "RENDER_",
636                 1,
637                 1,
638                 1,
639                 1,
640                 1);
641
642         return 0;
643 }
644
645
646
647
648
649
650 static void run_script(const char *script, const char *arg)
651 {
652         char *const argv[] = { (char*)script, (char*)arg, 0 };
653         execvp(script ,&argv[0]);
654         perror("execvp script failed");
655         exit(1);
656 }
657
658 RenderThread::RenderThread(MWindow *mwindow, Render *render)
659  : Thread(0, 0, 0)
660 {
661         this->mwindow = mwindow;
662         this->render = render;
663 }
664
665 RenderThread::~RenderThread()
666 {
667 }
668
669
670 void RenderThread::render_single(int test_overwrite, 
671         Asset *asset,
672         EDL *edl,
673         int strategy)
674 {
675 // Total length in seconds
676         double total_length;
677         RenderFarmServer *farm_server = 0;
678         FileSystem fs;
679         //int done = 0;
680         const int debug = 0;
681
682         render->in_progress = 1;
683
684
685         render->default_asset = asset;
686         render->progress = 0;
687         render->result = 0;
688
689         if(mwindow)
690         {
691                 if(!render->preferences)
692                         render->preferences = new Preferences;
693
694                 render->preferences->copy_from(mwindow->preferences);
695         }
696
697
698 // Create rendering command
699         TransportCommand *command = new TransportCommand;
700         command->command = NORMAL_FWD;
701         command->get_edl()->copy_all(edl);
702         command->change_type = CHANGE_ALL;
703 // Get highlighted playback range
704         command->set_playback_range();
705 // Adjust playback range with in/out points
706         command->adjust_playback_range();
707         render->packages = new PackageDispatcher;
708
709 // Create caches
710         CICache *audio_cache = new CICache(render->preferences);
711         CICache *video_cache = new CICache(render->preferences);
712
713         render->default_asset->frame_rate = command->get_edl()->session->frame_rate;
714         render->default_asset->sample_rate = command->get_edl()->session->sample_rate;
715
716 // Conform asset to EDL.  Find out if any tracks are playable.
717         render->result = render->check_asset(command->get_edl(), 
718                 *render->default_asset);
719
720         if(!render->result)
721         {
722 // Get total range to render
723                 render->total_start = command->start_position;
724                 render->total_end = command->end_position;
725                 total_length = render->total_end - render->total_start;
726
727 // Nothing to render
728                 if(EQUIV(total_length, 0))
729                 {
730                         render->result = 1;
731                 }
732         }
733
734
735
736
737
738
739
740 // Generate packages
741         if(!render->result)
742         {
743 // Stop background rendering
744                 if(mwindow) mwindow->stop_brender();
745
746                 fs.complete_path(render->default_asset->path);
747                 strategy = Render::fix_strategy(strategy, render->preferences->use_renderfarm);
748
749                 render->result = render->packages->create_packages(mwindow,
750                         command->get_edl(),
751                         render->preferences,
752                         strategy, 
753                         render->default_asset, 
754                         render->total_start, 
755                         render->total_end,
756                         test_overwrite);
757         }
758
759
760
761
762
763
764
765
766
767
768         //done = 0;
769         render->total_rendered = 0;
770
771         if(!render->result)
772         {
773 // Start dispatching external jobs
774                 if(mwindow)
775                 {
776                         mwindow->gui->lock_window("Render::render 1");
777                         mwindow->gui->show_message(_("Starting render farm"));
778                         mwindow->gui->start_hourglass();
779                         mwindow->gui->unlock_window();
780                 }
781                 else
782                 {
783                         printf("Render::render: starting render farm\n");
784                 }
785
786                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
787                 {
788                         farm_server = new RenderFarmServer(mwindow,
789                                 render->packages,
790                                 render->preferences, 
791                                 1,
792                                 &render->result,
793                                 &render->total_rendered,
794                                 render->counter_lock,
795                                 render->default_asset,
796                                 command->get_edl(),
797                                 0);
798                         render->result = farm_server->start_clients();
799
800                         if(render->result)
801                         {
802                                 if(mwindow)
803                                 {
804                                         mwindow->gui->lock_window("Render::render 2");
805                                         mwindow->gui->show_message(_("Failed to start render farm"),
806                                                 mwindow->theme->message_error);
807                                         mwindow->gui->stop_hourglass();
808                                         mwindow->gui->unlock_window();
809                                 }
810                                 else
811                                 {
812                                         printf("Render::render: Failed to start render farm\n");
813                                 }
814                         }
815                 }
816         }
817
818
819
820
821 // Perform local rendering
822
823
824         if(!render->result)
825         {
826                 render->start_progress();
827         
828
829
830
831                 MainPackageRenderer package_renderer(render);
832                 render->result = package_renderer.initialize(mwindow,
833                                 command->get_edl(),   // Copy of master EDL
834                                 render->preferences, 
835                                 render->default_asset);
836
837
838
839
840
841
842
843                 while(!render->result)
844                 {
845 // Get unfinished job
846                         RenderPackage *package;
847
848                         if(strategy == SINGLE_PASS_FARM)
849                         {
850                                 package = render->packages->get_package(
851                                         package_renderer.frames_per_second, 
852                                         -1, 
853                                         1);
854                         }
855                         else
856                         {
857                                 package = render->packages->get_package(0, -1, 1);
858                         }
859
860 // Exit point
861                         if(!package) 
862                         {
863                                 //done = 1;
864                                 break;
865                         }
866
867
868
869                         Timer timer;
870                         timer.update();
871
872                         if(package_renderer.render_package(package))
873                                 render->result = 1;
874
875
876                 } // file_number
877
878
879
880 printf("Render::render_single: Session finished.\n");
881
882
883
884
885
886                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
887                 {
888                         farm_server->wait_clients();
889                 }
890
891 if(debug) printf("Render::render %d\n", __LINE__);
892
893 // Notify of error
894                 if(render->result && 
895                         (!render->progress || !render->progress->is_cancelled()) &&
896                         !render->batch_cancelled)
897                 {
898 if(debug) printf("Render::render %d\n", __LINE__);
899                         if(mwindow)
900                         {
901 if(debug) printf("Render::render %d\n", __LINE__);
902                                 ErrorBox error_box(_(PROGRAM_NAME ": Error"),
903                                         mwindow->gui->get_abs_cursor_x(1),
904                                         mwindow->gui->get_abs_cursor_y(1));
905                                 error_box.create_objects(_("Error rendering data."));
906                                 error_box.raise_window();
907                                 error_box.run_window();
908 if(debug) printf("Render::render %d\n", __LINE__);
909                         }
910                         else
911                         {
912                                 printf("Render::render: Error rendering data\n");
913                         }
914                 }
915 if(debug) printf("Render::render %d\n", __LINE__);
916
917 // Delete the progress box
918                 render->stop_progress();
919
920 if(debug) printf("Render::render %d\n", __LINE__);
921
922
923
924
925         }
926
927
928 // Paste all packages into timeline if desired
929
930         if(!render->result && 
931                 render->load_mode != LOADMODE_NOTHING && 
932                 mwindow &&
933                 render->mode != Render::BATCH)
934         {
935 if(debug) printf("Render::render %d\n", __LINE__);
936                 mwindow->gui->lock_window("Render::render 3");
937 if(debug) printf("Render::render %d\n", __LINE__);
938
939                 mwindow->undo->update_undo_before();
940
941 if(debug) printf("Render::render %d\n", __LINE__);
942
943
944                 ArrayList<Indexable*> *assets = render->packages->get_asset_list();
945 if(debug) printf("Render::render %d\n", __LINE__);
946                 if(render->load_mode == LOADMODE_PASTE)
947                         mwindow->clear(0);
948 if(debug) printf("Render::render %d\n", __LINE__);
949                 mwindow->load_assets(assets, 
950                         -1, 
951                         render->load_mode,
952                         0,
953                         0,
954                         mwindow->edl->session->labels_follow_edits,
955                         mwindow->edl->session->plugins_follow_edits,
956                         mwindow->edl->session->autos_follow_edits);
957 if(debug) printf("Render::render %d\n", __LINE__);
958                 for(int i = 0; i < assets->size(); i++)
959                         assets->get(i)->Garbage::remove_user();
960                 delete assets;
961 if(debug) printf("Render::render %d\n", __LINE__);
962
963
964                 mwindow->save_backup();
965 if(debug) printf("Render::render %d\n", __LINE__);
966                 mwindow->undo->update_undo_after(_("render"), LOAD_ALL);
967 if(debug) printf("Render::render %d\n", __LINE__);
968                 mwindow->update_plugin_guis();
969 if(debug) printf("Render::render %d\n", __LINE__);
970                 mwindow->gui->update(1, 
971                         2,
972                         1,
973                         1,
974                         1,
975                         1,
976                         0);
977 if(debug) printf("Render::render %d\n", __LINE__);
978                 mwindow->sync_parameters(CHANGE_ALL);
979 if(debug) printf("Render::render %d\n", __LINE__);
980                 mwindow->gui->unlock_window();
981                 
982                 
983                 mwindow->awindow->gui->lock_window("Render::render");
984                 mwindow->awindow->gui->update_assets();
985                 mwindow->awindow->gui->flush();
986                 mwindow->awindow->gui->unlock_window();
987                 
988 if(debug) printf("Render::render %d\n", __LINE__);
989         }
990
991 if(debug) printf("Render::render %d\n", __LINE__);
992
993 // Disable hourglass
994         if(mwindow)
995         {
996                 mwindow->gui->lock_window("Render::render 3");
997                 mwindow->gui->stop_hourglass();
998                 mwindow->gui->unlock_window();
999         }
1000
1001 //printf("Render::render 110\n");
1002 // Need to restart because brender always stops before render.
1003         if(mwindow)
1004                 mwindow->restart_brender();
1005         if(farm_server) delete farm_server;
1006         delete command;
1007         delete audio_cache;
1008         delete video_cache;
1009 // Must delete packages after server
1010         delete render->packages;
1011
1012         render->packages = 0;
1013         render->in_progress = 0;
1014         render->completion->unlock();
1015 if(debug) printf("Render::render %d\n", __LINE__);
1016 }
1017
1018 void RenderThread::run()
1019 {
1020         if(render->mode == Render::INTERACTIVE)
1021         {
1022                 render_single(1, render->asset, mwindow->edl, render->strategy);
1023         }
1024         else
1025         if(render->mode == Render::BATCH)
1026         {
1027 // PRINT_TRACE
1028 // printf("RenderThread::run %d %d %d\n", 
1029 // __LINE__, 
1030 // render->jobs->total, 
1031 // render->result);
1032                 for(int i = 0; i < render->jobs->total && !render->result; i++)
1033                 {
1034 //PRINT_TRACE
1035                         BatchRenderJob *job = render->jobs->values[i];
1036 //PRINT_TRACE
1037                         if(job->enabled)
1038                         {
1039                                 if( *job->edl_path == '@' )
1040                                 {
1041                                         run_script(job->edl_path+1, job->asset->path);
1042                                 }
1043
1044                                 if(mwindow)
1045                                 {
1046                                         mwindow->batch_render->update_active(i);
1047                                 }
1048                                 else
1049                                 {
1050                                         printf("Render::run: %s\n", job->edl_path);
1051                                 }
1052
1053 //PRINT_TRACE
1054
1055                                 FileXML *file = new FileXML;
1056                                 EDL *edl = new EDL;
1057                                 edl->create_objects();
1058                                 file->read_from_file(job->edl_path);
1059                                 edl->load_xml(file, LOAD_ALL);
1060
1061 //PRINT_TRACE
1062                                 render_single(0, job->asset, edl, job->strategy);
1063
1064 //PRINT_TRACE
1065                                 edl->Garbage::remove_user();
1066                                 delete file;
1067                                 if(!render->result)
1068                                 {
1069                                         if(mwindow)
1070                                                 mwindow->batch_render->update_done(i, 1, render->elapsed_time);
1071                                         else
1072                                         {
1073                                                 char string[BCTEXTLEN];
1074                                                 render->elapsed_time = 
1075                                                         (double)render->progress_timer->get_scaled_difference(1);
1076                                                 Units::totext(string,
1077                                                         render->elapsed_time,
1078                                                         TIME_HMS2);
1079                                                 printf("Render::run: done in %s\n", string);
1080                                         }
1081                                 }
1082                                 else
1083                                 {
1084                                         if(mwindow)
1085                                                 mwindow->batch_render->update_active(-1);
1086                                         else
1087                                                 printf("Render::run: failed\n");
1088                                 }
1089                         }
1090 //PRINT_TRACE
1091                 }
1092
1093                 if(mwindow)
1094                 {
1095                         mwindow->batch_render->update_active(-1);
1096                         mwindow->batch_render->update_done(-1, 0, 0);
1097                 }
1098         }
1099 }
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109 #define WIDTH 410
1110 #define HEIGHT 360
1111
1112
1113 RenderWindow::RenderWindow(MWindow *mwindow, 
1114         Render *render, 
1115         Asset *asset,
1116         int x, 
1117         int y)
1118  : BC_Window(_(PROGRAM_NAME ": Render"), 
1119         x - WIDTH / 2,
1120         y - HEIGHT / 2,
1121         WIDTH, 
1122         HEIGHT,
1123         (int)BC_INFINITY,
1124         (int)BC_INFINITY,
1125         0,
1126         0,
1127         1)
1128 {
1129         this->mwindow = mwindow;
1130         this->render = render;
1131         this->asset = asset;
1132 }
1133
1134 RenderWindow::~RenderWindow()
1135 {
1136 SET_TRACE
1137         lock_window("RenderWindow::~RenderWindow");
1138 SET_TRACE
1139         delete format_tools;
1140 SET_TRACE
1141         delete loadmode;
1142 SET_TRACE
1143         unlock_window();
1144 SET_TRACE
1145 }
1146
1147
1148
1149 void RenderWindow::create_objects()
1150 {
1151         int x = 10, y = 5;
1152         lock_window("RenderWindow::create_objects");
1153         add_subwindow(new BC_Title(x, 
1154                 y, 
1155                 (char*)((render->strategy == FILE_PER_LABEL || 
1156                                 render->strategy == FILE_PER_LABEL_FARM) ? 
1157                         _("Select the first file to render to:") : 
1158                         _("Select a file to render to:"))));
1159         y += 25;
1160
1161         format_tools = new FormatTools(mwindow,
1162                                         this, 
1163                                         asset);
1164         format_tools->create_objects(x, 
1165                 y, 
1166                 1, 
1167                 1, 
1168                 1, 
1169                 1, 
1170                 0,
1171                 1,
1172                 0,
1173                 0,
1174                 &render->strategy,
1175                 0);
1176
1177         loadmode = new LoadMode(mwindow, 
1178                 this, 
1179                 x, 
1180                 y, 
1181                 &render->load_mode, 
1182                 1,
1183                 0);
1184         loadmode->create_objects();
1185
1186         add_subwindow(new BC_OKButton(this));
1187         add_subwindow(new BC_CancelButton(this));
1188         show_window();
1189         unlock_window();
1190 }