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)
85 folders.remove_all_objects();
86 clips.remove_all_objects();
90 int EDL::create_objects()
92 tracks = new Tracks(this);
95 assets = Assets_GC(new Assets(this));
96 session = new EDLSession(this);
100 assets = parent_edl->assets;
101 session = parent_edl->session;
104 local_session = new LocalSession(this);
105 labels = new Labels(this, "LABELS");
106 // last_playback_position = 0;
110 EDL& EDL::operator=(EDL &edl)
112 printf("EDL::operator= 1\n");
117 int EDL::load_defaults(BC_Hash *defaults)
120 session->load_defaults(defaults);
122 local_session->load_defaults(defaults);
126 int EDL::save_defaults(BC_Hash *defaults)
129 session->save_defaults(defaults);
131 local_session->save_defaults(defaults);
135 void EDL::boundaries()
137 session->boundaries();
138 local_session->boundaries();
141 int EDL::create_default_tracks()
144 for(int i = 0; i < session->video_tracks; i++)
146 tracks->add_video_track(0, 0);
148 for(int i = 0; i < session->audio_tracks; i++)
150 tracks->add_audio_track(0, 0);
155 int EDL::load_xml(ArrayList<PluginServer*> *plugindb,
160 // Track numbering offset for replacing undo data.
161 int track_offset = 0;
164 folders.remove_all_objects();
166 // Search for start of master EDL.
168 // The parent_edl test caused clip creation to fail since those XML files
169 // contained an EDL tag.
171 // The parent_edl test is required to make EDL loading work because
172 // when loading an EDL the EDL tag is already read by the parent.
177 result = file->read_tag();
179 !file->tag.title_is("XML") &&
180 !file->tag.title_is("EDL"));
185 // Get path for backups
187 file->tag.get_property("PROJECT_PATH", project_path);
190 if((load_flags & LOAD_ALL) == LOAD_ALL ||
191 (load_flags & LOAD_EDITS) == LOAD_EDITS)
193 while(tracks->last) delete tracks->last;
196 if((load_flags & LOAD_ALL) == LOAD_ALL)
198 clips.remove_all_objects();
201 if(load_flags & LOAD_TIMEBAR)
203 while(labels->last) delete labels->last;
204 local_session->unset_inpoint();
205 local_session->unset_outpoint();
209 result = file->read_tag();
213 if(file->tag.title_is("/XML") ||
214 file->tag.title_is("/EDL") ||
215 file->tag.title_is("/CLIP_EDL") ||
216 file->tag.title_is("/VWINDOW_EDL"))
221 if(file->tag.title_is("CLIPBOARD"))
223 local_session->clipboard_length = file->tag.get_property("LENGTH", 0);
226 if(file->tag.title_is("VIDEO"))
228 if((load_flags & LOAD_VCONFIG) &&
229 (load_flags & LOAD_SESSION))
230 session->load_video_config(file, 0, load_flags);
233 if(file->tag.title_is("AUDIO"))
235 if((load_flags & LOAD_ACONFIG) &&
236 (load_flags & LOAD_SESSION))
237 session->load_audio_config(file, 0, load_flags);
240 if(file->tag.title_is("FOLDER"))
242 char folder[BCTEXTLEN];
243 strcpy(folder, file->read_text());
247 if(file->tag.title_is("ASSETS"))
249 if(load_flags & LOAD_ASSETS)
250 assets->load(plugindb, file, load_flags);
253 if(file->tag.title_is(labels->xml_tag))
255 if(load_flags & LOAD_TIMEBAR)
256 labels->load(file, load_flags);
259 if(file->tag.title_is("LOCALSESSION"))
261 if((load_flags & LOAD_SESSION) ||
262 (load_flags & LOAD_TIMEBAR))
263 local_session->load_xml(file, load_flags);
266 if(file->tag.title_is("SESSION"))
268 if((load_flags & LOAD_SESSION) &&
270 session->load_xml(file, 0, load_flags);
273 if(file->tag.title_is("TRACK"))
275 tracks->load(file, track_offset, load_flags);
279 // Causes clip creation to fail because that involves an opening EDL tag.
280 if(file->tag.title_is("CLIP_EDL") && !parent_edl)
282 EDL *new_edl = new EDL(this);
283 new_edl->create_objects();
284 new_edl->load_xml(plugindb, file, LOAD_ALL);
286 if((load_flags & LOAD_ALL) == LOAD_ALL)
287 clips.append(new_edl);
292 if(file->tag.title_is("VWINDOW_EDL") && !parent_edl)
294 EDL *new_edl = new EDL(this);
295 new_edl->create_objects();
296 new_edl->load_xml(plugindb, file, LOAD_ALL);
299 if((load_flags & LOAD_ALL) == LOAD_ALL)
301 if(vwindow_edl && !vwindow_edl_shared) delete vwindow_edl;
302 vwindow_edl = new_edl;
303 vwindow_edl_shared = 0;
320 // Output path is the path of the output file if name truncation is desired.
321 // It is a "" if complete names should be used.
322 // Called recursively by copy for clips, thus the string can't be terminated.
323 // The string is not terminated in this call.
324 int EDL::save_xml(ArrayList<PluginServer*> *plugindb,
331 tracks->total_length(),
342 int EDL::copy_all(EDL *edl)
347 tracks->copy_from(edl->tracks);
348 labels->copy_from(edl->labels);
352 void EDL::copy_clips(EDL *edl)
354 if(vwindow_edl && !vwindow_edl_shared) delete vwindow_edl;
356 vwindow_edl_shared = 0;
359 vwindow_edl = new EDL(this);
360 vwindow_edl->create_objects();
361 vwindow_edl->copy_all(edl->vwindow_edl);
363 clips.remove_all_objects();
364 for(int i = 0; i < edl->clips.total; i++)
366 add_clip(edl->clips.values[i]);
370 void EDL::copy_assets(EDL *edl)
374 assets->copy_from(*edl->assets);
378 void EDL::copy_session(EDL *edl, int session_only)
382 strcpy(this->project_path, edl->project_path);
384 folders.remove_all_objects();
385 for(int i = 0; i < edl->folders.total; i++)
388 folders.append(new_folder = new char[strlen(edl->folders.values[i]) + 1]);
389 strcpy(new_folder, edl->folders.values[i]);
395 session->copy(edl->session);
400 local_session->copy_from(edl->local_session);
404 int EDL::copy_assets(double start,
408 ArrayList<PluginServer*> *plugindb,
411 std::vector<Asset_GC> asset_list;
414 file->tag.set_title("ASSETS");
416 file->append_newline();
418 // Copy everything for a save
421 for(Assets_list::iterator asset = assets->begin();
422 asset != assets->end();
425 asset_list.push_back(*asset);
429 // Copy just the ones being used.
431 for(current = tracks->first;
437 current->copy_assets(start,
444 // Paths relativised here
445 for(int i = 0; i < asset_list.size(); i++)
447 asset_list[i]->write(file,
452 file->tag.set_title("/ASSETS");
454 file->append_newline();
455 file->append_newline();
459 int EDL::copy(double start,
465 ArrayList<PluginServer*> *plugindb,
469 //printf("EDL::copy 1\n");
472 file->tag.set_title("CLIP_EDL");
475 file->tag.set_title("VWINDOW_EDL");
478 file->tag.set_title("EDL");
479 file->tag.set_property("VERSION", CINELERRA_VERSION);
480 // Save path for restoration of the project title from a backup.
481 if(this->project_path[0])
483 file->tag.set_property("PROJECT_PATH", project_path);
488 file->append_newline();
490 // Set clipboard samples only if copying to clipboard
493 file->tag.set_title("CLIPBOARD");
494 file->tag.set_property("LENGTH", end - start);
496 file->tag.set_title("/CLIPBOARD");
498 file->append_newline();
499 file->append_newline();
501 //printf("EDL::copy 1\n");
504 local_session->save_xml(file, start);
506 //printf("EDL::copy 1\n");
511 // Need to copy all this from child EDL if pasting is desired.
513 session->save_xml(file);
514 session->save_video_config(file);
515 session->save_audio_config(file);
518 for(int i = 0; i < folders.total; i++)
520 file->tag.set_title("FOLDER");
522 file->append_text(folders.values[i]);
523 file->tag.set_title("/FOLDER");
525 file->append_newline();
529 // Don't replicate all assets for every clip.
530 // The assets for the clips are probably in the mane EDL.
540 // Don't want this if using clipboard
546 vwindow_edl->save_xml(plugindb,
553 for(int i = 0; i < clips.total; i++)
554 clips.values[i]->save_xml(plugindb,
561 file->append_newline();
562 file->append_newline();
566 //printf("EDL::copy 1\n");
568 labels->copy(start, end, file);
569 //printf("EDL::copy 1\n");
570 tracks->copy(start, end, all, file, output_path);
571 //printf("EDL::copy 2\n");
575 file->tag.set_title("/CLIP_EDL");
578 file->tag.set_title("/VWINDOW_EDL");
580 file->tag.set_title("/EDL");
582 file->append_newline();
585 // For editing operations we want to rewind it for immediate pasting.
586 // For clips and saving to disk leave it alone.
589 file->terminate_string();
595 void EDL::rechannel()
597 for(Track *current = tracks->first; current; current = NEXT)
599 if(current->data_type == TRACK_AUDIO)
601 PanAutos *autos = (PanAutos*)current->automation->autos[AUTOMATION_PAN];
602 ((PanAuto*)autos->default_auto)->rechannel();
603 for(PanAuto *keyframe = (PanAuto*)autos->first;
605 keyframe = (PanAuto*)keyframe->next)
607 keyframe->rechannel();
613 void EDL::resample(double old_rate, double new_rate, int data_type)
615 for(Track *current = tracks->first; current; current = NEXT)
617 if(current->data_type == data_type)
619 current->resample(old_rate, new_rate);
625 void EDL::synchronize_params(EDL *edl)
627 local_session->synchronize_params(edl->local_session);
628 for(Track *this_track = tracks->first, *that_track = edl->tracks->first;
629 this_track && that_track;
630 this_track = this_track->next,
631 that_track = that_track->next)
633 this_track->synchronize_params(that_track);
637 int EDL::trim_selection(double start,
650 tracks->total_length(),
658 int EDL::equivalent(double position1, double position2)
660 double threshold = (double).5 / session->frame_rate;
661 if(session->cursor_on_frames)
662 threshold = (double).5 / session->frame_rate;
664 threshold = (double)1 / session->sample_rate;
666 if(fabs(position2 - position1) < threshold)
672 double EDL::equivalent_output(EDL *edl)
675 session->equivalent_output(edl->session, &result);
676 tracks->equivalent_output(edl->tracks, &result);
681 void EDL::set_project_path(char *path)
683 strcpy(this->project_path, path);
686 void EDL::set_inpoint(double position)
688 if(equivalent(local_session->get_inpoint(), position) &&
689 local_session->get_inpoint() >= 0)
691 local_session->unset_inpoint();
695 local_session->set_inpoint(align_to_frame(position, 0));
696 if(local_session->get_outpoint() <= local_session->get_inpoint())
697 local_session->unset_outpoint();
701 void EDL::set_outpoint(double position)
703 if(equivalent(local_session->get_outpoint(), position) &&
704 local_session->get_outpoint() >= 0)
706 local_session->unset_outpoint();
710 local_session->set_outpoint(align_to_frame(position, 0));
711 if(local_session->get_inpoint() >= local_session->get_outpoint())
712 local_session->unset_inpoint();
717 int EDL::clear(double start,
725 tracks->clear_handle(start,
730 if(clear_labels && distance > 0)
731 labels->paste_silence(start,
745 // Need to put at beginning so a subsequent paste operation starts at the
747 double position = local_session->get_selectionstart();
748 local_session->set_selectionend(position);
749 local_session->set_selectionstart(position);
753 void EDL::modify_edithandles(double oldposition,
760 tracks->modify_edithandles(oldposition,
766 labels->modify_handles(oldposition,
773 void EDL::modify_pluginhandles(double oldposition,
780 tracks->modify_pluginhandles(oldposition,
789 void EDL::paste_silence(double start,
795 labels->paste_silence(start, end);
796 tracks->paste_silence(start,
802 void EDL::remove_from_project(ArrayList<EDL*> *clips)
804 for(int i = 0; i < clips->total; i++)
806 for(int j = 0; j < this->clips.total; j++)
808 if(this->clips.values[j] == clips->values[i])
810 this->clips.remove_object(clips->values[i]);
816 void EDL::remove_from_project(Assets_vector &assets)
820 for(int j = 0; j < clips.total; j++)
822 clips.values[j]->remove_from_project(assets);
825 // Remove from VWindow
827 vwindow_edl->remove_from_project(assets);
829 for(int i = 0; i < assets.size(); i++)
831 // Remove from tracks
832 for(Track *track = tracks->first; track; track = track->next)
834 track->remove_asset(assets[i]);
837 // Remove from assets
840 this->assets->remove_asset(assets[i]);
845 void EDL::update_assets(EDL *src)
847 for(Assets_list::iterator current = src->assets->begin();
848 current != src->assets->end();
851 assets->update(*current);
855 int EDL::get_tracks_height(Theme *theme)
857 int total_pixels = 0;
858 for(Track *current = tracks->first;
862 total_pixels += current->vertical_span(theme);
867 int64_t EDL::get_tracks_width()
869 int64_t total_pixels = 0;
870 for(Track *current = tracks->first;
874 int64_t pixels = current->horizontal_span();
875 if(pixels > total_pixels) total_pixels = pixels;
877 //printf("EDL::get_tracks_width %d\n", total_pixels);
881 // int EDL::calculate_output_w(int single_channel)
883 // if(single_channel) return session->output_w;
886 // for(int i = 0; i < session->video_channels; i++)
888 // if(session->vchannel_x[i] + session->output_w > widest) widest = session->vchannel_x[i] + session->output_w;
893 // int EDL::calculate_output_h(int single_channel)
895 // if(single_channel) return session->output_h;
898 // for(int i = 0; i < session->video_channels; i++)
900 // if(session->vchannel_y[i] + session->output_h > tallest) tallest = session->vchannel_y[i] + session->output_h;
905 // Get the total output size scaled to aspect ratio
906 void EDL::calculate_conformed_dimensions(int single_channel, float &w, float &h)
908 w = session->output_w;
909 h = session->output_h;
911 if((float)session->output_w / session->output_h > get_aspect_ratio())
914 (session->output_w / get_aspect_ratio() / session->output_h);
919 (h * get_aspect_ratio() / session->output_w);
923 float EDL::get_aspect_ratio()
925 return session->aspect_w / session->aspect_h;
934 printf("clip_title: %s parent_edl: %p\n", local_session->clip_title, parent_edl);
935 printf("selectionstart %f selectionend %f loop_start %f loop_end %f\n",
936 local_session->get_selectionstart(1),
937 local_session->get_selectionend(1),
938 local_session->loop_start,
939 local_session->loop_end);
943 printf("audio_channels: %d "
944 "audio_tracks: %d \n"
946 session->audio_channels,
947 session->audio_tracks,
948 session->sample_rate);
949 printf("video_channels: %d "
952 "frames_per_foot: %.2f\n"
958 session->video_channels,
959 session->video_tracks,
961 session->frames_per_foot,
966 session->color_model);
969 printf(" total: %d\n", clips.total);
971 for(int i = 0; i < clips.total; i++)
974 clips.values[i]->dump();
985 //printf("EDL::dump 2\n");
989 EDL* EDL::add_clip(EDL *edl)
991 // Copy argument. New edls are deleted from MWindow::load_filenames.
992 EDL *new_edl = new EDL(this);
993 new_edl->create_objects();
994 new_edl->copy_all(edl);
995 clips.append(new_edl);
999 void EDL::insert_asset(Asset_GC asset,
1002 RecordLabels *labels)
1004 // Insert asset into asset table
1005 Asset_GC new_asset = assets->update(asset);
1010 Track *current = first_track ? first_track : tracks->first;
1013 // Fix length of single frame
1017 if(new_asset->video_length < 0)
1019 if(session->si_useduration)
1020 length = session->si_duration;
1022 length = 1.0 / session->frame_rate;
1025 if(new_asset->frame_rate > 0)
1026 length = ((double)new_asset->video_length / new_asset->frame_rate);
1028 length = 1.0 / session->frame_rate;
1031 current && vtrack < new_asset->layers;
1034 if(!current->record ||
1035 current->data_type != TRACK_VIDEO)
1038 current->insert_asset(new_asset,
1047 for(current = tracks->first;
1048 current && atrack < new_asset->channels;
1051 if(!current->record ||
1052 current->data_type != TRACK_AUDIO)
1055 current->insert_asset(new_asset,
1056 (double)new_asset->audio_length /
1057 new_asset->sample_rate,
1067 for(RecordLabel *label = labels->first; label; label = label->next)
1069 this->labels->toggle_label(label->position, label->position);
1076 void EDL::set_index_file(Asset_GC asset)
1078 assets->update_index(*asset);
1081 void EDL::optimize()
1083 //printf("EDL::optimize 1\n");
1084 double length = tracks->total_length();
1085 if(local_session->preview_end > length) local_session->preview_end = length;
1086 if(local_session->preview_start > length ||
1087 local_session->preview_start < 0) local_session->preview_start = 0;
1088 for(Track *current = tracks->first; current; current = NEXT)
1089 current->optimize();
1094 id_lock->lock("EDL::next_id");
1095 int result = EDLSession::current_id++;
1100 void EDL::get_shared_plugins(Track *source,
1101 ArrayList<SharedLocation*> *plugin_locations)
1103 for(Track *track = tracks->first; track; track = track->next)
1105 if(track != source &&
1106 track->data_type == source->data_type)
1108 for(int i = 0; i < track->plugin_set.total; i++)
1110 Plugin *plugin = track->get_current_plugin(
1111 local_session->get_selectionstart(1),
1116 if(plugin && plugin->plugin_type == PLUGIN_STANDALONE)
1118 plugin_locations->append(new SharedLocation(tracks->number_of(track), i));
1125 void EDL::get_shared_tracks(Track *track, ArrayList<SharedLocation*> *module_locations)
1127 for(Track *current = tracks->first; current; current = NEXT)
1129 if(current != track &&
1130 current->data_type == track->data_type)
1132 module_locations->append(new SharedLocation(tracks->number_of(current), 0));
1137 // Convert position to frames if cursor alignment is enabled
1138 double EDL::align_to_frame(double position, int round)
1140 //printf("EDL::align_to_frame 1 %f\n", position);
1141 if(session->cursor_on_frames)
1143 // Seconds -> Frames
1144 double temp = (double)position * session->frame_rate;
1145 //printf("EDL::align_to_frame 2 %f\n", temp);
1147 // Assert some things
1148 if(session->sample_rate == 0)
1149 printf("EDL::align_to_frame: sample_rate == 0\n");
1151 if(session->frame_rate == 0)
1152 printf("EDL::align_to_frame: frame_rate == 0\n");
1155 // Always round down negative numbers
1156 // but round up only if requested
1159 temp = Units::round(temp);
1168 temp = Units::to_int64(temp);
1170 //printf("EDL::align_to_frame 3 %f\n", temp);
1172 // Frames -> Seconds
1173 temp /= session->frame_rate;
1175 //printf("EDL::align_to_frame 5 %f\n", temp);
1179 //printf("EDL::align_to_frame 3 %d\n", position);
1186 void EDL::new_folder(char *folder)
1188 for(int i = 0; i < folders.total; i++)
1190 if(!strcasecmp(folders.values[i], folder)) return;
1194 folders.append(new_folder = new char[strlen(folder) + 1]);
1195 strcpy(new_folder, folder);
1198 void EDL::delete_folder(char *folder)
1201 for(i = 0; i < folders.total; i++)
1203 if(!strcasecmp(folders.values[i], folder))
1209 if(i < folders.total) delete folders.values[i];
1211 for( ; i < folders.total - 1; i++)
1213 folders.values[i] = folders.values[i + 1];
1219 // c-file-style: "linux"