r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / cinelerra / edl.C
blobca3b062b2630e3803b5fa29e55ec087284303bd5
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 "clip.h"
8 #include "colormodels.h"
9 #include "defaults.h"
10 #include "edl.h"
11 #include "edlsession.h"
12 #include "filexml.h"
13 #include "guicast.h"
14 #include "labels.h"
15 #include "localsession.h"
16 #include "panauto.h"
17 #include "panautos.h"
18 #include "playbackconfig.h"
19 #include "plugin.h"
20 #include "preferences.h"
21 #include "recordconfig.h"
22 #include "recordlabel.h"
23 #include "sharedlocation.h"
24 #include "theme.h"
25 #include "tracks.h"
26 #include "transportque.inc"
27 #include "vtrack.h"
29 EDL::EDL(EDL *parent_edl)
31         this->parent_edl = parent_edl;
32         tracks = 0;
33         labels = 0;
34         local_session = 0;
35         presentations = 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         }
57         if(presentations)
58         {
59                 delete presentations;
60         }
62         if(local_session)
63         {
64                 delete local_session;
65         }
67         if(vwindow_edl)
68                 delete vwindow_edl;
70         if(!parent_edl)
71         {
72                 delete assets;
73                 delete session;
74         }
77         folders.remove_all_objects();
78         clips.remove_all_objects();
79 //printf("EDL::~EDL 2\n");
83 int EDL::create_objects()
85         tracks = new Tracks(this);
86         if(!parent_edl)
87         {
88                 assets = new Assets(this);
89                 session = new EDLSession(this);
90         }
91         else
92         {
93                 assets = parent_edl->assets;
94                 session = parent_edl->session;
95         }
96         
97         local_session = new LocalSession(this);
98         labels = new Labels(this, "LABELS");
99         presentations = new Presentations(this);
100 //      last_playback_position = 0;
101         return 0;
104 EDL& EDL::operator=(EDL &edl)
106 printf("EDL::operator= 1\n");
107         copy_all(&edl);
108         return *this;
111 int EDL::load_defaults(Defaults *defaults)
113         if(!parent_edl)
114                 session->load_defaults(defaults);
116         local_session->load_defaults(defaults);
117         return 0;
120 int EDL::save_defaults(Defaults *defaults)
122         if(!parent_edl)
123                 session->save_defaults(defaults);
124         
125         local_session->save_defaults(defaults);
126         return 0;
129 void EDL::boundaries()
131         session->boundaries();
132         local_session->boundaries();
135 int EDL::create_default_tracks()
138         for(int i = 0; i < session->video_tracks; i++)
139         {
140                 tracks->add_video_track(0, 0);
141         }
142         for(int i = 0; i < session->audio_tracks; i++)
143         {
144                 tracks->add_audio_track(0, 0);
145         }
146         return 0;
149 int EDL::load_xml(ArrayList<PluginServer*> *plugindb,
150         FileXML *file, 
151         uint32_t load_flags)
153         int result = 0;
154 // Track numbering offset for replacing undo data.
155         int track_offset = 0;
157         folders.remove_all_objects();
159 // Search for start of master EDL.
161 // The parent_edl test caused clip creation to fail since those XML files
162 // contained an EDL tag.
164 // The parent_edl test is required to make EDL loading work because
165 // when loading an EDL the EDL tag is already read by the parent.
167         if(!parent_edl)
168         {
169                 do{
170                   result = file->read_tag();
171                 }while(!result && 
172                         !file->tag.title_is("XML") && 
173                         !file->tag.title_is("EDL"));
174         }
176         if(!result)
177         {
178 // Get path for backups
179                 project_path[0] = 0;
180                 file->tag.get_property("PROJECT_PATH", project_path);
182 // Erase everything
183                 if((load_flags & LOAD_ALL) == LOAD_ALL ||
184                         (load_flags & LOAD_EDITS) == LOAD_EDITS)
185                 {
186                         while(tracks->last) delete tracks->last;
187                 }
189                 if((load_flags & LOAD_ALL) == LOAD_ALL)
190                 {
191                         clips.remove_all_objects();
192                 }
194                 if(load_flags & LOAD_TIMEBAR)
195                 {
196                         while(labels->last) delete labels->last;
197                         local_session->in_point = -1;
198                         local_session->out_point = -1;
199                 }
201                 do{
202                         result = file->read_tag();
204                         if(!result)
205                         {
206                                 if(file->tag.title_is("/XML") ||
207                                         file->tag.title_is("/EDL") ||
208                                         file->tag.title_is("/CLIP_EDL") ||
209                                         file->tag.title_is("/VWINDOW_EDL"))
210                                 {
211                                         result = 1;
212                                 }
213                                 else
214                                 if(file->tag.title_is("CLIPBOARD"))
215                                 {
216                                         local_session->clipboard_length = file->tag.get_property("LENGTH", 0);
217                                 }
218                                 else
219                                 if(file->tag.title_is("VIDEO"))
220                                 {
221                                         if((load_flags & LOAD_VCONFIG) &&
222                                                 (load_flags & LOAD_SESSION))
223                                                 session->load_video_config(file, 0, load_flags);
224                                 }
225                                 else
226                                 if(file->tag.title_is("AUDIO"))
227                                 {
228                                         if((load_flags & LOAD_ACONFIG) &&
229                                                 (load_flags & LOAD_SESSION))
230                                                 session->load_audio_config(file, 0, load_flags);
231                                 }
232                                 else
233                                 if(file->tag.title_is("FOLDER"))
234                                 {
235                                         char folder[BCTEXTLEN];
236                                         strcpy(folder, file->read_text());
237                                         new_folder(folder);
238                                 }
239                                 else
240                                 if(file->tag.title_is("ASSETS"))
241                                 {
242                                         if(load_flags & LOAD_ASSETS)
243                                                 assets->load(plugindb, file, load_flags);
244                                 }
245                                 else
246                                 if(file->tag.title_is(labels->xml_tag))
247                                 {
248                                         if(load_flags & LOAD_TIMEBAR)
249                                                 labels->load(file, load_flags);
250                                 }
251                                 else
252                                 if(file->tag.title_is(presentations->xml_tag))
253                                 {
254                                         if(load_flags & LOAD_TIMEBAR)
255                                                 presentations->load(file, load_flags);
256                                 }
257                                 else
258                                 if(file->tag.title_is("LOCALSESSION"))
259                                 {
260                                         if((load_flags & LOAD_SESSION) ||
261                                                 (load_flags & LOAD_TIMEBAR))
262                                                 local_session->load_xml(file, load_flags);
263                                 }
264                                 else
265                                 if(file->tag.title_is("SESSION"))
266                                 {
267                                         if((load_flags & LOAD_SESSION) &&
268                                                 !parent_edl)
269                                                 session->load_xml(file, 0, load_flags);
270                                 }
271                                 else
272                                 if(file->tag.title_is("TRACK"))
273                                 {
274                                         tracks->load(file, track_offset, load_flags);
275                                 }
276                                 else
277 // Sub EDL.
278 // Causes clip creation to fail because that involves an opening EDL tag.
279                                 if(file->tag.title_is("CLIP_EDL") && !parent_edl)
280                                 {
281                                         EDL *new_edl = new EDL(this);
282                                         new_edl->create_objects();
283                                         new_edl->load_xml(plugindb, file, LOAD_ALL);
285                                         if((load_flags & LOAD_ALL) == LOAD_ALL)
286                                                 clips.append(new_edl);
287                                         else
288                                                 delete new_edl;
289                                 }
290                                 else
291                                 if(file->tag.title_is("VWINDOW_EDL") && !parent_edl)
292                                 {
293                                         EDL *new_edl = new EDL(this);
294                                         new_edl->create_objects();
295                                         new_edl->load_xml(plugindb, file, LOAD_ALL);
298                                         if((load_flags & LOAD_ALL) == LOAD_ALL)
299                                         {
300                                                 if(vwindow_edl) delete vwindow_edl;
301                                                 vwindow_edl = new_edl;
302                                         }
303                                         else
304                                         {
305                                                 delete new_edl;
306                                                 new_edl = 0;
307                                         }
308                                 }
309                         }
310                 }while(!result);
311 //printf("EDL::load_xml 4\n");
312         }
313         boundaries();
314 //printf("EDL::load_xml 6 %p\n", parent_edl);
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) delete vwindow_edl;
355         vwindow_edl = 0;
356         if(edl->vwindow_edl)
357         {
358                 vwindow_edl = new EDL(this);
359                 vwindow_edl->create_objects();
360                 vwindow_edl->copy_all(edl->vwindow_edl);
361         }
362         clips.remove_all_objects();
363         for(int i = 0; i < edl->clips.total; i++)
364         {
365                 add_clip(edl->clips.values[i]);
366         }
369 void EDL::copy_assets(EDL *edl)
371         if(!parent_edl)
372         {
373                 assets->copy_from(edl->assets);
374         }
377 void EDL::copy_session(EDL *edl)
379         strcpy(this->project_path, edl->project_path);
381         folders.remove_all_objects();
382         for(int i = 0; i < edl->folders.total; i++)
383         {
384                 char *new_folder;
385                 folders.append(new_folder = new char[strlen(edl->folders.values[i]) + 1]);
386                 strcpy(new_folder, edl->folders.values[i]);
387         }
389         if(!parent_edl)
390         {
391                 session->copy(edl->session);
392         }
393         
394         local_session->copy_from(edl->local_session);
397 int EDL::copy_assets(double start, 
398         double end, 
399         FileXML *file, 
400         int all, 
401         ArrayList<PluginServer*> *plugindb,
402         char *output_path)
404         ArrayList<Asset*> asset_list;
405         Track* current;
407         file->tag.set_title("ASSETS");
408         file->append_tag();
409         file->append_newline();
411 // Copy everything for a save
412         if(all)
413         {
414                 for(Asset *asset = assets->first;
415                         asset;
416                         asset = asset->next)
417                 {
418                         asset_list.append(asset);
419                 }
420         }
421         else
422 // Copy just the ones being used.
423         {
424                 for(current = tracks->first; 
425                         current; 
426                         current = NEXT)
427                 {
428                         if(current->record)
429                         {
430                                 current->copy_assets(start, 
431                                         end, 
432                                         &asset_list);
433                         }
434                 }
435         }
437 // Paths relativised here
438         for(int i = 0; i < asset_list.total; i++)
439         {
440                 asset_list.values[i]->write(plugindb,
441                         file, 
442                         0, 
443                         output_path);
444         }
446         file->tag.set_title("/ASSETS");
447         file->append_tag();
448         file->append_newline();
449         file->append_newline();
450         return 0;
453 int EDL::copy(double start, 
454         double end, 
455         int all, 
456         int is_clip,
457         int is_vwindow,
458         FileXML *file, 
459         ArrayList<PluginServer*> *plugindb, 
460         char *output_path,
461         int rewind_it)
463 //printf("EDL::copy 1\n");
464 // begin file
465         if(is_clip)
466                 file->tag.set_title("CLIP_EDL");
467         else
468         if(is_vwindow)
469                 file->tag.set_title("VWINDOW_EDL");
470         else
471         {
472                 file->tag.set_title("EDL");
473 // Save path for restoration of the project title from a backup.
474                 if(this->project_path[0])
475                 {
476                         file->tag.set_property("PROJECT_PATH", project_path);
477                 }
478         }
480         file->append_tag();
481         file->append_newline();
483 // Set clipboard samples only if copying to clipboard
484         if(!all)
485         {
486                 file->tag.set_title("CLIPBOARD");
487                 file->tag.set_property("LENGTH", end - start);
488                 file->append_tag();
489                 file->append_newline();
490                 file->append_newline();
491         }
492 //printf("EDL::copy 1\n");
494 // Sessions
495         local_session->save_xml(file, start);
497 //printf("EDL::copy 1\n");
499 // Top level stuff.
500 //      if(!parent_edl)
501         {
502 // Need to copy all this from child EDL if pasting is desired.
503 // Session
504                 session->save_xml(file);
505                 session->save_video_config(file);
506                 session->save_audio_config(file);
508 // Folders
509                 for(int i = 0; i < folders.total; i++)
510                 {
511                         file->tag.set_title("FOLDER");
512                         file->append_tag();
513                         file->append_text(folders.values[i]);
514                         file->tag.set_title("/FOLDER");
515                         file->append_tag();
516                         file->append_newline();
517                 }
519 // Media
520                 copy_assets(start, 
521                         end, 
522                         file, 
523                         all, 
524                         plugindb,
525                         output_path);
527 // Clips
528 // Don't want this if using clipboard
529                 if(all)
530                 {
531                         if(vwindow_edl)
532                         {
533                                 
534                                 vwindow_edl->save_xml(plugindb, 
535                                         file, 
536                                         output_path,
537                                         0,
538                                         1);
539                         }
541                         for(int i = 0; i < clips.total; i++)
542                                 clips.values[i]->save_xml(plugindb, 
543                                         file, 
544                                         output_path,
545                                         1,
546                                         0);
547                 }
549                 file->append_newline();
550                 file->append_newline();
551         }
554 //printf("EDL::copy 1\n");
556         labels->copy(start, end, file);
557 //printf("EDL::copy 1\n");
558         presentations->copy(start, end, file);
559 //printf("EDL::copy 1\n");
560         tracks->copy(start, end, all, file, output_path);
561 //printf("EDL::copy 2\n");
563 // terminate file
564         if(is_clip)
565                 file->tag.set_title("/CLIP_EDL");
566         else
567         if(is_vwindow)
568                 file->tag.set_title("/VWINDOW_EDL");
569         else
570                 file->tag.set_title("/EDL");
571         file->append_tag();
572         file->append_newline();
575 // For editing operations we want to rewind it for immediate pasting.
576 // For clips and saving to disk leave it alone.
577         if(rewind_it)
578         {
579                 file->terminate_string();
580                 file->rewind();
581         }
582         return 0;
585 void EDL::rechannel()
587         for(Track *current = tracks->first; current; current = NEXT)
588         {
589                 if(current->data_type == TRACK_AUDIO)
590                 {
591                         PanAutos *autos = current->automation->pan_autos;
592                         ((PanAuto*)autos->default_auto)->rechannel();
593                         for(PanAuto *keyframe = (PanAuto*)autos->first;
594                                 keyframe;
595                                 keyframe = (PanAuto*)keyframe->next)
596                         {
597                                 keyframe->rechannel();
598                         }
599                 }
600         }
603 void EDL::resample(double old_rate, double new_rate, int data_type)
605         for(Track *current = tracks->first; current; current = NEXT)
606         {
607                 if(current->data_type == data_type)
608                 {
609                         current->resample(old_rate, new_rate);
610                 }
611         }
615 void EDL::synchronize_params(EDL *edl)
617         local_session->synchronize_params(edl->local_session);
618         for(Track *this_track = tracks->first, *that_track = edl->tracks->first; 
619                 this_track && that_track; 
620                 this_track = this_track->next,
621                 that_track = that_track->next)
622         {
623                 this_track->synchronize_params(that_track);
624         }
627 int EDL::trim_selection(double start, 
628         double end,
629         int edit_labels,
630         int edit_plugins)
632         if(start != end)
633         {
634 // clear the data
635                 clear(0, 
636                         start,
637                         edit_labels,
638                         edit_plugins);
639                 clear(end - start, 
640                         tracks->total_length(),
641                         edit_labels,
642                         edit_plugins);
643         }
644         return 0;
648 int EDL::equivalent(double position1, double position2)
650         double half_frame = (double).5 / session->frame_rate;
651         if((session->cursor_on_frames && 
652                 fabs(position2 - position1) < half_frame) ||
653                 (fabs(position2 - position1) < half_frame))
654         return 1;
655     else
656         return 0;
659 double EDL::equivalent_output(EDL *edl)
661         double result = -1;
662         session->equivalent_output(edl->session, &result);
663         tracks->equivalent_output(edl->tracks, &result);
664         return result;
668 void EDL::set_project_path(char *path)
670         strcpy(this->project_path, path);
673 void EDL::set_inpoint(double position)
675         if(equivalent(local_session->in_point, position) && local_session->in_point >= 0)
676         {
677                 local_session->in_point = -1;
678         }
679         else
680         {
681                 local_session->in_point = align_to_frame(position, 0);
682                 if(local_session->out_point <= local_session->in_point) local_session->out_point = -1;
683         }
686 void EDL::set_outpoint(double position)
688         if(equivalent(local_session->out_point, position) && local_session->out_point >= 0)
689         {
690                 local_session->out_point = -1;
691         }
692         else
693         {
694                 local_session->out_point = align_to_frame(position, 0);
695                 if(local_session->in_point >= local_session->out_point) local_session->in_point = -1;
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                 presentations->clear(start, end);
727         }
729 // Need to put at beginning so a subsequent paste operation starts at the
730 // right position.
731         local_session->selectionend = 
732                 local_session->selectionstart = 
733                 local_session->get_selectionstart();
734         return 0;
737 void EDL::modify_edithandles(double oldposition, 
738         double newposition, 
739         int currentend, 
740         int handle_mode,
741         int edit_labels,
742         int edit_plugins)
744         tracks->modify_edithandles(oldposition, 
745                 newposition, 
746                 currentend, 
747                 handle_mode,
748                 edit_labels, 
749                 edit_plugins);
750         labels->modify_handles(oldposition, 
751                 newposition, 
752                 currentend,
753                 handle_mode,
754                 edit_labels);
757 void EDL::modify_pluginhandles(double oldposition, 
758         double newposition, 
759         int currentend, 
760         int handle_mode,
761         int edit_labels)
763         tracks->modify_pluginhandles(oldposition, 
764                 newposition, 
765                 currentend, 
766                 handle_mode,
767                 edit_labels);
768         optimize();
771 void EDL::paste_silence(double start, 
772         double end, 
773         int edit_labels, 
774         int edit_plugins)
776         if(edit_labels) 
777                 labels->paste_silence(start, end);
778         tracks->paste_silence(start, 
779                 end, 
780                 edit_plugins);
784 void EDL::remove_from_project(ArrayList<EDL*> *clips)
786         for(int i = 0; i < clips->total; i++)
787         {
788                 for(int j = 0; j < this->clips.total; j++)
789                 {
790                         if(this->clips.values[j] == clips->values[i])
791                         {
792                                 this->clips.remove_object(clips->values[i]);
793                         }
794                 }
795         }
798 void EDL::remove_from_project(ArrayList<Asset*> *assets)
800 // Remove from clips
801         if(!parent_edl)
802                 for(int j = 0; j < clips.total; j++)
803                 {
804                         clips.values[j]->remove_from_project(assets);
805                 }
807 // Remove from VWindow
808         if(vwindow_edl)
809                 vwindow_edl->remove_from_project(assets);
811         for(int i = 0; i < assets->total; i++)
812         {
813 // Remove from tracks
814                 for(Track *track = tracks->first; track; track = track->next)
815                 {
816                         track->remove_asset(assets->values[i]);
817                 }
819 // Remove from assets
820                 if(!parent_edl)
821                 {
822                         this->assets->remove_asset(assets->values[i]);
823                 }
824         }
827 void EDL::update_assets(EDL *src)
829         for(Asset *current = src->assets->first;
830                 current;
831                 current = NEXT)
832         {
833                 assets->update(current);
834         }
837 int EDL::get_tracks_height(Theme *theme)
839         int total_pixels = 0;
840         for(Track *current = tracks->first;
841                 current;
842                 current = NEXT)
843         {
844                 total_pixels += current->vertical_span(theme);
845         }
846         return total_pixels;
849 int64_t EDL::get_tracks_width()
851         int64_t total_pixels = 0;
852         for(Track *current = tracks->first;
853                 current;
854                 current = NEXT)
855         {
856                 int64_t pixels = current->horizontal_span();
857                 if(pixels > total_pixels) total_pixels = pixels;
858         }
859 //printf("EDL::get_tracks_width %d\n", total_pixels);
860         return total_pixels;
863 int EDL::calculate_output_w(int single_channel)
865         if(single_channel) return session->output_w;
867         int widest = 0;
868         for(int i = 0; i < session->video_channels; i++)
869         {
870                 if(session->vchannel_x[i] + session->output_w > widest) widest = session->vchannel_x[i] + session->output_w;
871         }
872         return widest;
875 int EDL::calculate_output_h(int single_channel)
877         if(single_channel) return session->output_h;
879         int tallest = 0;
880         for(int i = 0; i < session->video_channels; i++)
881         {
882                 if(session->vchannel_y[i] + session->output_h > tallest) tallest = session->vchannel_y[i] + session->output_h;
883         }
884         return tallest;
887 // Get the total output size scaled to aspect ratio
888 void EDL::calculate_conformed_dimensions(int single_channel, float &w, float &h)
890         w = calculate_output_w(single_channel);
891         h = calculate_output_h(single_channel);
893         if((float)session->output_w / session->output_h > get_aspect_ratio())
894         {
895                 h = (float)h * 
896                         (session->output_w / get_aspect_ratio() / session->output_h);
897         }
898         else
899         {
900                 w = (float)w * 
901                         (h * get_aspect_ratio() / session->output_w);
902         }
905 float EDL::get_aspect_ratio()
907         return session->aspect_w / session->aspect_h;
910 int EDL::dump()
912         if(parent_edl)
913                 printf("CLIP\n");
914         else
915                 printf("EDL\n");
916         printf("clip_title: %s parent_edl: %p\n", local_session->clip_title, parent_edl);
917         printf("selectionstart %f selectionend %f loop_start %f loop_end %f\n", 
918                 local_session->selectionstart, 
919                 local_session->selectionend,
920                 local_session->loop_start,
921                 local_session->loop_end);
923         if(!parent_edl)
924         {
925                 printf("audio_channels: %d "
926                         "audio_tracks: %d \n"
927                         "sample_rate: %d\n",
928                         session->audio_channels,
929                         session->audio_tracks,
930                         session->sample_rate);
931                 printf("video_channels: %d "
932                         "video_tracks: %d "
933                         "frame_rate: %.2f "
934                         "frames_per_foot: %.2f\n"
935                 "output_w: %d "
936                 "output_h: %d "
937                 "aspect_w: %f "
938                 "aspect_h %f "
939                         "color_model %d\n",
940                                 session->video_channels,
941                                 session->video_tracks,
942                                 session->frame_rate,
943                                 session->frames_per_foot,
944                         session->output_w,
945                         session->output_h,
946                         session->aspect_w,
947                         session->aspect_h,
948                                 session->color_model);
950                 printf(" EDLS\n");
951                 printf("  total: %d\n", clips.total);
952         
953                 for(int i = 0; i < clips.total; i++)
954                 {
955                         printf("\n\n");
956                         clips.values[i]->dump();
957                         printf("\n\n");
958                 }
960                 printf(" ASSETS\n");
961                 assets->dump();
962         }
963         printf(" LABELS\n");
964         labels->dump();
965         printf(" TRACKS\n");
966         tracks->dump();
967 //printf("EDL::dump 2\n");
968         return 0;
971 EDL* EDL::add_clip(EDL *edl)
973 // Copy argument.  New edls are deleted from MWindow::load_filenames.
974         EDL *new_edl = new EDL(this);
975         new_edl->create_objects();
976         new_edl->copy_all(edl);
977         clips.append(new_edl);
978         return new_edl;
981 void EDL::insert_asset(Asset *asset, 
982         double position, 
983         Track *first_track, 
984         RecordLabels *labels)
986 // Insert asset into asset table
987         Asset *new_asset = assets->update(asset);
990 // Paste video
991         int vtrack = 0;
992         Track *current = first_track ? first_track : tracks->first;
995 // Fix length of single frame
996         double length;
999         if(new_asset->video_length < 0) 
1000                 length = 1.0 / session->frame_rate; 
1001         else
1002         if(new_asset->frame_rate > 0)
1003                 length = ((double)new_asset->video_length / new_asset->frame_rate);
1004         else
1005                 length = 1.0 / session->frame_rate;
1007         for( ;
1008                 current && vtrack < new_asset->layers;
1009                 current = NEXT)
1010         {
1011                 if(!current->record || 
1012                         current->data_type != TRACK_VIDEO)
1013                         continue;
1015                 current->insert_asset(new_asset, 
1016                         length, 
1017                         position, 
1018                         vtrack);
1020                 vtrack++;
1021         }
1023         int atrack = 0;
1024         for(current = tracks->first;
1025                 current && atrack < new_asset->channels;
1026                 current = NEXT)
1027         {
1028                 if(!current->record ||
1029                         current->data_type != TRACK_AUDIO)
1030                         continue;
1032                 current->insert_asset(new_asset, 
1033                         (double)new_asset->audio_length / 
1034                                 new_asset->sample_rate, 
1035                         position, 
1036                         atrack);
1039                 atrack++;
1040         }
1042         if(labels)
1043         {
1044                 for(RecordLabel *label = labels->first; label; label = label->next)
1045                 {
1046                         this->labels->toggle_label(label->position, label->position);
1047                 }
1048         }
1053 void EDL::set_index_file(Asset *asset)
1055         assets->update_index(asset);
1058 void EDL::optimize()
1060 //printf("EDL::optimize 1\n");
1061         double length = tracks->total_length();
1062         if(local_session->preview_end > length) local_session->preview_end = length;
1063         if(local_session->preview_start > length ||
1064                 local_session->preview_start < 0) local_session->preview_start = 0;
1065         for(Track *current = tracks->first; current; current = NEXT)
1066                 current->optimize();
1069 int EDL::next_id()
1071         return EDLSession::current_id++;
1074 void EDL::get_shared_plugins(Track *source, 
1075         ArrayList<SharedLocation*> *plugin_locations)
1077         for(Track *track = tracks->first; track; track = track->next)
1078         {
1079                 if(track != source && 
1080                         track->data_type == source->data_type)
1081                 {
1082                         for(int i = 0; i < track->plugin_set.total; i++)
1083                         {
1084                                 Plugin *plugin = track->get_current_plugin(local_session->selectionstart, 
1085                                         i, 
1086                                         PLAY_FORWARD, 
1087                                         1,
1088                                         0);
1089                                 if(plugin && plugin->plugin_type == PLUGIN_STANDALONE)
1090                                 {
1091                                         plugin_locations->append(new SharedLocation(tracks->number_of(track), i));
1092                                 }
1093                         }
1094                 }
1095         }
1098 void EDL::get_shared_tracks(Track *track, ArrayList<SharedLocation*> *module_locations)
1100         for(Track *current = tracks->first; current; current = NEXT)
1101         {
1102                 if(current != track && 
1103                         current->data_type == track->data_type)
1104                 {
1105                         module_locations->append(new SharedLocation(tracks->number_of(current), 0));
1106                 }
1107         }
1110 // Convert position to frames if cursor alignment is enabled
1111 double EDL::align_to_frame(double position, int round)
1113 //printf("EDL::align_to_frame 1 %f\n", position);
1114         if(session->cursor_on_frames)
1115         {
1116 // Seconds -> Frames
1117                 double temp = (double)position * session->frame_rate;
1118 //printf("EDL::align_to_frame 2 %f\n", temp);
1120 // Assert some things
1121                 if(session->sample_rate == 0)
1122                         printf("EDL::align_to_frame: sample_rate == 0\n");
1124                 if(session->frame_rate == 0)
1125                         printf("EDL::align_to_frame: frame_rate == 0\n");
1127 // Round frames
1128 // Always round down negative numbers
1129 // but round up only if requested
1130                 if(round) 
1131                 {
1132                         temp = Units::round(temp);
1133                 }
1134                 else
1135                 {
1136 //                      if(temp < 0)
1137 //                      {
1138 //                              temp -= 0.5;
1139 //                      }
1140 //                      else
1141                                 temp = Units::to_int64(temp);
1142                 }
1143 //printf("EDL::align_to_frame 3 %f\n", temp);
1145 // Frames -> Seconds
1146                 temp /= session->frame_rate;
1148 //printf("EDL::align_to_frame 5 %f\n", temp);
1150                 return temp;
1151         }
1152 //printf("EDL::align_to_frame 3 %d\n", position);
1155         return position;
1159 void EDL::new_folder(char *folder)
1161         for(int i = 0; i < folders.total; i++)
1162         {
1163                 if(!strcasecmp(folders.values[i], folder)) return;
1164         }
1166         char *new_folder;
1167         folders.append(new_folder = new char[strlen(folder) + 1]);
1168         strcpy(new_folder, folder);
1171 void EDL::delete_folder(char *folder)
1173         int i;
1174         for(i = 0; i < folders.total; i++)
1175         {
1176                 if(!strcasecmp(folders.values[i], folder))
1177                 {
1178                         break;
1179                 }
1180         }
1182         if(i < folders.total) delete folders.values[i];
1184         for( ; i < folders.total - 1; i++)
1185         {
1186                 folders.values[i] = folders.values[i + 1];
1187         }