prevent popup deactivation while button_down
[goodguy/history.git] / cinelerra-5.0 / cinelerra / virtualanode.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 "aattachmentpoint.h"
23 #include "aedit.h"
24 #include "amodule.h"
25 #include "arender.h"
26 #include "atrack.h"
27 #include "automation.h"
28 #include "bcsignals.h"
29 #include "clip.h"
30 #include "edits.h"
31 #include "edl.h"
32 #include "edlsession.h"
33 #include "floatautos.h"
34 #include "format.inc"
35 #include "mwindow.h"
36 #include "module.h"
37 #include "panauto.h"
38 #include "plugin.h"
39 #include "renderengine.h"
40 #include "samples.h"
41 #include "track.h"
42 #include "transition.h"
43 #include "transportque.h"
44 #include "virtualaconsole.h"
45 #include "virtualanode.h"
46
47
48 #include <string.h>
49
50 VirtualANode::VirtualANode(RenderEngine *renderengine, 
51                 VirtualConsole *vconsole, 
52                 Module *real_module, 
53                 Plugin *real_plugin,
54                 Track *track, 
55                 VirtualNode *parent_module)
56  : VirtualNode(renderengine, 
57                 vconsole, 
58                 real_module, 
59                 real_plugin,
60                 track, 
61                 parent_module)
62 {
63         for(int i = 0; i < MAXCHANNELS; i++)
64         {
65                 pan_before[i] = pan_after[i] = 0;
66         }
67 }
68
69 VirtualANode::~VirtualANode()
70 {
71 }
72
73
74
75
76
77 VirtualNode* VirtualANode::create_module(Plugin *real_plugin, 
78                                                         Module *real_module, 
79                                                         Track *track)
80 {
81         return new VirtualANode(renderengine, 
82                 vconsole, 
83                 real_module,
84                 0,
85                 track,
86                 this);
87 }
88
89
90 VirtualNode* VirtualANode::create_plugin(Plugin *real_plugin)
91 {
92         return new VirtualANode(renderengine, 
93                 vconsole, 
94                 0,
95                 real_plugin,
96                 track,
97                 this);
98 }
99
100
101
102 int VirtualANode::read_data(Samples *output_temp,
103         int64_t size,
104         int64_t start_position,
105         int64_t sample_rate)
106 {
107         VirtualNode *previous_plugin = 0;
108
109 // Current edit in parent track
110         AEdit *parent_edit = 0;
111         if(parent_node && parent_node->track && renderengine)
112         {
113                 int64_t edl_rate = renderengine->get_edl()->session->sample_rate;
114                 int64_t start_position_project = (int64_t)(start_position *
115                         edl_rate /
116                         sample_rate + 
117                         0.5);
118                 parent_edit = (AEdit*)parent_node->track->edits->editof(start_position_project, 
119                         renderengine->command->get_direction(),
120                         0);
121         }
122
123
124         if(vconsole->debug_tree) 
125                 printf("  VirtualANode::read_data position=" _LD " rate=" _LD ""
126                         " title=%s parent_node=%p parent_edit=%p\n", 
127                         start_position, sample_rate, track->title,
128                         parent_node, parent_edit);
129
130
131 // This is a plugin on parent module with a preceeding effect.
132 // Get data from preceeding effect on parent module.
133         if(parent_node && 
134                 (previous_plugin = parent_node->get_previous_plugin(this)))
135         {
136                 ((VirtualANode*)previous_plugin)->render(output_temp,
137                         size,
138                         start_position,
139                         sample_rate);
140         }
141         else
142 // The current node is the first plugin on parent module.
143 // The parent module has an edit to read from or the current node
144 // has no source to read from.
145 // Read data from parent module
146         if(parent_node && (parent_edit || !real_module))
147         {
148                 ((VirtualANode*)parent_node)->read_data(output_temp,
149                         size,
150                         start_position,
151                         sample_rate);
152         }
153         else
154         if(real_module)
155 // This is the first node in the tree
156         {
157                 ((AModule*)real_module)->render(output_temp,
158                         size,
159                         start_position,
160                         renderengine->command->get_direction(),
161                         sample_rate,
162                         0);
163         }
164         return 0;
165 }
166
167 int VirtualANode::render(Samples *output_temp,
168         int64_t size,
169         int64_t start_position,
170         int64_t sample_rate)
171 {
172         const int debug = 0;
173 if(debug) printf("VirtualANode::render %d this=%p\n", __LINE__, this);
174         ARender *arender = ((VirtualAConsole*)vconsole)->arender;
175         if(real_module)
176         {
177 if(debug) printf("VirtualANode::render %d this=%p\n", __LINE__, this);
178                 render_as_module(arender->audio_out, 
179                         output_temp,
180                         size,
181                         start_position, 
182                         sample_rate);
183 if(debug) printf("VirtualANode::render %d this=%p\n", __LINE__, this);
184         }
185         else
186         if(real_plugin)
187         {
188 if(debug) printf("VirtualANode::render %d this=%p\n", __LINE__, this);
189                 render_as_plugin(output_temp,
190                         size,
191                         start_position,
192                         sample_rate);
193 if(debug) printf("VirtualANode::render %d this=%p\n", __LINE__, this);
194         }
195 if(debug) printf("VirtualANode::render %d this=%p\n", __LINE__, this);
196         return 0;
197 }
198
199 void VirtualANode::render_as_plugin(Samples *output_temp,
200         int64_t size,
201         int64_t start_position, 
202         int64_t sample_rate)
203 {
204         if(!attachment ||
205                 !real_plugin ||
206                 !real_plugin->on) return;
207
208 // If we're the first plugin in the parent module, data needs to be read from 
209 // what comes before the parent module.  Otherwise, data needs to come from the
210 // previous plugin.
211         ((AAttachmentPoint*)attachment)->render(
212                 output_temp, 
213                 plugin_buffer_number,
214                 start_position,
215                 size,
216                 sample_rate);
217 }
218
219 int VirtualANode::render_as_module(Samples **audio_out, 
220                                 Samples *output_temp,
221                                 int64_t len,
222                                 int64_t start_position,
223                                 int64_t sample_rate)
224 {
225         int direction = renderengine->command->get_direction();
226         EDL *edl = vconsole->renderengine->get_edl();
227         const int debug = 0;
228
229 // Process last subnode.  This calls read_data, propogates up the chain 
230 // of subnodes, and finishes the chain.
231         if(subnodes.total)
232         {
233                 VirtualANode *node = (VirtualANode*)subnodes.values[subnodes.total - 1];
234                 node->render(output_temp,
235                         len,
236                         start_position,
237                         sample_rate);
238
239         }
240         else
241 // Read data from previous entity
242         {
243                 read_data(output_temp,
244                         len,
245                         start_position,
246                         sample_rate);
247         }
248
249 // for(int k = 0; k < len; k++)
250 // {
251 //      output_temp->get_data()[k] = (k / 10) % 2;
252 // }
253
254 if(debug) printf("VirtualANode::render_as_module %d\n", __LINE__);
255         render_fade(output_temp->get_data(),
256                                 len,
257                                 start_position,
258                                 sample_rate,
259                                 track->automation->autos[AUTOMATION_FADE],
260                                 direction,
261                                 0);
262 if(debug) printf("VirtualANode::render_as_module %d\n", __LINE__);
263
264 // Get the peak but don't limit
265 // Calculate position relative to project for meters
266         int64_t project_sample_rate = edl->session->sample_rate;
267         int64_t start_position_project = start_position * 
268                 project_sample_rate /
269                 sample_rate;
270 if(debug) printf("VirtualANode::render_as_module %d\n", __LINE__);
271         if(real_module && renderengine->command->realtime)
272         {
273                 ARender *arender = ((VirtualAConsole*)vconsole)->arender;
274 // Starting sample of meter block
275                 int64_t meter_render_start;
276 // Ending sample of meter block
277                 int64_t meter_render_end;
278 // Number of samples in each meter fragment normalized to requested rate
279                 int meter_render_fragment = arender->meter_render_fragment * 
280                         sample_rate /
281                         project_sample_rate;
282
283
284 // Scan fragment in meter sized fragments
285                 for(int i = 0; i < len; )
286                 {
287                         int current_level = ((AModule*)real_module)->current_level;
288                         double peak = 0;
289                         meter_render_start = i;
290                         meter_render_end = i + meter_render_fragment;
291                         if(meter_render_end > len) 
292                                 meter_render_end = len;
293 // Number of samples into the fragment this meter sized fragment is,
294 // normalized to project sample rate.
295                         int64_t meter_render_start_project = meter_render_start *
296                                 project_sample_rate /
297                                 sample_rate;
298
299 // Scan meter sized fragment
300                         double *output_samples = output_temp->get_data();
301                         for( ; i < meter_render_end; i++)
302                         {
303                                 double sample = fabs(output_samples[i]);
304                                 if(sample > peak) peak = sample;
305                         }
306
307                         ((AModule*)real_module)->level_history[current_level] = 
308                                 peak;
309                         ((AModule*)real_module)->level_samples[current_level] = 
310                                 (direction == PLAY_FORWARD) ?
311                                 (start_position_project + meter_render_start_project) :
312                                 (start_position_project - meter_render_start_project);
313                         ((AModule*)real_module)->current_level = 
314                                 arender->get_next_peak(current_level);
315                 }
316         }
317 if(debug) printf("VirtualANode::render_as_module %d\n", __LINE__);
318
319 // process pans and copy the output to the output channels
320 // Keep rendering unmuted fragments until finished.
321         int mute_position = 0;
322
323         for(int i = 0; i < len; )
324         {
325                 int mute_constant;
326                 int mute_fragment = len - i;
327                 int mute_fragment_project = mute_fragment *
328                         project_sample_rate /
329                         sample_rate;
330                 start_position_project = start_position + 
331                         ((direction == PLAY_FORWARD) ? i : -i);
332                 start_position_project = start_position_project *
333                         project_sample_rate / 
334                         sample_rate;
335
336 // How many samples until the next mute?
337                 get_mute_fragment(start_position_project,
338                                 mute_constant, 
339                                 mute_fragment_project,
340                                 (Autos*)track->automation->autos[AUTOMATION_MUTE],
341                                 direction,
342                                 0);
343 // Fragment is playable
344                 if(!mute_constant)
345                 {
346                         for(int j = 0; 
347                                 j < MAX_CHANNELS; 
348                                 j++)
349                         {
350                                 if(audio_out[j])
351                                 {
352                                         double *buffer = audio_out[j]->get_data();
353
354                                         render_pan(output_temp->get_data() + mute_position, 
355                                                                 buffer + mute_position,
356                                                                 mute_fragment,
357                                                                 start_position,
358                                                                 sample_rate,
359                                                                 (Autos*)track->automation->autos[AUTOMATION_PAN],
360                                                                 j,
361                                                                 direction,
362                                                                 0);
363 //printf("VirtualANode::render_as_module %d %lld\n", __LINE__, start_position);
364                                 }
365                         }
366                 }
367
368                 len -= mute_fragment;
369                 i += mute_fragment;
370                 mute_position += mute_fragment;
371         }
372 if(debug) printf("VirtualANode::render_as_module %d\n", __LINE__);
373
374         return 0;
375 }
376
377 int VirtualANode::render_fade(double *buffer, int64_t len,
378         int64_t input_position, int64_t sample_rate,
379         Autos *autos, int direction, int use_nudge)
380 {
381         double fade_value;
382         FloatAuto *previous = 0;
383         FloatAuto *next = 0;
384         EDL *edl = vconsole->renderengine->get_edl();
385         const int debug = 0;
386         int64_t project_sample_rate = edl->session->sample_rate;
387         double to_project_rate = (double)project_sample_rate / sample_rate;
388         double to_sample_rate = (double)sample_rate / project_sample_rate;
389
390         if(use_nudge)
391                 input_position += track->nudge * to_sample_rate;
392
393 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
394 // Normalize input position to project sample rate here.
395 // Automation functions are general to video and audio so it 
396 // can't normalize itself.
397         int64_t input_pos = input_position * to_project_rate;
398         int64_t len_project = len * to_project_rate;
399
400 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
401         if(((FloatAutos*)autos)->automation_is_constant(
402                 input_pos, len_project, direction, fade_value))
403         {
404 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
405                 double value = fade_value<=INFINITYGAIN ?
406                          0. : DB::fromdb(fade_value);
407                 if( EQUIV(value, 0.) ) {
408                         for(int64_t i = 0; i < len; i++)
409                                 buffer[i] = 0;
410                 }
411                 else if( !EQUIV(value, 1.) ) {
412                         for(int64_t i = 0; i < len; i++)
413                                 buffer[i] *= value;
414                 }
415 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
416         }
417         else
418         {
419 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
420                 for(int64_t i = 0; i < len; i++)
421                 {
422                         input_pos = input_position * to_project_rate;
423
424                         fade_value = ((FloatAutos*)autos)->get_value(
425                                 input_pos, direction, previous, next);
426
427                         double value = fade_value<=INFINITYGAIN ?
428                                  0. : DB::fromdb(fade_value);
429                         if( EQUIV(value,0.) )
430                                 buffer[i] = 0;
431                         else if( !EQUIV(value,1.) ) {
432                                 buffer[i] *= value;
433                         }
434
435                         if(direction == PLAY_FORWARD)
436                                 input_position++;
437                         else
438                                 input_position--;
439                 }
440 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
441         }
442 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
443
444         return 0;
445 }
446
447 int VirtualANode::render_pan(double *input, // start of input fragment
448         double *output,            // start of output fragment
449         int64_t fragment_len,      // fragment length in input scale
450         int64_t input_position,    // starting sample of input buffer in project
451         int64_t sample_rate,       // sample rate of input_position
452         Autos *autos,
453         int channel,
454         int direction,
455         int use_nudge)
456 {
457         double slope = 0.0;
458         double intercept = 1.0;
459         EDL *edl = vconsole->renderengine->get_edl();
460         int64_t project_sample_rate = edl->session->sample_rate;
461         double to_project_rate = (double)project_sample_rate / sample_rate;
462         double to_sample_rate = (double)sample_rate / project_sample_rate;
463         if(use_nudge)
464                 input_position += track->nudge * to_sample_rate;
465
466         for(int i = 0; i < fragment_len; )
467         {
468                 int64_t len = fragment_len - i;
469                 int64_t slope_len = len * to_project_rate;
470                 int64_t input_pos = input_position * to_project_rate;
471
472 // Get slope intercept formula for next fragment
473                 get_pan_automation(slope, intercept, input_pos,
474                         slope_len, autos, channel, direction);
475
476                 slope_len *= to_sample_rate;
477                 slope = slope * to_sample_rate;
478                 slope_len = MIN(slope_len, len - i);
479
480 //printf("VirtualANode::render_pan 3 %d " _LD " %f %p %p\n", i, slope_len, slope, output, input);
481                 if(!EQUIV(slope, 0)) {
482                         for(double j = 0; j < slope_len; j++, i++) {
483                                 value = slope * j + intercept;
484                                 output[i] += input[i] * value;
485                         }
486                 }
487                 else if( EQUIV(intercept, 1) ) {
488                         for(int j = 0; j < slope_len; j++, i++)
489                                 output[i] += input[i];
490                 }
491                 else if( !EQUIV(intercept, 0) ) {
492                         for(int j = 0; j < slope_len; j++, i++)
493                                 output[i] += input[i] * intercept;
494                 }
495                 else
496                         i += slope_len;
497
498                 if(direction == PLAY_FORWARD)
499                         input_position += slope_len;
500                 else
501                         input_position -= slope_len;
502
503 //printf("VirtualANode::render_pan 4\n");
504         }
505
506         return 0;
507 }
508
509
510 void VirtualANode::get_pan_automation(double &slope,
511         double &intercept,
512         int64_t input_position,
513         int64_t &slope_len,
514         Autos *autos,
515         int channel,
516         int direction)
517 {
518         intercept = 0;
519         slope = 0;
520
521         PanAuto *prev_keyframe = 0;
522         PanAuto *next_keyframe = 0;
523         prev_keyframe = (PanAuto*)autos->get_prev_auto(input_position, 
524                 direction, 
525                 (Auto* &)prev_keyframe);
526         next_keyframe = (PanAuto*)autos->get_next_auto(input_position, 
527                 direction, 
528                 (Auto* &)next_keyframe);
529         
530         if(direction == PLAY_FORWARD)
531         {
532 // Two distinct automation points within range
533                 if(next_keyframe->position > prev_keyframe->position)
534                 {
535                         slope = ((double)next_keyframe->values[channel] - prev_keyframe->values[channel]) / 
536                                 ((double)next_keyframe->position - prev_keyframe->position);
537                         intercept = ((double)input_position - prev_keyframe->position) * slope + 
538                                 prev_keyframe->values[channel];
539
540                         if(next_keyframe->position < input_position + slope_len)
541                                 slope_len = next_keyframe->position - input_position;
542                 }
543                 else
544 // One automation point within range
545                 {
546                         slope = 0;
547                         intercept = prev_keyframe->values[channel];
548                 }
549         }
550         else
551         {
552 // Two distinct automation points within range
553                 if(next_keyframe->position < prev_keyframe->position)
554                 {
555                         slope = ((double)next_keyframe->values[channel] - prev_keyframe->values[channel]) / 
556                                 ((double)next_keyframe->position - prev_keyframe->position);
557                         intercept = ((double)input_position - prev_keyframe->position) * slope + 
558                                 prev_keyframe->values[channel];
559
560                         if(next_keyframe->position > input_position - slope_len)
561                                 slope_len = input_position - next_keyframe->position;
562                 }
563                 else
564 // One automation point within range
565                 {
566                         slope = 0;
567                         intercept = next_keyframe->values[channel];
568                 }
569         }
570 }