4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
22 #include "attachmentpoint.h"
24 #include "automation.h"
26 #include "bcsignals.h"
27 #include "floatauto.h"
28 #include "floatautos.h"
37 #include "pluginserver.h"
38 #include "renderengine.h"
40 #include "transition.h"
41 #include "transportque.h"
42 #include "virtualconsole.h"
43 #include "virtualnode.h"
45 VirtualNode::VirtualNode(RenderEngine *renderengine,
46 VirtualConsole *vconsole,
50 VirtualNode *parent_node)
52 this->renderengine = renderengine;
53 this->vconsole = vconsole;
54 this->real_module = real_module;
55 this->real_plugin = real_plugin;
57 this->parent_node = parent_node;
62 waiting_real_plugin = 0;
63 plugin_buffer_number = 0;
65 plugin_auto_before = plugin_auto_after = 0;
68 //printf("VirtualNode::VirtualNode 1\n");
71 VirtualNode::~VirtualNode()
73 subnodes.remove_all_objects();
74 //printf("VirtualNode::VirtualNode 2\n");
77 #define PRINT_INDENT for(int j = 0; j < indent; j++) printf(" ");
79 void VirtualNode::dump(int indent)
82 printf("VirtualNode %p title=%s real_module=%p %s\n",
90 printf(" Plugins total=%d\n", subnodes.total);
91 for(int i = 0; i < subnodes.total; i++)
93 subnodes.values[i]->dump(indent + 2);
99 printf(" Plugin %s\n", real_plugin->title);
103 int VirtualNode::expand(int persistent_plugins, int64_t current_position)
109 // TODO: need to use speed curve to determine chain for current position
112 // module needs to know where the input data for the next process is
113 if(debug) printf("VirtualNode::expand %d real_module=%p real_plugin=%p\n",
119 if(debug) printf("VirtualNode::expand %d\n", __LINE__);
120 expand_as_module(persistent_plugins, current_position);
125 // attach to a real plugin for a plugin
126 // plugin always takes data from input to output
127 if(debug) printf("VirtualNode::expand %d\n", __LINE__);
128 expand_as_plugin(persistent_plugins);
134 int VirtualNode::expand_as_module(int duplicate, int64_t current_position)
136 // create the plugins for this module
137 for(int i = 0; i < track->plugin_set.total; i++)
139 Plugin *plugin = track->get_current_plugin(current_position,
141 renderengine->command->get_direction(),
145 //printf("VirtualNode::expand_as_module %d plugin=%p\n", __LINE__, plugin);
146 int circular_reference = 0;
147 // Switch off if circular reference. This happens if a plugin set or a track is deleted.
148 if(plugin == real_plugin) circular_reference = 1;
150 // Switch off consecutive references to the same plugin
152 (plugin->plugin_type == PLUGIN_SHAREDPLUGIN ||
153 plugin->plugin_type == PLUGIN_SHAREDMODULE))
155 int real_module_number = plugin->shared_location.module;
156 int real_plugin_number = plugin->shared_location.plugin;
158 for(int j = i - 1; j >= 0; j--)
160 Plugin *prev_plugin = track->get_current_plugin(current_position,
162 renderengine->command->get_direction(),
166 prev_plugin->plugin_type == PLUGIN_SHAREDPLUGIN &&
167 plugin->plugin_type == PLUGIN_SHAREDPLUGIN)
169 int prev_module_number = prev_plugin->shared_location.module;
170 int prev_plugin_number = prev_plugin->shared_location.plugin;
171 if(real_module_number == prev_module_number &&
172 real_plugin_number == prev_plugin_number)
174 circular_reference = 1;
180 prev_plugin->plugin_type == PLUGIN_SHAREDMODULE &&
181 plugin->plugin_type == PLUGIN_SHAREDMODULE)
183 int prev_module_number = prev_plugin->shared_location.module;
184 if(real_module_number == prev_module_number)
186 circular_reference = 1;
193 if(circular_reference) continue;
195 if(plugin && plugin->on)
197 int plugin_type = plugin->plugin_type;
198 if(plugin_type == PLUGIN_SHAREDMODULE)
200 // plugin is a module
201 attach_virtual_module(plugin,
207 if(plugin_type == PLUGIN_SHAREDPLUGIN ||
208 plugin_type == PLUGIN_STANDALONE)
210 // plugin is a plugin
211 attach_virtual_plugin(plugin,
220 if(!parent_node) vconsole->append_exit_node(this);
221 //printf("VirtualNode::expand_as_module %d parent_node=%p\n", __LINE__, parent_node);
226 int VirtualNode::expand_as_plugin(int duplicate)
228 plugin_type = real_plugin->plugin_type;
230 if(plugin_type == PLUGIN_SHAREDPLUGIN)
232 // Attached to a shared plugin.
233 // Get the real real plugin it's attached to.
235 // Redirect the real_plugin to the shared plugin.
236 int real_module_number = real_plugin->shared_location.module;
237 int real_plugin_number = real_plugin->shared_location.plugin;
238 Module *real_module = vconsole->module_number(real_module_number);
240 // module references are absolute so may get the wrong data type track.
243 attachment = real_module->get_attachment(real_plugin_number);
244 // Attachment is NULL if off
247 real_plugin = attachment->plugin;
249 // Real plugin not on then null it.
250 if(!real_plugin || !real_plugin->on) real_plugin = 0;
260 if(plugin_type == PLUGIN_STANDALONE)
263 Module *module = vconsole->module_of(track);
265 attachment = module->attachment_of(real_plugin);
272 // Add to real plugin's list of virtual plugins for configuration updates
273 // and plugin_server initializations.
274 // Input and output are taken care of when the parent module creates this plugin.
275 // Get number for passing to render.
276 // real_plugin may become NULL after shared plugin test.
277 if(real_plugin && attachment)
280 plugin_buffer_number = attachment->attach_virtual_plugin(this);
289 int VirtualNode::attach_virtual_module(Plugin *plugin,
292 int64_t current_position)
296 int real_module_number = plugin->shared_location.module;
297 Module *real_module = vconsole->module_number(real_module_number);
298 // If a track is deleted real_module is not found
299 if(!real_module) return 1;
301 Track *track = real_module->track;
303 // Switch off if circular reference. This happens if a track is deleted.
304 if(this->real_module && track == this->real_module->track) return 1;
309 VirtualNode *virtual_module = create_module(plugin,
313 subnodes.append(virtual_module);
314 virtual_module->expand(duplicate, current_position);
320 int VirtualNode::attach_virtual_plugin(Plugin *plugin,
323 int64_t current_position)
325 // Get real plugin and test if it is on.
327 if(plugin->plugin_type == PLUGIN_SHAREDPLUGIN)
329 int real_module_number = plugin->shared_location.module;
330 int real_plugin_number = plugin->shared_location.plugin;
331 Module *real_module = vconsole->module_number(real_module_number);
334 AttachmentPoint *attachment = real_module->get_attachment(real_plugin_number);
337 Plugin *real_plugin = attachment->plugin;
338 if(!real_plugin || !real_plugin->on)
350 VirtualNode *virtual_plugin = create_plugin(plugin);
351 subnodes.append(virtual_plugin);
352 virtual_plugin->expand(duplicate, current_position);
357 VirtualNode* VirtualNode::get_previous_plugin(VirtualNode *current_node)
359 for(int i = 0; i < subnodes.total; i++)
361 // Assume plugin is on
362 if(subnodes.values[i] == current_node)
365 return subnodes.values[i - 1];
375 void VirtualNode::get_mute_fragment(int64_t input_position,
382 if(use_nudge) input_position += track->nudge;
384 Auto *prev_keyframe = 0;
385 Auto *next_keyframe = 0;
386 prev_keyframe = autos->get_prev_auto(input_position,
387 direction, prev_keyframe);
388 next_keyframe = autos->get_next_auto(input_position,
389 direction, next_keyframe);
390 IntAuto *prev_int_auto = (IntAuto *)prev_keyframe;
391 IntAuto *next_int_auto = (IntAuto *)next_keyframe;
393 if(direction == PLAY_FORWARD)
395 // Two distinct keyframes within range
396 if(next_int_auto->position > prev_int_auto->position)
398 mute_constant = prev_int_auto->value;
400 if(next_int_auto->position < input_position + fragment_len)
401 fragment_len = next_int_auto->position - input_position;
404 // One keyframe within range
406 mute_constant = prev_int_auto->value;
411 // Two distinct keyframes within range
412 if(next_int_auto->position < prev_int_auto->position)
414 mute_constant = next_int_auto->value;
416 if(next_int_auto->position > input_position - fragment_len)
417 fragment_len = input_position - next_int_auto->position;
420 // One keyframe within range
422 mute_constant = next_int_auto->value;