diff options
author | Campbell Barton <ideasman42@gmail.com> | 2013-07-24 10:51:04 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2013-07-24 10:51:04 +0400 |
commit | 576161b18673ef5cd5833330d4bfbf1266c3f624 (patch) | |
tree | 4448532c0b4b8aac30cac9d0de0d29e821df4dce /source/blender/blenkernel | |
parent | d0f225393cc4c65c1e2e9c2003f3a07eb18db28f (diff) |
fix [#36262] Paste strip with video or sound content from another file crashes Blender
existing code was very stupid.
- all ID pointers for clipboard strips are handled uniformly.
- clipboard stores a duplicate ID pointer which are restored on paste.
- restoring pointers...
-- use ID's that are still in the database (copy&paste within the same file).
-- fallback to name lookup.
-- fallback to loading them from the original filepath (movie-clip and sound only).
also fix bug pasting where initialing the sound wasn't done if there was no frame-offset.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_sequencer.h | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mask.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/movieclip.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/sequencer.c | 124 |
4 files changed, 101 insertions, 33 deletions
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 4494d127082..749b04d7328 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -208,6 +208,10 @@ int BKE_sequencer_recursive_apply(struct Sequence *seq, int (*apply_func)(struct void BKE_sequencer_free_clipboard(void); +void BKE_sequence_clipboard_pointers_free(struct Sequence *seq); +void BKE_sequence_clipboard_pointers_store(struct Sequence *seq); +void BKE_sequence_clipboard_pointers_restore(struct Sequence *seq, struct Main *bmain); + void BKE_sequence_free(struct Scene *scene, struct Sequence *seq); const char *BKE_sequence_give_name(struct Sequence *seq); void BKE_sequence_calc(struct Scene *scene, struct Sequence *seq); @@ -319,8 +323,6 @@ void BKE_sequence_base_dupli_recursive(struct Scene *scene, struct Scene *scene_ bool BKE_sequence_is_valid_check(struct Sequence *seq); void BKE_sequencer_clear_scene_in_allseqs(struct Main *bmain, struct Scene *sce); -void BKE_sequencer_clear_movieclip_in_clipboard(struct MovieClip *clip); -void BKE_sequencer_clear_mask_in_clipboard(struct Mask *mask); struct Sequence *BKE_sequence_get_by_name(struct ListBase *seqbase, const char *name, int recursive); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index b3c5ceefb2d..21e7fb3116e 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -939,8 +939,6 @@ void BKE_mask_free(Main *bmain, Mask *mask) SpaceLink *sl; Scene *scene; - BKE_sequencer_clear_mask_in_clipboard(mask); - for (scr = bmain->screen.first; scr; scr = scr->id.next) { for (area = scr->areabase.first; area; area = area->next) { for (sl = area->spacedata.first; sl; sl = sl->next) { diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index ef3b7ca0bdf..e8550e12e4f 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1395,8 +1395,6 @@ void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip, ImBuf *ibuf, stru void BKE_movieclip_free(MovieClip *clip) { - BKE_sequencer_clear_movieclip_in_clipboard(clip); - free_buffers(clip); BKE_tracking_free(&clip->tracking); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index b080cfcff2f..1dba2bd8eb9 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -65,6 +65,7 @@ #include "BKE_fcurve.h" #include "BKE_scene.h" #include "BKE_mask.h" +#include "BKE_library.h" #include "RNA_access.h" @@ -265,6 +266,7 @@ static void seq_free_clipboard_recursive(Sequence *seq_parent) seq_free_clipboard_recursive(seq); } + BKE_sequence_clipboard_pointers_free(seq_parent); BKE_sequence_free_ex(NULL, seq_parent, FALSE); } @@ -279,6 +281,101 @@ void BKE_sequencer_free_clipboard(void) seqbase_clipboard.first = seqbase_clipboard.last = NULL; } +/* -------------------------------------------------------------------- */ +/* Manage pointers in the clipboard. + * note that these pointers should _never_ be access in the sequencer, + * they are only for storage while in the clipboard + * notice 'newid' is used for temp pointer storage here, validate on access. + */ +#define ID_PT (*id_pt) +static void seqclipboard_ptr_free(ID **id_pt) +{ + if (ID_PT) { + BLI_assert(ID_PT->newid != NULL); + MEM_freeN(ID_PT); + ID_PT = NULL; + } +} +static void seqclipboard_ptr_store(ID **id_pt) +{ + if (ID_PT) { + ID *id_prev = ID_PT; + ID_PT = MEM_dupallocN(ID_PT); + ID_PT->newid = id_prev; + } +} +static void seqclipboard_ptr_restore(Main *bmain, ID **id_pt) +{ + if (ID_PT) { + const ListBase *lb = which_libbase(bmain, GS(ID_PT->name)); + void *id_restore; + + BLI_assert(ID_PT->newid != NULL); + if (BLI_findindex(lb, (ID_PT)->newid) != -1) { + /* the pointer is still valid */ + id_restore = (ID_PT)->newid; + } + else { + /* the pointer of the same name still exists */ + id_restore = BLI_findstring(lb, (ID_PT)->name + 2, offsetof(ID, name) + 2); + } + + if (id_restore == NULL) { + /* check for a data with the same filename */ + switch (GS(ID_PT->name)) { + case ID_SO: + { + id_restore = BLI_findstring(lb, ((bSound *)ID_PT)->name, offsetof(bSound, name)); + if (id_restore == NULL) { + id_restore = sound_new_file(bmain, ((bSound *)ID_PT)->name); + (ID_PT)->newid = id_restore; /* reuse next time */ + } + break; + } + case ID_MC: + { + id_restore = BLI_findstring(lb, ((MovieClip *)ID_PT)->name, offsetof(MovieClip, name)); + if (id_restore == NULL) { + id_restore = BKE_movieclip_file_add(bmain, ((MovieClip *)ID_PT)->name); + (ID_PT)->newid = id_restore; /* reuse next time */ + } + break; + } + } + } + + ID_PT = id_restore; + } +} +#undef ID_PT + +void BKE_sequence_clipboard_pointers_free(Sequence *seq) +{ + seqclipboard_ptr_free((ID **)&seq->scene); + seqclipboard_ptr_free((ID **)&seq->scene_camera); + seqclipboard_ptr_free((ID **)&seq->clip); + seqclipboard_ptr_free((ID **)&seq->mask); + seqclipboard_ptr_free((ID **)&seq->sound); +} +void BKE_sequence_clipboard_pointers_store(Sequence *seq) +{ + seqclipboard_ptr_store((ID **)&seq->scene); + seqclipboard_ptr_store((ID **)&seq->scene_camera); + seqclipboard_ptr_store((ID **)&seq->clip); + seqclipboard_ptr_store((ID **)&seq->mask); + seqclipboard_ptr_store((ID **)&seq->sound); +} +void BKE_sequence_clipboard_pointers_restore(Sequence *seq, Main *bmain) +{ + seqclipboard_ptr_restore(bmain, (ID **)&seq->scene); + seqclipboard_ptr_restore(bmain, (ID **)&seq->scene_camera); + seqclipboard_ptr_restore(bmain, (ID **)&seq->clip); + seqclipboard_ptr_restore(bmain, (ID **)&seq->mask); + seqclipboard_ptr_restore(bmain, (ID **)&seq->sound); +} +/* end clipboard pointer mess */ + + Editing *BKE_sequencer_editing_ensure(Scene *scene) { if (scene->ed == NULL) { @@ -818,33 +915,6 @@ void BKE_sequencer_clear_scene_in_allseqs(Main *bmain, Scene *scene) BKE_sequencer_base_recursive_apply(&scene_iter->ed->seqbase, clear_scene_in_allseqs_cb, scene); } } - - /* also clear clipboard */ - BKE_sequencer_base_recursive_apply(&seqbase_clipboard, clear_scene_in_allseqs_cb, scene); -} - -static int clear_movieclip_in_clipboard_cb(Sequence *seq, void *arg_pt) -{ - if (seq->clip == (MovieClip *)arg_pt) - seq->clip = NULL; - return 1; -} - -void BKE_sequencer_clear_movieclip_in_clipboard(MovieClip *clip) -{ - BKE_sequencer_base_recursive_apply(&seqbase_clipboard, clear_movieclip_in_clipboard_cb, clip); -} - -static int clear_mask_in_clipboard_cb(Sequence *seq, void *arg_pt) -{ - if (seq->mask == (Mask *)arg_pt) - seq->mask = NULL; - return 1; -} - -void BKE_sequencer_clear_mask_in_clipboard(Mask *mask) -{ - BKE_sequencer_base_recursive_apply(&seqbase_clipboard, clear_mask_in_clipboard_cb, mask); } typedef struct SeqUniqueInfo { |