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 43ee284..9425f39 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 0dcb109..f90429a 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 91e23d3..8d17380 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 d17990d..9fcbf20 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 ec8a252..171635c 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 0cd5176..13aedf6 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 32f0d35..a4bdf02 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 48a62a6..cc6c5e7 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 93e5dd1..9bdc815 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 c3a04a9..8968548 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 64f841d..ef73de5 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 4e3fdfc..2f6b8c0 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 54d5223..a1f8c59 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 7d30209..55295c8 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 26bb1bd..46e8b8e 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 b832473..4c55e4a 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 403c9cf..b7efdc0 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 cf1ebcc..bfb0a2a 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 0345f29..865da20 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 c2cc154..9f48dd2 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 4bc05bc..ef2862a 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 62a6167..09a761d 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 ab6242a..8fc565c 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 abec356..9e3f91b 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 7c03ba8..b3cbeca 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 c2a8804..7f4b5a4 100644 (file)
@@ -19,6 +19,7 @@ set(INC
   ../include
   ../../blenkernel
   ../../blenlib
+  ../../depsgraph
   ../../makesdna
   ../../makesrna
   ../../windowmanager
index 3811739..30ddd8c 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 ba40b8b..83d8133 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 c19b058..2de01e0 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 3450ca5..c9dc980 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 9ef646e..3789b6d 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 4668a9c..d57be0c 100644 (file)
@@ -21,6 +21,7 @@ set(INC
   ../../blenlib
   ../../blentranslation
   ../../gpu
+  ../../depsgraph
   ../../imbuf
   ../../makesdna
   ../../makesrna
index db6cc1a..190c2ed 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 b9b310c..6197a7b 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 ed72053..038ab0c 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 546c2a8..8a4e8c0 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 6a9c685..0a361d0 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 5a66665..139cb29 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 c21fa2b..5240de4 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 f101a29..0f0d057 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 29a06ee..3915c98 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 6bde162..2e27ec8 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 f688f52..952382c 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 bbaaab0..7e54afc 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();