Blender V4.3
sequencer.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 * SPDX-FileCopyrightText: 2003-2009 Blender Authors
3 * SPDX-FileCopyrightText: 2005-2006 Peter Schlaile <peter [at] schlaile [dot] de>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later */
6
11#include "DNA_listBase.h"
12#define DNA_DEPRECATED_ALLOW
13
14#include "MEM_guardedalloc.h"
15
16#include "DNA_anim_types.h"
17#include "DNA_scene_types.h"
18#include "DNA_sequence_types.h"
19#include "DNA_sound_types.h"
20
21#include "BLI_listbase.h"
22#include "BLI_path_utils.hh"
23
24#include "BKE_fcurve.hh"
25#include "BKE_idprop.hh"
26#include "BKE_lib_id.hh"
27#include "BKE_main.hh"
28#include "BKE_scene.hh"
29#include "BKE_sound.h"
30
31#include "DEG_depsgraph.hh"
32
33#include "IMB_imbuf.hh"
34
35#include "SEQ_channels.hh"
36#include "SEQ_connect.hh"
37#include "SEQ_edit.hh"
38#include "SEQ_effects.hh"
39#include "SEQ_iterator.hh"
40#include "SEQ_modifier.hh"
41#include "SEQ_proxy.hh"
42#include "SEQ_relations.hh"
43#include "SEQ_retiming.hh"
44#include "SEQ_select.hh"
45#include "SEQ_sequencer.hh"
46#include "SEQ_sound.hh"
48#include "SEQ_time.hh"
49#include "SEQ_utils.hh"
50
51#include "BLO_read_write.hh"
52
53#include "image_cache.hh"
54#include "prefetch.hh"
55#include "sequencer.hh"
56#include "utils.hh"
57
58/* -------------------------------------------------------------------- */
63{
64 StripProxy *strip_proxy = static_cast<StripProxy *>(
65 MEM_callocN(sizeof(StripProxy), "StripProxy"));
66 strip_proxy->quality = 50;
68 strip_proxy->tc = SEQ_PROXY_TC_RECORD_RUN;
69 return strip_proxy;
70}
71
72static Strip *seq_strip_alloc(int type)
73{
74 Strip *strip = static_cast<Strip *>(MEM_callocN(sizeof(Strip), "strip"));
75
76 if (type != SEQ_TYPE_SOUND_RAM) {
77 strip->transform = static_cast<StripTransform *>(
78 MEM_callocN(sizeof(StripTransform), "StripTransform"));
79 strip->transform->scale_x = 1;
80 strip->transform->scale_y = 1;
81 strip->transform->origin[0] = 0.5f;
82 strip->transform->origin[1] = 0.5f;
84 strip->crop = static_cast<StripCrop *>(MEM_callocN(sizeof(StripCrop), "StripCrop"));
85 }
86
87 strip->us = 1;
88 return strip;
89}
90
91static void seq_free_strip(Strip *strip)
92{
93 strip->us--;
94 if (strip->us > 0) {
95 return;
96 }
97 if (strip->us < 0) {
98 printf("error: negative users in strip\n");
99 return;
100 }
101
102 if (strip->stripdata) {
103 MEM_freeN(strip->stripdata);
104 }
105
106 if (strip->proxy) {
107 if (strip->proxy->anim) {
108 IMB_free_anim(strip->proxy->anim);
109 }
110
111 MEM_freeN(strip->proxy);
112 }
113 if (strip->crop) {
114 MEM_freeN(strip->crop);
115 }
116 if (strip->transform) {
117 MEM_freeN(strip->transform);
118 }
119
120 MEM_freeN(strip);
121}
122
123Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type)
124{
125 Sequence *seq;
126
127 seq = static_cast<Sequence *>(MEM_callocN(sizeof(Sequence), "addseq"));
128 BLI_addtail(lb, seq);
129
130 *((short *)seq->name) = ID_SEQ;
131 seq->name[2] = 0;
132
133 seq->flag = SELECT;
134 seq->start = timeline_frame;
135 seq->machine = machine;
136 seq->sat = 1.0;
137 seq->mul = 1.0;
138 seq->blend_opacity = 100.0;
139 seq->volume = 1.0f;
140 seq->scene_sound = nullptr;
141 seq->type = type;
142 seq->media_playback_rate = 0.0f;
143 seq->speed_factor = 1.0f;
144
145 if (seq->type == SEQ_TYPE_ADJUSTMENT) {
147 }
148 else {
150 }
151
152 seq->strip = seq_strip_alloc(type);
153 seq->stereo3d_format = static_cast<Stereo3dFormat *>(
154 MEM_callocN(sizeof(Stereo3dFormat), "Sequence Stereo Format"));
155
157
158 if (seq->type == SEQ_TYPE_META) {
160 }
161
163
164 return seq;
165}
166
167/* only give option to skip cache locally (static func) */
168static void seq_sequence_free_ex(Scene *scene,
169 Sequence *seq,
170 const bool do_cache,
171 const bool do_id_user)
172{
173 if (seq->strip) {
174 seq_free_strip(seq->strip);
175 }
176
178
179 if (seq->type & SEQ_TYPE_EFFECT) {
181 sh.free(seq, do_id_user);
182 }
183
184 if (seq->sound && do_id_user) {
185 id_us_min((ID *)seq->sound);
186 }
187
188 if (seq->stereo3d_format) {
190 }
191
192 /* clipboard has no scene and will never have a sound handle or be active
193 * same goes to sequences copy for proxy rebuild job
194 */
195 if (scene) {
196 Editing *ed = scene->ed;
197
198 if (ed->act_seq == seq) {
199 ed->act_seq = nullptr;
200 }
201
204 }
205 }
206
207 if (seq->prop) {
208 IDP_FreePropertyContent_ex(seq->prop, do_id_user);
209 MEM_freeN(seq->prop);
210 }
211
212 /* free modifiers */
214
215 if (SEQ_is_strip_connected(seq)) {
216 SEQ_disconnect(seq);
217 }
218
219 /* free cached data used by this strip,
220 * also invalidate cache for all dependent sequences
221 *
222 * be _very_ careful here, invalidating cache loops over the scene sequences and
223 * assumes the listbase is valid for all strips,
224 * this may not be the case if lists are being freed.
225 * this is optional SEQ_relations_invalidate_cache
226 */
227 if (do_cache) {
228 if (scene) {
230 }
231 }
232 if (seq->type == SEQ_TYPE_META) {
234 }
235
236 if (seq->retiming_keys != nullptr) {
238 seq->retiming_keys = nullptr;
239 seq->retiming_keys_num = 0;
240 }
241
242 MEM_freeN(seq);
243}
244
246{
247 seq_sequence_free_ex(scene, seq, true, true);
248}
249
250void seq_free_sequence_recurse(Scene *scene, Sequence *seq, const bool do_id_user)
251{
252 Sequence *iseq, *iseq_next;
253
254 for (iseq = static_cast<Sequence *>(seq->seqbase.first); iseq; iseq = iseq_next) {
255 iseq_next = iseq->next;
256 seq_free_sequence_recurse(scene, iseq, do_id_user);
257 }
258
259 seq_sequence_free_ex(scene, seq, false, do_id_user);
260}
261
263{
264 return scene->ed;
265}
266
268{
269 if (scene->ed == nullptr) {
270 Editing *ed;
271
272 ed = scene->ed = static_cast<Editing *>(MEM_callocN(sizeof(Editing), "addseq"));
273 ed->seqbasep = &ed->seqbase;
274 ed->cache = nullptr;
277 ed->displayed_channels = &ed->channels;
279 }
280
281 return scene->ed;
282}
283
284void SEQ_editing_free(Scene *scene, const bool do_id_user)
285{
286 Editing *ed = scene->ed;
287
288 if (ed == nullptr) {
289 return;
290 }
291
292 seq_prefetch_free(scene);
293 seq_cache_destruct(scene);
294
295 /* handle cache freeing above */
297 seq_free_sequence_recurse(scene, seq, do_id_user);
298 }
299
305
306 MEM_freeN(ed);
307
308 scene->ed = nullptr;
309}
310
312{
313 if (seq->type & SEQ_TYPE_EFFECT) {
314 if (seq->seq1 && seq->seq1->tmp) {
315 seq->seq1 = static_cast<Sequence *>(seq->seq1->tmp);
316 }
317 if (seq->seq2 && seq->seq2->tmp) {
318 seq->seq2 = static_cast<Sequence *>(seq->seq2->tmp);
319 }
320 }
321 else if (seq->type == SEQ_TYPE_META) {
322 LISTBASE_FOREACH (Sequence *, seqn, &seq->seqbase) {
324 }
325 }
326
328 if (smd->mask_sequence && smd->mask_sequence->tmp) {
329 smd->mask_sequence = static_cast<Sequence *>(smd->mask_sequence->tmp);
330 }
331 }
332
333 if (SEQ_is_strip_connected(seq)) {
335 if (con->seq_ref->tmp) {
336 con->seq_ref = static_cast<Sequence *>(con->seq_ref->tmp);
337 }
338 }
339 }
340}
341
343{
344 SequencerToolSettings *tool_settings = static_cast<SequencerToolSettings *>(
345 MEM_callocN(sizeof(SequencerToolSettings), "Sequencer tool settings"));
346 tool_settings->fit_method = SEQ_SCALE_TO_FIT;
351 tool_settings->snap_distance = 15;
352 tool_settings->overlap_mode = SEQ_OVERLAP_SHUFFLE;
353 tool_settings->pivot_point = V3D_AROUND_LOCAL_ORIGINS;
354
355 return tool_settings;
356}
357
359{
360 SequencerToolSettings *tool_settings = scene->toolsettings->sequencer_tool_settings;
361 if (tool_settings == nullptr) {
362 scene->toolsettings->sequencer_tool_settings = SEQ_tool_settings_init();
363 tool_settings = scene->toolsettings->sequencer_tool_settings;
364 }
365
366 return tool_settings;
367}
368
370{
371 MEM_freeN(tool_settings);
372}
373
375{
376 const SequencerToolSettings *tool_settings = SEQ_tool_settings_ensure(scene);
377 return eSeqImageFitMethod(tool_settings->fit_method);
378}
379
381{
382 const SequencerToolSettings *tool_settings = SEQ_tool_settings_ensure(scene);
383 return tool_settings->snap_mode;
384}
385
387{
388 const SequencerToolSettings *tool_settings = SEQ_tool_settings_ensure(scene);
389 return tool_settings->snap_flag;
390}
391
393{
394 const SequencerToolSettings *tool_settings = SEQ_tool_settings_ensure(scene);
395 return tool_settings->snap_distance;
396}
397
399{
400 SequencerToolSettings *tool_settings = SEQ_tool_settings_ensure(scene);
401 tool_settings->fit_method = fit_method;
402}
403
405{
406 const SequencerToolSettings *tool_settings = SEQ_tool_settings_ensure(scene);
407 return eSeqOverlapMode(tool_settings->overlap_mode);
408}
409
411{
412 const SequencerToolSettings *tool_settings = SEQ_tool_settings_ensure(scene);
413 return tool_settings->pivot_point;
414}
415
417{
418 if (ed == nullptr) {
419 return nullptr;
420 }
421
422 return ed->seqbasep;
423}
424
426{
427 ed->seqbasep = seqbase;
428}
429
430static MetaStack *seq_meta_stack_alloc(const Scene *scene, Sequence *seq_meta)
431{
432 Editing *ed = SEQ_editing_get(scene);
433
434 MetaStack *ms = static_cast<MetaStack *>(MEM_mallocN(sizeof(MetaStack), "metastack"));
435 BLI_addhead(&ed->metastack, ms);
436 ms->parseq = seq_meta;
437
438 /* Reference to previously displayed timeline data. */
439 Sequence *higher_level_meta = seq_sequence_lookup_meta_by_seq(scene, seq_meta);
440 ms->oldbasep = higher_level_meta ? &higher_level_meta->seqbase : &ed->seqbase;
441 ms->old_channels = higher_level_meta ? &higher_level_meta->channels : &ed->channels;
442
445 return ms;
446}
447
449{
450 if (ed == nullptr) {
451 return nullptr;
452 }
453
454 return static_cast<MetaStack *>(ed->metastack.last);
455}
456
457void SEQ_meta_stack_set(const Scene *scene, Sequence *dst_seq)
458{
459 Editing *ed = SEQ_editing_get(scene);
460 /* Clear metastack */
462
463 if (dst_seq != nullptr) {
464 /* Allocate meta stack in a way, that represents meta hierarchy in timeline. */
465 seq_meta_stack_alloc(scene, dst_seq);
466 Sequence *meta_parent = dst_seq;
467 while ((meta_parent = seq_sequence_lookup_meta_by_seq(scene, meta_parent))) {
468 seq_meta_stack_alloc(scene, meta_parent);
469 }
470
471 SEQ_seqbase_active_set(ed, &dst_seq->seqbase);
473 }
474 else {
475 /* Go to top level, exiting meta strip. */
478 }
479}
480
482{
484 Sequence *meta_parent = ms->parseq;
487 BLI_remlink(&ed->metastack, ms);
488 MEM_freeN(ms);
489 return meta_parent;
490}
491
494/* -------------------------------------------------------------------- */
498static Sequence *seq_dupli(const Scene *scene_src,
499 Scene *scene_dst,
500 ListBase *new_seq_list,
501 Sequence *seq,
502 int dupe_flag,
503 const int flag)
504{
505 Sequence *seqn = static_cast<Sequence *>(MEM_dupallocN(seq));
506
507 if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
509 }
510
511 seq->tmp = seqn;
512 seqn->strip = static_cast<Strip *>(MEM_dupallocN(seq->strip));
513
514 seqn->stereo3d_format = static_cast<Stereo3dFormat *>(MEM_dupallocN(seq->stereo3d_format));
515
516 /* XXX: add F-Curve duplication stuff? */
517
518 if (seq->strip->crop) {
519 seqn->strip->crop = static_cast<StripCrop *>(MEM_dupallocN(seq->strip->crop));
520 }
521
522 if (seq->strip->transform) {
523 seqn->strip->transform = static_cast<StripTransform *>(MEM_dupallocN(seq->strip->transform));
524 }
525
526 if (seq->strip->proxy) {
527 seqn->strip->proxy = static_cast<StripProxy *>(MEM_dupallocN(seq->strip->proxy));
528 seqn->strip->proxy->anim = nullptr;
529 }
530
531 if (seq->prop) {
532 seqn->prop = IDP_CopyProperty_ex(seq->prop, flag);
533 }
534
535 if (seqn->modifiers.first) {
537
538 SEQ_modifier_list_copy(seqn, seq);
539 }
540
541 if (SEQ_is_strip_connected(seq)) {
544 }
545
546 if (seq->type == SEQ_TYPE_META) {
547 seqn->strip->stripdata = nullptr;
548
550 /* WARNING: This meta-strip is not recursively duplicated here - do this after! */
551 // seq_dupli_recursive(&seq->seqbase, &seqn->seqbase);
552
555 }
556 else if (seq->type == SEQ_TYPE_SCENE) {
557 seqn->strip->stripdata = nullptr;
558 if (seq->scene_sound) {
560 }
561 }
562 else if (seq->type == SEQ_TYPE_MOVIECLIP) {
563 /* avoid assert */
564 }
565 else if (seq->type == SEQ_TYPE_MASK) {
566 /* avoid assert */
567 }
568 else if (seq->type == SEQ_TYPE_MOVIE) {
569 seqn->strip->stripdata = static_cast<StripElem *>(MEM_dupallocN(seq->strip->stripdata));
571 }
572 else if (seq->type == SEQ_TYPE_SOUND_RAM) {
573 seqn->strip->stripdata = static_cast<StripElem *>(MEM_dupallocN(seq->strip->stripdata));
574 seqn->scene_sound = nullptr;
576 id_us_plus((ID *)seqn->sound);
577 }
578 }
579 else if (seq->type == SEQ_TYPE_IMAGE) {
580 seqn->strip->stripdata = static_cast<StripElem *>(MEM_dupallocN(seq->strip->stripdata));
581 }
582 else if (seq->type & SEQ_TYPE_EFFECT) {
584 sh = SEQ_effect_handle_get(seq);
585 if (sh.copy) {
586 sh.copy(seqn, seq, flag);
587 }
588
589 seqn->strip->stripdata = nullptr;
590 }
591 else {
592 /* sequence type not handled in duplicate! Expect a crash now... */
594 }
595
596 /* When using #SEQ_DUPE_UNIQUE_NAME, it is mandatory to add new sequences in relevant container
597 * (scene or meta's one), *before* checking for unique names. Otherwise the meta's list is empty
598 * and hence we miss all sequence-strips in that meta that have already been duplicated,
599 * (see #55668). Note that unique name check itself could be done at a later step in calling
600 * code, once all sequence-strips have bee duplicated (that was first, simpler solution),
601 * but then handling of animation data will be broken (see #60194). */
602 if (new_seq_list != nullptr) {
603 BLI_addtail(new_seq_list, seqn);
604 }
605
606 if (scene_src == scene_dst) {
607 if (dupe_flag & SEQ_DUPE_UNIQUE_NAME) {
608 SEQ_sequence_base_unique_name_recursive(scene_dst, &scene_dst->ed->seqbase, seqn);
609 }
610 }
611
612 if (seq->retiming_keys != nullptr) {
613 seqn->retiming_keys = static_cast<SeqRetimingKey *>(MEM_dupallocN(seq->retiming_keys));
615 }
616
617 return seqn;
618}
619
621 Scene *scene_dst,
622 ListBase *new_seq_list,
623 Sequence *seq,
624 const int dupe_flag)
625{
626 Sequence *seqn;
627
628 seq->tmp = nullptr;
629 seqn = seq_dupli(scene_src, scene_dst, new_seq_list, seq, dupe_flag, 0);
630 if (seq->type == SEQ_TYPE_META) {
631 LISTBASE_FOREACH (Sequence *, s, &seq->seqbase) {
632 sequence_dupli_recursive_do(scene_src, scene_dst, &seqn->seqbase, s, dupe_flag);
633 }
634 }
635
636 return seqn;
637}
638
640 const Scene *scene_src, Scene *scene_dst, ListBase *new_seq_list, Sequence *seq, int dupe_flag)
641{
642 Sequence *seqn = sequence_dupli_recursive_do(scene_src, scene_dst, new_seq_list, seq, dupe_flag);
643
644 /* This does not need to be in recursive call itself, since it is already recursive... */
646 if (SEQ_is_strip_connected(seqn)) {
648 }
649
650 return seqn;
651}
652
654 Scene *scene_dst,
655 ListBase *nseqbase,
656 const ListBase *seqbase,
657 int dupe_flag,
658 const int flag)
659{
660 LISTBASE_FOREACH (Sequence *, seq, seqbase) {
661 seq->tmp = nullptr;
662 if ((seq->flag & SELECT) || (dupe_flag & SEQ_DUPE_ALL)) {
663 Sequence *seqn = seq_dupli(scene_src, scene_dst, nseqbase, seq, dupe_flag, flag);
664
665 if (seqn == nullptr) {
666 continue; /* Should never fail. */
667 }
668
669 if (seq->type == SEQ_TYPE_META) {
670 /* Always include meta all strip children. */
671 int dupe_flag_recursive = dupe_flag | SEQ_DUPE_ALL | SEQ_DUPE_IS_RECURSIVE_CALL;
673 scene_src, scene_dst, &seqn->seqbase, &seq->seqbase, dupe_flag_recursive, flag);
674 }
675 }
676 }
677
678 /* Fix modifier links recursively from the top level only, when all sequences have been
679 * copied. */
680 if (dupe_flag & SEQ_DUPE_IS_RECURSIVE_CALL) {
681 return;
682 }
683
684 /* Fix effect, modifier, and connected strip links. */
685 LISTBASE_FOREACH (Sequence *, seq, nseqbase) {
687 }
688 /* One-way connections cannot be cut until after all connections are resolved. */
689 LISTBASE_FOREACH (Sequence *, seq, nseqbase) {
690 if (SEQ_is_strip_connected(seq)) {
692 }
693 }
694}
695
697{
698 return seq->machine >= 1 && seq->machine <= SEQ_MAX_CHANNELS;
699}
700
702{
703 SequencerToolSettings *tool_settings_copy = static_cast<SequencerToolSettings *>(
704 MEM_dupallocN(tool_settings));
705 return tool_settings_copy;
706}
707
710static bool seq_set_strip_done_cb(Sequence *seq, void * /*userdata*/)
711{
712 if (seq->strip) {
713 seq->strip->done = false;
714 }
715 return true;
716}
717
718static bool seq_write_data_cb(Sequence *seq, void *userdata)
719{
720 BlendWriter *writer = (BlendWriter *)userdata;
721 BLO_write_struct(writer, Sequence, seq);
722 if (seq->strip && seq->strip->done == 0) {
723 /* Write strip with 'done' at 0 because read-file. */
724
725 /* TODO this doesn't depend on the `Strip` data to be present? */
726 if (seq->effectdata) {
727 switch (seq->type) {
728 case SEQ_TYPE_COLOR:
730 break;
731 case SEQ_TYPE_SPEED:
733 break;
734 case SEQ_TYPE_WIPE:
735 BLO_write_struct(writer, WipeVars, seq->effectdata);
736 break;
737 case SEQ_TYPE_GLOW:
738 BLO_write_struct(writer, GlowVars, seq->effectdata);
739 break;
742 break;
745 break;
746 case SEQ_TYPE_TEXT:
747 BLO_write_struct(writer, TextVars, seq->effectdata);
748 break;
751 break;
752 }
753 }
754
756
757 Strip *strip = seq->strip;
758 BLO_write_struct(writer, Strip, strip);
759 if (strip->crop) {
760 BLO_write_struct(writer, StripCrop, strip->crop);
761 }
762 if (strip->transform) {
764 }
765 if (strip->proxy) {
766 BLO_write_struct(writer, StripProxy, strip->proxy);
767 }
768 if (seq->type == SEQ_TYPE_IMAGE) {
770 StripElem,
771 MEM_allocN_len(strip->stripdata) / sizeof(StripElem),
772 strip->stripdata);
773 }
774 else if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM)) {
775 BLO_write_struct(writer, StripElem, strip->stripdata);
776 }
777
778 strip->done = true;
779 }
780
781 if (seq->prop) {
782 IDP_BlendWrite(writer, seq->prop);
783 }
784
785 SEQ_modifier_blend_write(writer, &seq->modifiers);
786
787 LISTBASE_FOREACH (SeqTimelineChannel *, channel, &seq->channels) {
788 BLO_write_struct(writer, SeqTimelineChannel, channel);
789 }
790
792 BLO_write_struct(writer, SeqConnection, con);
793 }
794
795 if (seq->retiming_keys != nullptr) {
796 int size = SEQ_retiming_keys_count(seq);
798 }
799
800 return true;
801}
802
803void SEQ_blend_write(BlendWriter *writer, ListBase *seqbase)
804{
805 /* reset write flags */
807
809}
810
811static bool seq_read_data_cb(Sequence *seq, void *user_data)
812{
813 BlendDataReader *reader = (BlendDataReader *)user_data;
814
815 /* Runtime data cleanup. */
816 seq->scene_sound = nullptr;
818
819 /* Do as early as possible, so that other parts of reading can rely on valid session UID. */
821
822 BLO_read_struct(reader, Sequence, &seq->seq1);
823 BLO_read_struct(reader, Sequence, &seq->seq2);
824
825 if (seq->effectdata) {
826 switch (seq->type) {
827 case SEQ_TYPE_COLOR:
829 break;
830 case SEQ_TYPE_SPEED:
832 break;
833 case SEQ_TYPE_WIPE:
834 BLO_read_struct(reader, WipeVars, &seq->effectdata);
835 break;
836 case SEQ_TYPE_GLOW:
837 BLO_read_struct(reader, GlowVars, &seq->effectdata);
838 break;
841 break;
844 break;
845 case SEQ_TYPE_TEXT:
846 BLO_read_struct(reader, TextVars, &seq->effectdata);
847 break;
850 break;
851 default:
853 seq->effectdata = nullptr;
854 break;
855 }
856 }
857
859
860 if (seq->type & SEQ_TYPE_EFFECT) {
862 }
863
864 if (seq->type == SEQ_TYPE_TEXT) {
865 TextVars *t = static_cast<TextVars *>(seq->effectdata);
867 }
868
869 BLO_read_struct(reader, IDProperty, &seq->prop);
870 IDP_BlendDataRead(reader, &seq->prop);
871
872 BLO_read_struct(reader, Strip, &seq->strip);
873 if (seq->strip && seq->strip->done == 0) {
874 seq->strip->done = true;
875
876 /* `SEQ_TYPE_SOUND_HD` case needs to be kept here, for backward compatibility. */
878 /* FIXME In #SEQ_TYPE_IMAGE case, there is currently no available information about the
879 * length of the stored array of #StripElem.
880 *
881 * This is 'not a problem' because the reading code only checks that the loaded buffer is at
882 * least large enough for the requested data (here a single #StripElem item), and always
883 * assign the whole read memory (without any truncating). But relying on this behavior is
884 * weak and should be addressed. */
885 BLO_read_struct(reader, StripElem, &seq->strip->stripdata);
886 }
887 else {
888 seq->strip->stripdata = nullptr;
889 }
890 BLO_read_struct(reader, StripCrop, &seq->strip->crop);
892 BLO_read_struct(reader, StripProxy, &seq->strip->proxy);
893 if (seq->strip->proxy) {
894 seq->strip->proxy->anim = nullptr;
895 }
896 else if (seq->flag & SEQ_USE_PROXY) {
897 SEQ_proxy_set(seq, true);
898 }
899
900 /* need to load color balance to it could be converted to modifier */
901 BLO_read_struct(reader, StripColorBalance, &seq->strip->color_balance);
902 }
903
905
908 if (con->seq_ref) {
909 BLO_read_struct(reader, Sequence, &con->seq_ref);
910 }
911 }
912
914
915 if (seq->retiming_keys != nullptr) {
916 const int size = SEQ_retiming_keys_count(seq);
918 }
919
920 return true;
921}
923{
924 SEQ_for_each_callback(seqbase, seq_read_data_cb, reader);
925}
926
927static bool seq_doversion_250_sound_proxy_update_cb(Sequence *seq, void *user_data)
928{
929 Main *bmain = static_cast<Main *>(user_data);
930 if (seq->type == SEQ_TYPE_SOUND_HD) {
931 char filepath_abs[FILE_MAX];
933 filepath_abs, sizeof(filepath_abs), seq->strip->dirpath, seq->strip->stripdata->filename);
934 BLI_path_abs(filepath_abs, BKE_main_blendfile_path(bmain));
935 seq->sound = BKE_sound_new_file(bmain, filepath_abs);
937 }
938 return true;
939}
940
945
946/* Depsgraph update functions. */
947
948static bool seq_mute_sound_strips_cb(Sequence *seq, void *user_data)
949{
950 Scene *scene = (Scene *)user_data;
951 if (seq->scene_sound != nullptr) {
953 seq->scene_sound = nullptr;
954 }
955 return true;
956}
957
958/* Adds sound of strip to the `scene->sound_scene` - "sound timeline". */
959static void seq_update_mix_sounds(Scene *scene, Sequence *seq)
960{
961 if (seq->scene_sound != nullptr) {
962 return;
963 }
964
965 if (seq->sound != nullptr) {
966 /* Adds `seq->sound->playback_handle` to `scene->sound_scene` */
968 }
969 else if (seq->type == SEQ_TYPE_SCENE && seq->scene != nullptr) {
970 /* Adds `seq->scene->sound_scene` to `scene->sound_scene`. */
973 }
974}
975
976static void seq_update_sound_properties(const Scene *scene, const Sequence *seq)
977{
978 const int frame = BKE_scene_frame_get(scene);
980 seq->scene_sound, frame, seq->volume, (seq->flag & SEQ_AUDIO_VOLUME_ANIMATED) != 0);
983 seq->scene_sound, frame, seq->pan, (seq->flag & SEQ_AUDIO_PAN_ANIMATED) != 0);
984}
985
987{
988 void *sound_handle = seq->sound->playback_handle;
989 if (!BLI_listbase_is_empty(&seq->modifiers)) {
991 sound_handle = SEQ_sound_modifier_recreator(seq, smd, sound_handle);
992 }
993 }
994
995 /* Assign modified sound back to `seq`. */
997}
998
999static bool must_update_strip_sound(Scene *scene, Sequence *seq)
1000{
1001 return (scene->id.recalc & (ID_RECALC_AUDIO | ID_RECALC_SYNC_TO_EVAL)) != 0 ||
1003}
1004
1005static void seq_update_sound_strips(Scene *scene, Sequence *seq)
1006{
1007 if (seq->sound == nullptr || !must_update_strip_sound(scene, seq)) {
1008 return;
1009 }
1010 /* Ensure strip is playing correct sound. */
1013}
1014
1015static bool scene_sequencer_is_used(const Scene *scene, ListBase *seqbase)
1016{
1017 bool sequencer_is_used = false;
1018 LISTBASE_FOREACH (Sequence *, seq_iter, seqbase) {
1019 if (seq_iter->scene == scene && (seq_iter->flag & SEQ_SCENE_STRIPS) != 0) {
1020 sequencer_is_used = true;
1021 }
1022 if (seq_iter->type == SEQ_TYPE_META) {
1023 sequencer_is_used |= scene_sequencer_is_used(scene, &seq_iter->seqbase);
1024 }
1025 }
1026
1027 return sequencer_is_used;
1028}
1029
1030static void seq_update_scene_strip_sound(const Scene *scene, Sequence *seq)
1031{
1032 if (seq->type != SEQ_TYPE_SCENE || seq->scene == nullptr) {
1033 return;
1034 }
1035
1036 /* Set `seq->scene` volume.
1037 * NOTE: Currently this doesn't work well, when this property is animated. Scene strip volume is
1038 * also controlled by `seq_update_sound_properties()` via `seq->volume` which works if animated.
1039 *
1040 * Ideally, the entire `BKE_scene_update_sound()` will happen from a dependency graph, so
1041 * then it is no longer needed to do such manual forced updates. */
1043
1044 /* Mute sound when all scene strips using particular scene are not rendering sequencer strips. */
1045 bool sequencer_is_used = scene_sequencer_is_used(seq->scene, &scene->ed->seqbase);
1046
1047 if (!sequencer_is_used && seq->scene->sound_scene != nullptr && seq->scene->ed != nullptr) {
1049 }
1050}
1051
1052static bool seq_sound_update_cb(Sequence *seq, void *user_data)
1053{
1054 Scene *scene = (Scene *)user_data;
1055
1056 seq_update_mix_sounds(scene, seq);
1057
1058 if (seq->scene_sound == nullptr) {
1059 return true;
1060 }
1061
1062 seq_update_sound_strips(scene, seq);
1063 seq_update_scene_strip_sound(scene, seq);
1064 seq_update_sound_properties(scene, seq);
1065 return true;
1066}
1067
1068void SEQ_eval_sequences(Depsgraph *depsgraph, Scene *scene, ListBase *seqbase)
1069{
1070 DEG_debug_print_eval(depsgraph, __func__, scene->id.name, scene);
1072
1074
1075 SEQ_edit_update_muting(scene->ed);
1077}
#define IDP_BlendDataRead(reader, prop)
void IDP_FreePropertyContent_ex(IDProperty *prop, bool do_id_user)
Definition idprop.cc:1189
IDProperty * IDP_CopyProperty_ex(const IDProperty *prop, int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:843
void IDP_BlendWrite(BlendWriter *writer, const IDProperty *prop)
Definition idprop.cc:1437
@ LIB_ID_CREATE_NO_USER_REFCOUNT
@ LIB_ID_CREATE_NO_MAIN
void id_us_plus(ID *id)
Definition lib_id.cc:351
void id_us_min(ID *id)
Definition lib_id.cc:359
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:832
float BKE_scene_frame_get(const Scene *scene)
Definition scene.cc:2331
void BKE_sound_set_scene_sound_pan_at_frame(void *handle, int frame, float pan, char animated)
void * BKE_sound_scene_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence)
void BKE_sound_set_scene_volume(struct Scene *scene, float volume)
struct bSound * BKE_sound_new_file(struct Main *bmain, const char *filepath)
void BKE_sound_ensure_scene(struct Scene *scene)
void BKE_sound_set_scene_sound_volume_at_frame(void *handle, int frame, float volume, char animated)
void BKE_sound_update_scene_sound(void *handle, struct bSound *sound)
void * BKE_sound_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence)
void BKE_sound_update_sequence_handle(void *handle, void *sound_handle)
void BKE_sound_remove_scene_sound(struct Scene *scene, void *handle)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:90
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
#define FILE_MAX
#define BLI_path_join(...)
#define ELEM(...)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
#define BLO_read_struct(reader, struct_name, ptr_p)
void DEG_debug_print_eval(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
@ ID_RECALC_AUDIO
Definition DNA_ID.h:1099
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1085
#define ID_SEQ
These structs are the foundation for all linked lists in the library system.
eSeqImageFitMethod
@ SEQ_SCALE_TO_FIT
@ SEQ_SNAP_TO_STRIPS
@ SEQ_SNAP_TO_MARKERS
@ SEQ_SNAP_TO_PREVIEW_CENTER
@ SEQ_SNAP_TO_STRIPS_PREVIEW
@ SEQ_SNAP_TO_PREVIEW_BORDERS
@ SEQ_SNAP_TO_STRIP_HOLD
@ SEQ_SNAP_TO_CURRENT_FRAME
eSeqOverlapMode
@ SEQ_OVERLAP_SHUFFLE
@ SEQ_CACHE_STORE_RAW
@ SEQ_CACHE_STORE_FINAL_OUT
@ SEQ_TYPE_TRANSFORM
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_CROSS
@ SEQ_TYPE_SOUND_HD
@ SEQ_TYPE_GLOW
@ SEQ_TYPE_COLORMIX
@ SEQ_TYPE_WIPE
@ SEQ_TYPE_META
@ SEQ_TYPE_SCENE
@ SEQ_TYPE_MOVIECLIP
@ SEQ_TYPE_GAUSSIAN_BLUR
@ SEQ_TYPE_ALPHAOVER
@ SEQ_TYPE_TEXT
@ SEQ_TYPE_IMAGE
@ SEQ_TYPE_SPEED
@ SEQ_TYPE_COLOR
@ SEQ_TYPE_EFFECT
@ SEQ_TYPE_MOVIE
@ SEQ_TYPE_MASK
@ SEQ_TYPE_ADJUSTMENT
#define SEQ_FONT_NOT_LOADED
@ SEQUENCE_COLOR_NONE
@ SEQ_EDIT_SHOW_MISSING_MEDIA
@ SEQ_EFFECT_NOT_LOADED
@ SEQ_SCENE_STRIPS
@ SEQ_USE_PROXY
@ SEQ_AUDIO_VOLUME_ANIMATED
@ SEQ_AUDIO_PAN_ANIMATED
@ SEQ_PROXY_TC_RECORD_RUN_NO_GAPS
@ SEQ_PROXY_TC_RECORD_RUN
@ SEQ_TRANSFORM_FILTER_AUTO
@ V3D_AROUND_LOCAL_ORIGINS
void IMB_free_anim(ImBufAnim *anim)
Definition anim_movie.cc:60
Read Guarded memory(de)allocation.
#define SEQ_DUPE_UNIQUE_NAME
#define SEQ_DUPE_ALL
constexpr int SEQ_MAX_CHANNELS
#define SEQ_DUPE_IS_RECURSIVE_CALL
void SEQ_channels_duplicate(ListBase *channels_dst, ListBase *channels_src)
Definition channels.cc:45
void SEQ_channels_free(ListBase *channels)
Definition channels.cc:54
void SEQ_channels_ensure(ListBase *channels)
Definition channels.cc:33
void SEQ_channels_displayed_set(Editing *ed, ListBase *channels)
Definition channels.cc:28
#define printf
#define SELECT
const Depsgraph * depsgraph
SeqEffectHandle SEQ_effect_handle_get(Sequence *seq)
Definition effects.cc:3430
void seq_cache_destruct(Scene *scene)
void SEQ_for_each_callback(ListBase *seqbase, SeqForEachFunc callback, void *user_data)
Definition iterator.cc:43
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
size_t(* MEM_allocN_len)(const void *vmemh)
Definition mallocn.cc:36
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
void media_presence_free(Scene *scene)
void thumbnail_cache_destroy(Scene *scene)
void seq_prefetch_free(Scene *scene)
Definition prefetch.cc:332
void SEQ_proxy_set(Sequence *seq, bool value)
Definition proxy.cc:591
Sequence * seq_sequence_lookup_meta_by_seq(const Scene *scene, const Sequence *key)
void SEQ_sequence_lookup_free(const Scene *scene)
void SEQ_modifier_blend_write(BlendWriter *writer, ListBase *modbase)
void SEQ_modifier_clear(Sequence *seq)
void SEQ_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb)
void SEQ_modifier_list_copy(Sequence *seqn, Sequence *seq)
void SEQ_sound_update_bounds_all(Scene *scene)
void * SEQ_sound_modifier_recreator(Sequence *seq, SequenceModifierData *smd, void *sound)
void SEQ_sequence_base_unique_name_recursive(Scene *scene, ListBase *seqbasep, Sequence *seq)
void SEQ_tool_settings_free(SequencerToolSettings *tool_settings)
Definition sequencer.cc:369
void SEQ_sequence_base_dupli_recursive(const Scene *scene_src, Scene *scene_dst, ListBase *nseqbase, const ListBase *seqbase, int dupe_flag, const int flag)
Definition sequencer.cc:653
static void seq_update_sound_strips(Scene *scene, Sequence *seq)
static void seq_new_fix_links_recursive(Sequence *seq)
Definition sequencer.cc:311
Editing * SEQ_editing_ensure(Scene *scene)
Definition sequencer.cc:267
void SEQ_sequence_free(Scene *scene, Sequence *seq)
Definition sequencer.cc:245
SequencerToolSettings * SEQ_tool_settings_ensure(Scene *scene)
Definition sequencer.cc:358
static bool seq_set_strip_done_cb(Sequence *seq, void *)
Definition sequencer.cc:710
static bool seq_mute_sound_strips_cb(Sequence *seq, void *user_data)
Definition sequencer.cc:948
ListBase * SEQ_active_seqbase_get(const Editing *ed)
Definition sequencer.cc:416
static bool seq_read_data_cb(Sequence *seq, void *user_data)
Definition sequencer.cc:811
static void seq_update_scene_strip_sound(const Scene *scene, Sequence *seq)
short SEQ_tool_settings_snap_mode_get(Scene *scene)
Definition sequencer.cc:380
static void seq_update_mix_sounds(Scene *scene, Sequence *seq)
Definition sequencer.cc:959
int SEQ_tool_settings_snap_distance_get(Scene *scene)
Definition sequencer.cc:392
void SEQ_doversion_250_sound_proxy_update(Main *bmain, Editing *ed)
Definition sequencer.cc:941
Sequence * SEQ_meta_stack_pop(Editing *ed)
Definition sequencer.cc:481
static void seq_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cache, const bool do_id_user)
Definition sequencer.cc:168
void SEQ_editing_free(Scene *scene, const bool do_id_user)
Definition sequencer.cc:284
static MetaStack * seq_meta_stack_alloc(const Scene *scene, Sequence *seq_meta)
Definition sequencer.cc:430
static bool seq_doversion_250_sound_proxy_update_cb(Sequence *seq, void *user_data)
Definition sequencer.cc:927
static Strip * seq_strip_alloc(int type)
Definition sequencer.cc:72
SequencerToolSettings * SEQ_tool_settings_init()
Definition sequencer.cc:342
short SEQ_tool_settings_snap_flag_get(Scene *scene)
Definition sequencer.cc:386
static Sequence * sequence_dupli_recursive_do(const Scene *scene_src, Scene *scene_dst, ListBase *new_seq_list, Sequence *seq, const int dupe_flag)
Definition sequencer.cc:620
SequencerToolSettings * SEQ_tool_settings_copy(SequencerToolSettings *tool_settings)
Definition sequencer.cc:701
void SEQ_eval_sequences(Depsgraph *depsgraph, Scene *scene, ListBase *seqbase)
Sequence * SEQ_sequence_dupli_recursive(const Scene *scene_src, Scene *scene_dst, ListBase *new_seq_list, Sequence *seq, int dupe_flag)
Definition sequencer.cc:639
StripProxy * seq_strip_proxy_alloc()
Definition sequencer.cc:62
void SEQ_seqbase_active_set(Editing *ed, ListBase *seqbase)
Definition sequencer.cc:425
void seq_free_sequence_recurse(Scene *scene, Sequence *seq, const bool do_id_user)
Definition sequencer.cc:250
void SEQ_blend_read(BlendDataReader *reader, ListBase *seqbase)
Definition sequencer.cc:922
eSeqOverlapMode SEQ_tool_settings_overlap_mode_get(Scene *scene)
Definition sequencer.cc:404
static bool scene_sequencer_is_used(const Scene *scene, ListBase *seqbase)
int SEQ_tool_settings_pivot_point_get(Scene *scene)
Definition sequencer.cc:410
static bool seq_write_data_cb(Sequence *seq, void *userdata)
Definition sequencer.cc:718
static bool seq_sound_update_cb(Sequence *seq, void *user_data)
static bool must_update_strip_sound(Scene *scene, Sequence *seq)
Definition sequencer.cc:999
static void seq_free_strip(Strip *strip)
Definition sequencer.cc:91
eSeqImageFitMethod SEQ_tool_settings_fit_method_get(Scene *scene)
Definition sequencer.cc:374
void SEQ_meta_stack_set(const Scene *scene, Sequence *dst_seq)
Definition sequencer.cc:457
Sequence * SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type)
Definition sequencer.cc:123
static void seq_update_sound_properties(const Scene *scene, const Sequence *seq)
Definition sequencer.cc:976
void SEQ_tool_settings_fit_method_set(Scene *scene, eSeqImageFitMethod fit_method)
Definition sequencer.cc:398
static void seq_update_sound_modifiers(Sequence *seq)
Definition sequencer.cc:986
Editing * SEQ_editing_get(const Scene *scene)
Definition sequencer.cc:262
bool SEQ_is_valid_strip_channel(const Sequence *seq)
Definition sequencer.cc:696
void SEQ_blend_write(BlendWriter *writer, ListBase *seqbase)
Definition sequencer.cc:803
MetaStack * SEQ_meta_stack_active_get(const Editing *ed)
Definition sequencer.cc:448
static Sequence * seq_dupli(const Scene *scene_src, Scene *scene_dst, ListBase *new_seq_list, Sequence *seq, int dupe_flag, const int flag)
Definition sequencer.cc:498
void SEQ_connections_duplicate(ListBase *connections_dst, ListBase *connections_src)
bool SEQ_disconnect(Sequence *seq)
bool SEQ_is_strip_connected(const Sequence *seq)
void SEQ_cut_one_way_connections(Sequence *seq)
void SEQ_edit_update_muting(Editing *ed)
void SEQ_relations_invalidate_cache_raw(Scene *scene, Sequence *seq)
void SEQ_relations_session_uid_generate(Sequence *sequence)
void SEQ_relations_sequence_free_anim(Sequence *seq)
int SEQ_retiming_keys_count(const Sequence *seq)
void SEQ_retiming_sound_animation_data_set(const Scene *scene, const Sequence *seq)
int SEQ_time_left_handle_frame_get(const Scene *, const Sequence *seq)
int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
ListBase seqbase
ListBase * seqbasep
Sequence * act_seq
ListBase channels
int show_missing_media_flag
ListBase * displayed_channels
ListBase metastack
struct SeqCache * cache
Definition DNA_ID.h:413
unsigned int recalc
Definition DNA_ID.h:437
void * last
void * first
Sequence * parseq
ListBase * old_channels
ListBase * oldbasep
void * sound_scene
struct Editing * ed
struct AudioData audio
void(* free)(Sequence *seq, bool do_id_user)
void(* copy)(Sequence *dst, const Sequence *src, int flag)
float media_playback_rate
struct Scene * scene
struct SeqRetimingKey * retiming_keys
ListBase channels
ListBase connections
ListBase modifiers
struct bSound * sound
struct Sequence * seq1
struct Sequence * seq2
struct Sequence * next
float pitch pan
struct IDProperty * prop
struct Stereo3dFormat * stereo3d_format
char filename[256]
struct ImBufAnim * anim
char dirpath[768]
StripProxy * proxy
StripTransform * transform
StripElem * stripdata
StripCrop * crop
void * playback_handle
uint8_t flag
Definition wm_window.cc:138