4 * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "automation.h"
27 #include "awindowgui.inc"
28 #include "bcsignals.h"
30 #include "bccmodels.h"
34 #include "edlsession.h"
37 #include "indexstate.h"
38 #include "interlacemodes.h"
40 #include "localsession.h"
41 #include "maskautos.h"
43 #include "nestededls.h"
46 #include "playbackconfig.h"
47 #include "playabletracks.h"
49 #include "preferences.h"
50 #include "recordconfig.h"
51 #include "recordlabel.h"
52 #include "sharedlocation.h"
55 #include "transportque.inc"
56 #include "versioninfo.h"
63 Mutex* EDL::id_lock = 0;
67 EDL::EDL(EDL *parent_edl)
70 this->parent_edl = parent_edl;
75 // vwindow_edl_shared = 0;
77 folders.set_array_delete();
80 // new_folder(CLIP_FOLDER);
81 // new_folder(MEDIA_FOLDER);
102 delete local_session;
106 remove_vwindow_edls();
108 // if(vwindow_edl && !vwindow_edl_shared)
109 // vwindow_edl->Garbage::remove_user();
118 folders.remove_all_objects();
119 for(int i = 0; i < clips.size(); i++)
120 clips.get(i)->Garbage::remove_user();
127 void EDL::create_objects()
129 tracks = new Tracks(this);
132 assets = new Assets(this);
133 session = new EDLSession(this);
137 assets = parent_edl->assets;
138 session = parent_edl->session;
141 local_session = new LocalSession(this);
142 labels = new Labels(this, "LABELS");
143 nested_edls = new NestedEDLs;
144 // last_playback_position = 0;
147 EDL& EDL::operator=(EDL &edl)
149 printf("EDL::operator= 1\n");
154 int EDL::load_defaults(BC_Hash *defaults)
157 session->load_defaults(defaults);
159 local_session->load_defaults(defaults);
163 int EDL::save_defaults(BC_Hash *defaults)
166 session->save_defaults(defaults);
168 local_session->save_defaults(defaults);
172 void EDL::boundaries()
174 session->boundaries();
175 local_session->boundaries();
178 int EDL::create_default_tracks()
181 for(int i = 0; i < session->video_tracks; i++)
183 tracks->add_video_track(0, 0);
185 for(int i = 0; i < session->audio_tracks; i++)
187 tracks->add_audio_track(0, 0);
192 int EDL::load_xml(FileXML *file,
196 // Track numbering offset for replacing undo data.
197 int track_offset = 0;
200 folders.remove_all_objects();
202 if((load_flags & LOAD_ALL) == LOAD_ALL)
204 remove_vwindow_edls();
208 // Search for start of master EDL.
210 // The parent_edl test caused clip creation to fail since those XML files
211 // contained an EDL tag.
213 // The parent_edl test is required to make EDL loading work because
214 // when loading an EDL the EDL tag is already read by the parent.
219 result = file->read_tag();
221 !file->tag.title_is("XML") &&
222 !file->tag.title_is("EDL"));
227 // Get path for backups
229 file->tag.get_property("path", path);
232 if((load_flags & LOAD_ALL) == LOAD_ALL ||
233 (load_flags & LOAD_EDITS) == LOAD_EDITS)
235 while(tracks->last) delete tracks->last;
238 if((load_flags & LOAD_ALL) == LOAD_ALL)
240 for(int i = 0; i < clips.size(); i++)
241 clips.get(i)->Garbage::remove_user();
243 mixers.remove_all_objects();
246 if(load_flags & LOAD_TIMEBAR)
248 while(labels->last) delete labels->last;
249 local_session->unset_inpoint();
250 local_session->unset_outpoint();
253 // This was originally in LocalSession::load_xml
254 if(load_flags & LOAD_SESSION)
256 local_session->clipboard_length = 0;
260 result = file->read_tag();
264 if(file->tag.title_is("/XML") ||
265 file->tag.title_is("/EDL") ||
266 file->tag.title_is("/CLIP_EDL") ||
267 file->tag.title_is("/VWINDOW_EDL"))
272 if(file->tag.title_is("CLIPBOARD"))
274 local_session->clipboard_length =
275 file->tag.get_property("LENGTH", (double)0);
278 if(file->tag.title_is("VIDEO"))
280 if((load_flags & LOAD_VCONFIG) &&
281 (load_flags & LOAD_SESSION))
282 session->load_video_config(file, 0, load_flags);
284 result = file->skip_tag();
287 if(file->tag.title_is("AUDIO"))
289 if((load_flags & LOAD_ACONFIG) &&
290 (load_flags & LOAD_SESSION))
291 session->load_audio_config(file, 0, load_flags);
293 result = file->skip_tag();
296 if(file->tag.title_is("FOLDER"))
298 char folder[BCTEXTLEN];
299 strcpy(folder, file->read_text());
303 if(file->tag.title_is("MIXERS"))
305 if((load_flags & LOAD_SESSION))
308 result = file->skip_tag();
311 if(file->tag.title_is("ASSETS"))
313 if(load_flags & LOAD_ASSETS)
314 assets->load(file, load_flags);
316 result = file->skip_tag();
319 if(file->tag.title_is(labels->xml_tag))
321 if(load_flags & LOAD_TIMEBAR)
322 labels->load(file, load_flags);
324 result = file->skip_tag();
327 if(file->tag.title_is("LOCALSESSION"))
329 if((load_flags & LOAD_SESSION) ||
330 (load_flags & LOAD_TIMEBAR))
331 local_session->load_xml(file, load_flags);
333 result = file->skip_tag();
336 if(file->tag.title_is("SESSION"))
338 if((load_flags & LOAD_SESSION) &&
340 session->load_xml(file, 0, load_flags);
342 result = file->skip_tag();
345 if(file->tag.title_is("TRACK"))
347 tracks->load(file, track_offset, load_flags);
351 // Causes clip creation to fail because that involves an opening EDL tag.
352 if(file->tag.title_is("CLIP_EDL") && !parent_edl)
354 EDL *new_edl = new EDL(this);
355 new_edl->create_objects();
356 new_edl->load_xml(file, LOAD_ALL);
358 if((load_flags & LOAD_ALL) == LOAD_ALL)
359 clips.append(new_edl);
361 new_edl->Garbage::remove_user();
364 if(file->tag.title_is("VWINDOW_EDL") && !parent_edl)
366 EDL *new_edl = new EDL(this);
367 new_edl->create_objects();
368 new_edl->load_xml(file, LOAD_ALL);
371 if((load_flags & LOAD_ALL) == LOAD_ALL)
373 // if(vwindow_edl && !vwindow_edl_shared)
374 // vwindow_edl->Garbage::remove_user();
375 // vwindow_edl_shared = 0;
376 // vwindow_edl = new_edl;
378 append_vwindow_edl(new_edl, 0);
382 // Discard if not replacing EDL
384 new_edl->Garbage::remove_user();
397 // Output path is the path of the output file if name truncation is desired.
398 // It is a "" if complete names should be used.
399 // Called recursively by copy for clips, thus the string can't be terminated.
400 // The string is not terminated in this call.
401 int EDL::save_xml(FileXML *file,
402 const char *output_path,
407 tracks->total_length(),
417 int EDL::copy_all(EDL *edl)
419 if(this == edl) return 0;
421 nested_edls->clear();
426 tracks->copy_from(edl->tracks);
427 labels->copy_from(edl->labels);
431 void EDL::copy_clips(EDL *edl)
433 if(this == edl) return;
435 remove_vwindow_edls();
437 // if(vwindow_edl && !vwindow_edl_shared)
438 // vwindow_edl->Garbage::remove_user();
440 // vwindow_edl_shared = 0;
442 for(int i = 0; i < edl->total_vwindow_edls(); i++)
444 EDL *new_edl = new EDL(this);
445 new_edl->create_objects();
446 new_edl->copy_all(edl->get_vwindow_edl(i));
447 append_vwindow_edl(new_edl, 0);
450 for(int i = 0; i < clips.size(); i++)
451 clips.get(i)->Garbage::remove_user();
453 for(int i = 0; i < edl->clips.total; i++)
455 add_clip(edl->clips.values[i]);
459 void EDL::copy_assets(EDL *edl)
461 if(this == edl) return;
465 assets->copy_from(edl->assets);
469 void EDL::copy_mixers(EDL *edl)
471 if(this == edl) return;
472 mixers.copy_from(edl->mixers);
475 void EDL::copy_session(EDL *edl, int session_only)
477 if(this == edl) return;
481 strcpy(this->path, edl->path);
482 //printf("EDL::copy_session %p %s\n", this, this->path);
484 folders.remove_all_objects();
485 for(int i = 0; i < edl->folders.total; i++)
488 folders.append(new_folder = new char[strlen(edl->folders.values[i]) + 1]);
489 strcpy(new_folder, edl->folders.values[i]);
495 session->copy(edl->session);
500 local_session->copy_from(edl->local_session);
504 int EDL::copy_assets(double start,
508 const char *output_path)
510 ArrayList<Asset*> asset_list;
513 file->tag.set_title("ASSETS");
515 file->append_newline();
517 // Copy everything for a save
520 for(Asset *asset = assets->first;
524 asset_list.append(asset);
528 // Copy just the ones being used.
530 for(current = tracks->first;
536 current->copy_assets(start,
543 // Paths relativised here
544 for(int i = 0; i < asset_list.total; i++)
546 asset_list.values[i]->write(file,
551 file->tag.set_title("/ASSETS");
553 file->append_newline();
554 file->append_newline();
558 int EDL::copy(double start,
564 const char *output_path,
567 //printf("EDL::copy 1\n");
570 file->tag.set_title("CLIP_EDL");
573 file->tag.set_title("VWINDOW_EDL");
576 file->tag.set_title("EDL");
577 file->tag.set_property("VERSION", CINELERRA_VERSION);
578 // Save path for restoration of the project title from a backup.
581 file->tag.set_property("PATH", path);
586 file->append_newline();
588 // Set clipboard samples only if copying to clipboard
591 file->tag.set_title("CLIPBOARD");
592 file->tag.set_property("LENGTH", end - start);
594 file->tag.set_title("/CLIPBOARD");
596 file->append_newline();
597 file->append_newline();
599 //printf("EDL::copy 1\n");
602 local_session->save_xml(file, start);
604 //printf("EDL::copy 1\n");
609 // Need to copy all this from child EDL if pasting is desired.
611 session->save_xml(file);
612 session->save_video_config(file);
613 session->save_audio_config(file);
616 for(int i = 0; i < folders.total; i++)
618 file->tag.set_title("FOLDER");
620 file->append_text(folders.values[i]);
621 file->tag.set_title("/FOLDER");
623 file->append_newline();
627 // Don't replicate all assets for every clip.
628 // The assets for the clips are probably in the main EDL.
630 copy_assets(start, end, file, all, output_path);
632 // Don't want this if using clipboard
635 for(int i = 0; i < total_vwindow_edls(); i++)
637 get_vwindow_edl(i)->save_xml(file,
643 for(int i = 0; i < clips.total; i++)
644 clips.values[i]->save_xml(file,
651 file->append_newline();
652 file->append_newline();
656 //printf("EDL::copy 1\n");
658 labels->copy(start, end, file);
659 //printf("EDL::copy 1\n");
660 tracks->copy(start, end, all, file, output_path);
661 //printf("EDL::copy 2\n");
665 file->tag.set_title("/CLIP_EDL");
666 else if( is_vwindow )
667 file->tag.set_title("/VWINDOW_EDL");
669 file->tag.set_title("/EDL");
671 file->append_newline();
674 // For editing operations we want to rewind it for immediate pasting.
675 // For clips and saving to disk leave it alone.
678 file->terminate_string();
686 int min_w = session->output_w, min_h = session->output_h;
687 for( Track *track=tracks->first; track!=0; track=track->next ) {
688 if( track->data_type != TRACK_VIDEO ) continue;
689 int w = min_w, h = min_h;
690 for( Edit *current=track->edits->first; current!=0; current=NEXT ) {
691 Indexable* indexable = current->get_source();
692 if( !indexable ) continue;
693 int edit_w = indexable->get_w(), edit_h = indexable->get_h();
694 if( w < edit_w ) w = edit_w;
695 if( h < edit_h ) h = edit_h;
697 if( track->track_w == w && track->track_h == h ) continue;
698 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->
699 translate_masks( (w - track->track_w) / 2, (h - track->track_h) / 2);
700 track->track_w = w; track->track_h = h;
704 void EDL::rechannel()
706 for(Track *current = tracks->first; current; current = NEXT)
708 if(current->data_type == TRACK_AUDIO)
710 PanAutos *autos = (PanAutos*)current->automation->autos[AUTOMATION_PAN];
711 ((PanAuto*)autos->default_auto)->rechannel();
712 for(PanAuto *keyframe = (PanAuto*)autos->first;
714 keyframe = (PanAuto*)keyframe->next)
716 keyframe->rechannel();
722 void EDL::resample(double old_rate, double new_rate, int data_type)
724 for(Track *current = tracks->first; current; current = NEXT)
726 if(current->data_type == data_type)
728 current->resample(old_rate, new_rate);
734 void EDL::synchronize_params(EDL *edl)
736 local_session->synchronize_params(edl->local_session);
737 for(Track *this_track = tracks->first, *that_track = edl->tracks->first;
738 this_track && that_track;
739 this_track = this_track->next,
740 that_track = that_track->next)
742 this_track->synchronize_params(that_track);
746 int EDL::trim_selection(double start,
761 tracks->total_length(),
770 int EDL::equivalent(double position1, double position2)
772 double threshold = (double).5 / session->frame_rate;
773 if(session->cursor_on_frames)
774 threshold = (double).5 / session->frame_rate;
776 threshold = (double)1 / session->sample_rate;
778 if(fabs(position2 - position1) < threshold)
784 double EDL::equivalent_output(EDL *edl)
787 session->equivalent_output(edl->session, &result);
788 tracks->equivalent_output(edl->tracks, &result);
793 void EDL::set_path(const char *path)
795 strcpy(this->path, path);
798 void EDL::set_inpoint(double position)
800 if(equivalent(local_session->get_inpoint(), position) &&
801 local_session->get_inpoint() >= 0)
803 local_session->unset_inpoint();
807 local_session->set_inpoint(align_to_frame(position, 0));
808 if(local_session->get_outpoint() <= local_session->get_inpoint())
809 local_session->unset_outpoint();
813 void EDL::set_outpoint(double position)
815 if(equivalent(local_session->get_outpoint(), position) &&
816 local_session->get_outpoint() >= 0)
818 local_session->unset_outpoint();
822 local_session->set_outpoint(align_to_frame(position, 0));
823 if(local_session->get_inpoint() >= local_session->get_outpoint())
824 local_session->unset_inpoint();
828 void EDL::unset_inoutpoint()
830 local_session->unset_inpoint();
831 local_session->unset_outpoint();
834 int EDL::blade(double position)
836 return tracks->blade(position);
839 int EDL::clear(double start, double end,
840 int clear_labels, int clear_plugins, int edit_autos)
845 tracks->clear_handle(start,
851 if(clear_labels && distance > 0)
852 labels->paste_silence(start,
867 // Need to put at beginning so a subsequent paste operation starts at the
869 double position = local_session->get_selectionstart();
870 local_session->set_selectionend(position);
871 local_session->set_selectionstart(position);
875 void EDL::modify_edithandles(double oldposition,
883 tracks->modify_edithandles(oldposition,
890 labels->modify_handles(oldposition,
897 void EDL::modify_pluginhandles(double oldposition,
905 tracks->modify_pluginhandles(oldposition,
915 void EDL::paste_silence(double start,
922 labels->paste_silence(start, end);
923 tracks->paste_silence(start,
930 void EDL::remove_from_project(ArrayList<EDL*> *clips)
932 for(int i = 0; i < clips->size(); i++)
934 for(int j = 0; j < this->clips.size(); j++)
936 if(this->clips.get(j) == clips->values[i])
938 EDL *clip = this->clips.get(j);
939 this->clips.remove(clip);
940 clip->Garbage::remove_user();
946 void EDL::remove_from_project(ArrayList<Indexable*> *assets)
950 for(int j = 0; j < clips.total; j++)
952 clips.values[j]->remove_from_project(assets);
955 // Remove from VWindow EDLs
956 for(int i = 0; i < total_vwindow_edls(); i++)
957 get_vwindow_edl(i)->remove_from_project(assets);
959 for(int i = 0; i < assets->size(); i++)
961 // Remove from tracks
962 for(Track *track = tracks->first; track; track = track->next)
964 track->remove_asset(assets->get(i));
967 // Remove from assets
968 if(!parent_edl && assets->get(i)->is_asset)
970 this->assets->remove_asset((Asset*)assets->get(i));
973 if(!parent_edl && !assets->get(i)->is_asset)
975 this->nested_edls->remove_edl((EDL*)assets->get(i));
980 void EDL::update_assets(EDL *src)
982 for(Asset *current = src->assets->first;
986 assets->update(current);
990 int EDL::get_tracks_height(Theme *theme)
992 int total_pixels = 0;
993 for(Track *current = tracks->first;
997 total_pixels += current->vertical_span(theme);
1002 int64_t EDL::get_tracks_width()
1004 int64_t total_pixels = 0;
1005 for(Track *current = tracks->first;
1009 int64_t pixels = current->horizontal_span();
1010 if(pixels > total_pixels) total_pixels = pixels;
1012 //printf("EDL::get_tracks_width %d\n", total_pixels);
1013 return total_pixels;
1016 // int EDL::calculate_output_w(int single_channel)
1018 // if(single_channel) return session->output_w;
1021 // for(int i = 0; i < session->video_channels; i++)
1023 // if(session->vchannel_x[i] + session->output_w > widest) widest = session->vchannel_x[i] + session->output_w;
1028 // int EDL::calculate_output_h(int single_channel)
1030 // if(single_channel) return session->output_h;
1033 // for(int i = 0; i < session->video_channels; i++)
1035 // if(session->vchannel_y[i] + session->output_h > tallest) tallest = session->vchannel_y[i] + session->output_h;
1040 // Get the total output size scaled to aspect ratio
1041 void EDL::calculate_conformed_dimensions(int single_channel, float &w, float &h)
1043 if((float)session->output_w / session->output_h > get_aspect_ratio())
1044 h = (w = session->output_w) / get_aspect_ratio();
1046 w = (h = session->output_h) * get_aspect_ratio();
1049 float EDL::get_aspect_ratio()
1051 return session->aspect_w / session->aspect_h;
1054 int EDL::dump(FILE *fp)
1057 fprintf(fp,"CLIP\n");
1059 fprintf(fp,"EDL\n");
1060 fprintf(fp," clip_title: %s\n"
1061 " parent_edl: %p\n", local_session->clip_title, parent_edl);
1062 fprintf(fp," selectionstart %f\n selectionend %f\n loop_start %f\n loop_end %f\n",
1063 local_session->get_selectionstart(1),
1064 local_session->get_selectionend(1),
1065 local_session->loop_start,
1066 local_session->loop_end);
1067 for(int i = 0; i < TOTAL_PANES; i++)
1069 fprintf(fp," pane %d view_start=%jd track_start=%d\n", i,
1070 local_session->view_start[i],
1071 local_session->track_start[i]);
1076 fprintf(fp,"audio_channels: %d audio_tracks: %d sample_rate: %jd\n",
1077 session->audio_channels,
1078 session->audio_tracks,
1079 session->sample_rate);
1080 fprintf(fp," video_channels: %d\n"
1081 " video_tracks: %d\n"
1082 " frame_rate: %.2f\n"
1083 " frames_per_foot: %.2f\n"
1088 " color_model: %d\n",
1089 session->video_channels,
1090 session->video_tracks,
1091 session->frame_rate,
1092 session->frames_per_foot,
1097 session->color_model);
1099 fprintf(fp," CLIPS\n");
1100 fprintf(fp," total: %d\n", clips.total);
1102 for(int i = 0; i < clips.total; i++)
1105 clips.values[i]->dump(fp);
1109 fprintf(fp," VWINDOW EDLS\n");
1110 fprintf(fp," total: %d\n", total_vwindow_edls());
1112 for(int i = 0; i < total_vwindow_edls(); i++)
1114 fprintf(fp," %s\n", get_vwindow_edl(i)->local_session->clip_title);
1117 fprintf(fp," ASSETS\n");
1120 fprintf(fp," LABELS\n");
1122 fprintf(fp," TRACKS\n");
1124 //printf("EDL::dump 2\n");
1128 EDL* EDL::add_clip(EDL *edl)
1130 // Copy argument. New edls are deleted from MWindow::load_filenames.
1131 EDL *new_edl = new EDL(this);
1132 new_edl->create_objects();
1133 new_edl->copy_all(edl);
1134 clips.append(new_edl);
1138 void EDL::insert_asset(Asset *asset,
1142 RecordLabels *labels)
1144 // Insert asset into asset table
1145 Asset *new_asset = 0;
1146 EDL *new_nested_edl = 0;
1148 if(asset) new_asset = assets->update(asset);
1149 if(nested_edl) new_nested_edl = nested_edls->get_copy(nested_edl);
1153 Track *current = first_track ? first_track : tracks->first;
1156 // Fix length of single frame
1163 length = new_nested_edl->tracks->total_length();
1165 channels = new_nested_edl->session->audio_channels;
1170 // Insert 1 frame for undefined length
1171 if(new_asset->video_length < 0)
1173 length = session->si_useduration ?
1174 session->si_duration :
1175 1.0 / session->frame_rate;
1178 length = new_asset->frame_rate > 0 ?
1179 (double)new_asset->video_length / new_asset->frame_rate :
1180 1.0 / session->frame_rate;
1182 layers = new_asset->layers;
1183 channels = new_asset->channels;
1187 current && vtrack < layers;
1190 if(!current->record ||
1191 current->data_type != TRACK_VIDEO)
1194 current->insert_asset(new_asset,
1206 if(new_asset->audio_length < 0)
1208 // Insert 1 frame for undefined length & video
1209 if(new_asset->video_data)
1210 length = (double)1.0 / new_asset->frame_rate;
1212 // Insert 1 second for undefined length & no video
1216 length = (double)new_asset->audio_length /
1217 new_asset->sample_rate;
1220 for(current = tracks->first;
1221 current && atrack < channels;
1224 if(!current->record ||
1225 current->data_type != TRACK_AUDIO)
1228 current->insert_asset(new_asset,
1238 // Insert labels from a recording window.
1241 for(RecordLabel *label = labels->first; label; label = label->next)
1243 this->labels->toggle_label(label->position, label->position);
1250 void EDL::set_index_file(Indexable *indexable)
1252 if(indexable->is_asset)
1253 assets->update_index((Asset*)indexable);
1255 nested_edls->update_index((EDL*)indexable);
1258 void EDL::optimize()
1260 //printf("EDL::optimize 1\n");
1261 if(local_session->preview_start < 0) local_session->preview_start = 0;
1262 double length = tracks->total_length();
1263 if(local_session->preview_end > length) local_session->preview_end = length;
1264 if(local_session->preview_start >= local_session->preview_end ) {
1265 local_session->preview_start = 0;
1266 local_session->preview_end = length;
1268 for(Track *current = tracks->first; current; current = NEXT)
1269 current->optimize();
1274 id_lock->lock("EDL::next_id");
1275 int result = EDLSession::current_id++;
1280 void EDL::get_shared_plugins(Track *source,
1281 ArrayList<SharedLocation*> *plugin_locations,
1282 int omit_recordable,
1285 for(Track *track = tracks->first; track; track = track->next)
1287 if(!track->record || !omit_recordable)
1289 if(track != source &&
1290 track->data_type == data_type)
1292 for(int i = 0; i < track->plugin_set.total; i++)
1294 Plugin *plugin = track->get_current_plugin(
1295 local_session->get_selectionstart(1),
1300 if(plugin && plugin->plugin_type == PLUGIN_STANDALONE)
1302 plugin_locations->append(new SharedLocation(tracks->number_of(track), i));
1310 void EDL::get_shared_tracks(Track *track,
1311 ArrayList<SharedLocation*> *module_locations,
1312 int omit_recordable,
1315 for(Track *current = tracks->first; current; current = NEXT)
1317 if(!omit_recordable || !current->record)
1319 if(current != track &&
1320 current->data_type == data_type)
1322 module_locations->append(new SharedLocation(tracks->number_of(current), 0));
1328 // aligned frame time
1329 double EDL::frame_align(double position, int round)
1331 double frame_pos = position * session->frame_rate;
1332 frame_pos = (int64_t)(frame_pos + (round ? 0.5 : 1e-6));
1333 position = frame_pos / session->frame_rate;
1337 // Convert position to frames if alignment is enabled.
1338 double EDL::align_to_frame(double position, int round)
1340 if( session->cursor_on_frames )
1341 position = frame_align(position, round);
1346 void EDL::new_folder(const char *folder)
1348 for(int i = 0; i < folders.total; i++)
1350 if(!strcasecmp(folders.values[i], folder)) return;
1354 folders.append(new_folder = new char[strlen(folder) + 1]);
1355 strcpy(new_folder, folder);
1358 void EDL::delete_folder(const char *folder)
1361 for(i = 0; i < folders.total; i++)
1363 if(!strcasecmp(folders.values[i], folder))
1369 if(i < folders.total) delete folders.values[i];
1371 for( ; i < folders.total - 1; i++)
1373 folders.values[i] = folders.values[i + 1];
1377 int EDL::get_use_vconsole(VEdit* *playable_edit,
1380 PlayableTracks *playable_tracks)
1382 int share_playable_tracks = 1;
1384 VTrack *playable_track = 0;
1385 const int debug = 0;
1388 // Calculate playable tracks when being called as a nested EDL
1389 if(!playable_tracks)
1391 share_playable_tracks = 0;
1392 playable_tracks = new PlayableTracks(this,
1400 // Total number of playable tracks is 1
1401 if(playable_tracks->size() != 1)
1407 playable_track = (VTrack*)playable_tracks->get(0);
1410 // Don't need playable tracks anymore
1411 if(!share_playable_tracks)
1413 delete playable_tracks;
1416 if(debug) printf("EDL::get_use_vconsole %d playable_tracks->size()=%d\n",
1418 playable_tracks->size());
1419 if(result) return 1;
1422 // Test mutual conditions between direct copy rendering and this.
1423 if(!playable_track->direct_copy_possible(position,
1427 if(debug) printf("EDL::get_use_vconsole %d\n", __LINE__);
1429 *playable_edit = (VEdit*)playable_track->edits->editof(position,
1432 // No edit at current location
1433 if(!*playable_edit) return 1;
1434 if(debug) printf("EDL::get_use_vconsole %d\n", __LINE__);
1437 // Edit is nested EDL
1438 if((*playable_edit)->nested_edl)
1441 EDL *nested_edl = (*playable_edit)->nested_edl;
1442 int64_t nested_position = (int64_t)((position -
1443 (*playable_edit)->startproject +
1444 (*playable_edit)->startsource) *
1445 nested_edl->session->frame_rate /
1446 session->frame_rate);
1449 VEdit *playable_edit_temp = 0;
1450 if(session->output_w != nested_edl->session->output_w ||
1451 session->output_h != nested_edl->session->output_h ||
1452 nested_edl->get_use_vconsole(&playable_edit_temp,
1461 if(debug) printf("EDL::get_use_vconsole %d\n", __LINE__);
1462 // Edit is not a nested EDL
1463 Asset *asset = (*playable_edit)->asset;
1465 if(!asset) return 1;
1466 if(debug) printf("EDL::get_use_vconsole %d\n", __LINE__);
1468 // Asset and output device must have the same dimensions
1469 if( asset->width != session->output_w ||
1470 asset->height != session->output_h )
1474 if(debug) printf("EDL::get_use_vconsole %d\n", __LINE__);
1475 // Asset and output device must have same resulting de-interlacing method
1476 if( ilaceautofixmethod2(session->interlace_mode,
1477 asset->interlace_autofixoption, asset->interlace_mode,
1478 asset->interlace_fixmethod) != ILACE_FIXMETHOD_NONE )
1481 // If we get here the frame is going to be directly copied. Whether it is
1482 // decompressed in hardware depends on the colormodel.
1488 int EDL::get_audio_channels()
1490 return session->audio_channels;
1493 int EDL::get_sample_rate()
1495 return session->sample_rate;
1498 int64_t EDL::get_audio_samples()
1500 return (int64_t)(tracks->total_length() *
1501 session->sample_rate);
1504 int EDL::have_audio()
1509 int EDL::have_video()
1517 return session->output_w;
1522 return session->output_h;
1525 double EDL::get_frame_rate()
1527 return session->frame_rate;
1530 int EDL::get_video_layers()
1535 int64_t EDL::get_video_frames()
1537 return (int64_t)(tracks->total_length() *
1538 session->frame_rate);
1542 void EDL::remove_vwindow_edls()
1544 for(int i = 0; i < total_vwindow_edls(); i++)
1546 get_vwindow_edl(i)->Garbage::remove_user();
1548 vwindow_edls.remove_all();
1551 void EDL::remove_vwindow_edl(EDL *edl)
1553 if(vwindow_edls.number_of(edl) >= 0)
1555 edl->Garbage::remove_user();
1557 vwindow_edls.remove(edl);
1562 EDL* EDL::get_vwindow_edl(int number)
1564 return vwindow_edls.get(number);
1567 int EDL::total_vwindow_edls()
1569 return vwindow_edls.size();
1572 void EDL::append_vwindow_edl(EDL *edl, int increase_counter)
1574 if(vwindow_edls.number_of(edl) >= 0) return;
1576 if(increase_counter) edl->Garbage::add_user();
1577 vwindow_edls.append(edl);
1581 double EDL::next_edit(double position)
1583 Units::fix_double(&position);
1584 double new_position = tracks->total_length();
1586 double max_rate = get_frame_rate();
1587 int sample_rate = get_sample_rate();
1588 if( sample_rate > max_rate ) max_rate = sample_rate;
1589 double min_movement = max_rate > 0 ? 1. / max_rate : 1e-6;
1591 // Test for edit handles after position
1592 for( Track *track=tracks->first; track; track=track->next ) {
1593 if( !track->record ) continue;
1594 for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
1595 double edit_end = track->from_units(edit->startproject + edit->length);
1596 Units::fix_double(&edit_end);
1597 if( fabs(edit_end-position) < min_movement ) continue;
1598 if( edit_end > position && edit_end < new_position )
1599 new_position = edit_end;
1602 return new_position;
1605 double EDL::prev_edit(double position)
1607 Units::fix_double(&position);
1608 double new_position = -1;
1610 double max_rate = get_frame_rate();
1611 int sample_rate = get_sample_rate();
1612 if( sample_rate > max_rate ) max_rate = sample_rate;
1613 double min_movement = max_rate > 0 ? 1. / max_rate : 1e-6;
1615 // Test for edit handles before cursor position
1616 for( Track *track=tracks->first; track; track=track->next ) {
1617 if( !track->record ) continue;
1618 for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
1619 double edit_end = track->from_units(edit->startproject);
1620 Units::fix_double(&edit_end);
1621 if( fabs(edit_end-position) < min_movement ) continue;
1622 if( edit_end < position && edit_end > new_position )
1623 new_position = edit_end;
1626 return new_position;