4 * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
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.
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.
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
26 #include "awindowgui.h"
27 #include "batchrender.h"
28 #include "bcprogressbox.h"
29 #include "bcsignals.h"
32 #include "compresspopup.h"
33 #include "condition.h"
34 #include "confirmsave.h"
35 #include "cwindowgui.h"
40 #include "edlsession.h"
43 #include "filesystem.h"
45 #include "formatcheck.h"
46 #include "formatpopup.h"
47 #include "formattools.h"
48 #include "indexable.h"
52 #include "localsession.h"
53 #include "mainprogress.h"
54 #include "mainsession.h"
58 #include "mwindowgui.h"
60 #include "packagedispatcher.h"
61 #include "packagerenderer.h"
63 #include "playabletracks.h"
64 #include "preferences.h"
65 #include "preferencesthread.h"
66 #include "renderfarm.h"
68 #include "renderprofiles.h"
69 #include "statusbar.h"
73 #include "transportque.h"
76 #include "videoconfig.h"
84 RenderItem::RenderItem(MWindow *mwindow)
85 : BC_MenuItem(_("Render..."), _("Shift-R"), 'R')
87 this->mwindow = mwindow;
91 int RenderItem::handle_event()
93 mwindow->gui->unlock_window();
94 mwindow->render->start_interactive();
95 mwindow->gui->lock_window("RenderItem::handle_event");
108 RenderProgress::RenderProgress(MWindow *mwindow, Render *render)
111 this->mwindow = mwindow;
112 this->render = render;
114 Thread::set_synchronous(1);
117 RenderProgress::~RenderProgress()
124 void RenderProgress::run()
126 Thread::disable_cancel();
129 if(render->total_rendered != last_value)
131 render->progress->update(render->total_rendered);
132 last_value = render->total_rendered;
134 if(mwindow) mwindow->preferences_thread->update_rates();
137 Thread::enable_cancel();
139 Thread::disable_cancel();
145 MainPackageRenderer::MainPackageRenderer(Render *render)
148 this->render = render;
153 MainPackageRenderer::~MainPackageRenderer()
158 int MainPackageRenderer::get_master()
163 int MainPackageRenderer::get_result()
165 return render->result;
168 void MainPackageRenderer::set_result(int value)
171 render->result = value;
177 void MainPackageRenderer::set_progress(int64_t value)
179 render->counter_lock->lock("MainPackageRenderer::set_progress");
180 // Increase total rendered for all nodes
181 render->total_rendered += value;
183 // Update frames per second for master node
184 render->preferences->set_rate(frames_per_second, -1);
186 //printf("MainPackageRenderer::set_progress %d %ld %f\n", __LINE__, (long)value, frames_per_second);
188 // If non interactive, print progress out
189 if(!render->progress)
190 render->show_progress();
192 render->counter_lock->unlock();
195 mwindow->preferences->copy_rates_from(preferences);
198 int MainPackageRenderer::progress_cancelled()
200 return (render->progress && render->progress->is_cancelled()) ||
201 render->batch_cancelled;
205 Render::Render(MWindow *mwindow)
208 this->mwindow = mwindow;
212 package_lock = new Mutex("Render::package_lock");
213 counter_lock = new Mutex("Render::counter_lock");
214 completion = new Condition(0, "Render::completion");
215 progress_timer = new Timer;
216 range_type = RANGE_BACKCOMPAT;
217 preferences = new Preferences();
218 thread = new RenderThread(mwindow, this);
231 delete progress_timer;
232 if( asset ) asset->Garbage::remove_user();
236 void Render::start_interactive()
238 if( !thread->running() ) {
239 mode = Render::INTERACTIVE;
240 BC_DialogThread::start();
242 else if( in_progress ) {
244 mwindow->gui->get_abs_cursor(cx, cy, 1);
245 ErrorBox error_box(_(PROGRAM_NAME ": Error"), cx, cy);
246 error_box.create_objects(_("Already rendering"));
247 error_box.raise_window();
248 error_box.run_window();
250 else if( render_window ) {
251 render_window->raise_window();
256 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs)
258 if(!thread->running())
260 mode = Render::BATCH;
266 else if( in_progress ) {
268 mwindow->gui->get_abs_cursor(cx, cy, 1);
269 ErrorBox error_box(_(PROGRAM_NAME ": Error"), cx, cy);
270 error_box.create_objects("Already rendering");
271 error_box.raise_window();
272 error_box.run_window();
274 // raise the window if rendering hasn't started yet
275 else if( render_window ) {
276 render_window->raise_window();
280 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs,
281 BC_Hash *boot_defaults, Preferences *batch_prefs)
283 mode = Render::BATCH;
285 preferences->copy_from(batch_prefs);
293 BC_Window* Render::new_gui()
299 if(mode == Render::INTERACTIVE) {
300 // Fix the asset for rendering
301 if(!asset) asset = new Asset;
302 load_defaults(asset);
303 check_asset(mwindow->edl, *asset);
304 int px = mwindow->gui->get_pop_cursor_x(1);
305 int py = mwindow->gui->get_pop_cursor_y(1);
306 // Get format from user
307 render_window = new RenderWindow(mwindow, this, asset, px, py);
308 render_window->create_objects();
311 return render_window;
314 void Render::handle_done_event(int result)
317 // add to recentlist only on OK
318 render_window->render_format->path_recent->
319 add_item(File::formattostr(asset->format), asset->path);
320 setenv("CIN_RENDER", asset->path, 1);
325 void Render::handle_close_event(int result)
328 double render_range = get_render_range();
329 const char *err_msg = 0;
331 if( !result && !render_range ) {
332 err_msg = _("zero render range");
335 if( !result && asset->video_data ) {
336 double frame_rate = mwindow->edl->session->frame_rate;
337 if( frame_rate > 0 && render_range+1e-3 < 1./frame_rate ) {
338 err_msg = _("Video data and range less than 1 frame");
342 if( !result && asset->audio_data ) {
343 double sample_rate = mwindow->edl->session->sample_rate;
344 if( sample_rate > 0 && render_range+1e-6 < 1./sample_rate ) {
345 err_msg = _("Audio data and range less than 1 sample");
349 if( !result && File::is_image_render(asset->format) ) {
350 if( asset->video_data ) {
351 double frames = render_range * mwindow->edl->session->frame_rate;
352 if( !EQUIV(frames, 1.) ) {
353 err_msg = _("Image format and not 1 frame");
358 err_msg = _("Image format and no video data");
364 mwindow->gui->get_abs_cursor(cx, cy, 1);
365 ErrorBox error_box(_(PROGRAM_NAME ": Error"),cx, cy);
366 error_box.create_objects(err_msg);
367 error_box.raise_window();
368 error_box.run_window();
372 // Check the asset format for errors.
373 FormatCheck format_check(asset);
374 if( format_check.check_format() )
380 save_defaults(asset);
382 mwindow->save_defaults();
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__);
395 void Render::stop_operation()
397 if(thread->Thread::running())
400 // Wait for completion
401 completion->lock("Render::stop_operation");
406 int Render::check_asset(EDL *edl, Asset &asset)
408 if(asset.video_data &&
409 edl->tracks->playable_video_tracks() &&
410 File::renders_video(&asset))
412 asset.video_data = 1;
414 asset.width = edl->session->output_w;
415 asset.height = edl->session->output_h;
416 asset.interlace_mode = edl->session->interlace_mode;
420 asset.video_data = 0;
424 if(asset.audio_data &&
425 edl->tracks->playable_audio_tracks() &&
426 File::renders_audio(&asset))
428 asset.audio_data = 1;
429 asset.channels = edl->session->audio_channels;
433 asset.audio_data = 0;
437 if(!asset.audio_data &&
445 int Render::get_strategy(int use_renderfarm, int use_labels)
447 return use_renderfarm ?
448 (use_labels ? FILE_PER_LABEL_FARM : SINGLE_PASS_FARM) :
449 (use_labels ? FILE_PER_LABEL : SINGLE_PASS ) ;
451 int Render::get_strategy()
453 return get_strategy(preferences->use_renderfarm, use_labels);
456 void Render::start_progress()
458 char filename[BCTEXTLEN];
459 char string[BCTEXTLEN];
462 progress_max = packages->get_progress_max();
464 progress_timer->update();
468 // Generate the progress box
469 fs.extract_name(filename, default_asset->path);
470 sprintf(string, _("Rendering %s..."), filename);
472 // Don't bother with the filename since renderfarm defeats the meaning
473 progress = mwindow->mainprogress->start_progress(_("Rendering..."),
475 render_progress = new RenderProgress(mwindow, this);
476 render_progress->start();
480 void Render::stop_progress()
484 char string[BCTEXTLEN], string2[BCTEXTLEN];
485 delete render_progress;
486 progress->get_time(string);
487 elapsed_time = progress->get_time();
488 progress->stop_progress();
491 sprintf(string2, _("Rendering took %s"), string);
492 mwindow->gui->lock_window("");
493 mwindow->gui->show_message(string2);
494 mwindow->gui->update_default_message();
495 mwindow->gui->stop_hourglass();
496 mwindow->gui->unlock_window();
501 void Render::show_progress()
503 int64_t current_eta = progress_timer->get_scaled_difference(1000);
504 if (current_eta - last_eta < 1000 ) return;
505 double eta = !total_rendered ? 0 :
506 current_eta / 1000. * (progress_max / (double)total_rendered - 1.);
507 char string[BCTEXTLEN]; Units::totext(string, eta, TIME_HMS2);
508 printf("\r%d%% %s: %s ",
509 (int)(100 * (float)total_rendered / progress_max), _("ETA"), string);
511 last_eta = current_eta;
516 void Render::start_render()
526 void Render::create_filename(char *path,
533 int len = strlen(default_path);
534 char printf_string[BCTEXTLEN];
536 for(i = 0, j = 0; i < number_start; i++, j++)
538 printf_string[j] = default_path[i];
542 sprintf(&printf_string[j], "%%0%dd", total_digits);
543 j = strlen(printf_string);
546 // Copy remainder of string
547 for( ; i < len; i++, j++)
549 printf_string[j] = default_path[i];
551 printf_string[j] = 0;
552 // Print the printf argument to the path
553 sprintf(path, printf_string, current_number);
556 void Render::get_starting_number(char *path,
562 int len = strlen(path);
563 char number_text[BCTEXTLEN];
571 ptr2 = strrchr(path, '/');
573 // Search for first 0 after last /.
575 ptr = strchr(ptr2, '0');
577 if(ptr && isdigit(*ptr))
579 number_start = ptr - path;
581 // Store the first number
582 char *ptr2 = number_text;
586 current_number = atol(number_text);
587 total_digits = strlen(number_text);
591 // No number found or number not long enough
592 if(total_digits < min_digits)
596 total_digits = min_digits;
601 int Render::load_defaults(Asset *asset)
603 use_labels = mwindow->defaults->get("RENDER_FILE_PER_LABEL", 0);
604 load_mode = mwindow->defaults->get("RENDER_LOADMODE", LOADMODE_NEW_TRACKS);
605 range_type = mwindow->defaults->get("RENDER_RANGE_TYPE", RANGE_PROJECT);
607 // some defaults which work
608 asset->video_data = 1;
609 asset->audio_data = 1;
610 asset->format = FILE_FFMPEG;
611 strcpy(asset->acodec, "mp4.qt");
612 strcpy(asset->vcodec, "mp4.qt");
614 asset->load_defaults(mwindow->defaults,
615 "RENDER_", 1, 1, 1, 1, 1);
619 int Render::load_profile(int profile_slot, Asset *asset)
621 char string_name[100];
622 sprintf(string_name, "RENDER_%i_FILE_PER_LABEL", profile_slot);
623 use_labels = mwindow->defaults->get(string_name, 0);
624 // Load mode is not part of the profile
625 // printf(string_name, "RENDER_%i_LOADMODE", profile_slot);
626 // load_mode = mwindow->defaults->get(string_name, LOADMODE_NEW_TRACKS);
627 sprintf(string_name, "RENDER_%i_RANGE_TYPE", profile_slot);
628 range_type = mwindow->defaults->get(string_name, RANGE_PROJECT);
630 sprintf(string_name, "RENDER_%i_", profile_slot);
631 asset->load_defaults(mwindow->defaults,
632 string_name, 1, 1, 1, 1, 1);
637 int Render::save_defaults(Asset *asset)
639 mwindow->defaults->update("RENDER_FILE_PER_LABEL", use_labels);
640 mwindow->defaults->update("RENDER_LOADMODE", load_mode);
641 mwindow->defaults->update("RENDER_RANGE_TYPE", range_type);
643 asset->save_defaults(mwindow->defaults,
644 "RENDER_", 1, 1, 1, 1, 1);
649 static void run_script(const char *script, const char *arg)
651 char *const argv[] = { (char*)script, (char*)arg, 0 };
652 execvp(script ,&argv[0]);
653 perror("execvp script failed");
657 RenderThread::RenderThread(MWindow *mwindow, Render *render)
660 this->mwindow = mwindow;
661 this->render = render;
664 RenderThread::~RenderThread()
669 void RenderThread::render_single(int test_overwrite, Asset *asset, EDL *edl,
670 int strategy, int range_type)
672 // Total length in seconds
674 RenderFarmServer *farm_server = 0;
678 render->in_progress = 1;
681 render->default_asset = asset;
682 render->progress = 0;
685 // Create rendering command
686 TransportCommand *command = new TransportCommand;
687 command->command = NORMAL_FWD;
688 command->get_edl()->copy_all(edl);
689 command->change_type = CHANGE_ALL;
691 switch( range_type ) {
692 case RANGE_BACKCOMPAT:
693 // Get highlighted playback range
694 command->set_playback_range();
695 // Adjust playback range with in/out points
696 command->playback_range_adjust_inout();
699 command->playback_range_project();
701 case RANGE_SELECTION:
702 command->set_playback_range();
705 command->playback_range_inout();
708 command->playback_range_1frame();
712 render->packages = new PackageDispatcher;
715 CICache *audio_cache = new CICache(render->preferences);
716 CICache *video_cache = new CICache(render->preferences);
718 render->default_asset->frame_rate = command->get_edl()->session->frame_rate;
719 render->default_asset->sample_rate = command->get_edl()->session->sample_rate;
721 // Conform asset to EDL. Find out if any tracks are playable.
722 render->result = render->check_asset(command->get_edl(),
723 *render->default_asset);
727 // Get total range to render
728 render->total_start = command->start_position;
729 render->total_end = command->end_position;
730 total_length = render->total_end - render->total_start;
733 if(EQUIV(total_length, 0))
742 // Stop background rendering
743 if(mwindow) mwindow->stop_brender();
745 fs.complete_path(render->default_asset->path);
747 render->result = render->packages->create_packages(mwindow,
751 render->default_asset,
757 render->total_rendered = 0;
761 // Start dispatching external jobs
764 mwindow->gui->lock_window("Render::render 1");
765 mwindow->gui->show_message(_("Starting render farm"));
766 mwindow->gui->start_hourglass();
767 mwindow->gui->unlock_window();
771 printf("Render::render: starting render farm\n");
774 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
776 farm_server = new RenderFarmServer(mwindow,
781 &render->total_rendered,
782 render->counter_lock,
783 render->default_asset,
786 render->result = farm_server->start_clients();
792 mwindow->gui->lock_window("Render::render 2");
793 mwindow->gui->show_message(_("Failed to start render farm"),
794 mwindow->theme->message_error);
795 mwindow->gui->stop_hourglass();
796 mwindow->gui->unlock_window();
800 printf("Render::render: Failed to start render farm\n");
806 // Perform local rendering
811 render->start_progress();
816 MainPackageRenderer package_renderer(render);
817 render->result = package_renderer.initialize(mwindow,
818 command->get_edl(), // Copy of master EDL
820 render->default_asset);
828 while(!render->result)
830 // Get unfinished job
831 RenderPackage *package;
833 if(strategy == SINGLE_PASS_FARM)
835 package = render->packages->get_package(
836 package_renderer.frames_per_second,
842 package = render->packages->get_package(0, -1, 1);
851 if(package_renderer.render_package(package))
859 printf("Render::render_single: Session finished.\n");
865 if( strategy == SINGLE_PASS_FARM ||
866 strategy == FILE_PER_LABEL_FARM ) {
867 if( !render->progress ) {
868 while( farm_server->active_clients() > 0 ) {
870 render->show_progress();
873 farm_server->wait_clients();
874 render->result |= render->packages->packages_are_done();
877 if(debug) printf("Render::render %d\n", __LINE__);
881 (!render->progress || !render->progress->is_cancelled()) &&
882 !render->batch_cancelled)
884 if(debug) printf("Render::render %d\n", __LINE__);
887 if(debug) printf("Render::render %d\n", __LINE__);
889 mwindow->gui->get_abs_cursor(cx, cy, 1);
890 ErrorBox error_box(_(PROGRAM_NAME ": Error"), cx, cy);
891 error_box.create_objects(_("Error rendering data."));
892 error_box.raise_window();
893 error_box.run_window();
894 if(debug) printf("Render::render %d\n", __LINE__);
898 printf("Render::render: Error rendering data\n");
901 if(debug) printf("Render::render %d\n", __LINE__);
903 // Delete the progress box
904 render->stop_progress();
906 if(debug) printf("Render::render %d\n", __LINE__);
910 // Paste all packages into timeline if desired
912 if(!render->result &&
913 render->load_mode != LOADMODE_NOTHING &&
915 render->mode != Render::BATCH)
917 if(debug) printf("Render::render %d\n", __LINE__);
918 mwindow->gui->lock_window("Render::render 3");
919 if(debug) printf("Render::render %d\n", __LINE__);
921 mwindow->undo->update_undo_before();
923 if(debug) printf("Render::render %d\n", __LINE__);
926 ArrayList<Indexable*> *assets = render->packages->get_asset_list();
927 if(debug) printf("Render::render %d\n", __LINE__);
928 if(render->load_mode == LOADMODE_PASTE)
930 if(debug) printf("Render::render %d\n", __LINE__);
931 mwindow->load_assets(assets, -1, render->load_mode, 0, 0,
932 mwindow->edl->session->labels_follow_edits,
933 mwindow->edl->session->plugins_follow_edits,
934 mwindow->edl->session->autos_follow_edits,
936 if(debug) printf("Render::render %d\n", __LINE__);
937 for(int i = 0; i < assets->size(); i++)
938 assets->get(i)->Garbage::remove_user();
940 if(debug) printf("Render::render %d\n", __LINE__);
943 mwindow->save_backup();
944 if(debug) printf("Render::render %d\n", __LINE__);
945 mwindow->undo->update_undo_after(_("render"), LOAD_ALL);
946 if(debug) printf("Render::render %d\n", __LINE__);
947 mwindow->update_plugin_guis();
948 if(debug) printf("Render::render %d\n", __LINE__);
949 mwindow->gui->update(1,
956 if(debug) printf("Render::render %d\n", __LINE__);
957 mwindow->sync_parameters(CHANGE_ALL);
958 if(debug) printf("Render::render %d\n", __LINE__);
959 mwindow->gui->unlock_window();
962 mwindow->awindow->gui->async_update_assets();
964 if(debug) printf("Render::render %d\n", __LINE__);
967 if(debug) printf("Render::render %d\n", __LINE__);
972 mwindow->gui->lock_window("Render::render 3");
973 mwindow->gui->stop_hourglass();
974 mwindow->gui->unlock_window();
977 //printf("Render::render 110\n");
978 // Need to restart because brender always stops before render.
980 mwindow->restart_brender();
981 if(farm_server) delete farm_server;
985 // Must delete packages after server
986 delete render->packages;
988 render->packages = 0;
989 render->in_progress = 0;
990 if(debug) printf("Render::render %d\n", __LINE__);
993 void RenderThread::run()
996 render->preferences->copy_from(mwindow->preferences);
998 if(render->mode == Render::INTERACTIVE)
1000 render_single(1, render->asset, mwindow->edl,
1001 render->get_strategy(), render->range_type);
1004 if(render->mode == Render::BATCH)
1007 // printf("RenderThread::run %d %d %d\n",
1009 // render->jobs->total,
1011 for(int i = 0; i < render->jobs->total && !render->result; i++)
1014 BatchRenderJob *job = render->jobs->values[i];
1018 if( *job->edl_path == '@' )
1020 run_script(job->edl_path+1, job->asset->path);
1025 mwindow->batch_render->update_active(i);
1029 printf("Render::run: %s\n", job->edl_path);
1034 FileXML *file = new FileXML;
1036 edl->create_objects();
1037 file->read_from_file(job->edl_path);
1038 edl->load_xml(file, LOAD_ALL);
1040 render_single(0, job->asset, edl, job->get_strategy(), RANGE_BACKCOMPAT);
1043 edl->Garbage::remove_user();
1048 mwindow->batch_render->update_done(i, 1, render->elapsed_time);
1051 char string[BCTEXTLEN];
1052 render->elapsed_time =
1053 (double)render->progress_timer->get_scaled_difference(1);
1054 Units::totext(string,
1055 render->elapsed_time,
1057 printf("Render::run: done in %s\n", string);
1063 mwindow->batch_render->update_active(-1);
1065 printf("Render::run: failed\n");
1073 mwindow->batch_render->update_active(-1);
1074 mwindow->batch_render->update_done(-1, 0, 0);
1077 render->completion->unlock();
1085 RenderWindow::RenderWindow(MWindow *mwindow,
1090 : BC_Window(_(PROGRAM_NAME ": Render"), x, y,
1091 WIDTH, HEIGHT, WIDTH, HEIGHT, 0, 0, 1)
1093 this->mwindow = mwindow;
1094 this->render = render;
1095 this->asset = asset;
1105 RenderWindow::~RenderWindow()
1107 lock_window("RenderWindow::~RenderWindow");
1108 delete render_format;
1110 delete renderprofile;
1115 void RenderWindow::load_profile(int profile_slot)
1117 render->load_profile(profile_slot, asset);
1118 update_range_type(render->range_type);
1119 render_format->update(asset, &render->use_labels);
1123 void RenderWindow::create_objects()
1126 lock_window("RenderWindow::create_objects");
1127 add_subwindow(new BC_Title(x, y,
1128 (char*)(render->use_labels ?
1129 _("Select the first file to render to:") :
1130 _("Select a file to render to:"))));
1133 render_format = new RenderFormat(mwindow, this, asset);
1134 render_format->create_objects(x, y,
1135 1, 1, 1, 1, 0, 1, 0, 0, &render->use_labels, 0);
1138 add_subwindow(title = new BC_Title(x, y, _("Render range:")));
1140 int is_image = File::is_image_render(asset->format);
1142 render->range_type = RANGE_1FRAME;
1144 int x1 = x + title->get_w() + 20;
1145 add_subwindow(rangeproject = new RenderRangeProject(this,
1146 render->range_type == RANGE_PROJECT, x1, y));
1148 add_subwindow(rangeselection = new RenderRangeSelection(this,
1149 render->range_type == RANGE_SELECTION, x1, y));
1151 add_subwindow(rangeinout = new RenderRangeInOut(this,
1152 render->range_type == RANGE_INOUT, x1, y));
1154 add_subwindow(range1frame = new RenderRange1Frame(this,
1155 render->range_type == RANGE_1FRAME, x1, y));
1159 enable_render_range(0);
1161 renderprofile = new RenderProfile(mwindow, this, x, y, 1);
1162 renderprofile->create_objects();
1165 loadmode = new LoadMode(mwindow, this, x, y, &render->load_mode, 1);
1166 loadmode->create_objects();
1168 add_subwindow(new BC_OKButton(this));
1169 add_subwindow(new BC_CancelButton(this));
1175 void RenderWindow::update_range_type(int range_type)
1177 if( render->range_type == range_type ) return;
1178 render->range_type = range_type;
1179 rangeproject->update(range_type == RANGE_PROJECT);
1180 rangeselection->update(range_type == RANGE_SELECTION);
1181 rangeinout->update(range_type == RANGE_INOUT);
1182 range1frame->update(range_type == RANGE_1FRAME);
1185 void RenderWindow::enable_render_range(int v)
1188 rangeproject->enable();
1189 rangeselection->enable();
1190 rangeinout->enable();
1191 range1frame->enable();
1194 rangeproject->disable();
1195 rangeselection->disable();
1196 rangeinout->disable();
1197 range1frame->disable();
1202 RenderRangeProject::RenderRangeProject(RenderWindow *rwindow, int value, int x, int y)
1203 : BC_Radial(x, y, value, _("Project"))
1205 this->rwindow = rwindow;
1207 int RenderRangeProject::handle_event()
1209 rwindow->update_range_type(RANGE_PROJECT);
1213 RenderRangeSelection::RenderRangeSelection(RenderWindow *rwindow, int value, int x, int y)
1214 : BC_Radial(x, y, value, _("Selection"))
1216 this->rwindow = rwindow;
1218 int RenderRangeSelection::handle_event()
1220 rwindow->update_range_type(RANGE_SELECTION);
1225 RenderRangeInOut::RenderRangeInOut(RenderWindow *rwindow, int value, int x, int y)
1226 : BC_Radial(x, y, value, _("In/Out Points"))
1228 this->rwindow = rwindow;
1230 int RenderRangeInOut::handle_event()
1232 rwindow->update_range_type(RANGE_INOUT);
1236 RenderRange1Frame::RenderRange1Frame(RenderWindow *rwindow, int value, int x, int y)
1237 : BC_Radial(x, y, value, _("One Frame"))
1239 this->rwindow = rwindow;
1241 int RenderRange1Frame::handle_event()
1243 rwindow->update_range_type(RANGE_1FRAME);
1247 double Render::get_render_range()
1249 EDL *edl = mwindow->edl;
1250 double last = edl->tracks->total_playable_length();
1251 double framerate = edl->session->frame_rate;
1252 if( framerate <= 0 ) framerate = 1;
1253 double start = 0, end = last;
1254 switch( range_type ) {
1256 case RANGE_BACKCOMPAT:
1257 start = edl->local_session->get_selectionstart(1);
1258 end = edl->local_session->get_selectionend(1);
1259 if( EQUIV(start, end) ) end = last;
1263 case RANGE_SELECTION:
1264 start = edl->local_session->get_selectionstart(1);
1265 end = edl->local_session->get_selectionend(1);
1268 start = edl->local_session->inpoint_valid() ?
1269 edl->local_session->get_inpoint() : 0;
1270 end = edl->local_session->outpoint_valid() ?
1271 edl->local_session->get_outpoint() : last;
1274 start = end = edl->local_session->get_selectionstart(1);
1275 if( edl->session->frame_rate > 0 ) end += 1./edl->session->frame_rate;
1278 if( start < 0 ) start = 0;
1279 if( end > last ) end = last;
1283 RenderFormat::RenderFormat(MWindow *mwindow, BC_WindowBase *window, Asset *asset)
1284 : FormatTools(mwindow, window, asset)
1287 RenderFormat::~RenderFormat()
1291 void RenderFormat::update_format()
1293 FormatTools::update_format();
1294 RenderWindow *render_window = (RenderWindow *)window;
1295 if( render_window->is_hidden() ) return;
1297 int is_image = File::is_image_render(asset->format);
1299 render_window->update_range_type(RANGE_1FRAME);
1300 render_window->enable_render_range(0);
1303 render_window->enable_render_range(1);