Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

pluginset.C

Go to the documentation of this file.
00001 #include "edl.h"
00002 #include "edlsession.h"
00003 #include "filexml.h"
00004 #include "keyframe.h"
00005 #include "keyframes.h"
00006 #include "plugin.h"
00007 #include "pluginautos.h"
00008 #include "pluginset.h"
00009 #include "track.h"
00010 
00011 #include <string.h>
00012 
00013 PluginSet::PluginSet(EDL *edl, Track *track)
00014  : Edits(edl, track)
00015 {
00016         record = 1;
00017 }
00018 
00019 PluginSet::~PluginSet()
00020 {
00021         while(last) delete last;
00022 }
00023 
00024 
00025 PluginSet& PluginSet::operator=(PluginSet& plugins)
00026 {
00027 printf("PluginSet::operator= 1\n");
00028         copy_from(&plugins);
00029         return *this;
00030 }
00031 
00032 void PluginSet::copy_from(PluginSet *src)
00033 {
00034         while(last) delete last;
00035         for(Plugin *current = (Plugin*)src->first; current; current = (Plugin*)NEXT)
00036         {
00037                 Plugin *new_plugin;
00038                 append(new_plugin = (Plugin*)create_edit());
00039                 new_plugin->copy_from(current);
00040         }
00041         this->record = src->record;
00042 }
00043 
00044 Plugin* PluginSet::get_first_plugin()
00045 {
00046 // Called when a new pluginset is added.
00047 // Get first non-silence plugin in the plugin set.
00048         for(Plugin *current = (Plugin*)first; current; current = (Plugin*)NEXT)
00049         {
00050                 if(current && current->plugin_type != PLUGIN_NONE)
00051                 {
00052                         return current;
00053                 }
00054         }
00055         return 0;
00056 }
00057 
00058 int64_t PluginSet::plugin_change_duration(int64_t input_position, 
00059         int64_t input_length, 
00060         int reverse)
00061 {
00062         int result = input_length;
00063         Edit *current;
00064 
00065         if(reverse)
00066         {
00067                 int input_start = input_position - input_length;
00068                 for(current = last; current; current = PREVIOUS)
00069                 {
00070                         int start = current->startproject;
00071                         int end = start + current->length;
00072                         if(end > input_start && end < input_position)
00073                         {
00074                                 result = input_position - end;
00075                                 return result;
00076                         }
00077                         else
00078                         if(start > input_start && start < input_position)
00079                         {
00080                                 result = input_position - start;
00081                                 return result;
00082                         }
00083                 }
00084         }
00085         else
00086         {
00087                 int input_end = input_position + input_length;
00088                 for(current = first; current; current = NEXT)
00089                 {
00090                         int start = current->startproject;
00091                         int end = start + current->length;
00092                         if(start > input_position && start < input_end)
00093                         {
00094                                 result = start - input_position;
00095                                 return result;
00096                         }
00097                         else
00098                         if(end > input_position && end < input_end)
00099                         {
00100                                 result = end - input_position;
00101                                 return result;
00102                         }
00103                 }
00104         }
00105         return input_length;
00106 }
00107 
00108 void PluginSet::synchronize_params(PluginSet *plugin_set)
00109 {
00110         for(Plugin *this_plugin = (Plugin*)first, *that_plugin = (Plugin*)plugin_set->first;
00111                 this_plugin && that_plugin;
00112                 this_plugin = (Plugin*)this_plugin->next, that_plugin = (Plugin*)that_plugin->next)
00113         {
00114                 this_plugin->synchronize_params(that_plugin);
00115         }
00116 }
00117 
00118 Plugin* PluginSet::insert_plugin(char *title, 
00119         int64_t unit_position, 
00120         int64_t unit_length,
00121         int plugin_type,
00122         SharedLocation *shared_location,
00123         KeyFrame *default_keyframe,
00124         int do_optimize)
00125 {
00126         Plugin *plugin = (Plugin*)create_and_insert_edit(unit_position, 
00127                 unit_position + unit_length);
00128 
00129 
00130         if(title) strcpy(plugin->title, title);
00131 
00132         if(shared_location) plugin->shared_location = *shared_location;
00133 
00134         plugin->plugin_type = plugin_type;
00135 
00136         if(default_keyframe) 
00137                 *plugin->keyframes->default_auto = *default_keyframe;
00138         plugin->keyframes->default_auto->position = unit_position;
00139 
00140 // May delete the plugin we just added so not desirable while loading.
00141         if(do_optimize) optimize();
00142         return plugin;
00143 }
00144 
00145 Edit* PluginSet::create_edit()
00146 {
00147         Plugin* result = new Plugin(edl, this, "");
00148         return result;
00149 }
00150 
00151 Edit* PluginSet::insert_edit_after(Edit *previous_edit)
00152 {
00153         Plugin *current = new Plugin(edl, this, "");
00154         List<Edit>::insert_after(previous_edit, current);
00155         return (Edit*)current;
00156 }
00157 
00158 
00159 int PluginSet::get_number()
00160 {
00161         return track->plugin_set.number_of(this);
00162 }
00163 
00164 void PluginSet::clear(int64_t start, int64_t end)
00165 {
00166 // Clear keyframes
00167         for(Plugin *current = (Plugin*)first;
00168                 current;
00169                 current = (Plugin*)NEXT)
00170         {
00171                 current->keyframes->clear(start, end, 1);
00172         }
00173 
00174 // Clear edits
00175         Edits::clear(start, end);
00176 }
00177 
00178 void PluginSet::clear_recursive(int64_t start, int64_t end)
00179 {
00180 //printf("PluginSet::clear_recursive 1\n");
00181         clear(start, end);
00182 }
00183 
00184 void PluginSet::shift_keyframes_recursive(int64_t position, int64_t length)
00185 {
00186 // Plugin keyframes are shifted in shift_effects
00187 }
00188 
00189 void PluginSet::shift_effects_recursive(int64_t position, int64_t length)
00190 {
00191 // Effects are shifted in length extension
00192 //      shift_effects(position, length);
00193 }
00194 
00195 
00196 void PluginSet::clear_keyframes(int64_t start, int64_t end)
00197 {
00198         for(Plugin *current = (Plugin*)first; current; current = (Plugin*)NEXT)
00199         {
00200                 current->clear_keyframes(start, end);
00201         }
00202 }
00203 
00204 void PluginSet::copy_keyframes(int64_t start, 
00205         int64_t end, 
00206         FileXML *file, 
00207         int default_only,
00208         int autos_only)
00209 {
00210         file->tag.set_title("PLUGINSET");       
00211         file->append_tag();
00212         file->append_newline();
00213 
00214         for(Plugin *current = (Plugin*)first; 
00215                 current; 
00216                 current = (Plugin*)NEXT)
00217         {
00218                 current->copy_keyframes(start, end, file, default_only, autos_only);
00219         }
00220 
00221         file->tag.set_title("/PLUGINSET");      
00222         file->append_tag();
00223         file->append_newline();
00224 }
00225 
00226 
00227 void PluginSet::paste_keyframes(int64_t start, 
00228         int64_t length, 
00229         FileXML *file, 
00230         int default_only,
00231         Track *track)
00232 {
00233         int result = 0;
00234         Plugin *current;
00235         
00236         PluginSet *target_pluginset;
00237         Plugin *first_target_plugin = 0;
00238 
00239         ArrayList<PluginSet*> unused_pluginsets;
00240         
00241 // get all available target pluginsets, we will be removing them one by one when we will paste into them
00242         for (int i = 0; i < track->plugin_set.total; i++)
00243         {
00244                 unused_pluginsets.append(track->plugin_set.values[i]);
00245         }
00246         
00247         char data[MESSAGESIZE];
00248         char data_default_keyframe[MESSAGESIZE];
00249         int default_keyframe;
00250         int do_default_keyframe = 0;
00251         
00252         while(!result)
00253         {
00254                 result = file->read_tag();
00255 
00256                 if(!result)
00257                 {
00258                         if(file->tag.title_is("/PLUGINSETS"))
00259                                 result = 1;
00260                         else
00261                         if(file->tag.title_is("PLUGINSET"))
00262                         {
00263                                 target_pluginset = 0;
00264                                 first_target_plugin = 0;
00265                         }
00266                         else
00267                         if(file->tag.title_is("KEYFRAME"))
00268                         {
00269                                 int64_t position = file->tag.get_property("POSITION", 0);
00270                                 position += start;
00271                                 if(file->tag.get_property("DEFAULT", 0))
00272                                 {
00273 // remember the default keyframe, we'll use it later
00274                                         default_keyframe = 1; 
00275                                         do_default_keyframe = 1;
00276                                         file->read_text_until("/KEYFRAME", data_default_keyframe, MESSAGESIZE);
00277                                 }
00278                                 else
00279                                 {
00280                                         default_keyframe = 0;
00281                                         file->read_text_until("/KEYFRAME", data, MESSAGESIZE);
00282                                 
00283                                 }
00284 
00285 //                              printf("d: a%sb\n", data);
00286                                 Plugin *picked_first_target = 0;
00287                                 if (!target_pluginset && default_keyframe && default_only && strlen(data_default_keyframe) > 0)
00288                                 {
00289                                         strcpy(data, data_default_keyframe);
00290                                 } 
00291                                 if ((!target_pluginset && !default_keyframe && strlen(data) > 0) ||     
00292                                     (!target_pluginset && default_keyframe && default_only && strlen(data_default_keyframe) > 0))        
00293                                 {
00294 // now try to find the target           
00295                                         int name_len = strchr(data, ' ') - data + 1;
00296 
00297                                         PluginSet *second_choice = 0;
00298                                         Plugin *second_choice_first_target_plugin = 0;
00299                                         for (int i = 0; i < unused_pluginsets.total && !target_pluginset; i++)
00300                                         {
00301                                                 PluginSet *pluginset = unused_pluginsets.values[i];
00302                                                 Plugin *current;
00303                                                 for(current = (Plugin*)(pluginset->last); 
00304                                                         current;
00305                                                         current = (Plugin*)PREVIOUS)
00306                                                 {
00307                                                         if(position >= current->startproject 
00308                                                         && position <= current->length + current->startproject 
00309                                                         && !strncmp(((KeyFrame *)current->keyframes->default_auto)->data, data, name_len))
00310                                                         {
00311                                                                 target_pluginset = pluginset;
00312                                                                 first_target_plugin = current;
00313                                                                 break;
00314                                                         }
00315                                                         if(position >= current->startproject 
00316                                                         && !strncmp(((KeyFrame *)current->keyframes->default_auto)->data, data, name_len))
00317                                                         {
00318                                                                 second_choice = pluginset;
00319                                                                 second_choice_first_target_plugin = current;
00320                                                                 break;
00321                                                         }
00322                                                                                                 
00323                                                 }
00324                                         }
00325                                         if (!target_pluginset) 
00326                                         {
00327                                                 target_pluginset = second_choice;
00328                                                 first_target_plugin = second_choice_first_target_plugin;
00329                                         }
00330                                 }
00331 //                              printf(" Target: %p\n", target_pluginset);
00332                                 if (target_pluginset) 
00333                                 {
00334                                         unused_pluginsets.remove(target_pluginset);
00335                                         if (do_default_keyframe)
00336                                         {
00337 // default plugin is always delayed
00338                                                 KeyFrame *keyframe = (KeyFrame*)first_target_plugin->keyframes->default_auto;
00339                                                 strcpy(keyframe->data, data_default_keyframe);
00340                                                 keyframe->position = position;
00341                                                 do_default_keyframe = 0;
00342                                         }
00343                                         if (!default_only && !default_keyframe)
00344                                         {
00345                                                 for(current = (Plugin*)target_pluginset->last; 
00346                                                         current;
00347                                                         current = (Plugin*)PREVIOUS)
00348                                                 {
00349                                                         if(position >= current->startproject)
00350                                                         {
00351                                                                 KeyFrame *keyframe;
00352                                                                 keyframe = (KeyFrame*)current->keyframes->insert_auto(position);
00353                                                                 strcpy(keyframe->data, data);
00354                                                                 keyframe->position = position;
00355                                                                 break;
00356                                                         }
00357                                                 }
00358                                         }
00359                                 }
00360                                 
00361 // Get plugin owning keyframe
00362 /*
00363                                 for(current = (Plugin*)last; 
00364                                         current;
00365                                         current = (Plugin*)PREVIOUS)
00366                                 {
00367 // We want keyframes to exist beyond the end of the last plugin to
00368 // make editing intuitive, but it will always be possible to 
00369 // paste keyframes from one plugin into an incompatible plugin.
00370                                         if(position >= current->startproject)
00371                                         {
00372                                                 KeyFrame *keyframe;
00373                                                 if(file->tag.get_property("DEFAULT", 0) || default_only)
00374                                                 {
00375                                                         keyframe = (KeyFrame*)current->keyframes->default_auto;
00376                                                 }
00377                                                 else
00378                                                 {
00379                                                         keyframe = 
00380                                                                 (KeyFrame*)current->keyframes->insert_auto(position);
00381                                                 }
00382                                                 keyframe->load(file);
00383                                                 keyframe->position = position;
00384                                                 break;
00385                                         }
00386                                 }
00387 */
00388                         }
00389                 }
00390         }
00391 }
00392 
00393 void PluginSet::shift_effects(int64_t start, int64_t length)
00394 {
00395         for(Plugin *current = (Plugin*)first;
00396                 current;
00397                 current = (Plugin*)NEXT)
00398         {
00399 // Shift beginning of this effect
00400                 if(current->startproject >= start)
00401                 {
00402                         current->startproject += length;
00403                 }
00404                 else
00405 // Extend end of this effect.
00406 // In loading new files, the effect should extend to fill the entire track.
00407 // In muting, the effect must extend to fill the gap if another effect follows.
00408 // The user should use Settings->edit effects to disable this.
00409                 if(current->startproject + current->length >= start)
00410                 {
00411                         current->length += length;
00412                 }
00413 
00414 // Shift keyframes in this effect.
00415 // If the default keyframe lands on the starting point, it must be shifted
00416 // since the effect start is shifted.
00417                 if(current->keyframes->default_auto->position >= start)
00418                         current->keyframes->default_auto->position += length;
00419 
00420                 current->keyframes->paste_silence(start, start + length);
00421         }
00422 }
00423 
00424 void PluginSet::copy(int64_t start, int64_t end, FileXML *file)
00425 {
00426         file->tag.set_title("PLUGINSET");       
00427         file->tag.set_property("RECORD", record);
00428         file->append_tag();
00429         file->append_newline();
00430 
00431         for(Plugin *current = (Plugin*)first; current; current = (Plugin*)NEXT)
00432         {
00433                 current->copy(start, end, file);
00434         }
00435 
00436         file->tag.set_title("/PLUGINSET");      
00437         file->append_tag();
00438         file->append_newline();
00439 }
00440 
00441 void PluginSet::save(FileXML *file)
00442 {
00443         copy(0, length(), file);
00444 }
00445 
00446 void PluginSet::load(FileXML *file, uint32_t load_flags)
00447 {
00448         int result = 0;
00449 // Current plugin being amended
00450         Plugin *plugin = (Plugin*)first;
00451         int64_t startproject = 0;
00452 
00453         record = file->tag.get_property("RECORD", record);
00454         do{
00455                 result = file->read_tag();
00456 
00457 
00458                 if(!result)
00459                 {
00460                         if(file->tag.title_is("/PLUGINSET"))
00461                         {
00462                                 result = 1;
00463                         }
00464                         else
00465                         if(file->tag.title_is("PLUGIN"))
00466                         {
00467                                 int64_t length = file->tag.get_property("LENGTH", (int64_t)0);
00468                                 int plugin_type = file->tag.get_property("TYPE", 1);
00469                                 char title[BCTEXTLEN];
00470                                 title[0] = 0;
00471                                 file->tag.get_property("TITLE", title);
00472                                 SharedLocation shared_location;
00473                                 shared_location.load(file);
00474 
00475 
00476                                 if(load_flags & LOAD_EDITS)
00477                                 {
00478                                         plugin = insert_plugin(title, 
00479                                                 startproject, 
00480                                                 length,
00481                                                 plugin_type,
00482                                                 &shared_location,
00483                                                 0,
00484                                                 0);
00485                                         plugin->load(file);
00486                                         startproject += length;
00487                                 }
00488                                 else
00489                                 if(load_flags & LOAD_AUTOMATION)
00490                                 {
00491                                         if(plugin)
00492                                         {
00493                                                 plugin->load(file);
00494                                                 plugin = (Plugin*)plugin->next;
00495                                         }
00496                                 }
00497                         }
00498                 }
00499         }while(!result);
00500 }
00501 
00502 
00503 
00504 int PluginSet::optimize()
00505 {
00506         int result = 1;
00507         Plugin *current_edit;
00508 
00509 
00510 // Delete keyframes out of range
00511         for(current_edit = (Plugin*)first;
00512                 current_edit; 
00513                 current_edit = (Plugin*)current_edit->next)
00514         {
00515                 current_edit->keyframes->default_auto->position = 0;
00516                 for(KeyFrame *current_keyframe = (KeyFrame*)current_edit->keyframes->last;
00517                         current_keyframe; )
00518                 {
00519                         KeyFrame *previous_keyframe = (KeyFrame*)current_keyframe->previous;
00520                         if(current_keyframe->position > 
00521                                 current_edit->startproject + current_edit->length ||
00522                                 current_keyframe->position < current_edit->startproject)
00523                         {
00524                                 delete current_keyframe;
00525                         }
00526                         current_keyframe = previous_keyframe;
00527                 }
00528         }
00529 
00530 // Insert silence between plugins
00531         for(Plugin *current = (Plugin*)last; current; current = (Plugin*)PREVIOUS)
00532         {
00533                 if(current->previous)
00534                 {
00535                         Plugin *previous = (Plugin*)PREVIOUS;
00536 
00537                         if(current->startproject - 
00538                                 previous->startproject - 
00539                                 previous->length > 0)
00540                         {
00541                                 Plugin *new_plugin = (Plugin*)create_edit();
00542                                 insert_before(current, new_plugin);
00543                                 new_plugin->startproject = previous->startproject + 
00544                                         previous->length;
00545                                 new_plugin->length = current->startproject - 
00546                                         previous->startproject - 
00547                                         previous->length;
00548                         }
00549                 }
00550                 else
00551                 if(current->startproject > 0)
00552                 {
00553                         Plugin *new_plugin = (Plugin*)create_edit();
00554                         insert_before(current, new_plugin);
00555                         new_plugin->length = current->startproject;
00556                 }
00557         }
00558 
00559 
00560 // delete 0 length plugins
00561         while(result)
00562         {
00563                 result = 0;
00564 
00565                 for(current_edit = (Plugin*)first; 
00566                         current_edit && !result; )
00567                 {
00568                         if(current_edit->length == 0)
00569                         {
00570                                 Plugin* next = (Plugin*)current_edit->next;
00571                                 delete current_edit;
00572                                 result = 1;
00573                                 current_edit = next;
00574                         }
00575                         else
00576                                 current_edit = (Plugin*)current_edit->next;
00577                 }
00578 
00579 
00580 // merge identical plugins with same keyframes
00581                 for(current_edit = (Plugin*)first; 
00582                         current_edit && current_edit->next && !result; )
00583                 {
00584                         Plugin *next_edit = (Plugin*)current_edit->next;
00585 
00586 
00587 // plugins identical
00588                         if(next_edit->identical(current_edit))
00589                 {
00590                         current_edit->length += next_edit->length;
00591 // Merge keyframes
00592                                 for(KeyFrame *source = (KeyFrame*)next_edit->keyframes->first;
00593                                         source;
00594                                         source = (KeyFrame*)source->next)
00595                                 {
00596                                         KeyFrame *dest = new KeyFrame(edl, current_edit->keyframes);
00597                                         *dest = *source;
00598                                         current_edit->keyframes->append(dest);
00599                                 }
00600                         remove(next_edit);
00601                         result = 1;
00602                 }
00603 
00604                 current_edit = (Plugin*)current_edit->next;
00605                 }
00606 
00607 // delete last edit if 0 length or silence
00608                 if(last)
00609                 {
00610                         if(last->silence() || !last->length)
00611                         {
00612                                 delete last;
00613                                 result = 1;
00614                         }
00615                 }
00616         }
00617 
00618         return 0;
00619 }
00620 
00621 
00622 
00623 
00624 
00625 void PluginSet::dump()
00626 {
00627         printf("   PLUGIN_SET:\n");
00628         for(Plugin *current = (Plugin*)first; current; current =  (Plugin*)NEXT)
00629                 current->dump();
00630 }

Generated on Sun Jan 8 13:38:59 2006 for Cinelerra-svn by  doxygen 1.4.4