r802: Remove renderframfsclient and renderfarmfsserver .h and .C from Makefile.am...
[cinelerra_cv/mob.git] / cinelerra / edl.C
blobccd6cc4d69481162c39689cd6869039fff9b53a2
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;
37         vwindow_edl_shared = 0;
39         folders.set_array_delete();
40         new_folder(CLIP_FOLDER);
41         new_folder(MEDIA_FOLDER);
42         id = next_id();
43         project_path[0] = 0;
47 EDL::~EDL()
49 //printf("EDL::~EDL 1\n");
50         if(tracks)
51         {
52                 delete tracks;
53         }
54         if(labels)
55         {
56                 delete labels;
57         }
59         if(local_session)
60         {
61                 delete local_session;
62         }
64         if(vwindow_edl && !vwindow_edl_shared)
65                 delete vwindow_edl;
67         if(!parent_edl)
68         {
69                 delete assets;
70                 delete session;
71         }
74         folders.remove_all_objects();
75         clips.remove_all_objects();
76 //printf("EDL::~EDL 2\n");
80 int EDL::create_objects()
82         tracks = new Tracks(this);
83         if(!parent_edl)
84         {
85                 assets = new Assets(this);
86                 session = new EDLSession(this);
87         }
88         else
89         {
90                 assets = parent_edl->assets;
91                 session = parent_edl->session;
92         }
93         
94         local_session = new LocalSession(this);
95         labels = new Labels(this, "LABELS");
96 //      last_playback_position = 0;
97         return 0;
100 EDL& EDL::operator=(EDL &edl)
102 printf("EDL::operator= 1\n");
103         copy_all(&edl);
104         return *this;
107 int EDL::load_defaults(Defaults *defaults)
109         if(!parent_edl)
110                 session->load_defaults(defaults);
112         local_session->load_defaults(defaults);
113         return 0;
116 int EDL::save_defaults(Defaults *defaults)
118         if(!parent_edl)
119                 session->save_defaults(defaults);
120         
121         local_session->save_defaults(defaults);
122         return 0;
125 void EDL::boundaries()
127         session->boundaries();
128         local_session->boundaries();
131 int EDL::create_default_tracks()
134         for(int i = 0; i < session->video_tracks; i++)
135         {
136                 tracks->add_video_track(0, 0);
137         }
138         for(int i = 0; i < session->audio_tracks; i++)
139         {
140                 tracks->add_audio_track(0, 0);
141         }
142         return 0;
145 int EDL::load_xml(ArrayList<PluginServer*> *plugindb,
146         FileXML *file, 
147         uint32_t load_flags)
149         int result = 0;
150 // Track numbering offset for replacing undo data.
151         int track_offset = 0;
153         folders.remove_all_objects();
155 // Search for start of master EDL.
157 // The parent_edl test caused clip creation to fail since those XML files
158 // contained an EDL tag.
160 // The parent_edl test is required to make EDL loading work because
161 // when loading an EDL the EDL tag is already read by the parent.
163         if(!parent_edl)
164         {
165                 do{
166                   result = file->read_tag();
167                 }while(!result && 
168                         !file->tag.title_is("XML") && 
169                         !file->tag.title_is("EDL"));
170         }
172         if(!result)
173         {
174 // Get path for backups
175                 project_path[0] = 0;
176                 file->tag.get_property("PROJECT_PATH", project_path);
178 // Erase everything
179                 if((load_flags & LOAD_ALL) == LOAD_ALL ||
180                         (load_flags & LOAD_EDITS) == LOAD_EDITS)
181                 {
182                         while(tracks->last) delete tracks->last;
183                 }
185                 if((load_flags & LOAD_ALL) == LOAD_ALL)
186                 {
187                         clips.remove_all_objects();
188                 }
190                 if(load_flags & LOAD_TIMEBAR)
191                 {
192                         while(labels->last) delete labels->last;
193                         local_session->unset_inpoint();
194                         local_session->unset_outpoint();
195                 }
197                 do{
198                         result = file->read_tag();
200                         if(!result)
201                         {
202                                 if(file->tag.title_is("/XML") ||
203                                         file->tag.title_is("/EDL") ||
204                                         file->tag.title_is("/CLIP_EDL") ||
205                                         file->tag.title_is("/VWINDOW_EDL"))
206                                 {
207                                         result = 1;
208                                 }
209                                 else
210                                 if(file->tag.title_is("CLIPBOARD"))
211                                 {
212                                         local_session->clipboard_length = file->tag.get_property("LENGTH", 0);
213                                 }
214                                 else
215                                 if(file->tag.title_is("VIDEO"))
216                                 {
217                                         if((load_flags & LOAD_VCONFIG) &&
218                                                 (load_flags & LOAD_SESSION))
219                                                 session->load_video_config(file, 0, load_flags);
220                                 }
221                                 else
222                                 if(file->tag.title_is("AUDIO"))
223                                 {
224                                         if((load_flags & LOAD_ACONFIG) &&
225                                                 (load_flags & LOAD_SESSION))
226                                                 session->load_audio_config(file, 0, load_flags);
227                                 }
228                                 else
229                                 if(file->tag.title_is("FOLDER"))
230                                 {
231                                         char folder[BCTEXTLEN];
232                                         strcpy(folder, file->read_text());
233                                         new_folder(folder);
234                                 }
235                                 else
236                                 if(file->tag.title_is("ASSETS"))
237                                 {
238                                         if(load_flags & LOAD_ASSETS)
239                                                 assets->load(plugindb, file, load_flags);
240                                 }
241                                 else
242                                 if(file->tag.title_is(labels->xml_tag))
243                                 {
244                                         if(load_flags & LOAD_TIMEBAR)
245                                                 labels->load(file, load_flags);
246                                 }
247                                 else
248                                 if(file->tag.title_is("LOCALSESSION"))
249                                 {
250                                         if((load_flags & LOAD_SESSION) ||
251                                                 (load_flags & LOAD_TIMEBAR))
252                                                 local_session->load_xml(file, load_flags);
253                                 }
254                                 else
255                                 if(file->tag.title_is("SESSION"))
256                                 {
257                                         if((load_flags & LOAD_SESSION) &&
258                                                 !parent_edl)
259                                                 session->load_xml(file, 0, load_flags);
260                                 }
261                                 else
262                                 if(file->tag.title_is("TRACK"))
263                                 {
264                                         tracks->load(file, track_offset, load_flags);
265                                 }
266                                 else
267 // Sub EDL.
268 // Causes clip creation to fail because that involves an opening EDL tag.
269                                 if(file->tag.title_is("CLIP_EDL") && !parent_edl)
270                                 {
271                                         EDL *new_edl = new EDL(this);
272                                         new_edl->create_objects();
273                                         new_edl->load_xml(plugindb, file, LOAD_ALL);
275                                         if((load_flags & LOAD_ALL) == LOAD_ALL)
276                                                 clips.append(new_edl);
277                                         else
278                                                 delete new_edl;
279                                 }
280                                 else
281                                 if(file->tag.title_is("VWINDOW_EDL") && !parent_edl)
282                                 {
283                                         EDL *new_edl = new EDL(this);
284                                         new_edl->create_objects();
285                                         new_edl->load_xml(plugindb, file, LOAD_ALL);
288                                         if((load_flags & LOAD_ALL) == LOAD_ALL)
289                                         {
290                                                 if(vwindow_edl && !vwindow_edl_shared) delete vwindow_edl;
291                                                 vwindow_edl = new_edl;
292                                                 vwindow_edl_shared = 0;
293                                         }
294                                         else
295                                         {
296                                                 delete new_edl;
297                                                 new_edl = 0;
298                                         }
299                                 }
300                         }
301                 }while(!result);
302 //printf("EDL::load_xml 4\n");
303         }
304         boundaries();
305 //printf("EDL::load_xml 6 %p\n", parent_edl);
306 //dump();
308         return 0;
311 // Output path is the path of the output file if name truncation is desired.
312 // It is a "" if complete names should be used.
313 // Called recursively by copy for clips, thus the string can't be terminated.
314 // The string is not terminated in this call.
315 int EDL::save_xml(ArrayList<PluginServer*> *plugindb,
316         FileXML *file, 
317         char *output_path,
318         int is_clip,
319         int is_vwindow)
321         copy(0, 
322                 tracks->total_length(), 
323                 1, 
324                 is_clip,
325                 is_vwindow,
326                 file, 
327                 plugindb, 
328                 output_path,
329                 0);
330         return 0;
333 int EDL::copy_all(EDL *edl)
335         copy_session(edl);
336         copy_assets(edl);
337         copy_clips(edl);
338         tracks->copy_from(edl->tracks);
339         labels->copy_from(edl->labels);
340         return 0;
343 void EDL::copy_clips(EDL *edl)
345         if(vwindow_edl && !vwindow_edl_shared) delete vwindow_edl;
346         vwindow_edl = 0;
347         vwindow_edl_shared = 0;
348         if(edl->vwindow_edl)
349         {
350                 vwindow_edl = new EDL(this);
351                 vwindow_edl->create_objects();
352                 vwindow_edl->copy_all(edl->vwindow_edl);
353         }
354         clips.remove_all_objects();
355         for(int i = 0; i < edl->clips.total; i++)
356         {
357                 add_clip(edl->clips.values[i]);
358         }
361 void EDL::copy_assets(EDL *edl)
363         if(!parent_edl)
364         {
365                 assets->copy_from(edl->assets);
366         }
369 void EDL::copy_session(EDL *edl)
371         strcpy(this->project_path, edl->project_path);
373         folders.remove_all_objects();
374         for(int i = 0; i < edl->folders.total; i++)
375         {
376                 char *new_folder;
377                 folders.append(new_folder = new char[strlen(edl->folders.values[i]) + 1]);
378                 strcpy(new_folder, edl->folders.values[i]);
379         }
381         if(!parent_edl)
382         {
383                 session->copy(edl->session);
384         }
385         
386         local_session->copy_from(edl->local_session);
389 int EDL::copy_assets(double start, 
390         double end, 
391         FileXML *file, 
392         int all, 
393         ArrayList<PluginServer*> *plugindb,
394         char *output_path)
396         ArrayList<Asset*> asset_list;
397         Track* current;
399         file->tag.set_title("ASSETS");
400         file->append_tag();
401         file->append_newline();
403 // Copy everything for a save
404         if(all)
405         {
406                 for(Asset *asset = assets->first;
407                         asset;
408                         asset = asset->next)
409                 {
410                         asset_list.append(asset);
411                 }
412         }
413         else
414 // Copy just the ones being used.
415         {
416                 for(current = tracks->first; 
417                         current; 
418                         current = NEXT)
419                 {
420                         if(current->record)
421                         {
422                                 current->copy_assets(start, 
423                                         end, 
424                                         &asset_list);
425                         }
426                 }
427         }
429 // Paths relativised here
430         for(int i = 0; i < asset_list.total; i++)
431         {
432                 asset_list.values[i]->write(file, 
433                         0, 
434                         output_path);
435         }
437         file->tag.set_title("/ASSETS");
438         file->append_tag();
439         file->append_newline();
440         file->append_newline();
441         return 0;
444 int EDL::copy(double start, 
445         double end, 
446         int all, 
447         int is_clip,
448         int is_vwindow,
449         FileXML *file, 
450         ArrayList<PluginServer*> *plugindb, 
451         char *output_path,
452         int rewind_it)
454 //printf("EDL::copy 1\n");
455 // begin file
456         if(is_clip)
457                 file->tag.set_title("CLIP_EDL");
458         else
459         if(is_vwindow)
460                 file->tag.set_title("VWINDOW_EDL");
461         else
462         {
463                 file->tag.set_title("EDL");
464                 file->tag.set_property("VERSION", CINELERRA_VERSION);
465 // Save path for restoration of the project title from a backup.
466                 if(this->project_path[0])
467                 {
468                         file->tag.set_property("PROJECT_PATH", project_path);
469                 }
470         }
472         file->append_tag();
473         file->append_newline();
475 // Set clipboard samples only if copying to clipboard
476         if(!all)
477         {
478                 file->tag.set_title("CLIPBOARD");
479                 file->tag.set_property("LENGTH", end - start);
480                 file->append_tag();
481                 file->tag.set_title("/CLIPBOARD");
482                 file->append_tag();
483                 file->append_newline();
484                 file->append_newline();
485         }
486 //printf("EDL::copy 1\n");
488 // Sessions
489         local_session->save_xml(file, start);
491 //printf("EDL::copy 1\n");
493 // Top level stuff.
494 //      if(!parent_edl)
495         {
496 // Need to copy all this from child EDL if pasting is desired.
497 // Session
498                 session->save_xml(file);
499                 session->save_video_config(file);
500                 session->save_audio_config(file);
502 // Folders
503                 for(int i = 0; i < folders.total; i++)
504                 {
505                         file->tag.set_title("FOLDER");
506                         file->append_tag();
507                         file->append_text(folders.values[i]);
508                         file->tag.set_title("/FOLDER");
509                         file->append_tag();
510                         file->append_newline();
511                 }
513 // Media
514                 if(!is_clip)
515                 copy_assets(start, 
516                         end, 
517                         file, 
518                         all, 
519                         plugindb,
520                         output_path);
522 // Clips
523 // Don't want this if using clipboard
524                 if(all)
525                 {
526                         if(vwindow_edl)
527                         {
528                                 
529                                 vwindow_edl->save_xml(plugindb, 
530                                         file, 
531                                         output_path,
532                                         0,
533                                         1);
534                         }
536                         for(int i = 0; i < clips.total; i++)
537                                 clips.values[i]->save_xml(plugindb, 
538                                         file, 
539                                         output_path,
540                                         1,
541                                         0);
542                 }
544                 file->append_newline();
545                 file->append_newline();
546         }
549 //printf("EDL::copy 1\n");
551         labels->copy(start, end, file);
552 //printf("EDL::copy 1\n");
553         tracks->copy(start, end, all, file, output_path);
554 //printf("EDL::copy 2\n");
556 // terminate file
557         if(is_clip)
558                 file->tag.set_title("/CLIP_EDL");
559         else
560         if(is_vwindow)
561                 file->tag.set_title("/VWINDOW_EDL");
562         else
563                 file->tag.set_title("/EDL");
564         file->append_tag();
565         file->append_newline();
568 // For editing operations we want to rewind it for immediate pasting.
569 // For clips and saving to disk leave it alone.
570         if(rewind_it)
571         {
572                 file->terminate_string();
573                 file->rewind();
574         }
575         return 0;
578 void EDL::rechannel()
580         for(Track *current = tracks->first; current; current = NEXT)
581         {
582                 if(current->data_type == TRACK_AUDIO)
583                 {
584                         PanAutos *autos = (PanAutos*)current->automation->autos[AUTOMATION_PAN];
585                         ((PanAuto*)autos->default_auto)->rechannel();
586                         for(PanAuto *keyframe = (PanAuto*)autos->first;
587                                 keyframe;
588                                 keyframe = (PanAuto*)keyframe->next)
589                         {
590                                 keyframe->rechannel();
591                         }
592                 }
593         }
596 void EDL::resample(double old_rate, double new_rate, int data_type)
598         for(Track *current = tracks->first; current; current = NEXT)
599         {
600                 if(current->data_type == data_type)
601                 {
602                         current->resample(old_rate, new_rate);
603                 }
604         }
608 void EDL::synchronize_params(EDL *edl)
610         local_session->synchronize_params(edl->local_session);
611         for(Track *this_track = tracks->first, *that_track = edl->tracks->first; 
612                 this_track && that_track; 
613                 this_track = this_track->next,
614                 that_track = that_track->next)
615         {
616                 this_track->synchronize_params(that_track);
617         }
620 int EDL::trim_selection(double start, 
621         double end,
622         int edit_labels,
623         int edit_plugins)
625         if(start != end)
626         {
627 // clear the data
628                 clear(0, 
629                         start,
630                         edit_labels,
631                         edit_plugins);
632                 clear(end - start, 
633                         tracks->total_length(),
634                         edit_labels,
635                         edit_plugins);
636         }
637         return 0;
641 int EDL::equivalent(double position1, double position2)
643         double threshold = (double).5 / session->frame_rate;
644         if(session->cursor_on_frames) 
645                 threshold = (double).5 / session->frame_rate;
646         else
647                 threshold = (double)1 / session->sample_rate;
649         if(fabs(position2 - position1) < threshold)
650         return 1;
651     else
652         return 0;
655 double EDL::equivalent_output(EDL *edl)
657         double result = -1;
658         session->equivalent_output(edl->session, &result);
659         tracks->equivalent_output(edl->tracks, &result);
660         return result;
664 void EDL::set_project_path(char *path)
666         strcpy(this->project_path, path);
669 void EDL::set_inpoint(double position)
671         if(equivalent(local_session->get_inpoint(), position) && 
672                 local_session->get_inpoint() >= 0)
673         {
674                 local_session->unset_inpoint();
675         }
676         else
677         {
678                 local_session->set_inpoint(align_to_frame(position, 0));
679                 if(local_session->get_outpoint() <= local_session->get_inpoint()) 
680                         local_session->unset_outpoint();
681         }
684 void EDL::set_outpoint(double position)
686         if(equivalent(local_session->get_outpoint(), position) && 
687                 local_session->get_outpoint() >= 0)
688         {
689                 local_session->unset_outpoint();
690         }
691         else
692         {
693                 local_session->set_outpoint(align_to_frame(position, 0));
694                 if(local_session->get_inpoint() >= local_session->get_outpoint()) 
695                         local_session->unset_inpoint();
696         }
700 int EDL::clear(double start, 
701         double end, 
702         int clear_labels,
703         int clear_plugins)
705         if(start == end)
706         {
707                 double distance = 0;
708                 tracks->clear_handle(start, 
709                         end,
710                         distance, 
711                         clear_labels,
712                         clear_plugins);
713                 if(clear_labels && distance > 0)
714                         labels->paste_silence(start, 
715                                 start + distance);
716         }
717         else
718         {
719                 tracks->clear(start, 
720                         end,
721                         clear_plugins);
722                 if(clear_labels) 
723                         labels->clear(start, 
724                                 end, 
725                                 1);
726         }
728 // Need to put at beginning so a subsequent paste operation starts at the
729 // right position.
730         double position = local_session->get_selectionstart();
731         local_session->set_selectionend(position);
732         local_session->set_selectionstart(position);
733         return 0;
736 void EDL::modify_edithandles(double oldposition, 
737         double newposition, 
738         int currentend,
739         int handle_mode,
740         int edit_labels,
741         int edit_plugins)
743         tracks->modify_edithandles(oldposition, 
744                 newposition, 
745                 currentend,
746                 handle_mode,
747                 edit_labels, 
748                 edit_plugins);
749         labels->modify_handles(oldposition, 
750                 newposition, 
751                 currentend,
752                 handle_mode,
753                 edit_labels);
756 void EDL::modify_pluginhandles(double oldposition, 
757         double newposition, 
758         int currentend, 
759         int handle_mode,
760         int edit_labels,
761         Edits *trim_edits)
763         tracks->modify_pluginhandles(oldposition, 
764                 newposition, 
765                 currentend, 
766                 handle_mode,
767                 edit_labels,
768                 trim_edits);
769         optimize();
772 void EDL::paste_silence(double start, 
773         double end, 
774         int edit_labels, 
775         int edit_plugins)
777         if(edit_labels) 
778                 labels->paste_silence(start, end);
779         tracks->paste_silence(start, 
780                 end, 
781                 edit_plugins);
785 void EDL::remove_from_project(ArrayList<EDL*> *clips)
787         for(int i = 0; i < clips->total; i++)
788         {
789                 for(int j = 0; j < this->clips.total; j++)
790                 {
791                         if(this->clips.values[j] == clips->values[i])
792                         {
793                                 this->clips.remove_object(clips->values[i]);
794                         }
795                 }
796         }
799 void EDL::remove_from_project(ArrayList<Asset*> *assets)
801 // Remove from clips
802         if(!parent_edl)
803                 for(int j = 0; j < clips.total; j++)
804                 {
805                         clips.values[j]->remove_from_project(assets);
806                 }
808 // Remove from VWindow
809         if(vwindow_edl)
810                 vwindow_edl->remove_from_project(assets);
812         for(int i = 0; i < assets->total; i++)
813         {
814 // Remove from tracks
815                 for(Track *track = tracks->first; track; track = track->next)
816                 {
817                         track->remove_asset(assets->values[i]);
818                 }
820 // Remove from assets
821                 if(!parent_edl)
822                 {
823                         this->assets->remove_asset(assets->values[i]);
824                 }
825         }
828 void EDL::update_assets(EDL *src)
830         for(Asset *current = src->assets->first;
831                 current;
832                 current = NEXT)
833         {
834                 assets->update(current);
835         }
838 int EDL::get_tracks_height(Theme *theme)
840         int total_pixels = 0;
841         for(Track *current = tracks->first;
842                 current;
843                 current = NEXT)
844         {
845                 total_pixels += current->vertical_span(theme);
846         }
847         return total_pixels;
850 int64_t EDL::get_tracks_width()
852         int64_t total_pixels = 0;
853         for(Track *current = tracks->first;
854                 current;
855                 current = NEXT)
856         {
857                 int64_t pixels = current->horizontal_span();
858                 if(pixels > total_pixels) total_pixels = pixels;
859         }
860 //printf("EDL::get_tracks_width %d\n", total_pixels);
861         return total_pixels;
864 // int EDL::calculate_output_w(int single_channel)
865 // {
866 //      if(single_channel) return session->output_w;
867 // 
868 //      int widest = 0;
869 //      for(int i = 0; i < session->video_channels; i++)
870 //      {
871 //              if(session->vchannel_x[i] + session->output_w > widest) widest = session->vchannel_x[i] + session->output_w;
872 //      }
873 //      return widest;
874 // }
875 // 
876 // int EDL::calculate_output_h(int single_channel)
877 // {
878 //      if(single_channel) return session->output_h;
879 // 
880 //      int tallest = 0;
881 //      for(int i = 0; i < session->video_channels; i++)
882 //      {
883 //              if(session->vchannel_y[i] + session->output_h > tallest) tallest = session->vchannel_y[i] + session->output_h;
884 //      }
885 //      return tallest;
886 // }
888 // Get the total output size scaled to aspect ratio
889 void EDL::calculate_conformed_dimensions(int single_channel, float &w, float &h)
891         w = session->output_w;
892         h = session->output_h;
894         if((float)session->output_w / session->output_h > get_aspect_ratio())
895         {
896                 h = (float)h * 
897                         (session->output_w / get_aspect_ratio() / session->output_h);
898         }
899         else
900         {
901                 w = (float)w * 
902                         (h * get_aspect_ratio() / session->output_w);
903         }
906 float EDL::get_aspect_ratio()
908         return session->aspect_w / session->aspect_h;
911 int EDL::dump()
913         if(parent_edl)
914                 printf("CLIP\n");
915         else
916                 printf("EDL\n");
917         printf("clip_title: %s parent_edl: %p\n", local_session->clip_title, parent_edl);
918         printf("selectionstart %f selectionend %f loop_start %f loop_end %f\n", 
919                 local_session->get_selectionstart(1), 
920                 local_session->get_selectionend(1),
921                 local_session->loop_start,
922                 local_session->loop_end);
924         if(!parent_edl)
925         {
926                 printf("audio_channels: %d "
927                         "audio_tracks: %d \n"
928                         "sample_rate: %d\n",
929                         session->audio_channels,
930                         session->audio_tracks,
931                         session->sample_rate);
932                 printf("video_channels: %d "
933                         "video_tracks: %d "
934                         "frame_rate: %.2f "
935                         "frames_per_foot: %.2f\n"
936                 "output_w: %d "
937                 "output_h: %d "
938                 "aspect_w: %f "
939                 "aspect_h %f "
940                         "color_model %d\n",
941                                 session->video_channels,
942                                 session->video_tracks,
943                                 session->frame_rate,
944                                 session->frames_per_foot,
945                         session->output_w,
946                         session->output_h,
947                         session->aspect_w,
948                         session->aspect_h,
949                                 session->color_model);
951                 printf(" EDLS\n");
952                 printf("  total: %d\n", clips.total);
953         
954                 for(int i = 0; i < clips.total; i++)
955                 {
956                         printf("\n\n");
957                         clips.values[i]->dump();
958                         printf("\n\n");
959                 }
961                 printf(" ASSETS\n");
962                 assets->dump();
963         }
964         printf(" LABELS\n");
965         labels->dump();
966         printf(" TRACKS\n");
967         tracks->dump();
968 //printf("EDL::dump 2\n");
969         return 0;
972 EDL* EDL::add_clip(EDL *edl)
974 // Copy argument.  New edls are deleted from MWindow::load_filenames.
975         EDL *new_edl = new EDL(this);
976         new_edl->create_objects();
977         new_edl->copy_all(edl);
978         clips.append(new_edl);
979         return new_edl;
982 void EDL::insert_asset(Asset *asset, 
983         double position, 
984         Track *first_track, 
985         RecordLabels *labels)
987 // Insert asset into asset table
988         Asset *new_asset = assets->update(asset);
991 // Paste video
992         int vtrack = 0;
993         Track *current = first_track ? first_track : tracks->first;
996 // Fix length of single frame
997         double length;
1000         if(new_asset->video_length < 0) 
1001         {
1002         if(session->si_useduration)
1003                 length = session->si_duration;
1004         else    
1005                 length = 1.0 / session->frame_rate; 
1006         }
1007         else
1008         if(new_asset->frame_rate > 0)
1009                 length = ((double)new_asset->video_length / new_asset->frame_rate);
1010         else
1011                 length = 1.0 / session->frame_rate;
1013         for( ;
1014                 current && vtrack < new_asset->layers;
1015                 current = NEXT)
1016         {
1017                 if(!current->record || 
1018                         current->data_type != TRACK_VIDEO)
1019                         continue;
1021                 current->insert_asset(new_asset, 
1022                         length, 
1023                         position, 
1024                         vtrack);
1026                 vtrack++;
1027         }
1029         int atrack = 0;
1030         for(current = tracks->first;
1031                 current && atrack < new_asset->channels;
1032                 current = NEXT)
1033         {
1034                 if(!current->record ||
1035                         current->data_type != TRACK_AUDIO)
1036                         continue;
1038                 current->insert_asset(new_asset, 
1039                         (double)new_asset->audio_length / 
1040                                 new_asset->sample_rate, 
1041                         position, 
1042                         atrack);
1045                 atrack++;
1046         }
1048         if(labels)
1049         {
1050                 for(RecordLabel *label = labels->first; label; label = label->next)
1051                 {
1052                         this->labels->toggle_label(label->position, label->position);
1053                 }
1054         }
1059 void EDL::set_index_file(Asset *asset)
1061         assets->update_index(asset);
1064 void EDL::optimize()
1066 //printf("EDL::optimize 1\n");
1067         double length = tracks->total_length();
1068         if(local_session->preview_end > length) local_session->preview_end = length;
1069         if(local_session->preview_start > length ||
1070                 local_session->preview_start < 0) local_session->preview_start = 0;
1071         for(Track *current = tracks->first; current; current = NEXT)
1072                 current->optimize();
1075 int EDL::next_id()
1077         return EDLSession::current_id++;
1080 void EDL::get_shared_plugins(Track *source, 
1081         ArrayList<SharedLocation*> *plugin_locations)
1083         for(Track *track = tracks->first; track; track = track->next)
1084         {
1085                 if(track != source && 
1086                         track->data_type == source->data_type)
1087                 {
1088                         for(int i = 0; i < track->plugin_set.total; i++)
1089                         {
1090                                 Plugin *plugin = track->get_current_plugin(
1091                                         local_session->get_selectionstart(1), 
1092                                         i, 
1093                                         PLAY_FORWARD, 
1094                                         1,
1095                                         0);
1096                                 if(plugin && plugin->plugin_type == PLUGIN_STANDALONE)
1097                                 {
1098                                         plugin_locations->append(new SharedLocation(tracks->number_of(track), i));
1099                                 }
1100                         }
1101                 }
1102         }
1105 void EDL::get_shared_tracks(Track *track, ArrayList<SharedLocation*> *module_locations)
1107         for(Track *current = tracks->first; current; current = NEXT)
1108         {
1109                 if(current != track && 
1110                         current->data_type == track->data_type)
1111                 {
1112                         module_locations->append(new SharedLocation(tracks->number_of(current), 0));
1113                 }
1114         }
1117 // Convert position to frames if cursor alignment is enabled
1118 double EDL::align_to_frame(double position, int round)
1120 //printf("EDL::align_to_frame 1 %f\n", position);
1121         if(session->cursor_on_frames)
1122         {
1123 // Seconds -> Frames
1124                 double temp = (double)position * session->frame_rate;
1125 //printf("EDL::align_to_frame 2 %f\n", temp);
1127 // Assert some things
1128                 if(session->sample_rate == 0)
1129                         printf("EDL::align_to_frame: sample_rate == 0\n");
1131                 if(session->frame_rate == 0)
1132                         printf("EDL::align_to_frame: frame_rate == 0\n");
1134 // Round frames
1135 // Always round down negative numbers
1136 // but round up only if requested
1137                 if(round) 
1138                 {
1139                         temp = Units::round(temp);
1140                 }
1141                 else
1142                 {
1143 //                      if(temp < 0)
1144 //                      {
1145 //                              temp -= 0.5;
1146 //                      }
1147 //                      else
1148                                 temp = Units::to_int64(temp);
1149                 }
1150 //printf("EDL::align_to_frame 3 %f\n", temp);
1152 // Frames -> Seconds
1153                 temp /= session->frame_rate;
1155 //printf("EDL::align_to_frame 5 %f\n", temp);
1157                 return temp;
1158         }
1159 //printf("EDL::align_to_frame 3 %d\n", position);
1162         return position;
1166 void EDL::new_folder(char *folder)
1168         for(int i = 0; i < folders.total; i++)
1169         {
1170                 if(!strcasecmp(folders.values[i], folder)) return;
1171         }
1173         char *new_folder;
1174         folders.append(new_folder = new char[strlen(folder) + 1]);
1175         strcpy(new_folder, folder);
1178 void EDL::delete_folder(char *folder)
1180         int i;
1181         for(i = 0; i < folders.total; i++)
1182         {
1183                 if(!strcasecmp(folders.values[i], folder))
1184                 {
1185                         break;
1186                 }
1187         }
1189         if(i < folders.total) delete folders.values[i];
1191         for( ; i < folders.total - 1; i++)
1192         {
1193                 folders.values[i] = folders.values[i + 1];
1194         }