update internationalization data
[goodguy/history.git] / cinelerra-5.0 / plugins / reverseaudio / reverseaudio.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
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.
10  * 
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.
15  * 
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
19  * 
20  */
21
22 #include "bcdisplayinfo.h"
23 #include "bchash.h"
24 #include "filexml.h"
25 #include "guicast.h"
26 #include "language.h"
27 #include "pluginaclient.h"
28 #include "samples.h"
29 #include "transportque.h"
30
31 #include <string.h>
32
33 class ReverseAudio;
34
35 class ReverseAudioConfig
36 {
37 public:
38         ReverseAudioConfig();
39         int enabled;
40 };
41
42
43 class ReverseAudioEnabled : public BC_CheckBox
44 {
45 public:
46         ReverseAudioEnabled(ReverseAudio *plugin,
47                 int x,
48                 int y);
49         int handle_event();
50         ReverseAudio *plugin;
51 };
52
53 class ReverseAudioWindow : public PluginClientWindow
54 {
55 public:
56         ReverseAudioWindow(ReverseAudio *plugin);
57         ~ReverseAudioWindow();
58         void create_objects();
59
60         ReverseAudio *plugin;
61         ReverseAudioEnabled *enabled;
62 };
63
64
65
66 class ReverseAudio : public PluginAClient
67 {
68 public:
69         ReverseAudio(PluginServer *server);
70         ~ReverseAudio();
71
72         PLUGIN_CLASS_MEMBERS(ReverseAudioConfig)
73
74         void save_data(KeyFrame *keyframe);
75         void read_data(KeyFrame *keyframe);
76         void update_gui();
77         int is_realtime();
78         int process_buffer(int64_t size, 
79                 Samples *buffer,
80                 int64_t start_position,
81                 int sample_rate);
82
83         int64_t input_position;
84         int fragment_size;
85 };
86
87
88
89
90
91
92
93 REGISTER_PLUGIN(ReverseAudio);
94
95
96
97 ReverseAudioConfig::ReverseAudioConfig()
98 {
99         enabled = 1;
100 }
101
102
103
104
105
106 ReverseAudioWindow::ReverseAudioWindow(ReverseAudio *plugin)
107  : PluginClientWindow(plugin, 
108         210, 
109         160, 
110         200, 
111         160, 
112         0)
113 {
114         this->plugin = plugin;
115 }
116
117 ReverseAudioWindow::~ReverseAudioWindow()
118 {
119 }
120
121 void ReverseAudioWindow::create_objects()
122 {
123         int x = 10, y = 10;
124
125         add_subwindow(enabled = new ReverseAudioEnabled(plugin, 
126                 x, 
127                 y));
128         show_window();
129         flush();
130 }
131
132
133
134
135
136
137 ReverseAudioEnabled::ReverseAudioEnabled(ReverseAudio *plugin, 
138         int x, 
139         int y)
140  : BC_CheckBox(x, 
141         y, 
142         plugin->config.enabled,
143         _("Enabled"))
144 {
145         this->plugin = plugin;
146 }
147
148 int ReverseAudioEnabled::handle_event()
149 {
150         plugin->config.enabled = get_value();
151         plugin->send_configure_change();
152         return 1;
153 }
154
155
156
157
158
159
160
161
162
163 ReverseAudio::ReverseAudio(PluginServer *server)
164  : PluginAClient(server)
165 {
166         
167 }
168
169
170 ReverseAudio::~ReverseAudio()
171 {
172         
173 }
174
175 const char* ReverseAudio::plugin_title() { return _("Reverse audio"); }
176 int ReverseAudio::is_realtime() { return 1; }
177
178
179 NEW_WINDOW_MACRO(ReverseAudio, ReverseAudioWindow)
180
181
182 int ReverseAudio::process_buffer(int64_t size, 
183         Samples *buffer,
184         int64_t start_position,
185         int sample_rate)
186 {
187         for(int i = 0; i < size; i += fragment_size)
188         {
189                 fragment_size = size - i;
190                 load_configuration();
191                 if(config.enabled)
192                 {
193                         int offset = buffer->get_offset();
194                         buffer->set_offset(offset + i);
195                         read_samples(buffer,
196                                 0,
197                                 sample_rate,
198                                 input_position,
199                                 fragment_size);
200                         buffer->set_offset(offset);
201                         double *buffer_samples = buffer->get_data();
202
203                         for(int start = i, end = i + fragment_size - 1;
204                                 end > start; 
205                                 start++, end--)
206                         {
207                                 double temp = buffer_samples[start];
208                                 buffer_samples[start] = buffer_samples[end];
209                                 buffer_samples[end] = temp;
210                         }
211                 }
212                 else
213                 {
214                         int offset = buffer->get_offset();
215                         buffer->set_offset(offset + i);
216                         read_samples(buffer,
217                                 0,
218                                 sample_rate,
219                                 start_position,
220                                 fragment_size);
221                         buffer->set_offset(offset);
222                 }
223
224                 if(get_direction() == PLAY_FORWARD)
225                         start_position += fragment_size;
226                 else
227                         start_position -= fragment_size;
228         }
229         
230
231         return 0;
232 }
233
234
235
236
237 int ReverseAudio::load_configuration()
238 {
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);
245
246         int64_t prev_position = edl_to_local(prev_keyframe->position);
247         int64_t next_position = edl_to_local(next_keyframe->position);
248
249 // printf("ReverseAudio::load_configuration 1 %lld %lld %lld %lld\n", 
250 // prev_position,
251 // next_position,
252 // prev_keyframe->position, 
253 // next_keyframe->position);
254 // Defeat default keyframe
255         if(prev_position == 0 && next_position == 0)
256         {
257                 next_position = prev_position = get_source_start();
258         }
259
260 // Get range to flip in requested rate
261         int64_t range_start = prev_position;
262         int64_t range_end = next_position;
263
264 // Between keyframe and edge of range or no keyframes
265         if(range_start == range_end)
266         {
267 // Between first keyframe and start of effect
268                 if(get_source_position() >= get_source_start() &&
269                         get_source_position() < range_start)
270                 {
271                         range_start = get_source_start();
272                 }
273                 else
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())
277                 {
278                         range_end = get_source_start() + get_total_len();
279                 }
280                 else
281                 {
282 // Should never get here
283                         ;
284                 }
285         }
286
287 // Convert start position to new direction
288         if(get_direction() == PLAY_FORWARD)
289         {
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;
295         }
296         else
297         {
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;
302         }
303 // printf("ReverseAudio::load_configuration 20 start=%lld end=%lld current=%lld input=%lld\n", 
304 // range_start, 
305 // range_end, 
306 // get_source_position(),
307 // input_position);
308
309         return 0;
310 }
311
312
313 void ReverseAudio::save_data(KeyFrame *keyframe)
314 {
315         FileXML output;
316
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);
321         output.append_tag();
322         output.terminate_string();
323 }
324
325 void ReverseAudio::read_data(KeyFrame *keyframe)
326 {
327         FileXML input;
328
329         input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
330
331         while(!input.read_tag())
332         {
333                 if(input.tag.title_is("REVERSEAUDIO"))
334                 {
335                         config.enabled = input.tag.get_property("ENABLED", config.enabled);
336                 }
337         }
338 }
339
340 void ReverseAudio::update_gui()
341 {
342         if(thread)
343         {
344                 load_configuration();
345                 thread->window->lock_window();
346                 ((ReverseAudioWindow*)thread->window)->enabled->update(config.enabled);
347                 thread->window->unlock_window();
348         }
349 }
350
351
352
353
354