Workspace: Move engines to workspace and Properties Editor cleanup
[blender.git] / source / blender / blenkernel / intern / sound.c
index 3132a8e27e7eaa0d0842e4622c57a3ee79eda96d..6cf310461c1331fea2dd3cbd737910a893c82c46 100644 (file)
 #include "DNA_speaker_types.h"
 
 #ifdef WITH_AUDASPACE
-#  include AUD_SOUND_H
-#  include AUD_SEQUENCE_H
-#  include AUD_HANDLE_H
-#  include AUD_SPECIAL_H
-#  ifdef WITH_SYSTEM_AUDASPACE
-#    include "../../../intern/audaspace/intern/AUD_Set.h"
-#  endif
+#  include <AUD_Sound.h>
+#  include <AUD_Sequence.h>
+#  include <AUD_Handle.h>
+#  include <AUD_Special.h>
+#  include "../../../intern/audaspace/intern/AUD_Set.h"
 #endif
 
 #include "BKE_global.h"
@@ -83,7 +81,7 @@ bSound *BKE_sound_new_file(struct Main *bmain, const char *filepath)
 
        BLI_path_abs(str, path);
 
-       sound = BKE_libblock_alloc(bmain, ID_SO, BLI_path_basename(filepath));
+       sound = BKE_libblock_alloc(bmain, ID_SO, BLI_path_basename(filepath), 0);
        BLI_strncpy(sound->name, filepath, FILE_MAX);
        /* sound->type = SOUND_TYPE_FILE; */ /* XXX unused currently */
 
@@ -147,12 +145,40 @@ void BKE_sound_free(bSound *sound)
 
        BKE_sound_free_waveform(sound);
        
+#endif  /* WITH_AUDASPACE */
        if (sound->spinlock) {
                BLI_spin_end(sound->spinlock);
                MEM_freeN(sound->spinlock);
                sound->spinlock = NULL;
-       }       
-#endif  /* WITH_AUDASPACE */
+       }
+}
+
+/**
+ * Only copy internal data of Sound ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag  Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_sound_copy_data(Main *bmain, bSound *sound_dst, const bSound *UNUSED(sound_src), const int UNUSED(flag))
+{
+       sound_dst->handle = NULL;
+       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... */
+
+       /* Just to be sure, should not have any value actually after reading time. */
+       sound_dst->ipo = NULL;
+       sound_dst->newpackedfile = NULL;
+
+       if (sound_dst->packedfile) {
+               sound_dst->packedfile = dupPackedFile(sound_dst->packedfile);
+       }
+
+       /* Initialize whole runtime (audaspace) stuff. */
+       BKE_sound_load(bmain, sound_dst);
 }
 
 void BKE_sound_make_local(Main *bmain, bSound *sound, const bool lib_local)
@@ -167,6 +193,10 @@ static const char *force_device = NULL;
 #ifdef WITH_JACK
 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)
+               return;
+
        struct Main *bmain = (struct Main *)data;
        struct Scene *scene;
 
@@ -196,7 +226,7 @@ void BKE_sound_init_once(void)
        atexit(BKE_sound_exit_once);
 }
 
