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_GC default_asset = Asset_GC(new Asset);
105 Assets_vector 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);
121 sprintf(string, _("No plugins available."));
122 ErrorBox error(PROGRAM_NAME ": Error");
123 error.create_objects(string);
129 // get default attributes for output file
130 // used after completion
131 get_derived_attributes(default_asset, defaults);
132 // to_tracks = defaults->get("RENDER_EFFECT_TO_TRACKS", 1);
133 load_mode = defaults->get("RENDER_EFFECT_LOADMODE", LOAD_PASTE);
134 strategy = defaults->get("RENDER_EFFECT_STRATEGY", SINGLE_PASS);
136 // get plugin information
143 // generate a list of plugins for the window
146 mwindow->create_plugindb(default_asset->audio_data,
147 default_asset->video_data,
153 for(int i = 0; i < local_plugindb.total; i++)
155 plugin_list.append(new BC_ListBoxItem(_(local_plugindb.values[i]->title)));
159 // find out which effect to run and get output file
160 int plugin_number, format_error = 0;
165 MenuEffectWindow window(mwindow,
167 need_plugin ? &plugin_list : 0,
169 window.create_objects();
170 result = window.run_window();
171 plugin_number = window.result;
176 FormatCheck format_check(default_asset);
177 format_error = format_check.check_format();
179 }while(format_error && !result);
182 save_derived_attributes(default_asset, defaults);
183 defaults->update("RENDER_EFFECT_LOADMODE", load_mode);
184 defaults->update("RENDER_EFFECT_STRATEGY", strategy);
185 mwindow->save_defaults();
187 // get plugin server to use and delete the plugin list
188 PluginServer *plugin_server = 0;
189 PluginServer *plugin = 0;
192 plugin_list.remove_all_objects();
193 if(plugin_number > -1)
195 plugin_server = local_plugindb.values[plugin_number];
196 strcpy(title, plugin_server->title);
201 for(int i = 0; i < plugindb->total && !plugin_server; i++)
203 if(!strcmp(plugindb->values[i]->title, title))
205 plugin_server = plugindb->values[i];
211 // Update the most recently used effects and copy the plugin server.
214 plugin = new PluginServer(*plugin_server);
218 if(!result && !strlen(default_asset->path))
220 result = 1; // no output path given
221 ErrorBox error(PROGRAM_NAME ": Error");
222 error.create_objects(_("No output file specified."));
226 if(!result && plugin_number < 0)
228 result = 1; // no output path given
229 ErrorBox error(PROGRAM_NAME ": Error");
230 error.create_objects(_("No effect selected."));
234 // Configuration for realtime plugins.
235 KeyFrame plugin_data;
237 // get selection to render
239 double total_start, total_end;
241 total_start = mwindow->edl->local_session->get_selectionstart();
244 if(mwindow->edl->local_session->get_selectionend() ==
245 mwindow->edl->local_session->get_selectionstart())
246 total_end = mwindow->edl->tracks->total_playable_length();
248 total_end = mwindow->edl->local_session->get_selectionend();
252 // get native units for range
253 total_start = to_units(total_start, 0);
254 total_end = to_units(total_end, 1);
258 // Trick boundaries in case of a non-realtime synthesis plugin
261 total_end == total_start) total_end = total_start + 1;
263 // Units are now in the track's units.
264 int64_t total_length = (int64_t)total_end - (int64_t)total_start;
265 // length of output file
266 int64_t output_start, output_end;
268 if(!result && total_length <= 0)
270 result = 1; // no output path given
271 ErrorBox error(PROGRAM_NAME ": Error");
272 error.create_objects(_("No selected range to process."));
276 // ========================= get keyframe from user
279 // ========================= realtime plugin
284 MenuEffectPrompt prompt(mwindow);
285 prompt.create_objects();
286 char title[BCTEXTLEN];
287 sprintf(title, PROGRAM_NAME ": %s", plugin->title);
289 // Open the plugin GUI
290 plugin->set_mwindow(mwindow);
291 plugin->set_keyframe(&plugin_data);
292 plugin->set_prompt(&prompt);
293 plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0, -1);
294 // Must set parameters since there is no plugin object to draw from.
295 plugin->get_parameters((int64_t)total_start,
300 // wait for user input
301 result = prompt.run_window();
304 plugin->save_data(&plugin_data);
306 default_asset->sample_rate = mwindow->edl->session->sample_rate;
307 default_asset->frame_rate = mwindow->edl->session->frame_rate;
311 // ============================non realtime plugin
313 plugin->set_mwindow(mwindow);
314 plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0, -1);
315 result = plugin->get_parameters((int64_t)total_start,
317 get_recordable_tracks(default_asset));
318 // some plugins can change the sample rate and the frame rate
323 default_asset->sample_rate = plugin->get_samplerate();
324 default_asset->frame_rate = plugin->get_framerate();
330 // Should take from first recordable track
331 default_asset->width = mwindow->edl->session->output_w;
332 default_asset->height = mwindow->edl->session->output_h;
335 // Process the total length in fragments
336 ArrayList<MenuEffectPacket*> packets;
339 Label *current_label = mwindow->edl->labels->first;
340 mwindow->stop_brender();
345 Render::get_starting_number(default_asset->path,
352 // Construct all packets for single overwrite confirmation
353 for(int64_t fragment_start = (int64_t)total_start, fragment_end;
354 fragment_start < (int64_t)total_end;
355 fragment_start = fragment_end)
358 if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM)
360 while(current_label &&
361 to_units(current_label->position, 0) <= fragment_start)
362 current_label = current_label->next;
364 fragment_end = (int64_t)total_end;
366 fragment_end = to_units(current_label->position, 0);
370 fragment_end = (int64_t)total_end;
374 char path[BCTEXTLEN];
375 if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM)
376 Render::create_filename(path,
382 strcpy(path, default_asset->path);
385 MenuEffectPacket *packet = new MenuEffectPacket(path,
388 packets.append(packet);
392 // Test existence of files
393 ArrayList<char*> paths;
394 for(int i = 0; i < packets.total; i++)
396 paths.append(packets.values[i]->path);
398 result = ConfirmSave::test_files(mwindow, &paths);
404 for(int current_packet = 0;
405 current_packet < packets.total && !result;
408 Asset_GC asset = Asset_GC(new Asset(*default_asset));
409 MenuEffectPacket *packet = packets.values[current_packet];
410 int64_t fragment_start = packet->start;
411 int64_t fragment_end = packet->end;
412 strcpy(asset->path, packet->path);
414 assets.push_back(asset);
415 File *file = new File;
417 // Open the output file after getting the information because the sample rate
421 // open output file in write mode
422 file->set_processors(mwindow->preferences->processors);
423 if(file->open_file(mwindow->preferences,
427 mwindow->edl->session->sample_rate,
428 mwindow->edl->session->frame_rate))
431 sprintf(string, _("Couldn't open %s"), asset->path);
432 ErrorBox error(PROGRAM_NAME ": Error");
433 error.create_objects(string);
439 mwindow->sighandler->push_file(file);
440 IndexFile::delete_index(mwindow->preferences, asset);
450 PluginArray *plugin_array;
451 plugin_array = create_plugin_array();
453 plugin_array->start_plugins(mwindow,
460 plugin_array->run_plugins();
462 plugin_array->stop_plugins();
463 mwindow->sighandler->pull_file(file);
465 asset->audio_length = file->asset->audio_length;
466 asset->video_length = file->asset->video_length;
473 packets.remove_all_objects();
475 // paste output to tracks
476 if(!result && load_mode != LOAD_NOTHING)
478 mwindow->gui->lock_window("MenuEffectThread::run");
480 if(load_mode == LOAD_PASTE)
482 mwindow->load_assets(assets,
487 mwindow->edl->session->labels_follow_edits,
488 mwindow->edl->session->plugins_follow_edits,
492 mwindow->save_backup();
493 mwindow->undo->update_undo(title, LOAD_ALL);
497 mwindow->restart_brender();
498 mwindow->update_plugin_guis();
499 mwindow->gui->update(1,
506 mwindow->sync_parameters(CHANGE_ALL);
507 mwindow->gui->unlock_window();
516 MenuEffectItem::MenuEffectItem(MenuEffects *menueffect, char *string)
517 : BC_MenuItem(string)
519 this->menueffect = menueffect;
521 int MenuEffectItem::handle_event()
523 menueffect->thread->set_title(get_text());
524 menueffect->thread->start();
538 MenuEffectWindow::MenuEffectWindow(MWindow *mwindow,
539 MenuEffectThread *menueffects,
540 ArrayList<BC_ListBoxItem*> *plugin_list,
542 : BC_Window(PROGRAM_NAME ": Render effect",
543 mwindow->gui->get_abs_cursor_x(1),
544 mwindow->gui->get_abs_cursor_y(1) - mwindow->session->menueffect_h / 2,
545 mwindow->session->menueffect_w,
546 mwindow->session->menueffect_h,
553 this->menueffects = menueffects;
554 this->plugin_list = plugin_list;
556 this->mwindow = mwindow;
559 MenuEffectWindow::~MenuEffectWindow()
566 int MenuEffectWindow::create_objects()
570 mwindow->theme->get_menueffect_sizes(plugin_list ? 1 : 0);
572 // only add the list if needed
575 add_subwindow(list_title = new BC_Title(mwindow->theme->menueffect_list_x,
576 mwindow->theme->menueffect_list_y,
577 _("Select an effect")));
578 add_subwindow(list = new MenuEffectWindowList(this,
579 mwindow->theme->menueffect_list_x,
580 mwindow->theme->menueffect_list_y + list_title->get_h() + 5,
581 mwindow->theme->menueffect_list_w,
582 mwindow->theme->menueffect_list_h - list_title->get_h() - 5,
586 add_subwindow(file_title = new BC_Title(mwindow->theme->menueffect_file_x,
587 mwindow->theme->menueffect_file_y,
588 (char*)((menueffects->strategy == FILE_PER_LABEL || menueffects->strategy == FILE_PER_LABEL_FARM) ?
589 _("Select the first file to render to:") :
590 _("Select a file to render to:"))));
592 x = mwindow->theme->menueffect_tools_x;
593 y = mwindow->theme->menueffect_tools_y;
594 format_tools = new FormatTools(mwindow,
597 format_tools->create_objects(x,
607 &menueffects->strategy,
610 loadmode = new LoadMode(mwindow,
614 &menueffects->load_mode,
616 loadmode->create_objects();
618 add_subwindow(new MenuEffectWindowOK(this));
619 add_subwindow(new MenuEffectWindowCancel(this));
625 int MenuEffectWindow::resize_event(int w, int h)
627 mwindow->session->menueffect_w = w;
628 mwindow->session->menueffect_h = h;
629 mwindow->theme->get_menueffect_sizes(plugin_list ? 1 : 0);
633 list_title->reposition_window(mwindow->theme->menueffect_list_x,
634 mwindow->theme->menueffect_list_y);
635 list->reposition_window(mwindow->theme->menueffect_list_x,
636 mwindow->theme->menueffect_list_y + list_title->get_h() + 5,
637 mwindow->theme->menueffect_list_w,
638 mwindow->theme->menueffect_list_h - list_title->get_h() - 5);
641 file_title->reposition_window(mwindow->theme->menueffect_file_x,
642 mwindow->theme->menueffect_file_y);
643 int x = mwindow->theme->menueffect_tools_x;
644 int y = mwindow->theme->menueffect_tools_y;
645 format_tools->reposition_window(x, y);
646 loadmode->reposition_window(x, y);
651 MenuEffectWindowOK::MenuEffectWindowOK(MenuEffectWindow *window)
652 : BC_OKButton(window)
654 this->window = window;
657 int MenuEffectWindowOK::handle_event()
659 if(window->plugin_list)
660 window->result = window->list->get_selection_number(0, 0);
665 int MenuEffectWindowOK::keypress_event()
667 if(get_keypress() == RETURN)
675 MenuEffectWindowCancel::MenuEffectWindowCancel(MenuEffectWindow *window)
676 : BC_CancelButton(window)
678 this->window = window;
681 int MenuEffectWindowCancel::handle_event()
686 int MenuEffectWindowCancel::keypress_event()
688 if(get_keypress() == ESC)
696 MenuEffectWindowList::MenuEffectWindowList(MenuEffectWindow *window,
701 ArrayList<BC_ListBoxItem*> *plugin_list)
709 this->window = window;
712 int MenuEffectWindowList::handle_event()
714 window->result = get_selection_number(0, 0);
718 #define PROMPT_TEXT _("Set up effect panel and hit \"OK\"")
720 MenuEffectPrompt::MenuEffectPrompt(MWindow *mwindow)
721 : BC_Window(PROGRAM_NAME ": Effect Prompt",
722 mwindow->gui->get_abs_cursor_x(1) - 260 / 2,
723 mwindow->gui->get_abs_cursor_y(1) - 300,
724 MenuEffectPrompt::calculate_w(mwindow->gui),
725 MenuEffectPrompt::calculate_h(mwindow->gui),
726 MenuEffectPrompt::calculate_w(mwindow->gui),
727 MenuEffectPrompt::calculate_h(mwindow->gui),
734 int MenuEffectPrompt::calculate_w(BC_WindowBase *gui)
736 int w = BC_Title::calculate_w(gui, PROMPT_TEXT) + 10;
737 w = MAX(w, BC_OKButton::calculate_w() + BC_CancelButton::calculate_w() + 30);
741 int MenuEffectPrompt::calculate_h(BC_WindowBase *gui)
743 int h = BC_Title::calculate_h(gui, PROMPT_TEXT);
744 h += BC_OKButton::calculate_h() + 30;
749 int MenuEffectPrompt::create_objects()
753 add_subwindow(title = new BC_Title(x, y, PROMPT_TEXT));
754 add_subwindow(new BC_OKButton(this));
755 add_subwindow(new BC_CancelButton(this));
765 // c-file-style: "linux"