r499: This commit was manufactured by cvs2svn to create tag 'r1_2_1-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / virtualnode.C
bloba9f2c49693d08a7c02a6bd59863310caa036b878
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_node)
30         this->renderengine = renderengine;
31         this->vconsole = vconsole;
32         this->real_module = real_module;
33         this->real_plugin = real_plugin;
34         this->track = track;
35         this->parent_node = parent_node;
36         render_count = 0;
37         plugin_type = 0;
38         waiting_real_plugin = 0;
39         plugin_buffer_number = 0;
40         plugin_autos = 0;
41         plugin_auto_before = plugin_auto_after = 0;
42         attachment = 0;
43         is_exit = 0;
44 //printf("VirtualNode::VirtualNode 1\n");
47 VirtualNode::~VirtualNode()
49         subnodes.remove_all_objects();
50 //printf("VirtualNode::VirtualNode 2\n");
53 #define PRINT_INDENT for(int j = 0; j < indent; j++) printf(" ");
55 void VirtualNode::dump(int indent)
57         PRINT_INDENT
58         printf("VirtualNode %p title=%s %s\n", 
59                 this, 
60                 track->title,
61                 is_exit ? "*" : " ");
62         if(real_module)
63         {
64                 PRINT_INDENT
65                 printf(" Plugins total=%d\n", subnodes.total);
66                 for(int i = 0; i < subnodes.total; i++)
67                 {
68                         subnodes.values[i]->dump(indent + 2);
69                 }
70         }
71         else
72         if(real_plugin)
73         {
74                 printf("    Plugin %s\n", real_plugin->title);
75         }
78 int VirtualNode::expand(int persistent_plugins, int64_t current_position)
80 // module needs to know where the input data for the next process is
81         if(real_module)
82         {
83                 expand_as_module(persistent_plugins, current_position);
84         }
85         else
86         if(real_plugin)
87         {
88 // attach to a real plugin for a plugin
89 // plugin always takes data from input to output
90                 expand_as_plugin(persistent_plugins);
91         }
93         return 0;
96 int VirtualNode::expand_as_module(int duplicate, int64_t current_position)
98         Transition *transition = 0;
100 // create the plugins for this module
101         for(int i = 0; i < track->plugin_set.total; i++)
102         {
103                 Plugin *plugin = track->get_current_plugin(current_position, 
104                         i, 
105                         renderengine->command->get_direction(),
106                         0,
107                         1);
109 // Switch off if circular reference.  This happens if a plugin set or a track is deleted.
110                 if(plugin == real_plugin) continue;
113                 if(plugin)
114                 {
115                         if(plugin->on)
116                         {
117                                 int plugin_type = plugin->plugin_type;
118                                 if(plugin_type == PLUGIN_SHAREDMODULE)
119                                 {
120 // plugin is a module
121                                         attach_virtual_module(plugin,
122                                                 i, 
123                                                 duplicate, 
124                                                 current_position);
125                                 }
126                                 else
127                                 if(plugin_type == PLUGIN_SHAREDPLUGIN ||
128                                         plugin_type == PLUGIN_STANDALONE)
129                                 {
130 // plugin is a plugin
131                                         attach_virtual_plugin(plugin, 
132                                                 i, 
133                                                 duplicate, 
134                                                 current_position);
135                                 }
136                         }
137                 }
138         }
141         if(!parent_node) vconsole->append_exit_node(this);
143         return 0;
146 int VirtualNode::expand_as_plugin(int duplicate)
148         plugin_type = real_plugin->plugin_type;
150         if(plugin_type == PLUGIN_SHAREDPLUGIN)
151         {
152 // Attached to a shared plugin.
153 // Get the real real plugin it's attached to.
155 // Redirect the real_plugin to the shared plugin.
156                 int real_module_number = real_plugin->shared_location.module;
157                 int real_plugin_number = real_plugin->shared_location.plugin;
158                 Module *real_module = 0;
161                 real_module = vconsole->module_number(real_module_number);
162 // module references are absolute so may get the wrong data type track.
163                 if(real_module &&
164                         real_plugin_number < real_module->total_attachments)
165                 {
166                         attachment = real_module->attachments[real_plugin_number];
167 // Attachment is NULL if off
168                         if(attachment)
169                         {
170                                 real_plugin = attachment->plugin;
172 // Real plugin not on then null it.
173                                 if(!real_plugin || !real_plugin->on) real_plugin = 0;
174                         }
175                         else
176                                 real_plugin = 0;
177                 }
178                 else
179                         real_plugin = 0;
180         }
187         if(plugin_type == PLUGIN_STANDALONE)
188         {
189 // Get plugin server
190                 Module *module = vconsole->module_of(track);
192                 attachment = module->attachment_of(real_plugin);
193         }
199 // Add to real plugin's list of virtual plugins for configuration updates
200 // and plugin_server initializations.
201 // Input and output are taken care of when the parent module creates this plugin.
202 // Get number for passing to render.
203 // real_plugin may become NULL after shared plugin test.
204         if(real_plugin && attachment)
205         {
206                 if(attachment)
207                         plugin_buffer_number = attachment->attach_virtual_plugin(this);
208         }
213         return 0;
216 int VirtualNode::attach_virtual_module(Plugin *plugin, 
217         int plugin_number, 
218         int duplicate, 
219         int64_t current_position)
221         if(plugin->on)
222         {
223 //printf("VirtualNode::attach_virtual_module 1 %p\n", plugin);
224                 int real_module_number = plugin->shared_location.module;
225 //printf("VirtualNode::attach_virtual_module 1\n");
226                 Module *real_module = vconsole->module_number(real_module_number);
227 //printf("VirtualNode::attach_virtual_module 1\n");
229 // If a track is deleted real_module is not found
230                 if(!real_module) return 1;
232                 Track *track = real_module->track;
234 // Switch off if circular reference.  This happens if a track is deleted.
235                 if(track == this->real_module->track) return 1;
240                 VirtualNode *virtual_module = create_module(plugin,
241                         real_module,
242                         track);
243 //printf("VirtualNode::attach_virtual_module 1\n");
245                 subnodes.append(virtual_module);
246 //printf("VirtualNode::attach_virtual_module 1\n");
247                 virtual_module->expand(duplicate, current_position);
248 //printf("VirtualNode::attach_virtual_module 2\n");
249         }
251         return 0;
254 int VirtualNode::attach_virtual_plugin(Plugin *plugin, 
255         int plugin_number, 
256         int duplicate, 
257         int64_t current_position)
259         if(plugin->on)
260         {
261                 VirtualNode *virtual_plugin = create_plugin(plugin);
262                 subnodes.append(virtual_plugin);
263                 virtual_plugin->expand(duplicate, current_position);
264         }
265         return 0;
268 VirtualNode* VirtualNode::get_previous_plugin(VirtualNode *current_node)
270         for(int i = 0; i < subnodes.total; i++)
271         {
272 // Assume plugin is on
273                 if(subnodes.values[i] == current_node)
274                 {
275                         if(i > 0) 
276                                 return subnodes.values[i - 1];
277                         else
278                                 return 0;
279                 }
280         }
281         return 0;
284 // int VirtualNode::sort(ArrayList<VirtualNode*>*render_list)
285 // {
286 //      int result = 0, total_result = 0;
287 // 
288 // //sleep(1);
289 // //printf("VirtualNode::sort %p %p\n", real_module, real_plugin);
290 //      if(real_module)
291 //      {
292 //              sort_as_module(render_list, result, total_result);
293 //      }
294 //      else
295 //      if(real_plugin)
296 //      {
297 //              sort_as_plugin(render_list, result, total_result);
298 //      }
299 // 
300 //      if(!result && total_result) result = total_result;
301 // // if a plugin that wasn't patched out couldn't be rendered, try again
302 // 
303 //      return result;
304 // }
306 // int VirtualNode::sort_as_module(ArrayList<VirtualNode*>*render_list, int &result, int &total_result)
307 // {
308 // 
309 // // Render plugins first.
310 //      for(int i = 0; i < subnodes.total && !result; i++)
311 //      {
312 // // stop when rendering can't continue without another higher level module
313 //              result = subnodes.values[i]->sort(render_list);
314 // 
315 //              if(result && !subnodes.values[i]->out)
316 //              {
317 //                      total_result = 1;
318 //                      result = 0;
319 // // couldn't render the last plugin but it wasn't patched out so continue to next plugin
320 //              }
321 //      }
322 // //printf("VirtualNode::sort_as_module 3\n");
323 // 
324 // // All plugins rendered.
325 // // Render this module.
326 //      if(render_count == 0 && !result)
327 //      {
328 //              render_list->append(this);
329 //              render_count++;
330 //              result = 0;
331 //      }
332 // //printf("VirtualNode::sort_as_module 4\n");
333 //      return 0;
334 // }
336 // int VirtualNode::sort_as_plugin(ArrayList<VirtualNode*>*render_list,
337 //      int &result, 
338 //      int &total_result)
339 // {
340 // // Plugin server does not exist at this point.
341 // // need to know if plugin requires all inputs to be armed before rendering
342 // //printf("VirtualNode::sort_as_plugin 1\n");
343 //      int multichannel = 0, singlechannel = 0;
344 // //sleep(1);
345 // 
346 // 
347 // // Referenced plugin is off
348 //      if(!attachment) return 0;
349 // 
350 // //printf("VirtualNode::sort_as_plugin 2 %p\n", attachment);
351 //      if(plugin_type == PLUGIN_STANDALONE || plugin_type == PLUGIN_SHAREDPLUGIN)
352 //      {
353 //              multichannel = attachment->multichannel_shared(1);
354 //              singlechannel = attachment->singlechannel();
355 //      }
356 // 
357 // //printf("VirtualNode::sort_as_plugin 3\n");
358 //      if(plugin_type == PLUGIN_STANDALONE && !multichannel)
359 //      {
360 // // unshared single channel plugin
361 // // render now
362 // //printf("VirtualNode::sort_as_plugin 4\n");
363 //              if(!render_count)
364 //              {
365 //                      render_list->append(this);
366 //                      render_count++;
367 //                      result = 0;
368 //              }
369 // //printf("VirtualNode::sort_as_plugin 5\n");
370 //      }
371 //      else
372 //      if(plugin_type == PLUGIN_SHAREDPLUGIN || multichannel)
373 //      {
374 // 
375 // // Shared plugin
376 // //printf("VirtualNode::sort_as_plugin 6\n");
377 //              if(!render_count)
378 //              {
379 //                      if(singlechannel)
380 //                      {
381 // // shared single channel plugin
382 // // render now
383 // //printf("VirtualNode::sort_as_plugin 7\n");
384 //                              render_list->append(this);
385 // //printf("VirtualNode::sort_as_plugin 8\n");
386 //                              render_count++;
387 //                              result = 0;
388 //                      }
389 //                      else
390 //                      {
391 // // shared multichannel plugin
392 // // all buffers must be armed before rendering at the same time
393 //                              if(!waiting_real_plugin)
394 //                              {
395 // //printf("VirtualNode::sort_as_plugin 9 %p\n", attachment);
396 //                                      waiting_real_plugin = 1;
397 //                                      if(real_plugin)
398 //                                              result = attachment->sort(this);
399 // //printf("VirtualNode::sort_as_plugin 10\n");
400 // 
401 //                                      render_list->append(this);
402 // //printf("VirtualNode::sort_as_plugin 11\n");
403 //                                      render_count++;
404 //                              }
405 //                              else
406 //                              {
407 // // Assume it was rendered later in the first pass
408 //                                      result = 0;
409 //                              }
410 //                      }
411 //              }
412 //      }
413 // //printf("VirtualNode::sort_as_plugin 12\n");
414 //      return 0;
415 // }
417 // int VirtualNode::get_plugin_input(int &ring_buffer_in, int64_t &fragment_position_in,
418 //                                                      int &ring_buffer_out, int64_t &fragment_position_out,
419 //                                                      int ring_buffer, int64_t fragment_position)
420 // {
421 //      if(input_is_master)
422 //      {
423 //              ring_buffer_in = ring_buffer;
424 //              fragment_position_in = fragment_position;
425 //      }
426 //      else
427 //      {
428 //              ring_buffer_in = 0;
429 //              fragment_position_in = 0;
430 //      }
431 // 
432 //      if(output_is_master)
433 //      {
434 //              ring_buffer_out = ring_buffer;
435 //              fragment_position_out = fragment_position;
436 //      }
437 //      else
438 //      {
439 //              ring_buffer_out = 0;
440 //              fragment_position_out = 0;
441 //      }
442 // }
444 // int VirtualNode::render_as_plugin(int64_t source_len,
445 //              int64_t source_position,
446 //              int ring_buffer,
447 //              int64_t fragment_position,
448 //              int64_t fragment_len)
449 // {
450 // // need numbers for actual buffers
451 //      int direction = renderengine->command->get_direction();
452 //      int ring_buffer_in, ring_buffer_out;
453 //      int64_t fragment_position_in, fragment_position_out;
454 //      int multichannel = 0;
455 // //printf("VirtualNode::render_as_plugin 1 %p\n", attachment);
456 // 
457 // // Abort if no plugin
458 //      if(!attachment ||
459 //              !real_plugin ||
460 //              !real_plugin->on) return 0;
461 // 
462 // //printf("VirtualNode::render_as_plugin 2\n");
463 // }
464 // 
467 void VirtualNode::get_mute_fragment(int64_t input_position,
468                                 int &mute_constant, 
469                                 int &fragment_len, 
470                                 Autos *autos,
471                                 int direction,
472                                 int use_nudge)
474         if(use_nudge) input_position += track->nudge;
476         IntAuto *prev_keyframe = 0;
477         IntAuto *next_keyframe = 0;
478         prev_keyframe = (IntAuto*)autos->get_prev_auto(input_position, direction, (Auto*&)prev_keyframe);
479         next_keyframe = (IntAuto*)autos->get_next_auto(input_position, direction, (Auto*&)next_keyframe);
481         if(direction == PLAY_FORWARD)
482         {
483 // Two distinct keyframes within range
484                 if(next_keyframe->position > prev_keyframe->position)
485                 {
486                         mute_constant = prev_keyframe->value;
488                         if(next_keyframe->position < input_position + fragment_len)
489                                 fragment_len = next_keyframe->position - input_position;
490                 }
491                 else
492 // One keyframe within range
493                 {
494                         mute_constant = prev_keyframe->value;
495                 }
496         }
497         else
498         {
499 // Two distinct keyframes within range
500                 if(next_keyframe->position < prev_keyframe->position)
501                 {
502                         mute_constant = next_keyframe->value;
504                         if(next_keyframe->position > input_position - fragment_len)
505                                 fragment_len = input_position - next_keyframe->position;
506                 }
507                 else
508 // One keyframe within range
509                 {
510                         mute_constant = next_keyframe->value;
511                 }
512         }
517 // void VirtualNode::get_fade_automation(double &slope,
518 //      double &intercept,
519 //      int64_t input_position,
520 //      int64_t &slope_len,
521 //      Autos *autos)
522 // {
523 //      int direction = renderengine->command->get_direction();
524 //      ((FloatAutos*)autos)->get_fade_automation(slope,
525 //              intercept,
526 //              input_position,
527 //              slope_len,
528 //              direction);
529 // }
532 // int VirtualNode::init_automation(int &automate, 
533 //                              double &constant, 
534 //                              int64_t input_position,
535 //                              int64_t buffer_len,
536 //                              Autos *autos,
537 //                              Auto **before, 
538 //                              Auto **after)
539 // {
540 //      return autos->init_automation(buffer_position,
541 //                              input_start, 
542 //                              input_end, 
543 //                              automate, 
544 //                              constant, 
545 //                              input_position,
546 //                              buffer_len,
547 //                              before, 
548 //                              after,
549 //                              reverse);
550 // }
552 // int VirtualNode::init_slope(Autos *autos, Auto **before, Auto **after)
553 // {
554 //      return autos->init_slope(&current_auto,
555 //                              slope_start, 
556 //                              slope_value,
557 //                              slope_position, 
558 //                              input_start, 
559 //                              input_end, 
560 //                              before, 
561 //                              after,
562 //                              reverse);
563 // }
565 // int VirtualNode::get_slope(Autos *autos, int64_t buffer_len, int64_t buffer_position)
566 // {
567 //      return autos->get_slope(&current_auto, 
568 //                              slope_start, 
569 //                              slope_end, 
570 //                              slope_value, 
571 //                              slope, 
572 //                              buffer_len, 
573 //                              buffer_position,
574 //                              reverse);
575 // }
576 // 
577 // int VirtualNode::advance_slope(Autos *autos)
578 // {
579 //      return autos->advance_slope(&current_auto, 
580 //                              slope_start, 
581 //                              slope_value,
582 //                              slope_position, 
583 //                              reverse);
584 // }