r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / virtualnode.C
blobd8ce7f3ebbd7789f0d8f07a3651fa535f2834035
1 #include "attachmentpoint.h"
2 #include "auto.h"
3 #include "automation.h"
4 #include "autos.h"
5 #include "floatauto.h"
6 #include "floatautos.h"
7 #include "intauto.h"
8 #include "intautos.h"
9 #include "mwindow.h"
10 #include "module.h"
11 #include "panauto.h"
12 #include "panautos.h"
13 #include "patchbay.h"
14 #include "plugin.h"
15 #include "pluginserver.h"
16 #include "renderengine.h"
17 #include "tracks.h"
18 #include "transition.h"
19 #include "transportque.h"
20 #include "virtualconsole.h"
21 #include "virtualnode.h"
23 VirtualNode::VirtualNode(RenderEngine *renderengine, 
24                 VirtualConsole *vconsole, 
25                 Module *real_module, 
26                 Plugin *real_plugin,
27                 Track *track, 
28                 VirtualNode *parent_module, 
29                 int input_is_master,
30                 int output_is_master,
31                 int in,
32                 int out)
34         this->renderengine = renderengine;
35         this->vconsole = vconsole;
36         this->real_module = real_module;
37         this->real_plugin = real_plugin;
38         this->track = track;
39         this->parent_module = parent_module;
40         this->ring_buffers = vconsole->total_ring_buffers();
41         this->input_is_master = input_is_master;
42         this->output_is_master = output_is_master;
43         this->in = in;
44         this->out = out;
45         shared_input = 1;
46         shared_output = 1;
47         render_count = 0;
48         plugin_type = 0;
49         waiting_real_plugin = 0;
50         plugin_buffer_number = 0;
51         plugin_autos = 0;
52         plugin_auto_before = plugin_auto_after = 0;
53         attachment = 0;
54 //printf("VirtualNode::VirtualNode 1\n");
57 VirtualNode::~VirtualNode()
59         vplugins.remove_all_objects();
60 //printf("VirtualNode::VirtualNode 2\n");
63 #define PRINT_INDENT for(int j = 0; j < indent; j++) printf(" ");
65 void VirtualNode::dump(int indent)
67         PRINT_INDENT
68         printf("VirtualNode title=%s\n", track->title);
69         if(real_module)
70         {
71                 PRINT_INDENT
72                 printf(" Plugins total=%d\n", vplugins.total);
73                 for(int i = 0; i < vplugins.total; i++)
74                 {
75                         vplugins.values[i]->dump(indent + 2);
76                 }
77         }
78         else
79         if(real_plugin)
80         {
81                 printf("    Plugin %s\n", real_plugin->title);
82         }
85 int VirtualNode::expand(int persistant_plugins, int64_t current_position)
87         expand_buffers();
89 //printf("VirtualNode::expand 1 %p\n", this);
90 // module needs to know where the input data for the next process is
91         data_in_input = 1;
92         if(real_module)
93         {
94 //printf("VirtualNode::expand 3\n");
95                 expand_as_module(persistant_plugins, current_position);
96 //printf("VirtualNode::expand 4\n");
97         }
98         else
99         if(real_plugin)
100         {
101 // attach to a real plugin for a plugin
102 // plugin always takes data from input to output
103 //printf("VirtualNode::expand 5\n");
104                 expand_as_plugin(persistant_plugins);
105         }
106 //printf("VirtualNode::expand 6\n");
108         return 0;
111 int VirtualNode::expand_buffers()
113 // temp needed for the output
114         if(!out)
115         {
116                 new_output_buffer();
117                 shared_output = 0;
118                 output_is_master = 0;
119         }
121 // temp needed for the output
122         if(!in)
123         {
124                 new_input_buffer();
125                 shared_input = 0;
126                 input_is_master = 0;
127         }
129         return 0;
132 int VirtualNode::expand_as_module(int duplicate, int64_t current_position)
134         Transition *transition = 0;
136 // create the plugins for this module
137         for(int i = 0; i < track->plugin_set.total; i++)
138         {
139                 Plugin *plugin = track->get_current_plugin(current_position, 
140                         i, 
141                         renderengine->command->get_direction(),
142                         0);
144 // printf("VirtualNode::expand_as_module 1 %d %d %p %p\n", 
145 // i, 
146 // track->plugin_set.total,
147 // plugin, 
148 // real_plugin);
150 // Switch off if circular reference.  This happens if a plugin set or a track is deleted.
151                 if(plugin == real_plugin) continue;
154 //printf("VirtualNode::expand_as_module 2 %d %p\n", i, plugin);
155                 if(plugin)
156                 {
157                         if(plugin->on)
158                         {
159                                 int plugin_type = plugin->plugin_type;
160                                 if(plugin_type == PLUGIN_SHAREDMODULE)
161                                 {
162 // plugin is a module
163 //printf("VirtualNode::expand_as_module 3\n");
164                                         attach_virtual_module(plugin,
165                                                 i, 
166                                                 duplicate, 
167                                                 current_position);
168 //printf("VirtualNode::expand_as_module 4\n");
169                                 }
170                                 else
171                                 if(plugin_type == PLUGIN_SHAREDPLUGIN ||
172                                         plugin_type == PLUGIN_STANDALONE)
173                                 {
174 // plugin is a plugin
175 //printf("VirtualNode::expand_as_module 5\n");
176                                         attach_virtual_plugin(plugin, 
177                                                 i, 
178                                                 duplicate, 
179                                                 current_position);
180 //printf("VirtualNode::expand_as_module 6\n");
181                                 }
182                         }
183                 }
184 //printf("VirtualNode::expand_as_module 7\n");
185         }
186         return 0;
189 int VirtualNode::expand_as_plugin(int duplicate)
191         plugin_type = real_plugin->plugin_type;
193         if(plugin_type == PLUGIN_SHAREDPLUGIN)
194         {
195 // Attached to a shared plugin.
196 // Get the real real plugin it's attached to.
198 // Redirect the real_plugin to the shared plugin.
199                 int real_module_number = real_plugin->shared_location.module;
200                 int real_plugin_number = real_plugin->shared_location.plugin;
201                 Module *real_module = 0;
204                 real_module = vconsole->module_number(real_module_number);
205 // module references are absolute so may get the wrong data type track.
206                 if(real_module &&
207                         real_plugin_number < real_module->total_attachments)
208                 {
209                         attachment = real_module->attachments[real_plugin_number];
210 // Attachment is NULL if off
211                         if(attachment)
212                         {
213                                 real_plugin = attachment->plugin;
215 // Real plugin not on then null it.
216                                 if(!real_plugin->on) real_plugin = 0;
217                         }
218                         else
219                                 real_plugin = 0;
220                 }
221                 else
222                         real_plugin = 0;
223         }
230         if(plugin_type == PLUGIN_STANDALONE)
231         {
232 // Get plugin server
233                 Module *module = vconsole->module_of(track);
235                 attachment = module->attachment_of(real_plugin);
236 //printf("VirtualNode::expand_as_plugin 1 %p %p\n", attachment, real_plugin);
237         }
244 // Add to real plugin's list of virtual plugins for configuration updates
245 // and plugin_server initializations.
246 // Input and output are taken care of when the parent module creates this plugin.
247 // Get number for passing to render.
248 // real_plugin may become NULL after shared plugin test.
249         if(real_plugin && attachment)
250         {
252                 if(attachment) 
253                         plugin_buffer_number = attachment->attach_virtual_plugin(this);
254         }
259         return 0;
262 int VirtualNode::attach_virtual_module(Plugin *plugin, 
263         int plugin_number, 
264         int duplicate, 
265         int64_t current_position)
267         if(plugin->on)
268         {
269 //printf("VirtualNode::attach_virtual_module 1 %p\n", plugin);
270                 int real_module_number = plugin->shared_location.module;
271 //printf("VirtualNode::attach_virtual_module 1\n");
272                 Module *real_module = vconsole->module_number(real_module_number);
273 //printf("VirtualNode::attach_virtual_module 1\n");
274                 Track *track = real_module->track;
276 // Switch off if circular reference.  This happens if a track is deleted.
277                 if(track == this->real_module->track) return 1;
282 // working data is now in output
283                 if(plugin->out) data_in_input = 0;
284 //printf("VirtualNode::attach_virtual_module 1\n");
285                 VirtualNode *virtual_module = create_module(plugin,
286                         real_module,
287                         track);
288 //printf("VirtualNode::attach_virtual_module 1\n");
290                 vplugins.append(virtual_module);
291 //printf("VirtualNode::attach_virtual_module 1\n");
292                 virtual_module->expand(duplicate, current_position);
293 //printf("VirtualNode::attach_virtual_module 2\n");
294         }
296         return 0;
299 int VirtualNode::attach_virtual_plugin(Plugin *plugin, 
300         int plugin_number, 
301         int duplicate, 
302         int64_t current_position)
304         if(plugin->on)
305         {
306 // working data is now in output
307                 if(plugin->out) data_in_input = 0;
309                 VirtualNode *virtual_plugin = create_plugin(plugin);
310                 vplugins.append(virtual_plugin);
311                 virtual_plugin->expand(duplicate, current_position);
312         }
313         return 0;
316 int VirtualNode::sort(ArrayList<VirtualNode*>*render_list)
318         int result = 0, total_result = 0;
320 //sleep(1);
321 //printf("VirtualNode::sort %p %p\n", real_module, real_plugin);
322         if(real_module)
323         {
324                 sort_as_module(render_list, result, total_result);
325         }
326         else
327         if(real_plugin)
328         {
329                 sort_as_plugin(render_list, result, total_result);
330         }
332         if(!result && total_result) result = total_result;
333 // if a plugin that wasn't patched out couldn't be rendered, try again
335         return result;
338 int VirtualNode::sort_as_module(ArrayList<VirtualNode*>*render_list, int &result, int &total_result)
341 // Render plugins first.
342         for(int i = 0; i < vplugins.total && !result; i++)
343         {
344 // stop when rendering can't continue without another higher level module
345                 result = vplugins.values[i]->sort(render_list);
347                 if(result && !vplugins.values[i]->out)
348                 {
349                         total_result = 1;
350                         result = 0;
351 // couldn't render the last plugin but it wasn't patched out so continue to next plugin
352                 }
353         }
354 //printf("VirtualNode::sort_as_module 3\n");
356 // All plugins rendered.
357 // Render this module.
358         if(render_count == 0 && !result)
359         {
360                 render_list->append(this);
361                 render_count++;
362                 result = 0;
363         }
364 //printf("VirtualNode::sort_as_module 4\n");
365         return 0;
368 int VirtualNode::sort_as_plugin(ArrayList<VirtualNode*>*render_list,
369         int &result, 
370         int &total_result)
372 // Plugin server does not exist at this point.
373 // need to know if plugin requires all inputs to be armed before rendering
374 //printf("VirtualNode::sort_as_plugin 1\n");
375         int multichannel = 0, singlechannel = 0;
376 //sleep(1);
379 // Referenced plugin is off
380         if(!attachment) return 0;
382 //printf("VirtualNode::sort_as_plugin 2 %p\n", attachment);
383         if(plugin_type == PLUGIN_STANDALONE || plugin_type == PLUGIN_SHAREDPLUGIN)
384         {
385                 multichannel = attachment->multichannel_shared(1);
386                 singlechannel = attachment->singlechannel();
387         }
389 //printf("VirtualNode::sort_as_plugin 3\n");
390         if(plugin_type == PLUGIN_STANDALONE && !multichannel)
391         {
392 // unshared single channel plugin
393 // render now
394 //printf("VirtualNode::sort_as_plugin 4\n");
395                 if(!render_count)
396                 {
397                         render_list->append(this);
398                         render_count++;
399                         result = 0;
400                 }
401 //printf("VirtualNode::sort_as_plugin 5\n");
402         }
403         else
404         if(plugin_type == PLUGIN_SHAREDPLUGIN || multichannel)
405         {
407 // Shared plugin
408 //printf("VirtualNode::sort_as_plugin 6\n");
409                 if(!render_count)
410                 {
411                         if(singlechannel)
412                         {
413 // shared single channel plugin
414 // render now
415 //printf("VirtualNode::sort_as_plugin 7\n");
416                                 render_list->append(this);
417 //printf("VirtualNode::sort_as_plugin 8\n");
418                                 render_count++;
419                                 result = 0;
420                         }
421                         else
422                         {
423 // shared multichannel plugin
424 // all buffers must be armed before rendering at the same time
425                                 if(!waiting_real_plugin)
426                                 {
427 //printf("VirtualNode::sort_as_plugin 9 %p\n", attachment);
428                                         waiting_real_plugin = 1;
429                                         if(real_plugin)
430                                                 result = attachment->sort(this);
431 //printf("VirtualNode::sort_as_plugin 10\n");
433                                         render_list->append(this);
434 //printf("VirtualNode::sort_as_plugin 11\n");
435                                         render_count++;
436                                 }
437                                 else
438                                 {
439 // Assume it was rendered later in the first pass
440                                         result = 0;
441                                 }
442                         }
443                 }
444         }
445 //printf("VirtualNode::sort_as_plugin 12\n");
446         return 0;
449 int VirtualNode::get_plugin_input(int &ring_buffer_in, int64_t &fragment_position_in,
450                                                         int &ring_buffer_out, int64_t &fragment_position_out,
451                                                         int ring_buffer, int64_t fragment_position)
453         if(input_is_master)
454         {
455                 ring_buffer_in = ring_buffer;
456                 fragment_position_in = fragment_position;
457         }
458         else
459         {
460                 ring_buffer_in = 0;
461                 fragment_position_in = 0;
462         }
464         if(output_is_master)
465         {
466                 ring_buffer_out = ring_buffer;
467                 fragment_position_out = fragment_position;
468         }
469         else
470         {
471                 ring_buffer_out = 0;
472                 fragment_position_out = 0;
473         }
476 int VirtualNode::render_as_plugin(int64_t source_len,
477                 int64_t source_position,
478                 int ring_buffer,
479                 int64_t fragment_position,
480                 int64_t fragment_len)
482 // need numbers for actual buffers
483         int direction = renderengine->command->get_direction();
484         int ring_buffer_in, ring_buffer_out;
485         int64_t fragment_position_in, fragment_position_out;
486         int multichannel = 0;
487 //printf("VirtualNode::render_as_plugin 1 %p\n", attachment);
489 // Abort if no plugin
490         if(!attachment ||
491                 !real_plugin ||
492                 !real_plugin->on) return 0;
494 //printf("VirtualNode::render_as_plugin 2\n");
499 void VirtualNode::get_mute_fragment(int64_t input_position,
500                                 int &mute_constant, 
501                                 int64_t &fragment_len, 
502                                 Autos *autos)
504         int64_t mute_len;
505         int direction = renderengine->command->get_direction();
507         IntAuto *prev_keyframe = 0;
508         IntAuto *next_keyframe = 0;
509         prev_keyframe = (IntAuto*)autos->get_prev_auto(input_position, direction, (Auto*)prev_keyframe);
510         next_keyframe = (IntAuto*)autos->get_next_auto(input_position, direction, (Auto*)next_keyframe);
512         if(direction == PLAY_FORWARD)
513         {
514 // Two distinct keyframes within range
515                 if(next_keyframe->position > prev_keyframe->position)
516                 {
517                         mute_constant = prev_keyframe->value;
519                         if(next_keyframe->position < input_position + fragment_len)
520                                 fragment_len = next_keyframe->position - input_position;
521                 }
522                 else
523 // One keyframe within range
524                 {
525                         mute_constant = prev_keyframe->value;
526                 }
527         }
528         else
529         {
530 // Two distinct keyframes within range
531                 if(next_keyframe->position < prev_keyframe->position)
532                 {
533                         mute_constant = next_keyframe->value;
535                         if(next_keyframe->position > input_position - fragment_len)
536                                 fragment_len = input_position - next_keyframe->position;
537                 }
538                 else
539 // One keyframe within range
540                 {
541                         mute_constant = next_keyframe->value;
542                 }
543         }
548 void VirtualNode::get_fade_automation(double &slope,
549         double &intercept,
550         int64_t input_position,
551         int64_t &slope_len,
552         Autos *autos)
554         int direction = renderengine->command->get_direction();
555         ((FloatAutos*)autos)->get_fade_automation(slope,
556                 intercept,
557                 input_position,
558                 slope_len,
559                 direction);
562 void VirtualNode::get_pan_automation(double &slope,
563         double &intercept,
564         int64_t input_position,
565         int64_t &slope_len,
566         Autos *autos,
567         int channel)
569         int direction = renderengine->command->get_direction();
570         intercept = 0;
571         slope = 0;
573         PanAuto *prev_keyframe = 0;
574         PanAuto *next_keyframe = 0;
575         prev_keyframe = (PanAuto*)autos->get_prev_auto(input_position, direction, (Auto*)prev_keyframe);
576         next_keyframe = (PanAuto*)autos->get_next_auto(input_position, direction, (Auto*)next_keyframe);
577         
578         if(direction == PLAY_FORWARD)
579         {
580 // Two distinct automation points within range
581                 if(next_keyframe->position > prev_keyframe->position)
582                 {
583                         slope = ((double)next_keyframe->values[channel] - prev_keyframe->values[channel]) / 
584                                 ((double)next_keyframe->position - prev_keyframe->position);
585                         intercept = ((double)input_position - prev_keyframe->position) * slope + 
586                                 prev_keyframe->values[channel];
588                         if(next_keyframe->position < input_position + slope_len)
589                                 slope_len = next_keyframe->position - input_position;
590                 }
591                 else
592 // One automation point within range
593                 {
594                         slope = 0;
595                         intercept = prev_keyframe->values[channel];
596                 }
597         }
598         else
599         {
600 // Two distinct automation points within range
601                 if(next_keyframe->position < prev_keyframe->position)
602                 {
603                         slope = ((double)next_keyframe->values[channel] - prev_keyframe->values[channel]) / 
604                                 ((double)next_keyframe->position - prev_keyframe->position);
605                         intercept = ((double)input_position - prev_keyframe->position) * slope + 
606                                 prev_keyframe->values[channel];
608                         if(next_keyframe->position > input_position - slope_len)
609                                 slope_len = input_position - next_keyframe->position;
610                 }
611                 else
612 // One automation point within range
613                 {
614                         slope = 0;
615                         intercept = next_keyframe->values[channel];
616                 }
617         }
621 int VirtualNode::init_automation(int &automate, 
622                                 double &constant, 
623                                 int64_t input_position,
624                                 int64_t buffer_len,
625                                 Autos *autos,
626                                 Auto **before, 
627                                 Auto **after)
629         
631         return autos->init_automation(buffer_position,
632                                 input_start, 
633                                 input_end, 
634                                 automate, 
635                                 constant, 
636                                 input_position,
637                                 buffer_len,
638                                 before, 
639                                 after,
640                                 reverse);
643 int VirtualNode::init_slope(Autos *autos, Auto **before, Auto **after)
645         return autos->init_slope(&current_auto,
646                                 slope_start, 
647                                 slope_value,
648                                 slope_position, 
649                                 input_start, 
650                                 input_end, 
651                                 before, 
652                                 after,
653                                 reverse);
656 int VirtualNode::get_slope(Autos *autos, int64_t buffer_len, int64_t buffer_position)
658         return autos->get_slope(&current_auto, 
659                                 slope_start, 
660                                 slope_end, 
661                                 slope_value, 
662                                 slope, 
663                                 buffer_len, 
664                                 buffer_position,
665                                 reverse);
668 int VirtualNode::advance_slope(Autos *autos)
670         return autos->advance_slope(&current_auto, 
671                                 slope_start, 
672                                 slope_value,
673                                 slope_position, 
674                                 reverse);