add edit clear submenu/clear hard_edges, fix tessy gl segv, mask toolgui layout,...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / virtualnode.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "attachmentpoint.h"
23 #include "auto.h"
24 #include "automation.h"
25 #include "autos.h"
26 #include "bcsignals.h"
27 #include "floatauto.h"
28 #include "floatautos.h"
29 #include "intauto.h"
30 #include "intautos.h"
31 #include "mwindow.h"
32 #include "module.h"
33 #include "panauto.h"
34 #include "panautos.h"
35 #include "patchbay.h"
36 #include "plugin.h"
37 #include "pluginserver.h"
38 #include "renderengine.h"
39 #include "tracks.h"
40 #include "transition.h"
41 #include "transportque.h"
42 #include "virtualconsole.h"
43 #include "virtualnode.h"
44
45 VirtualNode::VirtualNode(RenderEngine *renderengine,
46                 VirtualConsole *vconsole,
47                 Module *real_module,
48                 Plugin *real_plugin,
49                 Track *track,
50                 VirtualNode *parent_node)
51 {
52         this->renderengine = renderengine;
53         this->vconsole = vconsole;
54         this->real_module = real_module;
55         this->real_plugin = real_plugin;
56         this->track = track;
57         this->parent_node = parent_node;
58
59
60         render_count = 0;
61         plugin_type = 0;
62         waiting_real_plugin = 0;
63         plugin_buffer_number = 0;
64         plugin_autos = 0;
65         plugin_auto_before = plugin_auto_after = 0;
66         attachment = 0;
67         is_exit = 0;
68 //printf("VirtualNode::VirtualNode 1\n");
69 }
70
71 VirtualNode::~VirtualNode()
72 {
73         subnodes.remove_all_objects();
74 //printf("VirtualNode::VirtualNode 2\n");
75 }
76
77 #define PRINT_INDENT for(int j = 0; j < indent; j++) printf(" ");
78
79 void VirtualNode::dump(int indent)
80 {
81         PRINT_INDENT
82         printf("VirtualNode %p title=%s real_module=%p %s\n",
83                 this,
84                 track->title,
85                 real_module,
86                 is_exit ? "*" : " ");
87         if(real_module)
88         {
89                 PRINT_INDENT
90                 printf(" Plugins total=%d\n", subnodes.total);
91                 for(int i = 0; i < subnodes.total; i++)
92                 {
93                         subnodes.values[i]->dump(indent + 2);
94                 }
95         }
96         else
97         if(real_plugin)
98         {
99                 printf("    Plugin %s\n", real_plugin->title);
100         }
101 }
102
103 int VirtualNode::expand(int persistent_plugins, int64_t current_position)
104 {
105         const int debug = 0;
106
107
108
109 // TODO: need to use speed curve to determine chain for current position
110
111
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",
114 __LINE__,
115 real_module,
116 real_plugin);
117         if(real_module)
118         {
119 if(debug) printf("VirtualNode::expand %d\n", __LINE__);
120                 expand_as_module(persistent_plugins, current_position);
121         }
122         else
123         if(real_plugin)
124         {
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);
129         }
130
131         return 0;
132 }
133
134 int VirtualNode::expand_as_module(int duplicate, int64_t current_position)
135 {
136 // create the plugins for this module
137         for(int i = 0; i < track->plugin_set.total; i++)
138         {
139                 Plugin *plugin = track->get_current_plugin(current_position,
140                         i,
141                         renderengine->command->get_direction(),
142                         0,
143                         1);
144
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;
149
150 // Switch off consecutive references to the same plugin
151                 if(plugin &&
152                         (plugin->plugin_type == PLUGIN_SHAREDPLUGIN ||
153                         plugin->plugin_type == PLUGIN_SHAREDMODULE))
154                 {
155                         int real_module_number = plugin->shared_location.module;
156                         int real_plugin_number = plugin->shared_location.plugin;
157
158                         for(int j = i - 1; j >= 0; j--)
159                         {
160                                 Plugin *prev_plugin = track->get_current_plugin(current_position,
161                                         j,
162                                         renderengine->command->get_direction(),
163                                         0,
164                                         1);
165                                 if(prev_plugin &&
166                                         prev_plugin->plugin_type == PLUGIN_SHAREDPLUGIN &&
167                                         plugin->plugin_type == PLUGIN_SHAREDPLUGIN)
168                                 {
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)
173                                         {
174                                                 circular_reference = 1;
175                                                 break;
176                                         }
177                                 }
178                                 else
179                                 if(prev_plugin &&
180                                         prev_plugin->plugin_type == PLUGIN_SHAREDMODULE &&
181                                         plugin->plugin_type == PLUGIN_SHAREDMODULE)
182                                 {
183                                         int prev_module_number = prev_plugin->shared_location.module;
184                                         if(real_module_number == prev_module_number)
185                                         {
186                                                 circular_reference = 1;
187                                                 break;
188                                         }
189                                 }
190                         }
191                 }
192
193                 if(circular_reference) continue;
194
195                 if(plugin && plugin->on)
196                 {
197                         int plugin_type = plugin->plugin_type;
198                         if(plugin_type == PLUGIN_SHAREDMODULE)
199                         {
200 // plugin is a module
201                                 attach_virtual_module(plugin,
202                                         i,
203                                         duplicate,
204                                         current_position);
205                         }
206                         else
207                         if(plugin_type == PLUGIN_SHAREDPLUGIN ||
208                                 plugin_type == PLUGIN_STANDALONE)
209                         {
210 // plugin is a plugin
211                                 attach_virtual_plugin(plugin,
212                                         i,
213                                         duplicate,
214                                         current_position);
215                         }
216                 }
217         }
218
219
220         if(!parent_node) vconsole->append_exit_node(this);
221 //printf("VirtualNode::expand_as_module %d parent_node=%p\n", __LINE__, parent_node);
222
223         return 0;
224 }
225
226 int VirtualNode::expand_as_plugin(int duplicate)
227 {
228         plugin_type = real_plugin->plugin_type;
229
230         if(plugin_type == PLUGIN_SHAREDPLUGIN)
231         {
232 // Attached to a shared plugin.
233 // Get the real real plugin it's attached to.
234
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);
239                 real_plugin = 0;
240 // module references are absolute so may get the wrong data type track.
241                 if(real_module)
242                 {
243                         attachment = real_module->get_attachment(real_plugin_number);
244 // Attachment is NULL if off
245                         if(attachment)
246                         {
247                                 real_plugin = attachment->plugin;
248
249 // Real plugin not on then null it.
250                                 if(!real_plugin || !real_plugin->on) real_plugin = 0;
251                         }
252                 }
253         }
254
255
256
257
258
259
260         if(plugin_type == PLUGIN_STANDALONE)
261         {
262 // Get plugin server
263                 Module *module = vconsole->module_of(track);
264
265                 attachment = module->attachment_of(real_plugin);
266         }
267
268
269
270
271
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)
278         {
279                 if(attachment)
280                         plugin_buffer_number = attachment->attach_virtual_plugin(this);
281         }
282
283
284
285
286         return 0;
287 }
288
289 int VirtualNode::attach_virtual_module(Plugin *plugin,
290         int plugin_number,
291         int duplicate,
292         int64_t current_position)
293 {
294         if(plugin->on)
295         {
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;
300
301                 Track *track = real_module->track;
302
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;
305
306
307
308
309                 VirtualNode *virtual_module = create_module(plugin,
310                         real_module,
311                         track);
312
313                 subnodes.append(virtual_module);
314                 virtual_module->expand(duplicate, current_position);
315         }
316
317         return 0;
318 }
319
320 int VirtualNode::attach_virtual_plugin(Plugin *plugin,
321         int plugin_number,
322         int duplicate,
323         int64_t current_position)
324 {
325 // Get real plugin and test if it is on.
326         int is_on = 1;
327         if(plugin->plugin_type == PLUGIN_SHAREDPLUGIN)
328         {
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);
332                 if(real_module)
333                 {
334                         AttachmentPoint *attachment = real_module->get_attachment(real_plugin_number);
335                         if(attachment)
336                         {
337                                 Plugin *real_plugin = attachment->plugin;
338                                 if(!real_plugin || !real_plugin->on)
339                                         is_on = 0;
340                         }
341                         else
342                                 is_on = 0;
343                 }
344                 else
345                         is_on = 0;
346         }
347
348         if(is_on)
349         {
350                 VirtualNode *virtual_plugin = create_plugin(plugin);
351                 subnodes.append(virtual_plugin);
352                 virtual_plugin->expand(duplicate, current_position);
353         }
354         return 0;
355 }
356
357 VirtualNode* VirtualNode::get_previous_plugin(VirtualNode *current_node)
358 {
359         for(int i = 0; i < subnodes.total; i++)
360         {
361 // Assume plugin is on
362                 if(subnodes.values[i] == current_node)
363                 {
364                         if(i > 0)
365                                 return subnodes.values[i - 1];
366                         else
367                                 return 0;
368                 }
369         }
370         return 0;
371 }
372
373
374
375 void VirtualNode::get_mute_fragment(int64_t input_position,
376                                 int &mute_constant,
377                                 int &fragment_len,
378                                 Autos *autos,
379                                 int direction,
380                                 int use_nudge)
381 {
382         if(use_nudge) input_position += track->nudge;
383
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;
392
393         if(direction == PLAY_FORWARD)
394         {
395 // Two distinct keyframes within range
396                 if(next_int_auto->position > prev_int_auto->position)
397                 {
398                         mute_constant = prev_int_auto->value;
399
400                         if(next_int_auto->position < input_position + fragment_len)
401                                 fragment_len = next_int_auto->position - input_position;
402                 }
403                 else
404 // One keyframe within range
405                 {
406                         mute_constant = prev_int_auto->value;
407                 }
408         }
409         else
410         {
411 // Two distinct keyframes within range
412                 if(next_int_auto->position < prev_int_auto->position)
413                 {
414                         mute_constant = next_int_auto->value;
415
416                         if(next_int_auto->position > input_position - fragment_len)
417                                 fragment_len = input_position - next_int_auto->position;
418                 }
419                 else
420 // One keyframe within range
421                 {
422                         mute_constant = next_int_auto->value;
423                 }
424         }
425 }
426
427
428
429
430
431