X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fmwindowedit.C;h=7e6c644548f55b4d741836c455f272f39994df44;hp=bf5dc9177388679677bf9b01de192ff7497221d7;hb=1529091cdf16df199a901aabe6e8fa1813a933af;hpb=a0ed17a5d6ecf2b010d977bc1f9b7226f24c20f6 diff --git a/cinelerra-5.1/cinelerra/mwindowedit.C b/cinelerra-5.1/cinelerra/mwindowedit.C index bf5dc917..7e6c6445 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" @@ -91,13 +92,6 @@ void MWindow::add_audio_track_entry(int above, Track *dst) restart_brender(); gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); gui->activate_timeline(); - -// gui->get_scrollbars(0); -// gui->canvas->draw(); -// gui->patchbay->update(); -// gui->cursor->draw(1); -// gui->canvas->flash(); -// gui->canvas->activate(); cwindow->refresh_frame(CHANGE_EDL); } @@ -111,12 +105,6 @@ void MWindow::add_video_track_entry(Track *dst) gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); gui->activate_timeline(); -// gui->get_scrollbars(0); -// gui->canvas->draw(); -// gui->patchbay->update(); -// gui->cursor->draw(1); -// gui->canvas->flash(); -// gui->canvas->activate(); cwindow->refresh_frame(CHANGE_EDL); save_backup(); } @@ -131,12 +119,6 @@ void MWindow::add_subttl_track_entry(Track *dst) gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); gui->activate_timeline(); -// gui->get_scrollbars(0); -// gui->canvas->draw(); -// gui->patchbay->update(); -// gui->cursor->draw(1); -// gui->canvas->flash(); -// gui->canvas->activate(); cwindow->refresh_frame(CHANGE_EDL); save_backup(); } @@ -203,7 +185,7 @@ void MWindow::asset_to_all() } } - +#ifdef GLx4 if( ((edl->session->output_w % 4) || (edl->session->output_h % 4)) && edl->session->playback_config->vconfig->driver == PLAYBACK_X11_GL ) { @@ -211,7 +193,7 @@ void MWindow::asset_to_all() _("This project's dimensions are not multiples of 4 so\n" "it can't be rendered by OpenGL.")); } - +#endif // Get aspect ratio if( defaults->get("AUTOASPECT", 0) ) { create_aspect_ratio( @@ -250,7 +232,7 @@ void MWindow::asset_to_size() h = indexable->get_h(); edl->session->output_w = w; edl->session->output_h = h; - +#ifdef GLx4 if( ((edl->session->output_w % 4) || (edl->session->output_h % 4)) && edl->session->playback_config->vconfig->driver == PLAYBACK_X11_GL ) { @@ -258,7 +240,7 @@ void MWindow::asset_to_size() _("This project's dimensions are not multiples of 4 so\n" "it can't be rendered by OpenGL.")); } - +#endif // Get aspect ratio if( defaults->get("AUTOASPECT", 0) ) { create_aspect_ratio(edl->session->aspect_w, @@ -403,10 +385,43 @@ void MWindow::clear_labels() int MWindow::clear_labels(double start, double end) { + if( start == end ) { + start = 0; + end = edl->tracks->total_length(); + } edl->labels->clear(start, end, 0); return 0; } +void MWindow::clear_hard_edges() +{ + undo_before(); + clear_hard_edges(edl->local_session->get_selectionstart(), + edl->local_session->get_selectionend()); + edl->optimize(); + save_backup(); + undo_after(_("clear hard edges"), LOAD_EDITS); + restart_brender(); + gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0); + cwindow->refresh_frame(CHANGE_EDL); +} + +int MWindow::clear_hard_edges(double start, double end) +{ + if( start == end ) { + start = 0; + end = edl->tracks->total_length(); + } + edl->clear_hard_edges(start, end); + return 0; +} + +void MWindow::clear_select() +{ + edl->tracks->clear_selected_edits(); + gui->draw_overlays(1); +} + void MWindow::concatenate_tracks() { undo_before(); @@ -478,12 +493,10 @@ int MWindow::copy_default_keyframe() return 0; } - // Uses cropping coordinates in edl session to crop and translate video. // We modify the projector since camera automation depends on the track size. -void MWindow::crop_video() +void MWindow::crop_video(int mode) { - undo_before(); // Clamp EDL crop region if( edl->session->crop_x1 > edl->session->crop_x2 ) { @@ -496,22 +509,54 @@ void MWindow::crop_video() edl->session->crop_y2 ^= edl->session->crop_y1; edl->session->crop_y1 ^= edl->session->crop_y2; } - - float old_projector_x = (float)edl->session->output_w / 2; - float old_projector_y = (float)edl->session->output_h / 2; - float new_projector_x = (float)(edl->session->crop_x1 + edl->session->crop_x2) / 2; - float new_projector_y = (float)(edl->session->crop_y1 + edl->session->crop_y2) / 2; - float projector_offset_x = -(new_projector_x - old_projector_x); - float projector_offset_y = -(new_projector_y - old_projector_y); - - edl->tracks->translate_projector(projector_offset_x, projector_offset_y); - - edl->session->output_w = edl->session->crop_x2 - edl->session->crop_x1; - edl->session->output_h = edl->session->crop_y2 - edl->session->crop_y1; - edl->session->crop_x1 = 0; - edl->session->crop_y1 = 0; - edl->session->crop_x2 = edl->session->output_w; - edl->session->crop_y2 = edl->session->output_h; + switch( mode ) { + case CROP_REFORMAT: { + float ctr_x = edl->session->output_w / 2.; + float ctr_y = edl->session->output_h / 2.; + float new_x = (edl->session->crop_x1 + edl->session->crop_x2) / 2.; + float new_y = (edl->session->crop_y1 + edl->session->crop_y2) / 2.; + float dx = -(new_x - ctr_x), dy = -(new_y - ctr_y); + edl->tracks->translate_projector(dx, dy, 1); + + edl->session->output_w = edl->session->crop_x2 - edl->session->crop_x1; + edl->session->output_h = edl->session->crop_y2 - edl->session->crop_y1; + edl->session->crop_x1 = edl->session->crop_y1 = 0; + edl->session->crop_x2 = edl->session->output_w; + edl->session->crop_y2 = edl->session->output_h; + break; } + case CROP_RESIZE: { + float old_w = edl->session->output_w; + float old_h = edl->session->output_h; + float new_w = edl->session->crop_x2 - edl->session->crop_x1; + float new_h = edl->session->crop_y2 - edl->session->crop_y1; + if( !new_w ) new_w = 1; + if( !new_h ) new_h = 1; + float xzoom = old_w / new_w, yzoom = old_h / new_h; + float new_z = bmin(xzoom, yzoom); + float new_x = (edl->session->crop_x1 + edl->session->crop_x2) / 2.; + float new_y = (edl->session->crop_y1 + edl->session->crop_y2) / 2.; + edl->tracks->crop_resize(new_x, new_y, new_z); + + edl->session->crop_x1 = 0; + edl->session->crop_y1 = 0; + edl->session->crop_x2 = edl->session->output_w; + edl->session->crop_y2 = edl->session->output_h; + break; } + case CROP_SHRINK: { + float old_w = edl->session->output_w; + float old_h = edl->session->output_h; + float new_w = edl->session->crop_x2 - edl->session->crop_x1; + float new_h = edl->session->crop_y2 - edl->session->crop_y1; + if( !new_w ) new_w = 1; + if( !new_h ) new_h = 1; + float xzoom = old_w / new_w, yzoom = old_h / new_h; + float new_z = bmin(xzoom, yzoom); + + float new_x = (edl->session->crop_x1 + edl->session->crop_x2) / 2.; + float new_y = (edl->session->crop_y1 + edl->session->crop_y2) / 2.; + edl->tracks->crop_shrink(new_x, new_y, new_z); + break; } + } // Recalculate aspect ratio if( defaults->get("AUTOASPECT", 0) ) { @@ -646,12 +691,6 @@ int MWindow::cut_default_keyframe() } -void MWindow::delete_track() -{ - if( edl->tracks->last ) - delete_track(edl->tracks->last); -} - void MWindow::delete_tracks() { undo_before(); @@ -1211,10 +1250,16 @@ 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); @@ -1325,13 +1370,14 @@ void MWindow::load_assets(ArrayList *new_assets, load_mode = LOADMODE_ASSETSONLY; const int debug = 0; if( debug ) printf("MWindow::load_assets %d\n", __LINE__); - if( position < 0 ) position = edl->local_session->get_selectionstart(); + if( position < 0 ) + position = edl->local_session->get_selectionstart(); ArrayList new_edls; 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(); @@ -1491,6 +1537,9 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, default: continue; } +// re-label only if not already labeled + if( new_edl->local_session->asset2edl ) + strcpy(current->title, edl->tracks->last->title); destination_tracks.append(edl->tracks->last); } @@ -1502,8 +1551,7 @@ 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 ) { @@ -1540,16 +1588,21 @@ 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; case LOADMODE_NEW_TRACKS: + if( !overwrite ) + current_position = 0; break; case LOADMODE_CONCATENATE: @@ -1562,7 +1615,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); @@ -1623,7 +1675,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; @@ -1650,8 +1701,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; } @@ -1988,8 +2038,8 @@ void MWindow::redo_entry(BC_WindowBase *calling_window_gui) gui->update(1, FORCE_REDRAW, 1, 1, 1, 1, 1); gui->update_proxy_toggle(); gui->unlock_window(); - cwindow->update(1, 1, 1, 1, 1); cwindow->gui->unlock_window(); + cwindow->update(1, 1, 1, 1, 1); for( int i=0; i < vwindows.size(); ++i ) { if( vwindows.get(i)->is_running() ) { @@ -2125,28 +2175,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; @@ -2263,8 +2309,8 @@ void MWindow::undo_entry(BC_WindowBase *calling_window_gui) gui->update(1, FORCE_REDRAW, 1, 1, 1, 1, 1); gui->update_proxy_toggle(); gui->unlock_window(); - cwindow->update(1, 1, 1, 1, 1); cwindow->gui->unlock_window(); + cwindow->update(1, 1, 1, 1, 1); for( int i=0; iis_running() ) { @@ -2393,10 +2439,48 @@ void MWindow::rescale_proxy(EDL *clip, int orig_scale, int new_scale) edl->rescale_proxy(orig_scale, new_scale); } -void MWindow::add_proxy(int use_scaler, - ArrayList *orig_assets, ArrayList *proxy_assets) +void MWindow::add_proxy(ArrayList *orig_assets, ArrayList *proxy_assets) +{ + edl->add_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) { - edl->add_proxy(use_scaler, orig_assets, proxy_assets); + 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() @@ -2473,3 +2557,89 @@ 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(); +} +