X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fmwindowedit.C;h=458ced964e8f3418505b7d27ccf19adb80662dd0;hp=2db6fa0bd33e3788d436bd75dd90227fdcb929da;hb=f62d927a25cb3b02f2197fde99c77df3005d41a7;hpb=0e16112661802284c0d2c9eb8d1df84141125e91 diff --git a/cinelerra-5.1/cinelerra/mwindowedit.C b/cinelerra-5.1/cinelerra/mwindowedit.C index 2db6fa0b..458ced96 100644 --- a/cinelerra-5.1/cinelerra/mwindowedit.C +++ b/cinelerra-5.1/cinelerra/mwindowedit.C @@ -27,6 +27,7 @@ #include "clip.h" #include "clipedit.h" #include "commercials.h" +#include "convert.h" #include "cplayback.h" #include "ctimebar.h" #include "cwindow.h" @@ -84,7 +85,8 @@ void MWindow::add_audio_track_entry(int above, Track *dst) { undo_before(); - add_audio_track(above, dst); + Track *track = add_audio_track(above, dst); + track->master = 1; save_backup(); undo_after(_("add track"), LOAD_ALL); @@ -94,10 +96,11 @@ void MWindow::add_audio_track_entry(int above, Track *dst) cwindow->refresh_frame(CHANGE_EDL); } -void MWindow::add_video_track_entry(Track *dst) +void MWindow::add_video_track_entry(int above, Track *dst) { undo_before(); - add_video_track(1, dst); + Track *track = add_video_track(above, dst); + track->master = 1; undo_after(_("add track"), LOAD_ALL); restart_brender(); @@ -108,10 +111,11 @@ void MWindow::add_video_track_entry(Track *dst) save_backup(); } -void MWindow::add_subttl_track_entry(Track *dst) +void MWindow::add_subttl_track_entry(int above, Track *dst) { undo_before(); - add_subttl_track(1, dst); + Track *track = add_subttl_track(above, dst); + track->master = 1; undo_after(_("add track"), LOAD_ALL); restart_brender(); @@ -123,28 +127,28 @@ void MWindow::add_subttl_track_entry(Track *dst) } -int MWindow::add_audio_track(int above, Track *dst) +Track *MWindow::add_audio_track(int above, Track *dst) { - edl->tracks->add_audio_track(above, dst); + Track *track = edl->tracks->add_audio_track(above, dst); edl->tracks->update_y_pixels(theme); save_backup(); - return 0; + return track; } -int MWindow::add_video_track(int above, Track *dst) +Track *MWindow::add_video_track(int above, Track *dst) { - edl->tracks->add_video_track(above, dst); + Track *track = edl->tracks->add_video_track(above, dst); edl->tracks->update_y_pixels(theme); save_backup(); - return 0; + return track; } -int MWindow::add_subttl_track(int above, Track *dst) +Track *MWindow::add_subttl_track(int above, Track *dst) { - edl->tracks->add_subttl_track(above, dst); + Track *track = edl->tracks->add_subttl_track(above, dst); edl->tracks->update_y_pixels(theme); save_backup(); - return 0; + return track; } void MWindow::asset_to_all() @@ -178,7 +182,7 @@ void MWindow::asset_to_all() for( Track *current=edl->tracks->first; current; current=NEXT ) { if( current->data_type == TRACK_VIDEO /* && - current->record */ ) { + current->is_armed() */ ) { current->track_w = w; current->track_h = h; } @@ -285,7 +289,8 @@ void MWindow::clear_entry() edl->optimize(); save_backup(); - undo_after(_("clear"), LOAD_EDITS | LOAD_TIMEBAR); + undo_after(_("clear"), + LOAD_AUTOMATION + LOAD_EDITS + LOAD_TIMEBAR); restart_brender(); update_plugin_guis(); @@ -332,7 +337,7 @@ void MWindow::set_automation_mode(int mode) edl->local_session->get_selectionstart(), edl->local_session->get_selectionend(), mode); - int changed_edl = speed_after(1); + int changed_edl = speed_after(1, 1); save_backup(); char string[BCSTRLEN]; sprintf(string,"set %s", FloatAuto::curve_name(mode)); @@ -348,7 +353,7 @@ void MWindow::clear_automation() speed_before(); edl->tracks->clear_automation(edl->local_session->get_selectionstart(), edl->local_session->get_selectionend()); - int changed_edl = speed_after(1); + int changed_edl = speed_after(1, 1); save_backup(); undo_after(_("clear keyframes"), !changed_edl ? LOAD_AUTOMATION : @@ -361,7 +366,7 @@ int MWindow::clear_default_keyframe() undo_before(); speed_before(); edl->tracks->clear_default_keyframe(); - int changed_edl = speed_after(1); + int changed_edl = speed_after(1, 1); save_backup(); undo_after(_("clear default keyframe"), !changed_edl ? LOAD_AUTOMATION : @@ -421,6 +426,14 @@ void MWindow::clear_select() gui->draw_overlays(1); } +void MWindow::select_edits(int v) +{ + double start = edl->local_session->get_selectionstart(); + double end = edl->local_session->get_selectionend(); + edl->tracks->select_edits(start, end, v); + gui->draw_overlays(1); +} + void MWindow::concatenate_tracks() { undo_before(); @@ -664,7 +677,7 @@ int MWindow::cut_automation() copy_automation(); edl->tracks->clear_automation(edl->local_session->get_selectionstart(), edl->local_session->get_selectionend()); - int changed_edl = speed_after(1); + int changed_edl = speed_after(1, 1); save_backup(); undo_after(_("cut keyframes"), !changed_edl ? LOAD_AUTOMATION : @@ -680,7 +693,7 @@ int MWindow::cut_default_keyframe() speed_before(); copy_default_keyframe(); edl->tracks->clear_default_keyframe(); - int changed_edl = speed_after(1); + int changed_edl = speed_after(1, 1); save_backup(); undo_after(_("cut default keyframe"), !changed_edl ? LOAD_AUTOMATION : @@ -760,19 +773,40 @@ void MWindow::insert(double position, FileXML *file, //printf("MWindow::insert 6 %p\n", vwindow->get_edl()); } -void MWindow::insert_effects_canvas(double start, - double length) +void MWindow::insert_effects_canvas(Track *dest_track, double start, double length) { - Track *dest_track = session->track_highlighted; - if( !dest_track ) return; - undo_before(); - for( int i=0; idrag_pluginservers->total; ++i ) { - PluginServer *plugin = session->drag_pluginservers->values[i]; - insert_effect(plugin->title, 0, dest_track, - i == 0 ? session->pluginset_highlighted : 0, - start, length, PLUGIN_STANDALONE); + ArrayList shared_locations; + PluginSet *pluginset = session->pluginset_highlighted; + int gang = edl->local_session->gang_tracks != GANG_NONE ? 1 : 0; + int data_type = dest_track->data_type; + int first_track = 1; + + for( Track *track=dest_track; track; track=track->next ) { + if( gang && track->master && !first_track ) break; + if( track->data_type != data_type ) continue; + if( !track->is_armed() ) continue; + int module = edl->tracks->number_of(track); + for( int i=0; idrag_pluginservers->total; ++i ) { + PluginServer *plugin = session->drag_pluginservers->values[i]; + int shared = gang; // && plugin->multichannel ? 1 : 0; + int plugin_type = !first_track && shared ? + PLUGIN_SHAREDPLUGIN : PLUGIN_STANDALONE; + SharedLocation *shared_location = !first_track ? + &shared_locations[i] : &shared_locations.append(); + insert_effect(plugin->title, shared_location, track, + pluginset, start, length, plugin_type); + if( first_track && shared ) { + shared_location->module = module; + shared_location->plugin = pluginset ? + track->plugin_set.number_of(pluginset) : + track->plugin_set.total-1 ; + } + } + if( !gang ) break; + first_track = 0; + pluginset = 0; } save_backup(); @@ -786,8 +820,6 @@ void MWindow::insert_effects_cwindow(Track *dest_track) { if( !dest_track ) return; - undo_before(); - double start = 0; double length = dest_track->get_length(); @@ -798,55 +830,45 @@ void MWindow::insert_effects_cwindow(Track *dest_track) edl->local_session->get_selectionstart(); } - for( int i=0; idrag_pluginservers->total; ++i ) { - PluginServer *plugin = session->drag_pluginservers->values[i]; - insert_effect(plugin->title, 0, dest_track, 0, - start, length, PLUGIN_STANDALONE); - } - - save_backup(); - undo_after(_("insert effect"), LOAD_EDITS | LOAD_PATCHES); - restart_brender(); - sync_parameters(CHANGE_EDL); + insert_effects_canvas(dest_track, start, length); gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); } -void MWindow::insert_effect(char *title, - SharedLocation *shared_location, - int data_type, - int plugin_type, - int single_standalone) +void MWindow::insert_effect(char *title, SharedLocation *shared_location, + int data_type, int plugin_type, int single_standalone) { Track *current = edl->tracks->first; SharedLocation shared_location_local; shared_location_local.copy_from(shared_location); int first_track = 1; + double start_pos = edl->local_session->get_selectionstart(); + double end_pos = edl->local_session->get_selectionend(); for( ; current; current=NEXT ) { - if( current->data_type == data_type && - current->record ) { - insert_effect(title, &shared_location_local, - current, 0, 0, 0, plugin_type); - - if( first_track ) { - if( plugin_type == PLUGIN_STANDALONE && single_standalone ) { - plugin_type = PLUGIN_SHAREDPLUGIN; - shared_location_local.module = edl->tracks->number_of(current); - shared_location_local.plugin = current->plugin_set.total - 1; - } - first_track = 0; + if( current->data_type != data_type ) continue; + if( !current->is_armed() ) continue; + double start = start_pos, end = end_pos; + if( plugin_type == PLUGIN_STANDALONE && start >= end ) { + start = 0; + end = current->get_length(); + } + double length = end - start; + insert_effect(title, &shared_location_local, + current, 0, start, length, plugin_type); + if( first_track ) { + if( plugin_type == PLUGIN_STANDALONE && single_standalone ) { + plugin_type = PLUGIN_SHAREDPLUGIN; + shared_location_local.module = edl->tracks->number_of(current); + shared_location_local.plugin = current->plugin_set.total - 1; + start_pos = start; end_pos = end; } + first_track = 0; } } } - void MWindow::insert_effect(char *title, - SharedLocation *shared_location, - Track *track, - PluginSet *plugin_set, - double start, - double length, - int plugin_type) + SharedLocation *shared_location, Track *track, PluginSet *plugin_set, + double start, double length, int plugin_type) { KeyFrame *default_keyframe = 0; PluginServer *server = 0; @@ -859,9 +881,8 @@ void MWindow::insert_effect(char *title, server->save_data(default_keyframe); } // Insert plugin object - track->insert_effect(title, shared_location, - default_keyframe, plugin_set, - start, length, plugin_type); + track->insert_effect(title, shared_location, default_keyframe, + plugin_set, start, length, plugin_type); track->optimize(); if( plugin_type == PLUGIN_STANDALONE ) { @@ -939,6 +960,34 @@ void MWindow::finish_modify_handles() cwindow->update(1, 0, 0, 0, 1); } +int MWindow::modify_transnhandles() +{ + gui->reset_default_message(); + gui->default_message(); + Transition *transition = session->drag_transition; + if( !transition ) return 1; + int64_t length = transition->length; + Track *track = transition->edit->track; + int64_t start_pos = track->to_units(session->drag_start, 0); + int64_t end_pos = track->to_units(session->drag_position, 0); + length += end_pos - start_pos; + if( length < 0 ) length = 0; + if( length == transition->length ) return 0; + + undo_before(); + transition->length = length; + undo_after(_("trans handle"), LOAD_EDITS); + + save_backup(); + restart_brender(); + sync_parameters(CHANGE_EDL); + update_plugin_guis(); + gui->update(1, FORCE_REDRAW, 1, 1, 1, 1, 0); + cwindow->update(1, 0, 0, 0, 1); + + return 0; +} + void MWindow::match_output_size(Track *track) { undo_before(); @@ -1143,12 +1192,62 @@ void MWindow::move_plugins_down(PluginSet *plugin_set) sync_parameters(CHANGE_EDL); } +void MWindow::roll_track_down(Track *track) +{ + undo_before(); + edl->tracks->roll_track_down(track); + save_backup(); + undo_after(_("move track down"), LOAD_ALL); + + restart_brender(); + gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); + sync_parameters(CHANGE_EDL); + save_backup(); +} + +void MWindow::roll_tracks_down() +{ + undo_before(); + edl->tracks->roll_tracks_down(); + save_backup(); + undo_after(_("move tracks down"), LOAD_ALL); + + restart_brender(); + gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); + sync_parameters(CHANGE_EDL); + save_backup(); +} + +void MWindow::roll_track_up(Track *track) +{ + undo_before(); + edl->tracks->roll_track_up(track); + save_backup(); + undo_after(_("move track up"), LOAD_ALL); + restart_brender(); + gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); + sync_parameters(CHANGE_EDL); + save_backup(); +} + +void MWindow::roll_tracks_up() +{ + undo_before(); + edl->tracks->roll_tracks_up(); + save_backup(); + undo_after(_("move tracks up"), LOAD_ALL); + restart_brender(); + gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); + sync_parameters(CHANGE_EDL); +} + + void MWindow::move_track_down(Track *track) { undo_before(); edl->tracks->move_track_down(track); save_backup(); - undo_after(_("move track down"), LOAD_ALL); + undo_after(_("swap track down"), LOAD_ALL); restart_brender(); gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); @@ -1161,7 +1260,7 @@ void MWindow::move_tracks_down() undo_before(); edl->tracks->move_tracks_down(); save_backup(); - undo_after(_("move tracks down"), LOAD_ALL); + undo_after(_("swap tracks down"), LOAD_ALL); restart_brender(); gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); @@ -1174,7 +1273,7 @@ void MWindow::move_track_up(Track *track) undo_before(); edl->tracks->move_track_up(track); save_backup(); - undo_after(_("move track up"), LOAD_ALL); + undo_after(_("swap track up"), LOAD_ALL); restart_brender(); gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); sync_parameters(CHANGE_EDL); @@ -1186,7 +1285,7 @@ void MWindow::move_tracks_up() undo_before(); edl->tracks->move_tracks_up(); save_backup(); - undo_after(_("move tracks up"), LOAD_ALL); + undo_after(_("swap tracks up"), LOAD_ALL); restart_brender(); gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); sync_parameters(CHANGE_EDL); @@ -1249,16 +1348,23 @@ void MWindow::overwrite(EDL *source, int all) // so we need to clear only when not using both io points // FIXME: need to write simple overwrite_edl to be used for overwrite function if( edl->local_session->get_inpoint() < 0 || - edl->local_session->get_outpoint() < 0 ) - edl->clear(dst_start, dst_start + overwrite_len, 0, 0, 0); + edl->local_session->get_outpoint() < 0 ) + edl->clear(dst_start, dst_start + overwrite_len, + edl->session->labels_follow_edits, + edl->session->plugins_follow_edits, + edl->session->autos_follow_edits); - paste(dst_start, dst_start + overwrite_len, &file, 0, 0, 0, 0, 0); + paste(dst_start, dst_start + overwrite_len, &file, + edl->session->labels_follow_edits, + edl->session->plugins_follow_edits, + edl->session->autos_follow_edits, 0, 0); edl->local_session->set_selectionstart(dst_start + overwrite_len); edl->local_session->set_selectionend(dst_start + overwrite_len); save_backup(); - undo_after(_("overwrite"), LOAD_EDITS); + undo_after(_("overwrite"), + LOAD_AUTOMATION + LOAD_EDITS + LOAD_TIMEBAR); restart_brender(); update_plugin_guis(); @@ -1311,7 +1417,8 @@ void MWindow::paste(double start, Track *first_track, int clear_selection, int o save_backup(); - undo_after(_("paste"), LOAD_EDITS | LOAD_TIMEBAR); + undo_after(_("paste"), + LOAD_AUTOMATION + LOAD_EDITS + LOAD_TIMEBAR); restart_brender(); update_plugin_guis(); gui->update(1, FORCE_REDRAW, 1, 1, 0, 1, 0); @@ -1348,7 +1455,8 @@ int MWindow::paste_assets(double position, Track *dest_track, int overwrite) save_backup(); - undo_after(_("paste assets"), LOAD_EDITS); + undo_after(_("paste assets"), + LOAD_AUTOMATION + LOAD_EDITS + LOAD_TIMEBAR); restart_brender(); gui->update(1, FORCE_REDRAW, 1, 0, 0, 1, 0); sync_parameters(CHANGE_EDL); @@ -1370,7 +1478,7 @@ if( debug ) printf("MWindow::load_assets %d\n", __LINE__); for( int i=0; itotal; ++i ) { Indexable *indexable = new_assets->get(i); if( indexable->is_asset ) { - remove_asset_from_caches((Asset*)indexable); + remove_from_caches(indexable); } EDL *new_edl = new EDL; new_edl->create_objects(); @@ -1422,7 +1530,7 @@ int MWindow::paste_automation() edl->tracks->clear_automation(start, end); edl->tracks->paste_automation(start, &file, 0, 1, edl->session->typeless_keyframes); - int changed_edl = speed_after(1); + int changed_edl = speed_after(1, 0); save_backup(); undo_after(_("paste keyframes"), !changed_edl ? LOAD_AUTOMATION : @@ -1449,7 +1557,7 @@ int MWindow::paste_default_keyframe() edl->tracks->paste_automation(start, &file, 1, 0, edl->session->typeless_keyframes); // edl->tracks->paste_default_keyframe(&file); - int changed_edl = speed_after(1); + int changed_edl = speed_after(1, 1); undo_after(_("paste default keyframe"), !changed_edl ? LOAD_AUTOMATION : LOAD_AUTOMATION + LOAD_EDITS + LOAD_TIMEBAR); @@ -1482,7 +1590,7 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, // Delete current project if( load_mode == LOADMODE_REPLACE || load_mode == LOADMODE_REPLACE_CONCATENATE ) { - reset_caches(); + reset_caches(1); edl->save_defaults(defaults); hide_plugins(); edl->Garbage::remove_user(); @@ -1515,6 +1623,7 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, need_new_tracks = 1; for( int i=0; itotal; ++i ) { EDL *new_edl = new_edls->values[i]; + int first_track = 1; for( Track *current=new_edl->tracks->first; current; current=NEXT ) { switch( current->data_type ) { case TRACK_VIDEO: @@ -1530,6 +1639,10 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, default: continue; } + if( first_track ) { + edl->tracks->last->master = 1; + first_track = 0; + } // re-label only if not already labeled if( new_edl->local_session->asset2edl ) strcpy(current->title, edl->tracks->last->title); @@ -1544,11 +1657,10 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, else // Recycle existing tracks of master EDL if( load_mode == LOADMODE_CONCATENATE || - load_mode == LOADMODE_PASTE || - load_mode == LOADMODE_NESTED ) { + load_mode == LOADMODE_PASTE ) { Track *current = first_track ? first_track : edl->tracks->first; for( ; current; current=NEXT ) { - if( current->record ) { + if( current->is_armed() ) { destination_tracks.append(current); } } @@ -1582,13 +1694,15 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, // Add assets and prepare index files for( Asset *new_asset=new_edl->assets->first; new_asset; new_asset=new_asset->next ) { - mainindexes->add_next_asset(0, new_asset); + mainindexes->add_indexable(new_asset); } // Capture index file status from mainindex test edl->update_assets(new_edl); //PRINT_TRACE // Get starting point of insertion. Need this to paste labels. switch( load_mode ) { + case LOADMODE_NOTHING: + continue; case LOADMODE_REPLACE: current_position = 0; break; @@ -1607,7 +1721,6 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, break; case LOADMODE_PASTE: - case LOADMODE_NESTED: destination_track = 0; if( i == 0 ) { for( int j=0; j *new_edls, int load_mode, load_mode != LOADMODE_ASSETSONLY ) { // Insert labels if( edit_labels ) { - if( load_mode == LOADMODE_PASTE || load_mode == LOADMODE_NESTED ) + if( load_mode == LOADMODE_PASTE ) edl->labels->insert_labels(new_edl->labels, destination_tracks.total ? paste_position[0] : 0.0, edl_length, 1); @@ -1651,14 +1764,14 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, if( destination_track < destination_tracks.total && destination_tracks.values[destination_track]->data_type == new_track->data_type ) { Track *track = destination_tracks.values[destination_track]; - // Replace default keyframes if first EDL and new tracks were created. // This means data copied from one track and pasted to another won't retain // the camera position unless it's a keyframe. If it did, previous data in the // track might get unknowingly corrupted. Ideally we would detect when differing // default keyframes existed and create discrete keyframes for both. int replace_default = (i == 0) && need_new_tracks; - +// master tracks are the first track in each new edl when new tracks are created + int master = track->master; //printf("MWindow::paste_edls 1 %d\n", replace_default); // Insert new track at current position switch( load_mode ) { @@ -1668,7 +1781,6 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, break; case LOADMODE_PASTE: - case LOADMODE_NESTED: current_position = paste_position[destination_track]; paste_position[destination_track] += new_track->get_length(); break; @@ -1685,6 +1797,7 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, //PRINT_TRACE track->insert_track(new_track, current_position, replace_default, edit_plugins, edit_autos, edl_length); + if( master ) track->master = 1; //PRINT_TRACE } @@ -1695,8 +1808,7 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, } } - if( load_mode == LOADMODE_PASTE || - load_mode == LOADMODE_NESTED ) + if( load_mode == LOADMODE_PASTE ) current_position += edl_length; } @@ -1765,7 +1877,8 @@ void MWindow::paste_silence() edl->session->autos_follow_edits); edl->optimize(); save_backup(); - undo_after(_("silence"), LOAD_EDITS | LOAD_TIMEBAR); + undo_after(_("silence"), + LOAD_AUTOMATION + LOAD_EDITS + LOAD_TIMEBAR); update_plugin_guis(); restart_brender(); @@ -2136,7 +2249,8 @@ void MWindow::splice(EDL *source, int all) edl->local_session->set_selectionend(start + source_end - source_start); save_backup(); - undo_after(_("splice"), LOAD_EDITS | LOAD_TIMEBAR); + undo_after(_("splice"), + LOAD_AUTOMATION + LOAD_EDITS + LOAD_TIMEBAR); update_plugin_guis(); restart_brender(); gui->update(1, NORMAL_DRAW, 1, 1, 0, 1, 0); @@ -2159,7 +2273,7 @@ void MWindow::save_clip(EDL *new_edl, const char *txt) Track *track = new_edl->tracks->first; const char *path = edl->path; for( ; (!path || !*path) && track; track=track->next ) { - if( !track->record ) continue; + if( !track->is_armed() ) continue; Edit *edit = track->edits->first; if( !edit ) continue; Indexable *indexable = edit->get_source(); @@ -2170,28 +2284,24 @@ void MWindow::save_clip(EDL *new_edl, const char *txt) time_t now; time(&now); struct tm dtm; localtime_r(&now, &dtm); char *cp = new_edl->local_session->clip_notes; - int n, sz = sizeof(new_edl->local_session->clip_notes)-1; - if( txt && *txt ) { - n = snprintf(cp, sz, "%s", txt); - cp += n; sz -= n; - } - n = snprintf(cp, sz, + char *ep = cp + sizeof(new_edl->local_session->clip_notes)-1; + if( txt && *txt ) + cp += snprintf(cp, ep-cp, "%s", txt); + cp += snprintf(cp, ep-cp, "%02d/%02d/%02d %02d:%02d:%02d, +%s\n", dtm.tm_year+1900, dtm.tm_mon+1, dtm.tm_mday, dtm.tm_hour, dtm.tm_min, dtm.tm_sec, duration); - cp += n; sz -= n; if( path && *path ) { FileSystem fs; char title[BCTEXTLEN]; fs.extract_name(title, path); - n = snprintf(cp, sz, "%s", title); - cp += n; sz -= n; + cp += snprintf(cp, ep-cp, "%s", title); } - cp[n] = 0; sprintf(new_edl->local_session->clip_icon, - "clip_%02d%02d%02d-%02d%02d%02d.png", + "clip_%02d%02d%02d-%02d%02d%02d-%d.png", dtm.tm_year+1900, dtm.tm_mon+1, dtm.tm_mday, - dtm.tm_hour, dtm.tm_min, dtm.tm_sec); + dtm.tm_hour, dtm.tm_min, dtm.tm_sec, + new_edl->id); new_edl->folder_no = AW_CLIP_FOLDER; edl->update_assets(new_edl); int cur_x, cur_y; @@ -2271,7 +2381,8 @@ void MWindow::trim_selection() edl->session->autos_follow_edits); save_backup(); - undo_after(_("trim selection"), LOAD_EDITS | LOAD_TIMEBAR); + undo_after(_("trim selection"), + LOAD_AUTOMATION + LOAD_EDITS + LOAD_TIMEBAR); update_plugin_guis(); gui->update(1, FORCE_REDRAW, 1, 1, 1, 1, 0); cwindow->update(1, 0, 0, 0, 1); @@ -2390,7 +2501,7 @@ void MWindow::remap_audio(int pattern) int current_track = 0; for( Track *current=edl->tracks->first; current; current=NEXT ) { if( current->data_type == TRACK_AUDIO && - current->record ) { + current->is_armed() ) { Autos *pan_autos = current->automation->autos[AUTOMATION_PAN]; PanAuto *pan_auto = (PanAuto*)pan_autos->get_auto_for_editing(-1); @@ -2443,6 +2554,45 @@ void MWindow::add_proxy(ArrayList *orig_assets, ArrayListadd_proxy(orig_assets, proxy_assets); } +void MWindow::start_convert(Asset *format_asset, const char *suffix, + float beep, int to_proxy, int remove_originals) +{ + if( !convert_render ) + convert_render = new ConvertRender(this); + convert_render->set_format(format_asset, suffix, to_proxy); + int found = convert_render->find_convertable_assets(edl); + if( convert_render->needed_idxbls.size() > 0 ) + convert_render->start_convert(beep, remove_originals); + else if( found > 0 ) + finish_convert(remove_originals); + else if( found < 0 ) + eprintf(_("convert assets format error")); + else + eprintf(_("No convertable assets found")); +} + +void MWindow::finish_convert(int remove_originals) +{ + gui->lock_window("MWindow::finish_convert"); + undo_before(); + edl->replace_assets( + convert_render->orig_idxbls, + convert_render->orig_copies); + if( remove_originals ) { + remove_assets_from_project(0, 0, 0, + &convert_render->orig_idxbls, 0); + } + save_backup(); + undo_after(_("convert"), LOAD_ALL); + + update_plugin_guis(); + gui->update(1, FORCE_REDRAW, 1, 1, 1, 1, 0); + cwindow->update(1, 0, 0, 0, 1); + awindow->gui->async_update_assets(); + cwindow->refresh_frame(CHANGE_EDL); + gui->unlock_window(); +} + void MWindow::cut_commercials() { #ifdef HAVE_COMMERCIAL @@ -2460,9 +2610,13 @@ void MWindow::cut_commercials() #endif } -int MWindow::normalize_speed(EDL *old_edl, EDL *new_edl) +int MWindow::normalize_speed(EDL *old_edl, EDL *new_edl, int edit_speed) { - int result = 0; + int edit_plugins = edl->session->plugins_follow_edits; + int edit_autos = edl->session->autos_follow_edits; + int edit_labels = edl->session->labels_follow_edits; + if( !edit_autos ) edit_speed = 0; + int result = 0, first_track = 1; Track *old_track = old_edl->tracks->first; Track *new_track = new_edl->tracks->first; for( ; old_track && new_track; old_track=old_track->next, new_track=new_track->next ) { @@ -2476,20 +2630,107 @@ int MWindow::normalize_speed(EDL *old_edl, EDL *new_edl) old_speed = (FloatAuto *)old_speed->next; new_speed = (FloatAuto *)new_speed->next; } - Edit *old_edit = old_track->edits->first; - Edit *new_edit = new_track->edits->first; - for( ; old_edit && new_edit; old_edit=old_edit->next, new_edit=new_edit->next ) { - int64_t edit_start = old_edit->startproject, edit_end = edit_start + old_edit->length; - if( old_speed || new_speed ) { - double orig_start = old_speeds->automation_integral(0, edit_start, PLAY_FORWARD); - double orig_end = old_speeds->automation_integral(0, edit_end, PLAY_FORWARD); - edit_start = new_speeds->speed_position(orig_start); - edit_end = new_speeds->speed_position(orig_end); - result = 1; + if( !old_speed && !new_speed ) continue; + result = 1; + if( edit_speed ) { + Autos *old_autos = old_track->automation->autos[AUTOMATION_SPEED]; + Autos *new_autos = new_track->automation->autos[AUTOMATION_SPEED]; + Auto *old_auto = old_autos ? old_autos->first : 0; + for( ; old_auto; old_auto=old_auto->next ) { + Auto *new_auto = new_autos->get_auto(old_auto->orig_id); + if( !new_auto ) continue; + int64_t auto_pos = old_auto->position; + double orig_pos = old_speeds->automation_integral(0, auto_pos, PLAY_FORWARD); + auto_pos = new_track->frame_align(new_speeds->speed_position(orig_pos), 1); + new_auto->position = auto_pos; } + } + Edit *old_edit = old_track->edits->first; + for( ; old_edit; old_edit=old_edit->next ) { + Edit *new_edit = new_track->edits->get_edit(old_edit->orig_id); + if( !new_edit ) continue; + int64_t edit_start = old_edit->startproject; + int64_t edit_end = edit_start + old_edit->length; + double orig_start = old_speeds->automation_integral(0, edit_start, PLAY_FORWARD); + double orig_end = old_speeds->automation_integral(0, edit_end, PLAY_FORWARD); + edit_start = new_track->frame_align(new_speeds->speed_position(orig_start), 1); + edit_end = new_track->frame_align(new_speeds->speed_position(orig_end), 1); new_edit->startproject = edit_start; new_edit->length = edit_end - edit_start; } + if( first_track && old_track->is_armed() ) { + Labels *old_labels = old_edl->labels; + Labels *new_labels = new_edl->labels; + if( edit_labels && old_labels && new_labels ) { + Label *old_label = old_labels->first; + for( ; old_label; old_label=old_label->next ) { + Label *new_label = new_labels->get_label(old_label->orig_id); + if( !new_label ) continue; + int64_t label_pos = old_track->to_units(old_label->position, 1); + double orig_pos = old_speeds->automation_integral(0, label_pos, PLAY_FORWARD); + label_pos = new_track->frame_align(new_speeds->speed_position(orig_pos), 1); + new_label->position = new_track->from_units(label_pos); + } + } + first_track = 0; + } + if( edit_plugins ) { + int old_size = old_track->plugin_set.size(); + int new_size = new_track->plugin_set.size(); + int n = bmin(old_size, new_size); + for( int i=0; iplugin_set[i]; + if( !old_plugin_set ) continue; + PluginSet *new_plugin_set = new_track->plugin_set[i]; + if( !new_plugin_set ) continue; + Plugin *old_plugin = (Plugin *)old_plugin_set->first; + for( ; old_plugin; old_plugin=(Plugin *)old_plugin->next ) { + Plugin *new_plugin = (Plugin *)new_plugin_set->get_edit(old_plugin->orig_id); + if( !new_plugin ) continue; + int64_t plugin_start = old_plugin->startproject; + int64_t plugin_end = plugin_start + old_plugin->length; + double orig_start = old_speeds->automation_integral(0, plugin_start, PLAY_FORWARD); + double orig_end = old_speeds->automation_integral(0, plugin_end, PLAY_FORWARD); + plugin_start = new_track->frame_align(new_speeds->speed_position(orig_start), 1); + plugin_end = new_track->frame_align(new_speeds->speed_position(orig_end), 1); + new_plugin->startproject = plugin_start; + new_plugin->length = plugin_end - plugin_start; + if( edit_autos ) { + KeyFrames *old_keyframes = old_plugin->keyframes; + if( !old_keyframes ) continue; + KeyFrames *new_keyframes = new_plugin->keyframes; + if( !new_keyframes ) continue; + Auto *old_auto = old_keyframes->first; + for( ; old_auto; old_auto=old_auto->next ) { + Auto *new_auto = new_keyframes->get_auto(old_auto->orig_id); + if( !new_auto ) continue; + int64_t auto_pos = old_auto->position; + double orig_pos = old_speeds->automation_integral(0, auto_pos, PLAY_FORWARD); + auto_pos = new_track->frame_align(new_speeds->speed_position(orig_pos), 1); + new_auto->position = auto_pos; + old_auto = old_auto->next; + } + } + } + } + } + if( edit_autos ) { // speed must be last + for( int i=0; iautomation->autos[i]; + if( !old_autos ) continue; + Autos *new_autos = new_track->automation->autos[i]; + if( !new_autos ) continue; + Auto *old_auto = old_autos->first; + for( ; old_auto; old_auto=old_auto->next ) { + Auto *new_auto = new_autos->get_auto(old_auto->orig_id); + if( !new_auto ) continue; + int64_t auto_pos = old_auto->position; + double orig_pos = old_speeds->automation_integral(0, auto_pos, PLAY_FORWARD); + auto_pos = new_track->frame_align(new_speeds->speed_position(orig_pos), 1); + new_auto->position = auto_pos; + } + } + } } return result; } @@ -2503,12 +2744,12 @@ void MWindow::speed_before() speed_edl->copy_all(edl); } -int MWindow::speed_after(int done) +int MWindow::speed_after(int done, int edit_speed) { int result = 0; if( speed_edl ) { if( done >= 0 ) - result = normalize_speed(speed_edl, edl); + result = normalize_speed(speed_edl, edl, edit_speed); if( done != 0 ) { speed_edl->remove_user(); speed_edl = 0; @@ -2517,3 +2758,210 @@ int MWindow::speed_after(int done) return result; } +void MWindow::collect_effects() +{ + FileXML file; + const char *file_string = ""; + EDL *group = 0; + int ret = edl->collect_effects(group); + switch( ret ) { + case COLLECT_EFFECTS_RECORD: + eprintf(_("Selected edit track not armed.")); + break; + case COLLECT_EFFECTS_MULTIPLE: + eprintf(_("More than one edit selected on a track.")); + break; + case COLLECT_EFFECTS_MISSING: + eprintf(_("No effects under selected edit.")); + break; + case COLLECT_EFFECTS_EMPTY: + eprintf(_("No edits selected.")); + break; + case COLLECT_EFFECTS_MASTER: + eprintf(_("Shared effect added without master.")); + break; + case 0: + group->save_xml(&file, ""); + file_string = file.string(); + group->remove_user(); + } + long file_length = strlen(file_string); + gui->to_clipboard(file_string, file_length, BC_PRIMARY_SELECTION); + gui->to_clipboard(file_string, file_length, SECONDARY_SELECTION); +} + +void MWindow::paste_effects() +{ + char *string = 0; + int64_t len = gui->clipboard_len(BC_PRIMARY_SELECTION); + if( len ) { + string = new char[len]; + gui->from_clipboard(string, len, BC_PRIMARY_SELECTION); + } + if( !string || !string[0] ) { + eprintf(_("Error clipboard buffer empty.")); + return; + } + FileXML file; + file.read_from_string(string); + EDL *group = new EDL(); + group->create_objects(); + if( !group->load_xml(&file, LOAD_ALL) ) { + undo_before(); + int ret = edl->insert_effects(group); + switch( ret ) { + case INSERT_EFFECTS_RECORD: + eprintf(_("Selected edit track not armed.")); + break; + case INSERT_EFFECTS_TYPE: + eprintf(_("Track type mismatched.")); + break; + case INSERT_EFFECTS_MULTIPLE: + eprintf(_("More than one edit selected on a track.")); + break; + case INSERT_EFFECTS_MISSING: + eprintf(_("Too few target edits to add group effects.")); + break; + case INSERT_EFFECTS_EXTRA: + eprintf(_("Too many target edits to add group effects.")); + break; + case INSERT_EFFECTS_MASTER: + eprintf(_("Shared effect added without master.")); + break; + case 0: + break; + } + save_backup(); + undo_after(_("paste effects"), LOAD_ALL); + restart_brender(); + cwindow->refresh_frame(CHANGE_EDL); + update_plugin_guis(); + gui->update(1, NORMAL_DRAW, 1, 0, 0, 0, 0); + } + else + eprintf(_("Error loading clip from clipboard buffer.")); + delete [] string; + group->remove_user(); +} + +void MWindow::align_timecodes() +{ + undo_before(); + double offset = edl->tracks->align_timecodes(); + set_timecode_offset(offset); + save_backup(); + undo_after(_("align timecodes"), LOAD_ALL); + restart_brender(); + cwindow->refresh_frame(CHANGE_EDL); + update_plugin_guis(); +} + + +int MWindow::masters_to_mixers() +{ + Track *master_track = edl->tracks->first; + while( master_track && !master_track->master ) + master_track = master_track->next; + while( master_track ) { // test for track/mixer conflicts + int failed = 0; + Track *mixer_last = master_track; + Track *track = master_track->next; + for( ; track && !track->master; track=track->next ) + mixer_last = track; + Track *next_track = track; + if( !master_track->armed ) { + master_track = next_track; + continue; + } + Mixer *master_mixer = 0; + for( int i=0, n=edl->mixers.size(); iindex_in(edl->mixers[i]) >= 0 ) { + master_mixer = edl->mixers[i]; + break; + } + } + if( master_mixer ) { // existing mixer track group + for( track=master_track; !failed && track; track=track->next ) { + if( track->index_in(master_mixer) < 0 ) { + eprintf("Mixer: %s missing track: %s", + master_mixer->title, track->title); + failed = 1; + } + if( track == mixer_last ) break; + } + for( int i=0, n=master_mixer->mixer_ids.size(); !failed && imixer_ids[i], found = 0; + for( track=master_track; track; track=track->next ) { + if( track->mixer_id == mixer_id ) { + found = 1; + break; + } + if( track == mixer_last ) break; + } + if( !found ) { + eprintf("Mixer: %s track missing: %s", + master_mixer->title, track->title); + failed = 1; + } + } + } + else { // create mixer + for( track=master_track->next; !failed && track; track=track->next ) { + for( int i=0, n=edl->mixers.size(); !failed && imixers[i]; + if( track->index_in(mixer) >= 0 ) { + eprintf("Track: %s already exists in mixer: %s", + track->title, mixer->title); + failed = 1; + break; + } + } + if( track == mixer_last ) break; + } + if( !failed ) { // new mixer + ZWindow *zwindow = get_mixer(master_mixer); + zwindow->set_title(master_track->title); + sprintf(master_track->title, _("Mixer %d"), zwindow->idx); + for( track=master_track; track; track=track->next ) { + track->play = track->armed = 0; + master_mixer->mixer_ids.append(track->get_mixer_id()); + if( track == mixer_last ) break; + } + zwindow->start(); + } + } + master_track = next_track; + } + return 0; +} + +void MWindow::mix_masters() +{ + undo_before(); + masters_to_mixers(); + undo_after(_("mix masters"), LOAD_ALL); + + restart_brender(); + gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); + gui->activate_timeline(); + cwindow->refresh_frame(CHANGE_EDL); + save_backup(); +} + +void MWindow::create_keyframes(int mask, int mode) +{ + undo_before(); + double start = edl->local_session->get_selectionstart(); + edl->tracks->create_keyframes(start, mask, mode); + double end = edl->local_session->get_selectionend(); + if( end != start ) + edl->tracks->create_keyframes(end, mask, mode); + undo_after(_("create kyfrms"), LOAD_AUTOMATION); + + restart_brender(); + gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); + gui->activate_timeline(); + cwindow->refresh_frame(CHANGE_EDL); + save_backup(); +} +