r956: README.BUILD - add more library recommendations
[cinelerra_cv/ct.git] / cinelerra / virtualnode.C
blobe9a6d1472040613a3b8aed3d3e167d039b4eafb2
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 real_module=%p %s\n", 
59                 this, 
60                 track->title,
61                 real_module,
62                 is_exit ? "*" : " ");
63         if(real_module)
64         {
65                 PRINT_INDENT
66                 printf(" Plugins total=%d\n", subnodes.total);
67                 for(int i = 0; i < subnodes.total; i++)
68                 {
69                         subnodes.values[i]->dump(indent + 2);
70                 }
71         }
72         else
73         if(real_plugin)
74         {
75                 printf("    Plugin %s\n", real_plugin->title);
76         }
79 int VirtualNode::expand(int persistent_plugins, int64_t current_position)
81 // module needs to know where the input data for the next process is
82         if(real_module)
83         {
84                 expand_as_module(persistent_plugins, current_position);
85         }
86         else
87         if(real_plugin)
88         {
89 // attach to a real plugin for a plugin
90 // plugin always takes data from input to output
91                 expand_as_plugin(persistent_plugins);
92         }
94         return 0;
97 int VirtualNode::expand_as_module(int duplicate, int64_t current_position)
99         Transition *transition = 0;
101 // create the plugins for this module
102         for(int i = 0; i < track->plugin_set.total; i++)
103         {
104                 Plugin *plugin = track->get_current_plugin(current_position, 
105                         i, 
106                         renderengine->command->get_direction(),
107                         0,
108                         1);
110 // Switch off if circular reference.  This happens if a plugin set or a track is deleted.
111                 if(plugin == real_plugin) continue;
114                 if(plugin && plugin->on)
115                 {
116                         int plugin_type = plugin->plugin_type;
117                         if(plugin_type == PLUGIN_SHAREDMODULE)
118                         {
119 // plugin is a module
120                                 attach_virtual_module(plugin,
121                                         i, 
122                                         duplicate, 
123                                         current_position);
124                         }
125                         else
126                         if(plugin_type == PLUGIN_SHAREDPLUGIN ||
127                                 plugin_type == PLUGIN_STANDALONE)
128                         {
129 // plugin is a plugin
130                                 attach_virtual_plugin(plugin, 
131                                         i, 
132                                         duplicate, 
133                                         current_position);
134                         }
135                 }
136         }
139         if(!parent_node) vconsole->append_exit_node(this);
141         return 0;
144 int VirtualNode::expand_as_plugin(int duplicate)
146         plugin_type = real_plugin->plugin_type;
148         if(plugin_type == PLUGIN_SHAREDPLUGIN)
149         {
150 // Attached to a shared plugin.
151 // Get the real real plugin it's attached to.
153 // Redirect the real_plugin to the shared plugin.
154                 int real_module_number = real_plugin->shared_location.module;
155                 int real_plugin_number = real_plugin->shared_location.plugin;
156                 Module *real_module = vconsole->module_number(real_module_number);
157                 real_plugin = 0;
158 // module references are absolute so may get the wrong data type track.
159                 if(real_module)
160                 {
161                         attachment = real_module->get_attachment(real_plugin_number);
162 // Attachment is NULL if off
163                         if(attachment)
164                         {
165                                 real_plugin = attachment->plugin;
167 // Real plugin not on then null it.
168                                 if(!real_plugin || !real_plugin->on) real_plugin = 0;
169                         }
170                 }
171         }
178         if(plugin_type == PLUGIN_STANDALONE)
179         {
180 // Get plugin server
181                 Module *module = vconsole->module_of(track);
183                 attachment = module->attachment_of(real_plugin);
184         }
190 // Add to real plugin's list of virtual plugins for configuration updates
191 // and plugin_server initializations.
192 // Input and output are taken care of when the parent module creates this plugin.
193 // Get number for passing to render.
194 // real_plugin may become NULL after shared plugin test.
195         if(real_plugin && attachment)
196         {
197                 if(attachment)
198                         plugin_buffer_number = attachment->attach_virtual_plugin(this);
199         }
204         return 0;
207 int VirtualNode::attach_virtual_module(Plugin *plugin, 
208         int plugin_number, 
209         int duplicate, 
210         int64_t current_position)
212         if(plugin->on)
213         {
214                 int real_module_number = plugin->shared_location.module;
215                 Module *real_module = vconsole->module_number(real_module_number);
216 // If a track is deleted real_module is not found
217                 if(!real_module) return 1;
219                 Track *track = real_module->track;
221 // Switch off if circular reference.  This happens if a track is deleted.
222                 if(this->real_module && track == this->real_module->track) return 1;
227                 VirtualNode *virtual_module = create_module(plugin,
228                         real_module,
229                         track);
231                 subnodes.append(virtual_module);
232                 virtual_module->expand(duplicate, current_position);
233         }
235         return 0;
238 int VirtualNode::attach_virtual_plugin(Plugin *plugin, 
239         int plugin_number, 
240         int duplicate, 
241         int64_t current_position)
243 // Get real plugin and test if it is on.
244         int is_on = 1;
245         if(plugin->plugin_type == PLUGIN_SHAREDPLUGIN)
246         {
247                 int real_module_number = plugin->shared_location.module;
248                 int real_plugin_number = plugin->shared_location.plugin;
249                 Module *real_module = vconsole->module_number(real_module_number);
250                 if(real_module)
251                 {
252                         AttachmentPoint *attachment = real_module->get_attachment(real_plugin_number);
253                         if(attachment)
254                         {
255                                 Plugin *real_plugin = attachment->plugin;
256                                 if(!real_plugin || !real_plugin->on)
257                                         is_on = 0;
258                         }
259                         else
260                                 is_on = 0;
261                 }
262                 else
263                         is_on = 0;
264         }
266         if(is_on)
267         {
268                 VirtualNode *virtual_plugin = create_plugin(plugin);
269                 subnodes.append(virtual_plugin);
270                 virtual_plugin->expand(duplicate, current_position);
271         }
272         return 0;
275 VirtualNode* VirtualNode::get_previous_plugin(VirtualNode *current_node)
277         for(int i = 0; i < subnodes.total; i++)
278         {
279 // Assume plugin is on
280                 if(subnodes.values[i] == current_node)
281                 {
282                         if(i > 0) 
283                                 return subnodes.values[i - 1];
284                         else
285                                 return 0;
286                 }
287         }
288         return 0;
293 void VirtualNode::get_mute_fragment(int64_t input_position,
294                                 int &mute_constant, 
295                                 int &fragment_len, 
296                                 Autos *autos,
297                                 int direction,
298                                 int use_nudge)
300         if(use_nudge) input_position += track->nudge;
302         IntAuto *prev_keyframe = 0;
303         IntAuto *next_keyframe = 0;
304         prev_keyframe = (IntAuto*)autos->get_prev_auto(input_position, 
305                 direction, 
306                 (Auto* &)prev_keyframe);
307         next_keyframe = (IntAuto*)autos->get_next_auto(input_position, 
308                 direction, 
309                 (Auto* &)next_keyframe);
311         if(direction == PLAY_FORWARD)
312         {
313 // Two distinct keyframes within range
314                 if(next_keyframe->position > prev_keyframe->position)
315                 {
316                         mute_constant = prev_keyframe->value;
318                         if(next_keyframe->position < input_position + fragment_len)
319                                 fragment_len = next_keyframe->position - input_position;
320                 }
321                 else
322 // One keyframe within range
323                 {
324                         mute_constant = prev_keyframe->value;
325                 }
326         }
327         else
328         {
329 // Two distinct keyframes within range
330                 if(next_keyframe->position < prev_keyframe->position)
331                 {
332                         mute_constant = next_keyframe->value;
334                         if(next_keyframe->position > input_position - fragment_len)
335                                 fragment_len = input_position - next_keyframe->position;
336                 }
337                 else
338 // One keyframe within range
339                 {
340                         mute_constant = next_keyframe->value;
341                 }
342         }