b5d544577e8dcf648417a559a1b3e32a824abed3
[goodguy/history.git] / cinelerra-5.1 / plugins / overlayaudio / overlayaudio.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 "language.h"
26 #include "pluginaclient.h"
27 #include "samples.h"
28 #include "theme.h"
29 #include <string.h>
30
31
32 class OverlayAudioWindow;
33 class OverlayAudio;
34
35 #define AUDIO_TRANSFER_TYPES 2
36
37
38 class OverlayAudioConfig
39 {
40 public:
41         OverlayAudioConfig();
42         int equivalent(OverlayAudioConfig &that);
43         void copy_from(OverlayAudioConfig &that);
44         void interpolate(OverlayAudioConfig &prev,
45                 OverlayAudioConfig &next,
46                 int64_t prev_frame,
47                 int64_t next_frame,
48                 int64_t current_frame);
49         static const char* output_to_text(int output_layer);
50         static const char* mode_to_text(int mode);
51         int output_track;
52         enum
53         {
54                 TOP,
55                 BOTTOM
56         };
57
58
59         int mode;
60         enum
61         {
62                 ADD,
63                 MULTIPLY
64         };
65 };
66
67 class OutputTrack : public BC_PopupMenu
68 {
69 public:
70         OutputTrack(OverlayAudio *plugin, int x, int y);
71         void create_objects();
72         int handle_event();
73         OverlayAudio *plugin;
74 };
75
76
77 class OverlayMode : public BC_PopupMenu
78 {
79 public:
80         OverlayMode(OverlayAudio *plugin,
81                 int x,
82                 int y);
83         void create_objects();
84         int handle_event();
85         OverlayAudio *plugin;
86 };
87
88 class OverlayAudioWindow : public PluginClientWindow
89 {
90 public:
91         OverlayAudioWindow(OverlayAudio *plugin);
92
93         void create_objects();
94
95
96         OverlayAudio *plugin;
97         OutputTrack *output;
98         OverlayMode *mode;
99 };
100
101
102
103 class OverlayAudio : public PluginAClient
104 {
105 public:
106         OverlayAudio(PluginServer *server);
107         ~OverlayAudio();
108
109         int is_multichannel();
110         int is_realtime();
111         void read_data(KeyFrame *keyframe);
112         void save_data(KeyFrame *keyframe);
113         int process_buffer(int64_t size,
114                 Samples **buffer,
115                 int64_t start_position,
116                 int sample_rate);
117         void update_gui();
118
119
120         PLUGIN_CLASS_MEMBERS2(OverlayAudioConfig)
121 };
122
123
124
125
126
127
128
129
130 OverlayAudioConfig::OverlayAudioConfig()
131 {
132         output_track = OverlayAudioConfig::TOP;
133         mode = OverlayAudioConfig::ADD;
134
135 }
136
137 int OverlayAudioConfig::equivalent(OverlayAudioConfig &that)
138 {
139         return that.output_track == output_track &&
140                 that.mode == mode;
141 }
142
143 void OverlayAudioConfig::copy_from(OverlayAudioConfig &that)
144 {
145         output_track = that.output_track;
146         mode = that.mode;
147 }
148
149 void OverlayAudioConfig::interpolate(OverlayAudioConfig &prev,
150         OverlayAudioConfig &next,
151         int64_t prev_frame,
152         int64_t next_frame,
153         int64_t current_frame)
154 {
155         output_track = prev.output_track;
156         mode = prev.mode;
157 }
158
159 const char* OverlayAudioConfig::output_to_text(int output_layer)
160 {
161         switch(output_layer)
162         {
163                 case OverlayAudioConfig::TOP:    return _("Top");
164                 case OverlayAudioConfig::BOTTOM: return _("Bottom");
165         }
166         return "";
167 }
168
169
170 const char* OverlayAudioConfig::mode_to_text(int mode)
171 {
172         switch(mode)
173         {
174                 case OverlayAudioConfig::ADD:    return _("Add");
175                 case OverlayAudioConfig::MULTIPLY: return _("Multiply");
176         }
177         return "";
178 }
179
180
181
182
183
184
185
186 OverlayAudioWindow::OverlayAudioWindow(OverlayAudio *plugin)
187  : PluginClientWindow(plugin,
188         400,
189         100,
190         400,
191         100,
192         0)
193 {
194         this->plugin = plugin;
195 }
196
197 void OverlayAudioWindow::create_objects()
198 {
199         int x = 10, y = 10;
200         int x1 = x;
201         BC_Title *title;
202         add_subwindow(title = new BC_Title(x, y, _("Output track:")));
203         x += title->get_w() + plugin->get_theme()->widget_border;
204         add_subwindow(output = new OutputTrack(plugin, x, y));
205         output->create_objects();
206
207         y += output->get_h() + plugin->get_theme()->widget_border;
208         x = x1;
209         add_subwindow(title = new BC_Title(x, y, _("Mode:")));
210         x += title->get_w() + plugin->get_theme()->widget_border;
211         add_subwindow(mode = new OverlayMode(plugin, x, y));
212         mode->create_objects();
213
214
215         show_window();
216 }
217
218
219
220
221
222
223 OutputTrack::OutputTrack(OverlayAudio *plugin, int x , int y)
224  : BC_PopupMenu(x,
225         y,
226         100,
227         OverlayAudioConfig::output_to_text(plugin->config.output_track),
228         1)
229 {
230         this->plugin = plugin;
231 }
232
233 void OutputTrack::create_objects()
234 {
235         add_item(new BC_MenuItem(
236                 OverlayAudioConfig::output_to_text(
237                         OverlayAudioConfig::TOP)));
238         add_item(new BC_MenuItem(
239                 OverlayAudioConfig::output_to_text(
240                         OverlayAudioConfig::BOTTOM)));
241 }
242
243 int OutputTrack::handle_event()
244 {
245         char *text = get_text();
246
247         if(!strcmp(text,
248                 OverlayAudioConfig::output_to_text(
249                         OverlayAudioConfig::TOP)))
250                 plugin->config.output_track = OverlayAudioConfig::TOP;
251         else
252         if(!strcmp(text,
253                 OverlayAudioConfig::output_to_text(
254                         OverlayAudioConfig::BOTTOM)))
255                 plugin->config.output_track = OverlayAudioConfig::BOTTOM;
256
257         plugin->send_configure_change();
258         return 1;
259 }
260
261
262
263
264
265
266
267
268
269
270
271
272 OverlayMode::OverlayMode(OverlayAudio *plugin,
273         int x,
274         int y)
275  : BC_PopupMenu(x,
276         y,
277         150,
278         OverlayAudioConfig::mode_to_text(plugin->config.mode),
279         1)
280 {
281         this->plugin = plugin;
282 }
283
284 void OverlayMode::create_objects()
285 {
286         for(int i = 0; i < AUDIO_TRANSFER_TYPES; i++)
287                 add_item(new BC_MenuItem(OverlayAudioConfig::mode_to_text(i)));
288 }
289
290 int OverlayMode::handle_event()
291 {
292         char *text = get_text();
293
294         for(int i = 0; i < AUDIO_TRANSFER_TYPES; i++)
295         {
296                 if(!strcmp(text, OverlayAudioConfig::mode_to_text(i)))
297                 {
298                         plugin->config.mode = i;
299                         break;
300                 }
301         }
302
303         plugin->send_configure_change();
304         return 1;
305 }
306
307
308
309
310
311
312
313
314
315 REGISTER_PLUGIN(OverlayAudio)
316
317
318
319
320 OverlayAudio::OverlayAudio(PluginServer *server)
321  : PluginAClient(server)
322 {
323
324 }
325
326 OverlayAudio::~OverlayAudio()
327 {
328
329 }
330
331 const char* OverlayAudio::plugin_title() { return N_("Overlay"); }
332 int OverlayAudio::is_realtime() { return 1; }
333 int OverlayAudio::is_multichannel() { return 1; }
334
335
336
337 void OverlayAudio::read_data(KeyFrame *keyframe)
338 {
339         FileXML input;
340         input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
341
342         int result = 0;
343         while(!result)
344         {
345                 result = input.read_tag();
346
347                 if(!result)
348                 {
349                         if(input.tag.title_is("OVERLAY"))
350                         {
351                                 config.output_track = input.tag.get_property("OUTPUT", config.output_track);
352                                 config.mode = input.tag.get_property("MODE", config.mode);
353                         }
354                 }
355         }
356 }
357
358 void OverlayAudio::save_data(KeyFrame *keyframe)
359 {
360         FileXML output;
361         output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
362
363         output.tag.set_title("OVERLAY");
364         output.tag.set_property("OUTPUT", config.output_track);
365         output.tag.set_property("MODE", config.mode);
366         output.append_tag();
367         output.tag.set_title("/OVERLAY");
368         output.append_tag();
369         output.append_newline();
370         output.terminate_string();
371 }
372
373
374
375 void OverlayAudio::update_gui()
376 {
377         if(thread)
378         {
379                 if(load_configuration())
380                 {
381                         thread->window->lock_window("OverlayAudio::update_gui");
382                         ((OverlayAudioWindow*)thread->window)->output->set_text(
383                                 OverlayAudioConfig::output_to_text(config.output_track));
384                         ((OverlayAudioWindow*)thread->window)->mode->set_text(
385                                 OverlayAudioConfig::mode_to_text(config.mode));
386                         thread->window->unlock_window();
387                 }
388         }
389 }
390
391 NEW_WINDOW_MACRO(OverlayAudio, OverlayAudioWindow)
392 LOAD_CONFIGURATION_MACRO(OverlayAudio, OverlayAudioConfig)
393
394
395 int OverlayAudio::process_buffer(int64_t size,
396         Samples **buffer,
397         int64_t start_position,
398         int sample_rate)
399 {
400         load_configuration();
401
402
403         int output_track = 0;
404         if(config.output_track == OverlayAudioConfig::BOTTOM)
405                 output_track = get_total_buffers() - 1;
406
407 // Direct copy the output track
408         read_samples(buffer[output_track],
409                 output_track,
410                 sample_rate,
411                 start_position,
412                 size);
413
414 // Add remaining tracks
415         Samples *output_buffer = buffer[output_track];
416         double *output_samples = output_buffer->get_data();
417         for(int i = 0; i < get_total_buffers(); i++)
418         {
419                 if(i != output_track)
420                 {
421                         Samples *input_buffer = buffer[i];
422                         read_samples(buffer[i],
423                                 i,
424                                 sample_rate,
425                                 start_position,
426                                 size);
427                         double *input_samples = input_buffer->get_data();
428
429                         switch(config.mode)
430                         {
431                                 case OverlayAudioConfig::ADD:
432                                         for(int j = 0; j < size; j++)
433                                         {
434                                                 output_samples[j] += input_samples[j];
435                                         }
436                                         break;
437
438
439                                 case OverlayAudioConfig::MULTIPLY:
440                                         for(int j = 0; j < size; j++)
441                                         {
442                                                 output_samples[j] *= input_samples[j];
443                                         }
444                                         break;
445                         }
446                 }
447         }
448
449         return 0;
450 }
451
452
453
454
455
456