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"
39 #include "localsession.h"
41 #include "nestededls.h"
44 #include "playbackconfig.h"
45 #include "playabletracks.h"
47 #include "preferences.h"
48 #include "recordconfig.h"
49 #include "recordlabel.h"
50 #include "sharedlocation.h"
53 #include "transportque.inc"
54 #include "versioninfo.h"
61 Mutex* EDL::id_lock = 0;
65 EDL::EDL(EDL *parent_edl)
68 this->parent_edl = parent_edl;
73 // vwindow_edl_shared = 0;
75 folders.set_array_delete();
77 new_folder(CLIP_FOLDER);
79 new_folder(MEDIA_FOLDER);
100 delete local_session;
104 remove_vwindow_edls();
106 // if(vwindow_edl && !vwindow_edl_shared)
107 // vwindow_edl->Garbage::remove_user();
116 folders.remove_all_objects();
117 for(int i = 0; i < clips.size(); i++)
118 clips.get(i)->Garbage::remove_user();
125 void EDL::create_objects()
127 tracks = new Tracks(this);
130 assets = new Assets(this);
131 session = new EDLSession(this);
135 assets = parent_edl->assets;
136 session = parent_edl->session;
139 local_session = new LocalSession(this);
140 labels = new Labels(this, "LABELS");
141 nested_edls = new NestedEDLs;
142 // last_playback_position = 0;
145 EDL& EDL::operator=(EDL &edl)
147 printf("EDL::operator= 1\n");
152 int EDL::load_defaults(BC_Hash *defaults)
155 session->load_defaults(defaults);
157 local_session->load_defaults(defaults);
161 int EDL::save_defaults(BC_Hash *defaults)
164 session->save_defaults(defaults);
166 local_session->save_defaults(defaults);
170 void EDL::boundaries()
172 session->boundaries();
173 local_session->boundaries();
176 int EDL::create_default_tracks()
179 for(int i = 0; i < session->video_tracks; i++)
181 tracks->add_video_track(0, 0);
183 for(int i = 0; i < session->audio_tracks; i++)
185 tracks->add_audio_track(0, 0);
190 int EDL::load_xml(FileXML *file,
194 // Track numbering offset for replacing undo data.
195 int track_offset = 0;
198 folders.remove_all_objects();
200 if((load_flags & LOAD_ALL) == LOAD_ALL)
202 remove_vwindow_edls();
206 // Search for start of master EDL.
208 // The parent_edl test caused clip creation to fail since those XML files
209 // contained an EDL tag.
211 // The parent_edl test is required to make EDL loading work because
212 // when loading an EDL the EDL tag is already read by the parent.
217 result = file->read_tag();
219 !file->tag.title_is("XML") &&
220 !file->tag.title_is("EDL"));
225 // Get path for backups
227 file->tag.get_property("path", path);
230 if((load_flags & LOAD_ALL) == LOAD_ALL ||
231 (load_flags & LOAD_EDITS) == LOAD_EDITS)
233 while(tracks->last) delete tracks->last;
236 if((load_flags & LOAD_ALL) == LOAD_ALL)
238 for(int i = 0; i < clips.size(); i++)
239 clips.get(i)->Garbage::remove_user();
243 if(load_flags & LOAD_TIMEBAR)
245 while(labels->last) delete labels->last;
246 local_session->unset_inpoint();
247 local_session->unset_outpoint();
250 // This was originally in LocalSession::load_xml
251 if(load_flags & LOAD_SESSION)
253 local_session->clipboard_length = 0;
257 result = file->read_tag();
261 if(file->tag.title_is("/XML") ||
262 file->tag.title_is("/EDL") ||
263 file->tag.title_is("/CLIP_EDL") ||
264 file->tag.title_is("/VWINDOW_EDL"))
269 if(file->tag.title_is("CLIPBOARD"))
271 local_session->clipboard_length =
272 file->tag.get_property("LENGTH", (double)0);
275 if(file->tag.title_is("VIDEO"))
277 if((load_flags & LOAD_VCONFIG) &&
278 (load_flags & LOAD_SESSION))
279 session->load_video_config(file, 0, load_flags);
282 if(file->tag.title_is("AUDIO"))
284 if((load_flags & LOAD_ACONFIG) &&
285 (load_flags & LOAD_SESSION))
286 session->load_audio_config(file, 0, load_flags);
289 if(file->tag.title_is("FOLDER"))
291 char folder[BCTEXTLEN];
292 strcpy(folder, file->read_text());
296 if(file->tag.title_is("ASSETS"))
298 if(load_flags & LOAD_ASSETS)
299 assets->load(file, load_flags);
302 if(file->tag.title_is(labels->xml_tag))
304 if(load_flags & LOAD_TIMEBAR)
305 labels->load(file, load_flags);
308 if(file->tag.title_is("LOCALSESSION"))
310 if((load_flags & LOAD_SESSION) ||
311 (load_flags & LOAD_TIMEBAR))
312 local_session->load_xml(file, load_flags);
315 if(file->tag.title_is("SESSION"))
317 if((load_flags & LOAD_SESSION) &&
319 session->load_xml(file, 0, load_flags);
322 if(file->tag.title_is("TRACK"))
324 tracks->load(file, track_offset, load_flags);
328 // Causes clip creation to fail because that involves an opening EDL tag.
329 if(file->tag.title_is("CLIP_EDL") && !parent_edl)
331 EDL *new_edl = new EDL(this);
332 new_edl->create_objects();
333 new_edl->load_xml(file, LOAD_ALL);
335 if((load_flags & LOAD_ALL) == LOAD_ALL)
336 clips.append(new_edl);
338 new_edl->Garbage::remove_user();
341 if(file->tag.title_is("VWINDOW_EDL") && !parent_edl)
343 EDL *new_edl = new EDL(this);
344 new_edl->create_objects();
345 new_edl->load_xml(file, LOAD_ALL);
348 if((load_flags & LOAD_ALL) == LOAD_ALL)
350 // if(vwindow_edl && !vwindow_edl_shared)
351 // vwindow_edl->Garbage::remove_user();
352 // vwindow_edl_shared = 0;
353 // vwindow_edl = new_edl;
355 append_vwindow_edl(new_edl, 0);
359 // Discard if not replacing EDL
361 new_edl->Garbage::remove_user();
374 // Output path is the path of the output file if name truncation is desired.
375 // It is a "" if complete names should be used.
376 // Called recursively by copy for clips, thus the string can't be terminated.
377 // The string is not terminated in this call.
378 int EDL::save_xml(FileXML *file,
379 const char *output_path,
384 tracks->total_length(),
394 int EDL::copy_all(EDL *edl)
396 if(this == edl) return 0;
398 nested_edls->clear();
402 tracks->copy_from(edl->tracks);
403 labels->copy_from(edl->labels);
407 void EDL::copy_clips(EDL *edl)
409 if(this == edl) return;
411 remove_vwindow_edls();
413 // if(vwindow_edl && !vwindow_edl_shared)
414 // vwindow_edl->Garbage::remove_user();
416 // vwindow_edl_shared = 0;
418 for(int i = 0; i < edl->total_vwindow_edls(); i++)
420 EDL *new_edl = new EDL(this);
421 new_edl->create_objects();
422 new_edl->copy_all(edl->get_vwindow_edl(i));
423 append_vwindow_edl(new_edl, 0);
426 for(int i = 0; i < clips.size(); i++)
427 clips.get(i)->Garbage::remove_user();
429 for(int i = 0; i < edl->clips.total; i++)
431 add_clip(edl->clips.values[i]);
435 void EDL::copy_assets(EDL *edl)
437 if(this == edl) return;
441 assets->copy_from(edl->assets);
445 void EDL::copy_session(EDL *edl, int session_only)
447 if(this == edl) return;
451 strcpy(this->path, edl->path);
452 //printf("EDL::copy_session %p %s\n", this, this->path);
454 folders.remove_all_objects();
455 for(int i = 0; i < edl->folders.total; i++)
458 folders.append(new_folder = new char[strlen(edl->folders.values[i]) + 1]);
459 strcpy(new_folder, edl->folders.values[i]);
465 session->copy(edl->session);
470 local_session->copy_from(edl->local_session);
474 int EDL::copy_assets(double start,
478 const char *output_path)
480 ArrayList<Asset*> asset_list;
483 file->tag.set_title("ASSETS");
485 file->append_newline();
487 // Copy everything for a save
490 for(Asset *asset = assets->first;
494 asset_list.append(asset);
498 // Copy just the ones being used.
500 for(current = tracks->first;
506 current->copy_assets(start,
513 // Paths relativised here
514 for(int i = 0; i < asset_list.total; i++)
516 asset_list.values[i]->write(file,
521 file->tag.set_title("/ASSETS");
523 file->append_newline();
524 file->append_newline();
528 int EDL::copy(double start,
534 const char *output_path,
537 //printf("EDL::copy 1\n");
540 file->tag.set_title("CLIP_EDL");
543 file->tag.set_title("VWINDOW_EDL");
546 file->tag.set_title("EDL");
547 file->tag.set_property("VERSION", CINELERRA_VERSION);
548 // Save path for restoration of the project title from a backup.
551 file->tag.set_property("PATH", path);
556 file->append_newline();
558 // Set clipboard samples only if copying to clipboard
561 file->tag.set_title("CLIPBOARD");
562 file->tag.set_property("LENGTH", end - start);
564 file->tag.set_title("/CLIPBOARD");
566 file->append_newline();
567 file->append_newline();
569 //printf("EDL::copy 1\n");
572 local_session->save_xml(file, start);
574 //printf("EDL::copy 1\n");
579 // Need to copy all this from child EDL if pasting is desired.
581 session->save_xml(file);
582 session->save_video_config(file);
583 session->save_audio_config(file);
586 for(int i = 0; i < folders.total; i++)
588 file->tag.set_title("FOLDER");
590 file->append_text(folders.values[i]);
591 file->tag.set_title("/FOLDER");
593 file->append_newline();
597 // Don't replicate all assets for every clip.
598 // The assets for the clips are probably in the mane EDL.
607 // Don't want this if using clipboard
610 for(int i = 0; i < total_vwindow_edls(); i++)
612 get_vwindow_edl(i)->save_xml(file,
618 for(int i = 0; i < clips.total; i++)
619 clips.values[i]->save_xml(file,
625 file->append_newline();
626 file->append_newline();
630 //printf("EDL::copy 1\n");
632 labels->copy(start, end, file);
633 //printf("EDL::copy 1\n");
634 tracks->copy(start, end, all, file, output_path);
635 //printf("EDL::copy 2\n");
639 file->tag.set_title("/CLIP_EDL");
642 file->tag.set_title("/VWINDOW_EDL");
644 file->tag.set_title("/EDL");
646 file->append_newline();
649 // For editing operations we want to rewind it for immediate pasting.
650 // For clips and saving to disk leave it alone.
653 file->terminate_string();
659 void EDL::rechannel()
661 for(Track *current = tracks->first; current; current = NEXT)
663 if(current->data_type == TRACK_AUDIO)
665 PanAutos *autos = (PanAutos*)current->automation->autos[AUTOMATION_PAN];
666 ((PanAuto*)autos->default_auto)->rechannel();
667 for(PanAuto *keyframe = (PanAuto*)autos->first;
669 keyframe = (PanAuto*)keyframe->next)
671 keyframe->rechannel();
677 void EDL::resample(double old_rate, double new_rate, int data_type)
679 for(Track *current = tracks->first; current; current = NEXT)
681 if(current->data_type == data_type)
683 current->resample(old_rate, new_rate);
689 void EDL::synchronize_params(EDL *edl)
691 local_session->synchronize_params(edl->local_session);
692 for(Track *this_track = tracks->first, *that_track = edl->tracks->first;
693 this_track && that_track;
694 this_track = this_track->next,
695 that_track = that_track->next)
697 this_track->synchronize_params(that_track);
701 int EDL::trim_selection(double start,
716 tracks->total_length(),
725 int EDL::equivalent(double position1, double position2)
727 double threshold = (double).5 / session->frame_rate;
728 if(session->cursor_on_frames)
729 threshold = (double).5 / session->frame_rate;
731 threshold = (double)1 / session->sample_rate;
733 if(fabs(position2 - position1) < threshold)
739 double EDL::equivalent_output(EDL *edl)
742 session->equivalent_output(edl->session, &result);
743 tracks->equivalent_output(edl->tracks, &result);
748 void EDL::set_path(char *path)
750 strcpy(this->path, path);
753 void EDL::set_inpoint(double position)
755 if(equivalent(local_session->get_inpoint(), position) &&
756 local_session->get_inpoint() >= 0)
758 local_session->unset_inpoint();
762 local_session->set_inpoint(align_to_frame(position, 0));
763 if(local_session->get_outpoint() <= local_session->get_inpoint())
764 local_session->unset_outpoint();
768 void EDL::set_outpoint(double position)
770 if(equivalent(local_session->get_outpoint(), position) &&
771 local_session->get_outpoint() >= 0)
773 local_session->unset_outpoint();
777 local_session->set_outpoint(align_to_frame(position, 0));
778 if(local_session->get_inpoint() >= local_session->get_outpoint())
779 local_session->unset_inpoint();
784 int EDL::clear(double start,
793 tracks->clear_handle(start,
799 if(clear_labels && distance > 0)
800 labels->paste_silence(start,
815 // Need to put at beginning so a subsequent paste operation starts at the
817 double position = local_session->get_selectionstart();
818 local_session->set_selectionend(position);
819 local_session->set_selectionstart(position);
823 void EDL::modify_edithandles(double oldposition,
831 tracks->modify_edithandles(oldposition,
838 labels->modify_handles(oldposition,
845 void EDL::modify_pluginhandles(double oldposition,
853 tracks->modify_pluginhandles(oldposition,
863 void EDL::paste_silence(double start,
870 labels->paste_silence(start, end);
871 tracks->paste_silence(start,
878 void EDL::remove_from_project(ArrayList<EDL*> *clips)
880 for(int i = 0; i < clips->size(); i++)
882 for(int j = 0; j < this->clips.size(); j++)
884 if(this->clips.get(j) == clips->values[i])
886 EDL *clip = this->clips.get(j);
887 this->clips.remove(clip);
888 clip->Garbage::remove_user();
894 void EDL::remove_from_project(ArrayList<Indexable*> *assets)
898 for(int j = 0; j < clips.total; j++)
900 clips.values[j]->remove_from_project(assets);
903 // Remove from VWindow EDLs
904 for(int i = 0; i < total_vwindow_edls(); i++)
905 get_vwindow_edl(i)->remove_from_project(assets);
907 for(int i = 0; i < assets->size(); i++)
909 // Remove from tracks
910 for(Track *track = tracks->first; track; track = track->next)
912 track->remove_asset(assets->get(i));
915 // Remove from assets
916 if(!parent_edl && assets->get(i)->is_asset)
918 this->assets->remove_asset((Asset*)assets->get(i));
921 if(!parent_edl && !assets->get(i)->is_asset)
923 this->nested_edls->remove_edl((EDL*)assets->get(i));
928 void EDL::update_assets(EDL *src)
930 for(Asset *current = src->assets->first;
934 assets->update(current);
938 int EDL::get_tracks_height(Theme *theme)
940 int total_pixels = 0;
941 for(Track *current = tracks->first;
945 total_pixels += current->vertical_span(theme);
950 int64_t EDL::get_tracks_width()
952 int64_t total_pixels = 0;
953 for(Track *current = tracks->first;
957 int64_t pixels = current->horizontal_span();
958 if(pixels > total_pixels) total_pixels = pixels;
960 //printf("EDL::get_tracks_width %d\n", total_pixels);
964 // int EDL::calculate_output_w(int single_channel)
966 // if(single_channel) return session->output_w;
969 // for(int i = 0; i < session->video_channels; i++)
971 // if(session->vchannel_x[i] + session->output_w > widest) widest = session->vchannel_x[i] + session->output_w;
976 // int EDL::calculate_output_h(int single_channel)
978 // if(single_channel) return session->output_h;
981 // for(int i = 0; i < session->video_channels; i++)
983 // if(session->vchannel_y[i] + session->output_h > tallest) tallest = session->vchannel_y[i] + session->output_h;
988 // Get the total output size scaled to aspect ratio
989 void EDL::calculate_conformed_dimensions(int single_channel, float &w, float &h)
991 w = session->output_w;
992 h = session->output_h;
994 if((float)session->output_w / session->output_h > get_aspect_ratio())
997 (session->output_w / get_aspect_ratio() / session->output_h);
1002 (h * get_aspect_ratio() / session->output_w);
1006 float EDL::get_aspect_ratio()
1008 return session->aspect_w / session->aspect_h;
1011 int EDL::dump(FILE *fp)
1014 fprintf(fp,"CLIP\n");
1016 fprintf(fp,"EDL\n");
1017 fprintf(fp," clip_title: %s\n"
1018 " parent_edl: %p\n", local_session->clip_title, parent_edl);
1019 fprintf(fp," selectionstart %f\n selectionend %f\n loop_start %f\n loop_end %f\n",
1020 local_session->get_selectionstart(1),
1021 local_session->get_selectionend(1),
1022 local_session->loop_start,
1023 local_session->loop_end);
1024 for(int i = 0; i < TOTAL_PANES; i++)
1026 fprintf(fp," pane %d view_start=%jd track_start=%jd\n", i,
1027 local_session->view_start[i],
1028 local_session->track_start[i]);
1033 fprintf(fp,"audio_channels: %d audio_tracks: %d sample_rate: %jd\n",
1034 session->audio_channels,
1035 session->audio_tracks,
1036 session->sample_rate);
1037 fprintf(fp," video_channels: %d\n"
1038 " video_tracks: %d\n"
1039 " frame_rate: %.2f\n"
1040 " frames_per_foot: %.2f\n"
1045 " color_model: %d\n",
1046 session->video_channels,
1047 session->video_tracks,
1048 session->frame_rate,
1049 session->frames_per_foot,
1054 session->color_model);
1056 fprintf(fp," CLIPS\n");
1057 fprintf(fp," total: %d\n", clips.total);
1059 for(int i = 0; i < clips.total; i++)
1062 clips.values[i]->dump(fp);
1066 fprintf(fp," VWINDOW EDLS\n");
1067 fprintf(fp," total: %d\n", total_vwindow_edls());
1069 for(int i = 0; i < total_vwindow_edls(); i++)
1071 fprintf(fp," %s\n", get_vwindow_edl(i)->local_session->clip_title);
1074 fprintf(fp," ASSETS\n");
1077 fprintf(fp," LABELS\n");
1079 fprintf(fp," TRACKS\n");
1081 //printf("EDL::dump 2\n");
1085 EDL* EDL::add_clip(EDL *edl)
1087 // Copy argument. New edls are deleted from MWindow::load_filenames.
1088 EDL *new_edl = new EDL(this);
1089 new_edl->create_objects();
1090 new_edl->copy_all(edl);
1091 clips.append(new_edl);
1095 void EDL::insert_asset(Asset *asset,
1099 RecordLabels *labels)
1101 // Insert asset into asset table
1102 Asset *new_asset = 0;
1103 EDL *new_nested_edl = 0;
1105 if(asset) new_asset = assets->update(asset);
1106 if(nested_edl) new_nested_edl = nested_edls->get_copy(nested_edl);
1110 Track *current = first_track ? first_track : tracks->first;
1113 // Fix length of single frame
1120 length = new_nested_edl->tracks->total_playable_length();
1122 channels = new_nested_edl->session->audio_channels;
1127 // Insert 1 frame for undefined length
1128 if(new_asset->video_length < 0)
1130 length = session->si_useduration ?
1131 session->si_duration :
1132 1.0 / session->frame_rate;
1135 length = new_asset->frame_rate > 0 ?
1136 (double)new_asset->video_length / new_asset->frame_rate :
1137 1.0 / session->frame_rate;
1139 layers = new_asset->layers;
1140 channels = new_asset->channels;
1144 current && vtrack < layers;
1147 if(!current->record ||
1148 current->data_type != TRACK_VIDEO)
1151 current->insert_asset(new_asset,
1163 if(new_asset->audio_length < 0)
1165 // Insert 1 frame for undefined length & video
1166 if(new_asset->video_data)
1167 length = (double)1.0 / new_asset->frame_rate;
1169 // Insert 1 second for undefined length & no video
1173 length = (double)new_asset->audio_length /
1174 new_asset->sample_rate;
1177 for(current = tracks->first;
1178 current && atrack < channels;
1181 if(!current->record ||
1182 current->data_type != TRACK_AUDIO)
1185 current->insert_asset(new_asset,
1195 // Insert labels from a recording window.
1198 for(RecordLabel *label = labels->first; label; label = label->next)
1200 this->labels->toggle_label(label->position, label->position);
1207 void EDL::set_index_file(Indexable *indexable)
1209 if(indexable->is_asset)
1210 assets->update_index((Asset*)indexable);
1212 nested_edls->update_index((EDL*)indexable);
1215 void EDL::optimize()
1217 //printf("EDL::optimize 1\n");
1218 if(local_session->preview_start < 0) local_session->preview_start = 0;
1219 double length = tracks->total_length();
1220 if(local_session->preview_end > length) local_session->preview_end = length;
1221 if(local_session->preview_start >= local_session->preview_end ) {
1222 local_session->preview_start = 0;
1223 local_session->preview_end = length;
1225 for(Track *current = tracks->first; current; current = NEXT)
1226 current->optimize();
1231 id_lock->lock("EDL::next_id");
1232 int result = EDLSession::current_id++;
1237 void EDL::get_shared_plugins(Track *source,
1238 ArrayList<SharedLocation*> *plugin_locations,
1239 int omit_recordable,
1242 for(Track *track = tracks->first; track; track = track->next)
1244 if(!track->record || !omit_recordable)
1246 if(track != source &&
1247 track->data_type == data_type)
1249 for(int i = 0; i < track->plugin_set.total; i++)
1251 Plugin *plugin = track->get_current_plugin(
1252 local_session->get_selectionstart(1),
1257 if(plugin && plugin->plugin_type == PLUGIN_STANDALONE)
1259 plugin_locations->append(new SharedLocation(tracks->number_of(track), i));
1267 void EDL::get_shared_tracks(Track *track,
1268 ArrayList<SharedLocation*> *module_locations,
1269 int omit_recordable,
1272 for(Track *current = tracks->first; current; current = NEXT)
1274 if(!omit_recordable || !current->record)
1276 if(current != track &&
1277 current->data_type == data_type)
1279 module_locations->append(new SharedLocation(tracks->number_of(current), 0));
1285 // Convert position to frames if cursor alignment is enabled
1286 double EDL::align_to_frame(double position, int round)
1288 //printf("EDL::align_to_frame 1 %f\n", position);
1289 if(session->cursor_on_frames)
1291 // Seconds -> Frames
1292 double temp = (double)position * session->frame_rate;
1293 //printf("EDL::align_to_frame 2 %f\n", temp);
1295 // Assert some things
1296 if(session->sample_rate == 0)
1297 printf("EDL::align_to_frame: sample_rate == 0\n");
1299 if(session->frame_rate == 0)
1300 printf("EDL::align_to_frame: frame_rate == 0\n");
1303 // Always round down negative numbers
1304 // but round up only if requested
1307 temp = Units::round(temp);
1316 temp = Units::to_int64(temp);
1318 //printf("EDL::align_to_frame 3 %f\n", temp);
1320 // Frames -> Seconds
1321 temp /= session->frame_rate;
1323 //printf("EDL::align_to_frame 5 %f\n", temp);
1327 //printf("EDL::align_to_frame 3 %d\n", position);
1334 void EDL::new_folder(const char *folder)
1336 for(int i = 0; i < folders.total; i++)
1338 if(!strcasecmp(folders.values[i], folder)) return;
1342 folders.append(new_folder = new char[strlen(folder) + 1]);
1343 strcpy(new_folder, folder);
1346 void EDL::delete_folder(const char *folder)
1349 for(i = 0; i < folders.total; i++)
1351 if(!strcasecmp(folders.values[i], folder))
1357 if(i < folders.total) delete folders.values[i];
1359 for( ; i < folders.total - 1; i++)
1361 folders.values[i] = folders.values[i + 1];
1365 int EDL::get_use_vconsole(VEdit* *playable_edit,
1368 PlayableTracks *playable_tracks)
1370 int share_playable_tracks = 1;
1372 VTrack *playable_track = 0;
1373 const int debug = 0;
1376 // Calculate playable tracks when being called as a nested EDL
1377 if(!playable_tracks)
1379 share_playable_tracks = 0;
1380 playable_tracks = new PlayableTracks(this,
1388 // Total number of playable tracks is 1
1389 if(playable_tracks->size() != 1)
1395 playable_track = (VTrack*)playable_tracks->get(0);
1398 // Don't need playable tracks anymore
1399 if(!share_playable_tracks)
1401 delete playable_tracks;
1404 if(debug) printf("EDL::get_use_vconsole %d playable_tracks->size()=%d\n",
1406 playable_tracks->size());
1407 if(result) return 1;
1410 // Test mutual conditions between direct copy rendering and this.
1411 if(!playable_track->direct_copy_possible(position,
1415 if(debug) printf("EDL::get_use_vconsole %d\n", __LINE__);
1417 *playable_edit = (VEdit*)playable_track->edits->editof(position,
1420 // No edit at current location
1421 if(!*playable_edit) return 1;
1422 if(debug) printf("EDL::get_use_vconsole %d\n", __LINE__);
1425 // Edit is nested EDL
1426 if((*playable_edit)->nested_edl)
1429 EDL *nested_edl = (*playable_edit)->nested_edl;
1430 int64_t nested_position = (int64_t)((position -
1431 (*playable_edit)->startproject +
1432 (*playable_edit)->startsource) *
1433 nested_edl->session->frame_rate /
1434 session->frame_rate);
1437 VEdit *playable_edit_temp = 0;
1438 if(session->output_w != nested_edl->session->output_w ||
1439 session->output_h != nested_edl->session->output_h ||
1440 nested_edl->get_use_vconsole(&playable_edit_temp,
1449 if(debug) printf("EDL::get_use_vconsole %d\n", __LINE__);
1450 // Edit is not a nested EDL
1452 if(!(*playable_edit)->asset) return 1;
1453 if(debug) printf("EDL::get_use_vconsole %d\n", __LINE__);
1456 // Asset and output device must have the same dimensions
1457 if((*playable_edit)->asset->width != session->output_w ||
1458 (*playable_edit)->asset->height != session->output_h)
1462 if(debug) printf("EDL::get_use_vconsole %d\n", __LINE__);
1466 // If we get here the frame is going to be directly copied. Whether it is
1467 // decompressed in hardware depends on the colormodel.
1473 int EDL::get_audio_channels()
1475 return session->audio_channels;
1478 int EDL::get_sample_rate()
1480 return session->sample_rate;
1483 int64_t EDL::get_audio_samples()
1485 return (int64_t)(tracks->total_playable_length() *
1486 session->sample_rate);
1489 int EDL::have_audio()
1494 int EDL::have_video()
1502 return session->output_w;
1507 return session->output_h;
1510 double EDL::get_frame_rate()
1512 return session->frame_rate;
1515 int EDL::get_video_layers()
1520 int64_t EDL::get_video_frames()
1522 return (int64_t)(tracks->total_playable_length() *
1523 session->frame_rate);
1527 void EDL::remove_vwindow_edls()
1529 for(int i = 0; i < total_vwindow_edls(); i++)
1531 get_vwindow_edl(i)->Garbage::remove_user();
1533 vwindow_edls.remove_all();
1536 void EDL::remove_vwindow_edl(EDL *edl)
1538 if(vwindow_edls.number_of(edl) >= 0)
1540 edl->Garbage::remove_user();
1542 vwindow_edls.remove(edl);
1547 EDL* EDL::get_vwindow_edl(int number)
1549 return vwindow_edls.get(number);
1552 int EDL::total_vwindow_edls()
1554 return vwindow_edls.size();
1557 void EDL::append_vwindow_edl(EDL *edl, int increase_counter)
1559 if(vwindow_edls.number_of(edl) >= 0) return;
1561 if(increase_counter) edl->Garbage::add_user();
1562 vwindow_edls.append(edl);