-static AUD_Device *sound_device;
+static AUD_Device *sound_device = NULL;
 
 void *BKE_sound_get_device(void)
 {
@@ -205,6 +235,9 @@ void *BKE_sound_get_device(void)
 
 void BKE_sound_init(struct Main *bmain)
 {
+       /* Make sure no instance of the sound system is running, otherwise we get leaks. */
+       BKE_sound_exit();
+
        AUD_DeviceSpecs specs;
        int device, buffersize;
        const char *device_name;
@@ -251,7 +284,8 @@ void BKE_sound_init(struct Main *bmain)
 void BKE_sound_init_main(struct Main *bmain)
 {
 #ifdef WITH_JACK
-       AUD_setSynchronizerCallback(sound_sync_callback, bmain);
+       if (sound_device)
+               AUD_setSynchronizerCallback(sound_sync_callback, bmain);
 #else
        (void)bmain; /* unused */
 #endif
@@ -269,7 +303,6 @@ void BKE_sound_exit_once(void)
        sound_device = NULL;
        AUD_exitOnce();
 
-#ifdef WITH_SYSTEM_AUDASPACE
        if (audio_device_names != NULL) {
                int i;
                for (i = 0; audio_device_names[i]; i++) {
@@ -278,7 +311,6 @@ void BKE_sound_exit_once(void)
                free(audio_device_names);
                audio_device_names = NULL;
        }
-#endif
 }
 
 /* XXX unused currently */
@@ -449,6 +481,16 @@ void BKE_sound_destroy_scene(struct Scene *scene)
                AUD_destroySet(scene->speaker_handles);
 }
 
+void BKE_sound_reset_scene_specs(struct Scene *scene)
+{
+       AUD_Specs specs;
+
+       specs.channels = AUD_Device_getChannels(sound_device);
+       specs.rate = AUD_Device_getRate(sound_device);
+
+       AUD_Sequence_setSpecs(scene->sound_scene, specs);
+}
+
 void BKE_sound_mute_scene(struct Scene *scene, int muted)
 {
        if (scene->sound_scene)
@@ -575,15 +617,10 @@ void BKE_sound_update_sequencer(struct Main *main, bSound *sound)
 
 static void sound_start_play_scene(struct Scene *scene)
 {
-       AUD_Specs specs;
-
        if (scene->playback_handle)
                AUD_Handle_stop(scene->playback_handle);
 
-       specs.channels = AUD_Device_getChannels(sound_device);
-       specs.rate = AUD_Device_getRate(sound_device);
-
-       AUD_Sequence_setSpecs(scene->sound_scene, specs);
+       BKE_sound_reset_scene_specs(scene);
 
        if ((scene->playback_handle = AUD_Device_play(sound_device, scene->sound_scene, 1)))
                AUD_Handle_setLoopCount(scene->playback_handle, -1);
@@ -692,6 +729,10 @@ void BKE_sound_seek_scene(struct Main *bmain, struct Scene *scene)
 
 float BKE_sound_sync_scene(struct Scene *scene)
 {
+       // Ugly: Blender doesn't like it when the animation is played back during rendering
+       if (G.is_rendering)
+               return NAN_FLT;
+
        if (scene->playback_handle) {
                if (scene->audio.flag & AUDIO_SYNC)
                        return AUD_getSynchronizerPosition(scene->playback_handle);
@@ -703,6 +744,10 @@ float BKE_sound_sync_scene(struct Scene *scene)
 
 int BKE_sound_scene_playing(struct Scene *scene)
 {
+       // Ugly: Blender doesn't like it when the animation is played back during rendering
+       if (G.is_rendering)
+               return -1;
+
        if (scene->audio.flag & AUDIO_SYNC)
                return AUD_isSynchronizerPlaying();
        else
@@ -761,13 +806,76 @@ void BKE_sound_read_waveform(bSound *sound, short *stop)
        BLI_spin_unlock(sound->spinlock);
 }
 
-void BKE_sound_update_scene(Main *bmain, struct Scene *scene)
+static void sound_update_base(Scene *scene, Base *base, void *new_set)
 {
-       Object *ob;
-       Base *base;
+       Object *ob = base->object;
        NlaTrack *track;
        NlaStrip *strip;
        Speaker *speaker;
+       float quat[4];
+
+       if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
+               return;
+       }
+
+       ob->id.tag &= ~LIB_TAG_DOIT;
+
+       if ((ob->type != OB_SPEAKER) || !ob->adt) {
+               return;
+       }
+
+       for (track = ob->adt->nla_tracks.first; track; track = track->next) {
+               for (strip = track->strips.first; strip; strip = strip->next) {
+                       if (strip->type != NLASTRIP_TYPE_SOUND) {
+                               continue;
+                       }
+                       speaker = (Speaker *)ob->data;
+
+                       if (AUD_removeSet(scene->speaker_handles, strip->speaker_handle)) {
+                               if (speaker->sound) {
+                                       AUD_SequenceEntry_move(strip->speaker_handle, (double)strip->start / FPS, FLT_MAX, 0);
+                               }
+                               else {
+                                       AUD_Sequence_remove(scene->sound_scene, strip->speaker_handle);
+                                       strip->speaker_handle = NULL;
+                               }
+                       }
+                       else {
+                               if (speaker->sound) {
+                                       strip->speaker_handle = AUD_Sequence_add(scene->sound_scene,
+                                                                               speaker->sound->playback_handle,
+                                                                               (double)strip->start / FPS, FLT_MAX, 0);
+                                       AUD_SequenceEntry_setRelative(strip->speaker_handle, 0);
+                               }
+                       }
+
+                       if (strip->speaker_handle) {
+                               const bool mute = ((strip->flag & NLASTRIP_FLAG_MUTED) || (speaker->flag & SPK_MUTED));
+                               AUD_addSet(new_set, strip->speaker_handle);
+                               AUD_SequenceEntry_setVolumeMaximum(strip->speaker_handle, speaker->volume_max);
+                               AUD_SequenceEntry_setVolumeMinimum(strip->speaker_handle, speaker->volume_min);
+                               AUD_SequenceEntry_setDistanceMaximum(strip->speaker_handle, speaker->distance_max);
+                               AUD_SequenceEntry_setDistanceReference(strip->speaker_handle, speaker->distance_reference);
+                               AUD_SequenceEntry_setAttenuation(strip->speaker_handle, speaker->attenuation);
+                               AUD_SequenceEntry_setConeAngleOuter(strip->speaker_handle, speaker->cone_angle_outer);
+                               AUD_SequenceEntry_setConeAngleInner(strip->speaker_handle, speaker->cone_angle_inner);
+                               AUD_SequenceEntry_setConeVolumeOuter(strip->speaker_handle, speaker->cone_volume_outer);
+
+                               mat4_to_quat(quat, ob->obmat);
+                               AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_LOCATION, CFRA, ob->obmat[3], 1);
+                               AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_ORIENTATION, CFRA, quat, 1);
+                               AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_VOLUME, CFRA, &speaker->volume, 1);
+                               AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_PITCH, CFRA, &speaker->pitch, 1);
+                               AUD_SequenceEntry_setSound(strip->speaker_handle, speaker->sound->playback_handle);
+                               AUD_SequenceEntry_setMuted(strip->speaker_handle, mute);
+                       }
+               }
+       }
+}
+
+void BKE_sound_update_scene(Main *bmain, Scene *scene)
+{
+       Base *base;
        Scene *sce_it;
 
        void *new_set = AUD_createSet();
@@ -776,59 +884,18 @@ void BKE_sound_update_scene(Main *bmain, struct Scene *scene)
 
        /* cheap test to skip looping over all objects (no speakers is a common case) */
        if (!BLI_listbase_is_empty(&bmain->speaker)) {
-               for (SETLOOPER(scene, sce_it, base)) {
-                       ob = base->object;
-                       if ((ob->type != OB_SPEAKER) || !ob->adt) {
-                               continue;
-                       }
-                       for (track = ob->adt->nla_tracks.first; track; track = track->next) {
-                               for (strip = track->strips.first; strip; strip = strip->next) {
-                                       if (strip->type != NLASTRIP_TYPE_SOUND) {
-                                               continue;
-                                       }
-                                       speaker = (Speaker *)ob->data;
-
-                                       if (AUD_removeSet(scene->speaker_handles, strip->speaker_handle)) {
-                                               if (speaker->sound) {
-                                                       AUD_SequenceEntry_move(strip->speaker_handle, (double)strip->start / FPS, FLT_MAX, 0);
-                                               }
-                                               else {
-                                                       AUD_Sequence_remove(scene->sound_scene, strip->speaker_handle);
-                                                       strip->speaker_handle = NULL;
-                                               }
-                                       }
-                                       else {
-                                               if (speaker->sound) {
-                                                       strip->speaker_handle = AUD_Sequence_add(scene->sound_scene,
-                                                                                               speaker->sound->playback_handle,
-                                                                                               (double)strip->start / FPS, FLT_MAX, 0);
-                                                       AUD_SequenceEntry_setRelative(strip->speaker_handle, 0);
-                                               }
-                                       }
-
-                                       if (strip->speaker_handle) {
-                                               const bool mute = ((strip->flag & NLASTRIP_FLAG_MUTED) || (speaker->flag & SPK_MUTED));
-                                               AUD_addSet(new_set, strip->speaker_handle);
-                                               AUD_SequenceEntry_setVolumeMaximum(strip->speaker_handle, speaker->volume_max);
-                                               AUD_SequenceEntry_setVolumeMinimum(strip->speaker_handle, speaker->volume_min);
-                                               AUD_SequenceEntry_setDistanceMaximum(strip->speaker_handle, speaker->distance_max);
-                                               AUD_SequenceEntry_setDistanceReference(strip->speaker_handle, speaker->distance_reference);
-                                               AUD_SequenceEntry_setAttenuation(strip->speaker_handle, speaker->attenuation);
-                                               AUD_SequenceEntry_setConeAngleOuter(strip->speaker_handle, speaker->cone_angle_outer);
-                                               AUD_SequenceEntry_setConeAngleInner(strip->speaker_handle, speaker->cone_angle_inner);
-                                               AUD_SequenceEntry_setConeVolumeOuter(strip->speaker_handle, speaker->cone_volume_outer);
-
-                                               mat4_to_quat(quat, ob->obmat);
-                                               AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_LOCATION, CFRA, ob->obmat[3], 1);
-                                               AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_ORIENTATION, CFRA, quat, 1);
-                                               AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_VOLUME, CFRA, &speaker->volume, 1);
-                                               AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_PITCH, CFRA, &speaker->pitch, 1);
-                                               AUD_SequenceEntry_setSound(strip->speaker_handle, speaker->sound->playback_handle);
-                                               AUD_SequenceEntry_setMuted(strip->speaker_handle, mute);
-                                       }
-                               }
+               BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true);
+
+               for (SceneLayer *scene_layer = scene->render_layers.first; scene_layer; scene_layer = scene_layer->next) {
+                       for (base = scene_layer->object_bases.first; base; base = base->next) {
+                               sound_update_base(scene, base, new_set);
                        }
                }
