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