diff options
author | Richard Antalik <richardantalik@gmail.com> | 2021-03-02 14:08:16 +0300 |
---|---|---|
committer | Richard Antalik <richardantalik@gmail.com> | 2021-03-02 14:23:04 +0300 |
commit | bbb1936411a5f98f5a49ed0d63bcf1a547cbdb59 (patch) | |
tree | 87a9b39a54828a4f4447f1d41903fa70111cb981 | |
parent | b279fef85d1a561ceb71e2cdce458bd44b4d853a (diff) |
VSE: Refactor VSE strip loading code
Isolate RNA and operator logic from functions that create strips.
- Operator specific code was removed from `SeqLoadInfo` structure and
`SEQ_add_*` functions.
- Strip loading code was removed from RNA and operator functions.
- `SEQ_add_*` API was unified to work on `SeqLoadData` struct.
Only exception is image strip, which require files to be loaded
separately to strip creation itself. This is not ideal, but I think
it's acceptable.
- Some functions and variables were refactored so the code reads
better.
There are minor functional changes (coincidental bugfixes):
- Operator errors are reported per-strip. Previously they were not
reported at all?
- `new_sound()` RNA API function now create sound with length of 1
if source file does not exist. Previously it created strip with
length of 0.
- Replace selection operator property wasn't working correctly.
Fixed in this patch.
Reviewed By: sergey
Differential Revision: https://developer.blender.org/D9760
-rw-r--r-- | source/blender/editors/space_sequencer/sequencer_add.c | 581 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_sequencer_api.c | 196 | ||||
-rw-r--r-- | source/blender/sequencer/SEQ_add.h | 95 | ||||
-rw-r--r-- | source/blender/sequencer/intern/render.c | 28 | ||||
-rw-r--r-- | source/blender/sequencer/intern/strip_add.c | 501 |
5 files changed, 765 insertions, 636 deletions
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index a9033b98708..baa2e9cc964 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -36,6 +36,7 @@ #include "DNA_mask_types.h" #include "DNA_scene_types.h" +#include "DNA_sound_types.h" #include "BKE_context.h" #include "BKE_lib_id.h" @@ -44,6 +45,8 @@ #include "BKE_movieclip.h" #include "BKE_report.h" +#include "IMB_imbuf.h" + #include "WM_api.h" #include "WM_types.h" @@ -89,8 +92,6 @@ typedef struct SequencerAddData { #define SEQPROP_NOCHAN (1 << 3) #define SEQPROP_FIT_METHOD (1 << 4) -#define SELECT 1 - static const EnumPropertyItem scale_fit_methods[] = { {SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image to fit within the canvas"}, {SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image to completely fill the canvas"}, @@ -216,7 +217,7 @@ static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, i } } -static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperator *op) +static void load_data_init_from_operator(SeqLoadData *load_data, bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -224,69 +225,56 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato const bool relative = (prop = RNA_struct_find_property(op->ptr, "relative_path")) && RNA_property_boolean_get(op->ptr, prop); int is_file = -1; - memset(seq_load, 0, sizeof(SeqLoadInfo)); + memset(load_data, 0, sizeof(SeqLoadData)); - seq_load->start_frame = RNA_int_get(op->ptr, "frame_start"); - seq_load->end_frame = seq_load->start_frame; - seq_load->channel = RNA_int_get(op->ptr, "channel"); - seq_load->len = 1; - seq_load->fit_method = RNA_enum_get(op->ptr, "fit_method"); - SEQ_tool_settings_fit_method_set(CTX_data_scene(C), seq_load->fit_method); + load_data->start_frame = RNA_int_get(op->ptr, "frame_start"); + load_data->channel = RNA_int_get(op->ptr, "channel"); + load_data->image.end_frame = load_data->start_frame; + load_data->image.len = 1; + load_data->fit_method = RNA_enum_get(op->ptr, "fit_method"); + SEQ_tool_settings_fit_method_set(CTX_data_scene(C), load_data->fit_method); if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) { /* Full path, file is set by the caller. */ - RNA_property_string_get(op->ptr, prop, seq_load->path); + RNA_property_string_get(op->ptr, prop, load_data->path); is_file = 1; } else if ((prop = RNA_struct_find_property(op->ptr, "directory"))) { /* Full path, file is set by the caller. */ - RNA_property_string_get(op->ptr, prop, seq_load->path); + RNA_property_string_get(op->ptr, prop, load_data->path); is_file = 0; } if ((is_file != -1) && relative) { - BLI_path_rel(seq_load->path, BKE_main_blendfile_path(bmain)); + BLI_path_rel(load_data->path, BKE_main_blendfile_path(bmain)); } if ((prop = RNA_struct_find_property(op->ptr, "frame_end"))) { - seq_load->end_frame = RNA_property_int_get(op->ptr, prop); - } - - if ((prop = RNA_struct_find_property(op->ptr, "replace_sel")) && - RNA_property_boolean_get(op->ptr, prop)) { - seq_load->flag |= SEQ_LOAD_REPLACE_SEL; + load_data->image.end_frame = RNA_property_int_get(op->ptr, prop); } if ((prop = RNA_struct_find_property(op->ptr, "cache")) && RNA_property_boolean_get(op->ptr, prop)) { - seq_load->flag |= SEQ_LOAD_SOUND_CACHE; + load_data->flags |= SEQ_LOAD_SOUND_CACHE; } if ((prop = RNA_struct_find_property(op->ptr, "mono")) && RNA_property_boolean_get(op->ptr, prop)) { - seq_load->flag |= SEQ_LOAD_SOUND_MONO; - } - - if ((prop = RNA_struct_find_property(op->ptr, "sound")) && - RNA_property_boolean_get(op->ptr, prop)) { - seq_load->flag |= SEQ_LOAD_MOVIE_SOUND; + load_data->flags |= SEQ_LOAD_SOUND_MONO; } if ((prop = RNA_struct_find_property(op->ptr, "use_framerate")) && RNA_property_boolean_get(op->ptr, prop)) { - seq_load->flag |= SEQ_LOAD_SYNC_FPS; + load_data->flags |= SEQ_LOAD_MOVIE_SYNC_FPS; } - /* Create consecutive array of strips. */ - seq_load->flag |= SEQ_LOAD_FRAME_ADVANCE; - if (is_file == 1) { - BLI_strncpy(seq_load->name, BLI_path_basename(seq_load->path), sizeof(seq_load->name)); + BLI_strncpy(load_data->name, BLI_path_basename(load_data->path), sizeof(load_data->name)); } else if ((prop = RNA_struct_find_property(op->ptr, "files"))) { RNA_PROP_BEGIN (op->ptr, itemptr, prop) { char *name = RNA_string_get_alloc(&itemptr, "name", NULL, 0); - BLI_strncpy(seq_load->name, name, sizeof(seq_load->name)); + BLI_strncpy(load_data->name, name, sizeof(load_data->name)); MEM_freeN(name); break; } @@ -299,36 +287,31 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato SequencerAddData *sad = op->customdata; ImageFormatData *imf = &sad->im_format; - seq_load->views_format = imf->views_format; - seq_load->flag |= SEQ_USE_VIEWS; - seq_load->stereo3d_format = &imf->stereo3d_format; + load_data->use_multiview = true; + load_data->views_format = imf->views_format; + load_data->stereo3d_format = &imf->stereo3d_format; } } } -/** - * Apply generic operator options. - */ -static void sequencer_add_apply_overlap(bContext *C, wmOperator *op, Sequence *seq) +static void seq_load_apply_generic_options(bContext *C, wmOperator *op, Sequence *seq) { Scene *scene = CTX_data_scene(C); Editing *ed = SEQ_editing_get(scene, false); - if (RNA_boolean_get(op->ptr, "overlap") == false) { - if (SEQ_transform_test_overlap(ed->seqbasep, seq)) { - SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene); - } + if (seq == NULL) { + return; } -} - -static void sequencer_add_apply_replace_sel(bContext *C, wmOperator *op, Sequence *seq) -{ - Scene *scene = CTX_data_scene(C); if (RNA_boolean_get(op->ptr, "replace_sel")) { - ED_sequencer_deselect_all(scene); - SEQ_select_active_set(scene, seq); seq->flag |= SELECT; + SEQ_select_active_set(scene, seq); + } + + if (RNA_boolean_get(op->ptr, "overlap") == false) { + if (SEQ_transform_test_overlap(ed->seqbasep, seq)) { + SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene); + } } } @@ -356,34 +339,24 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Editing *ed = SEQ_editing_get(scene, true); - Scene *sce_seq; - Sequence *seq; - - int start_frame, channel; - start_frame = RNA_int_get(op->ptr, "frame_start"); - channel = RNA_int_get(op->ptr, "channel"); - sce_seq = BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene")); + const Editing *ed = SEQ_editing_get(scene, true); + Scene *sce_seq = BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene")); if (sce_seq == NULL) { BKE_report(op->reports, RPT_ERROR, "Scene not found"); return OPERATOR_CANCELLED; } - seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_SCENE); - seq->blend_mode = SEQ_TYPE_CROSS; - seq->scene = sce_seq; - seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1; - - BLI_strncpy(seq->name + 2, sce_seq->id.name + 2, sizeof(seq->name) - 2); - SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq); + if (RNA_boolean_get(op->ptr, "replace_sel")) { + ED_sequencer_deselect_all(scene); + } - SEQ_time_update_sequence_bounds(scene, seq); - SEQ_sort(scene); + SeqLoadData load_data; + load_data_init_from_operator(&load_data, C, op); + load_data.scene = sce_seq; - sequencer_add_apply_replace_sel(C, op, seq); - sequencer_add_apply_overlap(C, op, seq); - SEQ_relations_invalidate_cache_composite(scene, seq); + Sequence *seq = SEQ_add_scene_strip(scene, ed->seqbasep, &load_data); + seq_load_apply_generic_options(C, op, seq); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); DEG_relations_tag_update(bmain); @@ -430,36 +403,24 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Editing *ed = SEQ_editing_get(scene, true); - MovieClip *clip; - Sequence *seq; - - int start_frame, channel; - start_frame = RNA_int_get(op->ptr, "frame_start"); - channel = RNA_int_get(op->ptr, "channel"); - clip = BLI_findlink(&bmain->movieclips, RNA_enum_get(op->ptr, "clip")); + const Editing *ed = SEQ_editing_get(scene, true); + MovieClip *clip = BLI_findlink(&bmain->movieclips, RNA_enum_get(op->ptr, "clip")); if (clip == NULL) { BKE_report(op->reports, RPT_ERROR, "Movie clip not found"); return OPERATOR_CANCELLED; } - seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MOVIECLIP); - seq->blend_mode = SEQ_TYPE_CROSS; - seq->clip = clip; - seq->len = BKE_movieclip_get_duration(clip); - - id_us_ensure_real(&seq->clip->id); - - BLI_strncpy(seq->name + 2, clip->id.name + 2, sizeof(seq->name) - 2); - SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq); + if (RNA_boolean_get(op->ptr, "replace_sel")) { + ED_sequencer_deselect_all(scene); + } - SEQ_time_update_sequence_bounds(scene, seq); - SEQ_sort(scene); + SeqLoadData load_data; + load_data_init_from_operator(&load_data, C, op); + load_data.clip = clip; - sequencer_add_apply_replace_sel(C, op, seq); - sequencer_add_apply_overlap(C, op, seq); - SEQ_relations_invalidate_cache_composite(scene, seq); + Sequence *seq = SEQ_add_movieclip_strip(scene, ed->seqbasep, &load_data); + seq_load_apply_generic_options(C, op, seq); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -506,36 +467,24 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Editing *ed = SEQ_editing_get(scene, true); - Mask *mask; - Sequence *seq; - - int start_frame, channel; - start_frame = RNA_int_get(op->ptr, "frame_start"); - channel = RNA_int_get(op->ptr, "channel"); - mask = BLI_findlink(&bmain->masks, RNA_enum_get(op->ptr, "mask")); + const Editing *ed = SEQ_editing_get(scene, true); + Mask *mask = BLI_findlink(&bmain->masks, RNA_enum_get(op->ptr, "mask")); if (mask == NULL) { BKE_report(op->reports, RPT_ERROR, "Mask not found"); return OPERATOR_CANCELLED; } - seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MASK); - seq->blend_mode = SEQ_TYPE_CROSS; - seq->mask = mask; - seq->len = BKE_mask_get_duration(mask); - - id_us_ensure_real(&seq->mask->id); - - BLI_strncpy(seq->name + 2, mask->id.name + 2, sizeof(seq->name) - 2); - SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq); + if (RNA_boolean_get(op->ptr, "replace_sel")) { + ED_sequencer_deselect_all(scene); + } - SEQ_time_update_sequence_bounds(scene, seq); - SEQ_sort(scene); + SeqLoadData load_data; + load_data_init_from_operator(&load_data, C, op); + load_data.mask = mask; - sequencer_add_apply_replace_sel(C, op, seq); - sequencer_add_apply_overlap(C, op, seq); - SEQ_relations_invalidate_cache_composite(scene, seq); + Sequence *seq = SEQ_add_mask_strip(scene, ed->seqbasep, &load_data); + seq_load_apply_generic_options(C, op, seq); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -577,100 +526,120 @@ void SEQUENCER_OT_mask_strip_add(struct wmOperatorType *ot) ot->prop = prop; } -static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoadFn seq_load_fn) +static void sequencer_add_init(bContext *UNUSED(C), wmOperator *op) { - Scene *scene = CTX_data_scene(C); - Editing *ed = SEQ_editing_get(scene, true); - SeqLoadInfo seq_load; - int tot_files; - - seq_load_operator_info(&seq_load, C, op); + op->customdata = MEM_callocN(sizeof(SequencerAddData), __func__); +} - if (seq_load.flag & SEQ_LOAD_REPLACE_SEL) { - ED_sequencer_deselect_all(scene); +static void sequencer_add_cancel(bContext *UNUSED(C), wmOperator *op) +{ + if (op->customdata) { + MEM_freeN(op->customdata); } + op->customdata = NULL; +} - tot_files = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); - - if (tot_files > 1) { - char dir_only[FILE_MAX]; - char file_only[FILE_MAX]; - - RNA_BEGIN (op->ptr, itemptr, "files") { - Sequence *seq; +static bool sequencer_add_draw_check_fn(PointerRNA *UNUSED(ptr), + PropertyRNA *prop, + void *UNUSED(user_data)) +{ + const char *prop_id = RNA_property_identifier(prop); - RNA_string_get(op->ptr, "directory", dir_only); - RNA_string_get(&itemptr, "name", file_only); - BLI_join_dirfile(seq_load.path, sizeof(seq_load.path), dir_only, file_only); + return !(STR_ELEM(prop_id, "filepath", "directory", "filename")); +} - /* Set seq_load.name, otherwise all video/audio files get the same name. */ - BLI_strncpy(seq_load.name, file_only, sizeof(seq_load.name)); +static void sequencer_add_movie_multiple_strips(bContext *C, + wmOperator *op, + SeqLoadData *load_data) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + const Editing *ed = SEQ_editing_get(scene, true); - seq = seq_load_fn(C, ed->seqbasep, &seq_load); - if (seq) { - if (seq_load.seq_sound) { - sequencer_add_apply_overlap(C, op, seq_load.seq_sound); - } - sequencer_add_apply_overlap(C, op, seq); - } + RNA_BEGIN (op->ptr, itemptr, "files") { + char dir_only[FILE_MAX]; + char file_only[FILE_MAX]; + RNA_string_get(op->ptr, "directory", dir_only); + RNA_string_get(&itemptr, "name", file_only); + BLI_join_dirfile(load_data->path, sizeof(load_data->path), dir_only, file_only); + BLI_strncpy(load_data->name, file_only, sizeof(load_data->name)); + Sequence *seq_movie = NULL; + Sequence *seq_sound = NULL; + load_data->channel++; + seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data); + load_data->channel--; + if (seq_movie == NULL) { + BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path); } - RNA_END; - } - else { /* Single file./ */ - Sequence *seq; - seq = seq_load_fn(C, ed->seqbasep, &seq_load); - - if (seq) { - if (seq_load.seq_sound) { - sequencer_add_apply_overlap(C, op, seq_load.seq_sound); + else { + if (RNA_boolean_get(op->ptr, "sound")) { + seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data); } - sequencer_add_apply_overlap(C, op, seq); + load_data->start_frame += seq_movie->enddisp - seq_movie->startdisp; + seq_load_apply_generic_options(C, op, seq_sound); + seq_load_apply_generic_options(C, op, seq_movie); } } + RNA_END; +} - if (op->customdata) { - MEM_freeN(op->customdata); - } +static bool sequencer_add_movie_single_strip(bContext *C, wmOperator *op, SeqLoadData *load_data) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + const Editing *ed = SEQ_editing_get(scene, true); - if (seq_load.tot_success == 0) { - BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", seq_load.path); + Sequence *seq_movie = NULL; + Sequence *seq_sound = NULL; + load_data->channel++; + seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data); + load_data->channel--; - return OPERATOR_CANCELLED; + if (seq_movie == NULL) { + BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path); + return false; } + if (RNA_boolean_get(op->ptr, "sound")) { + seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data); + } + seq_load_apply_generic_options(C, op, seq_sound); + seq_load_apply_generic_options(C, op, seq_movie); - SEQ_sort(scene); - - DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); - WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); - - return OPERATOR_FINISHED; + return true; } -static void sequencer_add_init(bContext *UNUSED(C), wmOperator *op) +static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op) { - op->customdata = MEM_callocN(sizeof(SequencerAddData), __func__); -} + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + SeqLoadData load_data; + + load_data_init_from_operator(&load_data, C, op); + + if (RNA_boolean_get(op->ptr, "replace_sel")) { + ED_sequencer_deselect_all(scene); + } + + const int tot_files = RNA_property_collection_length(op->ptr, + RNA_struct_find_property(op->ptr, "files")); + if (tot_files > 1) { + sequencer_add_movie_multiple_strips(C, op, &load_data); + } + else { + if (!sequencer_add_movie_single_strip(C, op, &load_data)) { + return OPERATOR_CANCELLED; + } + } -static void sequencer_add_cancel(bContext *UNUSED(C), wmOperator *op) -{ if (op->customdata) { MEM_freeN(op->customdata); } - op->customdata = NULL; -} -static bool sequencer_add_draw_check_fn(PointerRNA *UNUSED(ptr), - PropertyRNA *prop, - void *UNUSED(user_data)) -{ - const char *prop_id = RNA_property_identifier(prop); - - return !(STR_ELEM(prop_id, "filepath", "directory", "filename")); -} + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); -static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op) -{ - return sequencer_add_generic_strip_exec(C, op, SEQ_add_movie_strip); + return OPERATOR_FINISHED; } static int sequencer_add_movie_strip_invoke(bContext *C, @@ -681,7 +650,8 @@ static int sequencer_add_movie_strip_invoke(bContext *C, Scene *scene = CTX_data_scene(C); Editing *ed = SEQ_editing_get(scene, false); - /* Only enable "use_framerate" if there aren't any existing strips, unless overridden by user. */ + /* Only enable "use_framerate" if there aren't any existing strips, unless overridden by user. + */ if (ed && ed->seqbasep && ed->seqbasep->first) { RNA_boolean_set(op->ptr, "use_framerate", false); } @@ -761,9 +731,80 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot) "Use framerate from the movie to keep sound and video in sync"); } +static void sequencer_add_sound_multiple_strips(bContext *C, + wmOperator *op, + SeqLoadData *load_data) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + Editing *ed = SEQ_editing_get(scene, true); + + RNA_BEGIN (op->ptr, itemptr, "files") { + char dir_only[FILE_MAX]; + char file_only[FILE_MAX]; + RNA_string_get(op->ptr, "directory", dir_only); + RNA_string_get(&itemptr, "name", file_only); + BLI_join_dirfile(load_data->path, sizeof(load_data->path), dir_only, file_only); + BLI_strncpy(load_data->name, file_only, sizeof(load_data->name)); + Sequence *seq = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data); + if (seq == NULL) { + BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path); + } + else { + seq_load_apply_generic_options(C, op, seq); + load_data->start_frame += seq->enddisp - seq->startdisp; + } + } + RNA_END; +} + +static bool sequencer_add_sound_single_strip(bContext *C, wmOperator *op, SeqLoadData *load_data) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + Editing *ed = SEQ_editing_get(scene, true); + + Sequence *seq = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data); + if (seq == NULL) { + BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path); + return false; + } + seq_load_apply_generic_options(C, op, seq); + + return true; +} + static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op) { - return sequencer_add_generic_strip_exec(C, op, SEQ_add_sound_strip); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + SeqLoadData load_data; + load_data_init_from_operator(&load_data, C, op); + + if (RNA_boolean_get(op->ptr, "replace_sel")) { + ED_sequencer_deselect_all(scene); + } + + const int tot_files = RNA_property_collection_length(op->ptr, + RNA_struct_find_property(op->ptr, "files")); + if (tot_files > 1) { + sequencer_add_sound_multiple_strips(C, op, &load_data); + } + else { + if (!sequencer_add_sound_single_strip(C, op, &load_data)) { + return OPERATOR_CANCELLED; + } + } + + if (op->customdata) { + MEM_freeN(op->customdata); + } + + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); + + return OPERATOR_FINISHED; } static int sequencer_add_sound_strip_invoke(bContext *C, @@ -873,78 +914,86 @@ void sequencer_image_seq_reserve_frames( } } -static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) +static int sequencer_add_image_strip_calculate_length(wmOperator *op, + const int start_frame, + int *minframe, + int *numdigits) { - int minframe, numdigits; - Scene *scene = CTX_data_scene(C); - Editing *ed = SEQ_editing_get(scene, true); - SeqLoadInfo seq_load; - Sequence *seq; - Strip *strip; - StripElem *se; const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders"); - seq_load_operator_info(&seq_load, C, op); - - /* Images are unique in how they handle this - 1 per strip elem. */ if (use_placeholders) { - seq_load.len = sequencer_image_seq_get_minmax_frame( - op, seq_load.start_frame, &minframe, &numdigits); + return sequencer_image_seq_get_minmax_frame(op, start_frame, minframe, numdigits); } else { - seq_load.len = RNA_property_collection_length(op->ptr, - RNA_struct_find_property(op->ptr, "files")); - } - - if (seq_load.len == 0) { - return OPERATOR_CANCELLED; + return RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); } +} - if (seq_load.flag & SEQ_LOAD_REPLACE_SEL) { - ED_sequencer_deselect_all(scene); - } +static void sequencer_add_image_strip_load_files(bContext *C, + wmOperator *op, + Sequence *seq, + SeqLoadData *load_data, + const int minframe, + const int numdigits) +{ + const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders"); - /* Main adding function. */ - seq = SEQ_add_image_strip(C, ed->seqbasep, &seq_load); - strip = seq->strip; - se = strip->stripdata; - seq->blend_mode = SEQ_TYPE_ALPHAOVER; + SEQ_add_image_set_directory(seq, load_data->path); if (use_placeholders) { - sequencer_image_seq_reserve_frames(op, se, seq_load.len, minframe, numdigits); + sequencer_image_seq_reserve_frames( + op, seq->strip->stripdata, load_data->image.len, minframe, numdigits); } else { + size_t strip_frame = 0; RNA_BEGIN (op->ptr, itemptr, "files") { char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); - BLI_strncpy(se->name, filename, sizeof(se->name)); + SEQ_add_image_load_file(seq, strip_frame, filename); MEM_freeN(filename); - se++; + strip_frame++; } RNA_END; } +} - if (seq_load.len == 1) { - if (seq_load.start_frame < seq_load.end_frame) { - seq->endstill = seq_load.end_frame - seq_load.start_frame; - } +static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Editing *ed = SEQ_editing_get(scene, true); + + SeqLoadData load_data; + load_data_init_from_operator(&load_data, C, op); + + int minframe, numdigits; + load_data.image.len = sequencer_add_image_strip_calculate_length( + op, load_data.start_frame, &minframe, &numdigits); + if (load_data.image.len == 0) { + return OPERATOR_CANCELLED; } - SEQ_render_init_colorspace(seq); - SEQ_time_update_sequence_bounds(scene, seq); - SEQ_sort(scene); + if (RNA_boolean_get(op->ptr, "replace_sel")) { + ED_sequencer_deselect_all(scene); + } - /* Last active name. */ - BLI_strncpy(ed->act_imagedir, strip->dir, sizeof(ed->act_imagedir)); - sequencer_add_apply_overlap(C, op, seq); + Sequence *seq = SEQ_add_image_strip(CTX_data_main(C), scene, ed->seqbasep, &load_data); + sequencer_add_image_strip_load_files(C, op, seq, &load_data, minframe, numdigits); + SEQ_add_image_init_alpha_mode(seq); - if (op->customdata) { - MEM_freeN(op->customdata); + /* Adjust length. */ + if (load_data.image.len == 1) { + SEQ_transform_set_right_handle_frame(seq, load_data.image.end_frame); + SEQ_time_update_sequence(scene, seq); } - SEQ_relations_invalidate_cache_composite(scene, seq); + seq_load_apply_generic_options(C, op, seq); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); + if (op->customdata) { + MEM_freeN(op->customdata); + } + return OPERATOR_FINISHED; } @@ -1016,80 +1065,46 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Editing *ed = SEQ_editing_get(scene, true); - Sequence *seq; - struct SeqEffectHandle sh; - Sequence *seq1, *seq2, *seq3; const char *error_msg; - int start_frame, end_frame, channel, type; - start_frame = RNA_int_get(op->ptr, "frame_start"); - end_frame = RNA_int_get(op->ptr, "frame_end"); - channel = RNA_int_get(op->ptr, "channel"); - type = RNA_enum_get(op->ptr, "type"); + SeqLoadData load_data; + load_data_init_from_operator(&load_data, C, op); + load_data.effect.type = RNA_enum_get(op->ptr, "type"); - if (!seq_effect_find_selected(scene, NULL, type, &seq1, &seq2, &seq3, &error_msg)) { + Sequence *seq1, *seq2, *seq3; + if (!seq_effect_find_selected( + scene, NULL, load_data.effect.type, &seq1, &seq2, &seq3, &error_msg)) { BKE_report(op->reports, RPT_ERROR, error_msg); return OPERATOR_CANCELLED; } - /* Check its start and end frames are valid. */ - if (seq1 == NULL && end_frame <= start_frame) { - end_frame = start_frame + 1; - RNA_int_set(op->ptr, "frame_end", end_frame); - } - - seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, type); - BLI_strncpy(seq->name + 2, SEQ_sequence_give_name(seq), sizeof(seq->name) - 2); - SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq); - - sh = SEQ_effect_handle_get(seq); - sh.init(seq); - seq->seq1 = seq1; - seq->seq2 = seq2; - seq->seq3 = seq3; - - if (!seq1) { - seq->len = 1; /* Effect is generator, set non zero length. */ - SEQ_transform_set_right_handle_frame(seq, end_frame); + if (RNA_boolean_get(op->ptr, "replace_sel")) { + ED_sequencer_deselect_all(scene); } - seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE; - SEQ_time_update_sequence(scene, seq); - - if (seq->type == SEQ_TYPE_COLOR) { - SolidColorVars *colvars = (SolidColorVars *)seq->effectdata; - RNA_float_get_array(op->ptr, "color", colvars->col); - seq->blend_mode = SEQ_TYPE_CROSS; - } - else if (seq->type == SEQ_TYPE_ADJUSTMENT) { - seq->blend_mode = SEQ_TYPE_CROSS; - } - else if (seq->type == SEQ_TYPE_TEXT) { - seq->blend_mode = SEQ_TYPE_ALPHAOVER; - } - else if (SEQ_effect_get_num_inputs(seq->type) == 1) { - seq->blend_mode = seq1->blend_mode; - } + load_data.effect.seq1 = seq1; + load_data.effect.seq2 = seq2; + load_data.effect.seq3 = seq3; /* Set channel. If unset, use lowest free one above strips. */ if (!RNA_struct_property_is_set(op->ptr, "channel")) { - if (seq->seq1) { - int chan = max_iii(seq->seq1 ? seq->seq1->machine : 0, - seq->seq2 ? seq->seq2->machine : 0, - seq->seq3 ? seq->seq3->machine : 0); + if (seq1 != NULL) { + int chan = max_iii( + seq1 ? seq1->machine : 0, seq2 ? seq2->machine : 0, seq3 ? seq3->machine : 0); if (chan < MAXSEQ) { - seq->machine = chan; + load_data.channel = chan; } } } - sequencer_add_apply_replace_sel(C, op, seq); - sequencer_add_apply_overlap(C, op, seq); + Sequence *seq = SEQ_add_effect_strip(scene, ed->seqbasep, &load_data); + seq_load_apply_generic_options(C, op, seq); - SEQ_relations_update_changed_seq_and_deps(scene, seq, 1, 1); /* Runs SEQ_time_update_sequence. */ - SEQ_sort(scene); + if (seq->type == SEQ_TYPE_COLOR) { + SolidColorVars *colvars = (SolidColorVars *)seq->effectdata; + RNA_float_get_array(op->ptr, "color", colvars->col); + } - SEQ_relations_invalidate_cache_composite(scene, seq); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 070fb08c3b4..77484488822 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -53,6 +53,7 @@ # include "SEQ_add.h" # include "SEQ_edit.h" +# include "SEQ_effects.h" # include "SEQ_relations.h" # include "SEQ_render.h" # include "SEQ_sequencer.h" @@ -80,34 +81,6 @@ static void rna_Sequence_swap_internal(Sequence *seq_self, } } -static Sequence *alloc_generic_sequence( - ListBase *seqbase, const char *name, int frame_start, int channel, int type, const char *file) -{ - Sequence *seq; - StripElem *se; - - seq = SEQ_sequence_alloc(seqbase, frame_start, channel, type); - - BLI_strncpy(seq->name + 2, name, sizeof(seq->name) - 2); - SEQ_sequence_base_unique_name_recursive(seqbase, seq); - - Strip *strip = seq->strip; - - /* Don't allocate StripElem for clip, mask and scene types. This struct is not handled in - * seq_dupli() function. */ - if (file && !ELEM(type, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK, SEQ_TYPE_SCENE)) { - strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem"); - BLI_split_dirfile(file, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); - - SEQ_render_init_colorspace(seq); - } - else { - strip->stripdata = NULL; - } - - return seq; -} - static Sequence *rna_Sequences_new_clip(ID *id, ListBase *seqbase, Main *bmain, @@ -117,15 +90,10 @@ static Sequence *rna_Sequences_new_clip(ID *id, int frame_start) { Scene *scene = (Scene *)id; - Sequence *seq; - - seq = alloc_generic_sequence( - seqbase, name, frame_start, channel, SEQ_TYPE_MOVIECLIP, clip->filepath); - seq->clip = clip; - seq->len = BKE_movieclip_get_duration(clip); - id_us_plus((ID *)clip); - - SEQ_time_update_sequence_bounds(scene, seq); + SeqLoadData load_data; + SEQ_add_load_data_init(&load_data, name, NULL, frame_start, channel); + load_data.clip = clip; + Sequence *seq = SEQ_add_movieclip_strip(scene, seqbase, &load_data); DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); @@ -165,15 +133,10 @@ static Sequence *rna_Sequences_new_mask(ID *id, int frame_start) { Scene *scene = (Scene *)id; - Sequence *seq; - - seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_MASK, mask->id.name); - seq->mask = mask; - seq->len = BKE_mask_get_duration(mask); - id_us_plus((ID *)mask); - - SEQ_time_update_sequence_bounds(scene, seq); - SEQ_relations_invalidate_cache_composite(scene, seq); + SeqLoadData load_data; + SEQ_add_load_data_init(&load_data, name, NULL, frame_start, channel); + load_data.mask = mask; + Sequence *seq = SEQ_add_mask_strip(scene, seqbase, &load_data); DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); @@ -202,15 +165,10 @@ static Sequence *rna_Sequences_new_scene(ID *id, int frame_start) { Scene *scene = (Scene *)id; - Sequence *seq; - - seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_SCENE, NULL); - seq->scene = sce_seq; - seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1; - id_us_plus((ID *)sce_seq); - - SEQ_time_update_sequence_bounds(scene, seq); - SEQ_relations_invalidate_cache_composite(scene, seq); + SeqLoadData load_data; + SEQ_add_load_data_init(&load_data, name, NULL, frame_start, channel); + load_data.scene = sce_seq; + Sequence *seq = SEQ_add_scene_strip(scene, seqbase, &load_data); DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); @@ -251,20 +209,17 @@ static Sequence *rna_Sequences_new_image(ID *id, int frame_start) { Scene *scene = (Scene *)id; - Sequence *seq; - seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_IMAGE, file); - seq->len = 1; + SeqLoadData load_data; + SEQ_add_load_data_init(&load_data, name, file, frame_start, channel); + load_data.image.len = 1; + Sequence *seq = SEQ_add_image_strip(bmain, scene, seqbase, &load_data); - if (seq->strip->stripdata->name[0] == '\0') { - BKE_report(reports, RPT_ERROR, "Sequences.new_image: unable to open image file"); - BLI_remlink(seqbase, seq); - SEQ_sequence_free(scene, seq, true); - return NULL; - } - - SEQ_time_update_sequence_bounds(scene, seq); - SEQ_relations_invalidate_cache_composite(scene, seq); + char dir[FILE_MAX], filename[FILE_MAX]; + BLI_split_dirfile(file, dir, filename, sizeof(dir), sizeof(filename)); + SEQ_add_image_set_directory(seq, dir); + SEQ_add_image_load_file(seq, 0, filename); + SEQ_add_image_init_alpha_mode(seq); DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); @@ -299,48 +254,47 @@ static Sequence *rna_Sequences_meta_new_image(ID *id, id, &seq->seqbase, bmain, reports, name, file, channel, frame_start); } -static Sequence *rna_Sequences_new_movie( - ID *id, ListBase *seqbase, const char *name, const char *file, int channel, int frame_start) +static Sequence *rna_Sequences_new_movie(ID *id, + ListBase *seqbase, + Main *bmain, + const char *name, + const char *file, + int channel, + int frame_start) { Scene *scene = (Scene *)id; - Sequence *seq; - StripAnim *sanim; - - seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_MOVIE, file); - - struct anim *an = openanim(file, IB_rect, 0, NULL); - if (an == NULL) { - /* Without anim, the strip gets duration 0, which makes it impossible to select in the UI. */ - seq->len = 1; - } - else { - sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); - BLI_addtail(&seq->anims, sanim); - sanim->anim = an; - - seq->anim_preseek = IMB_anim_get_preseek(an); - seq->len = IMB_anim_get_duration(an, IMB_TC_RECORD_RUN); - } - - SEQ_time_update_sequence_bounds(scene, seq); - SEQ_relations_invalidate_cache_composite(scene, seq); + SeqLoadData load_data; + SEQ_add_load_data_init(&load_data, name, file, frame_start, channel); + load_data.allow_invalid_file = true; + Sequence *seq = SEQ_add_movie_strip(bmain, scene, seqbase, &load_data); + DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); return seq; } -static Sequence *rna_Sequences_editing_new_movie( - ID *id, Editing *ed, const char *name, const char *file, int channel, int frame_start) +static Sequence *rna_Sequences_editing_new_movie(ID *id, + Editing *ed, + Main *bmain, + const char *name, + const char *file, + int channel, + int frame_start) { - return rna_Sequences_new_movie(id, &ed->seqbase, name, file, channel, frame_start); + return rna_Sequences_new_movie(id, &ed->seqbase, bmain, name, file, channel, frame_start); } -static Sequence *rna_Sequences_meta_new_movie( - ID *id, Sequence *seq, const char *name, const char *file, int channel, int frame_start) +static Sequence *rna_Sequences_meta_new_movie(ID *id, + Sequence *seq, + Main *bmain, + const char *name, + const char *file, + int channel, + int frame_start) { - return rna_Sequences_new_movie(id, &seq->seqbase, name, file, channel, frame_start); + return rna_Sequences_new_movie(id, &seq->seqbase, bmain, name, file, channel, frame_start); } # ifdef WITH_AUDASPACE @@ -354,22 +308,15 @@ static Sequence *rna_Sequences_new_sound(ID *id, int frame_start) { Scene *scene = (Scene *)id; - Sequence *seq; + SeqLoadData load_data; + SEQ_add_load_data_init(&load_data, name, file, frame_start, channel); + load_data.allow_invalid_file = true; + Sequence *seq = SEQ_add_sound_strip(bmain, scene, seqbase, &load_data); - bSound *sound = BKE_sound_new_file(bmain, file); - - SoundInfo info; - if (!BKE_sound_info_get(bmain, sound, &info)) { - BKE_id_free(bmain, sound); + if (seq == NULL) { BKE_report(reports, RPT_ERROR, "Sequences.new_sound: unable to open sound file"); return NULL; } - seq = alloc_generic_sequence( - seqbase, name, frame_start, channel, SEQ_TYPE_SOUND_RAM, sound->filepath); - seq->sound = sound; - seq->len = ceil((double)info.length * FPS); - - SEQ_time_update_sequence_bounds(scene, seq); DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); @@ -432,8 +379,7 @@ static Sequence *rna_Sequences_new_effect(ID *id, { Scene *scene = (Scene *)id; Sequence *seq; - struct SeqEffectHandle sh; - int num_inputs = SEQ_effect_get_num_inputs(type); + const int num_inputs = SEQ_effect_get_num_inputs(type); switch (num_inputs) { case 0: @@ -469,26 +415,14 @@ static Sequence *rna_Sequences_new_effect(ID *id, return NULL; } - seq = alloc_generic_sequence(seqbase, name, frame_start, channel, type, NULL); - - sh = SEQ_effect_handle_get(seq); - - seq->seq1 = seq1; - seq->seq2 = seq2; - seq->seq3 = seq3; - - sh.init(seq); - - if (!seq1) { /* effect has no deps */ - seq->len = 1; - SEQ_transform_set_right_handle_frame(seq, frame_end); - } - - seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE; - - SEQ_time_update_sequence(scene, seq); - SEQ_time_update_sequence_bounds(scene, seq); - SEQ_relations_invalidate_cache_composite(scene, seq); + SeqLoadData load_data; + SEQ_add_load_data_init(&load_data, name, NULL, frame_start, channel); + load_data.effect.end_frame = frame_end; + load_data.effect.type = type; + load_data.effect.seq1 = seq1; + load_data.effect.seq2 = seq2; + load_data.effect.seq3 = seq3; + seq = SEQ_add_effect_strip(scene, seqbase, &load_data); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); @@ -865,7 +799,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop, const bool metastri RNA_def_function_return(func, parm); func = RNA_def_function(srna, "new_movie", new_movie_func_name); - RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); RNA_def_function_ui_description(func, "Add a new movie sequence"); parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); diff --git a/source/blender/sequencer/SEQ_add.h b/source/blender/sequencer/SEQ_add.h index b136cb35e09..e262d7ed1ef 100644 --- a/source/blender/sequencer/SEQ_add.h +++ b/source/blender/sequencer/SEQ_add.h @@ -32,48 +32,73 @@ struct Scene; struct Sequence; struct bContext; -/* api for adding new sequence strips */ -typedef struct SeqLoadInfo { +/* SeqLoadData.flags */ +typedef enum eSeqLoadFlags { + SEQ_LOAD_SOUND_CACHE = (1 << 1), + SEQ_LOAD_SOUND_MONO = (1 << 2), + SEQ_LOAD_MOVIE_SYNC_FPS = (1 << 3), +} eSeqLoadFlags; + +/* Api for adding new sequence strips. */ +typedef struct SeqLoadData { int start_frame; - int end_frame; int channel; - int flag; /* use sound, replace sel */ - int type; - int len; /* only for image strips */ + char name[64]; /* Strip name. */ char path[1024]; /* 1024 = FILE_MAX */ + struct { + int len; + int end_frame; + } image; /* Only for image strips. */ + struct Scene *scene; /* Only for scene strips. */ + struct MovieClip *clip; /* Only for clip strips. */ + struct Mask *mask; /* Only for mask strips. */ + struct { + int type; + int end_frame; + struct Sequence *seq1; + struct Sequence *seq2; + struct Sequence *seq3; + } effect; /* Only for effect strips. */ + eSeqLoadFlags flags; eSeqImageFitMethod fit_method; - - /* multiview */ + bool use_multiview; char views_format; struct Stereo3dFormat *stereo3d_format; + bool allow_invalid_file; /* Used by RNA API to create placeholder strips. */ +} SeqLoadData; - /* return values */ - char name[64]; - struct Sequence *seq_sound; /* for movie's */ - int tot_success; - int tot_error; -} SeqLoadInfo; - -/* SeqLoadInfo.flag */ -#define SEQ_LOAD_REPLACE_SEL (1 << 0) -#define SEQ_LOAD_FRAME_ADVANCE (1 << 1) -#define SEQ_LOAD_MOVIE_SOUND (1 << 2) -#define SEQ_LOAD_SOUND_CACHE (1 << 3) -#define SEQ_LOAD_SYNC_FPS (1 << 4) -#define SEQ_LOAD_SOUND_MONO (1 << 5) - -/* use as an api function */ -typedef struct Sequence *(*SeqLoadFn)(struct bContext *, ListBase *, struct SeqLoadInfo *); - -struct Sequence *SEQ_add_image_strip(struct bContext *C, - ListBase *seqbasep, - struct SeqLoadInfo *seq_load); -struct Sequence *SEQ_add_sound_strip(struct bContext *C, - ListBase *seqbasep, - struct SeqLoadInfo *seq_load); -struct Sequence *SEQ_add_movie_strip(struct bContext *C, - ListBase *seqbasep, - struct SeqLoadInfo *seq_load); +void SEQ_add_load_data_init(struct SeqLoadData *load_data, + const char *name, + const char *path, + const int start_frame, + const int channel); +struct Sequence *SEQ_add_image_strip(struct Main *bmain, + struct Scene *scene, + struct ListBase *seqbase, + struct SeqLoadData *load_data); +struct Sequence *SEQ_add_sound_strip(struct Main *bmain, + struct Scene *scene, + struct ListBase *seqbase, + struct SeqLoadData *load_data); +struct Sequence *SEQ_add_movie_strip(struct Main *bmain, + struct Scene *scene, + struct ListBase *seqbase, + struct SeqLoadData *load_data); +struct Sequence *SEQ_add_scene_strip(struct Scene *scene, + struct ListBase *seqbase, + struct SeqLoadData *load_data); +struct Sequence *SEQ_add_movieclip_strip(struct Scene *scene, + struct ListBase *seqbase, + struct SeqLoadData *load_data); +struct Sequence *SEQ_add_mask_strip(struct Scene *scene, + struct ListBase *seqbase, + struct SeqLoadData *load_data); +struct Sequence *SEQ_add_effect_strip(struct Scene *scene, + struct ListBase *seqbase, + struct SeqLoadData *load_data); +void SEQ_add_image_set_directory(struct Sequence *seq, char *path); +void SEQ_add_image_load_file(struct Sequence *seq, size_t strip_frame, char *filename); +void SEQ_add_image_init_alpha_mode(struct Sequence *seq); void SEQ_add_reload_new_file(struct Main *bmain, struct Scene *scene, struct Sequence *seq, diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c index e9de73bc093..f1a0a7db13b 100644 --- a/source/blender/sequencer/intern/render.c +++ b/source/blender/sequencer/intern/render.c @@ -203,34 +203,6 @@ void SEQ_render_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4 } } -void SEQ_render_init_colorspace(Sequence *seq) -{ - if (seq->strip && seq->strip->stripdata) { - char name[FILE_MAX]; - ImBuf *ibuf; - - BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name); - BLI_path_abs(name, BKE_main_blendfile_path_from_global()); - - /* initialize input color space */ - if (seq->type == SEQ_TYPE_IMAGE) { - ibuf = IMB_loadiffname( - name, IB_test | IB_alphamode_detect, seq->strip->colorspace_settings.name); - - /* byte images are default to straight alpha, however sequencer - * works in premul space, so mark strip to be premultiplied first - */ - seq->alpha_mode = SEQ_ALPHA_STRAIGHT; - if (ibuf) { - if (ibuf->flags & IB_alphamode_premul) { - seq->alpha_mode = IMA_ALPHA_PREMUL; - } - - IMB_freeImBuf(ibuf); - } - } - } -} /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c index ba080a07879..1aa0e32a363 100644 --- a/source/blender/sequencer/intern/strip_add.c +++ b/source/blender/sequencer/intern/strip_add.c @@ -29,6 +29,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_mask_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" #include "DNA_sound_types.h" @@ -54,7 +55,9 @@ #include "IMB_metadata.h" #include "SEQ_add.h" +#include "SEQ_effects.h" #include "SEQ_relations.h" +#include "SEQ_render.h" #include "SEQ_select.h" #include "SEQ_sequencer.h" #include "SEQ_time.h" @@ -65,168 +68,369 @@ #include "proxy.h" #include "utils.h" -static void seq_load_apply(Main *bmain, Scene *scene, Sequence *seq, SeqLoadInfo *seq_load) +/** + * Initialize common SeqLoadData members + * + * \param load_data: SeqLoadData to be initialized + * \param name: strip name (can be NULL) + * \param path: path to file that is used as strip input (can be NULL) + * \param start_frame: timeline frame where strip will be created + * \param channel: timeline channel where strip will be created + * + */ +void SEQ_add_load_data_init(SeqLoadData *load_data, + const char *name, + const char *path, + const int start_frame, + const int channel) { - if (seq) { - BLI_strncpy_utf8(seq->name + 2, seq_load->name, sizeof(seq->name) - 2); - BLI_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2)); - SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); + memset(load_data, 0, sizeof(SeqLoadData)); + if (name != NULL) { + BLI_strncpy(load_data->name, name, sizeof(load_data->name)); + } + if (path != NULL) { + BLI_strncpy(load_data->path, path, sizeof(load_data->path)); + } + load_data->start_frame = start_frame; + load_data->channel = channel; +} - if (seq_load->flag & SEQ_LOAD_FRAME_ADVANCE) { - seq_load->start_frame += (seq->enddisp - seq->startdisp); - } +static void seq_add_generic_update(Scene *scene, ListBase *seqbase, Sequence *seq) +{ + SEQ_sequence_base_unique_name_recursive(seqbase, seq); + SEQ_time_update_sequence_bounds(scene, seq); + SEQ_sort(scene); + SEQ_relations_invalidate_cache_composite(scene, seq); +} - if (seq_load->flag & SEQ_LOAD_REPLACE_SEL) { - seq_load->flag |= SELECT; - SEQ_select_active_set(scene, seq); +static void seq_add_set_name(Sequence *seq, SeqLoadData *load_data) +{ + if (load_data->name != NULL) { + BLI_strncpy(seq->name + 2, load_data->name, sizeof(seq->name) - 2); + } + else { + if (seq->type == SEQ_TYPE_SCENE) { + BLI_strncpy(seq->name + 2, load_data->scene->id.name + 2, sizeof(seq->name) - 2); } - - if (seq_load->flag & SEQ_LOAD_SOUND_MONO) { - seq->sound->flags |= SOUND_FLAGS_MONO; - BKE_sound_load(bmain, seq->sound); + else if (seq->type == SEQ_TYPE_MOVIECLIP) { + BLI_strncpy(seq->name + 2, load_data->clip->id.name + 2, sizeof(seq->name) - 2); } - - if (seq_load->flag & SEQ_LOAD_SOUND_CACHE) { - if (seq->sound) { - seq->sound->flags |= SOUND_FLAGS_CACHING; - } + else if (seq->type == SEQ_TYPE_MASK) { + BLI_strncpy(seq->name + 2, load_data->mask->id.name + 2, sizeof(seq->name) - 2); + } + else if ((seq->type & SEQ_TYPE_EFFECT) != 0) { + BLI_strncpy(seq->name + 2, SEQ_sequence_give_name(seq), sizeof(seq->name) - 2); + } + else { /* Image, sound and movie. */ + BLI_strncpy_utf8(seq->name + 2, load_data->name, sizeof(seq->name) - 2); + BLI_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2)); } - - seq_load->tot_success++; - } - else { - seq_load->tot_error++; } } -/* NOTE: this function doesn't fill in image names */ -Sequence *SEQ_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) +/** + * Add scene strip. + * + * \param scene: Scene where strips will be added + * \param seqbase: ListBase where strips will be added + * \param load_data: SeqLoadData with information necessary to create strip + * \return created strip + */ +Sequence *SEQ_add_scene_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data) { - Scene *scene = CTX_data_scene(C); /* only for active seq */ - Sequence *seq; - Strip *strip; + Sequence *seq = SEQ_sequence_alloc( + seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_SCENE); + seq->blend_mode = SEQ_TYPE_CROSS; + seq->scene = load_data->scene; + seq->len = load_data->scene->r.efra - load_data->scene->r.sfra + 1; + id_us_ensure_real((ID *)load_data->scene); + seq_add_set_name(seq, load_data); + seq_add_generic_update(scene, seqbase, seq); + return seq; +} - seq = SEQ_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_IMAGE); - seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ +/** + * Add movieclip strip. + * + * \param scene: Scene where strips will be added + * \param seqbase: ListBase where strips will be added + * \param load_data: SeqLoadData with information necessary to create strip + * \return created strip + */ +Sequence *SEQ_add_movieclip_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data) +{ + Sequence *seq = SEQ_sequence_alloc( + seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MOVIECLIP); + seq->blend_mode = SEQ_TYPE_CROSS; + seq->clip = load_data->clip; + seq->len = BKE_movieclip_get_duration(load_data->clip); + id_us_ensure_real((ID *)load_data->clip); + seq_add_set_name(seq, load_data); + seq_add_generic_update(scene, seqbase, seq); + return seq; +} - /* basic defaults */ - seq->len = seq_load->len ? seq_load->len : 1; +/** + * Add mask strip. + * + * \param scene: Scene where strips will be added + * \param seqbase: ListBase where strips will be added + * \param load_data: SeqLoadData with information necessary to create strip + * \return created strip + */ +Sequence *SEQ_add_mask_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data) +{ + Sequence *seq = SEQ_sequence_alloc( + seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MASK); + seq->blend_mode = SEQ_TYPE_CROSS; + seq->mask = load_data->mask; + seq->len = BKE_mask_get_duration(load_data->mask); + id_us_ensure_real((ID *)load_data->mask); + seq_add_set_name(seq, load_data); + seq_add_generic_update(scene, seqbase, seq); + return seq; +} - strip = seq->strip; - strip->stripdata = MEM_callocN(seq->len * sizeof(StripElem), "stripelem"); - BLI_strncpy(strip->dir, seq_load->path, sizeof(strip->dir)); +/** + * Add effect strip. + * + * \param scene: Scene where strips will be added + * \param seqbase: ListBase where strips will be added + * \param load_data: SeqLoadData with information necessary to create strip + * \return created strip + */ +Sequence *SEQ_add_effect_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data) +{ + Sequence *seq = SEQ_sequence_alloc( + seqbase, load_data->start_frame, load_data->channel, load_data->effect.type); + + seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE; + struct SeqEffectHandle sh = SEQ_effect_handle_get(seq); + sh.init(seq); + seq->seq1 = load_data->effect.seq1; + seq->seq2 = load_data->effect.seq2; + seq->seq3 = load_data->effect.seq3; + + if (seq->type == SEQ_TYPE_COLOR) { + seq->blend_mode = SEQ_TYPE_CROSS; + } + else if (seq->type == SEQ_TYPE_ADJUSTMENT) { + seq->blend_mode = SEQ_TYPE_CROSS; + } + else if (seq->type == SEQ_TYPE_TEXT) { + seq->blend_mode = SEQ_TYPE_ALPHAOVER; + } + else if (SEQ_effect_get_num_inputs(seq->type) == 1) { + seq->blend_mode = seq->seq1->blend_mode; + } - if (seq_load->stereo3d_format) { - *seq->stereo3d_format = *seq_load->stereo3d_format; + if (!load_data->effect.seq1) { + seq->len = 1; /* Effect is generator, set non zero length. */ + SEQ_transform_set_right_handle_frame(seq, load_data->image.end_frame); } + SEQ_relations_update_changed_seq_and_deps(scene, seq, 1, 1); /* Runs SEQ_time_update_sequence. */ + seq_add_set_name(seq, load_data); + seq_add_generic_update(scene, seqbase, seq); + + return seq; +} + +/** + * Set directory used by image strip. + * + * \param seq: image strip to be changed + * \param path: directory path + */ +void SEQ_add_image_set_directory(Sequence *seq, char *path) +{ + BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir)); +} - seq->views_format = seq_load->views_format; - seq->flag |= seq_load->flag & SEQ_USE_VIEWS; +/** + * Set directory used by image strip. + * + * \param seq: image strip to be changed + * \param strip_frame: frame index of strip to be changed + * \param filename: image filename (only filename, not complete path) + */ +void SEQ_add_image_load_file(Sequence *seq, size_t strip_frame, char *filename) +{ + StripElem *se = SEQ_render_give_stripelem(seq, seq->start + strip_frame); + BLI_strncpy(se->name, filename, sizeof(se->name)); +} - seq_load_apply(CTX_data_main(C), scene, seq, seq_load); +/** + * Set image strip alpha mode + * + * \param seq: image strip to be changed + */ +void SEQ_add_image_init_alpha_mode(Sequence *seq) +{ + if (seq->strip && seq->strip->stripdata) { + char name[FILE_MAX]; + ImBuf *ibuf; + + BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name); + BLI_path_abs(name, BKE_main_blendfile_path_from_global()); + + /* Initialize input color space. */ + if (seq->type == SEQ_TYPE_IMAGE) { + ibuf = IMB_loadiffname( + name, IB_test | IB_alphamode_detect, seq->strip->colorspace_settings.name); + + /* Byte images are default to straight alpha, however sequencer + * works in premul space, so mark strip to be premultiplied first. + */ + seq->alpha_mode = SEQ_ALPHA_STRAIGHT; + if (ibuf) { + if (ibuf->flags & IB_alphamode_premul) { + seq->alpha_mode = IMA_ALPHA_PREMUL; + } + IMB_freeImBuf(ibuf); + } + } + } +} + +/** + * Add image strip. + * NOTE: Use SEQ_add_image_set_directory() and SEQ_add_image_load_file() to load image sequences + * + * \param main: Main reference + * \param scene: Scene where strips will be added + * \param seqbase: ListBase where strips will be added + * \param load_data: SeqLoadData with information necessary to create strip + * \return created strip + */ +Sequence *SEQ_add_image_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data) +{ + Sequence *seq = SEQ_sequence_alloc( + seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_IMAGE); + seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ + seq->len = load_data->image.len; + Strip *strip = seq->strip; + strip->stripdata = MEM_callocN(load_data->image.len * sizeof(StripElem), "stripelem"); + + /* Multiview settings. */ + if (load_data->use_multiview) { + seq->flag |= SEQ_USE_VIEWS; + seq->views_format = load_data->views_format; + } + if (load_data->stereo3d_format) { + seq->stereo3d_format = load_data->stereo3d_format; + } + + /* Set initial scale based on load_data->fit_method. */ char file_path[FILE_MAX]; - BLI_join_dirfile(file_path, sizeof(file_path), seq_load->path, seq_load->name); - BLI_path_abs(file_path, BKE_main_blendfile_path(CTX_data_main(C))); + BLI_join_dirfile(file_path, sizeof(file_path), load_data->path, load_data->name); + BLI_path_abs(file_path, BKE_main_blendfile_path(bmain)); ImBuf *ibuf = IMB_loadiffname(file_path, IB_rect, seq->strip->colorspace_settings.name); if (ibuf != NULL) { SEQ_set_scale_to_fit( - seq, ibuf->x, ibuf->y, scene->r.xsch, scene->r.ysch, seq_load->fit_method); + seq, ibuf->x, ibuf->y, scene->r.xsch, scene->r.ysch, load_data->fit_method); IMB_freeImBuf(ibuf); } - SEQ_relations_invalidate_cache_composite(scene, seq); + /* Set Last active directory. */ + BLI_strncpy(scene->ed->act_imagedir, seq->strip->dir, sizeof(scene->ed->act_imagedir)); + seq_add_set_name(seq, load_data); + seq_add_generic_update(scene, seqbase, seq); return seq; } #ifdef WITH_AUDASPACE -Sequence *SEQ_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); /* only for sound */ - Editing *ed = SEQ_editing_get(scene, false); - bSound *sound; - - Sequence *seq; /* generic strip vars */ - Strip *strip; - StripElem *se; - - sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */ +/** + * Add sound strip. + * NOTE: Use SEQ_add_image_set_directory() and SEQ_add_image_load_file() to load image sequences + * + * \param main: Main reference + * \param scene: Scene where strips will be added + * \param seqbase: ListBase where strips will be added + * \param load_data: SeqLoadData with information necessary to create strip + * \return created strip + */ +Sequence *SEQ_add_sound_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data) +{ + bSound *sound = BKE_sound_new_file(bmain, load_data->path); /* Handles relative paths. */ SoundInfo info; - if (!BKE_sound_info_get(bmain, sound, &info)) { + bool sound_loaded = BKE_sound_info_get(bmain, sound, &info); + + if (!sound_loaded && !load_data->allow_invalid_file) { BKE_id_free(bmain, sound); return NULL; } - if (info.specs.channels == SOUND_CHANNELS_INVALID) { + if (info.specs.channels == SOUND_CHANNELS_INVALID && !load_data->allow_invalid_file) { BKE_id_free(bmain, sound); return NULL; } - seq = SEQ_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_SOUND_RAM); + Sequence *seq = SEQ_sequence_alloc( + seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_SOUND_RAM); seq->sound = sound; - BLI_strncpy(seq->name + 2, "Sound", SEQ_NAME_MAXSTR - 2); - SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); + seq->scene_sound = NULL; - /* basic defaults */ /* We add a very small negative offset here, because * ceil(132.0) == 133.0, not nice with videos, see T47135. */ - seq->len = (int)ceil((double)info.length * FPS - 1e-4); - strip = seq->strip; - - /* we only need 1 element to store the filename */ - strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem"); - - BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); - - seq->scene_sound = NULL; + seq->len = MAX2(1, (int)ceil((double)info.length * FPS - 1e-4)); - SEQ_time_update_sequence_bounds(scene, seq); + Strip *strip = seq->strip; + /* We only need 1 element to store the filename. */ + StripElem *se = strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem"); + BLI_split_dirfile(load_data->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); - /* last active name */ - BLI_strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR); + if (seq != NULL && seq->sound != NULL) { + if (load_data->flags & SEQ_LOAD_SOUND_MONO) { + seq->sound->flags |= SOUND_FLAGS_MONO; + } - seq_load_apply(bmain, scene, seq, seq_load); + if (load_data->flags & SEQ_LOAD_SOUND_CACHE) { + if (seq->sound) { + seq->sound->flags |= SOUND_FLAGS_CACHING; + } + } + } - /* TODO(sergey): Shall we tag here or in the operator? */ - DEG_relations_tag_update(bmain); + /* Set Last active directory. */ + BLI_strncpy(scene->ed->act_sounddir, strip->dir, FILE_MAXDIR); + seq_add_set_name(seq, load_data); + seq_add_generic_update(scene, seqbase, seq); return seq; } + #else // WITH_AUDASPACE -Sequence *SEQ_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) -{ - (void)C; - (void)seqbasep; - (void)seq_load; - return NULL; -} +Sequence *SEQ_add_sound_strip(Main *UNUSED(bmain), + Scene *UNUSED(scene), + ListBase *UNUSED(seqbase), + const SeqLoadData *UNUSED(load_data)) #endif // WITH_AUDASPACE -Sequence *SEQ_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) +/** + * Add movie strip. + * + * \param main: Main reference + * \param scene: Scene where strips will be added + * \param seqbase: ListBase where strips will be added + * \param load_data: SeqLoadData with information necessary to create strip + * \return created strip + */ +Sequence *SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); /* only for sound */ - char path[sizeof(seq_load->path)]; + char path[sizeof(load_data->path)]; + BLI_strncpy(path, load_data->path, sizeof(path)); + BLI_path_abs(path, BKE_main_blendfile_path(bmain)); - Sequence *seq; /* generic strip vars */ - Strip *strip; - StripElem *se; char colorspace[64] = "\0"; /* MAX_COLORSPACE_NAME */ bool is_multiview_loaded = false; - const bool is_multiview = (seq_load->flag & SEQ_USE_VIEWS) != 0; - const int totfiles = seq_num_files(scene, seq_load->views_format, is_multiview); - struct anim **anim_arr; + const int totfiles = seq_num_files(scene, load_data->views_format, load_data->use_multiview); + struct anim **anim_arr = MEM_callocN(sizeof(struct anim *) * totfiles, "Video files"); int i; - BLI_strncpy(path, seq_load->path, sizeof(path)); - BLI_path_abs(path, BKE_main_blendfile_path(bmain)); - - anim_arr = MEM_callocN(sizeof(struct anim *) * totfiles, "Video files"); - - if (is_multiview && (seq_load->views_format == R_IMF_VIEWS_INDIVIDUAL)) { + if (load_data->use_multiview && (load_data->views_format == R_IMF_VIEWS_INDIVIDUAL)) { char prefix[FILE_MAX]; const char *ext = NULL; size_t j = 0; @@ -245,38 +449,30 @@ Sequence *SEQ_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_ j++; } } - - if (j == 0) { - MEM_freeN(anim_arr); - return NULL; - } is_multiview_loaded = true; } } if (is_multiview_loaded == false) { anim_arr[0] = openanim(path, IB_rect, 0, colorspace); - - if (anim_arr[0] == NULL) { - MEM_freeN(anim_arr); - return NULL; - } } - if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) { - seq_load->channel++; + if (anim_arr[0] == NULL && !load_data->allow_invalid_file) { + MEM_freeN(anim_arr); + return NULL; } - seq = SEQ_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_MOVIE); - /* multiview settings */ - if (seq_load->stereo3d_format) { - *seq->stereo3d_format = *seq_load->stereo3d_format; - seq->views_format = seq_load->views_format; - } - seq->flag |= seq_load->flag & SEQ_USE_VIEWS; + Sequence *seq = SEQ_sequence_alloc( + seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MOVIE); - seq->type = SEQ_TYPE_MOVIE; - seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ + /* Multiview settings. */ + if (load_data->use_multiview) { + seq->flag |= SEQ_USE_VIEWS; + seq->views_format = load_data->views_format; + } + if (load_data->stereo3d_format) { + seq->stereo3d_format = load_data->stereo3d_format; + } for (i = 0; i < totfiles; i++) { if (anim_arr[i]) { @@ -289,51 +485,38 @@ Sequence *SEQ_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_ } } - IMB_anim_load_metadata(anim_arr[0]); + seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ - seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]); + if (anim_arr[0] != NULL) { + seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]); + seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN); - const float width = IMB_anim_get_image_width(anim_arr[0]); - const float height = IMB_anim_get_image_height(anim_arr[0]); - SEQ_set_scale_to_fit(seq, width, height, scene->r.xsch, scene->r.ysch, seq_load->fit_method); + IMB_anim_load_metadata(anim_arr[0]); - BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2); - SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); + /* Adjust scene's frame rate settings to match. */ + if (load_data->flags & SEQ_LOAD_MOVIE_SYNC_FPS) { + IMB_anim_get_fps(anim_arr[0], &scene->r.frs_sec, &scene->r.frs_sec_base, true); + } - /* adjust scene's frame rate settings to match */ - if (seq_load->flag & SEQ_LOAD_SYNC_FPS) { - IMB_anim_get_fps(anim_arr[0], &scene->r.frs_sec, &scene->r.frs_sec_base, true); + /* Set initial scale based on load_data->fit_method. */ + const float width = IMB_anim_get_image_width(anim_arr[0]); + const float height = IMB_anim_get_image_height(anim_arr[0]); + SEQ_set_scale_to_fit(seq, width, height, scene->r.xsch, scene->r.ysch, load_data->fit_method); } - /* basic defaults */ - seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN); - strip = seq->strip; - + seq->len = MAX2(1, seq->len); BLI_strncpy(seq->strip->colorspace_settings.name, colorspace, sizeof(seq->strip->colorspace_settings.name)); - /* we only need 1 element for MOVIE strips */ + Strip *strip = seq->strip; + /* We only need 1 element for MOVIE strips. */ + StripElem *se; strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem"); + BLI_split_dirfile(load_data->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); - BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); - - SEQ_time_update_sequence_bounds(scene, seq); - - if (seq_load->name[0] == '\0') { - BLI_strncpy(seq_load->name, se->name, sizeof(seq_load->name)); - } - - if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) { - int start_frame_back = seq_load->start_frame; - seq_load->channel--; - seq_load->seq_sound = SEQ_add_sound_strip(C, seqbasep, seq_load); - seq_load->start_frame = start_frame_back; - } - - /* can be NULL */ - seq_load_apply(CTX_data_main(C), scene, seq, seq_load); - SEQ_relations_invalidate_cache_composite(scene, seq); + seq_add_set_name(seq, load_data); + seq_add_generic_update(scene, seqbase, seq); MEM_freeN(anim_arr); return seq; @@ -525,9 +708,9 @@ void SEQ_add_movie_reload_if_needed(struct Main *bmain, bool must_reload = false; - /* The Sequence struct allows for multiple anim structs to be associated with one strip. This - * function will return true only if there is at least one 'anim' AND all anims can produce - * frames. */ + /* The Sequence struct allows for multiple anim structs to be associated with one strip. + * This function will return true only if there is at least one 'anim' AND all anims can + * produce frames. */ if (BLI_listbase_is_empty(&seq->anims)) { /* No anim present, so reloading is always necessary. */ |