r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / plugin.C
blob72ce67249877d4dbd436edc425089190198e7460
1 #include "edl.h"
2 #include "edlsession.h"
3 #include "filexml.h"
4 #include "keyframe.h"
5 #include "keyframes.h"
6 #include "localsession.h"
7 #include "mwindow.h"
8 #include "messages.h"
9 #include "plugin.h"
10 #include "pluginpopup.h"
11 #include "pluginset.h"
12 #include "pluginserver.h"
13 #include "renderengine.h"
14 #include "track.h"
15 #include "tracks.h"
16 #include "virtualnode.h"
19 Plugin::Plugin(EDL *edl, 
20                 Track *track, 
21                 char *title)
22  : Edit(edl, track)
24         this->track = track;
25         this->plugin_set = 0;
26         strcpy(this->title, title);
27         plugin_type = PLUGIN_NONE;
28         in = 1;
29         out = 1;
30         show = 0;
31         on = 1;
32         keyframes = new KeyFrames(edl, track);
33         keyframes->create_objects();
37 Plugin::Plugin(EDL *edl, PluginSet *plugin_set, char *title)
38  : Edit(edl, plugin_set)
40         this->track = plugin_set->track;
41         this->plugin_set = plugin_set;
42         strcpy(this->title, title);
43         plugin_type = PLUGIN_NONE;
44         in = 1;
45         out = 1;
46         show = 0;
47         on = 1;
48         keyframes = new KeyFrames(edl, track);
49         keyframes->create_objects();
52 Plugin::~Plugin()
54         while(keyframes->last) delete keyframes->last;
55         delete keyframes;
58 Edit& Plugin::operator=(Edit& edit)
60         copy_from(&edit);
61         return *this;
64 Plugin& Plugin::operator=(Plugin& edit)
66         copy_from(&edit);
67         return *this;
70 int Plugin::operator==(Plugin& that)
72         return identical(&that);
75 int Plugin::operator==(Edit& that)
77         return identical((Plugin*)&that);
80 int Plugin::silence()
82         if(plugin_type != PLUGIN_NONE) 
83                 return 0;
84         else
85                 return 1;
88 void Plugin::clear_keyframes(int64_t start, int64_t end)
90         keyframes->clear(start, end, 0);
94 void Plugin::copy_from(Edit *edit)
96         Plugin *plugin = (Plugin*)edit;
98         this->startsource = edit->startsource;
99         this->startproject = edit->startproject;
100         this->length = edit->length;
103         this->plugin_type = plugin->plugin_type;
104         this->in = plugin->in;
105         this->out = plugin->out;
106         this->show = plugin->show;
107         this->on = plugin->on;
108 // Should reconfigure this based on where the first track is now.
109         this->shared_location = plugin->shared_location;
110         strcpy(this->title, plugin->title);
112         copy_keyframes(plugin);
115 void Plugin::copy_keyframes(Plugin *plugin)
117         keyframes->copy_from(plugin->keyframes);
120 void Plugin::copy_keyframes(int64_t start, 
121         int64_t end, 
122         FileXML *file, 
123         int default_only,
124         int autos_only)
126         keyframes->copy(start, end, file, default_only, autos_only);
129 void Plugin::synchronize_params(Edit *edit)
131         Plugin *plugin = (Plugin*)edit;
132         this->in = plugin->in;
133         this->out = plugin->out;
134         this->show = plugin->show;
135         this->on = plugin->on;
136         strcpy(this->title, plugin->title);
137         copy_keyframes(plugin);
140 void Plugin::shift_keyframes(int64_t position)
142         for(KeyFrame *keyframe = (KeyFrame*)keyframes->first;
143                 keyframe; 
144                 keyframe = (KeyFrame*)keyframe->next)
145         {
146                 keyframe->position += position;
147         }
151 void Plugin::equivalent_output(Edit *edit, int64_t *result)
153         Plugin *plugin = (Plugin*)edit;
154 // End of plugin changed
155         if(startproject + length != plugin->startproject + plugin->length)
156         {
157                 if(*result < 0 || startproject + length < *result)
158                         *result = startproject + length;
159         }
161 // Start of plugin changed
162         if(
163                 startproject != plugin->startproject ||
164                 plugin_type != plugin->plugin_type ||
165                 on != plugin->on ||
166                 !(shared_location == plugin->shared_location) ||
167                 strcmp(title, plugin->title)
168                 )
169         {
170                 if(*result < 0 || startproject < *result)
171                         *result = startproject;
172         }
174 // Test keyframes
175         keyframes->equivalent_output(plugin->keyframes, startproject, result);
180 int Plugin::is_synthesis(RenderEngine *renderengine, 
181                 int64_t position, 
182                 int direction)
184         switch(plugin_type)
185         {
186                 case PLUGIN_STANDALONE:
187                 {
188                         PluginServer *plugin_server = renderengine->scan_plugindb(title);
189                         return plugin_server->synthesis;
190                         break;
191                 }
193 // Dereference real plugin and descend another level
194                 case PLUGIN_SHAREDPLUGIN:
195                 {
196                         int real_module_number = shared_location.module;
197                         int real_plugin_number = shared_location.plugin;
198                         Track *track = edl->tracks->number(real_module_number);
199                         Plugin *plugin = track->get_current_plugin(position, 
200                                 real_plugin_number, 
201                                 direction, 
202                                 0);
203                         // if plugin at the master track is not present at this position
204                         if (!plugin) return 0;
205                         return plugin->is_synthesis(renderengine, position, direction);
206                         break;
207                 }
209 // Dereference the real track and descend
210                 case PLUGIN_SHAREDMODULE:
211                 {
212                         int real_module_number = shared_location.module;
213                         Track *track = edl->tracks->number(real_module_number);
214                         return track->is_synthesis(renderengine, position, direction);
215                         break;
216                 }
217         }
218         return 0;
223 int Plugin::identical(Plugin *that)
225         char title1[BCTEXTLEN], title2[BCTEXTLEN];
227         calculate_title(title1);
228         that->calculate_title(title2);
230 // printf("Plugin::identical %s %s %d %d %s %s %d\n",
231 // title1, 
232 // title2,
233 // plugin_type, 
234 // that->plugin_type,
235 // ((KeyFrame*)keyframes->default_auto)->data,
236 // ((KeyFrame*)that->keyframes->default_auto)->data,
237 // ((KeyFrame*)keyframes->default_auto)->identical(((KeyFrame*)that->keyframes->default_auto)));
239         return (this->plugin_type == that->plugin_type &&
240                 this->on == that->on &&
241                 !strcasecmp(title1, title2) &&
242                 ((KeyFrame*)keyframes->default_auto)->identical(
243                         ((KeyFrame*)that->keyframes->default_auto)));
246 int Plugin::identical_location(Plugin *that)
248 //printf("Plugin::identical_location\n");
249         if(!plugin_set || !plugin_set->track) return 0;
250         if(!that->plugin_set || !that->plugin_set->track) return 0;
252 //printf("Plugin::identical_location %d %d %d %d %d %d\n",
253 //plugin_set->track->number_of(),
254 //that->plugin_set->track->number_of(),
255 //plugin_set->get_number(),
256 //that->plugin_set->get_number(),
257 //startproject,
258 //that->startproject);
259         if(plugin_set->track->number_of() == that->plugin_set->track->number_of() &&
260                 plugin_set->get_number() == that->plugin_set->get_number() &&
261                 startproject == that->startproject) return 1;
263         return 0;
266 void Plugin::change_plugin(char *title, 
267                 SharedLocation *shared_location, 
268                 int plugin_type)
270         strcpy(this->title, title);
271         this->shared_location = *shared_location;
272         this->plugin_type = plugin_type;
277 KeyFrame* Plugin::get_prev_keyframe(int64_t position)
279         KeyFrame *current = 0;
281 //printf("Plugin::get_prev_keyframe 1 %p %p\n", this, edl);
282 // This doesn't work because edl->selectionstart doesn't change during
283 // playback at the same rate as PluginClient::source_position.
284         if(position < 0)
285         {
286 printf("Plugin::get_prev_keyframe position < 0\n");
287                 position = track->to_units(edl->local_session->selectionstart, 0);
288         }
289 //printf("Plugin::get_prev_keyframe 1 %d\n", position);
291         for(current = (KeyFrame*)keyframes->last;
292                 current;
293                 current = (KeyFrame*)PREVIOUS)
294         {
295                 if(current->position <= position) break;
296         }
298 //printf("Plugin::get_prev_keyframe %p %p %ld\n", current, keyframes->first, keyframes->first->position);
299         if(!current && keyframes->first)
300         {
301                 current = (KeyFrame*)keyframes->first;
302         }
303         else
304         if(!current)
305         {
306                 current = (KeyFrame*)keyframes->default_auto;
307         }
309 //printf("Plugin::get_prev_keyframe 2 %ld %ld\n", 
310 //      position, current->position);
311         return current;
314 KeyFrame* Plugin::get_next_keyframe(int64_t position)
316         KeyFrame *current;
318 // This doesn't work because edl->selectionstart doesn't change during
319 // playback at the same rate as PluginClient::source_position.
320         if(position < 0)
321         {
322 printf("Plugin::get_next_keyframe position < 0\n");
323                 position = track->to_units(edl->local_session->selectionstart, 0);
324         }
326         for(current = (KeyFrame*)keyframes->first;
327                 current;
328                 current = (KeyFrame*)NEXT)
329         {
330                 if(current->position > position) break;
331         }
333         if(!current && keyframes->last)
334         {
335                 current =  (KeyFrame*)keyframes->last;
336         }
337         else
338         if(!current)
339         {
340                 current = (KeyFrame*)keyframes->default_auto;
341         }
343 //printf("Plugin::get_next_keyframe 2 %ld %ld\n", 
344 //      position, current->position);
345         return current;
348 KeyFrame* Plugin::get_keyframe()
350 // Search for keyframe on or before selection
351         KeyFrame *result = 
352                 get_prev_keyframe(track->to_units(edl->local_session->selectionstart, 0));
354 //printf("Plugin::get_keyframe %p %p %p\n", result, edl, edl->session);
355 // Return nearest keyframe if not in automatic keyframe generation
356         if(!edl->session->auto_keyframes)
357         {
358                 return result;
359         }
360         else
361 // Return new keyframe
362         if(result == (KeyFrame*)keyframes->default_auto || 
363                 result->position != track->to_units(edl->local_session->selectionstart, 0))
364         {
365                 return (KeyFrame*)keyframes->insert_auto(track->to_units(edl->local_session->selectionstart, 0));
366         }
367         else
368 // Return existing keyframe
369         {
370                 return result;
371         }
373         return 0;
376 void Plugin::copy(int64_t start, int64_t end, FileXML *file)
378         int64_t endproject = startproject + length;
380         if((startproject >= start && startproject <= end) ||  // startproject in range
381                  (endproject <= end && endproject >= start) ||     // endproject in range
382                  (startproject <= start && endproject >= end))    // range in project
383         {
384 // edit is in range
385                 int64_t startproject_in_selection = startproject; // start of edit in selection in project
386                 int64_t startsource_in_selection = startsource; // start of source in selection in source
387                 int64_t endsource_in_selection = startsource + length; // end of source in selection
388                 int64_t length_in_selection = length;             // length of edit in selection
390                 if(startproject < start)
391                 {         // start is after start of edit in project
392                         int64_t length_difference = start - startproject;
394                         startsource_in_selection += length_difference;
395                         startproject_in_selection += length_difference;
396                         length_in_selection -= length_difference;
397                 }
399 // end is before end of edit in project
400                 if(endproject > end)
401                 {         
402                         length_in_selection = end - startproject_in_selection;
403                 }
405 // Plugins don't store silence
406                 file->tag.set_title("PLUGIN");  
407 //              file->tag.set_property("STARTPROJECT", startproject_in_selection - start);
408                 file->tag.set_property("LENGTH", length_in_selection);
409                 file->tag.set_property("TYPE", plugin_type);
410                 file->tag.set_property("TITLE", title);
411                 file->append_tag();
412                 file->append_newline();
415                 if(plugin_type == PLUGIN_SHAREDPLUGIN ||
416                         plugin_type == PLUGIN_SHAREDMODULE)
417                 {
418                         shared_location.save(file);
419                 }
423                 if(in)
424                 {
425                         file->tag.set_title("IN");
426                         file->append_tag();
427                 }
428                 if(out)
429                 {
430                         file->tag.set_title("OUT");
431                         file->append_tag();
432                 }
433                 if(show)
434                 {
435                         file->tag.set_title("SHOW");
436                         file->append_tag();
437                 }
438                 if(on)
439                 {
440                         file->tag.set_title("ON");
441                         file->append_tag();
442                 }
443                 file->append_newline();
445 // Keyframes
446                 keyframes->copy(start, end, file, 0, 0);
448                 file->tag.set_title("/PLUGIN"); 
449                 file->append_tag();
450                 file->append_newline();
451         }
454 void Plugin::load(FileXML *file)
456         int result = 0;
457         int first_keyframe = 1;
458         in = 0;
459         out = 0;
460 // Currently show is ignored when loading
461         show = 0;
462         on = 0;
463         while(keyframes->last) delete keyframes->last;
465         do{
466                 result = file->read_tag();
468 //printf("Plugin::load 1 %s\n", file->tag.get_title());
469                 if(!result)
470                 {
471                         if(file->tag.title_is("/PLUGIN"))
472                         {
473                                 result = 1;
474                         }
475                         else
476                         if(file->tag.title_is("SHARED_LOCATION"))
477                         {
478                                 shared_location.load(file);
479                         }
480                         else
481                         if(file->tag.title_is("IN"))
482                         {
483                                 in = 1;
484                         }
485                         else
486                         if(file->tag.title_is("OUT"))
487                         {
488                                 out = 1;
489                         }
490                         else
491                         if(file->tag.title_is("SHOW"))
492                         {
493 //                              show = 1;
494                         }
495                         else
496                         if(file->tag.title_is("ON"))
497                         {
498                                 on = 1;
499                         }
500                         else
501                         if(file->tag.title_is("KEYFRAME"))
502                         {
503 // Default keyframe
504                                 if(first_keyframe)
505                                 {
506                                         keyframes->default_auto->load(file);
507                                         first_keyframe = 0;
508                                 }
509                                 else
510 // Override default keyframe
511                                 {
512                                         KeyFrame *keyframe = (KeyFrame*)keyframes->append(new KeyFrame(edl, keyframes));
513                                         keyframe->position = file->tag.get_property("POSITION", (int64_t)0);
514                                         keyframe->load(file);
515                                 }
516                         }
517                 }
518         }while(!result);
521 void Plugin::get_shared_location(SharedLocation *result)
523         if(plugin_type == PLUGIN_STANDALONE && plugin_set)
524         {
525                 result->module = edl->tracks->number_of(track);
526                 result->plugin = track->plugin_set.number_of(plugin_set);
527         }
528         else
529         {
530                 *result = this->shared_location;
531         }
534 Track* Plugin::get_shared_track()
536         return edl->tracks->get_item_number(shared_location.module);
539 Plugin* Plugin::get_shared_plugin()
541         Track *track = get_shared_track();
543         if(track && 
544                 shared_location.plugin >= 0)
545         {
546                 return track->get_current_plugin(startproject, 
547                         shared_location.plugin, 
548                         PLAY_FORWARD,
549                         0);
550         }
551         else
552                 return 0;
556 void Plugin::calculate_title(char *string)
558         if(plugin_type == PLUGIN_STANDALONE || plugin_type == PLUGIN_NONE)
559         {
560                 strcpy(string, title);
561         }
562         else
563         if(plugin_type == PLUGIN_SHAREDPLUGIN || plugin_type == PLUGIN_SHAREDMODULE)
564         {
565                 shared_location.calculate_title(string, edl, startproject, 0, plugin_type);
566         }
570 void Plugin::paste(FileXML *file)
572         length = file->tag.get_property("LENGTH", (int64_t)0);
575 void Plugin::resample(double old_rate, double new_rate)
577 // Resample keyframes in here
578         keyframes->resample(old_rate, new_rate);
581 void Plugin::shift(int64_t difference)
583         Edit::shift(difference);
584         shift_keyframes(difference);
587 void Plugin::dump()
589         printf("    PLUGIN: type=%d title=\"%s\" on=%d track=%d plugin=%d\n", 
590                 plugin_type, 
591                 title, 
592                 on, 
593                 shared_location.module, 
594                 shared_location.plugin);
595         printf("    startproject %ld length %ld\n", startproject, length);
597         keyframes->dump();