diff options
Diffstat (limited to 'source/blender')
44 files changed, 887 insertions, 279 deletions
diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 43ee284a201..9425f396bc5 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -116,7 +116,8 @@ bool BKE_movieclip_put_frame_if_possible(struct MovieClip *clip, struct MovieClipUser *user, struct ImBuf *ibuf); -/* Evaluation. */ +/* Dependency graph evaluation. */ + void BKE_movieclip_eval_update(struct Depsgraph *depsgraph, struct MovieClip *clip); void BKE_movieclip_eval_selection_update(struct Depsgraph *depsgraph, struct MovieClip *clip); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 0dcb109240c..f90429aaebe 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -246,6 +246,14 @@ void BKE_scene_cursor_from_mat4(struct View3DCursor *cursor, const float mat[4][4], bool use_compat); +/* Dependency graph evaluation. */ + +/* Evaluate parts of sequences which needs to be done as a part of a dependency graph evaluation. + * This does NOT include actual rendering of the strips, but rather makes them up-to-date for + * animation playback and makes them ready for the sequencer's rendering pipeline to render them. + */ +void BKE_scene_eval_sequencer_sequences(struct Depsgraph *depsgraph, struct Scene *scene); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 91e23d35f0e..8d17380592e 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -32,6 +32,7 @@ struct Main; struct Sequence; struct bSound; +struct Depsgraph; typedef struct SoundWaveform { int length; @@ -71,10 +72,17 @@ void BKE_sound_cache(struct bSound *sound); void BKE_sound_delete_cache(struct bSound *sound); +void BKE_sound_reset_runtime(struct bSound *sound); void BKE_sound_load(struct Main *main, struct bSound *sound); +void BKE_sound_ensure_loaded(struct Main *bmain, struct bSound *sound); void BKE_sound_free(struct bSound *sound); +/* Is used by sequencer to temporarily load audio to access information about channels and + * duration. */ +void BKE_sound_load_audio(struct Main *main, struct bSound *sound); +void BKE_sound_free_audio(struct bSound *sound); + void BKE_sound_copy_data(struct Main *bmain, struct bSound *sound_dst, const struct bSound *sound_src, @@ -86,7 +94,9 @@ void BKE_sound_make_local(struct Main *bmain, struct bSound *sound, const bool l AUD_Device *BKE_sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume); #endif +void BKE_sound_reset_scene_runtime(struct Scene *scene); void BKE_sound_create_scene(struct Scene *scene); +void BKE_sound_ensure_scene(struct Scene *scene); void BKE_sound_destroy_scene(struct Scene *scene); @@ -150,4 +160,15 @@ float BKE_sound_get_length(struct bSound *sound); char **BKE_sound_get_device_names(void); +typedef void (*SoundJackSyncCallback)(struct Main *bmain, int mode, float time); + +void BKE_sound_jack_sync_callback_set(SoundJackSyncCallback callback); +void BKE_sound_jack_scene_update(struct Scene *scene, int mode, float time); + +/* Dependency graph evaluation. */ + +struct Depsgraph; + +void BKE_sound_evaluate(struct Depsgraph *depsgraph, struct Main *bmain, struct bSound *sound); + #endif /* __BKE_SOUND_H__ */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index d17990d4bee..9fcbf209cba 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -37,6 +37,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_sequence_types.h" +#include "DNA_sound_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" @@ -308,8 +309,7 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons flag_subdata); } - /* before scene copy */ - BKE_sound_create_scene(sce_dst); + BKE_sound_reset_scene_runtime(sce_dst); /* Copy sequencer, this is local data! */ if (sce_src->ed) { @@ -399,8 +399,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) sce_copy->r.ffcodecdata.properties = IDP_CopyProperty(sce->r.ffcodecdata.properties); } - /* before scene copy */ - BKE_sound_create_scene(sce_copy); + BKE_sound_reset_scene_runtime(sce_copy); /* grease pencil */ sce_copy->gpd = NULL; @@ -779,7 +778,7 @@ void BKE_scene_init(Scene *sce) srv = sce->r.views.last; BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix)); - BKE_sound_create_scene(sce); + BKE_sound_reset_scene_runtime(sce); /* color management */ colorspace_name = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_SEQUENCER); @@ -1507,6 +1506,30 @@ static void prepare_mesh_for_viewport_render(Main *bmain, const ViewLayer *view_ } } +static void scene_update_sound(Depsgraph *depsgraph, Main *bmain) +{ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + const int recalc = scene->id.recalc; + BKE_sound_ensure_scene(scene); + if (recalc & ID_RECALC_AUDIO_SEEK) { + BKE_sound_seek_scene(bmain, scene); + } + if (recalc & ID_RECALC_AUDIO_FPS) { + BKE_sound_update_fps(scene); + } + if (recalc & ID_RECALC_AUDIO_VOLUME) { + BKE_sound_set_scene_volume(scene, scene->audio.volume); + } + if (recalc & ID_RECALC_AUDIO_MUTE) { + const bool is_mute = (scene->audio.flag & AUDIO_MUTE); + BKE_sound_mute_scene(scene, is_mute); + } + if (recalc & ID_RECALC_AUDIO_LISTENER) { + BKE_sound_update_scene_listener(scene); + } + BKE_sound_update_scene(bmain, scene); +} + /* TODO(sergey): This actually should become view_layer_graph or so. * Same applies to update_for_newframe. * @@ -1542,10 +1565,9 @@ static void scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain, bool on * by depgraph or manual, no layer check here, gets correct flushed. */ DEG_evaluate_on_refresh(depsgraph); - /* Update sound system animation (TODO, move to depsgraph). */ - BKE_sound_update_scene(bmain, scene); - - /* Notify python about depsgraph update */ + /* Update sound system. */ + scene_update_sound(depsgraph, bmain); + /* Notify python about depsgraph update. */ if (run_callbacks) { BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_DEPSGRAPH_UPDATE_POST); } @@ -1590,8 +1612,8 @@ void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph, Main *bmain) * by depgraph or manual, no layer check here, gets correct flushed. */ DEG_evaluate_on_framechange(bmain, depsgraph, ctime); - /* Update sound system animation (TODO, move to depsgraph). */ - BKE_sound_update_scene(bmain, scene); + /* Update sound system animation. */ + scene_update_sound(depsgraph, bmain); /* Notify editors and python about recalc. */ BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_FRAME_CHANGE_POST); /* Inform editors about possible changes. */ @@ -2420,3 +2442,31 @@ void BKE_scene_cursor_from_mat4(View3DCursor *cursor, const float mat[4][4], boo } /** \} */ + +/* Dependency graph evaluation. */ + +void BKE_scene_eval_sequencer_sequences(Depsgraph *depsgraph, Scene *scene) +{ + DEG_debug_print_eval(depsgraph, __func__, scene->id.name, scene); + if (scene->ed == NULL) { + return; + } + BKE_sound_ensure_scene(scene); + Sequence *seq; + SEQ_BEGIN (scene->ed, seq) { + if (seq->sound != NULL && seq->scene_sound == NULL) { + seq->scene_sound = BKE_sound_add_scene_sound_defaults(scene, seq); + } + if (seq->scene_sound) { + BKE_sound_set_scene_sound_volume( + seq->scene_sound, seq->volume, (seq->flag & SEQ_AUDIO_VOLUME_ANIMATED) != 0); + BKE_sound_set_scene_sound_pitch( + seq->scene_sound, seq->pitch, (seq->flag & SEQ_AUDIO_PITCH_ANIMATED) != 0); + BKE_sound_set_scene_sound_pan( + seq->scene_sound, seq->pan, (seq->flag & SEQ_AUDIO_PAN_ANIMATED) != 0); + } + } + SEQ_END; + BKE_sequencer_update_muting(scene->ed); + BKE_sequencer_update_sound_bounds_all(scene); +} diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index ec8a2520461..171635cc6b5 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -808,10 +808,7 @@ void BKE_sequence_calc_disp(Scene *scene, Sequence *seq) seq->handsize = (float)((seq->enddisp - seq->startdisp) / 25); } - if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { - BKE_sequencer_update_sound_bounds(scene, seq); - } - else if (seq->type == SEQ_TYPE_META) { + if (seq->type == SEQ_TYPE_META) { seq_update_sound_bounds_recursive(scene, seq); } } @@ -5505,17 +5502,18 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad Strip *strip; StripElem *se; - AUD_SoundInfo info; - sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */ + /* Load the original sound, so we can access number of channels and length information. + * We free the sound handle on the original bSound datablock before existing this function, it is + * to be allocated on an evaluated version after this. */ + BKE_sound_load_audio(bmain, sound); + AUD_SoundInfo info = AUD_getInfo(sound->playback_handle); if (sound->playback_handle == NULL) { BKE_id_free(bmain, sound); return NULL; } - info = AUD_getInfo(sound->playback_handle); - if (info.specs.channels == AUD_CHANNELS_INVALID) { BKE_id_free(bmain, sound); return NULL; @@ -5537,8 +5535,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); - seq->scene_sound = BKE_sound_add_scene_sound( - scene, seq, seq_load->start_frame, seq_load->start_frame + seq->len, 0); + seq->scene_sound = NULL; BKE_sequence_calc_disp(scene, seq); @@ -5547,6 +5544,11 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad seq_load_apply(bmain, scene, seq, seq_load); + BKE_sound_free_audio(sound); + + /* TODO(sergey): Shall we tag here or in the oeprator? */ + DEG_relations_tag_update(bmain); + return seq; } #else // WITH_AUDASPACE @@ -5755,10 +5757,7 @@ static Sequence *seq_dupli(const Scene *scene_src, } else if (seq->type == SEQ_TYPE_SOUND_RAM) { seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); - if (seq->scene_sound) { - seqn->scene_sound = BKE_sound_add_scene_sound_defaults(scene_dst, seqn); - } - + seqn->scene_sound = NULL; if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { id_us_plus((ID *)seqn->sound); } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 0cd51766078..13aedf60cd0 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -38,6 +38,7 @@ #include "DNA_screen_types.h" #include "DNA_sound_types.h" #include "DNA_speaker_types.h" +#include "DNA_windowmanager_types.h" #ifdef WITH_AUDASPACE # include <AUD_Sound.h> @@ -55,12 +56,36 @@ #include "BKE_sequencer.h" #include "BKE_scene.h" +#include "DEG_depsgraph.h" + #ifdef WITH_AUDASPACE /* evil globals ;-) */ static int sound_cfra; static char **audio_device_names = NULL; #endif +BLI_INLINE void sound_verify_evaluated_id(ID *id) +{ + UNUSED_VARS_NDEBUG(id); + /* This is a bit tricky and not quite reliable, but good enough check. + * + * We don't want audio system handles to be allocated on amn original datablocks, and only want + * them to be allocated on a datablocks which are result of dependency graph evaluation. + * + * Datablocks which are covered by a copy-on-write system of dependency graph will have + * LIB_TAG_COPIED_ON_WRITE tag set on them. But if some of datablocks during its evaluation + * decides to re-allocate it's nested one (for example, object evaluation could re-allocate mesh + * when evaluating modifier stack). Such datablocks will have LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT + * tag set on them. + * + * Additionally, we also allow datablocks outside of main database. Those can not be "original" + * and could be used as a temporary evaluated result during operations like baking. + * + * NOTE: We conder ID evaluated if ANY of those flags is set. We do NOT require ALL of them. */ + BLI_assert(id->tag & + (LIB_TAG_COPIED_ON_WRITE | LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT | LIB_TAG_NO_MAIN)); +} + bSound *BKE_sound_new_file(Main *bmain, const char *filepath) { bSound *sound; @@ -77,7 +102,10 @@ bSound *BKE_sound_new_file(Main *bmain, const char *filepath) BLI_strncpy(sound->name, filepath, FILE_MAX); /* sound->type = SOUND_TYPE_FILE; */ /* XXX unused currently */ - BKE_sound_load(bmain, sound); + sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); + BLI_spin_init(sound->spinlock); + + BKE_sound_reset_runtime(sound); return sound; } @@ -125,6 +153,18 @@ void BKE_sound_free(bSound *sound) sound->packedfile = NULL; } + BKE_sound_free_audio(sound); + BKE_sound_free_waveform(sound); + + if (sound->spinlock) { + BLI_spin_end(sound->spinlock); + MEM_freeN(sound->spinlock); + sound->spinlock = NULL; + } +} + +void BKE_sound_free_audio(bSound *sound) +{ #ifdef WITH_AUDASPACE if (sound->handle) { AUD_Sound_free(sound->handle); @@ -136,15 +176,9 @@ void BKE_sound_free(bSound *sound) AUD_Sound_free(sound->cache); sound->cache = NULL; } - - BKE_sound_free_waveform(sound); - +#else + UNUSED_VARS(sound); #endif /* WITH_AUDASPACE */ - if (sound->spinlock) { - BLI_spin_end(sound->spinlock); - MEM_freeN(sound->spinlock); - sound->spinlock = NULL; - } } /** @@ -157,7 +191,7 @@ void BKE_sound_free(bSound *sound) * * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). */ -void BKE_sound_copy_data(Main *bmain, +void BKE_sound_copy_data(Main *UNUSED(bmain), bSound *sound_dst, const bSound *UNUSED(sound_src), const int UNUSED(flag)) @@ -166,8 +200,8 @@ void BKE_sound_copy_data(Main *bmain, sound_dst->cache = NULL; sound_dst->waveform = NULL; sound_dst->playback_handle = NULL; - sound_dst->spinlock = - NULL; /* Think this is OK? Otherwise, easy to create new spinlock here... */ + sound_dst->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); + BLI_spin_init(sound_dst->spinlock); /* Just to be sure, should not have any value actually after reading time. */ sound_dst->ipo = NULL; @@ -177,8 +211,7 @@ void BKE_sound_copy_data(Main *bmain, sound_dst->packedfile = dupPackedFile(sound_dst->packedfile); } - /* Initialize whole runtime (audaspace) stuff. */ - BKE_sound_load(bmain, sound_dst); + BKE_sound_reset_runtime(sound_dst); } void BKE_sound_make_local(Main *bmain, bSound *sound, const bool lib_local) @@ -191,31 +224,15 @@ void BKE_sound_make_local(Main *bmain, bSound *sound, const bool lib_local) static const char *force_device = NULL; # ifdef WITH_JACK +static SoundJackSyncCallback sound_jack_sync_callback = NULL; + static void sound_sync_callback(void *data, int mode, float time) { - // Ugly: Blender doesn't like it when the animation is played back during rendering - if (G.is_rendering) { + if (sound_jack_sync_callback == NULL) { return; } - Main *bmain = (Main *)data; - Scene *scene; - - scene = bmain->scenes.first; - while (scene) { - if (scene->audio.flag & AUDIO_SYNC) { - if (mode) { - BKE_sound_play_scene(scene); - } - else { - BKE_sound_stop_scene(scene); - } - if (scene->playback_handle) { - AUD_Handle_setPosition(scene->playback_handle, time); - } - } - scene = scene->id.next; - } + sound_jack_sync_callback(bmain, mode, time); } # endif @@ -298,7 +315,7 @@ void BKE_sound_init_main(Main *bmain) AUD_setSynchronizerCallback(sound_sync_callback, bmain); } # else - (void)bmain; /* unused */ + UNUSED_VARS(bmain); # endif } @@ -367,6 +384,8 @@ bSound *BKE_sound_new_limiter(Main *bmain, bSound *source, float start, float en void BKE_sound_cache(bSound *sound) { + sound_verify_evaluated_id(&sound->id); + sound->flags |= SOUND_FLAGS_CACHING; if (sound->cache) { AUD_Sound_free(sound->cache); @@ -393,44 +412,50 @@ void BKE_sound_delete_cache(bSound *sound) void BKE_sound_load(Main *bmain, bSound *sound) { - if (sound) { - if (sound->cache) { - AUD_Sound_free(sound->cache); - sound->cache = NULL; - } + sound_verify_evaluated_id(&sound->id); + BKE_sound_load_audio(bmain, sound); +} - if (sound->handle) { - AUD_Sound_free(sound->handle); - sound->handle = NULL; - sound->playback_handle = NULL; - } +void BKE_sound_load_audio(Main *bmain, bSound *sound) +{ + + if (sound->cache) { + AUD_Sound_free(sound->cache); + sound->cache = NULL; + } + + if (sound->handle) { + AUD_Sound_free(sound->handle); + sound->handle = NULL; + sound->playback_handle = NULL; + } - BKE_sound_free_waveform(sound); + BKE_sound_free_waveform(sound); /* XXX unused currently */ # if 0 switch (sound->type) { case SOUND_TYPE_FILE: # endif - { - char fullpath[FILE_MAX]; + { + char fullpath[FILE_MAX]; - /* load sound */ - PackedFile *pf = sound->packedfile; + /* load sound */ + PackedFile *pf = sound->packedfile; - /* don't modify soundact->sound->name, only change a copy */ - BLI_strncpy(fullpath, sound->name, sizeof(fullpath)); - BLI_path_abs(fullpath, ID_BLEND_PATH(bmain, &sound->id)); + /* don't modify soundact->sound->name, only change a copy */ + BLI_strncpy(fullpath, sound->name, sizeof(fullpath)); + BLI_path_abs(fullpath, ID_BLEND_PATH(bmain, &sound->id)); - /* but we need a packed file then */ - if (pf) { - sound->handle = AUD_Sound_bufferFile((unsigned char *)pf->data, pf->size); - } - else { - /* or else load it from disk */ - sound->handle = AUD_Sound_file(fullpath); - } + /* but we need a packed file then */ + if (pf) { + sound->handle = AUD_Sound_bufferFile((unsigned char *)pf->data, pf->size); } + else { + /* or else load it from disk */ + sound->handle = AUD_Sound_file(fullpath); + } + } /* XXX unused currently */ # if 0 break; @@ -447,34 +472,34 @@ void BKE_sound_load(Main *bmain, bSound *sound) break; } # endif - if (sound->flags & SOUND_FLAGS_MONO) { - void *handle = AUD_Sound_rechannel(sound->handle, AUD_CHANNELS_MONO); - AUD_Sound_free(sound->handle); - sound->handle = handle; - } - - if (sound->flags & SOUND_FLAGS_CACHING) { - sound->cache = AUD_Sound_cache(sound->handle); - } + if (sound->flags & SOUND_FLAGS_MONO) { + void *handle = AUD_Sound_rechannel(sound->handle, AUD_CHANNELS_MONO); + AUD_Sound_free(sound->handle); + sound->handle = handle; + } - if (sound->cache) { - sound->playback_handle = sound->cache; - } - else { - sound->playback_handle = sound->handle; - } + if (sound->flags & SOUND_FLAGS_CACHING) { + sound->cache = AUD_Sound_cache(sound->handle); + } - BKE_sound_update_sequencer(bmain, sound); + if (sound->cache) { + sound->playback_handle = sound->cache; + } + else { + sound->playback_handle = sound->handle; } } AUD_Device *BKE_sound_mixdown(Scene *scene, AUD_DeviceSpecs specs, int start, float volume) { + sound_verify_evaluated_id(&scene->id); return AUD_openMixdownDevice(specs, scene->sound_scene, volume, start / FPS); } void BKE_sound_create_scene(Scene *scene) { + sound_verify_evaluated_id(&scene->id); + /* should be done in version patch, but this gets called before */ if (scene->r.frs_sec_base == 0) { scene->r.frs_sec_base = 1; @@ -507,16 +532,21 @@ void BKE_sound_destroy_scene(Scene *scene) void BKE_sound_reset_scene_specs(Scene *scene) { - AUD_Specs specs; + sound_verify_evaluated_id(&scene->id); + + if (scene->sound_scene) { + AUD_Specs specs; - specs.channels = AUD_Device_getChannels(sound_device); - specs.rate = AUD_Device_getRate(sound_device); + specs.channels = AUD_Device_getChannels(sound_device); + specs.rate = AUD_Device_getRate(sound_device); - AUD_Sequence_setSpecs(scene->sound_scene, specs); + AUD_Sequence_setSpecs(scene->sound_scene, specs); + } } void BKE_sound_mute_scene(Scene *scene, int muted) { + sound_verify_evaluated_id(&scene->id); if (scene->sound_scene) { AUD_Sequence_setMuted(scene->sound_scene, muted); } @@ -524,6 +554,8 @@ void BKE_sound_mute_scene(Scene *scene, int muted) void BKE_sound_update_fps(Scene *scene) { + sound_verify_evaluated_id(&scene->id); + if (scene->sound_scene) { AUD_Sequence_setFPS(scene->sound_scene, FPS); } @@ -533,6 +565,8 @@ void BKE_sound_update_fps(Scene *scene) void BKE_sound_update_scene_listener(Scene *scene) { + sound_verify_evaluated_id(&scene->id); + AUD_Sequence_setSpeedOfSound(scene->sound_scene, scene->audio.speed_of_sound); AUD_Sequence_setDopplerFactor(scene->sound_scene, scene->audio.doppler_factor); AUD_Sequence_setDistanceModel(scene->sound_scene, scene->audio.distance_model); @@ -541,6 +575,7 @@ void BKE_sound_update_scene_listener(Scene *scene) void *BKE_sound_scene_add_scene_sound( Scene *scene, Sequence *sequence, int startframe, int endframe, int frameskip) { + sound_verify_evaluated_id(&scene->id); if (sequence->scene && scene != sequence->scene) { const double fps = FPS; return AUD_Sequence_add(scene->sound_scene, @@ -564,6 +599,7 @@ void *BKE_sound_scene_add_scene_sound_defaults(Scene *scene, Sequence *sequence) void *BKE_sound_add_scene_sound( Scene *scene, Sequence *sequence, int startframe, int endframe, int frameskip) { + sound_verify_evaluated_id(&scene->id); /* Happens when sequence's sound datablock was removed. */ if (sequence->sound == NULL) { return NULL; @@ -603,12 +639,14 @@ void BKE_sound_mute_scene_sound(void *handle, char mute) void BKE_sound_move_scene_sound( Scene *scene, void *handle, int startframe, int endframe, int frameskip) { + sound_verify_evaluated_id(&scene->id); const double fps = FPS; AUD_SequenceEntry_move(handle, startframe / fps, endframe / fps, frameskip / fps); } void BKE_sound_move_scene_sound_defaults(Scene *scene, Sequence *sequence) { + sound_verify_evaluated_id(&scene->id); if (sequence->scene_sound) { BKE_sound_move_scene_sound(scene, sequence->scene_sound, @@ -630,6 +668,7 @@ void BKE_sound_set_cfra(int cfra) void BKE_sound_set_scene_volume(Scene *scene, float volume) { + sound_verify_evaluated_id(&scene->id); AUD_Sequence_setAnimationData(scene->sound_scene, AUD_AP_VOLUME, CFRA, @@ -649,12 +688,13 @@ void BKE_sound_set_scene_sound_pitch(void *handle, float pitch, char animated) void BKE_sound_set_scene_sound_pan(void *handle, float pan, char animated) { - printf("%s\n", __func__); AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PANNING, sound_cfra, &pan, animated); } void BKE_sound_update_sequencer(Main *main, bSound *sound) { + BLI_assert(!"is not supposed to be used, is weird function."); + Scene *scene; for (scene = main->scenes.first; scene; scene = scene->id.next) { @@ -664,6 +704,8 @@ void BKE_sound_update_sequencer(Main *main, bSound *sound) static void sound_start_play_scene(Scene *scene) { + sound_verify_evaluated_id(&scene->id); + if (scene->playback_handle) { AUD_Handle_stop(scene->playback_handle); } @@ -677,6 +719,8 @@ static void sound_start_play_scene(Scene *scene) void BKE_sound_play_scene(Scene *scene) { + sound_verify_evaluated_id(&scene->id); + AUD_Status status; const float cur_time = (float)((double)CFRA / FPS); @@ -719,6 +763,8 @@ void BKE_sound_stop_scene(Scene *scene) void BKE_sound_seek_scene(Main *bmain, Scene *scene) { + sound_verify_evaluated_id(&scene->id); + AUD_Status status; bScreen *screen; int animation_playing; @@ -783,6 +829,8 @@ void BKE_sound_seek_scene(Main *bmain, Scene *scene) float BKE_sound_sync_scene(Scene *scene) { + sound_verify_evaluated_id(&scene->id); + // Ugly: Blender doesn't like it when the animation is played back during rendering if (G.is_rendering) { return NAN_FLT; @@ -801,6 +849,8 @@ float BKE_sound_sync_scene(Scene *scene) int BKE_sound_scene_playing(Scene *scene) { + sound_verify_evaluated_id(&scene->id); + // Ugly: Blender doesn't like it when the animation is played back during rendering if (G.is_rendering) { return -1; @@ -836,6 +886,9 @@ void BKE_sound_free_waveform(bSound *sound) sound->tags &= ~SOUND_TAGS_WAVEFORM_NO_RELOAD; } +/* TODO(sergey): Consider mamakinging this function fully autonomous, as in, not require having + * an existing playback handle. That would make it easy to read waveforms, which doesn't seem to + * be affected by evaluated scene (waveworm comes from file). */ void BKE_sound_read_waveform(bSound *sound, short *stop) { AUD_SoundInfo info = AUD_getInfo(sound->playback_handle); @@ -884,11 +937,14 @@ static void sound_update_base(Scene *scene, Base *base, void *new_set) Speaker *speaker; float quat[4]; - if ((ob->id.tag & LIB_TAG_DOIT) == 0) { - return; - } + sound_verify_evaluated_id(&scene->id); + sound_verify_evaluated_id(&ob->id); - ob->id.tag &= ~LIB_TAG_DOIT; + // TODO(sergey): Bring the test back, or make it a part of dependency graph update. + // if ((ob->id.tag & LIB_TAG_DOIT) == 0) { + // return; + // } + // ob->id.tag &= ~LIB_TAG_DOIT; if ((ob->type != OB_SPEAKER) || !ob->adt) { return; @@ -951,6 +1007,8 @@ static void sound_update_base(Scene *scene, Base *base, void *new_set) void BKE_sound_update_scene(Main *bmain, Scene *scene) { + sound_verify_evaluated_id(&scene->id); + Base *base; Scene *sce_it; @@ -960,7 +1018,8 @@ void BKE_sound_update_scene(Main *bmain, Scene *scene) /* cheap test to skip looping over all objects (no speakers is a common case) */ if (!BLI_listbase_is_empty(&bmain->speakers)) { - BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, true); + // TODO(sergey): Bring the test back, or make it a part of dependency graph update. + // BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, true); for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { @@ -997,6 +1056,7 @@ void *BKE_sound_get_factory(void *sound) /* stupid wrapper because AUD_C-API.h includes Python.h which makesrna doesn't like */ float BKE_sound_get_length(bSound *sound) { + sound_verify_evaluated_id(&sound->id); AUD_SoundInfo info = AUD_getInfo(sound->playback_handle); return info.length; @@ -1159,4 +1219,81 @@ char **BKE_sound_get_device_names(void) return names; } +void BKE_sound_free_waveform(bSound *UNUSED(sound)) +{ +} + +void BKE_sound_load_audio(Main *UNUSED(bmain), bSound *UNUSED(sound)) +{ +} + #endif /* WITH_AUDASPACE */ + +void BKE_sound_reset_scene_runtime(Scene *scene) +{ + scene->sound_scene = NULL; + scene->playback_handle = NULL; + scene->sound_scrub_handle = NULL; + scene->speaker_handles = NULL; +} + +void BKE_sound_ensure_scene(struct Scene *scene) +{ + if (scene->sound_scene != NULL) { + return; + } + BKE_sound_create_scene(scene); +} + +void BKE_sound_reset_runtime(bSound *sound) +{ + sound->cache = NULL; + sound->playback_handle = NULL; +} + +void BKE_sound_ensure_loaded(Main *bmain, bSound *sound) +{ + if (sound->cache != NULL) { + return; + } + BKE_sound_load(bmain, sound); +} + +void BKE_sound_jack_sync_callback_set(SoundJackSyncCallback callback) +{ +#if defined(WITH_AUDASPACE) && defined(WITH_JACK) + sound_jack_sync_callback = callback; +#else + UNUSED_VARS(callback); +#endif +} + +void BKE_sound_jack_scene_update(Scene *scene, int mode, float time) +{ + sound_verify_evaluated_id(&scene->id); + + /* Ugly: Blender doesn't like it when the animation is played back during rendering. */ + if (G.is_rendering) { + return; + } + + if (mode) { + BKE_sound_play_scene(scene); + } + else { + BKE_sound_stop_scene(scene); + } +#ifdef WITH_AUDASPACE + if (scene->playback_handle != NULL) { + AUD_Handle_setPosition(scene->playback_handle, time); + } +#else + UNUSED_VARS(time); +#endif +} + +void BKE_sound_evaluate(Depsgraph *depsgraph, Main *bmain, bSound *sound) +{ + DEG_debug_print_eval(depsgraph, __func__, sound->id.name, sound); + BKE_sound_ensure_loaded(bmain, sound); +} diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 32f0d35cd53..a4bdf02c838 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6462,9 +6462,7 @@ static void lib_link_scene(FileData *fd, Main *main) seq->scene_sound = NULL; if (seq->scene) { seq->scene = newlibadr(fd, sce->id.lib, seq->scene); - if (seq->scene) { - seq->scene_sound = BKE_sound_scene_add_scene_sound_defaults(sce, seq); - } + seq->scene_sound = NULL; } if (seq->clip) { seq->clip = newlibadr_us(fd, sce->id.lib, seq->clip); @@ -6485,7 +6483,7 @@ static void lib_link_scene(FileData *fd, Main *main) } if (seq->sound) { id_us_plus_no_lib((ID *)seq->sound); - seq->scene_sound = BKE_sound_add_scene_sound_defaults(sce, seq); + seq->scene_sound = NULL; } } if (seq->type == SEQ_TYPE_TEXT) { @@ -6504,9 +6502,6 @@ static void lib_link_scene(FileData *fd, Main *main) } } - BKE_sequencer_update_muting(sce->ed); - BKE_sequencer_update_sound_bounds_all(sce); - /* rigidbody world relies on it's linked collections */ if (sce->rigidbody_world) { RigidBodyWorld *rbw = sce->rigidbody_world; @@ -6685,7 +6680,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) memset(&sce->customdata_mask, 0, sizeof(sce->customdata_mask)); memset(&sce->customdata_mask_modal, 0, sizeof(sce->customdata_mask_modal)); - BKE_sound_create_scene(sce); + BKE_sound_reset_scene_runtime(sce); /* set users to one by default, not in lib-link, this will increase it for compo nodes */ id_us_ensure_real(&sce->id); @@ -8395,10 +8390,9 @@ static void direct_link_sound(FileData *fd, bSound *sound) sound->waveform = NULL; } - if (sound->spinlock) { - sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); - BLI_spin_init(sound->spinlock); - } + sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); + BLI_spin_init(sound->spinlock); + /* clear waveform loading flag */ sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING; @@ -8415,7 +8409,7 @@ static void lib_link_sound(FileData *fd, Main *main) sound->ipo = newlibadr_us( fd, sound->id.lib, sound->ipo); // XXX deprecated - old animation system - BKE_sound_load(main, sound); + BKE_sound_reset_runtime(sound); sound->id.tag &= ~LIB_TAG_NEED_LINK; } diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h index 48a62a69f30..cc6c5e7282a 100644 --- a/source/blender/depsgraph/DEG_depsgraph_query.h +++ b/source/blender/depsgraph/DEG_depsgraph_query.h @@ -85,6 +85,16 @@ void DEG_get_customdata_mask_for_object(const struct Depsgraph *graph, * one. Assert will happen if it's not. */ struct Scene *DEG_get_evaluated_scene(const struct Depsgraph *graph); +/* Similar to DEG_get_evaluated_scene(), but allows to access non-fully evaluated pointer without + * causing asserts or crashes. Works the following way: + * - If the scene was never evaluated NULL returned. + * - Otherwise the last known state of the scene is returned. + * + * Use in exceptional case if it's absolutely must to. + * + * Allows to pass depsgraph == NULL, wil lreturn NULL in that case. */ +struct Scene *DEG_get_evaluated_scene_if_exists(const struct Depsgraph *graph); + /* Get view layer at its evaluated state. * This is a shortcut for accessing active view layer from evaluated scene. */ struct ViewLayer *DEG_get_evaluated_view_layer(const struct Depsgraph *graph); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 93e5dd14ae0..9bdc815518d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -58,6 +58,7 @@ extern "C" { #include "DNA_lightprobe_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" +#include "DNA_sequence_types.h" #include "DNA_sound_types.h" #include "DNA_speaker_types.h" #include "DNA_texture_types.h" @@ -89,6 +90,8 @@ extern "C" { #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_rigidbody.h" +#include "BKE_scene.h" +#include "BKE_sequencer.h" #include "BKE_shader_fx.h" #include "BKE_sound.h" #include "BKE_tracking.h" @@ -1564,12 +1567,42 @@ void DepsgraphNodeBuilder::build_sound(bSound *sound) if (built_map_.checkIsBuiltAndTag(sound)) { return; } - /* Placeholder so we can add relations and tag ID node for update. */ - add_operation_node(&sound->id, NodeType::AUDIO, OperationCode::SOUND_EVAL); + add_id_node(&sound->id); + bSound *sound_cow = get_cow_datablock(sound); + add_operation_node(&sound->id, + NodeType::AUDIO, + OperationCode::SOUND_EVAL, + function_bind(BKE_sound_evaluate, _1, bmain_, sound_cow)); build_animdata(&sound->id); build_parameters(&sound->id); } +void DepsgraphNodeBuilder::build_scene_sequencer(Scene *scene) +{ + if (scene->ed == NULL) { + return; + } + Scene *scene_cow = get_cow_datablock(scene_); + add_operation_node(&scene->id, + NodeType::SEQUENCER, + OperationCode::SEQUENCES_EVAL, + function_bind(BKE_scene_eval_sequencer_sequences, _1, scene_cow)); + /* Make sure data for sequences is in the graph. */ + Sequence *seq; + SEQ_BEGIN (scene->ed, seq) { + if (seq->sound != NULL) { + build_sound(seq->sound); + } + /* TODO(sergey): Movie clip, scene, camera, mask. */ + } + SEQ_END; +} + +void DepsgraphNodeBuilder::build_scene_audio(Scene *scene) +{ + add_operation_node(&scene->id, NodeType::AUDIO, OperationCode::SOUND_EVAL); +} + /* **** ID traversal callbacks functions **** */ void DepsgraphNodeBuilder::modifier_walk(void *user_data, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index c3a04a9ad88..896854870de 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -212,6 +212,8 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { void build_lightprobe(LightProbe *probe); void build_speaker(Speaker *speaker); void build_sound(bSound *sound); + void build_scene_sequencer(Scene *scene); + void build_scene_audio(Scene *scene); /* Per-ID information about what was already in the dependency graph. * Allows to re-use certain values, to speed up following evaluation. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc index 64f841d56fc..ef73de517e8 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc @@ -31,13 +31,19 @@ void DepsgraphNodeBuilder::build_scene_render(Scene *scene) { scene_ = scene; const bool build_compositor = (scene->r.scemode & R_DOCOMP); + const bool build_sequencer = (scene->r.scemode & R_DOSEQ); IDNode *id_node = add_id_node(&scene->id); id_node->linked_state = DEG_ID_LINKED_DIRECTLY; add_time_source(); + build_animdata(&scene->id); build_scene_parameters(scene); + build_scene_audio(scene); if (build_compositor) { build_scene_compositor(scene); } + if (build_sequencer) { + build_scene_sequencer(scene); + } } void DepsgraphNodeBuilder::build_scene_parameters(Scene *scene) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index 4e3fdfc6c19..2f6b8c0ba6b 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -146,6 +146,11 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene, build_collection(NULL, fls->group); } } + /* Sequencer. */ + if (linked_state == DEG_ID_LINKED_DIRECTLY) { + build_scene_audio(scene); + build_scene_sequencer(scene); + } /* Collections. */ add_operation_node( &scene->id, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 54d5223497e..a1f8c59f936 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -58,6 +58,7 @@ extern "C" { #include "DNA_object_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" +#include "DNA_sequence_types.h" #include "DNA_sound_types.h" #include "DNA_speaker_types.h" #include "DNA_texture_types.h" @@ -84,6 +85,7 @@ extern "C" { #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_rigidbody.h" +#include "BKE_sequencer.h" #include "BKE_shader_fx.h" #include "BKE_shrinkwrap.h" #include "BKE_sound.h" @@ -2324,6 +2326,35 @@ void DepsgraphRelationBuilder::build_sound(bSound *sound) build_parameters(&sound->id); } +void DepsgraphRelationBuilder::build_scene_sequencer(Scene *scene) +{ + if (scene->ed == NULL) { + return; + } + /* Make sure dependencies from sequences data goes to the sequencer evaluation. */ + ComponentKey sequencer_key(&scene->id, NodeType::SEQUENCER); + Sequence *seq; + bool has_audio_strips = false; + SEQ_BEGIN (scene->ed, seq) { + if (seq->sound != NULL) { + build_sound(seq->sound); + ComponentKey sound_key(&seq->sound->id, NodeType::AUDIO); + add_relation(sound_key, sequencer_key, "Sound -> Sequencer"); + has_audio_strips = true; + } + /* TODO(sergey): Movie clip, scene, camera, mask. */ + } + SEQ_END; + if (has_audio_strips) { + ComponentKey scene_audio_key(&scene->id, NodeType::AUDIO); + add_relation(sequencer_key, scene_audio_key, "Sequencer -> Audio"); + } +} + +void DepsgraphRelationBuilder::build_scene_audio(Scene * /*scene*/) +{ +} + void DepsgraphRelationBuilder::build_copy_on_write_relations() { for (IDNode *id_node : graph_->id_nodes) { @@ -2387,6 +2418,10 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) (id_type == ID_CF && comp_node->type == NodeType::CACHE)) { rel_flag &= ~RELATION_FLAG_NO_FLUSH; } + /* TODO(sergey): Needs better solution for this. */ + if (id_type == ID_SO) { + rel_flag &= ~RELATION_FLAG_NO_FLUSH; + } /* Notes on exceptions: * - Parameters component is where drivers are living. Changing any * of the (custom) properties in the original datablock (even the diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 7d302092119..55295c8b075 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -41,6 +41,7 @@ #include "intern/builder/deg_builder_rna.h" #include "intern/depsgraph.h" #include "intern/node/deg_node.h" +#include "intern/node/deg_node_id.h" #include "intern/node/deg_node_component.h" #include "intern/node/deg_node_operation.h" @@ -200,7 +201,9 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder { void build_scene_compositor(Scene *scene); void build_layer_collections(ListBase *lb); - void build_view_layer(Scene *scene, ViewLayer *view_layer); + void build_view_layer(Scene *scene, + ViewLayer *view_layer, + eDepsNode_LinkedState_Type linked_state); void build_collection(LayerCollection *from_layer_collection, Object *object, Collection *collection); @@ -270,6 +273,8 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder { void build_lightprobe(LightProbe *probe); void build_speaker(Speaker *speaker); void build_sound(bSound *sound); + void build_scene_sequencer(Scene *scene); + void build_scene_audio(Scene *scene); void build_nested_datablock(ID *owner, ID *id); void build_nested_nodetree(ID *owner, bNodeTree *ntree); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc index 26bb1bd3d2a..46e8b8e7acc 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc @@ -31,10 +31,16 @@ void DepsgraphRelationBuilder::build_scene_render(Scene *scene) { scene_ = scene; const bool build_compositor = (scene->r.scemode & R_DOCOMP); + const bool build_sequencer = (scene->r.scemode & R_DOSEQ); build_scene_parameters(scene); + build_animdata(&scene->id); + build_scene_audio(scene); if (build_compositor) { build_scene_compositor(scene); } + if (build_sequencer) { + build_scene_sequencer(scene); + } } void DepsgraphRelationBuilder::build_scene_parameters(Scene *scene) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc index b832473bde9..4c55e4a137a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc @@ -75,7 +75,9 @@ void DepsgraphRelationBuilder::build_layer_collections(ListBase *lb) } } -void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_layer) +void DepsgraphRelationBuilder::build_view_layer(Scene *scene, + ViewLayer *view_layer, + eDepsNode_LinkedState_Type linked_state) { /* Setup currently building context. */ scene_ = scene; @@ -132,10 +134,15 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la &scene->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL); OperationKey scene_eval_key(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL); add_relation(scene_view_layer_key, scene_eval_key, "View Layer -> Scene Eval"); + /* Sequencer. */ + if (linked_state == DEG_ID_LINKED_DIRECTLY) { + build_scene_audio(scene); + build_scene_sequencer(scene); + } /* Build all set scenes. */ if (scene->set != NULL) { ViewLayer *set_view_layer = BKE_view_layer_default_render(scene->set); - build_view_layer(scene->set, set_view_layer); + build_view_layer(scene->set, set_view_layer, DEG_ID_LINKED_VIA_SET); } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index 403c9cfc778..b7efdc0fa3f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -329,10 +329,8 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, return node_identifier; } else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) { - const Sequence *seq = static_cast<Sequence *>(ptr->data); /* Sequencer strip */ node_identifier.type = NodeType::SEQUENCER; - node_identifier.component_name = seq->name; return node_identifier; } else if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) { diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index cf1ebccc6c6..bfb0a2aade4 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -272,7 +272,7 @@ void DEG_graph_build_from_view_layer(Depsgraph *graph, /* Hook up relationships between operations - to determine evaluation order. */ DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache); relation_builder.begin_build(); - relation_builder.build_view_layer(scene, view_layer); + relation_builder.build_view_layer(scene, view_layer, DEG::DEG_ID_LINKED_DIRECTLY); relation_builder.build_copy_on_write_relations(); /* Finalize building. */ graph_build_finalize_common(deg_graph, bmain); diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc index 0345f294860..865da20e6fd 100644 --- a/source/blender/depsgraph/intern/depsgraph_query.cc +++ b/source/blender/depsgraph/intern/depsgraph_query.cc @@ -160,6 +160,19 @@ Scene *DEG_get_evaluated_scene(const Depsgraph *graph) return scene_cow; } +Scene *DEG_get_evaluated_scene_if_exists(const Depsgraph *graph) +{ + if (graph == NULL) { + return NULL; + } + const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph); + Scene *scene_cow = deg_graph->scene_cow; + if (scene_cow == NULL || !DEG::deg_copy_on_write_is_expanded(&scene_cow->id)) { + return NULL; + } + return scene_cow; +} + ViewLayer *DEG_get_evaluated_view_layer(const Depsgraph *graph) { const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph); diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index c2cc15460d1..9f48dd2b47e 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -215,6 +215,16 @@ void depsgraph_tag_to_component_opcode(const ID *id, /* There is no such node in depsgraph, this tag is to be handled * separately. */ break; + case ID_RECALC_SEQUENCER_STRIPS: + *component_type = NodeType::SEQUENCER; + break; + case ID_RECALC_AUDIO_SEEK: + case ID_RECALC_AUDIO_FPS: + case ID_RECALC_AUDIO_VOLUME: + case ID_RECALC_AUDIO_MUTE: + case ID_RECALC_AUDIO_LISTENER: + *component_type = NodeType::AUDIO; + break; case ID_RECALC_ALL: case ID_RECALC_PSYS_ALL: BLI_assert(!"Should not happen"); @@ -633,6 +643,18 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag) return "POINT_CACHE"; case ID_RECALC_EDITORS: return "EDITORS"; + case ID_RECALC_SEQUENCER_STRIPS: + return "SEQUENCER_STRIPS"; + case ID_RECALC_AUDIO_SEEK: + return "AUDIO_SEEK"; + case ID_RECALC_AUDIO_FPS: + return "AUDIO_FPS"; + case ID_RECALC_AUDIO_VOLUME: + return "AUDIO_VOLUME"; + case ID_RECALC_AUDIO_MUTE: + return "AUDIO_MUTE"; + case ID_RECALC_AUDIO_LISTENER: + return "AUDIO_LISTENER"; case ID_RECALC_ALL: return "ALL"; } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index 4bc05bc9185..ef2862ab387 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -59,6 +59,8 @@ extern "C" { #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_scene_types.h" +#include "DNA_sequence_types.h" +#include "DNA_sound_types.h" #include "DNA_object_types.h" #include "DNA_particle_types.h" @@ -84,6 +86,8 @@ extern "C" { #include "BKE_library_query.h" #include "BKE_modifier.h" #include "BKE_object.h" +#include "BKE_sequencer.h" +#include "BKE_sound.h" } #include "intern/depsgraph.h" @@ -467,6 +471,25 @@ void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph, * Still not an excuse to have those. */ } +void update_sequence_orig_pointers(const ListBase *sequences_orig, ListBase *sequences_cow) +{ + Sequence *sequence_orig = reinterpret_cast<Sequence *>(sequences_orig->first); + Sequence *sequence_cow = reinterpret_cast<Sequence *>(sequences_cow->first); + while (sequence_orig != NULL) { + update_sequence_orig_pointers(&sequence_orig->seqbase, &sequence_cow->seqbase); + sequence_cow->orig_sequence = sequence_orig; + sequence_cow = sequence_cow->next; + sequence_orig = sequence_orig->next; + } +} + +void update_scene_orig_pointers(const Scene *scene_orig, Scene *scene_cow) +{ + if (scene_orig->ed != NULL) { + update_sequence_orig_pointers(&scene_orig->ed->seqbase, &scene_cow->ed->seqbase); + } +} + /* Check whether given ID is expanded or still a shallow copy. */ BLI_INLINE bool check_datablock_expanded(const ID *id_cow) { @@ -751,6 +774,7 @@ void update_id_after_copy(const Depsgraph *depsgraph, scene_cow->toolsettings = scene_orig->toolsettings; scene_cow->eevee.light_cache = scene_orig->eevee.light_cache; scene_setup_view_layers_after_remap(depsgraph, id_node, reinterpret_cast<Scene *>(id_cow)); + update_scene_orig_pointers(scene_orig, scene_cow); break; } default: @@ -881,6 +905,205 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph, namespace { +/* Backup of sequencer strips runtime data. */ + +/* Backup of a single strip. */ +class SequenceBackup { + public: + SequenceBackup() + { + reset(); + } + + inline void reset() + { + scene_sound = NULL; + } + + void init_from_sequence(Sequence *sequence) + { + scene_sound = sequence->scene_sound; + + sequence->scene_sound = NULL; + } + + void restore_to_sequence(Sequence *sequence) + { + sequence->scene_sound = scene_sound; + reset(); + } + + inline bool isEmpty() const + { + return (scene_sound == NULL); + } + + void *scene_sound; +}; + +class SequencerBackup { + public: + SequencerBackup(); + + void init_from_scene(Scene *scene); + void restore_to_scene(Scene *scene); + + typedef map<Sequence *, SequenceBackup> SequencesBackupMap; + SequencesBackupMap sequences_backup; +}; + +SequencerBackup::SequencerBackup() +{ +} + +void SequencerBackup::init_from_scene(Scene *scene) +{ + Sequence *sequence; + SEQ_BEGIN (scene->ed, sequence) { + SequenceBackup sequence_backup; + sequence_backup.init_from_sequence(sequence); + if (!sequence_backup.isEmpty()) { + sequences_backup.insert(make_pair(sequence->orig_sequence, sequence_backup)); + } + } + SEQ_END; +} + +void SequencerBackup::restore_to_scene(Scene *scene) +{ + Sequence *sequence; + SEQ_BEGIN (scene->ed, sequence) { + SequencesBackupMap::iterator it = sequences_backup.find(sequence->orig_sequence); + if (it == sequences_backup.end()) { + continue; + } + SequenceBackup &sequence_backup = it->second; + sequence_backup.restore_to_sequence(sequence); + } + SEQ_END; + /* Cleanup audio while the scene is still known. */ + for (SequencesBackupMap::value_type &it : sequences_backup) { + SequenceBackup &sequence_backup = it.second; + if (sequence_backup.scene_sound != NULL) { + BKE_sound_remove_scene_sound(scene, sequence_backup.scene_sound); + } + } +} + +/* Backup of scene runtime data. */ + +class SceneBackup { + public: + SceneBackup(); + + void reset(); + + void init_from_scene(Scene *scene); + void restore_to_scene(Scene *scene); + + /* Sound/audio related pointers of the scene itself. + * + * NOTE: Scene can not disappear after relations update, because otherwise the entire dependency + * graph will be gone. This means we don't need to compare original scene pointer, or worry about + * freeing those if they cant' be restorted: we just copy them over to a new scene. */ + void *sound_scene; + void *playback_handle; + void *sound_scrub_handle; + void *speaker_handles; + + SequencerBackup sequencer_backup; +}; + +SceneBackup::SceneBackup() +{ + reset(); +} + +void SceneBackup::reset() +{ + sound_scene = NULL; + playback_handle = NULL; + sound_scrub_handle = NULL; + speaker_handles = NULL; +} + +void SceneBackup::init_from_scene(Scene *scene) +{ + sound_scene = scene->sound_scene; + playback_handle = scene->playback_handle; + sound_scrub_handle = scene->sound_scrub_handle; + speaker_handles = scene->speaker_handles; + + /* Clear pointers stored in the scene, so they are not freed when copied-on-written datablock + * is freed for re-allocation. */ + scene->sound_scene = NULL; + scene->playback_handle = NULL; + scene->sound_scrub_handle = NULL; + scene->speaker_handles = NULL; + + sequencer_backup.init_from_scene(scene); +} + +void SceneBackup::restore_to_scene(Scene *scene) +{ + scene->sound_scene = sound_scene; + scene->playback_handle = playback_handle; + scene->sound_scrub_handle = sound_scrub_handle; + scene->speaker_handles = speaker_handles; + + sequencer_backup.restore_to_scene(scene); + + reset(); +} + +/* Backup of sound datablocks runtime data. */ + +class SoundBackup { + public: + SoundBackup(); + + void reset(); + + void init_from_sound(bSound *sound); + void restore_to_sound(bSound *sound); + + void *cache; + void *waveform; + void *playback_handle; +}; + +SoundBackup::SoundBackup() +{ + reset(); +} + +void SoundBackup::reset() +{ + cache = NULL; + waveform = NULL; + playback_handle = NULL; +} + +void SoundBackup::init_from_sound(bSound *sound) +{ + cache = sound->cache; + waveform = sound->waveform; + playback_handle = sound->playback_handle; + + sound->cache = NULL; + sound->waveform = NULL; + sound->playback_handle = NULL; +} + +void SoundBackup::restore_to_sound(bSound *sound) +{ + sound->cache = cache; + sound->waveform = waveform; + sound->playback_handle = playback_handle; + + reset(); +} + /* Identifier used to match modifiers to backup/restore their runtime data. * Identification is happening using original modifier data pointer and the * modifier type. @@ -921,7 +1144,8 @@ typedef map<ModifierDataBackupID, void *> ModifierRuntimeDataBackup; /* Storage for backed up pose channel runtime data. */ typedef map<bPoseChannel *, bPoseChannel_Runtime> PoseChannelRuntimeDataBackup; -struct ObjectRuntimeBackup { +class ObjectRuntimeBackup { + public: ObjectRuntimeBackup() : base_flag(0), base_local_view_bits(0) { /* TODO(sergey): Use something like BKE_object_runtime_reset(). */ @@ -1099,6 +1323,8 @@ class RuntimeBackup { /* Restore fields to the given ID. */ void restore_to_id(ID *id); + SceneBackup scene_backup; + SoundBackup sound_backup; ObjectRuntimeBackup object_backup; DrawDataList drawdata_backup; DrawDataList *drawdata_ptr; @@ -1114,6 +1340,12 @@ void RuntimeBackup::init_from_id(ID *id) case ID_OB: object_backup.init_from_object(reinterpret_cast<Object *>(id)); break; + case ID_SCE: + scene_backup.init_from_scene(reinterpret_cast<Scene *>(id)); + break; + case ID_SO: + sound_backup.init_from_sound(reinterpret_cast<bSound *>(id)); + break; default: break; } @@ -1133,6 +1365,12 @@ void RuntimeBackup::restore_to_id(ID *id) case ID_OB: object_backup.restore_to_object(reinterpret_cast<Object *>(id)); break; + case ID_SCE: + scene_backup.restore_to_scene(reinterpret_cast<Scene *>(id)); + break; + case ID_SO: + sound_backup.restore_to_sound(reinterpret_cast<bSound *>(id)); + break; default: break; } @@ -1321,9 +1559,7 @@ bool deg_copy_on_write_is_expanded(const ID *id_cow) bool deg_copy_on_write_is_needed(const ID *id_orig) { const ID_Type id_type = GS(id_orig->name); - /* TODO(sergey): Make Sound copyable. It is here only because the code for dependency graph is - * being work in progress. */ - return !ELEM(id_type, ID_IM, ID_SO); + return !ELEM(id_type, ID_IM); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc index 62a61675bcc..09a761d282f 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc @@ -185,6 +185,9 @@ const char *operationCodeAsString(OperationCode opcode) /* Generic datablock. */ case OperationCode::GENERIC_DATABLOCK_UPDATE: return "GENERIC_DATABLOCK_UPDATE"; + /* Sequencer. */ + case OperationCode::SEQUENCES_EVAL: + return "SEQUENCES_EVAL"; /* instancing/duplication. */ case OperationCode::DUPLI: return "DUPLI"; diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h index ab6242a6196..8fc565cfa77 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.h +++ b/source/blender/depsgraph/intern/node/deg_node_operation.h @@ -185,12 +185,16 @@ enum class OperationCode { /* Images. -------------------------------------------------------------- */ IMAGE_ANIMATION, - /* Synchronization clips. ----------------------------------------------- */ + /* Synchronization. ----------------------------------------------------- */ SYNCHRONIZE_TO_ORIGINAL, /* Generic datablock ---------------------------------------------------- */ GENERIC_DATABLOCK_UPDATE, + /* Sequencer. ----------------------------------------------------------- */ + + SEQUENCES_EVAL, + /* Duplication/instancing system. --------------------------------------- */ DUPLI, }; diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index abec3563d0c..9e3f91bc971 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -36,7 +36,6 @@ #include "BKE_sequencer.h" #include "BKE_global.h" #include "BKE_main.h" -#include "BKE_sound.h" #include "BKE_scene.h" #include "UI_view2d.h" @@ -52,6 +51,9 @@ #include "ED_sequencer.h" #include "ED_util.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + #include "anim_intern.h" /* ********************** frame change operator ***************************/ @@ -88,7 +90,6 @@ static bool change_frame_poll(bContext *C) /* Set the new frame number */ static void change_frame_apply(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); float frame = RNA_float_get(op->ptr, "frame"); bool do_snap = RNA_boolean_get(op->ptr, "snap"); @@ -114,7 +115,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) FRAMENUMBER_MIN_CLAMP(CFRA); /* do updates */ - BKE_sound_seek_scene(bmain, scene); + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 7c03ba889a7..b3cbeca7317 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -67,6 +67,7 @@ #include "WM_types.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "ED_anim_api.h" #include "ED_armature.h" @@ -2740,7 +2741,6 @@ static void areas_do_frame_follow(bContext *C, bool middle) /* function to be called outside UI context, or for redo */ static int frame_offset_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); int delta; @@ -2752,7 +2752,7 @@ static int frame_offset_exec(bContext *C, wmOperator *op) areas_do_frame_follow(C, false); - BKE_sound_seek_scene(bmain, scene); + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); @@ -2784,7 +2784,6 @@ static void SCREEN_OT_frame_offset(wmOperatorType *ot) /* function to be called outside UI context, or for redo */ static int frame_jump_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); wmTimer *animtimer = CTX_wm_screen(C)->animtimer; @@ -2814,7 +2813,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op) areas_do_frame_follow(C, true); - BKE_sound_seek_scene(bmain, scene); + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } @@ -2847,7 +2846,6 @@ static void SCREEN_OT_frame_jump(wmOperatorType *ot) /* function to be called outside UI context, or for redo */ static int keyframe_jump_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); bDopeSheet ads = {NULL}; @@ -2930,7 +2928,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) else { areas_do_frame_follow(C, true); - BKE_sound_seek_scene(bmain, scene); + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); @@ -2963,7 +2961,6 @@ static void SCREEN_OT_keyframe_jump(wmOperatorType *ot) /* function to be called outside UI context, or for redo */ static int marker_jump_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); TimeMarker *marker; int closest = CFRA; @@ -2997,7 +2994,7 @@ static int marker_jump_exec(bContext *C, wmOperator *op) areas_do_frame_follow(C, true); - BKE_sound_seek_scene(bmain, scene); + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); @@ -4206,7 +4203,8 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv if (screen->animtimer && screen->animtimer == event->customdata) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - struct Depsgraph *depsgraph = CTX_data_depsgraph(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); wmTimer *wt = screen->animtimer; ScreenAnimData *sad = wt->customdata; wmWindowManager *wm = CTX_wm_manager(C); @@ -4227,7 +4225,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } if ((scene->audio.flag & AUDIO_SYNC) && (sad->flag & ANIMPLAY_FLAG_REVERSE) == false && - isfinite(time = BKE_sound_sync_scene(scene))) { + isfinite(time = BKE_sound_sync_scene(scene_eval))) { double newfra = (double)time * FPS; /* give some space here to avoid jumps */ @@ -4320,7 +4318,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } if (sad->flag & ANIMPLAY_FLAG_JUMPED) { - BKE_sound_seek_scene(bmain, scene); + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK); #ifdef PROFILE_AUDIO_SYNCH old_frame = CFRA; #endif @@ -4442,11 +4440,12 @@ int ED_screen_animation_play(bContext *C, int sync, int mode) { bScreen *screen = CTX_wm_screen(C); Scene *scene = CTX_data_scene(C); + Scene *scene_eval = DEG_get_evaluated_scene(CTX_data_depsgraph(C)); if (ED_screen_animation_playing(CTX_wm_manager(C))) { /* stop playback now */ ED_screen_animation_timer(C, 0, 0, 0, 0); - BKE_sound_stop_scene(scene); + BKE_sound_stop_scene(scene_eval); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } @@ -4455,7 +4454,7 @@ int ED_screen_animation_play(bContext *C, int sync, int mode) int refresh = SPACE_ACTION; if (mode == 1) { /* XXX only play audio forwards!? */ - BKE_sound_play_scene(scene); + BKE_sound_play_scene(scene_eval); } ED_screen_animation_timer(C, screen->redraws_flag, refresh, sync, mode); diff --git a/source/blender/editors/sound/CMakeLists.txt b/source/blender/editors/sound/CMakeLists.txt index c2a88041a85..7f4b5a45aa3 100644 --- a/source/blender/editors/sound/CMakeLists.txt +++ b/source/blender/editors/sound/CMakeLists.txt @@ -19,6 +19,7 @@ set(INC ../include ../../blenkernel ../../blenlib + ../../depsgraph ../../makesdna ../../makesrna ../../windowmanager diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 381173999c4..30ddd8c7d33 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -62,6 +62,8 @@ # include <AUD_Special.h> #endif +#include "DEG_depsgraph_query.h" + #include "ED_sound.h" #include "ED_util.h" @@ -88,7 +90,6 @@ static int sound_open_exec(bContext *C, wmOperator *op) bSound *sound; PropertyPointerRNA *pprop; PointerRNA idptr; - AUD_SoundInfo info; Main *bmain = CTX_data_main(C); RNA_string_get(op->ptr, "filepath", path); @@ -98,29 +99,8 @@ static int sound_open_exec(bContext *C, wmOperator *op) sound_open_init(C, op); } - if (sound->playback_handle == NULL) { - if (op->customdata) { - MEM_freeN(op->customdata); - } - BKE_id_free(bmain, sound); - BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); - return OPERATOR_CANCELLED; - } - - info = AUD_getInfo(sound->playback_handle); - - if (info.specs.channels == AUD_CHANNELS_INVALID) { - BKE_id_free(bmain, sound); - if (op->customdata) { - MEM_freeN(op->customdata); - } - BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); - return OPERATOR_CANCELLED; - } - if (RNA_boolean_get(op->ptr, "mono")) { sound->flags |= SOUND_FLAGS_MONO; - BKE_sound_load(bmain, sound); } if (RNA_boolean_get(op->ptr, "cache")) { @@ -140,6 +120,8 @@ static int sound_open_exec(bContext *C, wmOperator *op) RNA_property_update(C, &pprop->ptr, pprop->prop); } + DEG_relations_tag_update(bmain); + MEM_freeN(op->customdata); return OPERATOR_FINISHED; } @@ -361,8 +343,9 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op) #ifdef WITH_AUDASPACE char path[FILE_MAX]; char filename[FILE_MAX]; - Scene *scene; - Main *bmain; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + Main *bmain = CTX_data_main(C); int split; int bitrate, accuracy; @@ -380,18 +363,20 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op) container = RNA_enum_get(op->ptr, "container"); codec = RNA_enum_get(op->ptr, "codec"); split = RNA_boolean_get(op->ptr, "split_channels"); - scene = CTX_data_scene(C); - bmain = CTX_data_main(C); - specs.channels = scene->r.ffcodecdata.audio_channels; - specs.rate = scene->r.ffcodecdata.audio_mixrate; + specs.channels = scene_eval->r.ffcodecdata.audio_channels; + specs.rate = scene_eval->r.ffcodecdata.audio_mixrate; BLI_strncpy(filename, path, sizeof(filename)); BLI_path_abs(filename, BKE_main_blendfile_path(bmain)); + const double fps = (((double)scene_eval->r.frs_sec) / (double)scene_eval->r.frs_sec_base); + const int start_frame = scene_eval->r.sfra; + const int end_frame = scene_eval->r.efra; + if (split) { - result = AUD_mixdown_per_channel(scene->sound_scene, - SFRA * specs.rate / FPS, - (EFRA - SFRA + 1) * specs.rate / FPS, + result = AUD_mixdown_per_channel(scene_eval->sound_scene, + start_frame * specs.rate / fps, + (end_frame - start_frame + 1) * specs.rate / fps, accuracy, filename, specs, @@ -400,9 +385,9 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op) bitrate); } else { - result = AUD_mixdown(scene->sound_scene, - SFRA * specs.rate / FPS, - (EFRA - SFRA + 1) * specs.rate / FPS, + result = AUD_mixdown(scene_eval->sound_scene, + start_frame * specs.rate / fps, + (end_frame - start_frame + 1) * specs.rate / fps, accuracy, filename, specs, @@ -411,7 +396,7 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op) bitrate); } - BKE_sound_reset_scene_specs(scene); + BKE_sound_reset_scene_specs(scene_eval); if (result) { BKE_report(op->reports, RPT_ERROR, result); diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index ba40b8bfaae..83d8133a99e 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -52,7 +52,6 @@ #include "BKE_main.h" #include "BKE_movieclip.h" #include "BKE_report.h" -#include "BKE_sound.h" #include "BKE_tracking.h" #include "WM_api.h" @@ -74,6 +73,7 @@ #include "PIL_time.h" +#include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "clip_intern.h" // own include @@ -999,7 +999,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) SUBFRA = 0.0f; /* do updates */ - BKE_sound_seek_scene(CTX_data_main(C), scene); + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index c19b0583a5c..2de01e0b7ec 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -35,7 +35,6 @@ #include "BKE_movieclip.h" #include "BKE_tracking.h" #include "BKE_report.h" -#include "BKE_sound.h" #include "DEG_depsgraph.h" @@ -1356,7 +1355,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op) if (CFRA != sc->user.framenr) { CFRA = sc->user.framenr; - BKE_sound_seek_scene(CTX_data_main(C), scene); + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 3450ca5a431..c9dc9803105 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -33,7 +33,6 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" -#include "BKE_sound.h" #include "UI_view2d.h" @@ -49,6 +48,8 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -74,7 +75,6 @@ static bool graphview_cursor_poll(bContext *C) /* Set the new frame number */ static void graphview_cursor_apply(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); SpaceGraph *sipo = CTX_wm_space_graph(C); /* this isn't technically "frame", but it'll do... */ @@ -105,7 +105,7 @@ static void graphview_cursor_apply(bContext *C, wmOperator *op) } SUBFRA = 0.0f; - BKE_sound_seek_scene(bmain, scene); + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK); } /* set the cursor value */ diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 9ef646e6c71..3789b6d7a6d 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -61,7 +61,6 @@ #include "BKE_paint.h" #include "BKE_report.h" #include "BKE_screen.h" -#include "BKE_sound.h" #include "BKE_scene.h" #include "DEG_depsgraph.h" @@ -3608,7 +3607,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) SUBFRA = 0.0f; /* do updates */ - BKE_sound_seek_scene(CTX_data_main(C), scene); + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt index 4668a9cef90..d57be0c85c3 100644 --- a/source/blender/editors/space_sequencer/CMakeLists.txt +++ b/source/blender/editors/space_sequencer/CMakeLists.txt @@ -21,6 +21,7 @@ set(INC ../../blenlib ../../blentranslation ../../gpu + ../../depsgraph ../../imbuf ../../makesdna ../../makesrna diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index db6cc1af31e..190c2edf30c 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -64,6 +64,8 @@ # include <AUD_Sequence.h> #endif +#include "DEG_depsgraph.h" + /* own include */ #include "sequencer_intern.h" @@ -351,6 +353,7 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op) sequencer_add_apply_replace_sel(C, op, seq); sequencer_add_apply_overlap(C, op, seq); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -433,6 +436,7 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op) sequencer_add_apply_replace_sel(C, op, seq); sequencer_add_apply_overlap(C, op, seq); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -515,6 +519,7 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op) sequencer_add_apply_replace_sel(C, op, seq); sequencer_add_apply_overlap(C, op, seq); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -627,8 +632,8 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad } BKE_sequencer_sort(scene); - BKE_sequencer_update_muting(ed); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -956,6 +961,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) MEM_freeN(op->customdata); } + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -1105,6 +1111,7 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) * it was NOT called in blender 2.4x, but wont hurt */ BKE_sequencer_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; diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index b9b310cf922..6197a7bd559 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -260,11 +260,6 @@ static void drawseqwave(View2D *v2d, return; } - if (!sound->spinlock) { - sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); - BLI_spin_init(sound->spinlock); - } - BLI_spin_lock(sound->spinlock); if (!sound->waveform) { if (!(sound->tags & SOUND_TAGS_WAVEFORM_LOADING)) { diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index ed7205328eb..038ab0cc7cd 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -64,6 +64,8 @@ #include "UI_view2d.h" #include "UI_interface.h" +#include "DEG_depsgraph.h" + /* own include */ #include "sequencer_intern.h" @@ -1809,7 +1811,7 @@ static int sequencer_mute_exec(bContext *C, wmOperator *op) } } - BKE_sequencer_update_muting(ed); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -1860,7 +1862,7 @@ static int sequencer_unmute_exec(bContext *C, wmOperator *op) } } - BKE_sequencer_update_muting(ed); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -2370,6 +2372,7 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op)) ms = ms->prev; } + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -2625,7 +2628,7 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op)) MEM_freeN(ms); } - BKE_sequencer_update_muting(ed); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -2686,7 +2689,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op) BKE_sequence_base_shuffle(ed->seqbasep, seqm, scene); } - BKE_sequencer_update_muting(ed); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqm); @@ -2773,7 +2776,7 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op)) } BKE_sequencer_sort(scene); - BKE_sequencer_update_muting(ed); + 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/editors/space_sequencer/sequencer_preview.c b/source/blender/editors/space_sequencer/sequencer_preview.c index 546c2a8a9f0..8a4e8c007f7 100644 --- a/source/blender/editors/space_sequencer/sequencer_preview.c +++ b/source/blender/editors/space_sequencer/sequencer_preview.c @@ -50,6 +50,7 @@ typedef struct PreviewJob { typedef struct PreviewJobAudio { struct PreviewJobAudio *next, *prev; + struct Main *bmain; bSound *sound; int lr; /* sample left or right */ int startframe; @@ -79,7 +80,9 @@ static void preview_startjob(void *data, short *stop, short *do_update, float *p PreviewJobAudio *preview_next; bSound *sound = previewjb->sound; + BKE_sound_load_audio(previewjb->bmain, sound); BKE_sound_read_waveform(sound, stop); + BKE_sound_free_audio(sound); if (*stop || G.is_break) { BLI_mutex_lock(pj->mutex); @@ -153,6 +156,7 @@ void sequencer_preview_add_sound(const bContext *C, Sequence *seq) /* attempt to lock mutex of job here */ + audiojob->bmain = CTX_data_main(C); audiojob->sound = seq->sound; BLI_mutex_lock(pj->mutex); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 6a9c6856a03..0a361d0d09e 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1183,6 +1183,8 @@ static void recalcData_sequencer(TransInfo *t) seq_prev = seq; } + DEG_id_tag_update(&t->scene->id, ID_RECALC_SEQUENCER_STRIPS); + flushTransSeq(t); } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 5a666653043..139cb298710 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -448,9 +448,7 @@ typedef enum ID_Type { /* No copy-on-write for these types. * Keep in sync with check_datablocks_copy_on_writable and deg_copy_on_write_is_needed */ -/* TODO(sergey): Make Sound copyable. It is here only because the code for dependency graph is - * being work in progress. */ -#define ID_TYPE_IS_COW(_id_type) (!ELEM(_id_type, ID_BR, ID_LS, ID_PAL, ID_IM, ID_SO)) +#define ID_TYPE_IS_COW(_id_type) (!ELEM(_id_type, ID_BR, ID_LS, ID_PAL, ID_IM)) #ifdef GS # undef GS @@ -604,6 +602,16 @@ typedef enum IDRecalcFlag { */ ID_RECALC_COPY_ON_WRITE = (1 << 13), + /* Sequences in the sequencer did change. + * Use this tag with a scene ID which owns the sequences. */ + ID_RECALC_SEQUENCER_STRIPS = (1 << 14), + + ID_RECALC_AUDIO_SEEK = (1 << 15), + ID_RECALC_AUDIO_FPS = (1 << 16), + ID_RECALC_AUDIO_VOLUME = (1 << 17), + ID_RECALC_AUDIO_MUTE = (1 << 18), + ID_RECALC_AUDIO_LISTENER = (1 << 19), + /*************************************************************************** * Pseudonyms, to have more semantic meaning in the actual code without * using too much low-level and implementation specific tags. */ diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index c21fa2ba64e..5240de4aff9 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -232,6 +232,9 @@ typedef struct Sequence { int cache_flag; int _pad2[3]; + + struct Sequence *orig_sequence; + void *_pad3; } Sequence; typedef struct MetaStack { diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index f101a29ec22..0f0d057845e 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -669,7 +669,6 @@ const EnumPropertyItem rna_enum_transform_orientation_items[] = { # include "BKE_pointcache.h" # include "BKE_scene.h" # include "BKE_mesh.h" -# include "BKE_sound.h" # include "BKE_screen.h" # include "BKE_sequencer.h" # include "BKE_animsys.h" @@ -819,23 +818,17 @@ static void rna_Scene_camera_update(Main *bmain, Scene *UNUSED(scene_unused), Po static void rna_Scene_fps_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { - BKE_sound_update_fps(scene); - BKE_sequencer_update_sound_bounds_all(scene); + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_FPS | ID_RECALC_SEQUENCER_STRIPS); } static void rna_Scene_listener_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { - BKE_sound_update_scene_listener(scene); + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_LISTENER); } -static void rna_Scene_volume_set(PointerRNA *ptr, float value) +static void rna_Scene_volume_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { - Scene *scene = (Scene *)(ptr->data); - - scene->audio.volume = value; - if (scene->sound_scene) { - BKE_sound_set_scene_volume(scene, value); - } + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_VOLUME); } static const char *rna_Scene_statistics_string_get(Scene *scene, @@ -962,10 +955,12 @@ static void rna_Scene_show_subframe_update(Main *UNUSED(bmain), scene->r.subframe = 0.0f; } -static void rna_Scene_frame_update(Main *bmain, Scene *UNUSED(current_scene), PointerRNA *ptr) +static void rna_Scene_frame_update(Main *UNUSED(bmain), + Scene *UNUSED(current_scene), + PointerRNA *ptr) { Scene *scene = (Scene *)ptr->id.data; - BKE_sound_seek_scene(bmain, scene); + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK); WM_main_add_notifier(NC_SCENE | ND_FRAME, scene); } @@ -1825,8 +1820,11 @@ static void rna_Scene_use_audio_set(PointerRNA *ptr, bool value) else { scene->audio.flag &= ~AUDIO_MUTE; } +} - BKE_sound_mute_scene(scene, value); +static void rna_Scene_use_audio_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) +{ + DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_MUTE); } static int rna_Scene_sync_mode_get(PointerRNA *ptr) @@ -7420,7 +7418,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, "rna_Scene_use_audio_get", "rna_Scene_use_audio_set"); RNA_def_property_ui_text( prop, "Audio Muted", "Play back of audio from Sequence Editor will be muted"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE, "rna_Scene_use_audio_update"); # if 0 /* XXX: Is this actually needed? */ prop = RNA_def_property(srna, "use_audio_sync", PROP_BOOLEAN, PROP_NONE); @@ -7467,7 +7465,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Volume", "Audio volume"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND); RNA_def_property_update(prop, NC_SCENE, NULL); - RNA_def_property_float_funcs(prop, NULL, "rna_Scene_volume_set", NULL); + RNA_def_property_update(prop, NC_SCENE, "rna_Scene_volume_update"); /* Statistics */ func = RNA_def_function(srna, "statistics", "rna_Scene_statistics_string_get"); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 29a06eeabf2..3915c989614 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -75,6 +75,8 @@ const EnumPropertyItem rna_enum_sequence_modifier_type_items[] = { # include "WM_api.h" +# include "DEG_depsgraph.h" + # include "IMB_imbuf.h" typedef struct SequenceSearchData { @@ -727,37 +729,9 @@ static int rna_Sequence_proxy_filepath_length(PointerRNA *ptr) return strlen(path); } -static void rna_Sequence_volume_set(PointerRNA *ptr, float value) -{ - Sequence *seq = (Sequence *)(ptr->data); - - seq->volume = value; - if (seq->scene_sound) { - BKE_sound_set_scene_sound_volume( - seq->scene_sound, value, (seq->flag & SEQ_AUDIO_VOLUME_ANIMATED) != 0); - } -} - -static void rna_Sequence_pitch_set(PointerRNA *ptr, float value) -{ - Sequence *seq = (Sequence *)(ptr->data); - - seq->pitch = value; - if (seq->scene_sound) { - BKE_sound_set_scene_sound_pitch( - seq->scene_sound, value, (seq->flag & SEQ_AUDIO_PITCH_ANIMATED) != 0); - } -} - -static void rna_Sequence_pan_set(PointerRNA *ptr, float value) +static void rna_Sequence_audio_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { - Sequence *seq = (Sequence *)(ptr->data); - - seq->pan = value; - if (seq->scene_sound) { - BKE_sound_set_scene_sound_pan( - seq->scene_sound, value, (seq->flag & SEQ_AUDIO_PAN_ANIMATED) != 0); - } + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); } static int rna_Sequence_input_count_get(PointerRNA *ptr) @@ -801,9 +775,8 @@ static void rna_Sequence_reopen_files_update(Main *bmain, Scene *UNUSED(scene), static void rna_Sequence_mute_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->id.data; - Editing *ed = BKE_sequencer_editing_get(scene, false); - BKE_sequencer_update_muting(ed); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); } static void rna_Sequence_filepath_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) @@ -2392,23 +2365,20 @@ static void rna_def_sound(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_text(prop, "Volume", "Playback volume of the sound"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND); - RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_volume_set", NULL); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_audio_update"); prop = RNA_def_property(srna, "pitch", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pitch"); RNA_def_property_range(prop, 0.1f, 10.0f); RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND); - RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_pitch_set", NULL); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_audio_update"); prop = RNA_def_property(srna, "pan", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pan"); RNA_def_property_range(prop, -2.0f, 2.0f); RNA_def_property_ui_text(prop, "Pan", "Playback panning of the sound (only for Mono sources)"); - RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_pan_set", NULL); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_audio_update"); prop = RNA_def_property(srna, "show_waveform", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_AUDIO_DRAW_WAVEFORM); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 6bde162f507..2e27ec81bd0 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2537,8 +2537,14 @@ void RE_RenderAnim(Render *re, re->movie_ctx_arr[i] = mh->context_create(); - if (!mh->start_movie( - re->movie_ctx_arr[i], scene, &re->r, width, height, re->reports, false, suffix)) { + if (!mh->start_movie(re->movie_ctx_arr[i], + re->pipeline_scene_eval, + &re->r, + width, + height, + re->reports, + false, + suffix)) { is_error = true; break; } @@ -2744,7 +2750,7 @@ void RE_RenderAnim(Render *re, BLI_callback_exec( re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE); - BKE_sound_reset_scene_specs(scene); + BKE_sound_reset_scene_specs(re->pipeline_scene_eval); RE_CleanAfterRender(re); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index f688f520572..952382c2e36 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -86,6 +86,7 @@ #include "RNA_enum_types.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" static void wm_notifier_clear(wmNotifier *note); static void update_tablet_data(wmWindow *win, wmEvent *event); @@ -3154,13 +3155,17 @@ void wm_event_do_handlers(bContext *C) else { Scene *scene = WM_window_get_active_scene(win); - if (scene) { - int is_playing_sound = BKE_sound_scene_playing(scene); + CTX_wm_window_set(C, win); + CTX_data_scene_set(C, scene); + + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene_eval = DEG_get_evaluated_scene_if_exists(depsgraph); + + if (scene_eval) { + const int is_playing_sound = BKE_sound_scene_playing(scene_eval); if (is_playing_sound != -1) { bool is_playing_screen; - CTX_wm_window_set(C, win); - CTX_data_scene_set(C, scene); is_playing_screen = (ED_screen_animation_playing(wm) != NULL); @@ -3175,18 +3180,17 @@ void wm_event_do_handlers(bContext *C) int ncfra = time * (float)FPS + 0.5f; if (ncfra != scene->r.cfra) { scene->r.cfra = ncfra; - Depsgraph *depsgraph = CTX_data_depsgraph(C); ED_update_for_newframe(CTX_data_main(C), depsgraph); WM_event_add_notifier(C, NC_WINDOW, NULL); } } } - - CTX_data_scene_set(C, NULL); - CTX_wm_screen_set(C, NULL); - CTX_wm_window_set(C, NULL); } } + + CTX_data_scene_set(C, NULL); + CTX_wm_screen_set(C, NULL); + CTX_wm_window_set(C, NULL); } while ((event = win->queue.first)) { diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index bbaaab01b18..7e54afcb9aa 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -65,6 +65,8 @@ #include "BKE_node.h" #include "BKE_report.h" #include "BKE_screen.h" +#include "BKE_scene.h" +#include "BKE_sound.h" #include "BKE_keyconfig.h" #include "BKE_addon.h" @@ -123,6 +125,7 @@ #include "COM_compositor.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "DRW_engine.h" @@ -195,6 +198,30 @@ void WM_init_opengl(Main *bmain) opengl_is_init = true; } +static void sound_jack_sync_callback(Main *bmain, int mode, float time) +{ + /* Ugly: Blender doesn't like it when the animation is played back during rendering. */ + if (G.is_rendering) { + return; + } + + wmWindowManager *wm = bmain->wm.first; + + for (wmWindow *window = wm->windows.first; window != NULL; window = window->next) { + Scene *scene = WM_window_get_active_scene(window); + if ((scene->audio.flag & AUDIO_SYNC) == 0) { + continue; + } + ViewLayer *view_layer = WM_window_get_active_view_layer(window); + Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false); + if (depsgraph == NULL) { + continue; + } + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + BKE_sound_jack_scene_update(scene_eval, mode, time); + } +} + /* only called once, for startup */ void WM_init(bContext *C, int argc, const char **argv) { @@ -202,6 +229,7 @@ void WM_init(bContext *C, int argc, const char **argv) if (!G.background) { wm_ghost_init(C); /* note: it assigns C to ghost! */ wm_init_cursor_data(); + BKE_sound_jack_sync_callback_set(sound_jack_sync_callback); } GHOST_CreateSystemPaths(); |