4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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
22 #include "bcdisplayinfo.h"
27 #include "pluginaclient.h"
29 #include "transportque.h"
35 class ReverseAudioConfig
43 class ReverseAudioEnabled : public BC_CheckBox
46 ReverseAudioEnabled(ReverseAudio *plugin,
53 class ReverseAudioWindow : public PluginClientWindow
56 ReverseAudioWindow(ReverseAudio *plugin);
57 ~ReverseAudioWindow();
58 void create_objects();
61 ReverseAudioEnabled *enabled;
66 class ReverseAudio : public PluginAClient
69 ReverseAudio(PluginServer *server);
72 PLUGIN_CLASS_MEMBERS(ReverseAudioConfig)
74 void save_data(KeyFrame *keyframe);
75 void read_data(KeyFrame *keyframe);
78 int process_buffer(int64_t size,
80 int64_t start_position,
83 int64_t input_position;
93 REGISTER_PLUGIN(ReverseAudio);
97 ReverseAudioConfig::ReverseAudioConfig()
106 ReverseAudioWindow::ReverseAudioWindow(ReverseAudio *plugin)
107 : PluginClientWindow(plugin,
114 this->plugin = plugin;
117 ReverseAudioWindow::~ReverseAudioWindow()
121 void ReverseAudioWindow::create_objects()
125 add_subwindow(enabled = new ReverseAudioEnabled(plugin,
137 ReverseAudioEnabled::ReverseAudioEnabled(ReverseAudio *plugin,
142 plugin->config.enabled,
145 this->plugin = plugin;
148 int ReverseAudioEnabled::handle_event()
150 plugin->config.enabled = get_value();
151 plugin->send_configure_change();
163 ReverseAudio::ReverseAudio(PluginServer *server)
164 : PluginAClient(server)
170 ReverseAudio::~ReverseAudio()
175 const char* ReverseAudio::plugin_title() { return _("Reverse audio"); }
176 int ReverseAudio::is_realtime() { return 1; }
179 NEW_WINDOW_MACRO(ReverseAudio, ReverseAudioWindow)
182 int ReverseAudio::process_buffer(int64_t size,
184 int64_t start_position,
187 for(int i = 0; i < size; i += fragment_size)
189 fragment_size = size - i;
190 load_configuration();
193 int offset = buffer->get_offset();
194 buffer->set_offset(offset + i);
200 buffer->set_offset(offset);
201 double *buffer_samples = buffer->get_data();
203 for(int start = i, end = i + fragment_size - 1;
207 double temp = buffer_samples[start];
208 buffer_samples[start] = buffer_samples[end];
209 buffer_samples[end] = temp;
214 int offset = buffer->get_offset();
215 buffer->set_offset(offset + i);
221 buffer->set_offset(offset);
224 if(get_direction() == PLAY_FORWARD)
225 start_position += fragment_size;
227 start_position -= fragment_size;
237 int ReverseAudio::load_configuration()
239 KeyFrame *prev_keyframe, *next_keyframe;
240 next_keyframe = get_next_keyframe(get_source_position());
241 prev_keyframe = get_prev_keyframe(get_source_position());
242 read_data(next_keyframe);
243 // Previous keyframe stays in config object.
244 read_data(prev_keyframe);
246 int64_t prev_position = edl_to_local(prev_keyframe->position);
247 int64_t next_position = edl_to_local(next_keyframe->position);
249 // printf("ReverseAudio::load_configuration 1 %lld %lld %lld %lld\n",
252 // prev_keyframe->position,
253 // next_keyframe->position);
254 // Defeat default keyframe
255 if(prev_position == 0 && next_position == 0)
257 next_position = prev_position = get_source_start();
260 // Get range to flip in requested rate
261 int64_t range_start = prev_position;
262 int64_t range_end = next_position;
264 // Between keyframe and edge of range or no keyframes
265 if(range_start == range_end)
267 // Between first keyframe and start of effect
268 if(get_source_position() >= get_source_start() &&
269 get_source_position() < range_start)
271 range_start = get_source_start();
274 // Between last keyframe and end of effect
275 if(get_source_position() >= range_start &&
276 get_source_position() < get_source_start() + get_total_len())
278 range_end = get_source_start() + get_total_len();
282 // Should never get here
287 // Convert start position to new direction
288 if(get_direction() == PLAY_FORWARD)
290 // Truncate next buffer to keyframe
291 if(range_end - get_source_position() < fragment_size)
292 fragment_size = range_end - get_source_position();
293 input_position = get_source_position() - range_start;
294 input_position = range_end - input_position - fragment_size;
298 if(get_source_position() - range_start < fragment_size)
299 fragment_size = get_source_position() - range_start;
300 input_position = range_end - get_source_position();
301 input_position = range_start + input_position + fragment_size;
303 // printf("ReverseAudio::load_configuration 20 start=%lld end=%lld current=%lld input=%lld\n",
306 // get_source_position(),
313 void ReverseAudio::save_data(KeyFrame *keyframe)
317 // cause data to be stored directly in text
318 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
319 output.tag.set_title("REVERSEAUDIO");
320 output.tag.set_property("ENABLED", config.enabled);
322 output.terminate_string();
325 void ReverseAudio::read_data(KeyFrame *keyframe)
329 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
331 while(!input.read_tag())
333 if(input.tag.title_is("REVERSEAUDIO"))
335 config.enabled = input.tag.get_property("ENABLED", config.enabled);
340 void ReverseAudio::update_gui()
344 load_configuration();
345 thread->window->lock_window();
346 ((ReverseAudioWindow*)thread->window)->enabled->update(config.enabled);
347 thread->window->unlock_window();