/* * CINELERRA * Copyright (C) 2008 Adam Williams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "bcdisplayinfo.h" #include "bchash.h" #include "filexml.h" #include "language.h" #include "pluginaclient.h" #include "samples.h" #include "theme.h" #include class OverlayAudioWindow; class OverlayAudio; #define AUDIO_TRANSFER_TYPES 2 class OverlayAudioConfig { public: OverlayAudioConfig(); int equivalent(OverlayAudioConfig &that); void copy_from(OverlayAudioConfig &that); void interpolate(OverlayAudioConfig &prev, OverlayAudioConfig &next, int64_t prev_frame, int64_t next_frame, int64_t current_frame); static const char* output_to_text(int output_layer); static const char* mode_to_text(int mode); int output_track; enum { TOP, BOTTOM }; int mode; enum { ADD, MULTIPLY }; }; class OutputTrack : public BC_PopupMenu { public: OutputTrack(OverlayAudio *plugin, int x, int y); void create_objects(); int handle_event(); OverlayAudio *plugin; }; class OverlayMode : public BC_PopupMenu { public: OverlayMode(OverlayAudio *plugin, int x, int y); void create_objects(); int handle_event(); OverlayAudio *plugin; }; class OverlayAudioWindow : public PluginClientWindow { public: OverlayAudioWindow(OverlayAudio *plugin); void create_objects(); OverlayAudio *plugin; OutputTrack *output; OverlayMode *mode; }; class OverlayAudio : public PluginAClient { public: OverlayAudio(PluginServer *server); ~OverlayAudio(); int is_multichannel(); int is_realtime(); void read_data(KeyFrame *keyframe); void save_data(KeyFrame *keyframe); int process_buffer(int64_t size, Samples **buffer, int64_t start_position, int sample_rate); void update_gui(); PLUGIN_CLASS_MEMBERS2(OverlayAudioConfig) }; OverlayAudioConfig::OverlayAudioConfig() { output_track = OverlayAudioConfig::TOP; mode = OverlayAudioConfig::ADD; } int OverlayAudioConfig::equivalent(OverlayAudioConfig &that) { return that.output_track == output_track && that.mode == mode; } void OverlayAudioConfig::copy_from(OverlayAudioConfig &that) { output_track = that.output_track; mode = that.mode; } void OverlayAudioConfig::interpolate(OverlayAudioConfig &prev, OverlayAudioConfig &next, int64_t prev_frame, int64_t next_frame, int64_t current_frame) { output_track = prev.output_track; mode = prev.mode; } const char* OverlayAudioConfig::output_to_text(int output_layer) { switch(output_layer) { case OverlayAudioConfig::TOP: return _("Top"); case OverlayAudioConfig::BOTTOM: return _("Bottom"); } return ""; } const char* OverlayAudioConfig::mode_to_text(int mode) { switch(mode) { case OverlayAudioConfig::ADD: return _("Add"); case OverlayAudioConfig::MULTIPLY: return _("Multiply"); } return ""; } OverlayAudioWindow::OverlayAudioWindow(OverlayAudio *plugin) : PluginClientWindow(plugin, xS(300), yS(70), xS(300), yS(70), 0) { this->plugin = plugin; } void OverlayAudioWindow::create_objects() { int x = xS(10), y = yS(10); int x1 = x; BC_Title *title; add_subwindow(title = new BC_Title(x, y, _("Output track:"))); x += title->get_w() + plugin->get_theme()->widget_border; add_subwindow(output = new OutputTrack(plugin, x, y)); output->create_objects(); y += output->get_h() + plugin->get_theme()->widget_border; x = x1; add_subwindow(title = new BC_Title(x, y, _("Mode:"))); x += title->get_w() + plugin->get_theme()->widget_border; add_subwindow(mode = new OverlayMode(plugin, x, y)); mode->create_objects(); show_window(); } OutputTrack::OutputTrack(OverlayAudio *plugin, int x , int y) : BC_PopupMenu(x, y, xS(100), OverlayAudioConfig::output_to_text(plugin->config.output_track), 1) { this->plugin = plugin; } void OutputTrack::create_objects() { add_item(new BC_MenuItem( OverlayAudioConfig::output_to_text( OverlayAudioConfig::TOP))); add_item(new BC_MenuItem( OverlayAudioConfig::output_to_text( OverlayAudioConfig::BOTTOM))); } int OutputTrack::handle_event() { char *text = get_text(); if(!strcmp(text, OverlayAudioConfig::output_to_text( OverlayAudioConfig::TOP))) plugin->config.output_track = OverlayAudioConfig::TOP; else if(!strcmp(text, OverlayAudioConfig::output_to_text( OverlayAudioConfig::BOTTOM))) plugin->config.output_track = OverlayAudioConfig::BOTTOM; plugin->send_configure_change(); return 1; } OverlayMode::OverlayMode(OverlayAudio *plugin, int x, int y) : BC_PopupMenu(x, y, xS(150), OverlayAudioConfig::mode_to_text(plugin->config.mode), 1) { this->plugin = plugin; } void OverlayMode::create_objects() { for(int i = 0; i < AUDIO_TRANSFER_TYPES; i++) add_item(new BC_MenuItem(OverlayAudioConfig::mode_to_text(i))); } int OverlayMode::handle_event() { char *text = get_text(); for(int i = 0; i < AUDIO_TRANSFER_TYPES; i++) { if(!strcmp(text, OverlayAudioConfig::mode_to_text(i))) { plugin->config.mode = i; break; } } plugin->send_configure_change(); return 1; } REGISTER_PLUGIN(OverlayAudio) OverlayAudio::OverlayAudio(PluginServer *server) : PluginAClient(server) { } OverlayAudio::~OverlayAudio() { } const char* OverlayAudio::plugin_title() { return N_("Overlay"); } int OverlayAudio::is_realtime() { return 1; } int OverlayAudio::is_multichannel() { return 1; } void OverlayAudio::read_data(KeyFrame *keyframe) { FileXML input; input.set_shared_input(keyframe->xbuf); int result = 0; while(!result) { result = input.read_tag(); if(!result) { if(input.tag.title_is("OVERLAY")) { config.output_track = input.tag.get_property("OUTPUT", config.output_track); config.mode = input.tag.get_property("MODE", config.mode); } } } } void OverlayAudio::save_data(KeyFrame *keyframe) { FileXML output; output.set_shared_output(keyframe->xbuf); output.tag.set_title("OVERLAY"); output.tag.set_property("OUTPUT", config.output_track); output.tag.set_property("MODE", config.mode); output.append_tag(); output.tag.set_title("/OVERLAY"); output.append_tag(); output.append_newline(); output.terminate_string(); } void OverlayAudio::update_gui() { if(thread) { if(load_configuration()) { thread->window->lock_window("OverlayAudio::update_gui"); ((OverlayAudioWindow*)thread->window)->output->set_text( OverlayAudioConfig::output_to_text(config.output_track)); ((OverlayAudioWindow*)thread->window)->mode->set_text( OverlayAudioConfig::mode_to_text(config.mode)); thread->window->unlock_window(); } } } NEW_WINDOW_MACRO(OverlayAudio, OverlayAudioWindow) LOAD_CONFIGURATION_MACRO(OverlayAudio, OverlayAudioConfig) int OverlayAudio::process_buffer(int64_t size, Samples **buffer, int64_t start_position, int sample_rate) { load_configuration(); int output_track = 0; if(config.output_track == OverlayAudioConfig::BOTTOM) output_track = get_total_buffers() - 1; // Direct copy the output track read_samples(buffer[output_track], output_track, sample_rate, start_position, size); // Add remaining tracks Samples *output_buffer = buffer[output_track]; double *output_samples = output_buffer->get_data(); for(int i = 0; i < get_total_buffers(); i++) { if(i != output_track) { Samples *input_buffer = buffer[i]; read_samples(buffer[i], i, sample_rate, start_position, size); double *input_samples = input_buffer->get_data(); switch(config.mode) { case OverlayAudioConfig::ADD: for(int j = 0; j < size; j++) { output_samples[j] += input_samples[j]; } break; case OverlayAudioConfig::MULTIPLY: for(int j = 0; j < size; j++) { output_samples[j] *= input_samples[j]; } break; } } } return 0; }