r1009: Move the dependencies to newer package names
[cinelerra_cv/mob.git] / cinelerra / amodule.C
blob17dca62274f59b3c9b73b635a32327ecb4f8b937
1 #include "aattachmentpoint.h"
2 #include "aedit.h"
3 #include "amodule.h"
4 #include "aplugin.h"
5 #include "arender.h"
6 #include "asset.h"
7 #include "atrack.h"
8 #include "bcsignals.h"
9 #include "cache.h"
10 #include "edits.h"
11 #include "edl.h"
12 #include "edlsession.h"
13 #include "file.h"
14 #include "filexml.h"
15 #include "floatautos.h"
16 #include "language.h"
17 #include "module.h"
18 #include "patch.h"
19 #include "plugin.h"
20 #include "pluginarray.h"
21 #include "preferences.h"
22 #include "renderengine.h"
23 #include "mainsession.h"
24 #include "sharedlocation.h"
25 #include "theme.h"
26 #include "transition.h"
27 #include "transportque.h"
28 #include <string.h>
32 AModule::AModule(RenderEngine *renderengine, 
33         CommonRender *commonrender, 
34         PluginArray *plugin_array,
35         Track *track)
36  : Module(renderengine, commonrender, plugin_array, track)
38         data_type = TRACK_AUDIO;
39         transition_temp = 0;
40         transition_temp_alloc = 0;
41         level_history = 0;
42         current_level = 0;
48 AModule::~AModule()
50         if(transition_temp) delete [] transition_temp;
51         if(level_history)
52         {
53                 delete [] level_history;
54                 delete [] level_samples;
55         }
58 AttachmentPoint* AModule::new_attachment(Plugin *plugin)
60         return new AAttachmentPoint(renderengine, plugin);
64 void AModule::create_objects()
66         Module::create_objects();
67 // Not needed in pluginarray
68         if(commonrender)
69         {
70                 level_history = new double[((ARender*)commonrender)->total_peaks];
71                 level_samples = new int64_t[((ARender*)commonrender)->total_peaks];
72                 current_level = 0;
74                 for(int i = 0; i < ((ARender*)commonrender)->total_peaks; i++)
75                 {
76                         level_history[i] = 0;
77                         level_samples[i] = -1;
78                 }
79         }
82 int AModule::get_buffer_size()
84         if(renderengine)
85                 return renderengine->fragment_len;
86         else
87                 return plugin_array->get_bufsize();
90 void AModule::reverse_buffer(double *buffer, int64_t len)
92         int start, end;
93         double temp;
95         for(start = 0, end = len - 1; end > start; start++, end--)
96         {
97                 temp = buffer[start];
98                 buffer[start] = buffer[end];
99                 buffer[end] = temp;
100         }
104 CICache* AModule::get_cache()
106         if(renderengine)
107                 return renderengine->get_acache();
108         else
109                 return cache;
112 int AModule::render(double *buffer, 
113         int64_t input_position,
114         int input_len, 
115         int direction,
116         int sample_rate,
117         int use_nudge)
119         int64_t edl_rate = get_edl()->session->sample_rate;
120         if(use_nudge) 
121                 input_position += track->nudge * 
122                         sample_rate /
123                         edl_rate;
125         AEdit *playable_edit;
126         int64_t start_project = input_position;
127         int64_t end_project = input_position + input_len;
128         int64_t buffer_offset = 0;
129         int result = 0;
132 // Flip range around so start_project < end_project
133         if(direction == PLAY_REVERSE)
134         {
135                 start_project -= input_len;
136                 end_project -= input_len;
137         }
140 // Clear buffer
141         bzero(buffer, input_len * sizeof(double));
143 // The EDL is normalized to the requested sample rate because the requested rate may
144 // be the project sample rate and a sample rate 
145 // might as well be directly from the source rate to the requested rate.
146 // Get first edit containing the range
147         for(playable_edit = (AEdit*)track->edits->first; 
148                 playable_edit;
149                 playable_edit = (AEdit*)playable_edit->next)
150         {
151                 int64_t edit_start = playable_edit->startproject;
152                 int64_t edit_end = playable_edit->startproject + playable_edit->length;
153 // Normalize to requested rate
154                 edit_start = edit_start * sample_rate / edl_rate;
155                 edit_end = edit_end * sample_rate / edl_rate;
157                 if(start_project < edit_end && start_project + input_len > edit_start)
158                 {
159                         break;
160                 }
161         }
169 // Fill output one fragment at a time
170         while(start_project < end_project)
171         {
172                 int64_t fragment_len = input_len;
175                 if(fragment_len + start_project > end_project)
176                         fragment_len = end_project - start_project;
178 // Normalize position here since update_transition is a boolean operation.
179                 update_transition(start_project * 
180                                 edl_rate / 
181                                 sample_rate, 
182                         PLAY_FORWARD);
184                 if(playable_edit)
185                 {
186 // Normalize EDL positions to requested rate
187                         int64_t edit_startproject = playable_edit->startproject;
188                         int64_t edit_endproject = playable_edit->startproject + playable_edit->length;
189                         int64_t edit_startsource = playable_edit->startsource;
190 //printf("AModule::render 52 %lld\n", fragment_len);
192                         edit_startproject = edit_startproject * sample_rate / edl_rate;
193                         edit_endproject = edit_endproject * sample_rate / edl_rate;
194                         edit_startsource = edit_startsource * sample_rate / edl_rate;
195 //printf("AModule::render 53 %lld\n", fragment_len);
199 // Trim fragment_len
200                         if(fragment_len + start_project > edit_endproject)
201                                 fragment_len = edit_endproject - start_project;
202 //printf("AModule::render 56 %lld\n", fragment_len);
204                         if(playable_edit->asset)
205                         {
206                                 File *source;
207                                 get_cache()->age();
211                                 if(!(source = get_cache()->check_out(playable_edit->asset,
212                                         get_edl())))
213                                 {
214 // couldn't open source file / skip the edit
215                                         result = 1;
216                                         printf(_("VirtualAConsole::load_track Couldn't open %s.\n"), playable_edit->asset->path);
217                                 }
218                                 else
219                                 {
220                                         int result = 0;
223                                         result = source->set_audio_position(start_project - 
224                                                         edit_startproject + 
225                                                         edit_startsource, 
226                                                 sample_rate);
228 //                                      if(result) printf("AModule::render start_project=%d playable_edit->startproject=%d playable_edit->startsource=%d\n"
229 //                                              "source=%p playable_edit=%p edl=%p edlsession=%p sample_rate=%d\n",
230 //                                              start_project, playable_edit->startproject, playable_edit->startsource, 
231 //                                              source, playable_edit, get_edl(), get_edl()->session, get_edl()->session->sample_rate);
233                                         source->set_channel(playable_edit->channel);
235                                         source->read_samples(buffer + buffer_offset, 
236                                                 fragment_len,
237                                                 sample_rate);
239                                         get_cache()->check_in(playable_edit->asset);
240                                 }
241                         }
247 // Read transition into temp and render
248                         AEdit *previous_edit = (AEdit*)playable_edit->previous;
249                         if(transition && previous_edit)
250                         {
251                                 int64_t transition_len = transition->length * 
252                                         sample_rate / 
253                                         edl_rate;
254                                 int64_t previous_startproject = previous_edit->startproject *
255                                         sample_rate /
256                                         edl_rate;
257                                 int64_t previous_startsource = previous_edit->startsource *
258                                         sample_rate /
259                                         edl_rate;
261 // Read into temp buffers
262 // Temp + master or temp + temp ? temp + master
263                                 if(transition_temp && transition_temp_alloc < fragment_len)
264                                 {
265                                         delete [] transition_temp;
266                                         transition_temp = 0;
267                                 }
269                                 if(!transition_temp)
270                                 {
271                                         transition_temp = new double[fragment_len];
272                                         transition_temp_alloc = fragment_len;
273                                 }
277 // Trim transition_len
278                                 int transition_fragment_len = fragment_len;
279                                 if(fragment_len + start_project > 
280                                         edit_startproject + transition_len)
281                                         fragment_len = edit_startproject + transition_len - start_project;
282 //printf("AModule::render 54 %lld\n", fragment_len);
284                                 if(transition_fragment_len > 0)
285                                 {
286                                         if(previous_edit->asset)
287                                         {
288                                                 File *source;
289                                                 get_cache()->age();
290                                                 if(!(source = get_cache()->check_out(
291                                                         previous_edit->asset,
292                                                         get_edl())))
293                                                 {
294 // couldn't open source file / skip the edit
295                                                         printf(_("VirtualAConsole::load_track Couldn't open %s.\n"), playable_edit->asset->path);
296                                                         result = 1;
297                                                 }
298                                                 else
299                                                 {
300                                                         int result = 0;
302                                                         result = source->set_audio_position(start_project - 
303                                                                         previous_startproject + 
304                                                                         previous_startsource, 
305                                                                 get_edl()->session->sample_rate);
307 //                                                      if(result) printf("AModule::render start_project=%d playable_edit->startproject=%d playable_edit->startsource=%d\n"
308 //                                                              "source=%p playable_edit=%p edl=%p edlsession=%p sample_rate=%d\n",
309 //                                                              start_project, 
310 //                                                              previous_edit->startproject, 
311 //                                                              previous_edit->startsource, 
312 //                                                              source, 
313 //                                                              playable_edit, 
314 //                                                              get_edl(), 
315 //                                                              get_edl()->session, 
316 //                                                              get_edl()->session->sample_rate);
318                                                         source->set_channel(previous_edit->channel);
320                                                         source->read_samples(transition_temp, 
321                                                                 transition_fragment_len,
322                                                                 sample_rate);
324                                                         get_cache()->check_in(previous_edit->asset);
325                                                 }
326                                         }
327                                         else
328                                         {
329                                                 bzero(transition_temp, transition_fragment_len * sizeof(double));
330                                         }
332                                         double *output = buffer + buffer_offset;
333                                         transition_server->process_transition(
334                                                 transition_temp,
335                                                 output,
336                                                 start_project - edit_startproject,
337                                                 transition_fragment_len,
338                                                 transition->length);
339                                 }
340                         }
342                         if(playable_edit && start_project + fragment_len >= edit_endproject)
343                                 playable_edit = (AEdit*)playable_edit->next;
344                 }
346                 buffer_offset += fragment_len;
347                 start_project += fragment_len;
348         }
351 // Reverse buffer here so plugins always render forward.
352         if(direction == PLAY_REVERSE)
353                 reverse_buffer(buffer, input_len);
356         return result;