Fixed initialisation of tf in file_open(). Without setting the memory to 0,
[cinelerra_cv/mob.git] / plugins / loopaudio / loopaudio.C
blobfcc37e55eddc0c012a69f4725aae7c95af52c9c2
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "bchash.h"
4 #include "filexml.h"
5 #include "guicast.h"
6 #include "language.h"
7 #include "pluginaclient.h"
8 #include "transportque.h"
10 #include <string.h>
12 class LoopAudio;
14 class LoopAudioConfig
16 public:
17         LoopAudioConfig();
18         int64_t samples;
22 class LoopAudioSamples : public BC_TextBox
24 public:
25         LoopAudioSamples(LoopAudio *plugin,
26                 int x,
27                 int y);
28         int handle_event();
29         LoopAudio *plugin;
32 class LoopAudioWindow : public BC_Window
34 public:
35         LoopAudioWindow(LoopAudio *plugin, int x, int y);
36         ~LoopAudioWindow();
37         void create_objects();
38         int close_event();
39         LoopAudio *plugin;
40         LoopAudioSamples *samples;
43 PLUGIN_THREAD_HEADER(LoopAudio, LoopAudioThread, LoopAudioWindow)
45 class LoopAudio : public PluginAClient
47 public:
48         LoopAudio(PluginServer *server);
49         ~LoopAudio();
51         PLUGIN_CLASS_MEMBERS(LoopAudioConfig, LoopAudioThread)
53         int load_defaults();
54         int save_defaults();
55         void save_data(KeyFrame *keyframe);
56         void read_data(KeyFrame *keyframe);
57         void update_gui();
58         int is_realtime();
59         int is_synthesis();
60         int process_buffer(int64_t size, 
61                 double *buffer,
62                 int64_t start_position,
63                 int sample_rate);
72 REGISTER_PLUGIN(LoopAudio);
76 LoopAudioConfig::LoopAudioConfig()
78         samples = 48000;
85 LoopAudioWindow::LoopAudioWindow(LoopAudio *plugin, int x, int y)
86  : BC_Window(plugin->gui_string, 
87         x, 
88         y, 
89         210, 
90         160, 
91         200, 
92         160, 
93         0, 
94         0,
95         1)
97         this->plugin = plugin;
100 LoopAudioWindow::~LoopAudioWindow()
104 void LoopAudioWindow::create_objects()
106         int x = 10, y = 10;
108         add_subwindow(new BC_Title(x, y, _("Samples to loop:")));
109         y += 20;
110         add_subwindow(samples = new LoopAudioSamples(plugin, 
111                 x, 
112                 y));
113         show_window();
114         flush();
117 WINDOW_CLOSE_EVENT(LoopAudioWindow)
120 PLUGIN_THREAD_OBJECT(LoopAudio, LoopAudioThread, LoopAudioWindow)
127 LoopAudioSamples::LoopAudioSamples(LoopAudio *plugin, 
128         int x, 
129         int y)
130  : BC_TextBox(x, 
131         y, 
132         100,
133         1,
134         plugin->config.samples)
136         this->plugin = plugin;
137         set_precision(2);
140 int LoopAudioSamples::handle_event()
142         plugin->config.samples = atol(get_text());
143         plugin->config.samples = MAX(1, plugin->config.samples);
144         plugin->send_configure_change();
145         return 1;
156 LoopAudio::LoopAudio(PluginServer *server)
157  : PluginAClient(server)
159         PLUGIN_CONSTRUCTOR_MACRO
163 LoopAudio::~LoopAudio()
165         PLUGIN_DESTRUCTOR_MACRO
168 char* LoopAudio::plugin_title() { return N_("Loop audio"); }
169 int LoopAudio::is_realtime() { return 1; } 
170 int LoopAudio::is_synthesis() { return 1; }
173 #include "picon_png.h"
174 NEW_PICON_MACRO(LoopAudio)
176 SHOW_GUI_MACRO(LoopAudio, LoopAudioThread)
178 RAISE_WINDOW_MACRO(LoopAudio)
180 SET_STRING_MACRO(LoopAudio);
183 int LoopAudio::process_buffer(int64_t size, 
184         double *buffer,
185         int64_t start_position,
186         int sample_rate)
188         int64_t current_position = start_position;
189         int step = (get_direction() == PLAY_FORWARD) ? 1 : -1;
190         int fragment_size;
191         int64_t current_loop_end;
193 //printf("LoopAudio::process_buffer 1 %lld %d\n", start_position, size);
195         current_position = start_position;
197         for(int i = 0; i < size; i += fragment_size)
198         {
199 // Truncate to end of buffer
200                 fragment_size = MIN(size - i, size);
202                 int64_t current_loop_position;
204 // Truncate to next keyframe
205                 if(get_direction() == PLAY_FORWARD)
206                 {
207                         KeyFrame *next_keyframe = get_next_keyframe(current_position);
208                         int64_t next_position = edl_to_local(next_keyframe->position);
209                         if(next_position > current_position)
210                                 fragment_size = MIN(fragment_size, next_position - current_position);
212 // Get start of current loop
213                         KeyFrame *prev_keyframe = get_prev_keyframe(current_position);
214                         int64_t prev_position = edl_to_local(prev_keyframe->position);
215                         if(prev_position == 0)
216                                 prev_position = get_source_start();
217                         read_data(prev_keyframe);
219 // Get start of fragment in current loop
220                         current_loop_position = prev_position +
221                                 ((current_position - prev_position) % 
222                                         config.samples);
223                         while(current_loop_position < prev_position) current_loop_position += config.samples;
224                         while(current_loop_position >= prev_position + config.samples) current_loop_position -= config.samples;
226 // Truncate fragment to end of loop
227                         current_loop_end = current_position - 
228                                 current_loop_position +
229                                 prev_position + 
230                                 config.samples;
231                         fragment_size = MIN(current_loop_end - current_position,
232                                 fragment_size);
233                 }
234                 else
235                 {
236                         KeyFrame *next_keyframe = get_prev_keyframe(current_position);
237                         int64_t next_position = edl_to_local(next_keyframe->position);
238                         if(next_position < current_position)
239                                 fragment_size = MIN(fragment_size, current_position - next_position);
241                         KeyFrame *prev_keyframe = get_next_keyframe(current_position);
242                         int64_t prev_position = edl_to_local(prev_keyframe->position);
243                         if(prev_position == 0)
244                                 prev_position = get_source_start() + get_total_len();
245                         read_data(prev_keyframe);
247                         current_loop_position = prev_position - 
248                                 ((prev_position - current_position) %
249                                           config.samples);
250                         while(current_loop_position <= prev_position - config.samples) current_loop_position += config.samples;
251                         while(current_loop_position > prev_position) current_loop_position -= config.samples;
253 // Truncate fragment to end of loop
254                         current_loop_end = current_position + 
255                                 prev_position -
256                                 current_loop_position -
257                                 config.samples;
258                         fragment_size = MIN(current_position - current_loop_end,
259                                 fragment_size);
260                 }
263 // printf("LoopAudio::process_buffer 100 %lld %lld %lld %d\n", 
264 // current_position, current_loop_position, current_loop_end, fragment_size);
265                 read_samples(buffer + i,
266                         0,
267                         sample_rate,
268                         current_loop_position,
269                         fragment_size);
272                 current_position += step * fragment_size;
273         }
274         
276         return 0;
282 int LoopAudio::load_configuration()
284         KeyFrame *prev_keyframe;
285         int64_t old_samples = config.samples;
286         prev_keyframe = get_prev_keyframe(get_source_position());
287         read_data(prev_keyframe);
288         return old_samples != config.samples;
291 int LoopAudio::load_defaults()
293         char directory[BCTEXTLEN];
294 // set the default directory
295         sprintf(directory, "%sloopaudio.rc", BCASTDIR);
297 // load the defaults
298         defaults = new BC_Hash(directory);
299         defaults->load();
301         config.samples = defaults->get("SAMPLES", config.samples);
302         return 0;
305 int LoopAudio::save_defaults()
307         defaults->update("SAMPLES", config.samples);
308         defaults->save();
309         return 0;
312 void LoopAudio::save_data(KeyFrame *keyframe)
314         FileXML output;
316 // cause data to be stored directly in text
317         output.set_shared_string(keyframe->data, MESSAGESIZE);
318         output.tag.set_title("LOOPAUDIO");
319         output.tag.set_property("SAMPLES", config.samples);
320         output.append_tag();
321         output.terminate_string();
324 void LoopAudio::read_data(KeyFrame *keyframe)
326         FileXML input;
328         input.set_shared_string(keyframe->data, strlen(keyframe->data));
330         int result = 0;
332         while(!input.read_tag())
333         {
334                 if(input.tag.title_is("LOOPAUDIO"))
335                 {
336                         config.samples = input.tag.get_property("SAMPLES", config.samples);
337                 }
338         }
341 void LoopAudio::update_gui()
343         if(thread)
344         {
345                 load_configuration();
346                 thread->window->lock_window();
347                 thread->window->samples->update(config.samples);
348                 thread->window->unlock_window();
349         }