5 #include "automation.h"
6 #include "awindowgui.inc"
9 #include "colormodels.h"
12 #include "edlsession.h"
16 #include "localsession.h"
20 #include "playbackconfig.h"
22 #include "preferences.h"
23 #include "recordconfig.h"
24 #include "recordlabel.h"
25 #include "sharedlocation.h"
28 #include "transportque.inc"
34 Mutex* EDL::id_lock = 0;
38 EDL::EDL(EDL *parent_edl)
40 this->parent_edl = parent_edl;
45 vwindow_edl_shared = 0;
48 folders.set_array_delete();
50 new_folder(CLIP_FOLDER);
52 new_folder(MEDIA_FOLDER);
76 if(vwindow_edl && !vwindow_edl_shared)
86 folders.remove_all_objects();
87 clips.remove_all_objects();
91 int EDL::create_objects()
93 tracks = new Tracks(this);
96 assets = new Assets(this);
97 session = new EDLSession(this);
101 assets = parent_edl->assets;
102 session = parent_edl->session;
105 local_session = new LocalSession(this);
106 labels = new Labels(this, "LABELS");
107 // last_playback_position = 0;
111 EDL& EDL::operator=(EDL &edl)
113 printf("EDL::operator= 1\n");
118 int EDL::load_defaults(BC_Hash *defaults)
121 session->load_defaults(defaults);
123 local_session->load_defaults(defaults);
127 int EDL::save_defaults(BC_Hash *defaults)
130 session->save_defaults(defaults);
132 local_session->save_defaults(defaults);
136 void EDL::boundaries()
138 session->boundaries();
139 local_session->boundaries();
142 int EDL::create_default_tracks()
145 for(int i = 0; i < session->video_tracks; i++)
147 tracks->add_video_track(0, 0);
149 for(int i = 0; i < session->audio_tracks; i++)
151 tracks->add_audio_track(0, 0);
156 int EDL::load_xml(ArrayList<PluginServer*> *plugindb,
161 // Track numbering offset for replacing undo data.
162 int track_offset = 0;
165 folders.remove_all_objects();
167 // Search for start of master EDL.
169 // The parent_edl test caused clip creation to fail since those XML files
170 // contained an EDL tag.
172 // The parent_edl test is required to make EDL loading work because
173 // when loading an EDL the EDL tag is already read by the parent.
178 result = file->read_tag();
180 !file->tag.title_is("XML") &&
181 !file->tag.title_is("EDL"));
186 // Get path for backups
188 file->tag.get_property("PROJECT_PATH", project_path);
191 if((load_flags & LOAD_ALL) == LOAD_ALL ||
192 (load_flags & LOAD_EDITS) == LOAD_EDITS)
194 while(tracks->last) delete tracks->last;
197 if((load_flags & LOAD_ALL) == LOAD_ALL)
199 clips.remove_all_objects();
202 if(load_flags & LOAD_TIMEBAR)
204 while(labels->last) delete labels->last;
205 local_session->unset_inpoint();
206 local_session->unset_outpoint();
210 result = file->read_tag();
214 if(file->tag.title_is("/XML") ||
215 file->tag.title_is("/EDL") ||
216 file->tag.title_is("/CLIP_EDL") ||
217 file->tag.title_is("/VWINDOW_EDL"))
222 if(file->tag.title_is("CLIPBOARD"))
224 local_session->clipboard_length = file->tag.get_property("LENGTH", 0);
227 if(file->tag.title_is("VIDEO"))
229 if((load_flags & LOAD_VCONFIG) &&
230 (load_flags & LOAD_SESSION))
231 session->load_video_config(file, 0, load_flags);
234 if(file->tag.title_is("AUDIO"))
236 if((load_flags & LOAD_ACONFIG) &&
237 (load_flags & LOAD_SESSION))
238 session->load_audio_config(file, 0, load_flags);
241 if(file->tag.title_is("FOLDER"))
243 char folder[BCTEXTLEN];
244 strcpy(folder, file->read_text());
248 if(file->tag.title_is("ASSETS"))
250 if(load_flags & LOAD_ASSETS)
251 assets->load(plugindb, file, load_flags);
254 if(file->tag.title_is(labels->xml_tag))
256 if(load_flags & LOAD_TIMEBAR)
257 labels->load(file, load_flags);
260 if(file->tag.title_is("LOCALSESSION"))
262 if((load_flags & LOAD_SESSION) ||
263 (load_flags & LOAD_TIMEBAR))
264 local_session->load_xml(file, load_flags);
267 if(file->tag.title_is("SESSION"))
269 if((load_flags & LOAD_SESSION) &&
271 session->load_xml(file, 0, load_flags);
274 if(file->tag.title_is("TRACK"))
276 tracks->load(file, track_offset, load_flags);
280 // Causes clip creation to fail because that involves an opening EDL tag.
281 if(file->tag.title_is("CLIP_EDL") && !parent_edl)
283 EDL *new_edl = new EDL(this);
284 new_edl->create_objects();
285 new_edl->load_xml(plugindb, file, LOAD_ALL);
287 if((load_flags & LOAD_ALL) == LOAD_ALL)
288 clips.append(new_edl);
293 if(file->tag.title_is("VWINDOW_EDL") && !parent_edl)
295 EDL *new_edl = new EDL(this);
296 new_edl->create_objects();
297 new_edl->load_xml(plugindb, file, LOAD_ALL);
300 if((load_flags & LOAD_ALL) == LOAD_ALL)
302 if(vwindow_edl && !vwindow_edl_shared) delete vwindow_edl;
303 vwindow_edl = new_edl;
304 vwindow_edl_shared = 0;
321 // Output path is the path of the output file if name truncation is desired.
322 // It is a "" if complete names should be used.
323 // Called recursively by copy for clips, thus the string can't be terminated.
324 // The string is not terminated in this call.
325 int EDL::save_xml(ArrayList<PluginServer*> *plugindb,
332 tracks->total_length(),
343 int EDL::copy_all(EDL *edl)
348 tracks->copy_from(edl->tracks);
349 labels->copy_from(edl->labels);
353 void EDL::copy_clips(EDL *edl)
355 if(vwindow_edl && !vwindow_edl_shared) delete vwindow_edl;
357 vwindow_edl_shared = 0;
360 vwindow_edl = new EDL(this);
361 vwindow_edl->create_objects();
362 vwindow_edl->copy_all(edl->vwindow_edl);
364 clips.remove_all_objects();
365 for(int i = 0; i < edl->clips.total; i++)
367 add_clip(edl->clips.values[i]);
371 void EDL::copy_assets(EDL *edl)
375 assets->copy_from(edl->assets);
379 void EDL::copy_session(EDL *edl, int session_only)
383 strcpy(this->project_path, edl->project_path);
385 folders.remove_all_objects();
386 for(int i = 0; i < edl->folders.total; i++)
389 folders.append(new_folder = new char[strlen(edl->folders.values[i]) + 1]);
390 strcpy(new_folder, edl->folders.values[i]);
396 session->copy(edl->session);
401 local_session->copy_from(edl->local_session);
405 int EDL::copy_assets(double start,
409 ArrayList<PluginServer*> *plugindb,
412 ArrayList<Asset*> asset_list;
415 file->tag.set_title("ASSETS");
417 file->append_newline();
419 // Copy everything for a save
422 for(Asset *asset = assets->first;
426 asset_list.append(asset);
430 // Copy just the ones being used.
432 for(current = tracks->first;
438 current->copy_assets(start,
445 // Paths relativised here
446 for(int i = 0; i < asset_list.total; i++)
448 asset_list.values[i]->write(file,
453 file->tag.set_title("/ASSETS");
455 file->append_newline();
456 file->append_newline();
460 int EDL::copy(double start,
466 ArrayList<PluginServer*> *plugindb,
470 //printf("EDL::copy 1\n");
473 file->tag.set_title("CLIP_EDL");
476 file->tag.set_title("VWINDOW_EDL");
479 file->tag.set_title("EDL");
480 file->tag.set_property("VERSION", CINELERRA_VERSION);
481 // Save path for restoration of the project title from a backup.
482 if(this->project_path[0])
484 file->tag.set_property("PROJECT_PATH", project_path);
489 file->append_newline();
491 // Set clipboard samples only if copying to clipboard
494 file->tag.set_title("CLIPBOARD");
495 file->tag.set_property("LENGTH", end - start);
497 file->tag.set_title("/CLIPBOARD");
499 file->append_newline();
500 file->append_newline();
502 //printf("EDL::copy 1\n");
505 local_session->save_xml(file, start);
507 //printf("EDL::copy 1\n");
512 // Need to copy all this from child EDL if pasting is desired.
514 session->save_xml(file);
515 session->save_video_config(file);
516 session->save_audio_config(file);
519 for(int i = 0; i < folders.total; i++)
521 file->tag.set_title("FOLDER");
523 file->append_text(folders.values[i]);
524 file->tag.set_title("/FOLDER");
526 file->append_newline();
530 // Don't replicate all assets for every clip.
531 // The assets for the clips are probably in the mane EDL.
541 // Don't want this if using clipboard
547 vwindow_edl->save_xml(plugindb,
554 for(int i = 0; i < clips.total; i++)
555 clips.values[i]->save_xml(plugindb,
562 file->append_newline();
563 file->append_newline();
567 //printf("EDL::copy 1\n");
569 labels->copy(start, end, file);
570 //printf("EDL::copy 1\n");
571 tracks->copy(start, end, all, file, output_path);
572 //printf("EDL::copy 2\n");
576 file->tag.set_title("/CLIP_EDL");
579 file->tag.set_title("/VWINDOW_EDL");
581 file->tag.set_title("/EDL");
583 file->append_newline();
586 // For editing operations we want to rewind it for immediate pasting.
587 // For clips and saving to disk leave it alone.
590 file->terminate_string();
596 void EDL::rechannel()
598 for(Track *current = tracks->first; current; current = NEXT)
600 if(current->data_type == TRACK_AUDIO)
602 PanAutos *autos = (PanAutos*)current->automation->autos[AUTOMATION_PAN];
603 ((PanAuto*)autos->default_auto)->rechannel();
604 for(PanAuto *keyframe = (PanAuto*)autos->first;
606 keyframe = (PanAuto*)keyframe->next)
608 keyframe->rechannel();
614 void EDL::resample(double old_rate, double new_rate, int data_type)
616 for(Track *current = tracks->first; current; current = NEXT)
618 if(current->data_type == data_type)
620 current->resample(old_rate, new_rate);
626 void EDL::synchronize_params(EDL *edl)
628 local_session->synchronize_params(edl->local_session);
629 for(Track *this_track = tracks->first, *that_track = edl->tracks->first;
630 this_track && that_track;
631 this_track = this_track->next,
632 that_track = that_track->next)
634 this_track->synchronize_params(that_track);
638 int EDL::trim_selection(double start,
651 tracks->total_length(),
659 int EDL::equivalent(double position1, double position2)
661 double threshold = (double).5 / session->frame_rate;
662 if(session->cursor_on_frames)
663 threshold = (double).5 / session->frame_rate;
665 threshold = (double)1 / session->sample_rate;
667 if(fabs(position2 - position1) < threshold)
673 double EDL::equivalent_output(EDL *edl)
676 session->equivalent_output(edl->session, &result);
677 tracks->equivalent_output(edl->tracks, &result);
682 void EDL::set_project_path(char *path)
684 strcpy(this->project_path, path);
687 void EDL::set_inpoint(double position)
689 if(equivalent(local_session->get_inpoint(), position) &&
690 local_session->get_inpoint() >= 0)
692 local_session->unset_inpoint();
696 local_session->set_inpoint(align_to_frame(position, 0));
697 if(local_session->get_outpoint() <= local_session->get_inpoint())
698 local_session->unset_outpoint();
702 void EDL::set_outpoint(double position)
704 if(equivalent(local_session->get_outpoint(), position) &&
705 local_session->get_outpoint() >= 0)
707 local_session->unset_outpoint();
711 local_session->set_outpoint(align_to_frame(position, 0));
712 if(local_session->get_inpoint() >= local_session->get_outpoint())
713 local_session->unset_inpoint();
718 int EDL::clear(double start,
726 tracks->clear_handle(start,
731 if(clear_labels && distance > 0)
732 labels->paste_silence(start,
746 // Need to put at beginning so a subsequent paste operation starts at the
748 double position = local_session->get_selectionstart();
749 local_session->set_selectionend(position);
750 local_session->set_selectionstart(position);
754 void EDL::modify_edithandles(double oldposition,
761 tracks->modify_edithandles(oldposition,
767 labels->modify_handles(oldposition,
774 void EDL::modify_pluginhandles(double oldposition,
781 tracks->modify_pluginhandles(oldposition,
790 void EDL::paste_silence(double start,
796 labels->paste_silence(start, end);
797 tracks->paste_silence(start,
803 void EDL::remove_from_project(ArrayList<EDL*> *clips)
805 for(int i = 0; i < clips->total; i++)
807 for(int j = 0; j < this->clips.total; j++)
809 if(this->clips.values[j] == clips->values[i])
811 this->clips.remove_object(clips->values[i]);
817 void EDL::remove_from_project(ArrayList<Asset*> *assets)
821 for(int j = 0; j < clips.total; j++)
823 clips.values[j]->remove_from_project(assets);
826 // Remove from VWindow
828 vwindow_edl->remove_from_project(assets);
830 for(int i = 0; i < assets->total; i++)
832 // Remove from tracks
833 for(Track *track = tracks->first; track; track = track->next)
835 track->remove_asset(assets->values[i]);
838 // Remove from assets
841 this->assets->remove_asset(assets->values[i]);
846 void EDL::update_assets(EDL *src)
848 for(Asset *current = src->assets->first;
852 assets->update(current);
856 int EDL::get_tracks_height(Theme *theme)
858 int total_pixels = 0;
859 for(Track *current = tracks->first;
863 total_pixels += current->vertical_span(theme);
868 int64_t EDL::get_tracks_width()
870 int64_t total_pixels = 0;
871 for(Track *current = tracks->first;
875 int64_t pixels = current->horizontal_span();
876 if(pixels > total_pixels) total_pixels = pixels;
878 //printf("EDL::get_tracks_width %d\n", total_pixels);
882 // int EDL::calculate_output_w(int single_channel)
884 // if(single_channel) return session->output_w;
887 // for(int i = 0; i < session->video_channels; i++)
889 // if(session->vchannel_x[i] + session->output_w > widest) widest = session->vchannel_x[i] + session->output_w;
894 // int EDL::calculate_output_h(int single_channel)
896 // if(single_channel) return session->output_h;
899 // for(int i = 0; i < session->video_channels; i++)
901 // if(session->vchannel_y[i] + session->output_h > tallest) tallest = session->vchannel_y[i] + session->output_h;
906 // Get the total output size scaled to aspect ratio
907 void EDL::calculate_conformed_dimensions(int single_channel, float &w, float &h)
909 w = session->output_w;
910 h = session->output_h;
912 if((float)session->output_w / session->output_h > get_aspect_ratio())
915 (session->output_w / get_aspect_ratio() / session->output_h);
920 (h * get_aspect_ratio() / session->output_w);
924 float EDL::get_aspect_ratio()
926 return session->aspect_w / session->aspect_h;
935 printf("clip_title: %s parent_edl: %p\n", local_session->clip_title, parent_edl);
936 printf("selectionstart %f selectionend %f loop_start %f loop_end %f\n",
937 local_session->get_selectionstart(1),
938 local_session->get_selectionend(1),
939 local_session->loop_start,
940 local_session->loop_end);
944 printf("audio_channels: %d "
945 "audio_tracks: %d \n"
947 session->audio_channels,
948 session->audio_tracks,
949 session->sample_rate);
950 printf("video_channels: %d "
953 "frames_per_foot: %.2f\n"
959 session->video_channels,
960 session->video_tracks,
962 session->frames_per_foot,
967 session->color_model);
970 printf(" total: %d\n", clips.total);
972 for(int i = 0; i < clips.total; i++)
975 clips.values[i]->dump();
986 //printf("EDL::dump 2\n");
990 EDL* EDL::add_clip(EDL *edl)
992 // Copy argument. New edls are deleted from MWindow::load_filenames.
993 EDL *new_edl = new EDL(this);
994 new_edl->create_objects();
995 new_edl->copy_all(edl);
996 clips.append(new_edl);
1000 void EDL::insert_asset(Asset *asset,
1003 RecordLabels *labels)
1005 // Insert asset into asset table
1006 Asset *new_asset = assets->update(asset);
1011 Track *current = first_track ? first_track : tracks->first;
1014 // Fix length of single frame
1018 if(new_asset->video_length < 0)
1020 if(session->si_useduration)
1021 length = session->si_duration;
1023 length = 1.0 / session->frame_rate;
1026 if(new_asset->frame_rate > 0)
1027 length = ((double)new_asset->video_length / new_asset->frame_rate);
1029 length = 1.0 / session->frame_rate;
1032 current && vtrack < new_asset->layers;
1035 if(!current->record ||
1036 current->data_type != TRACK_VIDEO)
1039 current->insert_asset(new_asset,
1048 for(current = tracks->first;
1049 current && atrack < new_asset->channels;
1052 if(!current->record ||
1053 current->data_type != TRACK_AUDIO)
1056 current->insert_asset(new_asset,
1057 (double)new_asset->audio_length /
1058 new_asset->sample_rate,
1068 for(RecordLabel *label = labels->first; label; label = label->next)
1070 this->labels->toggle_label(label->position, label->position);
1077 void EDL::set_index_file(Asset *asset)
1079 assets->update_index(asset);
1082 void EDL::optimize()
1084 //printf("EDL::optimize 1\n");
1085 double length = tracks->total_length();
1086 if(local_session->preview_end > length) local_session->preview_end = length;
1087 if(local_session->preview_start > length ||
1088 local_session->preview_start < 0) local_session->preview_start = 0;
1089 for(Track *current = tracks->first; current; current = NEXT)
1090 current->optimize();
1095 id_lock->lock("EDL::next_id");
1096 int result = EDLSession::current_id++;
1101 void EDL::get_shared_plugins(Track *source,
1102 ArrayList<SharedLocation*> *plugin_locations)
1104 for(Track *track = tracks->first; track; track = track->next)
1106 if(track != source &&
1107 track->data_type == source->data_type)
1109 for(int i = 0; i < track->plugin_set.total; i++)
1111 Plugin *plugin = track->get_current_plugin(
1112 local_session->get_selectionstart(1),
1117 if(plugin && plugin->plugin_type == PLUGIN_STANDALONE)
1119 plugin_locations->append(new SharedLocation(tracks->number_of(track), i));
1126 void EDL::get_shared_tracks(Track *track, ArrayList<SharedLocation*> *module_locations)
1128 for(Track *current = tracks->first; current; current = NEXT)
1130 if(current != track &&
1131 current->data_type == track->data_type)
1133 module_locations->append(new SharedLocation(tracks->number_of(current), 0));
1138 // Convert position to frames if cursor alignment is enabled
1139 double EDL::align_to_frame(double position, int round)
1141 //printf("EDL::align_to_frame 1 %f\n", position);
1142 if(session->cursor_on_frames)
1144 // Seconds -> Frames
1145 double temp = (double)position * session->frame_rate;
1146 //printf("EDL::align_to_frame 2 %f\n", temp);
1148 // Assert some things
1149 if(session->sample_rate == 0)
1150 printf("EDL::align_to_frame: sample_rate == 0\n");
1152 if(session->frame_rate == 0)
1153 printf("EDL::align_to_frame: frame_rate == 0\n");
1156 // Always round down negative numbers
1157 // but round up only if requested
1160 temp = Units::round(temp);
1169 temp = Units::to_int64(temp);
1171 //printf("EDL::align_to_frame 3 %f\n", temp);
1173 // Frames -> Seconds
1174 temp /= session->frame_rate;
1176 //printf("EDL::align_to_frame 5 %f\n", temp);
1180 //printf("EDL::align_to_frame 3 %d\n", position);
1187 void EDL::new_folder(char *folder)
1189 for(int i = 0; i < folders.total; i++)
1191 if(!strcasecmp(folders.values[i], folder)) return;
1195 folders.append(new_folder = new char[strlen(folder) + 1]);
1196 strcpy(new_folder, folder);
1199 void EDL::delete_folder(char *folder)
1202 for(i = 0; i < folders.total; i++)
1204 if(!strcasecmp(folders.values[i], folder))
1210 if(i < folders.total) delete folders.values[i];
1212 for( ; i < folders.total - 1; i++)
1214 folders.values[i] = folders.values[i + 1];