5 #include "automation.h"
6 #include "awindowgui.inc"
9 #include "colormodels.h"
12 #include "edlsession.h"
16 #include "localsession.h"
19 #include "playbackconfig.h"
21 #include "preferences.h"
22 #include "recordconfig.h"
23 #include "recordlabel.h"
24 #include "sharedlocation.h"
27 #include "transportque.inc"
30 EDL::EDL(EDL *parent_edl)
32 this->parent_edl = parent_edl;
38 folders.set_array_delete();
39 new_folder(CLIP_FOLDER);
40 new_folder(MEDIA_FOLDER);
48 //printf("EDL::~EDL 1\n");
73 folders.remove_all_objects();
74 clips.remove_all_objects();
75 //printf("EDL::~EDL 2\n");
79 int EDL::create_objects()
81 tracks = new Tracks(this);
84 assets = new Assets(this);
85 session = new EDLSession(this);
89 assets = parent_edl->assets;
90 session = parent_edl->session;
93 local_session = new LocalSession(this);
94 labels = new Labels(this, "LABELS");
95 // last_playback_position = 0;
99 EDL& EDL::operator=(EDL &edl)
101 printf("EDL::operator= 1\n");
106 int EDL::load_defaults(Defaults *defaults)
109 session->load_defaults(defaults);
111 local_session->load_defaults(defaults);
115 int EDL::save_defaults(Defaults *defaults)
118 session->save_defaults(defaults);
120 local_session->save_defaults(defaults);
124 void EDL::boundaries()
126 session->boundaries();
127 local_session->boundaries();
130 int EDL::create_default_tracks()
133 for(int i = 0; i < session->video_tracks; i++)
135 tracks->add_video_track(0, 0);
137 for(int i = 0; i < session->audio_tracks; i++)
139 tracks->add_audio_track(0, 0);
144 int EDL::load_xml(ArrayList<PluginServer*> *plugindb,
149 // Track numbering offset for replacing undo data.
150 int track_offset = 0;
152 folders.remove_all_objects();
154 // Search for start of master EDL.
156 // The parent_edl test caused clip creation to fail since those XML files
157 // contained an EDL tag.
159 // The parent_edl test is required to make EDL loading work because
160 // when loading an EDL the EDL tag is already read by the parent.
165 result = file->read_tag();
167 !file->tag.title_is("XML") &&
168 !file->tag.title_is("EDL"));
173 // Get path for backups
175 file->tag.get_property("PROJECT_PATH", project_path);
178 if((load_flags & LOAD_ALL) == LOAD_ALL ||
179 (load_flags & LOAD_EDITS) == LOAD_EDITS)
181 while(tracks->last) delete tracks->last;
184 if((load_flags & LOAD_ALL) == LOAD_ALL)
186 clips.remove_all_objects();
189 if(load_flags & LOAD_TIMEBAR)
191 while(labels->last) delete labels->last;
192 local_session->unset_inpoint();
193 local_session->unset_outpoint();
197 result = file->read_tag();
201 if(file->tag.title_is("/XML") ||
202 file->tag.title_is("/EDL") ||
203 file->tag.title_is("/CLIP_EDL") ||
204 file->tag.title_is("/VWINDOW_EDL"))
209 if(file->tag.title_is("CLIPBOARD"))
211 local_session->clipboard_length = file->tag.get_property("LENGTH", 0);
214 if(file->tag.title_is("VIDEO"))
216 if((load_flags & LOAD_VCONFIG) &&
217 (load_flags & LOAD_SESSION))
218 session->load_video_config(file, 0, load_flags);
221 if(file->tag.title_is("AUDIO"))
223 if((load_flags & LOAD_ACONFIG) &&
224 (load_flags & LOAD_SESSION))
225 session->load_audio_config(file, 0, load_flags);
228 if(file->tag.title_is("FOLDER"))
230 char folder[BCTEXTLEN];
231 strcpy(folder, file->read_text());
235 if(file->tag.title_is("ASSETS"))
237 if(load_flags & LOAD_ASSETS)
238 assets->load(plugindb, file, load_flags);
241 if(file->tag.title_is(labels->xml_tag))
243 if(load_flags & LOAD_TIMEBAR)
244 labels->load(file, load_flags);
247 if(file->tag.title_is("LOCALSESSION"))
249 if((load_flags & LOAD_SESSION) ||
250 (load_flags & LOAD_TIMEBAR))
251 local_session->load_xml(file, load_flags);
254 if(file->tag.title_is("SESSION"))
256 if((load_flags & LOAD_SESSION) &&
258 session->load_xml(file, 0, load_flags);
261 if(file->tag.title_is("TRACK"))
263 tracks->load(file, track_offset, load_flags);
267 // Causes clip creation to fail because that involves an opening EDL tag.
268 if(file->tag.title_is("CLIP_EDL") && !parent_edl)
270 EDL *new_edl = new EDL(this);
271 new_edl->create_objects();
272 new_edl->load_xml(plugindb, file, LOAD_ALL);
274 if((load_flags & LOAD_ALL) == LOAD_ALL)
275 clips.append(new_edl);
280 if(file->tag.title_is("VWINDOW_EDL") && !parent_edl)
282 EDL *new_edl = new EDL(this);
283 new_edl->create_objects();
284 new_edl->load_xml(plugindb, file, LOAD_ALL);
287 if((load_flags & LOAD_ALL) == LOAD_ALL)
289 if(vwindow_edl) delete vwindow_edl;
290 vwindow_edl = new_edl;
300 //printf("EDL::load_xml 4\n");
303 //printf("EDL::load_xml 6 %p\n", parent_edl);
309 // Output path is the path of the output file if name truncation is desired.
310 // It is a "" if complete names should be used.
311 // Called recursively by copy for clips, thus the string can't be terminated.
312 // The string is not terminated in this call.
313 int EDL::save_xml(ArrayList<PluginServer*> *plugindb,
320 tracks->total_length(),
331 int EDL::copy_all(EDL *edl)
336 tracks->copy_from(edl->tracks);
337 labels->copy_from(edl->labels);
341 void EDL::copy_clips(EDL *edl)
343 if(vwindow_edl) delete vwindow_edl;
347 vwindow_edl = new EDL(this);
348 vwindow_edl->create_objects();
349 vwindow_edl->copy_all(edl->vwindow_edl);
351 clips.remove_all_objects();
352 for(int i = 0; i < edl->clips.total; i++)
354 add_clip(edl->clips.values[i]);
358 void EDL::copy_assets(EDL *edl)
362 assets->copy_from(edl->assets);
366 void EDL::copy_session(EDL *edl)
368 strcpy(this->project_path, edl->project_path);
370 folders.remove_all_objects();
371 for(int i = 0; i < edl->folders.total; i++)
374 folders.append(new_folder = new char[strlen(edl->folders.values[i]) + 1]);
375 strcpy(new_folder, edl->folders.values[i]);
380 session->copy(edl->session);
383 local_session->copy_from(edl->local_session);
386 int EDL::copy_assets(double start,
390 ArrayList<PluginServer*> *plugindb,
393 ArrayList<Asset*> asset_list;
396 file->tag.set_title("ASSETS");
398 file->append_newline();
400 // Copy everything for a save
403 for(Asset *asset = assets->first;
407 asset_list.append(asset);
411 // Copy just the ones being used.
413 for(current = tracks->first;
419 current->copy_assets(start,
426 // Paths relativised here
427 for(int i = 0; i < asset_list.total; i++)
429 asset_list.values[i]->write(file,
434 file->tag.set_title("/ASSETS");
436 file->append_newline();
437 file->append_newline();
441 int EDL::copy(double start,
447 ArrayList<PluginServer*> *plugindb,
451 //printf("EDL::copy 1\n");
454 file->tag.set_title("CLIP_EDL");
457 file->tag.set_title("VWINDOW_EDL");
460 file->tag.set_title("EDL");
461 file->tag.set_property("VERSION", CINELERRA_VERSION);
462 // Save path for restoration of the project title from a backup.
463 if(this->project_path[0])
465 file->tag.set_property("PROJECT_PATH", project_path);
470 file->append_newline();
472 // Set clipboard samples only if copying to clipboard
475 file->tag.set_title("CLIPBOARD");
476 file->tag.set_property("LENGTH", end - start);
478 file->tag.set_title("/CLIPBOARD");
480 file->append_newline();
481 file->append_newline();
483 //printf("EDL::copy 1\n");
486 local_session->save_xml(file, start);
488 //printf("EDL::copy 1\n");
493 // Need to copy all this from child EDL if pasting is desired.
495 session->save_xml(file);
496 session->save_video_config(file);
497 session->save_audio_config(file);
500 for(int i = 0; i < folders.total; i++)
502 file->tag.set_title("FOLDER");
504 file->append_text(folders.values[i]);
505 file->tag.set_title("/FOLDER");
507 file->append_newline();
519 // Don't want this if using clipboard
525 vwindow_edl->save_xml(plugindb,
532 for(int i = 0; i < clips.total; i++)
533 clips.values[i]->save_xml(plugindb,
540 file->append_newline();
541 file->append_newline();
545 //printf("EDL::copy 1\n");
547 labels->copy(start, end, file);
548 //printf("EDL::copy 1\n");
549 tracks->copy(start, end, all, file, output_path);
550 //printf("EDL::copy 2\n");
554 file->tag.set_title("/CLIP_EDL");
557 file->tag.set_title("/VWINDOW_EDL");
559 file->tag.set_title("/EDL");
561 file->append_newline();
564 // For editing operations we want to rewind it for immediate pasting.
565 // For clips and saving to disk leave it alone.
568 file->terminate_string();
574 void EDL::rechannel()
576 for(Track *current = tracks->first; current; current = NEXT)
578 if(current->data_type == TRACK_AUDIO)
580 PanAutos *autos = (PanAutos*)current->automation->autos[AUTOMATION_PAN];
581 ((PanAuto*)autos->default_auto)->rechannel();
582 for(PanAuto *keyframe = (PanAuto*)autos->first;
584 keyframe = (PanAuto*)keyframe->next)
586 keyframe->rechannel();
592 void EDL::resample(double old_rate, double new_rate, int data_type)
594 for(Track *current = tracks->first; current; current = NEXT)
596 if(current->data_type == data_type)
598 current->resample(old_rate, new_rate);
604 void EDL::synchronize_params(EDL *edl)
606 local_session->synchronize_params(edl->local_session);
607 for(Track *this_track = tracks->first, *that_track = edl->tracks->first;
608 this_track && that_track;
609 this_track = this_track->next,
610 that_track = that_track->next)
612 this_track->synchronize_params(that_track);
616 int EDL::trim_selection(double start,
629 tracks->total_length(),
637 int EDL::equivalent(double position1, double position2)
639 double threshold = (double).5 / session->frame_rate;
640 if(session->cursor_on_frames)
641 threshold = (double).5 / session->frame_rate;
643 threshold = (double)1 / session->sample_rate;
645 if(fabs(position2 - position1) < threshold)
651 double EDL::equivalent_output(EDL *edl)
654 session->equivalent_output(edl->session, &result);
655 tracks->equivalent_output(edl->tracks, &result);
660 void EDL::set_project_path(char *path)
662 strcpy(this->project_path, path);
665 void EDL::set_inpoint(double position)
667 if(equivalent(local_session->get_inpoint(), position) &&
668 local_session->get_inpoint() >= 0)
670 local_session->unset_inpoint();
674 local_session->set_inpoint(align_to_frame(position, 0));
675 if(local_session->get_outpoint() <= local_session->get_inpoint())
676 local_session->unset_outpoint();
680 void EDL::set_outpoint(double position)
682 if(equivalent(local_session->get_outpoint(), position) &&
683 local_session->get_outpoint() >= 0)
685 local_session->unset_outpoint();
689 local_session->set_outpoint(align_to_frame(position, 0));
690 if(local_session->get_inpoint() >= local_session->get_outpoint())
691 local_session->unset_inpoint();
696 int EDL::clear(double start,
704 tracks->clear_handle(start,
709 if(clear_labels && distance > 0)
710 labels->paste_silence(start,
724 // Need to put at beginning so a subsequent paste operation starts at the
726 double position = local_session->get_selectionstart();
727 local_session->set_selectionend(position);
728 local_session->set_selectionstart(position);
732 void EDL::modify_edithandles(double oldposition,
739 tracks->modify_edithandles(oldposition,
745 labels->modify_handles(oldposition,
752 void EDL::modify_pluginhandles(double oldposition,
759 tracks->modify_pluginhandles(oldposition,
768 void EDL::paste_silence(double start,
774 labels->paste_silence(start, end);
775 tracks->paste_silence(start,
781 void EDL::remove_from_project(ArrayList<EDL*> *clips)
783 for(int i = 0; i < clips->total; i++)
785 for(int j = 0; j < this->clips.total; j++)
787 if(this->clips.values[j] == clips->values[i])
789 this->clips.remove_object(clips->values[i]);
795 void EDL::remove_from_project(ArrayList<Asset*> *assets)
799 for(int j = 0; j < clips.total; j++)
801 clips.values[j]->remove_from_project(assets);
804 // Remove from VWindow
806 vwindow_edl->remove_from_project(assets);
808 for(int i = 0; i < assets->total; i++)
810 // Remove from tracks
811 for(Track *track = tracks->first; track; track = track->next)
813 track->remove_asset(assets->values[i]);
816 // Remove from assets
819 this->assets->remove_asset(assets->values[i]);
824 void EDL::update_assets(EDL *src)
826 for(Asset *current = src->assets->first;
830 assets->update(current);
834 int EDL::get_tracks_height(Theme *theme)
836 int total_pixels = 0;
837 for(Track *current = tracks->first;
841 total_pixels += current->vertical_span(theme);
846 int64_t EDL::get_tracks_width()
848 int64_t total_pixels = 0;
849 for(Track *current = tracks->first;
853 int64_t pixels = current->horizontal_span();
854 if(pixels > total_pixels) total_pixels = pixels;
856 //printf("EDL::get_tracks_width %d\n", total_pixels);
860 // int EDL::calculate_output_w(int single_channel)
862 // if(single_channel) return session->output_w;
865 // for(int i = 0; i < session->video_channels; i++)
867 // if(session->vchannel_x[i] + session->output_w > widest) widest = session->vchannel_x[i] + session->output_w;
872 // int EDL::calculate_output_h(int single_channel)
874 // if(single_channel) return session->output_h;
877 // for(int i = 0; i < session->video_channels; i++)
879 // if(session->vchannel_y[i] + session->output_h > tallest) tallest = session->vchannel_y[i] + session->output_h;
884 // Get the total output size scaled to aspect ratio
885 void EDL::calculate_conformed_dimensions(int single_channel, float &w, float &h)
887 w = session->output_w;
888 h = session->output_h;
890 if((float)session->output_w / session->output_h > get_aspect_ratio())
893 (session->output_w / get_aspect_ratio() / session->output_h);
898 (h * get_aspect_ratio() / session->output_w);
902 float EDL::get_aspect_ratio()
904 return session->aspect_w / session->aspect_h;
913 printf("clip_title: %s parent_edl: %p\n", local_session->clip_title, parent_edl);
914 printf("selectionstart %f selectionend %f loop_start %f loop_end %f\n",
915 local_session->get_selectionstart(1),
916 local_session->get_selectionend(1),
917 local_session->loop_start,
918 local_session->loop_end);
922 printf("audio_channels: %d "
923 "audio_tracks: %d \n"
925 session->audio_channels,
926 session->audio_tracks,
927 session->sample_rate);
928 printf("video_channels: %d "
931 "frames_per_foot: %.2f\n"
937 session->video_channels,
938 session->video_tracks,
940 session->frames_per_foot,
945 session->color_model);
948 printf(" total: %d\n", clips.total);
950 for(int i = 0; i < clips.total; i++)
953 clips.values[i]->dump();
964 //printf("EDL::dump 2\n");
968 EDL* EDL::add_clip(EDL *edl)
970 // Copy argument. New edls are deleted from MWindow::load_filenames.
971 EDL *new_edl = new EDL(this);
972 new_edl->create_objects();
973 new_edl->copy_all(edl);
974 clips.append(new_edl);
978 void EDL::insert_asset(Asset *asset,
981 RecordLabels *labels)
983 // Insert asset into asset table
984 Asset *new_asset = assets->update(asset);
989 Track *current = first_track ? first_track : tracks->first;
992 // Fix length of single frame
996 if(new_asset->video_length < 0)
998 if(session->si_useduration)
999 length = session->si_duration;
1001 length = 1.0 / session->frame_rate;
1004 if(new_asset->frame_rate > 0)
1005 length = ((double)new_asset->video_length / new_asset->frame_rate);
1007 length = 1.0 / session->frame_rate;
1010 current && vtrack < new_asset->layers;
1013 if(!current->record ||
1014 current->data_type != TRACK_VIDEO)
1017 current->insert_asset(new_asset,
1026 for(current = tracks->first;
1027 current && atrack < new_asset->channels;
1030 if(!current->record ||
1031 current->data_type != TRACK_AUDIO)
1034 current->insert_asset(new_asset,
1035 (double)new_asset->audio_length /
1036 new_asset->sample_rate,
1046 for(RecordLabel *label = labels->first; label; label = label->next)
1048 this->labels->toggle_label(label->position, label->position);
1055 void EDL::set_index_file(Asset *asset)
1057 assets->update_index(asset);
1060 void EDL::optimize()
1062 //printf("EDL::optimize 1\n");
1063 double length = tracks->total_length();
1064 if(local_session->preview_end > length) local_session->preview_end = length;
1065 if(local_session->preview_start > length ||
1066 local_session->preview_start < 0) local_session->preview_start = 0;
1067 for(Track *current = tracks->first; current; current = NEXT)
1068 current->optimize();
1073 return EDLSession::current_id++;
1076 void EDL::get_shared_plugins(Track *source,
1077 ArrayList<SharedLocation*> *plugin_locations)
1079 for(Track *track = tracks->first; track; track = track->next)
1081 if(track != source &&
1082 track->data_type == source->data_type)
1084 for(int i = 0; i < track->plugin_set.total; i++)
1086 Plugin *plugin = track->get_current_plugin(
1087 local_session->get_selectionstart(1),
1092 if(plugin && plugin->plugin_type == PLUGIN_STANDALONE)
1094 plugin_locations->append(new SharedLocation(tracks->number_of(track), i));
1101 void EDL::get_shared_tracks(Track *track, ArrayList<SharedLocation*> *module_locations)
1103 for(Track *current = tracks->first; current; current = NEXT)
1105 if(current != track &&
1106 current->data_type == track->data_type)
1108 module_locations->append(new SharedLocation(tracks->number_of(current), 0));
1113 // Convert position to frames if cursor alignment is enabled
1114 double EDL::align_to_frame(double position, int round)
1116 //printf("EDL::align_to_frame 1 %f\n", position);
1117 if(session->cursor_on_frames)
1119 // Seconds -> Frames
1120 double temp = (double)position * session->frame_rate;
1121 //printf("EDL::align_to_frame 2 %f\n", temp);
1123 // Assert some things
1124 if(session->sample_rate == 0)
1125 printf("EDL::align_to_frame: sample_rate == 0\n");
1127 if(session->frame_rate == 0)
1128 printf("EDL::align_to_frame: frame_rate == 0\n");
1131 // Always round down negative numbers
1132 // but round up only if requested
1135 temp = Units::round(temp);
1144 temp = Units::to_int64(temp);
1146 //printf("EDL::align_to_frame 3 %f\n", temp);
1148 // Frames -> Seconds
1149 temp /= session->frame_rate;
1151 //printf("EDL::align_to_frame 5 %f\n", temp);
1155 //printf("EDL::align_to_frame 3 %d\n", position);
1162 void EDL::new_folder(char *folder)
1164 for(int i = 0; i < folders.total; i++)
1166 if(!strcasecmp(folders.values[i], folder)) return;
1170 folders.append(new_folder = new char[strlen(folder) + 1]);
1171 strcpy(new_folder, folder);
1174 void EDL::delete_folder(char *folder)
1177 for(i = 0; i < folders.total; i++)
1179 if(!strcasecmp(folders.values[i], folder))
1185 if(i < folders.total) delete folders.values[i];
1187 for( ; i < folders.total - 1; i++)
1189 folders.values[i] = folders.values[i + 1];