r1053: Add Russian translation.
[cinelerra_cv.git] / cinelerra / plugin.C
blob7929fb35258941368cfa97dd6da6a1fa4c4bf250
1 #include "bcsignals.h"
2 #include "edl.h"
3 #include "edlsession.h"
4 #include "filexml.h"
5 #include "keyframe.h"
6 #include "keyframes.h"
7 #include "localsession.h"
8 #include "mwindow.h"
9 #include "messages.h"
10 #include "plugin.h"
11 #include "pluginpopup.h"
12 #include "pluginset.h"
13 #include "pluginserver.h"
14 #include "renderengine.h"
15 #include "track.h"
16 #include "tracks.h"
17 #include "virtualnode.h"
20 Plugin::Plugin(EDL *edl, 
21                 Track *track, 
22                 char *title)
23  : Edit(edl, track)
25         this->track = track;
26         this->plugin_set = 0;
27         strcpy(this->title, title);
28         plugin_type = PLUGIN_NONE;
29         in = 1;
30         out = 1;
31         show = 0;
32         on = 1;
33         keyframes = new KeyFrames(edl, track);
34         keyframes->create_objects();
38 Plugin::Plugin(EDL *edl, PluginSet *plugin_set, char *title)
39  : Edit(edl, plugin_set)
41         this->track = plugin_set->track;
42         this->plugin_set = plugin_set;
43         strcpy(this->title, title);
44         plugin_type = PLUGIN_NONE;
45         in = 1;
46         out = 1;
47         show = 0;
48         on = 1;
49         keyframes = new KeyFrames(edl, track);
50         keyframes->create_objects();
53 Plugin::~Plugin()
55         while(keyframes->last) delete keyframes->last;
56         delete keyframes;
59 Edit& Plugin::operator=(Edit& edit)
61         copy_from(&edit);
62         return *this;
65 Plugin& Plugin::operator=(Plugin& edit)
67         copy_from(&edit);
68         return *this;
71 int Plugin::operator==(Plugin& that)
73         return identical(&that);
76 int Plugin::operator==(Edit& that)
78         return identical((Plugin*)&that);
81 int Plugin::silence()
83         if(plugin_type != PLUGIN_NONE) 
84                 return 0;
85         else
86                 return 1;
89 void Plugin::clear_keyframes(int64_t start, int64_t end)
91         keyframes->clear(start, end, 0);
95 void Plugin::copy_from(Edit *edit)
97         Plugin *plugin = (Plugin*)edit;
99         this->startsource = edit->startsource;
100         this->startproject = edit->startproject;
101         this->length = edit->length;
104         this->plugin_type = plugin->plugin_type;
105         this->in = plugin->in;
106         this->out = plugin->out;
107         this->show = plugin->show;
108         this->on = plugin->on;
109 // Should reconfigure this based on where the first track is now.
110         this->shared_location = plugin->shared_location;
111         strcpy(this->title, plugin->title);
113         copy_keyframes(plugin);
116 void Plugin::copy_keyframes(Plugin *plugin)
118         keyframes->copy_from(plugin->keyframes);
121 void Plugin::copy_keyframes(int64_t start, 
122         int64_t end, 
123         FileXML *file, 
124         int default_only,
125         int autos_only)
127         keyframes->copy(start, end, file, default_only, autos_only);
130 void Plugin::synchronize_params(Edit *edit)
132         Plugin *plugin = (Plugin*)edit;
133         this->in = plugin->in;
134         this->out = plugin->out;
135         this->show = plugin->show;
136         this->on = plugin->on;
137         strcpy(this->title, plugin->title);
138         copy_keyframes(plugin);
141 void Plugin::shift_keyframes(int64_t position)
143         for(KeyFrame *keyframe = (KeyFrame*)keyframes->first;
144                 keyframe; 
145                 keyframe = (KeyFrame*)keyframe->next)
146         {
147                 keyframe->position += position;
148         }
152 void Plugin::equivalent_output(Edit *edit, int64_t *result)
154         Plugin *plugin = (Plugin*)edit;
155 // End of plugin changed
156         if(startproject + length != plugin->startproject + plugin->length)
157         {
158                 if(*result < 0 || startproject + length < *result)
159                         *result = startproject + length;
160         }
162 // Start of plugin changed
163         if(
164                 startproject != plugin->startproject ||
165                 plugin_type != plugin->plugin_type ||
166                 on != plugin->on ||
167                 !(shared_location == plugin->shared_location) ||
168                 strcmp(title, plugin->title)
169                 )
170         {
171                 if(*result < 0 || startproject < *result)
172                         *result = startproject;
173         }
175 // Test keyframes
176         keyframes->equivalent_output(plugin->keyframes, startproject, result);
181 int Plugin::is_synthesis(RenderEngine *renderengine, 
182                 int64_t position, 
183                 int direction)
185         switch(plugin_type)
186         {
187                 case PLUGIN_STANDALONE:
188                 {
189                         if(!track)
190                         {
191                                 printf("Plugin::is_synthesis track not defined\n");
192                                 return 0;
193                         }
194                         PluginServer *plugin_server = renderengine->scan_plugindb(title,
195                                 track->data_type);
196                         return plugin_server->synthesis;
197                         break;
198                 }
200 // Dereference real plugin and descend another level
201                 case PLUGIN_SHAREDPLUGIN:
202                 {
203                         int real_module_number = shared_location.module;
204                         int real_plugin_number = shared_location.plugin;
205                         Track *track = edl->tracks->number(real_module_number);
206 // Get shared plugin from master track
207                         Plugin *plugin = track->get_current_plugin(position, 
208                                 real_plugin_number, 
209                                 direction, 
210                                 0,
211                                 0);
213                         if(plugin)
214                                 return plugin->is_synthesis(renderengine, position, direction);
215                         break;
216                 }
218 // Dereference the real track and descend
219                 case PLUGIN_SHAREDMODULE:
220                 {
221                         int real_module_number = shared_location.module;
222                         Track *track = edl->tracks->number(real_module_number);
223                         return track->is_synthesis(renderengine, position, direction);
224                         break;
225                 }
226         }
227         return 0;
232 int Plugin::identical(Plugin *that)
234 // Test type
235         if(plugin_type != that->plugin_type) return 0;
237 // Test title or location
238         switch(plugin_type)
239         {
240                 case PLUGIN_STANDALONE:
241                         if(strcmp(title, that->title)) return 0;
242                         break;
243                 case PLUGIN_SHAREDPLUGIN:
244                         if(shared_location.module != that->shared_location.module ||
245                                 shared_location.plugin != that->shared_location.plugin) return 0;
246                         break;
247                 case PLUGIN_SHAREDMODULE:
248                         if(shared_location.module != that->shared_location.module) return 0;
249                         break;
250         }
252 // Test remaining fields
253         return (this->on == that->on &&
254                 ((KeyFrame*)keyframes->default_auto)->identical(
255                         ((KeyFrame*)that->keyframes->default_auto)));
258 int Plugin::identical_location(Plugin *that)
260         if(!plugin_set || !plugin_set->track) return 0;
261         if(!that->plugin_set || !that->plugin_set->track) return 0;
263         if(plugin_set->track->number_of() == that->plugin_set->track->number_of() &&
264                 plugin_set->get_number() == that->plugin_set->get_number() &&
265                 startproject == that->startproject) return 1;
267         return 0;
270 void Plugin::change_plugin(char *title, 
271                 SharedLocation *shared_location, 
272                 int plugin_type)
274         strcpy(this->title, title);
275         this->shared_location = *shared_location;
276         this->plugin_type = plugin_type;
281 KeyFrame* Plugin::get_prev_keyframe(int64_t position,
282         int direction)
284         KeyFrame *current = 0;
286 // This doesn't work because edl->selectionstart doesn't change during
287 // playback at the same rate as PluginClient::source_position.
288         if(position < 0)
289         {
290                 position = track->to_units(edl->local_session->get_selectionstart(1), 0);
291         }
293 // Get keyframe on or before current position
294         for(current = (KeyFrame*)keyframes->last;
295                 current;
296                 current = (KeyFrame*)PREVIOUS)
297         {
298                 if(direction == PLAY_FORWARD && current->position <= position) break;
299                 else
300                 if(direction == PLAY_REVERSE && current->position < position) break;
301         }
303 // Nothing before current position
304         if(!current && keyframes->first)
305         {
306                 current = (KeyFrame*)keyframes->first;
307         }
308         else
309 // No keyframes
310         if(!current)
311         {
312                 current = (KeyFrame*)keyframes->default_auto;
313         }
315         return current;
318 KeyFrame* Plugin::get_next_keyframe(int64_t position,
319         int direction)
321         KeyFrame *current;
323 // This doesn't work for playback because edl->selectionstart doesn't 
324 // change during playback at the same rate as PluginClient::source_position.
325         if(position < 0)
326         {
327 //printf("Plugin::get_next_keyframe position < 0\n");
328                 position = track->to_units(edl->local_session->get_selectionstart(1), 0);
329         }
331 // Get keyframe after current position
332         for(current = (KeyFrame*)keyframes->first;
333                 current;
334                 current = (KeyFrame*)NEXT)
335         {
336                 if(direction == PLAY_FORWARD && current->position > position) break;
337                 else
338                 if(direction == PLAY_REVERSE && current->position >= position) break;
339         }
341 // Nothing after current position
342         if(!current && keyframes->last)
343         {
344                 current =  (KeyFrame*)keyframes->last;
345         }
346         else
347 // No keyframes
348         if(!current)
349         {
350                 current = (KeyFrame*)keyframes->default_auto;
351         }
353         return current;
356 KeyFrame* Plugin::get_keyframe()
358 // Search for keyframe on or before selection
359         KeyFrame *result = 
360                 get_prev_keyframe(track->to_units(edl->local_session->get_selectionstart(1), 0), 
361                         PLAY_FORWARD);
363 // Return nearest keyframe if not in automatic keyframe generation
364         if(!edl->session->auto_keyframes)
365         {
366                 return result;
367         }
368         else
369 // Return new keyframe
370         if(result == (KeyFrame*)keyframes->default_auto || 
371                 result->position != track->to_units(edl->local_session->get_selectionstart(1), 0))
372         {
373                 return (KeyFrame*)keyframes->insert_auto(track->to_units(edl->local_session->get_selectionstart(1), 0));
374         }
375         else
376 // Return existing keyframe
377         {
378                 return result;
379         }
381         return 0;
384 void Plugin::copy(int64_t start, int64_t end, FileXML *file)
386         int64_t endproject = startproject + length;
388         if((startproject >= start && startproject <= end) ||  // startproject in range
389                  (endproject <= end && endproject >= start) ||     // endproject in range
390                  (startproject <= start && endproject >= end))    // range in project
391         {
392 // edit is in range
393                 int64_t startproject_in_selection = startproject; // start of edit in selection in project
394                 int64_t startsource_in_selection = startsource; // start of source in selection in source
395                 int64_t endsource_in_selection = startsource + length; // end of source in selection
396                 int64_t length_in_selection = length;             // length of edit in selection
398                 if(startproject < start)
399                 {         // start is after start of edit in project
400                         int64_t length_difference = start - startproject;
402                         startsource_in_selection += length_difference;
403                         startproject_in_selection += length_difference;
404                         length_in_selection -= length_difference;
405                 }
407 // end is before end of edit in project
408                 if(endproject > end)
409                 {         
410                         length_in_selection = end - startproject_in_selection;
411                 }
413 // Plugins don't store silence
414                 file->tag.set_title("PLUGIN");  
415 //              file->tag.set_property("STARTPROJECT", startproject_in_selection - start);
416                 file->tag.set_property("LENGTH", length_in_selection);
417                 file->tag.set_property("TYPE", plugin_type);
418                 file->tag.set_property("TITLE", title);
419                 file->append_tag();
420                 file->append_newline();
423                 if(plugin_type == PLUGIN_SHAREDPLUGIN ||
424                         plugin_type == PLUGIN_SHAREDMODULE)
425                 {
426                         shared_location.save(file);
427                 }
431                 if(in)
432                 {
433                         file->tag.set_title("IN");
434                         file->append_tag();
435                         file->tag.set_title("/IN");
436                         file->append_tag();
437                 }
438                 if(out)
439                 {
440                         file->tag.set_title("OUT");
441                         file->append_tag();
442                         file->tag.set_title("/OUT");
443                         file->append_tag();
444                 }
445                 if(show)
446                 {
447                         file->tag.set_title("SHOW");
448                         file->append_tag();
449                         file->tag.set_title("/SHOW");
450                         file->append_tag();
451                 }
452                 if(on)
453                 {
454                         file->tag.set_title("ON");
455                         file->append_tag();
456                         file->tag.set_title("/ON");
457                         file->append_tag();
458                 }
459                 file->append_newline();
461 // Keyframes
462                 keyframes->copy(start, end, file, 0, 0);
464                 file->tag.set_title("/PLUGIN"); 
465                 file->append_tag();
466                 file->append_newline();
467         }
470 void Plugin::load(FileXML *file)
472         int result = 0;
473         int first_keyframe = 1;
474         in = 0;
475         out = 0;
476 // Currently show is ignored when loading
477         show = 0;
478         on = 0;
479         while(keyframes->last) delete keyframes->last;
481         do{
482                 result = file->read_tag();
484 //printf("Plugin::load 1 %s\n", file->tag.get_title());
485                 if(!result)
486                 {
487                         if(file->tag.title_is("/PLUGIN"))
488                         {
489                                 result = 1;
490                         }
491                         else
492                         if(file->tag.title_is("SHARED_LOCATION"))
493                         {
494                                 shared_location.load(file);
495                         }
496                         else
497                         if(file->tag.title_is("IN"))
498                         {
499                                 in = 1;
500                         }
501                         else
502                         if(file->tag.title_is("OUT"))
503                         {
504                                 out = 1;
505                         }
506                         else
507                         if(file->tag.title_is("SHOW"))
508                         {
509 //                              show = 1;
510                         }
511                         else
512                         if(file->tag.title_is("ON"))
513                         {
514                                 on = 1;
515                         }
516                         else
517                         if(file->tag.title_is("KEYFRAME"))
518                         {
519 // Default keyframe
520                                 if(first_keyframe)
521                                 {
522                                         keyframes->default_auto->load(file);
523                                         first_keyframe = 0;
524                                 }
525                                 else
526 // Override default keyframe
527                                 {
528                                         KeyFrame *keyframe = (KeyFrame*)keyframes->append(new KeyFrame(edl, keyframes));
529                                         keyframe->position = file->tag.get_property("POSITION", (int64_t)0);
530                                         keyframe->load(file);
531                                 }
532                         }
533                 }
534         }while(!result);
537 void Plugin::get_shared_location(SharedLocation *result)
539         if(plugin_type == PLUGIN_STANDALONE && plugin_set)
540         {
541                 result->module = edl->tracks->number_of(track);
542                 result->plugin = track->plugin_set.number_of(plugin_set);
543         }
544         else
545         {
546                 *result = this->shared_location;
547         }
550 Track* Plugin::get_shared_track()
552         return edl->tracks->get_item_number(shared_location.module);
556 void Plugin::calculate_title(char *string, int use_nudge)
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, 
566                         edl, 
567                         startproject, 
568                         0, 
569                         plugin_type,
570                         use_nudge);
571         }
575 void Plugin::paste(FileXML *file)
577         length = file->tag.get_property("LENGTH", (int64_t)0);
580 void Plugin::resample(double old_rate, double new_rate)
582 // Resample keyframes in here
583         keyframes->resample(old_rate, new_rate);
586 void Plugin::shift(int64_t difference)
588         Edit::shift(difference);
589         shift_keyframes(difference);
592 void Plugin::dump()
594         printf("    PLUGIN: type=%d title=\"%s\" on=%d track=%d plugin=%d\n", 
595                 plugin_type, 
596                 title, 
597                 on, 
598                 shared_location.module, 
599                 shared_location.plugin);
600         printf("    startproject %lld length %lld\n", startproject, length);
602         keyframes->dump();