r668: Configure.in and autogen.sh cleanup based on ideas by giskard.
[cinelerra_cv.git] / cinelerra / edl.C
blobf118343343021057ac7d0b57acc3f6b00eded189
1 #include "asset.h"
2 #include "assets.h"
3 #include "atrack.h"
4 #include "autoconf.h"
5 #include "automation.h"
6 #include "awindowgui.inc"
7 #include "bcsignals.h"
8 #include "clip.h"
9 #include "colormodels.h"
10 #include "defaults.h"
11 #include "edl.h"
12 #include "edlsession.h"
13 #include "filexml.h"
14 #include "guicast.h"
15 #include "labels.h"
16 #include "localsession.h"
17 #include "panauto.h"
18 #include "panautos.h"
19 #include "playbackconfig.h"
20 #include "plugin.h"
21 #include "preferences.h"
22 #include "recordconfig.h"
23 #include "recordlabel.h"
24 #include "sharedlocation.h"
25 #include "theme.h"
26 #include "tracks.h"
27 #include "transportque.inc"
28 #include "vtrack.h"
30 EDL::EDL(EDL *parent_edl)
32         this->parent_edl = parent_edl;
33         tracks = 0;
34         labels = 0;
35         local_session = 0;
36         vwindow_edl = 0;
38         folders.set_array_delete();
39         new_folder(CLIP_FOLDER);
40         new_folder(MEDIA_FOLDER);
41         id = next_id();
42         project_path[0] = 0;
46 EDL::~EDL()
48 //printf("EDL::~EDL 1\n");
49         if(tracks)
50         {
51                 delete tracks;
52         }
53         if(labels)
54         {
55                 delete labels;
56         }
58         if(local_session)
59         {
60                 delete local_session;
61         }
63         if(vwindow_edl)
64                 delete vwindow_edl;
66         if(!parent_edl)
67         {
68                 delete assets;
69                 delete session;
70         }
73         folders.remove_all_objects();
74         clips.remove_all_objects();
75 //printf("EDL::~EDL 2\n");
79 int EDL::create_objects()
81         tracks = new Tracks(this);
82         if(!parent_edl)
83         {
84                 assets = new Assets(this);
85                 session = new EDLSession(this);
86         }
87         else
88         {
89                 assets = parent_edl->assets;
90                 session = parent_edl->session;
91         }
92         
93         local_session = new LocalSession(this);
94         labels = new Labels(this, "LABELS");
95 //      last_playback_position = 0;
96         return 0;
99 EDL& EDL::operator=(EDL &edl)
101 printf("EDL::operator= 1\n");
102         copy_all(&edl);
103         return *this;
106 int EDL::load_defaults(Defaults *defaults)
108         if(!parent_edl)
109                 session->load_defaults(defaults);
111         local_session->load_defaults(defaults);
112         return 0;
115 int EDL::save_defaults(Defaults *defaults)
117         if(!parent_edl)
118                 session->save_defaults(defaults);
119         
120         local_session->save_defaults(defaults);
121         return 0;
124 void EDL::boundaries()
126         session->boundaries();
127         local_session->boundaries();
130 int EDL::create_default_tracks()
133         for(int i = 0; i < session->video_tracks; i++)
134         {
135                 tracks->add_video_track(0, 0);
136         }
137         for(int i = 0; i < session->audio_tracks; i++)
138         {
139                 tracks->add_audio_track(0, 0);
140         }
141         return 0;
144 int EDL::load_xml(ArrayList<PluginServer*> *plugindb,
145         FileXML *file, 
146         uint32_t load_flags)
148         int result = 0;
149 // Track numbering offset for replacing undo data.
150         int track_offset = 0;
152         folders.remove_all_objects();
154 // Search for start of master EDL.
156 // The parent_edl test caused clip creation to fail since those XML files
157 // contained an EDL tag.
159 // The parent_edl test is required to make EDL loading work because
160 // when loading an EDL the EDL tag is already read by the parent.
162         if(!parent_edl)
163         {
164                 do{
165                   result = file->read_tag();
166                 }while(!result && 
167                         !file->tag.title_is("XML") && 
168                         !file->tag.title_is("EDL"));
169         }
171         if(!result)
172         {
173 // Get path for backups
174                 project_path[0] = 0;
175                 file->tag.get_property("PROJECT_PATH", project_path);
177 // Erase everything
178                 if((load_flags & LOAD_ALL) == LOAD_ALL ||
179                         (load_flags & LOAD_EDITS) == LOAD_EDITS)
180                 {
181                         while(tracks->last) delete tracks->last;
182                 }
184                 if((load_flags & LOAD_ALL) == LOAD_ALL)
185                 {
186                         clips.remove_all_objects();
187                 }
189                 if(load_flags & LOAD_TIMEBAR)
190                 {
191                         while(labels->last) delete labels->last;
192                         local_session->unset_inpoint();
193                         local_session->unset_outpoint();
194                 }
196                 do{
197                         result = file->read_tag();
199                         if(!result)
200                         {
201                                 if(file->tag.title_is("/XML") ||
202                                         file->tag.title_is("/EDL") ||
203                                         file->tag.title_is("/CLIP_EDL") ||
204                                         file->tag.title_is("/VWINDOW_EDL"))
205                                 {
206                                         result = 1;
207                                 }
208                                 else
209                                 if(file->tag.title_is("CLIPBOARD"))
210                                 {
211                                         local_session->clipboard_length = file->tag.get_property("LENGTH", 0);
212                                 }
213                                 else
214                                 if(file->tag.title_is("VIDEO"))
215                                 {
216                                         if((load_flags & LOAD_VCONFIG) &&
217                                                 (load_flags & LOAD_SESSION))
218                                                 session->load_video_config(file, 0, load_flags);
219                                 }
220                                 else
221                                 if(file->tag.title_is("AUDIO"))
222                                 {
223                                         if((load_flags & LOAD_ACONFIG) &&
224                                                 (load_flags & LOAD_SESSION))
225                                                 session->load_audio_config(file, 0, load_flags);
226                                 }
227                                 else
228                                 if(file->tag.title_is("FOLDER"))
229                                 {
230                                         char folder[BCTEXTLEN];
231                                         strcpy(folder, file->read_text());
232                                         new_folder(folder);
233                                 }
234                                 else
235                                 if(file->tag.title_is("ASSETS"))
236                                 {
237                                         if(load_flags & LOAD_ASSETS)
238                                                 assets->load(plugindb, file, load_flags);
239                                 }
240                                 else
241                                 if(file->tag.title_is(labels->xml_tag))
242                                 {
243                                         if(load_flags & LOAD_TIMEBAR)
244                                                 labels->load(file, load_flags);
245                                 }
246                                 else
247                                 if(file->tag.title_is("LOCALSESSION"))
248                                 {
249                                         if((load_flags & LOAD_SESSION) ||
250                                                 (load_flags & LOAD_TIMEBAR))
251                                                 local_session->load_xml(file, load_flags);
252                                 }
253                                 else
254                                 if(file->tag.title_is("SESSION"))
255                                 {
256                                         if((load_flags & LOAD_SESSION) &&
257                                                 !parent_edl)
258                                                 session->load_xml(file, 0, load_flags);
259                                 }
260                                 else
261                                 if(file->tag.title_is("TRACK"))
262                                 {
263                                         tracks->load(file, track_offset, load_flags);
264                                 }
265                                 else
266 // Sub EDL.
267 // Causes clip creation to fail because that involves an opening EDL tag.
268                                 if(file->tag.title_is("CLIP_EDL") && !parent_edl)
269                                 {
270                                         EDL *new_edl = new EDL(this);
271                                         new_edl->create_objects();
272                                         new_edl->load_xml(plugindb, file, LOAD_ALL);
274                                         if((load_flags & LOAD_ALL) == LOAD_ALL)
275                                                 clips.append(new_edl);
276                                         else
277                                                 delete new_edl;
278                                 }
279                                 else
280                                 if(file->tag.title_is("VWINDOW_EDL") && !parent_edl)
281                                 {
282                                         EDL *new_edl = new EDL(this);
283                                         new_edl->create_objects();
284                                         new_edl->load_xml(plugindb, file, LOAD_ALL);
287                                         if((load_flags & LOAD_ALL) == LOAD_ALL)
288                                         {
289                                                 if(vwindow_edl) delete vwindow_edl;
290                                                 vwindow_edl = new_edl;
291                                         }
292                                         else
293                                         {
294                                                 delete new_edl;
295                                                 new_edl = 0;
296                                         }
297                                 }
298                         }
299                 }while(!result);
300 //printf("EDL::load_xml 4\n");
301         }
302         boundaries();
303 //printf("EDL::load_xml 6 %p\n", parent_edl);
304 //dump();
306         return 0;
309 // Output path is the path of the output file if name truncation is desired.
310 // It is a "" if complete names should be used.
311 // Called recursively by copy for clips, thus the string can't be terminated.
312 // The string is not terminated in this call.
313 int EDL::save_xml(ArrayList<PluginServer*> *plugindb,
314         FileXML *file, 
315         char *output_path,
316         int is_clip,
317         int is_vwindow)
319         copy(0, 
320                 tracks->total_length(), 
321                 1, 
322                 is_clip,
323                 is_vwindow,
324                 file, 
325                 plugindb, 
326                 output_path,
327                 0);
328         return 0;
331 int EDL::copy_all(EDL *edl)
333         copy_session(edl);
334         copy_assets(edl);
335         copy_clips(edl);
336         tracks->copy_from(edl->tracks);
337         labels->copy_from(edl->labels);
338         return 0;
341 void EDL::copy_clips(EDL *edl)
343         if(vwindow_edl) delete vwindow_edl;
344         vwindow_edl = 0;
345         if(edl->vwindow_edl)
346         {
347                 vwindow_edl = new EDL(this);
348                 vwindow_edl->create_objects();
349                 vwindow_edl->copy_all(edl->vwindow_edl);
350         }
351         clips.remove_all_objects();
352         for(int i = 0; i < edl->clips.total; i++)
353         {
354                 add_clip(edl->clips.values[i]);
355         }
358 void EDL::copy_assets(EDL *edl)
360         if(!parent_edl)
361         {
362                 assets->copy_from(edl->assets);
363         }
366 void EDL::copy_session(EDL *edl)
368         strcpy(this->project_path, edl->project_path);
370         folders.remove_all_objects();
371         for(int i = 0; i < edl->folders.total; i++)
372         {
373                 char *new_folder;
374                 folders.append(new_folder = new char[strlen(edl->folders.values[i]) + 1]);
375                 strcpy(new_folder, edl->folders.values[i]);
376         }
378         if(!parent_edl)
379         {
380                 session->copy(edl->session);
381         }
382         
383         local_session->copy_from(edl->local_session);
386 int EDL::copy_assets(double start, 
387         double end, 
388         FileXML *file, 
389         int all, 
390         ArrayList<PluginServer*> *plugindb,
391         char *output_path)
393         ArrayList<Asset*> asset_list;
394         Track* current;
396         file->tag.set_title("ASSETS");
397         file->append_tag();
398         file->append_newline();
400 // Copy everything for a save
401         if(all)
402         {
403                 for(Asset *asset = assets->first;
404                         asset;
405                         asset = asset->next)
406                 {
407                         asset_list.append(asset);
408                 }
409         }
410         else
411 // Copy just the ones being used.
412         {
413                 for(current = tracks->first; 
414                         current; 
415                         current = NEXT)
416                 {
417                         if(current->record)
418                         {
419                                 current->copy_assets(start, 
420                                         end, 
421                                         &asset_list);
422                         }
423                 }
424         }
426 // Paths relativised here
427         for(int i = 0; i < asset_list.total; i++)
428         {
429                 asset_list.values[i]->write(file, 
430                         0, 
431                         output_path);
432         }
434         file->tag.set_title("/ASSETS");
435         file->append_tag();
436         file->append_newline();
437         file->append_newline();
438         return 0;
441 int EDL::copy(double start, 
442         double end, 
443         int all, 
444         int is_clip,
445         int is_vwindow,
446         FileXML *file, 
447         ArrayList<PluginServer*> *plugindb, 
448         char *output_path,
449         int rewind_it)
451 //printf("EDL::copy 1\n");
452 // begin file
453         if(is_clip)
454                 file->tag.set_title("CLIP_EDL");
455         else
456         if(is_vwindow)
457                 file->tag.set_title("VWINDOW_EDL");
458         else
459         {
460                 file->tag.set_title("EDL");
461                 file->tag.set_property("VERSION", CINELERRA_VERSION);
462 // Save path for restoration of the project title from a backup.
463                 if(this->project_path[0])
464                 {
465                         file->tag.set_property("PROJECT_PATH", project_path);
466                 }
467         }
469         file->append_tag();
470         file->append_newline();
472 // Set clipboard samples only if copying to clipboard
473         if(!all)
474         {
475                 file->tag.set_title("CLIPBOARD");
476                 file->tag.set_property("LENGTH", end - start);
477                 file->append_tag();
478                 file->tag.set_title("/CLIPBOARD");
479                 file->append_tag();
480                 file->append_newline();
481                 file->append_newline();
482         }
483 //printf("EDL::copy 1\n");
485 // Sessions
486         local_session->save_xml(file, start);
488 //printf("EDL::copy 1\n");
490 // Top level stuff.
491 //      if(!parent_edl)
492         {
493 // Need to copy all this from child EDL if pasting is desired.
494 // Session
495                 session->save_xml(file);
496                 session->save_video_config(file);
497                 session->save_audio_config(file);
499 // Folders
500                 for(int i = 0; i < folders.total; i++)
501                 {
502                         file->tag.set_title("FOLDER");
503                         file->append_tag();
504                         file->append_text(folders.values[i]);
505                         file->tag.set_title("/FOLDER");
506                         file->append_tag();
507                         file->append_newline();
508                 }
510 // Media
511                 copy_assets(start, 
512                         end, 
513                         file, 
514                         all, 
515                         plugindb,
516                         output_path);
518 // Clips
519 // Don't want this if using clipboard
520                 if(all)
521                 {
522                         if(vwindow_edl)
523                         {
524                                 
525                                 vwindow_edl->save_xml(plugindb, 
526                                         file, 
527                                         output_path,
528                                         0,
529                                         1);
530                         }
532                         for(int i = 0; i < clips.total; i++)
533                                 clips.values[i]->save_xml(plugindb, 
534                                         file, 
535                                         output_path,
536                                         1,
537                                         0);
538                 }
540                 file->append_newline();
541                 file->append_newline();
542         }
545 //printf("EDL::copy 1\n");
547         labels->copy(start, end, file);
548 //printf("EDL::copy 1\n");
549         tracks->copy(start, end, all, file, output_path);
550 //printf("EDL::copy 2\n");
552 // terminate file
553         if(is_clip)
554                 file->tag.set_title("/CLIP_EDL");
555         else
556         if(is_vwindow)
557                 file->tag.set_title("/VWINDOW_EDL");
558         else
559                 file->tag.set_title("/EDL");
560         file->append_tag();
561         file->append_newline();
564 // For editing operations we want to rewind it for immediate pasting.
565 // For clips and saving to disk leave it alone.
566         if(rewind_it)
567         {
568                 file->terminate_string();
569                 file->rewind();
570         }
571         return 0;
574 void EDL::rechannel()
576         for(Track *current = tracks->first; current; current = NEXT)
577         {
578                 if(current->data_type == TRACK_AUDIO)
579                 {
580                         PanAutos *autos = (PanAutos*)current->automation->autos[AUTOMATION_PAN];
581                         ((PanAuto*)autos->default_auto)->rechannel();
582                         for(PanAuto *keyframe = (PanAuto*)autos->first;
583                                 keyframe;
584                                 keyframe = (PanAuto*)keyframe->next)
585                         {
586                                 keyframe->rechannel();
587                         }
588                 }
589         }
592 void EDL::resample(double old_rate, double new_rate, int data_type)
594         for(Track *current = tracks->first; current; current = NEXT)
595         {
596                 if(current->data_type == data_type)
597                 {
598                         current->resample(old_rate, new_rate);
599                 }
600         }
604 void EDL::synchronize_params(EDL *edl)
606         local_session->synchronize_params(edl->local_session);
607         for(Track *this_track = tracks->first, *that_track = edl->tracks->first; 
608                 this_track && that_track; 
609                 this_track = this_track->next,
610                 that_track = that_track->next)
611         {
612                 this_track->synchronize_params(that_track);
613         }
616 int EDL::trim_selection(double start, 
617         double end,
618         int edit_labels,
619         int edit_plugins)
621         if(start != end)
622         {
623 // clear the data
624                 clear(0, 
625                         start,
626                         edit_labels,
627                         edit_plugins);
628                 clear(end - start, 
629                         tracks->total_length(),
630                         edit_labels,
631                         edit_plugins);
632         }
633         return 0;
637 int EDL::equivalent(double position1, double position2)
639         double threshold = (double).5 / session->frame_rate;
640         if(session->cursor_on_frames) 
641                 threshold = (double).5 / session->frame_rate;
642         else
643                 threshold = (double)1 / session->sample_rate;
645         if(fabs(position2 - position1) < threshold)
646         return 1;
647     else
648         return 0;
651 double EDL::equivalent_output(EDL *edl)
653         double result = -1;
654         session->equivalent_output(edl->session, &result);
655         tracks->equivalent_output(edl->tracks, &result);
656         return result;
660 void EDL::set_project_path(char *path)
662         strcpy(this->project_path, path);
665 void EDL::set_inpoint(double position)
667         if(equivalent(local_session->get_inpoint(), position) && 
668                 local_session->get_inpoint() >= 0)
669         {
670                 local_session->unset_inpoint();
671         }
672         else
673         {
674                 local_session->set_inpoint(align_to_frame(position, 0));
675                 if(local_session->get_outpoint() <= local_session->get_inpoint()) 
676                         local_session->unset_outpoint();
677         }
680 void EDL::set_outpoint(double position)
682         if(equivalent(local_session->get_outpoint(), position) && 
683                 local_session->get_outpoint() >= 0)
684         {
685                 local_session->unset_outpoint();
686         }
687         else
688         {
689                 local_session->set_outpoint(align_to_frame(position, 0));
690                 if(local_session->get_inpoint() >= local_session->get_outpoint()) 
691                         local_session->unset_inpoint();
692         }
696 int EDL::clear(double start, 
697         double end, 
698         int clear_labels,
699         int clear_plugins)
701         if(start == end)
702         {
703                 double distance = 0;
704                 tracks->clear_handle(start, 
705                         end,
706                         distance, 
707                         clear_labels,
708                         clear_plugins);
709                 if(clear_labels && distance > 0)
710                         labels->paste_silence(start, 
711                                 start + distance);
712         }
713         else
714         {
715                 tracks->clear(start, 
716                         end,
717                         clear_plugins);
718                 if(clear_labels) 
719                         labels->clear(start, 
720                                 end, 
721                                 1);
722         }
724 // Need to put at beginning so a subsequent paste operation starts at the
725 // right position.
726         double position = local_session->get_selectionstart();
727         local_session->set_selectionend(position);
728         local_session->set_selectionstart(position);
729         return 0;
732 void EDL::modify_edithandles(double oldposition, 
733         double newposition, 
734         int currentend,
735         int handle_mode,
736         int edit_labels,
737         int edit_plugins)
739         tracks->modify_edithandles(oldposition, 
740                 newposition, 
741                 currentend,
742                 handle_mode,
743                 edit_labels, 
744                 edit_plugins);
745         labels->modify_handles(oldposition, 
746                 newposition, 
747                 currentend,
748                 handle_mode,
749                 edit_labels);
752 void EDL::modify_pluginhandles(double oldposition, 
753         double newposition, 
754         int currentend, 
755         int handle_mode,
756         int edit_labels,
757         Edits *trim_edits)
759         tracks->modify_pluginhandles(oldposition, 
760                 newposition, 
761                 currentend, 
762                 handle_mode,
763                 edit_labels,
764                 trim_edits);
765         optimize();
768 void EDL::paste_silence(double start, 
769         double end, 
770         int edit_labels, 
771         int edit_plugins)
773         if(edit_labels) 
774                 labels->paste_silence(start, end);
775         tracks->paste_silence(start, 
776                 end, 
777                 edit_plugins);
781 void EDL::remove_from_project(ArrayList<EDL*> *clips)
783         for(int i = 0; i < clips->total; i++)
784         {
785                 for(int j = 0; j < this->clips.total; j++)
786                 {
787                         if(this->clips.values[j] == clips->values[i])
788                         {
789                                 this->clips.remove_object(clips->values[i]);
790                         }
791                 }
792         }
795 void EDL::remove_from_project(ArrayList<Asset*> *assets)
797 // Remove from clips
798         if(!parent_edl)
799                 for(int j = 0; j < clips.total; j++)
800                 {
801                         clips.values[j]->remove_from_project(assets);
802                 }
804 // Remove from VWindow
805         if(vwindow_edl)
806                 vwindow_edl->remove_from_project(assets);
808         for(int i = 0; i < assets->total; i++)
809         {
810 // Remove from tracks
811                 for(Track *track = tracks->first; track; track = track->next)
812                 {
813                         track->remove_asset(assets->values[i]);
814                 }
816 // Remove from assets
817                 if(!parent_edl)
818                 {
819                         this->assets->remove_asset(assets->values[i]);
820                 }
821         }
824 void EDL::update_assets(EDL *src)
826         for(Asset *current = src->assets->first;
827                 current;
828                 current = NEXT)
829         {
830                 assets->update(current);
831         }
834 int EDL::get_tracks_height(Theme *theme)
836         int total_pixels = 0;
837         for(Track *current = tracks->first;
838                 current;
839                 current = NEXT)
840         {
841                 total_pixels += current->vertical_span(theme);
842         }
843         return total_pixels;
846 int64_t EDL::get_tracks_width()
848         int64_t total_pixels = 0;
849         for(Track *current = tracks->first;
850                 current;
851                 current = NEXT)
852         {
853                 int64_t pixels = current->horizontal_span();
854                 if(pixels > total_pixels) total_pixels = pixels;
855         }
856 //printf("EDL::get_tracks_width %d\n", total_pixels);
857         return total_pixels;
860 // int EDL::calculate_output_w(int single_channel)
861 // {
862 //      if(single_channel) return session->output_w;
863 // 
864 //      int widest = 0;
865 //      for(int i = 0; i < session->video_channels; i++)
866 //      {
867 //              if(session->vchannel_x[i] + session->output_w > widest) widest = session->vchannel_x[i] + session->output_w;
868 //      }
869 //      return widest;
870 // }
871 // 
872 // int EDL::calculate_output_h(int single_channel)
873 // {
874 //      if(single_channel) return session->output_h;
875 // 
876 //      int tallest = 0;
877 //      for(int i = 0; i < session->video_channels; i++)
878 //      {
879 //              if(session->vchannel_y[i] + session->output_h > tallest) tallest = session->vchannel_y[i] + session->output_h;
880 //      }
881 //      return tallest;
882 // }
884 // Get the total output size scaled to aspect ratio
885 void EDL::calculate_conformed_dimensions(int single_channel, float &w, float &h)
887         w = session->output_w;
888         h = session->output_h;
890         if((float)session->output_w / session->output_h > get_aspect_ratio())
891         {
892                 h = (float)h * 
893                         (session->output_w / get_aspect_ratio() / session->output_h);
894         }
895         else
896         {
897                 w = (float)w * 
898                         (h * get_aspect_ratio() / session->output_w);
899         }
902 float EDL::get_aspect_ratio()
904         return session->aspect_w / session->aspect_h;
907 int EDL::dump()
909         if(parent_edl)
910                 printf("CLIP\n");
911         else
912                 printf("EDL\n");
913         printf("clip_title: %s parent_edl: %p\n", local_session->clip_title, parent_edl);
914         printf("selectionstart %f selectionend %f loop_start %f loop_end %f\n", 
915                 local_session->get_selectionstart(1), 
916                 local_session->get_selectionend(1),
917                 local_session->loop_start,
918                 local_session->loop_end);
920         if(!parent_edl)
921         {
922                 printf("audio_channels: %d "
923                         "audio_tracks: %d \n"
924                         "sample_rate: %d\n",
925                         session->audio_channels,
926                         session->audio_tracks,
927                         session->sample_rate);
928                 printf("video_channels: %d "
929                         "video_tracks: %d "
930                         "frame_rate: %.2f "
931                         "frames_per_foot: %.2f\n"
932                 "output_w: %d "
933                 "output_h: %d "
934                 "aspect_w: %f "
935                 "aspect_h %f "
936                         "color_model %d\n",
937                                 session->video_channels,
938                                 session->video_tracks,
939                                 session->frame_rate,
940                                 session->frames_per_foot,
941                         session->output_w,
942                         session->output_h,
943                         session->aspect_w,
944                         session->aspect_h,
945                                 session->color_model);
947                 printf(" EDLS\n");
948                 printf("  total: %d\n", clips.total);
949         
950                 for(int i = 0; i < clips.total; i++)
951                 {
952                         printf("\n\n");
953                         clips.values[i]->dump();
954                         printf("\n\n");
955                 }
957                 printf(" ASSETS\n");
958                 assets->dump();
959         }
960         printf(" LABELS\n");
961         labels->dump();
962         printf(" TRACKS\n");
963         tracks->dump();
964 //printf("EDL::dump 2\n");
965         return 0;
968 EDL* EDL::add_clip(EDL *edl)
970 // Copy argument.  New edls are deleted from MWindow::load_filenames.
971         EDL *new_edl = new EDL(this);
972         new_edl->create_objects();
973         new_edl->copy_all(edl);
974         clips.append(new_edl);
975         return new_edl;
978 void EDL::insert_asset(Asset *asset, 
979         double position, 
980         Track *first_track, 
981         RecordLabels *labels)
983 // Insert asset into asset table
984         Asset *new_asset = assets->update(asset);
987 // Paste video
988         int vtrack = 0;
989         Track *current = first_track ? first_track : tracks->first;
992 // Fix length of single frame
993         double length;
996         if(new_asset->video_length < 0) 
997         {
998         if(session->si_useduration)
999                 length = session->si_duration;
1000         else    
1001                 length = 1.0 / session->frame_rate; 
1002         }
1003         else
1004         if(new_asset->frame_rate > 0)
1005                 length = ((double)new_asset->video_length / new_asset->frame_rate);
1006         else
1007                 length = 1.0 / session->frame_rate;
1009         for( ;
1010                 current && vtrack < new_asset->layers;
1011                 current = NEXT)
1012         {
1013                 if(!current->record || 
1014                         current->data_type != TRACK_VIDEO)
1015                         continue;
1017                 current->insert_asset(new_asset, 
1018                         length, 
1019                         position, 
1020                         vtrack);
1022                 vtrack++;
1023         }
1025         int atrack = 0;
1026         for(current = tracks->first;
1027                 current && atrack < new_asset->channels;
1028                 current = NEXT)
1029         {
1030                 if(!current->record ||
1031                         current->data_type != TRACK_AUDIO)
1032                         continue;
1034                 current->insert_asset(new_asset, 
1035                         (double)new_asset->audio_length / 
1036                                 new_asset->sample_rate, 
1037                         position, 
1038                         atrack);
1041                 atrack++;
1042         }
1044         if(labels)
1045         {
1046                 for(RecordLabel *label = labels->first; label; label = label->next)
1047                 {
1048                         this->labels->toggle_label(label->position, label->position);
1049                 }
1050         }
1055 void EDL::set_index_file(Asset *asset)
1057         assets->update_index(asset);
1060 void EDL::optimize()
1062 //printf("EDL::optimize 1\n");
1063         double length = tracks->total_length();
1064         if(local_session->preview_end > length) local_session->preview_end = length;
1065         if(local_session->preview_start > length ||
1066                 local_session->preview_start < 0) local_session->preview_start = 0;
1067         for(Track *current = tracks->first; current; current = NEXT)
1068                 current->optimize();
1071 int EDL::next_id()
1073         return EDLSession::current_id++;
1076 void EDL::get_shared_plugins(Track *source, 
1077         ArrayList<SharedLocation*> *plugin_locations)
1079         for(Track *track = tracks->first; track; track = track->next)
1080         {
1081                 if(track != source && 
1082                         track->data_type == source->data_type)
1083                 {
1084                         for(int i = 0; i < track->plugin_set.total; i++)
1085                         {
1086                                 Plugin *plugin = track->get_current_plugin(
1087                                         local_session->get_selectionstart(1), 
1088                                         i, 
1089                                         PLAY_FORWARD, 
1090                                         1,
1091                                         0);
1092                                 if(plugin && plugin->plugin_type == PLUGIN_STANDALONE)
1093                                 {
1094                                         plugin_locations->append(new SharedLocation(tracks->number_of(track), i));
1095                                 }
1096                         }
1097                 }
1098         }
1101 void EDL::get_shared_tracks(Track *track, ArrayList<SharedLocation*> *module_locations)
1103         for(Track *current = tracks->first; current; current = NEXT)
1104         {
1105                 if(current != track && 
1106                         current->data_type == track->data_type)
1107                 {
1108                         module_locations->append(new SharedLocation(tracks->number_of(current), 0));
1109                 }
1110         }
1113 // Convert position to frames if cursor alignment is enabled
1114 double EDL::align_to_frame(double position, int round)
1116 //printf("EDL::align_to_frame 1 %f\n", position);
1117         if(session->cursor_on_frames)
1118         {
1119 // Seconds -> Frames
1120                 double temp = (double)position * session->frame_rate;
1121 //printf("EDL::align_to_frame 2 %f\n", temp);
1123 // Assert some things
1124                 if(session->sample_rate == 0)
1125                         printf("EDL::align_to_frame: sample_rate == 0\n");
1127                 if(session->frame_rate == 0)
1128                         printf("EDL::align_to_frame: frame_rate == 0\n");
1130 // Round frames
1131 // Always round down negative numbers
1132 // but round up only if requested
1133                 if(round) 
1134                 {
1135                         temp = Units::round(temp);
1136                 }
1137                 else
1138                 {
1139 //                      if(temp < 0)
1140 //                      {
1141 //                              temp -= 0.5;
1142 //                      }
1143 //                      else
1144                                 temp = Units::to_int64(temp);
1145                 }
1146 //printf("EDL::align_to_frame 3 %f\n", temp);
1148 // Frames -> Seconds
1149                 temp /= session->frame_rate;
1151 //printf("EDL::align_to_frame 5 %f\n", temp);
1153                 return temp;
1154         }
1155 //printf("EDL::align_to_frame 3 %d\n", position);
1158         return position;
1162 void EDL::new_folder(char *folder)
1164         for(int i = 0; i < folders.total; i++)
1165         {
1166                 if(!strcasecmp(folders.values[i], folder)) return;
1167         }
1169         char *new_folder;
1170         folders.append(new_folder = new char[strlen(folder) + 1]);
1171         strcpy(new_folder, folder);
1174 void EDL::delete_folder(char *folder)
1176         int i;
1177         for(i = 0; i < folders.total; i++)
1178         {
1179                 if(!strcasecmp(folders.values[i], folder))
1180                 {
1181                         break;
1182                 }
1183         }
1185         if(i < folders.total) delete folders.values[i];
1187         for( ; i < folders.total - 1; i++)
1188         {
1189                 folders.values[i] = folders.values[i + 1];
1190         }