emacs vars for .inc files
[cinelerra_cv/ct.git] / cinelerra / edl.C
blob70e7b92abfb14105b8c42ec77cb8f86903b325d2
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 "bchash.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 "mutex.h"
18 #include "panauto.h"
19 #include "panautos.h"
20 #include "playbackconfig.h"
21 #include "plugin.h"
22 #include "preferences.h"
23 #include "recordconfig.h"
24 #include "recordlabel.h"
25 #include "sharedlocation.h"
26 #include "theme.h"
27 #include "tracks.h"
28 #include "transportque.inc"
29 #include "vtrack.h"
31 #include <vector>
34 Mutex* EDL::id_lock = 0;
38 EDL::EDL(EDL *parent_edl)
40         this->parent_edl = parent_edl;
41         tracks = 0;
42         labels = 0;
43         local_session = 0;
44         vwindow_edl = 0;
45         vwindow_edl_shared = 0;
48         folders.set_array_delete();
50         new_folder(CLIP_FOLDER);
52         new_folder(MEDIA_FOLDER);
54         id = next_id();
55         project_path[0] = 0;
59 EDL::~EDL()
62         if(tracks)
63         {
64                 delete tracks;
65         }
66         if(labels)
67         {
68                 delete labels;
69         }
71         if(local_session)
72         {
73                 delete local_session;
74         }
76         if(vwindow_edl && !vwindow_edl_shared)
77                 delete vwindow_edl;
79         if(!parent_edl)
80         {
81                 delete session;
82         }
85         folders.remove_all_objects();
86         clips.remove_all_objects();
90 int EDL::create_objects()
92         tracks = new Tracks(this);
93         if(!parent_edl)
94         {
95                 assets = Assets_GC(new Assets(this));
96                 session = new EDLSession(this);
97         }
98         else
99         {
100                 assets = parent_edl->assets;
101                 session = parent_edl->session;
102         }
103         
104         local_session = new LocalSession(this);
105         labels = new Labels(this, "LABELS");
106 //      last_playback_position = 0;
107         return 0;
110 EDL& EDL::operator=(EDL &edl)
112 printf("EDL::operator= 1\n");
113         copy_all(&edl);
114         return *this;
117 int EDL::load_defaults(BC_Hash *defaults)
119         if(!parent_edl)
120                 session->load_defaults(defaults);
122         local_session->load_defaults(defaults);
123         return 0;
126 int EDL::save_defaults(BC_Hash *defaults)
128         if(!parent_edl)
129                 session->save_defaults(defaults);
130         
131         local_session->save_defaults(defaults);
132         return 0;
135 void EDL::boundaries()
137         session->boundaries();
138         local_session->boundaries();
141 int EDL::create_default_tracks()
144         for(int i = 0; i < session->video_tracks; i++)
145         {
146                 tracks->add_video_track(0, 0);
147         }
148         for(int i = 0; i < session->audio_tracks; i++)
149         {
150                 tracks->add_audio_track(0, 0);
151         }
152         return 0;
155 int EDL::load_xml(ArrayList<PluginServer*> *plugindb,
156         FileXML *file, 
157         uint32_t load_flags)
159         int result = 0;
160 // Track numbering offset for replacing undo data.
161         int track_offset = 0;
164         folders.remove_all_objects();
166 // Search for start of master EDL.
168 // The parent_edl test caused clip creation to fail since those XML files
169 // contained an EDL tag.
171 // The parent_edl test is required to make EDL loading work because
172 // when loading an EDL the EDL tag is already read by the parent.
174         if(!parent_edl)
175         {
176                 do{
177                   result = file->read_tag();
178                 }while(!result && 
179                         !file->tag.title_is("XML") && 
180                         !file->tag.title_is("EDL"));
181         }
183         if(!result)
184         {
185 // Get path for backups
186                 project_path[0] = 0;
187                 file->tag.get_property("PROJECT_PATH", project_path);
189 // Erase everything
190                 if((load_flags & LOAD_ALL) == LOAD_ALL ||
191                         (load_flags & LOAD_EDITS) == LOAD_EDITS)
192                 {
193                         while(tracks->last) delete tracks->last;
194                 }
196                 if((load_flags & LOAD_ALL) == LOAD_ALL)
197                 {
198                         clips.remove_all_objects();
199                 }
201                 if(load_flags & LOAD_TIMEBAR)
202                 {
203                         while(labels->last) delete labels->last;
204                         local_session->unset_inpoint();
205                         local_session->unset_outpoint();
206                 }
208                 do{
209                         result = file->read_tag();
211                         if(!result)
212                         {
213                                 if(file->tag.title_is("/XML") ||
214                                         file->tag.title_is("/EDL") ||
215                                         file->tag.title_is("/CLIP_EDL") ||
216                                         file->tag.title_is("/VWINDOW_EDL"))
217                                 {
218                                         result = 1;
219                                 }
220                                 else
221                                 if(file->tag.title_is("CLIPBOARD"))
222                                 {
223                                         local_session->clipboard_length = file->tag.get_property("LENGTH", 0);
224                                 }
225                                 else
226                                 if(file->tag.title_is("VIDEO"))
227                                 {
228                                         if((load_flags & LOAD_VCONFIG) &&
229                                                 (load_flags & LOAD_SESSION))
230                                                 session->load_video_config(file, 0, load_flags);
231                                 }
232                                 else
233                                 if(file->tag.title_is("AUDIO"))
234                                 {
235                                         if((load_flags & LOAD_ACONFIG) &&
236                                                 (load_flags & LOAD_SESSION))
237                                                 session->load_audio_config(file, 0, load_flags);
238                                 }
239                                 else
240                                 if(file->tag.title_is("FOLDER"))
241                                 {
242                                         char folder[BCTEXTLEN];
243                                         strcpy(folder, file->read_text());
244                                         new_folder(folder);
245                                 }
246                                 else
247                                 if(file->tag.title_is("ASSETS"))
248                                 {
249                                         if(load_flags & LOAD_ASSETS)
250                                                 assets->load(plugindb, file, load_flags);
251                                 }
252                                 else
253                                 if(file->tag.title_is(labels->xml_tag))
254                                 {
255                                         if(load_flags & LOAD_TIMEBAR)
256                                                 labels->load(file, load_flags);
257                                 }
258                                 else
259                                 if(file->tag.title_is("LOCALSESSION"))
260                                 {
261                                         if((load_flags & LOAD_SESSION) ||
262                                                 (load_flags & LOAD_TIMEBAR))
263                                                 local_session->load_xml(file, load_flags);
264                                 }
265                                 else
266                                 if(file->tag.title_is("SESSION"))
267                                 {
268                                         if((load_flags & LOAD_SESSION) &&
269                                                 !parent_edl)
270                                                 session->load_xml(file, 0, load_flags);
271                                 }
272                                 else
273                                 if(file->tag.title_is("TRACK"))
274                                 {
275                                         tracks->load(file, track_offset, load_flags);
276                                 }
277                                 else
278 // Sub EDL.
279 // Causes clip creation to fail because that involves an opening EDL tag.
280                                 if(file->tag.title_is("CLIP_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);
286                                         if((load_flags & LOAD_ALL) == LOAD_ALL)
287                                                 clips.append(new_edl);
288                                         else
289                                                 delete new_edl;
290                                 }
291                                 else
292                                 if(file->tag.title_is("VWINDOW_EDL") && !parent_edl)
293                                 {
294                                         EDL *new_edl = new EDL(this);
295                                         new_edl->create_objects();
296                                         new_edl->load_xml(plugindb, file, LOAD_ALL);
299                                         if((load_flags & LOAD_ALL) == LOAD_ALL)
300                                         {
301                                                 if(vwindow_edl && !vwindow_edl_shared) delete vwindow_edl;
302                                                 vwindow_edl = new_edl;
303                                                 vwindow_edl_shared = 0;
304                                         }
305                                         else
306                                         {
307                                                 delete new_edl;
308                                                 new_edl = 0;
309                                         }
310                                 }
311                         }
312                 }while(!result);
313         }
314         boundaries();
315 //dump();
317         return 0;
320 // Output path is the path of the output file if name truncation is desired.
321 // It is a "" if complete names should be used.
322 // Called recursively by copy for clips, thus the string can't be terminated.
323 // The string is not terminated in this call.
324 int EDL::save_xml(ArrayList<PluginServer*> *plugindb,
325         FileXML *file, 
326         char *output_path,
327         int is_clip,
328         int is_vwindow)
330         copy(0, 
331                 tracks->total_length(), 
332                 1, 
333                 is_clip,
334                 is_vwindow,
335                 file, 
336                 plugindb, 
337                 output_path,
338                 0);
339         return 0;
342 int EDL::copy_all(EDL *edl)
344         copy_session(edl);
345         copy_assets(edl);
346         copy_clips(edl);
347         tracks->copy_from(edl->tracks);
348         labels->copy_from(edl->labels);
349         return 0;
352 void EDL::copy_clips(EDL *edl)
354         if(vwindow_edl && !vwindow_edl_shared) delete vwindow_edl;
355         vwindow_edl = 0;
356         vwindow_edl_shared = 0;
357         if(edl->vwindow_edl)
358         {
359                 vwindow_edl = new EDL(this);
360                 vwindow_edl->create_objects();
361                 vwindow_edl->copy_all(edl->vwindow_edl);
362         }
363         clips.remove_all_objects();
364         for(int i = 0; i < edl->clips.total; i++)
365         {
366                 add_clip(edl->clips.values[i]);
367         }
370 void EDL::copy_assets(EDL *edl)
372         if(!parent_edl)
373         {
374                 assets->copy_from(*edl->assets);
375         }
378 void EDL::copy_session(EDL *edl, int session_only)
380         if(!session_only)
381         {
382                 strcpy(this->project_path, edl->project_path);
384                 folders.remove_all_objects();
385                 for(int i = 0; i < edl->folders.total; i++)
386                 {
387                         char *new_folder;
388                         folders.append(new_folder = new char[strlen(edl->folders.values[i]) + 1]);
389                         strcpy(new_folder, edl->folders.values[i]);
390                 }
391         }
393         if(!parent_edl)
394         {
395                 session->copy(edl->session);
396         }
398         if(!session_only)
399         {
400                 local_session->copy_from(edl->local_session);
401         }
404 int EDL::copy_assets(double start, 
405         double end, 
406         FileXML *file, 
407         int all, 
408         ArrayList<PluginServer*> *plugindb,
409         char *output_path)
411         std::vector<Asset_GC> asset_list;
412         Track* current;
414         file->tag.set_title("ASSETS");
415         file->append_tag();
416         file->append_newline();
418 // Copy everything for a save
419         if(all)
420         {
421                 for(Assets_list::iterator asset = assets->begin();
422                         asset != assets->end();
423                         ++asset)
424                 {
425                         asset_list.push_back(*asset);
426                 }
427         }
428         else
429 // Copy just the ones being used.
430         {
431                 for(current = tracks->first; 
432                         current; 
433                         current = NEXT)
434                 {
435                         if(current->record)
436                         {
437                                 current->copy_assets(start, 
438                                         end, 
439                                         asset_list);
440                         }
441                 }
442         }
444 // Paths relativised here
445         for(int i = 0; i < asset_list.size(); i++)
446         {
447                 asset_list[i]->write(file, 
448                         0, 
449                         output_path);
450         }
452         file->tag.set_title("/ASSETS");
453         file->append_tag();
454         file->append_newline();
455         file->append_newline();
456         return 0;
459 int EDL::copy(double start, 
460         double end, 
461         int all, 
462         int is_clip,
463         int is_vwindow,
464         FileXML *file, 
465         ArrayList<PluginServer*> *plugindb, 
466         char *output_path,
467         int rewind_it)
469 //printf("EDL::copy 1\n");
470 // begin file
471         if(is_clip)
472                 file->tag.set_title("CLIP_EDL");
473         else
474         if(is_vwindow)
475                 file->tag.set_title("VWINDOW_EDL");
476         else
477         {
478                 file->tag.set_title("EDL");
479                 file->tag.set_property("VERSION", CINELERRA_VERSION);
480 // Save path for restoration of the project title from a backup.
481                 if(this->project_path[0])
482                 {
483                         file->tag.set_property("PROJECT_PATH", project_path);
484                 }
485         }
487         file->append_tag();
488         file->append_newline();
490 // Set clipboard samples only if copying to clipboard
491         if(!all)
492         {
493                 file->tag.set_title("CLIPBOARD");
494                 file->tag.set_property("LENGTH", end - start);
495                 file->append_tag();
496                 file->tag.set_title("/CLIPBOARD");
497                 file->append_tag();
498                 file->append_newline();
499                 file->append_newline();
500         }
501 //printf("EDL::copy 1\n");
503 // Sessions
504         local_session->save_xml(file, start);
506 //printf("EDL::copy 1\n");
508 // Top level stuff.
509 //      if(!parent_edl)
510         {
511 // Need to copy all this from child EDL if pasting is desired.
512 // Session
513                 session->save_xml(file);
514                 session->save_video_config(file);
515                 session->save_audio_config(file);
517 // Folders
518                 for(int i = 0; i < folders.total; i++)
519                 {
520                         file->tag.set_title("FOLDER");
521                         file->append_tag();
522                         file->append_text(folders.values[i]);
523                         file->tag.set_title("/FOLDER");
524                         file->append_tag();
525                         file->append_newline();
526                 }
528 // Media
529 // Don't replicate all assets for every clip.
530 // The assets for the clips are probably in the mane EDL.
531                 if(!is_clip)
532                         copy_assets(start, 
533                                 end, 
534                                 file, 
535                                 all, 
536                                 plugindb,
537                                 output_path);
539 // Clips
540 // Don't want this if using clipboard
541                 if(all)
542                 {
543                         if(vwindow_edl)
544                         {
545                                 
546                                 vwindow_edl->save_xml(plugindb, 
547                                         file, 
548                                         output_path,
549                                         0,
550                                         1);
551                         }
553                         for(int i = 0; i < clips.total; i++)
554                                 clips.values[i]->save_xml(plugindb, 
555                                         file, 
556                                         output_path,
557                                         1,
558                                         0);
559                 }
561                 file->append_newline();
562                 file->append_newline();
563         }
566 //printf("EDL::copy 1\n");
568         labels->copy(start, end, file);
569 //printf("EDL::copy 1\n");
570         tracks->copy(start, end, all, file, output_path);
571 //printf("EDL::copy 2\n");
573 // terminate file
574         if(is_clip)
575                 file->tag.set_title("/CLIP_EDL");
576         else
577         if(is_vwindow)
578                 file->tag.set_title("/VWINDOW_EDL");
579         else
580                 file->tag.set_title("/EDL");
581         file->append_tag();
582         file->append_newline();
585 // For editing operations we want to rewind it for immediate pasting.
586 // For clips and saving to disk leave it alone.
587         if(rewind_it)
588         {
589                 file->terminate_string();
590                 file->rewind();
591         }
592         return 0;
595 void EDL::rechannel()
597         for(Track *current = tracks->first; current; current = NEXT)
598         {
599                 if(current->data_type == TRACK_AUDIO)
600                 {
601                         PanAutos *autos = (PanAutos*)current->automation->autos[AUTOMATION_PAN];
602                         ((PanAuto*)autos->default_auto)->rechannel();
603                         for(PanAuto *keyframe = (PanAuto*)autos->first;
604                                 keyframe;
605                                 keyframe = (PanAuto*)keyframe->next)
606                         {
607                                 keyframe->rechannel();
608                         }
609                 }
610         }
613 void EDL::resample(double old_rate, double new_rate, int data_type)
615         for(Track *current = tracks->first; current; current = NEXT)
616         {
617                 if(current->data_type == data_type)
618                 {
619                         current->resample(old_rate, new_rate);
620                 }
621         }
625 void EDL::synchronize_params(EDL *edl)
627         local_session->synchronize_params(edl->local_session);
628         for(Track *this_track = tracks->first, *that_track = edl->tracks->first; 
629                 this_track && that_track; 
630                 this_track = this_track->next,
631                 that_track = that_track->next)
632         {
633                 this_track->synchronize_params(that_track);
634         }
637 int EDL::trim_selection(double start, 
638         double end,
639         int edit_labels,
640         int edit_plugins)
642         if(start != end)
643         {
644 // clear the data
645                 clear(0, 
646                         start,
647                         edit_labels,
648                         edit_plugins);
649                 clear(end - start, 
650                         tracks->total_length(),
651                         edit_labels,
652                         edit_plugins);
653         }
654         return 0;
658 int EDL::equivalent(double position1, double position2)
660         double threshold = (double).5 / session->frame_rate;
661         if(session->cursor_on_frames) 
662                 threshold = (double).5 / session->frame_rate;
663         else
664                 threshold = (double)1 / session->sample_rate;
666         if(fabs(position2 - position1) < threshold)
667         return 1;
668     else
669         return 0;
672 double EDL::equivalent_output(EDL *edl)
674         double result = -1;
675         session->equivalent_output(edl->session, &result);
676         tracks->equivalent_output(edl->tracks, &result);
677         return result;
681 void EDL::set_project_path(char *path)
683         strcpy(this->project_path, path);
686 void EDL::set_inpoint(double position)
688         if(equivalent(local_session->get_inpoint(), position) && 
689                 local_session->get_inpoint() >= 0)
690         {
691                 local_session->unset_inpoint();
692         }
693         else
694         {
695                 local_session->set_inpoint(align_to_frame(position, 0));
696                 if(local_session->get_outpoint() <= local_session->get_inpoint()) 
697                         local_session->unset_outpoint();
698         }
701 void EDL::set_outpoint(double position)
703         if(equivalent(local_session->get_outpoint(), position) && 
704                 local_session->get_outpoint() >= 0)
705         {
706                 local_session->unset_outpoint();
707         }
708         else
709         {
710                 local_session->set_outpoint(align_to_frame(position, 0));
711                 if(local_session->get_inpoint() >= local_session->get_outpoint()) 
712                         local_session->unset_inpoint();
713         }
717 int EDL::clear(double start, 
718         double end, 
719         int clear_labels,
720         int clear_plugins)
722         if(start == end)
723         {
724                 double distance = 0;
725                 tracks->clear_handle(start, 
726                         end,
727                         distance, 
728                         clear_labels,
729                         clear_plugins);
730                 if(clear_labels && distance > 0)
731                         labels->paste_silence(start, 
732                                 start + distance);
733         }
734         else
735         {
736                 tracks->clear(start, 
737                         end,
738                         clear_plugins);
739                 if(clear_labels) 
740                         labels->clear(start, 
741                                 end, 
742                                 1);
743         }
745 // Need to put at beginning so a subsequent paste operation starts at the
746 // right position.
747         double position = local_session->get_selectionstart();
748         local_session->set_selectionend(position);
749         local_session->set_selectionstart(position);
750         return 0;
753 void EDL::modify_edithandles(double oldposition, 
754         double newposition, 
755         int currentend,
756         int handle_mode,
757         int edit_labels,
758         int edit_plugins)
760         tracks->modify_edithandles(oldposition, 
761                 newposition, 
762                 currentend,
763                 handle_mode,
764                 edit_labels, 
765                 edit_plugins);
766         labels->modify_handles(oldposition, 
767                 newposition, 
768                 currentend,
769                 handle_mode,
770                 edit_labels);
773 void EDL::modify_pluginhandles(double oldposition, 
774         double newposition, 
775         int currentend, 
776         int handle_mode,
777         int edit_labels,
778         Edits *trim_edits)
780         tracks->modify_pluginhandles(oldposition, 
781                 newposition, 
782                 currentend, 
783                 handle_mode,
784                 edit_labels,
785                 trim_edits);
786         optimize();
789 void EDL::paste_silence(double start, 
790         double end, 
791         int edit_labels, 
792         int edit_plugins)
794         if(edit_labels) 
795                 labels->paste_silence(start, end);
796         tracks->paste_silence(start, 
797                 end, 
798                 edit_plugins);
802 void EDL::remove_from_project(ArrayList<EDL*> *clips)
804         for(int i = 0; i < clips->total; i++)
805         {
806                 for(int j = 0; j < this->clips.total; j++)
807                 {
808                         if(this->clips.values[j] == clips->values[i])
809                         {
810                                 this->clips.remove_object(clips->values[i]);
811                         }
812                 }
813         }
816 void EDL::remove_from_project(Assets_vector &assets)
818 // Remove from clips
819         if(!parent_edl)
820                 for(int j = 0; j < clips.total; j++)
821                 {
822                         clips.values[j]->remove_from_project(assets);
823                 }
825 // Remove from VWindow
826         if(vwindow_edl)
827                 vwindow_edl->remove_from_project(assets);
829         for(int i = 0; i < assets.size(); i++)
830         {
831 // Remove from tracks
832                 for(Track *track = tracks->first; track; track = track->next)
833                 {
834                         track->remove_asset(assets[i]);
835                 }
837 // Remove from assets
838                 if(!parent_edl)
839                 {
840                         this->assets->remove_asset(assets[i]);
841                 }
842         }
845 void EDL::update_assets(EDL *src)
847         for(Assets_list::iterator current = src->assets->begin();
848                 current != src->assets->end();
849                 ++current)
850         {
851                 assets->update(*current);
852         }
855 int EDL::get_tracks_height(Theme *theme)
857         int total_pixels = 0;
858         for(Track *current = tracks->first;
859                 current;
860                 current = NEXT)
861         {
862                 total_pixels += current->vertical_span(theme);
863         }
864         return total_pixels;
867 int64_t EDL::get_tracks_width()
869         int64_t total_pixels = 0;
870         for(Track *current = tracks->first;
871                 current;
872                 current = NEXT)
873         {
874                 int64_t pixels = current->horizontal_span();
875                 if(pixels > total_pixels) total_pixels = pixels;
876         }
877 //printf("EDL::get_tracks_width %d\n", total_pixels);
878         return total_pixels;
881 // int EDL::calculate_output_w(int single_channel)
882 // {
883 //      if(single_channel) return session->output_w;
884 // 
885 //      int widest = 0;
886 //      for(int i = 0; i < session->video_channels; i++)
887 //      {
888 //              if(session->vchannel_x[i] + session->output_w > widest) widest = session->vchannel_x[i] + session->output_w;
889 //      }
890 //      return widest;
891 // }
892 // 
893 // int EDL::calculate_output_h(int single_channel)
894 // {
895 //      if(single_channel) return session->output_h;
896 // 
897 //      int tallest = 0;
898 //      for(int i = 0; i < session->video_channels; i++)
899 //      {
900 //              if(session->vchannel_y[i] + session->output_h > tallest) tallest = session->vchannel_y[i] + session->output_h;
901 //      }
902 //      return tallest;
903 // }
905 // Get the total output size scaled to aspect ratio
906 void EDL::calculate_conformed_dimensions(int single_channel, float &w, float &h)
908         w = session->output_w;
909         h = session->output_h;
911         if((float)session->output_w / session->output_h > get_aspect_ratio())
912         {
913                 h = (float)h * 
914                         (session->output_w / get_aspect_ratio() / session->output_h);
915         }
916         else
917         {
918                 w = (float)w * 
919                         (h * get_aspect_ratio() / session->output_w);
920         }
923 float EDL::get_aspect_ratio()
925         return session->aspect_w / session->aspect_h;
928 int EDL::dump()
930         if(parent_edl)
931                 printf("CLIP\n");
932         else
933                 printf("EDL\n");
934         printf("clip_title: %s parent_edl: %p\n", local_session->clip_title, parent_edl);
935         printf("selectionstart %f selectionend %f loop_start %f loop_end %f\n", 
936                 local_session->get_selectionstart(1), 
937                 local_session->get_selectionend(1),
938                 local_session->loop_start,
939                 local_session->loop_end);
941         if(!parent_edl)
942         {
943                 printf("audio_channels: %d "
944                         "audio_tracks: %d \n"
945                         "sample_rate: %d\n",
946                         session->audio_channels,
947                         session->audio_tracks,
948                         session->sample_rate);
949                 printf("video_channels: %d "
950                         "video_tracks: %d "
951                         "frame_rate: %.2f "
952                         "frames_per_foot: %.2f\n"
953                 "output_w: %d "
954                 "output_h: %d "
955                 "aspect_w: %f "
956                 "aspect_h %f "
957                         "color_model %d\n",
958                                 session->video_channels,
959                                 session->video_tracks,
960                                 session->frame_rate,
961                                 session->frames_per_foot,
962                         session->output_w,
963                         session->output_h,
964                         session->aspect_w,
965                         session->aspect_h,
966                                 session->color_model);
968                 printf(" EDLS\n");
969                 printf("  total: %d\n", clips.total);
970         
971                 for(int i = 0; i < clips.total; i++)
972                 {
973                         printf("\n\n");
974                         clips.values[i]->dump();
975                         printf("\n\n");
976                 }
978                 printf(" ASSETS\n");
979                 assets->dump();
980         }
981         printf(" LABELS\n");
982         labels->dump();
983         printf(" TRACKS\n");
984         tracks->dump();
985 //printf("EDL::dump 2\n");
986         return 0;
989 EDL* EDL::add_clip(EDL *edl)
991 // Copy argument.  New edls are deleted from MWindow::load_filenames.
992         EDL *new_edl = new EDL(this);
993         new_edl->create_objects();
994         new_edl->copy_all(edl);
995         clips.append(new_edl);
996         return new_edl;
999 void EDL::insert_asset(Asset_GC asset, 
1000         double position, 
1001         Track *first_track, 
1002         RecordLabels *labels)
1004 // Insert asset into asset table
1005         Asset_GC new_asset = assets->update(asset);
1008 // Paste video
1009         int vtrack = 0;
1010         Track *current = first_track ? first_track : tracks->first;
1013 // Fix length of single frame
1014         double length;
1017         if(new_asset->video_length < 0) 
1018         {
1019         if(session->si_useduration)
1020                 length = session->si_duration;
1021         else    
1022                 length = 1.0 / session->frame_rate; 
1023         }
1024         else
1025         if(new_asset->frame_rate > 0)
1026                 length = ((double)new_asset->video_length / new_asset->frame_rate);
1027         else
1028                 length = 1.0 / session->frame_rate;
1030         for( ;
1031                 current && vtrack < new_asset->layers;
1032                 current = NEXT)
1033         {
1034                 if(!current->record || 
1035                         current->data_type != TRACK_VIDEO)
1036                         continue;
1038                 current->insert_asset(new_asset, 
1039                         length, 
1040                         position, 
1041                         vtrack);
1043                 vtrack++;
1044         }
1046         int atrack = 0;
1047         for(current = tracks->first;
1048                 current && atrack < new_asset->channels;
1049                 current = NEXT)
1050         {
1051                 if(!current->record ||
1052                         current->data_type != TRACK_AUDIO)
1053                         continue;
1055                 current->insert_asset(new_asset, 
1056                         (double)new_asset->audio_length / 
1057                                 new_asset->sample_rate, 
1058                         position, 
1059                         atrack);
1062                 atrack++;
1063         }
1065         if(labels)
1066         {
1067                 for(RecordLabel *label = labels->first; label; label = label->next)
1068                 {
1069                         this->labels->toggle_label(label->position, label->position);
1070                 }
1071         }
1076 void EDL::set_index_file(Asset_GC asset)
1078         assets->update_index(*asset);
1081 void EDL::optimize()
1083 //printf("EDL::optimize 1\n");
1084         double length = tracks->total_length();
1085         if(local_session->preview_end > length) local_session->preview_end = length;
1086         if(local_session->preview_start > length ||
1087                 local_session->preview_start < 0) local_session->preview_start = 0;
1088         for(Track *current = tracks->first; current; current = NEXT)
1089                 current->optimize();
1092 int EDL::next_id()
1094         id_lock->lock("EDL::next_id");
1095         int result = EDLSession::current_id++;
1096         id_lock->unlock();
1097         return result;
1100 void EDL::get_shared_plugins(Track *source, 
1101         ArrayList<SharedLocation*> *plugin_locations)
1103         for(Track *track = tracks->first; track; track = track->next)
1104         {
1105                 if(track != source && 
1106                         track->data_type == source->data_type)
1107                 {
1108                         for(int i = 0; i < track->plugin_set.total; i++)
1109                         {
1110                                 Plugin *plugin = track->get_current_plugin(
1111                                         local_session->get_selectionstart(1), 
1112                                         i, 
1113                                         PLAY_FORWARD, 
1114                                         1,
1115                                         0);
1116                                 if(plugin && plugin->plugin_type == PLUGIN_STANDALONE)
1117                                 {
1118                                         plugin_locations->append(new SharedLocation(tracks->number_of(track), i));
1119                                 }
1120                         }
1121                 }
1122         }
1125 void EDL::get_shared_tracks(Track *track, ArrayList<SharedLocation*> *module_locations)
1127         for(Track *current = tracks->first; current; current = NEXT)
1128         {
1129                 if(current != track && 
1130                         current->data_type == track->data_type)
1131                 {
1132                         module_locations->append(new SharedLocation(tracks->number_of(current), 0));
1133                 }
1134         }
1137 // Convert position to frames if cursor alignment is enabled
1138 double EDL::align_to_frame(double position, int round)
1140 //printf("EDL::align_to_frame 1 %f\n", position);
1141         if(session->cursor_on_frames)
1142         {
1143 // Seconds -> Frames
1144                 double temp = (double)position * session->frame_rate;
1145 //printf("EDL::align_to_frame 2 %f\n", temp);
1147 // Assert some things
1148                 if(session->sample_rate == 0)
1149                         printf("EDL::align_to_frame: sample_rate == 0\n");
1151                 if(session->frame_rate == 0)
1152                         printf("EDL::align_to_frame: frame_rate == 0\n");
1154 // Round frames
1155 // Always round down negative numbers
1156 // but round up only if requested
1157                 if(round) 
1158                 {
1159                         temp = Units::round(temp);
1160                 }
1161                 else
1162                 {
1163 //                      if(temp < 0)
1164 //                      {
1165 //                              temp -= 0.5;
1166 //                      }
1167 //                      else
1168                                 temp = Units::to_int64(temp);
1169                 }
1170 //printf("EDL::align_to_frame 3 %f\n", temp);
1172 // Frames -> Seconds
1173                 temp /= session->frame_rate;
1175 //printf("EDL::align_to_frame 5 %f\n", temp);
1177                 return temp;
1178         }
1179 //printf("EDL::align_to_frame 3 %d\n", position);
1182         return position;
1186 void EDL::new_folder(char *folder)
1188         for(int i = 0; i < folders.total; i++)
1189         {
1190                 if(!strcasecmp(folders.values[i], folder)) return;
1191         }
1193         char *new_folder;
1194         folders.append(new_folder = new char[strlen(folder) + 1]);
1195         strcpy(new_folder, folder);
1198 void EDL::delete_folder(char *folder)
1200         int i;
1201         for(i = 0; i < folders.total; i++)
1202         {
1203                 if(!strcasecmp(folders.values[i], folder))
1204                 {
1205                         break;
1206                 }
1207         }
1209         if(i < folders.total) delete folders.values[i];
1211         for( ; i < folders.total - 1; i++)
1212         {
1213                 folders.values[i] = folders.values[i + 1];
1214         }
1217 //      Local Variables:
1218 //      mode: C++
1219 //      c-file-style: "linux"
1220 //      End: