Sound: Port to a copy-on-write concept
authorSergey Sharybin <sergey.vfx@gmail.com>
Tue, 4 Jun 2019 14:52:48 +0000 (16:52 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 5 Jun 2019 12:23:54 +0000 (14:23 +0200)
This change makes it so sound handles are created for evaluated scene,
sequencer and speakers. This allows to have properly evaluated animation
on them.

For the viewport playback sound uses regular dependency graph.

For the final render sound uses dependency graph created for render pipeline,
which now also contains sequencer and sound datablocks.

All the direct sound update calls are replaced with corresponding dependency
graph recalc tag.

44 files changed:
source/blender/blenkernel/BKE_movieclip.h
source/blender/blenkernel/BKE_scene.h
source/blender/blenkernel/BKE_sound.h
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/sound.c
source/blender/blenloader/intern/readfile.c
source/blender/depsgraph/DEG_depsgraph_query.h
source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
source/blender/depsgraph/intern/builder/deg_builder_nodes.h
source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.h
source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
source/blender/depsgraph/intern/builder/deg_builder_rna.cc
source/blender/depsgraph/intern/depsgraph_build.cc
source/blender/depsgraph/intern/depsgraph_query.cc
source/blender/depsgraph/intern/depsgraph_tag.cc
source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
source/blender/depsgraph/intern/node/deg_node_operation.cc
source/blender/depsgraph/intern/node/deg_node_operation.h
source/blender/editors/animation/anim_ops.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/sound/CMakeLists.txt
source/blender/editors/sound/sound_ops.c
source/blender/editors/space_clip/clip_ops.c
source/blender/editors/space_clip/tracking_ops.c
source/blender/editors/space_graph/graph_ops.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_sequencer/CMakeLists.txt
source/blender/editors/space_sequencer/sequencer_add.c
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/editors/space_sequencer/sequencer_preview.c
source/blender/editors/transform/transform_generics.c
source/blender/makesdna/DNA_ID.h
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_sequencer.c
source/blender/render/intern/source/pipeline.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_init_exit.c

index 43ee284a201ed275adaab39cd5d9e0c134efab81..9425f396bc52ea4705456a6bff586f3908d950b5 100644 (file)
@@ -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);
 
index 0dcb109240c9a6a8f6cff1220dfe642fc4824bef..f90429aaebef06bae3e7c08687c619ad6e367daf 100644 (file)
@@ -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
index 91e23d35f0ea72a5f8fd9e67f1c0115f6e7da3c5..8d17380592e3701df0f8a8db8d6050875b6e93dc 100644 (file)
@@ -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__ */
index d17990d4bee47971beb179638e022731de75a318..9fcbf209cba4d09591b6c7d5c50b842cb513f874 100644 (file)
@@ -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);
+}
index ec8a25204613cd343fb2640ffc3cdd4b29a5087b..171635cc6b5a0a913a51287bcd174bbf66c9b1ac 100644 (file)
@@ -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);
     }
index 0cd51766078c23f1073427deb10950dc1496a1a6..13aedf60cd0d504c0586d960ea1da35693692982 100644 (file)
@@ -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>
 #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);
+}
index 32f0d35cd53dabe41370c11734450a9bec17dde1..a4bdf02c8387dbf307f49a1555ae544da06a8d7c 100644 (file)
@@ -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;
     }
index 48a62a69f30e925045ded915301834c4d715dc26..cc6c5e7282a545f517e882fce8787adae178345e 100644 (file)
@@ -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);
index 93e5dd14ae0baa7b536f3c41285fb923a208afaf..9bdc815518d4ba4045158bf6731115a0fd8925f4 100644 (file)
@@ -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,
index c3a04a9ad8819614a30638424ec4db3b72108dfa..896854870de29e5af3f7be1a8307b7992ae7adae 100644 (file)
@@ -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. */
index 64f841d56fc3575e906fb0a2a7b10df7bfadebcc..ef73de517e853a35c787d1be5f66783479a8b75a 100644 (file)
@@ -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)
index 4e3fdfc6c19e6d97174d77ec31790d19e867a451..2f6b8c0ba6bdda36f2e1895a7d0e9bb903fb907d 100644 (file)
@@ -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,
index 54d5223497e50cac725d087578471c0a06d271d3..a1f8c59f9360ed3355c2b90a6a1805b7d184585c 100644 (file)
@@ -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
index 7d3020921196519801e4a11187a4e1c674e81f00..55295c8b075b8c75c9eb9e487db7568b770032f5 100644 (file)
@@ -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);
index 26bb1bd3d2ab6fcf59390989df17c72122d0a395..46e8b8e7accd1a9623d666e3438c04c8cbf73ffb 100644 (file)
@@ -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)
index b832473bde9f29b58bfd3a2a9ad54e42d4fc8b70..4c55e4a137a0fd7aace17db93b3dcb5412627d93 100644 (file)
@@ -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);
   }
 }
 
index 403c9cfc778990b75ef2e2246d5317caabc01178..b7efdc0fa3f167fecf72a9451520a011fb0ebe0e 100644 (file)
@@ -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)) {
index cf1ebccc6c6af14971c1105a6b97cf30200a9033..bfb0a2aade49b4b09b62563ccd6152b1d9d6d220 100644 (file)
@@ -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);
index 0345f2948606c80dac86a60434baba27d8fcff1e..865da20e6fd2f0c0f55a640fe3be6d62f1ae5cdb 100644 (file)
@@ -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);
index c2cc15460d11fb305fef5872976dc0414a55c646..9f48dd2b47ea685a70b8e81dfda41bb16587cbc2 100644 (file)
@@ -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";
   }
index 4bc05bc9185c71e6f86b49bf2f1228a81dcf64c1..ef2862ab387f9ec4ba84f3737bcf20ac1ae55407 100644 (file)
@@ -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
index 62a61675bccda52f218a7ebd8bfc2650ba856a1e..09a761d282f2b1887ee6b4faa0c6454e969ba0cf 100644 (file)
@@ -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";
index ab6242a6196a677c486e57a6bc77701debaa8f15..8fc565cfa77d8999bb92bb3eccc91fb48e4a14b4 100644 (file)
@@ -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,
 };
index abec3563d0c2c62d63fab082baa9384bc508b2d7..9e3f91bc9719995e9195f2b6c9bd58b05b9e9f2e 100644 (file)
@@ -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);
 }
 
index 7c03ba889a7fc970153332380d75adb6c7a135f5..b3cbeca7317db52bdb2a95d1faa4fec772bf14a9 100644 (file)
@@ -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);
index c2a88041a85cc9673c241410f84ecc7a340b9d71..7f4b5a45aa369a007cd9fc7ed3e4757a97a8ca61 100644 (file)
@@ -19,6 +19,7 @@ set(INC
   ../include
   ../../blenkernel
   ../../blenlib
+  ../../depsgraph
   ../../makesdna
   ../../makesrna
   ../../windowmanager
index 381173999c4212bcc1ef81469f952afb6294c7f0..30ddd8c7d3310d90a5653428f23ca647c084d9d6 100644 (file)
@@ -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);
index ba40b8bfaae045eea9f3b04ce4c109fd27dee70b..83d8133a99e3ab7011563a2ac331e3703bf8f9e0 100644 (file)
@@ -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);
 }
 
index c19b0583a5c4d9e367463efa4d82e3df22699620..2de01e0b7ecf9b9c4d6b12c4f38c251702e7fc4b 100644 (file)
@@ -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);
   }
index 3450ca5a431e1ad3d1692517e031661939809ff2..c9dc980310535eab79c510dc5d57c0a9caed4339 100644 (file)
@@ -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 */
index 9ef646e6c71c3b15024fb78a74734152781b22bd..3789b6d7a6d4a46548e0c70daffb32cc73495f9d 100644 (file)
@@ -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);
 }
 
index 4668a9cef90a2fe37fb5ae79e6a0fe90705093b5..d57be0c85c3b81685fc2ac6588a8005298ed504d 100644 (file)
@@ -21,6 +21,7 @@ set(INC
   ../../blenlib
   ../../blentranslation
   ../../gpu
+  ../../depsgraph
   ../../imbuf
   ../../makesdna
   ../../makesrna
index db6cc1af31e13fce51e848628f47a15c825628f2..190c2edf30c34b48564d5afcca3ec4aa19080929 100644 (file)
@@ -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;
index b9b310cf922565683e57b275f1c0dd4eba0eb652..6197a7bd55955b7cae1f553450bf9b19d7e97570 100644 (file)
@@ -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)) {
index ed7205328eb080afcbacf88d577b35739d3f712e..038ab0cc7cd7618a250c9ae2675ca05f24bb4d09 100644 (file)
@@ -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);
 
index 546c2a8a9f0a1d2f95d848ca3da8048bbb964990..8a4e8c007f7f949fb8797d1eb40c902916fb9ba8 100644 (file)
@@ -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);
index 6a9c6856a03d64b4f5cc3cf59621886ef5fa703b..0a361d0d09e8a67d3f4228914a852f781e515d09 100644 (file)
@@ -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);
 }
 
index 5a66665304337aabbc983879f9823df6c6096ccb..139cb2987109143368e1c7f81a2facb4b5fe567d 100644 (file)
@@ -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. */
index c21fa2ba64e8627351c936e78b9898348e8c1ca9..5240de4aff9eedbbeff472c7a9795bc587e2dc9a 100644 (file)
@@ -232,6 +232,9 @@ typedef struct Sequence {
 
   int cache_flag;
   int _pad2[3];
+
+  struct Sequence *orig_sequence;
+  void *_pad3;
 } Sequence;
 
 typedef struct MetaStack {
index f101a29ec22c9b432101f1bde13f942c0e1cdfa8..0f0d057845e2625cd467986897b3379cfb9e7fb2 100644 (file)
@@ -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");
index 29a06eeabf210ac15e21c36815feed7071b6889f..3915c98961498d1d31cf8a28f1f20f0556c9285b 100644 (file)
@@ -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);
index 6bde162f507c3e612a0fe25caf60fe32ed2c4c54..2e27ec81bd0d67f5613d10b7131c8eb8e3200dc0 100644 (file)
@@ -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);
 
index f688f5205729891fde436e9a23af82347757fe39..952382c2e36c8bb038a4ccd457528df17b929caf 100644 (file)
@@ -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)) {
index bbaaab01b18bed120964c97ccfd80006c318af0a..7e54afcb9aae561aeba9e19dadc4b8613f086346 100644 (file)
@@ -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"
 #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();