4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5 * Copyright (C) 2003-2016 Cinelerra CV contributors
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "attachmentpoint.h"
25 #include "automation.h"
27 #include "bcsignals.h"
28 #include "floatauto.h"
29 #include "floatautos.h"
32 #include "mainerror.h"
39 #include "pluginserver.h"
40 #include "renderengine.h"
42 #include "transition.h"
43 #include "transportque.h"
44 #include "virtualconsole.h"
45 #include "virtualnode.h"
47 VirtualNode::VirtualNode(RenderEngine *renderengine,
48 VirtualConsole *vconsole,
52 VirtualNode *parent_node)
54 this->renderengine = renderengine;
55 this->vconsole = vconsole;
56 this->real_module = real_module;
57 this->real_plugin = real_plugin;
59 this->parent_node = parent_node;
64 waiting_real_plugin = 0;
65 plugin_buffer_number = 0;
67 plugin_auto_before = plugin_auto_after = 0;
70 //printf("VirtualNode::VirtualNode 1\n");
73 VirtualNode::~VirtualNode()
75 subnodes.remove_all_objects();
76 //printf("VirtualNode::VirtualNode 2\n");
79 #define PRINT_INDENT for(int j = 0; j < indent; j++) printf(" ");
81 void VirtualNode::dump(int indent)
84 printf("VirtualNode %p title=%s real_module=%p %s\n",
92 printf(" Plugins total=%d\n", subnodes.total);
93 for(int i = 0; i < subnodes.total; i++)
95 subnodes.values[i]->dump(indent + 2);
101 printf(" Plugin %s\n", real_plugin->title);
105 int VirtualNode::expand(int persistent_plugins, int64_t current_position)
111 // TODO: need to use speed curve to determine chain for current position
114 // module needs to know where the input data for the next process is
115 if(debug) printf("VirtualNode::expand %d real_module=%p real_plugin=%p\n",
121 if(debug) printf("VirtualNode::expand %d\n", __LINE__);
122 expand_as_module(persistent_plugins, current_position);
127 // attach to a real plugin for a plugin
128 // plugin always takes data from input to output
129 if(debug) printf("VirtualNode::expand %d\n", __LINE__);
130 expand_as_plugin(persistent_plugins);
136 int VirtualNode::expand_as_module(int duplicate, int64_t current_position)
138 // create the plugins for this module
139 for(int i = 0; i < track->plugin_set.total; i++)
141 Plugin *plugin = track->get_current_plugin(current_position,
143 renderengine->command->get_direction(),
147 //printf("VirtualNode::expand_as_module %d plugin=%p\n", __LINE__, plugin);
148 int circular_reference = 0;
149 // Switch off if circular reference. This happens if a plugin set or a track is deleted.
150 if(plugin == real_plugin) circular_reference = 1;
152 // Switch off consecutive references to the same plugin
154 (plugin->plugin_type == PLUGIN_SHAREDPLUGIN ||
155 plugin->plugin_type == PLUGIN_SHAREDMODULE))
157 int real_module_number = plugin->shared_location.module;
158 int real_plugin_number = plugin->shared_location.plugin;
160 for(int j = i - 1; j >= 0; j--)
162 Plugin *prev_plugin = track->get_current_plugin(current_position,
164 renderengine->command->get_direction(),
168 prev_plugin->plugin_type == PLUGIN_SHAREDPLUGIN &&
169 plugin->plugin_type == PLUGIN_SHAREDPLUGIN)
171 int prev_module_number = prev_plugin->shared_location.module;
172 int prev_plugin_number = prev_plugin->shared_location.plugin;
173 if(real_module_number == prev_module_number &&
174 real_plugin_number == prev_plugin_number)
176 circular_reference = 1;
182 prev_plugin->plugin_type == PLUGIN_SHAREDMODULE &&
183 plugin->plugin_type == PLUGIN_SHAREDMODULE)
185 int prev_module_number = prev_plugin->shared_location.module;
186 if(real_module_number == prev_module_number)
188 circular_reference = 1;
195 if(circular_reference) continue;
197 if(plugin && plugin->on)
199 int plugin_type = plugin->plugin_type;
200 if(plugin_type == PLUGIN_SHAREDMODULE)
202 // plugin is a module
203 attach_virtual_module(plugin,
209 if(plugin_type == PLUGIN_SHAREDPLUGIN ||
210 plugin_type == PLUGIN_STANDALONE)
212 // plugin is a plugin
213 attach_virtual_plugin(plugin,
222 if(!parent_node) vconsole->append_exit_node(this);
223 //printf("VirtualNode::expand_as_module %d parent_node=%p\n", __LINE__, parent_node);
228 int VirtualNode::expand_as_plugin(int duplicate)
230 plugin_type = real_plugin->plugin_type;
232 if(plugin_type == PLUGIN_SHAREDPLUGIN)
234 // Attached to a shared plugin.
235 // Get the real real plugin it's attached to.
237 // Redirect the real_plugin to the shared plugin.
238 int real_module_number = real_plugin->shared_location.module;
239 int real_plugin_number = real_plugin->shared_location.plugin;
240 Module *real_module = vconsole->module_number(real_module_number);
242 // module references are absolute so may get the wrong data type track.
245 attachment = real_module->get_attachment(real_plugin_number);
246 // Attachment is NULL if off
249 real_plugin = attachment->plugin;
251 // Real plugin not on then null it.
252 if(!real_plugin || !real_plugin->on) real_plugin = 0;
262 if(plugin_type == PLUGIN_STANDALONE)
265 Module *module = vconsole->module_of(track);
267 attachment = module->attachment_of(real_plugin);
274 // Add to real plugin's list of virtual plugins for configuration updates
275 // and plugin_server initializations.
276 // Input and output are taken care of when the parent module creates this plugin.
277 // Get number for passing to render.
278 // real_plugin may become NULL after shared plugin test.
279 if(real_plugin && attachment)
282 plugin_buffer_number = attachment->attach_virtual_plugin(this);
291 int VirtualNode::check_circular(Track *track)
293 if( real_module && real_module->track == track ) return 1;
294 return !parent_node ? 0 : parent_node->check_circular(track);
297 int VirtualNode::attach_virtual_module(Plugin *plugin, int plugin_set_no,
298 int duplicate, int64_t current_position)
301 int shared_track_no = plugin->shared_location.module;
302 Module *real_module = vconsole->module_number(shared_track_no);
303 // If a track is deleted real_module is not found
304 if( !real_module ) return 1;
305 Track *real_track = real_module->track;
306 // Switch off if circular reference. This happens if a track is deleted.
307 if( check_circular(real_track) ) {
308 int plugin_track_no = plugin->track->get_item_number();
309 eprintf("circular references, track %d, plugin_set %d, plugin %d\n",
310 plugin_track_no, plugin_set_no, plugin->get_item_number());
313 VirtualNode *virtual_module = create_module(plugin, real_module, real_track);
315 subnodes.append(virtual_module);
316 virtual_module->expand(duplicate, current_position);
322 int VirtualNode::attach_virtual_plugin(Plugin *plugin,
325 int64_t current_position)
327 // Get real plugin and test if it is on.
329 if(plugin->plugin_type == PLUGIN_SHAREDPLUGIN)
331 int real_module_number = plugin->shared_location.module;
332 int real_plugin_number = plugin->shared_location.plugin;
333 Module *real_module = vconsole->module_number(real_module_number);
336 AttachmentPoint *attachment = real_module->get_attachment(real_plugin_number);
339 Plugin *real_plugin = attachment->plugin;
340 if(!real_plugin || !real_plugin->on)
352 VirtualNode *virtual_plugin = create_plugin(plugin);
353 subnodes.append(virtual_plugin);
354 virtual_plugin->expand(duplicate, current_position);
359 VirtualNode* VirtualNode::get_previous_plugin(VirtualNode *current_node)
361 for(int i = 0; i < subnodes.total; i++)
363 // Assume plugin is on
364 if(subnodes.values[i] == current_node)
367 return subnodes.values[i - 1];
377 void VirtualNode::get_mute_fragment(int64_t input_position,
384 if(use_nudge) input_position += track->nudge;
386 Auto *prev_keyframe = 0;
387 Auto *next_keyframe = 0;
388 prev_keyframe = autos->get_prev_auto(input_position,
389 direction, prev_keyframe);
390 next_keyframe = autos->get_next_auto(input_position,
391 direction, next_keyframe);
392 IntAuto *prev_int_auto = (IntAuto *)prev_keyframe;
393 IntAuto *next_int_auto = (IntAuto *)next_keyframe;
395 if(direction == PLAY_FORWARD)
397 // Two distinct keyframes within range
398 if(next_int_auto->position > prev_int_auto->position)
400 mute_constant = prev_int_auto->value;
402 if(next_int_auto->position < input_position + fragment_len)
403 fragment_len = next_int_auto->position - input_position;
406 // One keyframe within range
408 mute_constant = prev_int_auto->value;
413 // Two distinct keyframes within range
414 if(next_int_auto->position < prev_int_auto->position)
416 mute_constant = next_int_auto->value;
418 if(next_int_auto->position > input_position - fragment_len)
419 fragment_len = input_position - next_int_auto->position;
422 // One keyframe within range
424 mute_constant = next_int_auto->value;