Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorRichard Antalik <richardantalik@gmail.com>2021-03-02 14:08:16 +0300
committerRichard Antalik <richardantalik@gmail.com>2021-03-02 14:23:04 +0300
commitbbb1936411a5f98f5a49ed0d63bcf1a547cbdb59 (patch)
tree87a9b39a54828a4f4447f1d41903fa70111cb981 /source
parentb279fef85d1a561ceb71e2cdce458bd44b4d853a (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
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c581
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c196
-rw-r--r--source/blender/sequencer/SEQ_add.h95
-rw-r--r--source/blender/sequencer/intern/render.c28
-rw-r--r--source/blender/sequencer/intern/strip_add.c501
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. */