3 #include "confirmsave.h"
6 #include "edlsession.h"
9 #include "formatcheck.h"
10 #include "indexfile.h"
16 #include "localsession.h"
18 #include "mainsession.h"
21 #include "mwindowgui.h"
22 #include "menueffects.h"
23 #include "playbackengine.h"
24 #include "pluginarray.h"
25 #include "pluginserver.h"
26 #include "preferences.h"
28 #include "sighandler.h"
34 MenuEffects::MenuEffects(MWindow *mwindow)
35 : BC_MenuItem(_("Render effect..."))
37 this->mwindow = mwindow;
40 MenuEffects::~MenuEffects()
45 int MenuEffects::handle_event()
47 thread->set_title("");
55 MenuEffectPacket::MenuEffectPacket(char *path, int64_t start, int64_t end)
59 strcpy(this->path, path);
62 MenuEffectPacket::~MenuEffectPacket()
71 MenuEffectThread::MenuEffectThread(MWindow *mwindow)
73 this->mwindow = mwindow;
77 MenuEffectThread::~MenuEffectThread()
85 int MenuEffectThread::set_title(char *title)
87 strcpy(this->title, title);
90 // for recent effect menu items and running new effects
91 // prompts for an effect if title is blank
92 void MenuEffectThread::run()
94 // get stuff from main window
95 ArrayList<PluginServer*> *plugindb = mwindow->plugindb;
96 BC_Hash *defaults = mwindow->defaults;
97 ArrayList<BC_ListBoxItem*> plugin_list;
98 ArrayList<PluginServer*> local_plugindb;
102 // Default configuration
103 Asset *default_asset = new Asset;
105 ArrayList<Asset*> assets;
108 // check for recordable tracks
109 if(!get_recordable_tracks(default_asset))
111 sprintf(string, _("No recordable tracks specified."));
112 ErrorBox error(PROGRAM_NAME ": Error");
113 error.create_objects(string);
115 Garbage::delete_object(default_asset);
122 sprintf(string, _("No plugins available."));
123 ErrorBox error(PROGRAM_NAME ": Error");
124 error.create_objects(string);
126 Garbage::delete_object(default_asset);
131 // get default attributes for output file
132 // used after completion
133 get_derived_attributes(default_asset, defaults);
134 // to_tracks = defaults->get("RENDER_EFFECT_TO_TRACKS", 1);
135 load_mode = defaults->get("RENDER_EFFECT_LOADMODE", LOAD_PASTE);
136 strategy = defaults->get("RENDER_EFFECT_STRATEGY", SINGLE_PASS);
138 // get plugin information
145 // generate a list of plugins for the window
148 mwindow->create_plugindb(default_asset->audio_data,
149 default_asset->video_data,
155 for(int i = 0; i < local_plugindb.total; i++)
157 plugin_list.append(new BC_ListBoxItem(_(local_plugindb.values[i]->title)));
161 // find out which effect to run and get output file
162 int plugin_number, format_error = 0;
167 MenuEffectWindow window(mwindow,
169 need_plugin ? &plugin_list : 0,
171 window.create_objects();
172 result = window.run_window();
173 plugin_number = window.result;
178 FormatCheck format_check(default_asset);
179 format_error = format_check.check_format();
181 }while(format_error && !result);
184 save_derived_attributes(default_asset, defaults);
185 defaults->update("RENDER_EFFECT_LOADMODE", load_mode);
186 defaults->update("RENDER_EFFECT_STRATEGY", strategy);
187 mwindow->save_defaults();
189 // get plugin server to use and delete the plugin list
190 PluginServer *plugin_server = 0;
191 PluginServer *plugin = 0;
194 plugin_list.remove_all_objects();
195 if(plugin_number > -1)
197 plugin_server = local_plugindb.values[plugin_number];
198 strcpy(title, plugin_server->title);
203 for(int i = 0; i < plugindb->total && !plugin_server; i++)
205 if(!strcmp(plugindb->values[i]->title, title))
207 plugin_server = plugindb->values[i];
213 // Update the most recently used effects and copy the plugin server.
216 plugin = new PluginServer(*plugin_server);
220 if(!result && !strlen(default_asset->path))
222 result = 1; // no output path given
223 ErrorBox error(PROGRAM_NAME ": Error");
224 error.create_objects(_("No output file specified."));
228 if(!result && plugin_number < 0)
230 result = 1; // no output path given
231 ErrorBox error(PROGRAM_NAME ": Error");
232 error.create_objects(_("No effect selected."));
236 // Configuration for realtime plugins.
237 KeyFrame plugin_data;
239 // get selection to render
241 double total_start, total_end;
243 total_start = mwindow->edl->local_session->get_selectionstart();
246 if(mwindow->edl->local_session->get_selectionend() ==
247 mwindow->edl->local_session->get_selectionstart())
248 total_end = mwindow->edl->tracks->total_playable_length();
250 total_end = mwindow->edl->local_session->get_selectionend();
254 // get native units for range
255 total_start = to_units(total_start, 0);
256 total_end = to_units(total_end, 1);
260 // Trick boundaries in case of a non-realtime synthesis plugin
263 total_end == total_start) total_end = total_start + 1;
265 // Units are now in the track's units.
266 int64_t total_length = (int64_t)total_end - (int64_t)total_start;
267 // length of output file
268 int64_t output_start, output_end;
270 if(!result && total_length <= 0)
272 result = 1; // no output path given
273 ErrorBox error(PROGRAM_NAME ": Error");
274 error.create_objects(_("No selected range to process."));
278 // ========================= get keyframe from user
281 // ========================= realtime plugin
286 MenuEffectPrompt prompt(mwindow);
287 prompt.create_objects();
288 char title[BCTEXTLEN];
289 sprintf(title, PROGRAM_NAME ": %s", plugin->title);
291 // Open the plugin GUI
292 plugin->set_mwindow(mwindow);
293 plugin->set_keyframe(&plugin_data);
294 plugin->set_prompt(&prompt);
295 plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0, -1);
296 // Must set parameters since there is no plugin object to draw from.
297 plugin->get_parameters((int64_t)total_start,
302 // wait for user input
303 result = prompt.run_window();
306 plugin->save_data(&plugin_data);
308 default_asset->sample_rate = mwindow->edl->session->sample_rate;
309 default_asset->frame_rate = mwindow->edl->session->frame_rate;
313 // ============================non realtime plugin
315 plugin->set_mwindow(mwindow);
316 plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0, -1);
317 result = plugin->get_parameters((int64_t)total_start,
319 get_recordable_tracks(default_asset));
320 // some plugins can change the sample rate and the frame rate
325 default_asset->sample_rate = plugin->get_samplerate();
326 default_asset->frame_rate = plugin->get_framerate();
332 // Should take from first recordable track
333 default_asset->width = mwindow->edl->session->output_w;
334 default_asset->height = mwindow->edl->session->output_h;
337 // Process the total length in fragments
338 ArrayList<MenuEffectPacket*> packets;
341 Label *current_label = mwindow->edl->labels->first;
342 mwindow->stop_brender();
347 Render::get_starting_number(default_asset->path,
354 // Construct all packets for single overwrite confirmation
355 for(int64_t fragment_start = (int64_t)total_start, fragment_end;
356 fragment_start < (int64_t)total_end;
357 fragment_start = fragment_end)
360 if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM)
362 while(current_label &&
363 to_units(current_label->position, 0) <= fragment_start)
364 current_label = current_label->next;
366 fragment_end = (int64_t)total_end;
368 fragment_end = to_units(current_label->position, 0);
372 fragment_end = (int64_t)total_end;
376 char path[BCTEXTLEN];
377 if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM)
378 Render::create_filename(path,
384 strcpy(path, default_asset->path);
387 MenuEffectPacket *packet = new MenuEffectPacket(path,
390 packets.append(packet);
394 // Test existence of files
395 ArrayList<char*> paths;
396 for(int i = 0; i < packets.total; i++)
398 paths.append(packets.values[i]->path);
400 result = ConfirmSave::test_files(mwindow, &paths);
406 for(int current_packet = 0;
407 current_packet < packets.total && !result;
410 Asset *asset = new Asset(*default_asset);
411 MenuEffectPacket *packet = packets.values[current_packet];
412 int64_t fragment_start = packet->start;
413 int64_t fragment_end = packet->end;
414 strcpy(asset->path, packet->path);
416 assets.append(asset);
417 File *file = new File;
419 // Open the output file after getting the information because the sample rate
423 // open output file in write mode
424 file->set_processors(mwindow->preferences->processors);
425 if(file->open_file(mwindow->preferences,
429 mwindow->edl->session->sample_rate,
430 mwindow->edl->session->frame_rate))
433 sprintf(string, _("Couldn't open %s"), asset->path);
434 ErrorBox error(PROGRAM_NAME ": Error");
435 error.create_objects(string);
441 mwindow->sighandler->push_file(file);
442 IndexFile::delete_index(mwindow->preferences, asset);
452 PluginArray *plugin_array;
453 plugin_array = create_plugin_array();
455 plugin_array->start_plugins(mwindow,
462 plugin_array->run_plugins();
464 plugin_array->stop_plugins();
465 mwindow->sighandler->pull_file(file);
467 asset->audio_length = file->asset->audio_length;
468 asset->video_length = file->asset->video_length;
475 packets.remove_all_objects();
477 // paste output to tracks
478 if(!result && load_mode != LOAD_NOTHING)
480 mwindow->gui->lock_window("MenuEffectThread::run");
482 if(load_mode == LOAD_PASTE)
484 mwindow->load_assets(&assets,
489 mwindow->edl->session->labels_follow_edits,
490 mwindow->edl->session->plugins_follow_edits,
494 mwindow->save_backup();
495 mwindow->undo->update_undo(title, LOAD_ALL);
499 mwindow->restart_brender();
500 mwindow->update_plugin_guis();
501 mwindow->gui->update(1,
508 mwindow->sync_parameters(CHANGE_ALL);
509 mwindow->gui->unlock_window();
512 for(int i = 0; i < assets.total; i++)
513 Garbage::delete_object(assets.values[i]);
515 Garbage::delete_object(default_asset);
521 MenuEffectItem::MenuEffectItem(MenuEffects *menueffect, char *string)
522 : BC_MenuItem(string)
524 this->menueffect = menueffect;
526 int MenuEffectItem::handle_event()
528 menueffect->thread->set_title(get_text());
529 menueffect->thread->start();
543 MenuEffectWindow::MenuEffectWindow(MWindow *mwindow,
544 MenuEffectThread *menueffects,
545 ArrayList<BC_ListBoxItem*> *plugin_list,
547 : BC_Window(PROGRAM_NAME ": Render effect",
548 mwindow->gui->get_abs_cursor_x(1),
549 mwindow->gui->get_abs_cursor_y(1) - mwindow->session->menueffect_h / 2,
550 mwindow->session->menueffect_w,
551 mwindow->session->menueffect_h,
558 this->menueffects = menueffects;
559 this->plugin_list = plugin_list;
561 this->mwindow = mwindow;
564 MenuEffectWindow::~MenuEffectWindow()
571 int MenuEffectWindow::create_objects()
575 mwindow->theme->get_menueffect_sizes(plugin_list ? 1 : 0);
577 // only add the list if needed
580 add_subwindow(list_title = new BC_Title(mwindow->theme->menueffect_list_x,
581 mwindow->theme->menueffect_list_y,
582 _("Select an effect")));
583 add_subwindow(list = new MenuEffectWindowList(this,
584 mwindow->theme->menueffect_list_x,
585 mwindow->theme->menueffect_list_y + list_title->get_h() + 5,
586 mwindow->theme->menueffect_list_w,
587 mwindow->theme->menueffect_list_h - list_title->get_h() - 5,
591 add_subwindow(file_title = new BC_Title(mwindow->theme->menueffect_file_x,
592 mwindow->theme->menueffect_file_y,
593 (char*)((menueffects->strategy == FILE_PER_LABEL || menueffects->strategy == FILE_PER_LABEL_FARM) ?
594 _("Select the first file to render to:") :
595 _("Select a file to render to:"))));
597 x = mwindow->theme->menueffect_tools_x;
598 y = mwindow->theme->menueffect_tools_y;
599 format_tools = new FormatTools(mwindow,
602 format_tools->create_objects(x,
612 &menueffects->strategy,
615 loadmode = new LoadMode(mwindow,
619 &menueffects->load_mode,
621 loadmode->create_objects();
623 add_subwindow(new MenuEffectWindowOK(this));
624 add_subwindow(new MenuEffectWindowCancel(this));
630 int MenuEffectWindow::resize_event(int w, int h)
632 mwindow->session->menueffect_w = w;
633 mwindow->session->menueffect_h = h;
634 mwindow->theme->get_menueffect_sizes(plugin_list ? 1 : 0);
638 list_title->reposition_window(mwindow->theme->menueffect_list_x,
639 mwindow->theme->menueffect_list_y);
640 list->reposition_window(mwindow->theme->menueffect_list_x,
641 mwindow->theme->menueffect_list_y + list_title->get_h() + 5,
642 mwindow->theme->menueffect_list_w,
643 mwindow->theme->menueffect_list_h - list_title->get_h() - 5);
646 file_title->reposition_window(mwindow->theme->menueffect_file_x,
647 mwindow->theme->menueffect_file_y);
648 int x = mwindow->theme->menueffect_tools_x;
649 int y = mwindow->theme->menueffect_tools_y;
650 format_tools->reposition_window(x, y);
651 loadmode->reposition_window(x, y);
656 MenuEffectWindowOK::MenuEffectWindowOK(MenuEffectWindow *window)
657 : BC_OKButton(window)
659 this->window = window;
662 int MenuEffectWindowOK::handle_event()
664 if(window->plugin_list)
665 window->result = window->list->get_selection_number(0, 0);
670 int MenuEffectWindowOK::keypress_event()
672 if(get_keypress() == RETURN)
680 MenuEffectWindowCancel::MenuEffectWindowCancel(MenuEffectWindow *window)
681 : BC_CancelButton(window)
683 this->window = window;
686 int MenuEffectWindowCancel::handle_event()
691 int MenuEffectWindowCancel::keypress_event()
693 if(get_keypress() == ESC)
701 MenuEffectWindowList::MenuEffectWindowList(MenuEffectWindow *window,
706 ArrayList<BC_ListBoxItem*> *plugin_list)
714 this->window = window;
717 int MenuEffectWindowList::handle_event()
719 window->result = get_selection_number(0, 0);
723 #define PROMPT_TEXT _("Set up effect panel and hit \"OK\"")
725 MenuEffectPrompt::MenuEffectPrompt(MWindow *mwindow)
726 : BC_Window(PROGRAM_NAME ": Effect Prompt",
727 mwindow->gui->get_abs_cursor_x(1) - 260 / 2,
728 mwindow->gui->get_abs_cursor_y(1) - 300,
729 MenuEffectPrompt::calculate_w(mwindow->gui),
730 MenuEffectPrompt::calculate_h(mwindow->gui),
731 MenuEffectPrompt::calculate_w(mwindow->gui),
732 MenuEffectPrompt::calculate_h(mwindow->gui),
739 int MenuEffectPrompt::calculate_w(BC_WindowBase *gui)
741 int w = BC_Title::calculate_w(gui, PROMPT_TEXT) + 10;
742 w = MAX(w, BC_OKButton::calculate_w() + BC_CancelButton::calculate_w() + 30);
746 int MenuEffectPrompt::calculate_h(BC_WindowBase *gui)
748 int h = BC_Title::calculate_h(gui, PROMPT_TEXT);
749 h += BC_OKButton::calculate_h() + 30;
754 int MenuEffectPrompt::create_objects()
758 add_subwindow(title = new BC_Title(x, y, PROMPT_TEXT));
759 add_subwindow(new BC_OKButton(this));
760 add_subwindow(new BC_CancelButton(this));