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"
31 #include "mainerror.h"
38 #include "pluginserver.h"
39 #include "renderengine.h"
41 #include "transition.h"
42 #include "transportque.h"
43 #include "virtualconsole.h"
44 #include "virtualnode.h"
46 VirtualNode::VirtualNode(RenderEngine *renderengine,
47 VirtualConsole *vconsole,
51 VirtualNode *parent_node)
53 this->renderengine = renderengine;
54 this->vconsole = vconsole;
55 this->real_module = real_module;
56 this->real_plugin = real_plugin;
58 this->parent_node = parent_node;
63 waiting_real_plugin = 0;
64 plugin_buffer_number = 0;
66 plugin_auto_before = plugin_auto_after = 0;
69 //printf("VirtualNode::VirtualNode 1\n");
72 VirtualNode::~VirtualNode()
74 subnodes.remove_all_objects();
75 //printf("VirtualNode::VirtualNode 2\n");
78 #define PRINT_INDENT for(int j = 0; j < indent; j++) printf(" ");
80 void VirtualNode::dump(int indent)
83 printf("VirtualNode %p title=%s real_module=%p %s\n",
91 printf(" Plugins total=%d\n", subnodes.total);
92 for(int i = 0; i < subnodes.total; i++)
94 subnodes.values[i]->dump(indent + 2);
100 printf(" Plugin %s\n", real_plugin->title);
104 int VirtualNode::expand(int persistent_plugins, int64_t current_position)
110 // TODO: need to use speed curve to determine chain for current position
113 // module needs to know where the input data for the next process is
114 if(debug) printf("VirtualNode::expand %d real_module=%p real_plugin=%p\n",
120 if(debug) printf("VirtualNode::expand %d\n", __LINE__);
121 expand_as_module(persistent_plugins, current_position);
126 // attach to a real plugin for a plugin
127 // plugin always takes data from input to output
128 if(debug) printf("VirtualNode::expand %d\n", __LINE__);
129 expand_as_plugin(persistent_plugins);
135 int VirtualNode::expand_as_module(int duplicate, int64_t current_position)
137 // create the plugins for this module
138 for(int i = 0; i < track->plugin_set.total; i++)
140 Plugin *plugin = track->get_current_plugin(current_position,
142 renderengine->command->get_direction(),
146 //printf("VirtualNode::expand_as_module %d plugin=%p\n", __LINE__, plugin);
147 int circular_reference = 0;
148 // Switch off if circular reference. This happens if a plugin set or a track is deleted.
149 if(plugin == real_plugin) circular_reference = 1;
151 // Switch off consecutive references to the same plugin
153 (plugin->plugin_type == PLUGIN_SHAREDPLUGIN ||
154 plugin->plugin_type == PLUGIN_SHAREDMODULE))
156 int real_module_number = plugin->shared_location.module;
157 int real_plugin_number = plugin->shared_location.plugin;
159 for(int j = i - 1; j >= 0; j--)
161 Plugin *prev_plugin = track->get_current_plugin(current_position,
163 renderengine->command->get_direction(),
167 prev_plugin->plugin_type == PLUGIN_SHAREDPLUGIN &&
168 plugin->plugin_type == PLUGIN_SHAREDPLUGIN)
170 int prev_module_number = prev_plugin->shared_location.module;
171 int prev_plugin_number = prev_plugin->shared_location.plugin;
172 if(real_module_number == prev_module_number &&
173 real_plugin_number == prev_plugin_number)
175 circular_reference = 1;
181 prev_plugin->plugin_type == PLUGIN_SHAREDMODULE &&
182 plugin->plugin_type == PLUGIN_SHAREDMODULE)
184 int prev_module_number = prev_plugin->shared_location.module;
185 if(real_module_number == prev_module_number)
187 circular_reference = 1;
194 if(circular_reference) continue;
196 if(plugin && plugin->on)
198 int plugin_type = plugin->plugin_type;
199 if(plugin_type == PLUGIN_SHAREDMODULE)
201 // plugin is a module
202 attach_virtual_module(plugin,
208 if(plugin_type == PLUGIN_SHAREDPLUGIN ||
209 plugin_type == PLUGIN_STANDALONE)
211 // plugin is a plugin
212 attach_virtual_plugin(plugin,
221 if(!parent_node) vconsole->append_exit_node(this);
222 //printf("VirtualNode::expand_as_module %d parent_node=%p\n", __LINE__, parent_node);
227 int VirtualNode::expand_as_plugin(int duplicate)
229 plugin_type = real_plugin->plugin_type;
231 if(plugin_type == PLUGIN_SHAREDPLUGIN)
233 // Attached to a shared plugin.
234 // Get the real real plugin it's attached to.
236 // Redirect the real_plugin to the shared plugin.
237 int real_module_number = real_plugin->shared_location.module;
238 int real_plugin_number = real_plugin->shared_location.plugin;
239 Module *real_module = vconsole->module_number(real_module_number);
241 // module references are absolute so may get the wrong data type track.
244 attachment = real_module->get_attachment(real_plugin_number);
245 // Attachment is NULL if off
248 real_plugin = attachment->plugin;
250 // Real plugin not on then null it.
251 if(!real_plugin || !real_plugin->on) real_plugin = 0;
261 if(plugin_type == PLUGIN_STANDALONE)
264 Module *module = vconsole->module_of(track);
266 attachment = module->attachment_of(real_plugin);
273 // Add to real plugin's list of virtual plugins for configuration updates
274 // and plugin_server initializations.
275 // Input and output are taken care of when the parent module creates this plugin.
276 // Get number for passing to render.
277 // real_plugin may become NULL after shared plugin test.
278 if(real_plugin && attachment)
281 plugin_buffer_number = attachment->attach_virtual_plugin(this);
290 int VirtualNode::check_circular(Track *track)
292 if( real_module && real_module->track == track ) return 1;
293 return !parent_node ? 0 : parent_node->check_circular(track);
296 int VirtualNode::attach_virtual_module(Plugin *plugin, int plugin_set_no,
297 int duplicate, int64_t current_position)
300 int shared_track_no = plugin->shared_location.module;
301 Module *real_module = vconsole->module_number(shared_track_no);
302 // If a track is deleted real_module is not found
303 if( !real_module ) return 1;
304 Track *real_track = real_module->track;
305 // Switch off if circular reference. This happens if a track is deleted.
306 if( check_circular(real_track) ) {
307 int plugin_track_no = plugin->track->get_item_number();
308 eprintf("circular references, track %d, plugin_set %d, plugin %d\n",
309 plugin_track_no, plugin_set_no, plugin->get_item_number());
312 VirtualNode *virtual_module = create_module(plugin, real_module, real_track);
314 subnodes.append(virtual_module);
315 virtual_module->expand(duplicate, current_position);
321 int VirtualNode::attach_virtual_plugin(Plugin *plugin,
324 int64_t current_position)
326 // Get real plugin and test if it is on.
328 if(plugin->plugin_type == PLUGIN_SHAREDPLUGIN)
330 int real_module_number = plugin->shared_location.module;
331 int real_plugin_number = plugin->shared_location.plugin;
332 Module *real_module = vconsole->module_number(real_module_number);
335 AttachmentPoint *attachment = real_module->get_attachment(real_plugin_number);
338 Plugin *real_plugin = attachment->plugin;
339 if(!real_plugin || !real_plugin->on)
351 VirtualNode *virtual_plugin = create_plugin(plugin);
352 subnodes.append(virtual_plugin);
353 virtual_plugin->expand(duplicate, current_position);
358 VirtualNode* VirtualNode::get_previous_plugin(VirtualNode *current_node)
360 for(int i = 0; i < subnodes.total; i++)
362 // Assume plugin is on
363 if(subnodes.values[i] == current_node)
366 return subnodes.values[i - 1];
376 void VirtualNode::get_mute_fragment(int64_t input_position,
383 if(use_nudge) input_position += track->nudge;
385 Auto *prev_keyframe = 0;
386 Auto *next_keyframe = 0;
387 prev_keyframe = autos->get_prev_auto(input_position,
388 direction, prev_keyframe);
389 next_keyframe = autos->get_next_auto(input_position,
390 direction, next_keyframe);
391 IntAuto *prev_int_auto = (IntAuto *)prev_keyframe;
392 IntAuto *next_int_auto = (IntAuto *)next_keyframe;
394 if(direction == PLAY_FORWARD)
396 // Two distinct keyframes within range
397 if(next_int_auto->position > prev_int_auto->position)
399 mute_constant = prev_int_auto->value;
401 if(next_int_auto->position < input_position + fragment_len)
402 fragment_len = next_int_auto->position - input_position;
405 // One keyframe within range
407 mute_constant = prev_int_auto->value;
412 // Two distinct keyframes within range
413 if(next_int_auto->position < prev_int_auto->position)
415 mute_constant = next_int_auto->value;
417 if(next_int_auto->position > input_position - fragment_len)
418 fragment_len = input_position - next_int_auto->position;
421 // One keyframe within range
423 mute_constant = next_int_auto->value;