3 * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
4 * Copyright (C) 2003-2016 Cinelerra CV contributors
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 "mainerror.h"
54 #include "mainprogress.h"
55 #include "mainsession.h"
59 #include "mwindowgui.h"
61 #include "packagedispatcher.h"
62 #include "packagerenderer.h"
64 #include "playabletracks.h"
65 #include "preferences.h"
66 #include "preferencesthread.h"
67 #include "renderfarm.h"
69 #include "renderprofiles.h"
70 #include "statusbar.h"
74 #include "transportque.h"
77 #include "videoconfig.h"
85 RenderItem::RenderItem(MWindow *mwindow)
86 : BC_MenuItem(_("Render..."), _("Shift-R"), 'R')
88 this->mwindow = mwindow;
92 int RenderItem::handle_event()
94 mwindow->gui->unlock_window();
95 mwindow->render->start_interactive();
96 mwindow->gui->lock_window("RenderItem::handle_event");
100 RenderProgress::RenderProgress(MWindow *mwindow, Render *render)
103 this->mwindow = mwindow;
104 this->render = render;
106 Thread::set_synchronous(1);
109 RenderProgress::~RenderProgress()
116 void RenderProgress::run()
118 Thread::disable_cancel();
120 if( render->total_rendered != last_value ) {
121 render->progress->update(render->total_rendered);
122 last_value = render->total_rendered;
124 if( mwindow ) mwindow->preferences_thread->update_rates();
127 Thread::enable_cancel();
129 Thread::disable_cancel();
135 MainPackageRenderer::MainPackageRenderer(Render *render)
138 this->render = render;
143 MainPackageRenderer::~MainPackageRenderer()
148 int MainPackageRenderer::get_master()
153 int MainPackageRenderer::get_result()
155 return render->result;
158 void MainPackageRenderer::set_result(int value)
161 render->result = value;
164 void MainPackageRenderer::set_progress(int64_t value)
166 render->counter_lock->lock("MainPackageRenderer::set_progress");
167 // Increase total rendered for all nodes
168 render->total_rendered += value;
170 // Update frames per second for master node
171 render->preferences->set_rate(frames_per_second, -1);
173 //printf("MainPackageRenderer::set_progress %d %ld %f\n", __LINE__, (long)value, frames_per_second);
175 // If non interactive, print progress out
176 if( !render->progress )
177 render->show_progress();
179 render->counter_lock->unlock();
182 mwindow->preferences->copy_rates_from(preferences);
185 int MainPackageRenderer::progress_cancelled()
187 return (render->progress && render->progress->is_cancelled()) ||
188 render->batch_cancelled;
191 void RenderAssets::clear()
193 for( int i=size(); --i>=0; get(i)->remove_user() );
196 RenderAssets::RenderAssets()
199 RenderAssets::~RenderAssets()
204 Render::Render(MWindow *mwindow)
207 this->mwindow = mwindow;
211 package_lock = new Mutex("Render::package_lock");
212 counter_lock = new Mutex("Render::counter_lock");
213 completion = new Condition(0, "Render::completion");
214 progress_timer = new Timer;
215 range_type = RANGE_BACKCOMPAT;
216 preferences = new Preferences();
217 thread = new RenderThread(mwindow, this);
232 delete progress_timer;
233 if( asset ) asset->Garbage::remove_user();
237 void Render::start_interactive()
239 if( !thread->running() ) {
240 mode = Render::INTERACTIVE;
241 BC_DialogThread::start();
243 else if( in_progress ) {
245 mwindow->gui->get_abs_cursor(cx, cy, 1);
246 ErrorBox error_box(_(PROGRAM_NAME ": Error"), cx, cy);
247 error_box.create_objects(_("Already rendering"));
248 error_box.raise_window();
249 error_box.run_window();
251 else if( render_window ) {
252 render_window->raise_window();
257 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs)
259 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 mwindow->edl->session->render_beep = beep;
318 // add to recentlist only on OK
319 render_window->render_format->path_recent->
320 add_item(File::formattostr(asset->format), asset->path);
321 setenv("CIN_RENDER", asset->path, 1);
326 void Render::handle_close_event(int result)
329 double render_range = get_render_range();
330 const char *err_msg = 0;
332 if( !result && !render_range ) {
333 err_msg = _("zero render range");
336 if( !result && !asset->audio_data && !asset->video_data ) {
337 err_msg = _("no audio or video in render asset format\n");
340 EDL *edl = mwindow->edl;
341 if( !result && use_labels && !edl->labels->first ) {
342 eprintf(_("Create new file at labels checked, but no labels\n"));
345 if( !result && asset->video_data ) {
346 double frame_rate = edl->session->frame_rate;
347 if( frame_rate > 0 && render_range+1e-3 < 1./frame_rate ) {
348 err_msg = _("Video data and range less than 1 frame");
352 if( !result && asset->audio_data ) {
353 double sample_rate = edl->session->sample_rate;
354 if( sample_rate > 0 && render_range+1e-6 < 1./sample_rate ) {
355 err_msg = _("Audio data and range less than 1 sample");
359 if( !result && File::is_image_render(asset->format) ) {
360 if( asset->video_data ) {
361 double frames = render_range * edl->session->frame_rate;
362 if( !EQUIV(frames, 1.) ) {
363 err_msg = _("Image format and not 1 frame");
368 err_msg = _("Image format and no video data");
375 mwindow->gui->get_abs_cursor(cx, cy, 1);
376 ErrorBox error_box(_(PROGRAM_NAME ": Error"),cx, cy);
377 error_box.create_objects(err_msg);
378 error_box.raise_window();
379 error_box.run_window();
383 // Check the asset format for errors.
384 FormatCheck format_check(asset);
385 if( format_check.check_format() )
391 save_defaults(asset);
393 mwindow->save_defaults();
397 if( debug ) printf("Render::handle_close_event %d\n", __LINE__);
398 if( !result ) start_render();
399 if( debug ) printf("Render::handle_close_event %d\n", __LINE__);
406 void Render::stop_operation()
408 if( thread->Thread::running() ) {
410 // Wait for completion
411 completion->lock("Render::stop_operation");
416 int Render::check_asset(EDL *edl, Asset &asset)
418 if( asset.video_data &&
419 edl->tracks->playable_video_tracks() &&
420 File::renders_video(&asset) ) {
421 asset.video_data = 1;
423 asset.width = edl->session->output_w;
424 asset.height = edl->session->output_h;
425 asset.interlace_mode = edl->session->interlace_mode;
428 asset.video_data = 0;
432 if( asset.audio_data &&
433 edl->tracks->playable_audio_tracks() &&
434 File::renders_audio(&asset) ) {
435 asset.audio_data = 1;
436 asset.channels = edl->session->audio_channels;
439 asset.audio_data = 0;
443 if( !asset.audio_data &&
444 !asset.video_data ) {
450 int Render::get_strategy(int use_renderfarm, int use_labels, int range_type)
452 return range_type == RANGE_1FRAME ? SINGLE_PASS :
454 (use_labels ? FILE_PER_LABEL_FARM : SINGLE_PASS_FARM) :
455 (use_labels ? FILE_PER_LABEL : SINGLE_PASS ) ;
457 int Render::get_strategy()
459 return get_strategy(preferences->use_renderfarm, use_labels, range_type);
462 void Render::start_progress()
464 char filename[BCTEXTLEN];
465 char string[BCTEXTLEN];
466 progress_max = packages->get_progress_max();
468 progress_timer->update();
471 // Generate the progress box
473 fs.extract_name(filename, default_asset->path);
474 sprintf(string, _("Rendering %s..."), filename);
476 // Don't bother with the filename since renderfarm defeats the meaning
477 mwindow->gui->lock_window("Render::start_progress");
478 progress = mwindow->mainprogress->start_progress(_("Rendering..."),
480 mwindow->gui->unlock_window();
481 render_progress = new RenderProgress(mwindow, this);
482 render_progress->start();
486 void Render::stop_progress()
489 char string[BCTEXTLEN], string2[BCTEXTLEN];
490 delete render_progress;
491 progress->get_time(string);
492 elapsed_time = progress->get_time();
493 progress->stop_progress();
496 sprintf(string2, _("Rendering took %s"), string);
497 mwindow->gui->lock_window("Render::stop_progress");
498 mwindow->gui->show_message(string2);
499 mwindow->gui->update_default_message();
500 mwindow->gui->stop_hourglass();
501 mwindow->gui->unlock_window();
506 void Render::show_progress()
508 int64_t current_eta = progress_timer->get_scaled_difference(1000);
509 if( current_eta - last_eta < 1000 ) return;
510 double eta = !total_rendered ? 0 :
511 current_eta / 1000. * (progress_max / (double)total_rendered - 1.);
512 char string[BCTEXTLEN]; Units::totext(string, eta, TIME_HMS2);
513 printf("\r%d%% %s: %s ",
514 (int)(100 * (float)total_rendered / progress_max), _("ETA"), string);
516 last_eta = current_eta;
521 void Render::start_render()
531 void Render::create_filename(char *path,
538 int len = strlen(default_path);
539 char printf_string[BCTEXTLEN];
541 for( i=0, j=0; i<number_start; ++i, ++j ) {
542 printf_string[j] = default_path[i];
546 sprintf(&printf_string[j], "%%0%dd", total_digits);
547 j = strlen(printf_string);
550 // Copy remainder of string
551 for( ; i<len; ++i, ++j ) {
552 printf_string[j] = default_path[i];
554 printf_string[j] = 0;
555 // Print the printf argument to the path
556 sprintf(path, printf_string, current_number);
559 void Render::get_starting_number(char *path,
565 int len = strlen(path);
566 char number_text[BCTEXTLEN];
574 ptr2 = strrchr(path, '/');
576 // Search for first 0 after last /.
578 ptr = strchr(ptr2, '0');
580 if( ptr && isdigit(*ptr) ) {
581 number_start = ptr - path;
583 // Store the first number
584 char *ptr2 = number_text;
585 while( isdigit(*ptr) ) *ptr2++ = *ptr++;
587 current_number = atol(number_text);
588 total_digits = strlen(number_text);
592 // No number found or number not long enough
593 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);
648 void Render::update_assets()
651 packages->get_asset_list(assets);
654 static void run_script(const char *script, const char *arg)
656 char *const argv[] = { (char*)script, (char*)arg, 0 };
657 execvp(script ,&argv[0]);
658 perror("execvp script failed");
662 RenderThread::RenderThread(MWindow *mwindow, Render *render)
665 this->mwindow = mwindow;
666 this->render = render;
670 RenderThread::~RenderThread()
675 void RenderThread::render_single(int test_overwrite, Asset *asset, EDL *edl,
676 int strategy, int range_type)
678 // Total length in seconds
679 double total_length = 0;
680 RenderFarmServer *farm_server = 0;
682 render->in_progress = 1;
683 render->default_asset = asset;
684 render->progress = 0;
687 // Create rendering command
688 TransportCommand *command = new TransportCommand(render->preferences);
689 command->command = NORMAL_FWD;
690 command->get_edl()->copy_all(edl);
691 command->change_type = CHANGE_ALL;
693 switch( range_type ) {
694 case RANGE_BACKCOMPAT:
695 // Get highlighted playback range
696 command->set_playback_range();
697 // Adjust playback range with in/out points
698 command->playback_range_adjust_inout();
701 command->playback_range_project();
703 case RANGE_SELECTION:
704 command->set_playback_range();
707 command->playback_range_inout();
710 command->playback_range_1frame();
714 render->packages = new PackageDispatcher;
717 CICache *audio_cache = new CICache(render->preferences);
718 CICache *video_cache = new CICache(render->preferences);
720 render->default_asset->frame_rate = command->get_edl()->session->frame_rate;
721 render->default_asset->sample_rate = command->get_edl()->session->sample_rate;
723 // Conform asset to EDL. Find out if any tracks are playable.
724 render->result = render->check_asset(command->get_edl(),
725 *render->default_asset);
727 if( !render->result ) {
728 // Get total range to render
729 render->total_start = command->start_position;
731 render->default_asset->timecode = command->start_position;
732 printf("tc: %f \n", render->default_asset->timecode);
733 render->default_asset->timecode += edl->session->timecode_offset;
735 render->total_end = command->end_position;
736 total_length = render->total_end - render->total_start;
739 if( EQUIV(total_length, 0) ) {
743 // prevent single frame truncation to zero frames
744 render_frames = render->default_asset->frame_rate * total_length + 1e-4;
747 if( !render->result ) {
748 // Stop background rendering
749 if( mwindow ) mwindow->stop_brender();
752 fs.complete_path(render->default_asset->path);
754 render->result = render->packages->create_packages(mwindow, command->get_edl(),
755 render->preferences, strategy, render->default_asset,
756 render->total_start, render->total_end, test_overwrite);
759 render->total_rendered = 0;
761 if( !render->result &&
762 ( strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM ) ) {
763 // Start dispatching external jobs
765 mwindow->gui->lock_window("Render::render 1");
766 mwindow->gui->show_message(_("Starting render farm"));
767 mwindow->gui->start_hourglass();
768 mwindow->gui->unlock_window();
771 printf("Render::render: starting render farm\n");
774 farm_server = new RenderFarmServer(mwindow, render->packages,
775 render->preferences, 1, &render->result,
776 &render->total_rendered, render->counter_lock,
777 render->default_asset, command->get_edl(), 0);
778 render->result = farm_server->start_clients();
780 if( render->result ) {
782 mwindow->gui->lock_window("Render::render 2");
783 mwindow->gui->show_message(_("Failed to start render farm"),
784 mwindow->theme->message_error);
785 mwindow->gui->stop_hourglass();
786 mwindow->gui->unlock_window();
789 printf("Render::render: Failed to start render farm\n");
794 // Perform local rendering
796 render->assets.clear();
797 if( !render->result ) {
798 render->start_progress();
800 MainPackageRenderer package_renderer(render);
801 render->result = package_renderer.initialize(mwindow,
802 command->get_edl(), // Copy of master EDL
804 render->default_asset);
806 while( !render->result ) {
807 int fps = strategy == SINGLE_PASS_FARM ?
808 package_renderer.frames_per_second : 0;
809 // Get unfinished job
810 RenderPackage *package = render->packages->get_package(fps, -1, 1);
812 if( !package ) break;
814 if( package_renderer.render_package(package) )
818 printf("Render::render_single: Session finished.\n");
820 if( strategy == SINGLE_PASS_FARM ||
821 strategy == FILE_PER_LABEL_FARM ) {
822 if( !render->progress ) {
823 while( farm_server->active_clients() > 0 ) {
825 render->show_progress();
828 farm_server->wait_clients();
829 render->result |= render->packages->packages_are_done();
833 if( render->result && !render->batch_cancelled &&
834 (!render->progress || !render->progress->is_cancelled()) ) {
837 mwindow->gui->get_abs_cursor(cx, cy, 1);
838 ErrorBox error_box(_(PROGRAM_NAME ": Error"), cx, cy);
839 error_box.create_objects(_("Error rendering data."));
840 error_box.raise_window();
841 error_box.run_window();
844 printf("Render::render: Error rendering data\n");
848 // Delete the progress box
849 render->stop_progress();
850 render->update_assets();
853 // Paste all packages into timeline if desired
855 if( !render->result && mwindow &&
856 render->load_mode != LOADMODE_NOTHING &&
857 render->mode != Render::BATCH ) {
858 mwindow->gui->lock_window("Render::render 3");
860 mwindow->undo->update_undo_before();
861 if( render->load_mode == LOADMODE_PASTE )
863 mwindow->load_assets(&render->assets,
864 -1, render->load_mode, 0, 0,
865 mwindow->edl->session->labels_follow_edits,
866 mwindow->edl->session->plugins_follow_edits,
867 mwindow->edl->session->autos_follow_edits,
869 mwindow->save_backup();
870 mwindow->undo->update_undo_after(_("render"), LOAD_ALL);
871 mwindow->update_plugin_guis();
872 mwindow->gui->update(1, FORCE_REDRAW, 1, 1, 1, 1, 0);
873 mwindow->sync_parameters(CHANGE_ALL);
874 mwindow->gui->unlock_window();
876 mwindow->awindow->gui->async_update_assets();
881 mwindow->gui->lock_window("Render::render 3");
882 mwindow->gui->stop_hourglass();
883 mwindow->gui->unlock_window();
886 //printf("Render::render 110\n");
887 // Need to restart because brender always stops before render.
889 mwindow->restart_brender();
890 if( farm_server ) delete farm_server;
892 audio_cache->remove_user();
893 video_cache->remove_user();
894 // Must delete packages after server
895 delete render->packages;
897 render->packages = 0;
898 render->in_progress = 0;
901 void RenderThread::run()
907 render->preferences->copy_from(mwindow->preferences);
909 if( render->mode == Render::INTERACTIVE ) {
910 render_single(1, render->asset, mwindow->edl,
911 render->get_strategy(), render->range_type);
914 if( render->mode == Render::BATCH ) {
915 for( int i=0; i<render->jobs->total && !render->result; ++i ) {
916 BatchRenderJob *job = render->jobs->values[i];
917 if( !job->enabled ) continue;
919 mwindow->batch_render->update_active(i);
921 printf("Render::run: %s\n", job->edl_path);
923 FileXML *file = new FileXML;
925 edl->create_objects();
926 file->read_from_file(job->edl_path);
927 edl->load_xml(file, LOAD_ALL);
930 render_single(0, job->asset, edl, job->get_strategy(), RANGE_BACKCOMPAT);
931 if( !render->result ) {
933 script = job->create_script(edl, &render->assets);
935 mwindow->batch_render->update_done(i, 1, render->elapsed_time);
937 char string[BCTEXTLEN];
938 render->elapsed_time =
939 (double)render->progress_timer->get_scaled_difference(1);
940 Units::totext(string, render->elapsed_time, TIME_HMS2);
941 printf("Render::run: done in %s\n", string);
946 mwindow->batch_render->update_active(-1);
948 printf("Render::run: failed\n");
952 mwindow->batch_render->update_active(-1);
953 mwindow->batch_render->update_done(-1, 0, 0);
956 render->completion->unlock();
958 if( !render->result ) {
959 double render_time = render_timer.get_difference() / 1000.0;
960 double render_rate = render_time > 0 ? render_frames / render_time : 0;
961 printf("** rendered %jd frames in %0.3f secs, %0.3f fps\n",
962 render_frames, render_time, render_rate);
965 float gain = render->beep;
966 if( render->mode == Render::INTERACTIVE && gain > 0 )
967 mwindow->beep(3000., 1.5, gain);
970 if( !render->result )
971 run_script(script, 0);
977 #define WIDTH xS(480)
978 #define HEIGHT yS(480)
981 RenderWindow::RenderWindow(MWindow *mwindow,
986 : BC_Window(_(PROGRAM_NAME ": Render"), x, y,
987 WIDTH, HEIGHT, WIDTH, HEIGHT, 0, 0, 1)
989 this->mwindow = mwindow;
990 this->render = render;
999 // *** CONTEXT_HELP ***
1000 context_help_set_keyword("Single File Rendering");
1003 RenderWindow::~RenderWindow()
1005 lock_window("RenderWindow::~RenderWindow");
1006 delete render_format;
1008 delete renderprofile;
1013 void RenderWindow::load_profile(int profile_slot)
1015 render->load_profile(profile_slot, asset);
1016 update_range_type(render->range_type);
1017 render_format->update(asset, &render->use_labels);
1021 void RenderWindow::create_objects()
1023 int xs10 = xS(10), xs20 = xS(20);
1024 int ys10 = yS(10), ys20 = yS(20), ys25 = yS(25), ys30 = yS(30);
1025 int x = xs10, y = ys10;
1026 lock_window("RenderWindow::create_objects");
1027 add_subwindow(file_format = new BC_Title(x, y,
1028 (render->use_labels ?
1029 _("Select the first file to render to:") :
1030 _("Select a file to render to:"))));
1033 render_format = new RenderFormat(mwindow, this, asset);
1034 render_format->create_objects(x, y,
1035 1, 1, 1, 1, 0, 1, 0, 0, &render->use_labels, 0);
1038 add_subwindow(title = new BC_Title(x, y, _("Render range:")));
1040 int is_image = File::is_image_render(asset->format);
1042 render->range_type = RANGE_1FRAME;
1044 int x1 = x + title->get_w() + xs20, y1 = y;
1045 add_subwindow(rangeproject = new RenderRangeProject(this,
1046 render->range_type == RANGE_PROJECT, x1, y));
1047 int x2 = x1 + rangeproject->get_w();
1049 add_subwindow(rangeselection = new RenderRangeSelection(this,
1050 render->range_type == RANGE_SELECTION, x1, y));
1051 int x3 = x1 + rangeselection->get_w();
1052 if( x2 < x3 ) x2 = x3;
1054 add_subwindow(rangeinout = new RenderRangeInOut(this,
1055 render->range_type == RANGE_INOUT, x1, y));
1056 x3 = x1 + rangeinout->get_w();
1057 if( x2 < x3 ) x2 = x3;
1059 add_subwindow(range1frame = new RenderRange1Frame(this,
1060 render->range_type == RANGE_1FRAME, x1, y));
1061 x3 = x1 + range1frame->get_w();
1062 if( x2 < x3 ) x2 = x3;
1065 enable_render_range(0);
1068 render->beep = mwindow->edl->session->render_beep;
1069 add_subwindow(beep_on_done = new RenderBeepOnDone(this, x1, y1));
1070 y1 += beep_on_done->get_h();
1071 add_subwindow(new BC_Title(x1, y1, _("Beep on done volume")));
1073 renderprofile = new RenderProfile(mwindow, this, x, y, 1);
1074 renderprofile->create_objects();
1077 loadmode = new LoadMode(mwindow, this, x, y, &render->load_mode);
1078 loadmode->create_objects();
1080 add_subwindow(new BC_OKButton(this));
1081 add_subwindow(new BC_CancelButton(this));
1087 void RenderWindow::update_range_type(int range_type)
1089 if( render->range_type == range_type ) return;
1090 render->range_type = range_type;
1091 rangeproject->update(range_type == RANGE_PROJECT);
1092 rangeselection->update(range_type == RANGE_SELECTION);
1093 rangeinout->update(range_type == RANGE_INOUT);
1094 range1frame->update(range_type == RANGE_1FRAME);
1097 void RenderWindow::enable_render_range(int v)
1100 rangeproject->enable();
1101 rangeselection->enable();
1102 rangeinout->enable();
1103 range1frame->enable();
1106 rangeproject->disable();
1107 rangeselection->disable();
1108 rangeinout->disable();
1109 range1frame->disable();
1114 RenderRangeProject::RenderRangeProject(RenderWindow *rwindow, int value, int x, int y)
1115 : BC_Radial(x, y, value, _("Project"))
1117 this->rwindow = rwindow;
1119 int RenderRangeProject::handle_event()
1121 rwindow->update_range_type(RANGE_PROJECT);
1125 RenderRangeSelection::RenderRangeSelection(RenderWindow *rwindow, int value, int x, int y)
1126 : BC_Radial(x, y, value, _("Selection"))
1128 this->rwindow = rwindow;
1130 int RenderRangeSelection::handle_event()
1132 rwindow->update_range_type(RANGE_SELECTION);
1137 RenderRangeInOut::RenderRangeInOut(RenderWindow *rwindow, int value, int x, int y)
1138 : BC_Radial(x, y, value, _("In/Out Points"))
1140 this->rwindow = rwindow;
1142 int RenderRangeInOut::handle_event()
1144 rwindow->update_range_type(RANGE_INOUT);
1148 RenderRange1Frame::RenderRange1Frame(RenderWindow *rwindow, int value, int x, int y)
1149 : BC_Radial(x, y, value, _("One Frame"))
1151 this->rwindow = rwindow;
1153 int RenderRange1Frame::handle_event()
1155 rwindow->update_range_type(RANGE_1FRAME);
1159 double Render::get_render_range()
1161 EDL *edl = mwindow->edl;
1162 double last = edl->tracks->total_playable_length();
1163 double framerate = edl->session->frame_rate;
1164 if( framerate <= 0 ) framerate = 1;
1165 double start = 0, end = last;
1166 switch( range_type ) {
1168 case RANGE_BACKCOMPAT:
1169 start = edl->local_session->get_selectionstart(1);
1170 end = edl->local_session->get_selectionend(1);
1171 if( EQUIV(start, end) ) end = last;
1175 case RANGE_SELECTION:
1176 start = edl->local_session->get_selectionstart(1);
1177 end = edl->local_session->get_selectionend(1);
1180 start = edl->local_session->inpoint_valid() ?
1181 edl->local_session->get_inpoint() : 0;
1182 end = edl->local_session->outpoint_valid() ?
1183 edl->local_session->get_outpoint() : last;
1186 start = end = edl->local_session->get_selectionstart(1);
1187 if( edl->session->frame_rate > 0 ) end += 1./edl->session->frame_rate;
1190 if( start < 0 ) start = 0;
1191 if( end > last ) end = last;
1195 RenderFormat::RenderFormat(MWindow *mwindow, BC_WindowBase *window, Asset *asset)
1196 : FormatTools(mwindow, window, asset)
1199 RenderFormat::~RenderFormat()
1203 void RenderFormat::update_format()
1205 FormatTools::update_format();
1206 RenderWindow *render_window = (RenderWindow *)window;
1207 if( render_window->is_hidden() ) return;
1208 int is_image = File::is_image_render(asset->format);
1210 render_window->update_range_type(RANGE_1FRAME);
1211 render_window->enable_render_range(0);
1214 render_window->enable_render_range(1);
1216 int RenderFormat::handle_event()
1218 RenderWindow *render_window = (RenderWindow *)window;
1219 render_window->file_format->update(
1220 (render_window->render->use_labels ?
1221 _("Select the first file to render to:") :
1222 _("Select a file to render to:")));
1226 RenderBeepOnDone::RenderBeepOnDone(RenderWindow *rwindow, int x, int y)
1227 : BC_FPot(x, y, rwindow->render->beep*100.f, 0.f, 100.f)
1229 this->rwindow = rwindow;
1232 int RenderBeepOnDone::handle_event()
1234 rwindow->render->beep = get_value()/100.f;