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 Track *track = real_module->track;
300 // Switch off if circular reference. This happens if a track is deleted.
301 if(this->real_module && track == this->real_module->track) return 1;
306 VirtualNode *virtual_module = create_module(plugin,
310 subnodes.append(virtual_module);
311 virtual_module->expand(duplicate, current_position);
317 int VirtualNode::attach_virtual_plugin(Plugin *plugin,
320 int64_t current_position)
322 // Get real plugin and test if it is on.
324 if(plugin->plugin_type == PLUGIN_SHAREDPLUGIN)
326 int real_module_number = plugin->shared_location.module;
327 int real_plugin_number = plugin->shared_location.plugin;
328 Module *real_module = vconsole->module_number(real_module_number);
331 AttachmentPoint *attachment = real_module->get_attachment(real_plugin_number);
334 Plugin *real_plugin = attachment->plugin;
335 if(!real_plugin || !real_plugin->on)
347 VirtualNode *virtual_plugin = create_plugin(plugin);
348 subnodes.append(virtual_plugin);
349 virtual_plugin->expand(duplicate, current_position);
354 VirtualNode* VirtualNode::get_previous_plugin(VirtualNode *current_node)
356 for(int i = 0; i < subnodes.total; i++)
358 // Assume plugin is on
359 if(subnodes.values[i] == current_node)
362 return subnodes.values[i - 1];
372 void VirtualNode::get_mute_fragment(int64_t input_position,
379 if(use_nudge) input_position += track->nudge;
381 IntAuto *prev_keyframe = 0;
382 IntAuto *next_keyframe = 0;
383 prev_keyframe = (IntAuto*)autos->get_prev_auto(input_position,
385 (Auto* &)prev_keyframe);
386 next_keyframe = (IntAuto*)autos->get_next_auto(input_position,
388 (Auto* &)next_keyframe);
390 if(direction == PLAY_FORWARD)
392 // Two distinct keyframes within range
393 if(next_keyframe->position > prev_keyframe->position)
395 mute_constant = prev_keyframe->value;
397 if(next_keyframe->position < input_position + fragment_len)
398 fragment_len = next_keyframe->position - input_position;
401 // One keyframe within range
403 mute_constant = prev_keyframe->value;
408 // Two distinct keyframes within range
409 if(next_keyframe->position < prev_keyframe->position)
411 mute_constant = next_keyframe->value;
413 if(next_keyframe->position > input_position - fragment_len)
414 fragment_len = input_position - next_keyframe->position;
417 // One keyframe within range
419 mute_constant = next_keyframe->value;