4 #include "automation.h"
5 #include "awindowgui.inc"
7 #include "colormodels.h"
10 #include "edlsession.h"
14 #include "localsession.h"
17 #include "playbackconfig.h"
19 #include "preferences.h"
20 #include "recordconfig.h"
21 #include "recordlabel.h"
22 #include "sharedlocation.h"
25 #include "transportque.inc"
28 EDL::EDL(EDL *parent_edl)
30 this->parent_edl = parent_edl;
37 folders.set_array_delete();
38 new_folder(CLIP_FOLDER);
39 new_folder(MEDIA_FOLDER);
46 //printf("EDL::~EDL 1\n");
75 folders.remove_all_objects();
76 clips.remove_all_objects();
77 //printf("EDL::~EDL 2\n");
81 int EDL::create_objects()
83 tracks = new Tracks(this);
86 assets = new Assets(this);
87 session = new EDLSession(this);
91 assets = parent_edl->assets;
92 session = parent_edl->session;
95 local_session = new LocalSession(this);
96 labels = new Labels(this, "LABELS");
97 presentations = new Presentations(this);
98 // last_playback_position = 0;
102 EDL& EDL::operator=(EDL &edl)
104 //printf("EDL::operator= 1\n");
106 //printf("EDL::operator= 2\n");
110 int EDL::load_defaults(Defaults *defaults)
113 session->load_defaults(defaults);
115 local_session->load_defaults(defaults);
119 int EDL::save_defaults(Defaults *defaults)
122 session->save_defaults(defaults);
124 local_session->save_defaults(defaults);
128 void EDL::boundaries()
130 session->boundaries();
131 local_session->boundaries();
134 int EDL::create_default_tracks()
137 for(int i = 0; i < session->video_tracks; i++)
139 tracks->add_video_track(0, 0);
141 for(int i = 0; i < session->audio_tracks; i++)
143 tracks->add_audio_track(0, 0);
148 int EDL::load_xml(ArrayList<PluginServer*> *plugindb,
153 // Track numbering offset for replacing undo data.
154 int track_offset = 0;
156 folders.remove_all_objects();
158 // Search for start of master EDL.
160 // The parent_edl test caused clip creation to fail since those XML files
161 // contained an EDL tag.
163 // The parent_edl test is required to make EDL loading work because
164 // when loading an EDL the EDL tag is already read by the parent.
166 if(!parent_edl /* && (load_flags & LOAD_ALL) == LOAD_ALL */)
169 result = file->read_tag();
171 !file->tag.title_is("XML") &&
172 !file->tag.title_is("EDL"));
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->in_point = -1;
193 local_session->out_point = -1;
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(presentations->xml_tag))
249 if(load_flags & LOAD_TIMEBAR)
250 presentations->load(file, load_flags);
253 if(file->tag.title_is("LOCALSESSION"))
255 if((load_flags & LOAD_SESSION) ||
256 (load_flags & LOAD_TIMEBAR))
257 local_session->load_xml(file, load_flags);
260 if(file->tag.title_is("SESSION"))
262 if((load_flags & LOAD_SESSION) &&
264 session->load_xml(file, 0, load_flags);
267 if(file->tag.title_is("TRACK"))
269 tracks->load(file, track_offset, load_flags);
273 // Causes clip creation to fail because that involves an opening EDL tag.
274 if(file->tag.title_is("CLIP_EDL") && !parent_edl)
276 EDL *new_edl = new EDL(this);
277 new_edl->create_objects();
278 new_edl->load_xml(plugindb, file, LOAD_ALL);
280 if((load_flags & LOAD_ALL) == LOAD_ALL)
281 clips.append(new_edl);
286 if(file->tag.title_is("VWINDOW_EDL") && !parent_edl)
288 EDL *new_edl = new EDL(this);
289 new_edl->create_objects();
290 new_edl->load_xml(plugindb, file, LOAD_ALL);
293 if((load_flags & LOAD_ALL) == LOAD_ALL)
295 if(vwindow_edl) delete vwindow_edl;
296 vwindow_edl = new_edl;
306 //printf("EDL::load_xml 4\n");
308 //printf("EDL::load_xml 6 %p\n", parent_edl);
314 // Output path is the path of the output file if name truncation is desired.
315 // It is a "" if complete names should be used.
316 // Called recursively by copy for clips, thus the string can't be terminated.
317 // The string is not terminated in this call.
318 int EDL::save_xml(ArrayList<PluginServer*> *plugindb,
325 tracks->total_length(),
336 int EDL::copy_all(EDL *edl)
341 *this->tracks = *edl->tracks;
342 *this->labels = *edl->labels;
346 void EDL::copy_clips(EDL *edl)
348 if(vwindow_edl) delete vwindow_edl;
352 vwindow_edl = new EDL(this);
353 vwindow_edl->create_objects();
354 vwindow_edl->copy_all(edl->vwindow_edl);
356 clips.remove_all_objects();
357 for(int i = 0; i < edl->clips.total; i++)
359 add_clip(edl->clips.values[i]);
363 void EDL::copy_assets(EDL *edl)
366 *this->assets = *edl->assets;
369 void EDL::copy_session(EDL *edl)
371 folders.remove_all_objects();
372 for(int i = 0; i < edl->folders.total; i++)
375 folders.append(new_folder = new char[strlen(edl->folders.values[i]) + 1]);
376 strcpy(new_folder, edl->folders.values[i]);
381 session->copy(edl->session);
384 local_session->copy_from(edl->local_session);
387 int EDL::copy_assets(double start,
391 ArrayList<PluginServer*> *plugindb,
394 ArrayList<Asset*> asset_list;
397 file->tag.set_title("ASSETS");
399 file->append_newline();
401 // Copy everything for a save
404 for(Asset *asset = assets->first;
408 asset_list.append(asset);
412 // Copy just the ones being used.
414 for(current = tracks->first;
420 current->copy_assets(start,
427 // Paths relativised here
428 for(int i = 0; i < asset_list.total; i++)
430 asset_list.values[i]->write(plugindb,
436 file->tag.set_title("/ASSETS");
438 file->append_newline();
439 file->append_newline();
443 int EDL::copy(double start,
449 ArrayList<PluginServer*> *plugindb,
453 //printf("EDL::copy 1\n");
456 file->tag.set_title("CLIP_EDL");
459 file->tag.set_title("VWINDOW_EDL");
461 file->tag.set_title("EDL");
464 file->append_newline();
466 // Set clipboard samples only if copying to clipboard
469 file->tag.set_title("CLIPBOARD");
470 file->tag.set_property("LENGTH", end - start);
472 file->append_newline();
473 file->append_newline();
475 //printf("EDL::copy 1\n");
478 local_session->save_xml(file, start);
480 //printf("EDL::copy 1\n");
485 // Need to copy all this from child EDL if pasting is desired.
487 session->save_xml(file);
488 session->save_video_config(file);
489 session->save_audio_config(file);
492 for(int i = 0; i < folders.total; i++)
494 file->tag.set_title("FOLDER");
496 file->append_text(folders.values[i]);
497 file->tag.set_title("/FOLDER");
499 file->append_newline();
511 // Don't want this if using clipboard
517 vwindow_edl->save_xml(plugindb,
524 for(int i = 0; i < clips.total; i++)
525 clips.values[i]->save_xml(plugindb,
532 file->append_newline();
533 file->append_newline();
537 //printf("EDL::copy 1\n");
539 labels->copy(start, end, file);
540 //printf("EDL::copy 1\n");
541 presentations->copy(start, end, file);
542 //printf("EDL::copy 1\n");
543 tracks->copy(start, end, all, file, output_path);
544 //printf("EDL::copy 2\n");
548 file->tag.set_title("/CLIP_EDL");
551 file->tag.set_title("/VWINDOW_EDL");
553 file->tag.set_title("/EDL");
555 file->append_newline();
558 // For editing operations we want to rewind it for immediate pasting.
559 // For clips and saving to disk leave it alone.
562 file->terminate_string();
568 void EDL::rechannel()
570 for(Track *current = tracks->first; current; current = NEXT)
572 if(current->data_type == TRACK_AUDIO)
574 PanAutos *autos = current->automation->pan_autos;
575 ((PanAuto*)autos->default_auto)->rechannel();
576 for(PanAuto *keyframe = (PanAuto*)autos->first;
578 keyframe = (PanAuto*)keyframe->next)
580 keyframe->rechannel();
586 void EDL::resample(double old_rate, double new_rate, int data_type)
588 for(Track *current = tracks->first; current; current = NEXT)
590 if(current->data_type == data_type)
592 current->resample(old_rate, new_rate);
598 void EDL::synchronize_params(EDL *edl)
600 local_session->synchronize_params(edl->local_session);
601 for(Track *this_track = tracks->first, *that_track = edl->tracks->first;
602 this_track && that_track;
603 this_track = this_track->next,
604 that_track = that_track->next)
606 this_track->synchronize_params(that_track);
610 int EDL::trim_selection(double start,
623 tracks->total_length(),
631 int EDL::equivalent(double position1, double position2)
633 double half_frame = (double).5 / session->frame_rate;
634 if((session->cursor_on_frames &&
635 fabs(position2 - position1) < half_frame) ||
636 (fabs(position2 - position1) < half_frame))
642 double EDL::equivalent_output(EDL *edl)
645 //printf("EDL::equivalent_output 1 %f\n", result);
646 session->equivalent_output(edl->session, &result);
647 //printf("EDL::equivalent_output 2 %f\n", result);
648 tracks->equivalent_output(edl->tracks, &result);
649 //printf("EDL::equivalent_output 3 %f\n", result);
654 void EDL::set_inpoint(double position)
656 if(equivalent(local_session->in_point, position) && local_session->in_point >= 0)
658 local_session->in_point = -1;
662 local_session->in_point = align_to_frame(position, 0);
663 if(local_session->out_point <= local_session->in_point) local_session->out_point = -1;
667 void EDL::set_outpoint(double position)
669 if(equivalent(local_session->out_point, position) && local_session->out_point >= 0)
671 local_session->out_point = -1;
675 local_session->out_point = align_to_frame(position, 0);
676 if(local_session->in_point >= local_session->out_point) local_session->in_point = -1;
681 int EDL::clear(double start,
689 tracks->clear_handle(start,
694 if(clear_labels && distance > 0)
695 labels->paste_silence(start,
707 presentations->clear(start, end);
710 // Need to put at beginning so a subsequent paste operation starts at the
712 local_session->selectionend =
713 local_session->selectionstart =
714 local_session->get_selectionstart();
718 void EDL::modify_edithandles(double oldposition,
725 tracks->modify_edithandles(oldposition,
731 labels->modify_handles(oldposition,
738 void EDL::modify_pluginhandles(double oldposition,
744 tracks->modify_pluginhandles(oldposition,
752 void EDL::paste_silence(double start,
758 labels->paste_silence(start, end);
759 tracks->paste_silence(start,
765 void EDL::remove_from_project(ArrayList<EDL*> *clips)
767 for(int i = 0; i < clips->total; i++)
769 for(int j = 0; j < this->clips.total; j++)
771 if(this->clips.values[j] == clips->values[i])
773 this->clips.remove_object(clips->values[i]);
779 void EDL::remove_from_project(ArrayList<Asset*> *assets)
783 for(int j = 0; j < clips.total; j++)
785 clips.values[j]->remove_from_project(assets);
788 // Remove from VWindow
790 vwindow_edl->remove_from_project(assets);
792 for(int i = 0; i < assets->total; i++)
794 // Remove from tracks
795 for(Track *track = tracks->first; track; track = track->next)
797 track->remove_asset(assets->values[i]);
800 // Remove from assets
803 this->assets->remove_asset(assets->values[i]);
808 void EDL::update_assets(EDL *src)
810 for(Asset *current = src->assets->first;
814 assets->update(current);
818 int EDL::get_tracks_height(Theme *theme)
820 int total_pixels = 0;
821 for(Track *current = tracks->first;
825 total_pixels += current->vertical_span(theme);
830 int64_t EDL::get_tracks_width()
832 int64_t total_pixels = 0;
833 for(Track *current = tracks->first;
837 int64_t pixels = current->horizontal_span();
838 if(pixels > total_pixels) total_pixels = pixels;
840 //printf("EDL::get_tracks_width %d\n", total_pixels);
844 int EDL::calculate_output_w(int single_channel)
846 if(single_channel) return session->output_w;
849 for(int i = 0; i < session->video_channels; i++)
851 if(session->vchannel_x[i] + session->output_w > widest) widest = session->vchannel_x[i] + session->output_w;
856 int EDL::calculate_output_h(int single_channel)
858 if(single_channel) return session->output_h;
861 for(int i = 0; i < session->video_channels; i++)
863 if(session->vchannel_y[i] + session->output_h > tallest) tallest = session->vchannel_y[i] + session->output_h;
868 // Get the total output size scaled to aspect ratio
869 void EDL::calculate_conformed_dimensions(int single_channel, float &w, float &h)
871 w = calculate_output_w(single_channel);
872 h = calculate_output_h(single_channel);
874 if((float)session->output_w / session->output_h > get_aspect_ratio())
877 (session->output_w / get_aspect_ratio() / session->output_h);
882 (h * get_aspect_ratio() / session->output_w);
886 float EDL::get_aspect_ratio()
888 return session->aspect_w / session->aspect_h;
897 printf("clip_title: %s parent_edl: %p\n", local_session->clip_title, parent_edl);
898 printf("selectionstart %f selectionend %f loop_start %f loop_end %f\n",
899 local_session->selectionstart,
900 local_session->selectionend,
901 local_session->loop_start,
902 local_session->loop_end);
906 printf("audio_channels: %d "
907 "audio_tracks: %d \n"
909 session->audio_channels,
910 session->audio_tracks,
911 session->sample_rate);
912 printf("video_channels: %d "
915 "frames_per_foot: %.2f\n"
921 session->video_channels,
922 session->video_tracks,
924 session->frames_per_foot,
929 session->color_model);
932 printf(" total: %d\n", clips.total);
934 for(int i = 0; i < clips.total; i++)
937 clips.values[i]->dump();
948 //printf("EDL::dump 2\n");
952 EDL* EDL::add_clip(EDL *edl)
954 // Copy argument. New edls are deleted from MWindow::load_filenames.
955 EDL *new_edl = new EDL(this);
956 new_edl->create_objects();
957 new_edl->copy_all(edl);
958 clips.append(new_edl);
962 void EDL::insert_asset(Asset *asset,
965 RecordLabels *labels)
967 // Insert asset into asset table
968 Asset *new_asset = assets->update(asset);
972 Track *current = first_track ? first_track : tracks->first;
974 //printf("EDL::insert_asset 1\n");
976 // Fix length of single frame
980 if(new_asset->video_length < 0)
981 length = 1.0 / session->frame_rate;
983 if(new_asset->frame_rate > 0)
984 length = ((double)new_asset->video_length / new_asset->frame_rate);
986 length = 1.0 / session->frame_rate;
988 //printf("EDL::insert_asset 2 %f\n", length);
990 current && vtrack < new_asset->layers;
993 if(!current->record ||
994 current->data_type != TRACK_VIDEO)
997 //printf("EDL::insert_asset 3\n");
998 current->insert_asset(new_asset,
1003 //printf("EDL::insert_asset 4\n");
1008 for(current = tracks->first;
1009 current && atrack < new_asset->channels;
1012 if(!current->record ||
1013 current->data_type != TRACK_AUDIO)
1016 //printf("EDL::insert_asset 5\n");
1017 current->insert_asset(new_asset,
1018 (double)new_asset->audio_length /
1019 new_asset->sample_rate,
1023 //printf("EDL::insert_asset 6\n");
1030 for(RecordLabel *label = labels->first; label; label = label->next)
1032 //printf("EDL::insert_asset 1 %f\n", label->position);
1033 this->labels->toggle_label(label->position, label->position);
1042 void EDL::set_index_file(Asset *asset)
1044 assets->update_index(asset);
1047 void EDL::optimize()
1049 //printf("EDL::optimize 1\n");
1050 double length = tracks->total_length();
1051 if(local_session->preview_end > length) local_session->preview_end = length;
1052 if(local_session->preview_start > length ||
1053 local_session->preview_start < 0) local_session->preview_start = 0;
1054 for(Track *current = tracks->first; current; current = NEXT)
1055 current->optimize();
1060 return EDLSession::current_id++;
1063 void EDL::get_shared_plugins(Track *source,
1064 ArrayList<SharedLocation*> *plugin_locations)
1066 for(Track *track = tracks->first; track; track = track->next)
1068 if(track != source &&
1069 track->data_type == source->data_type)
1071 for(int i = 0; i < track->plugin_set.total; i++)
1073 Plugin *plugin = track->get_current_plugin(local_session->selectionstart,
1077 if(plugin && plugin->plugin_type == PLUGIN_STANDALONE)
1079 plugin_locations->append(new SharedLocation(tracks->number_of(track), i));
1086 void EDL::get_shared_tracks(Track *track, ArrayList<SharedLocation*> *module_locations)
1088 for(Track *current = tracks->first; current; current = NEXT)
1090 if(current != track &&
1091 current->data_type == track->data_type)
1093 module_locations->append(new SharedLocation(tracks->number_of(current), 0));
1098 // Convert position to frames if cursor alignment is enabled
1099 double EDL::align_to_frame(double position, int round)
1101 //printf("EDL::align_to_frame 1 %f\n", position);
1102 if(session->cursor_on_frames)
1104 // Seconds -> Frames
1105 double temp = (double)position * session->frame_rate;
1106 //printf("EDL::align_to_frame 2 %f\n", temp);
1108 // Assert some things
1109 if(session->sample_rate == 0)
1110 printf("EDL::align_to_frame: sample_rate == 0\n");
1112 if(session->frame_rate == 0)
1113 printf("EDL::align_to_frame: frame_rate == 0\n");
1116 // Always round down negative numbers
1117 // but round up only if requested
1120 temp = Units::round(temp);
1129 temp = Units::to_int64(temp);
1131 //printf("EDL::align_to_frame 3 %f\n", temp);
1133 // Frames -> Seconds
1134 temp /= session->frame_rate;
1136 //printf("EDL::align_to_frame 5 %f\n", temp);
1140 //printf("EDL::align_to_frame 3 %d\n", position);
1147 void EDL::new_folder(char *folder)
1149 for(int i = 0; i < folders.total; i++)
1151 if(!strcasecmp(folders.values[i], folder)) return;
1155 folders.append(new_folder = new char[strlen(folder) + 1]);
1156 strcpy(new_folder, folder);
1159 void EDL::delete_folder(char *folder)
1162 for(i = 0; i < folders.total; i++)
1164 if(!strcasecmp(folders.values[i], folder))
1170 if(i < folders.total) delete folders.values[i];
1172 for( ; i < folders.total - 1; i++)
1174 folders.values[i] = folders.values[i + 1];