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 "bcsignals.h"
25 #include "edlsession.h"
28 #include "keyframes.h"
29 #include "localsession.h"
33 #include "pluginpopup.h"
34 #include "pluginset.h"
35 #include "pluginserver.h"
38 #include "virtualnode.h"
41 Plugin::Plugin(EDL *edl, Track *track, const char *title)
46 strcpy(this->title, title);
47 plugin_type = PLUGIN_NONE;
53 keyframes = new KeyFrames(edl, this);
54 keyframes->create_objects();
58 Plugin::Plugin(EDL *edl, PluginSet *plugin_set, const char *title)
59 : Edit(edl, plugin_set)
61 this->track = plugin_set->track;
62 this->plugin_set = plugin_set;
63 strcpy(this->title, title);
64 plugin_type = PLUGIN_NONE;
70 keyframes = new KeyFrames(edl, this);
71 keyframes->create_objects();
76 while(keyframes->last) delete keyframes->last;
80 Edit& Plugin::operator=(Edit& edit)
86 Plugin& Plugin::operator=(Plugin& edit)
92 int Plugin::operator==(Plugin& that)
94 return identical(&that);
97 int Plugin::operator==(Edit& that)
99 return identical((Plugin*)&that);
102 int Plugin::silence()
104 return plugin_type == PLUGIN_NONE ? 1 : 0;
107 void Plugin::clear_keyframes(int64_t start, int64_t end)
109 keyframes->clear(start, end, 0);
113 void Plugin::init(const char *title,
114 int64_t unit_position, int64_t unit_length, int plugin_type,
115 SharedLocation *shared_location, KeyFrame *default_keyframe)
117 if( title ) strcpy(this->title, title);
118 if( shared_location ) this->shared_location = *shared_location;
119 this->plugin_type = plugin_type;
120 if( default_keyframe )
121 *this->keyframes->default_auto = *default_keyframe;
122 this->keyframes->default_auto->position = unit_position;
123 this->startproject = unit_position;
124 this->length = unit_length;
127 void Plugin::copy_base(Edit *edit)
129 Plugin *plugin = (Plugin*)edit;
131 this->startsource = edit->startsource;
132 this->startproject = edit->startproject;
133 this->length = edit->length;
134 this->orig_id = edit->orig_id;
136 this->plugin_type = plugin->plugin_type;
137 this->in = plugin->in;
138 this->out = plugin->out;
139 this->show = plugin->show;
140 this->on = plugin->on;
141 // dont copy gui_id, it will be a duplicate ref
142 // Should reconfigure this based on where the first track is now.
143 this->shared_location = plugin->shared_location;
144 strcpy(this->title, plugin->title);
147 void Plugin::copy_from(Edit *edit)
150 copy_keyframes((Plugin*)edit);
153 void Plugin::copy_keyframes(Plugin *plugin)
156 keyframes->copy_from(plugin->keyframes);
159 void Plugin::copy_keyframes(int64_t start,
165 // Only 1 default is copied from where the start position is
166 int64_t endproject = startproject + length;
169 start < endproject &&
170 start >= startproject))
171 keyframes->copy(start, end, file, default_only, active_only);
174 void Plugin::synchronize_params(Edit *edit)
176 Plugin *plugin = (Plugin*)edit;
177 this->in = plugin->in;
178 this->out = plugin->out;
179 this->show = plugin->show;
180 this->gui_id = plugin->gui_id;
181 this->on = plugin->on;
182 strcpy(this->title, plugin->title);
183 copy_keyframes(plugin);
186 void Plugin::shift_keyframes(int64_t position)
188 for(KeyFrame *keyframe = (KeyFrame*)keyframes->first;
190 keyframe = (KeyFrame*)keyframe->next)
192 keyframe->position += position;
197 void Plugin::equivalent_output(Edit *edit, int64_t *result)
199 Plugin *plugin = (Plugin*)edit;
200 // End of plugin changed
201 if(startproject + length != plugin->startproject + plugin->length)
203 if(*result < 0 || startproject + length < *result)
204 *result = startproject + length;
207 // Start of plugin changed
208 if( startproject != plugin->startproject || plugin_type != plugin->plugin_type ||
209 on != plugin->on || !(shared_location == plugin->shared_location) ||
210 strcmp(title, plugin->title) ) {
211 if( *result < 0 || startproject < *result )
212 *result = startproject;
216 keyframes->equivalent_output(plugin->keyframes, startproject, result);
219 const char* Plugin::type_to_text(int type)
222 case PLUGIN_STANDALONE: return _("standalone");
223 case PLUGIN_SHAREDPLUGIN: return _("shared plugin");
224 case PLUGIN_SHAREDMODULE: return _("shared module");
229 int Plugin::is_synthesis(int64_t position, int direction, int depth)
232 printf("Plugin::is_synthesis %d: depth range limit, type=%s, title=%s\n",
233 __LINE__, type_to_text(plugin_type), title);
236 switch( plugin_type ) {
237 case PLUGIN_STANDALONE: {
239 printf("Plugin::is_synthesis track not defined\n");
242 PluginServer *plugin_server = MWindow::scan_plugindb(title, track->data_type);
243 return plugin_server->get_synthesis(); }
245 // Dereference real plugin and descend another level
246 case PLUGIN_SHAREDPLUGIN: {
247 int real_module_number = shared_location.module;
248 int real_plugin_number = shared_location.plugin;
249 Track *track = edl->tracks->number(real_module_number);
250 // Get shared plugin from master track
251 Plugin *plugin = track->get_current_plugin(position,
252 real_plugin_number, direction, 0, 0);
255 return plugin->is_synthesis(position, direction, depth+1);
258 // Dereference the real track and descend
259 case PLUGIN_SHAREDMODULE: {
260 int real_module_number = shared_location.module;
261 Track *track = edl->tracks->number(real_module_number);
262 return track->is_synthesis(position, direction, depth+1); }
269 int Plugin::identical(Plugin *that)
272 if(plugin_type != that->plugin_type) return 0;
274 // Test title or location
277 case PLUGIN_STANDALONE:
278 if(strcmp(title, that->title)) return 0;
280 case PLUGIN_SHAREDPLUGIN:
281 if(shared_location.module != that->shared_location.module ||
282 shared_location.plugin != that->shared_location.plugin) return 0;
284 case PLUGIN_SHAREDMODULE:
285 if(shared_location.module != that->shared_location.module) return 0;
289 // Test remaining fields
290 return (this->on == that->on &&
291 ((KeyFrame*)keyframes->default_auto)->identical(
292 ((KeyFrame*)that->keyframes->default_auto)));
295 int Plugin::keyframe_exists(KeyFrame *ptr)
297 for(KeyFrame *current = (KeyFrame*)keyframes->first;
299 current = (KeyFrame*)NEXT)
301 if(current == ptr) return 1;
307 void Plugin::change_plugin(char *title,
308 SharedLocation *shared_location,
311 strcpy(this->title, title);
312 this->shared_location = *shared_location;
313 this->plugin_type = plugin_type;
318 KeyFrame* Plugin::get_prev_keyframe(int64_t position,
321 return keyframes->get_prev_keyframe(position, direction);
324 KeyFrame* Plugin::get_next_keyframe(int64_t position,
329 // This doesn't work for playback because edl->selectionstart doesn't
330 // change during playback at the same rate as PluginClient::source_position.
333 //printf("Plugin::get_next_keyframe position < 0\n");
334 position = track->to_units(edl->local_session->get_selectionstart(1), 0);
337 // Get keyframe after current position
338 for(current = (KeyFrame*)keyframes->first;
340 current = (KeyFrame*)NEXT)
342 if(direction == PLAY_FORWARD && current->position > position) break;
344 if(direction == PLAY_REVERSE && current->position >= position) break;
347 // Nothing after current position
348 if(!current && keyframes->last)
350 current = (KeyFrame*)keyframes->last;
356 current = (KeyFrame*)keyframes->default_auto;
362 KeyFrame* Plugin::get_keyframe()
364 return keyframes->get_keyframe();
367 void Plugin::copy(int64_t start, int64_t end, FileXML *file)
369 int64_t endproject = startproject + length;
371 if((startproject >= start && startproject <= end) || // startproject in range
372 (endproject <= end && endproject >= start) || // endproject in range
373 (startproject <= start && endproject >= end)) // range in project
376 int64_t startproject_in_selection = startproject; // start of edit in selection in project
377 int64_t startsource_in_selection = startsource; // start of source in selection in source
378 //int64_t endsource_in_selection = startsource + length; // end of source in selection
379 int64_t length_in_selection = length; // length of edit in selection
381 if(startproject < start)
382 { // start is after start of edit in project
383 int64_t length_difference = start - startproject;
385 startsource_in_selection += length_difference;
386 startproject_in_selection += length_difference;
387 length_in_selection -= length_difference;
390 // end is before end of edit in project
393 length_in_selection = end - startproject_in_selection;
396 // Plugins don't store silence
397 file->tag.set_title("PLUGIN");
398 // file->tag.set_property("STARTPROJECT", startproject_in_selection - start);
399 file->tag.set_property("LENGTH", length_in_selection);
400 file->tag.set_property("TYPE", plugin_type);
401 file->tag.set_property("TITLE", title);
403 file->append_newline();
406 if(plugin_type == PLUGIN_SHAREDPLUGIN ||
407 plugin_type == PLUGIN_SHAREDMODULE)
409 shared_location.save(file);
416 file->tag.set_title("IN");
418 file->tag.set_title("/IN");
423 file->tag.set_title("OUT");
425 file->tag.set_title("/OUT");
430 file->tag.set_title("SHOW");
432 file->tag.set_title("/SHOW");
437 file->tag.set_title("ON");
439 file->tag.set_title("/ON");
442 file->append_newline();
445 keyframes->copy(start, end, file, 0, 0);
447 file->tag.set_title("/PLUGIN");
449 file->append_newline();
453 void Plugin::load(FileXML *file)
456 int first_keyframe = 1;
459 // Currently show is ignored when loading
462 while(keyframes->last) delete keyframes->last;
465 result = file->read_tag();
467 //printf("Plugin::load 1 %s\n", file->tag.get_title());
470 if(file->tag.title_is("/PLUGIN"))
475 if(file->tag.title_is("SHARED_LOCATION"))
477 shared_location.load(file);
480 if(file->tag.title_is("IN"))
485 if(file->tag.title_is("OUT"))
490 if(file->tag.title_is("SHOW"))
495 if(file->tag.title_is("ON"))
500 if(file->tag.title_is("KEYFRAME"))
505 keyframes->default_auto->load(file);
509 // Override default keyframe
511 KeyFrame *keyframe = (KeyFrame*)keyframes->append(new KeyFrame(edl, keyframes));
512 keyframe->position = file->tag.get_property("POSITION", (int64_t)0);
513 keyframe->load(file);
520 void Plugin::get_shared_location(SharedLocation *result)
522 if(plugin_type == PLUGIN_STANDALONE && plugin_set)
524 result->module = edl->tracks->number_of(track);
525 result->plugin = track->plugin_set.number_of(plugin_set);
529 *result = this->shared_location;
533 Track* Plugin::get_shared_track()
535 return edl->tracks->get_item_number(shared_location.module);
539 void Plugin::calculate_title(char *string, int use_nudge)
541 switch( plugin_type ) {
542 case PLUGIN_STANDALONE:
544 strcpy(string, _(title));
546 case PLUGIN_SHAREDPLUGIN:
547 case PLUGIN_SHAREDMODULE:
548 shared_location.calculate_title(string, edl,
549 startproject, 0, plugin_type, use_nudge);
554 void Plugin::fix_plugin_title(char *title)
556 MWindow::fix_plugin_title(title);
560 void Plugin::paste(FileXML *file)
562 length = file->tag.get_property("LENGTH", (int64_t)0);
565 void Plugin::resample(double old_rate, double new_rate)
567 // Resample keyframes in here
568 keyframes->resample(old_rate, new_rate);
571 void Plugin::shift(int64_t difference)
573 Edit::shift(difference);
575 if(edl->session->autos_follow_edits)
576 shift_keyframes(difference);
579 void Plugin::dump(FILE *fp)
581 fprintf(fp," PLUGIN: type=%d, id %d, orig_id %d, title=\"%s\" on=%d track=%d plugin=%d gui_id=%d\n",
582 plugin_type, id, orig_id, title, on, shared_location.module, shared_location.plugin, gui_id);
583 fprintf(fp," startproject %jd length %jd\n", startproject, length);