int PluginArray::start_plugins(MWindow *mwindow, EDL *edl, PluginServer *plugin_server, KeyFrame *keyframe, int64_t start, int64_t end, File *file) { this->mwindow = mwindow; this->edl = edl; this->plugin_server = plugin_server; this->keyframe = keyframe; this->start = start; this->end = end; this->file = file; cache = new CICache(mwindow->preferences); buffer_size = get_bufsize(); get_recordable_tracks(); create_modules(); create_buffers(); if(!plugin_server->realtime) { PluginServer *plugin; int i; if(!plugin_server->multichannel) { // ============================ single channel plugins // start 1 plugin for each track for(i = 0; i < total_tracks(); i++) { append(plugin = new PluginServer(*plugin_server)); plugin->set_mwindow(mwindow); plugin->set_keyframe(keyframe); plugin->append_module(modules[i]); plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0); if(i == 0) plugin->set_interactive(); plugin->start_loop(start, end, buffer_size, 1); } } else { // ============================ multichannel // start 1 plugin for all tracks append(plugin = new PluginServer(*plugin_server)); plugin->set_mwindow(mwindow); plugin->set_keyframe(keyframe); for(i = 0; i < total_tracks(); i++) plugin->append_module(modules[i]); plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0); // set one plugin for progress bars plugin->set_interactive(); plugin->start_loop(start, end, buffer_size, total_tracks()); } //printf("PluginArray::start_plugins 5\n"); } else { PluginServer *plugin; int i; if(!plugin_server->multichannel) { // single channel plugins // start 1 plugin for each track for(i = 0; i < total_tracks(); i++) { append(plugin = new PluginServer(*plugin_server)); plugin->set_mwindow(mwindow); plugin->set_keyframe(keyframe); plugin->append_module(modules[i]); plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0); plugin->get_parameters(start, end, 1); plugin->init_realtime(0, 1, get_bufsize()); } } else { // multichannel // start 1 plugin for all tracks append(plugin = new PluginServer(*plugin_server)); plugin->set_mwindow(mwindow); plugin->set_keyframe(keyframe); for(i = 0; i < total_tracks(); i++) plugin->append_module(modules[i]); plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0); plugin->get_parameters(start, end, total_tracks()); plugin->init_realtime(0, total_tracks(), get_bufsize()); } } //printf("PluginArray::start_plugins 8\n"); return 0; }
// for recent effect menu items and running new effects // prompts for an effect if title is blank void MenuEffectThread::run() { for(int i = 0; i < dead_plugins->size(); i++) { delete dead_plugins->get(i); } dead_plugins->remove_all(); // get stuff from main window ArrayList<PluginServer*> *plugindb = mwindow->plugindb; BC_Hash *defaults = mwindow->defaults; ArrayList<BC_ListBoxItem*> plugin_list; ArrayList<PluginServer*> local_plugindb; char string[1024]; int i; int result = 0; // Default configuration Asset *default_asset = new Asset; // Output ArrayList<Indexable*> assets; // check for recordable tracks if(!get_recordable_tracks(default_asset)) { sprintf(string, _("No recordable tracks specified.")); ErrorBox error(PROGRAM_NAME ": Error"); error.create_objects(string); error.run_window(); default_asset->Garbage::remove_user(); return; } // check for plugins if(!plugindb->total) { sprintf(string, _("No plugins available.")); ErrorBox error(PROGRAM_NAME ": Error"); error.create_objects(string); error.run_window(); default_asset->Garbage::remove_user(); return; } // get default attributes for output file // used after completion get_derived_attributes(default_asset, defaults); // to_tracks = defaults->get("RENDER_EFFECT_TO_TRACKS", 1); load_mode = defaults->get("RENDER_EFFECT_LOADMODE", LOADMODE_PASTE); strategy = defaults->get("RENDER_EFFECT_STRATEGY", SINGLE_PASS); // get plugin information int need_plugin; if(!strlen(title)) need_plugin = 1; else need_plugin = 0; // generate a list of plugins for the window if(need_plugin) { mwindow->search_plugindb(default_asset->audio_data, default_asset->video_data, -1, 0, 0, local_plugindb); for(int i = 0; i < local_plugindb.total; i++) { plugin_list.append(new BC_ListBoxItem(_(local_plugindb.values[i]->title))); } } // find out which effect to run and get output file int plugin_number, format_error = 0; do { { MenuEffectWindow window(mwindow, this, need_plugin ? &plugin_list : 0, default_asset); window.create_objects(); result = window.run_window(); plugin_number = window.result; } if(!result) { FormatCheck format_check(default_asset); format_error = format_check.check_format(); } }while(format_error && !result); // save defaults save_derived_attributes(default_asset, defaults); defaults->update("RENDER_EFFECT_LOADMODE", load_mode); defaults->update("RENDER_EFFECT_STRATEGY", strategy); mwindow->save_defaults(); // get plugin server to use and delete the plugin list PluginServer *plugin_server = 0; PluginServer *plugin = 0; if(need_plugin) { plugin_list.remove_all_objects(); if(plugin_number > -1) { plugin_server = local_plugindb.values[plugin_number]; strcpy(title, plugin_server->title); } } else { for(int i = 0; i < plugindb->total && !plugin_server; i++) { if(!strcmp(plugindb->values[i]->title, title)) { plugin_server = plugindb->values[i]; plugin_number = i; } } } // Update the most recently used effects and copy the plugin server. if(plugin_server) { plugin = new PluginServer(*plugin_server); fix_menu(title); } if(!result && !strlen(default_asset->path)) { result = 1; // no output path given ErrorBox error(PROGRAM_NAME ": Error"); error.create_objects(_("No output file specified.")); error.run_window(); } if(!result && plugin_number < 0) { result = 1; // no output path given ErrorBox error(PROGRAM_NAME ": Error"); error.create_objects(_("No effect selected.")); error.run_window(); } // Configuration for realtime plugins. KeyFrame plugin_data; // get selection to render // Range double total_start, total_end; total_start = mwindow->edl->local_session->get_selectionstart(); if(mwindow->edl->local_session->get_selectionend() == mwindow->edl->local_session->get_selectionstart()) total_end = mwindow->edl->tracks->total_playable_length(); else total_end = mwindow->edl->local_session->get_selectionend(); // get native units for range total_start = to_units(total_start, 0); total_end = to_units(total_end, 1); // Trick boundaries in case of a non-realtime synthesis plugin if(plugin && !plugin->realtime && total_end == total_start) total_end = total_start + 1; // Units are now in the track's units. int64_t total_length = (int64_t)total_end - (int64_t)total_start; // length of output file int64_t output_start, output_end; if(!result && total_length <= 0) { result = 1; // no output path given ErrorBox error(PROGRAM_NAME ": Error"); error.create_objects(_("No selected range to process.")); error.run_window(); } // ========================= get keyframe from user if(!result) { // ========================= realtime plugin // no get_parameters if(plugin->realtime) { // Open a prompt GUI MenuEffectPrompt prompt(mwindow); prompt.create_objects(); char title[BCTEXTLEN]; sprintf(title, PROGRAM_NAME ": %s", plugin->title); // Open the plugin GUI plugin->set_mwindow(mwindow); plugin->set_keyframe(&plugin_data); plugin->set_prompt(&prompt); plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0, -1); // Must set parameters since there is no plugin object to draw from. plugin->get_parameters((int64_t)total_start, (int64_t)total_end, 1); plugin->show_gui(); // wait for user input result = prompt.run_window(); // Close plugin. plugin->save_data(&plugin_data); plugin->hide_gui(); // Can't delete here. dead_plugins->append(plugin); default_asset->sample_rate = mwindow->edl->session->sample_rate; default_asset->frame_rate = mwindow->edl->session->frame_rate; realtime = 1; } else // ============================non realtime plugin { plugin->set_mwindow(mwindow); plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0, -1); result = plugin->get_parameters((int64_t)total_start, (int64_t)total_end, get_recordable_tracks(default_asset)); // some plugins can change the sample rate and the frame rate if(!result) { default_asset->sample_rate = plugin->get_samplerate(); default_asset->frame_rate = plugin->get_framerate(); } delete plugin; realtime = 0; } // Should take from first recordable track default_asset->width = mwindow->edl->session->output_w; default_asset->height = mwindow->edl->session->output_h; } // Process the total length in fragments ArrayList<MenuEffectPacket*> packets; if(!result) { Label *current_label = mwindow->edl->labels->first; mwindow->stop_brender(); int current_number; int number_start; int total_digits; Render::get_starting_number(default_asset->path, current_number, number_start, total_digits); // Construct all packets for single overwrite confirmation for(int64_t fragment_start = (int64_t)total_start, fragment_end; fragment_start < (int64_t)total_end; fragment_start = fragment_end) { // Get fragment end if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM) { while(current_label && to_units(current_label->position, 0) <= fragment_start) current_label = current_label->next; if(!current_label) fragment_end = (int64_t)total_end; else fragment_end = to_units(current_label->position, 0); } else { fragment_end = (int64_t)total_end; } // Get path char path[BCTEXTLEN]; if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM) Render::create_filename(path, default_asset->path, current_number, total_digits, number_start); else strcpy(path, default_asset->path); current_number++; MenuEffectPacket *packet = new MenuEffectPacket(path, fragment_start, fragment_end); packets.append(packet); } // Test existence of files ArrayList<char*> paths; for(int i = 0; i < packets.total; i++) { paths.append(packets.values[i]->path); } result = ConfirmSave::test_files(mwindow, &paths); paths.remove_all(); } for(int current_packet = 0; current_packet < packets.total && !result; current_packet++) { Asset *asset = new Asset(*default_asset); MenuEffectPacket *packet = packets.values[current_packet]; int64_t fragment_start = packet->start; int64_t fragment_end = packet->end; strcpy(asset->path, packet->path); assets.append(asset); File *file = new File; // Open the output file after getting the information because the sample rate // is needed here. if(!result) { // open output file in write mode file->set_processors(mwindow->preferences->processors); file->set_cache(mwindow->preferences->cache_size); if(file->open_file(mwindow->preferences, asset, 0, 1)) { // open failed sprintf(string, _("Couldn't open %s"), asset->path); ErrorBox error(PROGRAM_NAME ": Error"); error.create_objects(string); error.run_window(); result = 1; } else { mwindow->sighandler->push_file(file); IndexFile::delete_index(mwindow->preferences, asset); } } // run plugins if(!result) { // position file output_start = 0; PluginArray *plugin_array; plugin_array = create_plugin_array(); plugin_array->start_plugins(mwindow, mwindow->edl, plugin_server, &plugin_data, fragment_start, fragment_end, file); plugin_array->run_plugins(); plugin_array->stop_plugins(); mwindow->sighandler->pull_file(file); file->close_file(); asset->audio_length = file->asset->audio_length; asset->video_length = file->asset->video_length; delete plugin_array; } delete file; } packets.remove_all_objects(); // paste output to tracks if(!result && load_mode != LOADMODE_NOTHING) { mwindow->gui->lock_window("MenuEffectThread::run"); mwindow->undo->update_undo_before("", 0); if(load_mode == LOADMODE_PASTE) mwindow->clear(0); mwindow->load_assets(&assets, -1, load_mode, 0, 0, mwindow->edl->session->labels_follow_edits, mwindow->edl->session->plugins_follow_edits, mwindow->edl->session->autos_follow_edits); mwindow->save_backup(); mwindow->undo->update_undo_after(title, LOAD_ALL); mwindow->restart_brender(); mwindow->update_plugin_guis(); mwindow->gui->update(1, 2, 1, 1, 1, 1, 0); mwindow->sync_parameters(CHANGE_ALL); mwindow->gui->unlock_window(); mwindow->awindow->gui->lock_window("MenuEffectThread::run"); mwindow->awindow->gui->update_assets(); mwindow->awindow->gui->flush(); mwindow->awindow->gui->unlock_window(); } for(int i = 0; i < assets.total; i++) assets.values[i]->Garbage::remove_user(); assets.remove_all(); default_asset->Garbage::remove_user(); }