3 * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "awindowgui.h"
26 #include "batchrender.h"
27 #include "bcprogressbox.h"
28 #include "bcsignals.h"
31 #include "compresspopup.h"
32 #include "condition.h"
33 #include "confirmsave.h"
34 #include "cwindowgui.h"
39 #include "edlsession.h"
42 #include "filesystem.h"
44 #include "formatcheck.h"
45 #include "formatpopup.h"
46 #include "formattools.h"
47 #include "indexable.h"
51 #include "localsession.h"
52 #include "mainprogress.h"
53 #include "mainsession.h"
57 #include "mwindowgui.h"
59 #include "packagedispatcher.h"
60 #include "packagerenderer.h"
62 #include "playabletracks.h"
63 #include "preferences.h"
64 #include "preferencesthread.h"
65 #include "renderfarm.h"
67 #include "renderprofiles.h"
68 #include "statusbar.h"
72 #include "transportque.h"
75 #include "videoconfig.h"
83 RenderItem::RenderItem(MWindow *mwindow)
84 : BC_MenuItem(_("Render..."), _("Shift-R"), 'R')
86 this->mwindow = mwindow;
90 int RenderItem::handle_event()
92 mwindow->gui->unlock_window();
93 mwindow->render->start_interactive();
94 mwindow->gui->lock_window("RenderItem::handle_event");
98 RenderProgress::RenderProgress(MWindow *mwindow, Render *render)
101 this->mwindow = mwindow;
102 this->render = render;
104 Thread::set_synchronous(1);
107 RenderProgress::~RenderProgress()
114 void RenderProgress::run()
116 Thread::disable_cancel();
118 if( render->total_rendered != last_value ) {
119 render->progress->update(render->total_rendered);
120 last_value = render->total_rendered;
122 if( mwindow ) mwindow->preferences_thread->update_rates();
125 Thread::enable_cancel();
127 Thread::disable_cancel();
133 MainPackageRenderer::MainPackageRenderer(Render *render)
136 this->render = render;
141 MainPackageRenderer::~MainPackageRenderer()
146 int MainPackageRenderer::get_master()
151 int MainPackageRenderer::get_result()
153 return render->result;
156 void MainPackageRenderer::set_result(int value)
159 render->result = value;
162 void MainPackageRenderer::set_progress(int64_t value)
164 render->counter_lock->lock("MainPackageRenderer::set_progress");
165 // Increase total rendered for all nodes
166 render->total_rendered += value;
168 // Update frames per second for master node
169 render->preferences->set_rate(frames_per_second, -1);
171 //printf("MainPackageRenderer::set_progress %d %ld %f\n", __LINE__, (long)value, frames_per_second);
173 // If non interactive, print progress out
174 if( !render->progress )
175 render->show_progress();
177 render->counter_lock->unlock();
180 mwindow->preferences->copy_rates_from(preferences);
183 int MainPackageRenderer::progress_cancelled()
185 return (render->progress && render->progress->is_cancelled()) ||
186 render->batch_cancelled;
189 void RenderAssets::clear()
191 for( int i=size(); --i>=0; get(i)->remove_user() );
194 RenderAssets::RenderAssets()
197 RenderAssets::~RenderAssets()
202 Render::Render(MWindow *mwindow)
205 this->mwindow = mwindow;
209 package_lock = new Mutex("Render::package_lock");
210 counter_lock = new Mutex("Render::counter_lock");
211 completion = new Condition(0, "Render::completion");
212 progress_timer = new Timer;
213 range_type = RANGE_BACKCOMPAT;
214 preferences = new Preferences();
215 thread = new RenderThread(mwindow, this);
229 delete progress_timer;
230 if( asset ) asset->Garbage::remove_user();
234 void Render::start_interactive()
236 if( !thread->running() ) {
237 mode = Render::INTERACTIVE;
238 BC_DialogThread::start();
240 else if( in_progress ) {
242 mwindow->gui->get_abs_cursor(cx, cy, 1);
243 ErrorBox error_box(_(PROGRAM_NAME ": Error"), cx, cy);
244 error_box.create_objects(_("Already rendering"));
245 error_box.raise_window();
246 error_box.run_window();
248 else if( render_window ) {
249 render_window->raise_window();
254 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs)
256 if( !thread->running() ) {
257 mode = Render::BATCH;
263 else if( in_progress ) {
265 mwindow->gui->get_abs_cursor(cx, cy, 1);
266 ErrorBox error_box(_(PROGRAM_NAME ": Error"), cx, cy);
267 error_box.create_objects("Already rendering");
268 error_box.raise_window();
269 error_box.run_window();
271 // raise the window if rendering hasn't started yet
272 else if( render_window ) {
273 render_window->raise_window();
277 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs,
278 BC_Hash *boot_defaults, Preferences *batch_prefs)
280 mode = Render::BATCH;
282 preferences->copy_from(batch_prefs);
290 BC_Window* Render::new_gui()
296 if( mode == Render::INTERACTIVE ) {
297 // Fix the asset for rendering
298 if( !asset ) asset = new Asset;
299 load_defaults(asset);
300 check_asset(mwindow->edl, *asset);
301 int px = mwindow->gui->get_pop_cursor_x(1);
302 int py = mwindow->gui->get_pop_cursor_y(1);
303 // Get format from user
304 render_window = new RenderWindow(mwindow, this, asset, px, py);
305 render_window->create_objects();
308 return render_window;
311 void Render::handle_done_event(int result)
314 mwindow->edl->session->render_beep = beep;
315 // add to recentlist only on OK
316 render_window->render_format->path_recent->
317 add_item(File::formattostr(asset->format), asset->path);
318 setenv("CIN_RENDER", asset->path, 1);
323 void Render::handle_close_event(int result)
326 double render_range = get_render_range();
327 const char *err_msg = 0;
329 if( !result && !render_range ) {
330 err_msg = _("zero render range");
333 if( !result && asset->video_data ) {
334 double frame_rate = mwindow->edl->session->frame_rate;
335 if( frame_rate > 0 && render_range+1e-3 < 1./frame_rate ) {
336 err_msg = _("Video data and range less than 1 frame");
340 if( !result && asset->audio_data ) {
341 double sample_rate = mwindow->edl->session->sample_rate;
342 if( sample_rate > 0 && render_range+1e-6 < 1./sample_rate ) {
343 err_msg = _("Audio data and range less than 1 sample");
347 if( !result && File::is_image_render(asset->format) ) {
348 if( asset->video_data ) {
349 double frames = render_range * mwindow->edl->session->frame_rate;
350 if( !EQUIV(frames, 1.) ) {
351 err_msg = _("Image format and not 1 frame");
356 err_msg = _("Image format and no video data");
362 mwindow->gui->get_abs_cursor(cx, cy, 1);
363 ErrorBox error_box(_(PROGRAM_NAME ": Error"),cx, cy);
364 error_box.create_objects(err_msg);
365 error_box.raise_window();
366 error_box.run_window();
370 // Check the asset format for errors.
371 FormatCheck format_check(asset);
372 if( format_check.check_format() )
378 save_defaults(asset);
380 mwindow->save_defaults();
384 if( debug ) printf("Render::handle_close_event %d\n", __LINE__);
385 if( !result ) start_render();
386 if( debug ) printf("Render::handle_close_event %d\n", __LINE__);
393 void Render::stop_operation()
395 if( thread->Thread::running() ) {
397 // Wait for completion
398 completion->lock("Render::stop_operation");
403 int Render::check_asset(EDL *edl, Asset &asset)
405 if( asset.video_data &&
406 edl->tracks->playable_video_tracks() &&
407 File::renders_video(&asset) ) {
408 asset.video_data = 1;
410 asset.width = edl->session->output_w;
411 asset.height = edl->session->output_h;
412 asset.interlace_mode = edl->session->interlace_mode;
415 asset.video_data = 0;
419 if( asset.audio_data &&
420 edl->tracks->playable_audio_tracks() &&
421 File::renders_audio(&asset) ) {
422 asset.audio_data = 1;
423 asset.channels = edl->session->audio_channels;
426 asset.audio_data = 0;
430 if( !asset.audio_data &&
431 !asset.video_data ) {
437 int Render::get_strategy(int use_renderfarm, int use_labels)
439 return use_renderfarm ?
440 (use_labels ? FILE_PER_LABEL_FARM : SINGLE_PASS_FARM) :
441 (use_labels ? FILE_PER_LABEL : SINGLE_PASS ) ;
443 int Render::get_strategy()
445 return get_strategy(preferences->use_renderfarm, use_labels);
448 void Render::start_progress()
450 char filename[BCTEXTLEN];
451 char string[BCTEXTLEN];
452 progress_max = packages->get_progress_max();
454 progress_timer->update();
457 // Generate the progress box
459 fs.extract_name(filename, default_asset->path);
460 sprintf(string, _("Rendering %s..."), filename);
462 // Don't bother with the filename since renderfarm defeats the meaning
463 mwindow->gui->lock_window("Render::start_progress");
464 progress = mwindow->mainprogress->start_progress(_("Rendering..."),
466 mwindow->gui->unlock_window();
467 render_progress = new RenderProgress(mwindow, this);
468 render_progress->start();
472 void Render::stop_progress()
475 char string[BCTEXTLEN], string2[BCTEXTLEN];
476 delete render_progress;
477 progress->get_time(string);
478 elapsed_time = progress->get_time();
479 progress->stop_progress();
482 sprintf(string2, _("Rendering took %s"), string);
483 mwindow->gui->lock_window("Render::stop_progress");
484 mwindow->gui->show_message(string2);
485 mwindow->gui->update_default_message();
486 mwindow->gui->stop_hourglass();
487 mwindow->gui->unlock_window();
492 void Render::show_progress()
494 int64_t current_eta = progress_timer->get_scaled_difference(1000);
495 if( current_eta - last_eta < 1000 ) return;
496 double eta = !total_rendered ? 0 :
497 current_eta / 1000. * (progress_max / (double)total_rendered - 1.);
498 char string[BCTEXTLEN]; Units::totext(string, eta, TIME_HMS2);
499 printf("\r%d%% %s: %s ",
500 (int)(100 * (float)total_rendered / progress_max), _("ETA"), string);
502 last_eta = current_eta;
507 void Render::start_render()
517 void Render::create_filename(char *path,
524 int len = strlen(default_path);
525 char printf_string[BCTEXTLEN];
527 for( i=0, j=0; i<number_start; ++i, ++j ) {
528 printf_string[j] = default_path[i];
532 sprintf(&printf_string[j], "%%0%dd", total_digits);
533 j = strlen(printf_string);
536 // Copy remainder of string
537 for( ; i<len; ++i, ++j ) {
538 printf_string[j] = default_path[i];
540 printf_string[j] = 0;
541 // Print the printf argument to the path
542 sprintf(path, printf_string, current_number);
545 void Render::get_starting_number(char *path,
551 int len = strlen(path);
552 char number_text[BCTEXTLEN];
560 ptr2 = strrchr(path, '/');
562 // Search for first 0 after last /.
564 ptr = strchr(ptr2, '0');
566 if( ptr && isdigit(*ptr) ) {
567 number_start = ptr - path;
569 // Store the first number
570 char *ptr2 = number_text;
571 while( isdigit(*ptr) ) *ptr2++ = *ptr++;
573 current_number = atol(number_text);
574 total_digits = strlen(number_text);
578 // No number found or number not long enough
579 if( total_digits < min_digits ) {
582 total_digits = min_digits;
587 int Render::load_defaults(Asset *asset)
589 use_labels = mwindow->defaults->get("RENDER_FILE_PER_LABEL", 0);
590 load_mode = mwindow->defaults->get("RENDER_LOADMODE", LOADMODE_NEW_TRACKS);
591 range_type = mwindow->defaults->get("RENDER_RANGE_TYPE", RANGE_PROJECT);
593 // some defaults which work
594 asset->video_data = 1;
595 asset->audio_data = 1;
596 asset->format = FILE_FFMPEG;
597 strcpy(asset->acodec, "mp4.qt");
598 strcpy(asset->vcodec, "mp4.qt");
600 asset->load_defaults(mwindow->defaults,
601 "RENDER_", 1, 1, 1, 1, 1);
605 int Render::load_profile(int profile_slot, Asset *asset)
607 char string_name[100];
608 sprintf(string_name, "RENDER_%i_FILE_PER_LABEL", profile_slot);
609 use_labels = mwindow->defaults->get(string_name, 0);
610 // Load mode is not part of the profile
611 // printf(string_name, "RENDER_%i_LOADMODE", profile_slot);
612 // load_mode = mwindow->defaults->get(string_name, LOADMODE_NEW_TRACKS);
613 sprintf(string_name, "RENDER_%i_RANGE_TYPE", profile_slot);
614 range_type = mwindow->defaults->get(string_name, RANGE_PROJECT);
616 sprintf(string_name, "RENDER_%i_", profile_slot);
617 asset->load_defaults(mwindow->defaults,
618 string_name, 1, 1, 1, 1, 1);
623 int Render::save_defaults(Asset *asset)
625 mwindow->defaults->update("RENDER_FILE_PER_LABEL", use_labels);
626 mwindow->defaults->update("RENDER_LOADMODE", load_mode);
627 mwindow->defaults->update("RENDER_RANGE_TYPE", range_type);
629 asset->save_defaults(mwindow->defaults,
630 "RENDER_", 1, 1, 1, 1, 1);
634 void Render::update_assets()
637 packages->get_asset_list(assets);
640 static void run_script(const char *script, const char *arg)
642 char *const argv[] = { (char*)script, (char*)arg, 0 };
643 execvp(script ,&argv[0]);
644 perror("execvp script failed");
648 RenderThread::RenderThread(MWindow *mwindow, Render *render)
651 this->mwindow = mwindow;
652 this->render = render;
656 RenderThread::~RenderThread()
661 void RenderThread::render_single(int test_overwrite, Asset *asset, EDL *edl,
662 int strategy, int range_type)
664 // Total length in seconds
665 double total_length = 0;
666 RenderFarmServer *farm_server = 0;
668 render->in_progress = 1;
669 render->default_asset = asset;
670 render->progress = 0;
673 // Create rendering command
674 TransportCommand *command = new TransportCommand;
675 command->command = NORMAL_FWD;
676 command->get_edl()->copy_all(edl);
677 command->change_type = CHANGE_ALL;
679 switch( range_type ) {
680 case RANGE_BACKCOMPAT:
681 // Get highlighted playback range
682 command->set_playback_range();
683 // Adjust playback range with in/out points
684 command->playback_range_adjust_inout();
687 command->playback_range_project();
689 case RANGE_SELECTION:
690 command->set_playback_range();
693 command->playback_range_inout();
696 command->playback_range_1frame();
700 render->packages = new PackageDispatcher;
703 CICache *audio_cache = new CICache(render->preferences);
704 CICache *video_cache = new CICache(render->preferences);
706 render->default_asset->frame_rate = command->get_edl()->session->frame_rate;
707 render->default_asset->sample_rate = command->get_edl()->session->sample_rate;
709 // Conform asset to EDL. Find out if any tracks are playable.
710 render->result = render->check_asset(command->get_edl(),
711 *render->default_asset);
713 if( !render->result ) {
714 // Get total range to render
715 render->total_start = command->start_position;
716 render->total_end = command->end_position;
717 total_length = render->total_end - render->total_start;
720 if( EQUIV(total_length, 0) ) {
724 render_frames = render->default_asset->frame_rate * total_length;
727 if( !render->result ) {
728 // Stop background rendering
729 if( mwindow ) mwindow->stop_brender();
732 fs.complete_path(render->default_asset->path);
734 render->result = render->packages->create_packages(mwindow, command->get_edl(),
735 render->preferences, strategy, render->default_asset,
736 render->total_start, render->total_end, test_overwrite);
739 render->total_rendered = 0;
741 if( !render->result &&
742 ( strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM ) ) {
743 // Start dispatching external jobs
745 mwindow->gui->lock_window("Render::render 1");
746 mwindow->gui->show_message(_("Starting render farm"));
747 mwindow->gui->start_hourglass();
748 mwindow->gui->unlock_window();
751 printf("Render::render: starting render farm\n");
754 farm_server = new RenderFarmServer(mwindow, render->packages,
755 render->preferences, 1, &render->result,
756 &render->total_rendered, render->counter_lock,
757 render->default_asset, command->get_edl(), 0);
758 render->result = farm_server->start_clients();
760 if( render->result ) {
762 mwindow->gui->lock_window("Render::render 2");
763 mwindow->gui->show_message(_("Failed to start render farm"),
764 mwindow->theme->message_error);
765 mwindow->gui->stop_hourglass();
766 mwindow->gui->unlock_window();
769 printf("Render::render: Failed to start render farm\n");
774 // Perform local rendering
776 render->assets.clear();
777 if( !render->result ) {
778 render->start_progress();
780 MainPackageRenderer package_renderer(render);
781 render->result = package_renderer.initialize(mwindow,
782 command->get_edl(), // Copy of master EDL
784 render->default_asset);
786 while( !render->result ) {
787 int fps = strategy == SINGLE_PASS_FARM ?
788 package_renderer.frames_per_second : 0;
789 // Get unfinished job
790 RenderPackage *package = render->packages->get_package(fps, -1, 1);
792 if( !package ) break;
794 if( package_renderer.render_package(package) )
798 printf("Render::render_single: Session finished.\n");
800 if( strategy == SINGLE_PASS_FARM ||
801 strategy == FILE_PER_LABEL_FARM ) {
802 if( !render->progress ) {
803 while( farm_server->active_clients() > 0 ) {
805 render->show_progress();
808 farm_server->wait_clients();
809 render->result |= render->packages->packages_are_done();
813 if( render->result && !render->batch_cancelled &&
814 (!render->progress || !render->progress->is_cancelled()) ) {
817 mwindow->gui->get_abs_cursor(cx, cy, 1);
818 ErrorBox error_box(_(PROGRAM_NAME ": Error"), cx, cy);
819 error_box.create_objects(_("Error rendering data."));
820 error_box.raise_window();
821 error_box.run_window();
824 printf("Render::render: Error rendering data\n");
828 // Delete the progress box
829 render->stop_progress();
830 render->update_assets();
833 // Paste all packages into timeline if desired
835 if( !render->result && mwindow &&
836 render->load_mode != LOADMODE_NOTHING &&
837 render->mode != Render::BATCH ) {
838 mwindow->gui->lock_window("Render::render 3");
840 mwindow->undo->update_undo_before();
841 if( render->load_mode == LOADMODE_PASTE )
843 mwindow->load_assets(&render->assets,
844 -1, render->load_mode, 0, 0,
845 mwindow->edl->session->labels_follow_edits,
846 mwindow->edl->session->plugins_follow_edits,
847 mwindow->edl->session->autos_follow_edits,
849 mwindow->save_backup();
850 mwindow->undo->update_undo_after(_("render"), LOAD_ALL);
851 mwindow->update_plugin_guis();
852 mwindow->gui->update(1, FORCE_REDRAW, 1, 1, 1, 1, 0);
853 mwindow->sync_parameters(CHANGE_ALL);
854 mwindow->gui->unlock_window();
856 mwindow->awindow->gui->async_update_assets();
861 mwindow->gui->lock_window("Render::render 3");
862 mwindow->gui->stop_hourglass();
863 mwindow->gui->unlock_window();
866 //printf("Render::render 110\n");
867 // Need to restart because brender always stops before render.
869 mwindow->restart_brender();
870 if( farm_server ) delete farm_server;
874 // Must delete packages after server
875 delete render->packages;
877 render->packages = 0;
878 render->in_progress = 0;
881 void RenderThread::run()
887 render->preferences->copy_from(mwindow->preferences);
889 if( render->mode == Render::INTERACTIVE ) {
890 render_single(1, render->asset, mwindow->edl,
891 render->get_strategy(), render->range_type);
894 if( render->mode == Render::BATCH ) {
895 for( int i=0; i<render->jobs->total && !render->result; ++i ) {
896 BatchRenderJob *job = render->jobs->values[i];
897 if( !job->enabled ) continue;
899 mwindow->batch_render->update_active(i);
901 printf("Render::run: %s\n", job->edl_path);
903 FileXML *file = new FileXML;
905 edl->create_objects();
906 file->read_from_file(job->edl_path);
907 edl->load_xml(file, LOAD_ALL);
910 render_single(0, job->asset, edl, job->get_strategy(), RANGE_BACKCOMPAT);
911 if( !render->result ) {
913 script = job->create_script(edl, &render->assets);
915 mwindow->batch_render->update_done(i, 1, render->elapsed_time);
917 char string[BCTEXTLEN];
918 render->elapsed_time =
919 (double)render->progress_timer->get_scaled_difference(1);
920 Units::totext(string, render->elapsed_time, TIME_HMS2);
921 printf("Render::run: done in %s\n", string);
926 mwindow->batch_render->update_active(-1);
928 printf("Render::run: failed\n");
932 mwindow->batch_render->update_active(-1);
933 mwindow->batch_render->update_done(-1, 0, 0);
936 render->completion->unlock();
938 if( !render->result ) {
939 double render_time = render_timer.get_difference() / 1000.0;
940 double render_rate = render_time > 0 ? render_frames / render_time : 0;
941 printf("** rendered %jd frames in %0.3f secs, %0.3f fps\n",
942 render_frames, render_time, render_rate);
945 if( render->mode == Render::INTERACTIVE && render->beep )
946 mwindow->beep(3000., 1.5, 0.5);
949 if( !render->result )
950 run_script(script, 0);
960 RenderWindow::RenderWindow(MWindow *mwindow,
965 : BC_Window(_(PROGRAM_NAME ": Render"), x, y,
966 WIDTH, HEIGHT, WIDTH, HEIGHT, 0, 0, 1)
968 this->mwindow = mwindow;
969 this->render = render;
980 RenderWindow::~RenderWindow()
982 lock_window("RenderWindow::~RenderWindow");
983 delete render_format;
985 delete renderprofile;
990 void RenderWindow::load_profile(int profile_slot)
992 render->load_profile(profile_slot, asset);
993 update_range_type(render->range_type);
994 render_format->update(asset, &render->use_labels);
998 void RenderWindow::create_objects()
1001 lock_window("RenderWindow::create_objects");
1002 add_subwindow(new BC_Title(x, y,
1003 (char*)(render->use_labels ?
1004 _("Select the first file to render to:") :
1005 _("Select a file to render to:"))));
1008 render_format = new RenderFormat(mwindow, this, asset);
1009 render_format->create_objects(x, y,
1010 1, 1, 1, 1, 0, 1, 0, 0, &render->use_labels, 0);
1013 add_subwindow(title = new BC_Title(x, y, _("Render range:")));
1015 int is_image = File::is_image_render(asset->format);
1017 render->range_type = RANGE_1FRAME;
1019 int x1 = x + title->get_w() + 20, y1 = y;
1020 add_subwindow(rangeproject = new RenderRangeProject(this,
1021 render->range_type == RANGE_PROJECT, x1, y));
1022 int x2 = x1 + rangeproject->get_w();
1024 add_subwindow(rangeselection = new RenderRangeSelection(this,
1025 render->range_type == RANGE_SELECTION, x1, y));
1026 int x3 = x1 + rangeselection->get_w();
1027 if( x2 < x3 ) x2 = x3;
1029 add_subwindow(rangeinout = new RenderRangeInOut(this,
1030 render->range_type == RANGE_INOUT, x1, y));
1031 x3 = x1 + rangeinout->get_w();
1032 if( x2 < x3 ) x2 = x3;
1034 add_subwindow(range1frame = new RenderRange1Frame(this,
1035 render->range_type == RANGE_1FRAME, x1, y));
1036 x3 = x1 + range1frame->get_w();
1037 if( x2 < x3 ) x2 = x3;
1040 enable_render_range(0);
1043 render->beep = mwindow->edl->session->render_beep;
1044 add_subwindow(beep_on_done = new RenderBeepOnDone(this, x1, y1));
1046 renderprofile = new RenderProfile(mwindow, this, x, y, 1);
1047 renderprofile->create_objects();
1050 loadmode = new LoadMode(mwindow, this, x, y, &render->load_mode, 1);
1051 loadmode->create_objects();
1053 add_subwindow(new BC_OKButton(this));
1054 add_subwindow(new BC_CancelButton(this));
1060 void RenderWindow::update_range_type(int range_type)
1062 if( render->range_type == range_type ) return;
1063 render->range_type = range_type;
1064 rangeproject->update(range_type == RANGE_PROJECT);
1065 rangeselection->update(range_type == RANGE_SELECTION);
1066 rangeinout->update(range_type == RANGE_INOUT);
1067 range1frame->update(range_type == RANGE_1FRAME);
1070 void RenderWindow::enable_render_range(int v)
1073 rangeproject->enable();
1074 rangeselection->enable();
1075 rangeinout->enable();
1076 range1frame->enable();
1079 rangeproject->disable();
1080 rangeselection->disable();
1081 rangeinout->disable();
1082 range1frame->disable();
1087 RenderRangeProject::RenderRangeProject(RenderWindow *rwindow, int value, int x, int y)
1088 : BC_Radial(x, y, value, _("Project"))
1090 this->rwindow = rwindow;
1092 int RenderRangeProject::handle_event()
1094 rwindow->update_range_type(RANGE_PROJECT);
1098 RenderRangeSelection::RenderRangeSelection(RenderWindow *rwindow, int value, int x, int y)
1099 : BC_Radial(x, y, value, _("Selection"))
1101 this->rwindow = rwindow;
1103 int RenderRangeSelection::handle_event()
1105 rwindow->update_range_type(RANGE_SELECTION);
1110 RenderRangeInOut::RenderRangeInOut(RenderWindow *rwindow, int value, int x, int y)
1111 : BC_Radial(x, y, value, _("In/Out Points"))
1113 this->rwindow = rwindow;
1115 int RenderRangeInOut::handle_event()
1117 rwindow->update_range_type(RANGE_INOUT);
1121 RenderRange1Frame::RenderRange1Frame(RenderWindow *rwindow, int value, int x, int y)
1122 : BC_Radial(x, y, value, _("One Frame"))
1124 this->rwindow = rwindow;
1126 int RenderRange1Frame::handle_event()
1128 rwindow->update_range_type(RANGE_1FRAME);
1132 double Render::get_render_range()
1134 EDL *edl = mwindow->edl;
1135 double last = edl->tracks->total_playable_length();
1136 double framerate = edl->session->frame_rate;
1137 if( framerate <= 0 ) framerate = 1;
1138 double start = 0, end = last;
1139 switch( range_type ) {
1141 case RANGE_BACKCOMPAT:
1142 start = edl->local_session->get_selectionstart(1);
1143 end = edl->local_session->get_selectionend(1);
1144 if( EQUIV(start, end) ) end = last;
1148 case RANGE_SELECTION:
1149 start = edl->local_session->get_selectionstart(1);
1150 end = edl->local_session->get_selectionend(1);
1153 start = edl->local_session->inpoint_valid() ?
1154 edl->local_session->get_inpoint() : 0;
1155 end = edl->local_session->outpoint_valid() ?
1156 edl->local_session->get_outpoint() : last;
1159 start = end = edl->local_session->get_selectionstart(1);
1160 if( edl->session->frame_rate > 0 ) end += 1./edl->session->frame_rate;
1163 if( start < 0 ) start = 0;
1164 if( end > last ) end = last;
1168 RenderFormat::RenderFormat(MWindow *mwindow, BC_WindowBase *window, Asset *asset)
1169 : FormatTools(mwindow, window, asset)
1172 RenderFormat::~RenderFormat()
1176 void RenderFormat::update_format()
1178 FormatTools::update_format();
1179 RenderWindow *render_window = (RenderWindow *)window;
1180 if( render_window->is_hidden() ) return;
1182 int is_image = File::is_image_render(asset->format);
1184 render_window->update_range_type(RANGE_1FRAME);
1185 render_window->enable_render_range(0);
1188 render_window->enable_render_range(1);
1191 RenderBeepOnDone::RenderBeepOnDone(RenderWindow *rwindow, int x, int y)
1192 : BC_CheckBox(x, y, rwindow->render->beep, _("Beep on done"))
1194 this->rwindow = rwindow;
1197 int RenderBeepOnDone::handle_event()
1199 rwindow->render->beep = get_value();