+
+               for (SETLOOPER_SET_ONLY(scene, sce_it, base)) {
+                       sound_update_base(scene, base, new_set);
+               }
+
        }
 
        while ((handle = AUD_getSet(scene->speaker_handles))) {
@@ -861,28 +928,12 @@ float BKE_sound_get_length(bSound *sound)
 char **BKE_sound_get_device_names(void)
 {
        if (audio_device_names == NULL) {
-#ifdef WITH_SYSTEM_AUDASPACE
                audio_device_names = AUD_getDeviceNames();
-#else
-               static const char *names[] = {
-                       "Null", "SDL", "OpenAL", "JACK", NULL
-               };
-               audio_device_names = (char **)names;
-#endif
        }
 
        return audio_device_names;
 }
 
-bool BKE_sound_is_jack_supported(void)
-{
-#ifdef WITH_SYSTEM_AUDASPACE
-       return 1;
-#else
-       return (bool)AUD_isJackSupported();
-#endif
-}
-
 #else  /* WITH_AUDASPACE */
 
 #include "BLI_utildefines.h"
@@ -897,6 +948,7 @@ void BKE_sound_delete_cache(struct bSound *UNUSED(sound)) {}
 void BKE_sound_load(struct Main *UNUSED(bmain), struct bSound *UNUSED(sound)) {}
 void BKE_sound_create_scene(struct Scene *UNUSED(scene)) {}
 void BKE_sound_destroy_scene(struct Scene *UNUSED(scene)) {}
+void BKE_sound_reset_scene_specs(struct Scene *UNUSED(scene)) {}
 void BKE_sound_mute_scene(struct Scene *UNUSED(scene), int UNUSED(muted)) {}
 void *BKE_sound_scene_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence),
                                       int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; }
@@ -928,5 +980,6 @@ void BKE_sound_set_scene_sound_pan(void *UNUSED(handle), float UNUSED(pan), char
 void BKE_sound_set_scene_volume(struct Scene *UNUSED(scene), float UNUSED(volume)) {}
 void BKE_sound_set_scene_sound_pitch(void *UNUSED(handle), float UNUSED(pitch), char UNUSED(animated)) {}
 float BKE_sound_get_length(struct bSound *UNUSED(sound)) { return 0; }
-bool BKE_sound_is_jack_supported(void) { return false; }
+char **BKE_sound_get_device_names(void) { static char *names[1] = {NULL}; return names; }
+
 #endif  /* WITH_AUDASPACE */