2.5 Audio:
authorJoerg Mueller <nexyon@gmail.com>
Sun, 21 Feb 2010 18:01:41 +0000 (18:01 +0000)
committerJoerg Mueller <nexyon@gmail.com>
Sun, 21 Feb 2010 18:01:41 +0000 (18:01 +0000)
* Jack Transport support!
* Minor sequencer audio corrections.

12 files changed:
intern/audaspace/intern/AUD_C-API.cpp
intern/audaspace/intern/AUD_C-API.h
intern/audaspace/jack/AUD_JackDevice.cpp
intern/audaspace/jack/AUD_JackDevice.h
source/blender/blenkernel/BKE_sound.h
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/sound.c
source/blender/editors/include/ED_screen.h
source/blender/editors/screen/screen_ops.c
source/blender/makesrna/intern/rna_userdef.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_files.c

index 3c29b5d9e08ead6d2000aa9b0eb5f358d6ecbb9c..d2540d59eda3d5001fee7940edf186e3396bd663 100644 (file)
@@ -761,6 +761,69 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
        return length;
 }
 
+void AUD_startPlayback()
+{
+#ifdef WITH_JACK
+       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
+       if(device)
+               device->startPlayback();
+#endif
+}
+
+void AUD_stopPlayback()
+{
+#ifdef WITH_JACK
+       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
+       if(device)
+               device->stopPlayback();
+#endif
+}
+
+void AUD_seekSequencer(AUD_Handle* handle, float time)
+{
+#ifdef WITH_JACK
+       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
+       if(device)
+               device->seekPlayback(time);
+       else
+#endif
+       {
+               AUD_device->seek(handle, time);
+       }
+}
+
+float AUD_getSequencerPosition(AUD_Handle* handle)
+{
+#ifdef WITH_JACK
+       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
+       if(device)
+               return device->getPlaybackPosition();
+       else
+#endif
+       {
+               return AUD_device->getPosition(handle);
+       }
+}
+
+void AUD_setSyncCallback(AUD_syncFunction function, void* data)
+{
+#ifdef WITH_JACK
+       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
+       if(device)
+               device->setSyncCallback(function, data);
+#endif
+}
+
+int AUD_doesPlayback()
+{
+#ifdef WITH_JACK
+       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
+       if(device)
+               return device->doesPlayback();
+#endif
+       return -1;
+}
+
 #ifdef AUD_DEBUG_MEMORY
 int AUD_References(int count, const char* text)
 {
index ce1791886de5be548343d41aef55c3dd3c5cf90e..a252ad904b617a58c58bb512eb47a9d6528a7c8b 100644 (file)
@@ -52,6 +52,7 @@ typedef struct
        typedef void AUD_Device;
        typedef void AUD_SequencerEntry;
        typedef float (*AUD_volumeFunction)(void*, void*, float);
+       typedef void (*AUD_syncFunction)(void*, int, float);
 #endif
 
 /**
@@ -383,6 +384,18 @@ extern void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
 
 extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length);
 
+extern void AUD_startPlayback();
+
+extern void AUD_stopPlayback();
+
+extern void AUD_seekSequencer(AUD_Handle* handle, float time);
+
+extern float AUD_getSequencerPosition(AUD_Handle* handle);
+
+extern void AUD_setSyncCallback(AUD_syncFunction function, void* data);
+
+extern int AUD_doesPlayback();
+
 #ifdef __cplusplus
 }
 #endif
index dfb2a60d6298878d3cf24f56af9d273548cdb28f..ae7725be81c4af7df8267ff6bea77ed0885fd8f2 100644 (file)
@@ -31,7 +31,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-void* AUD_JackDevice::runThread(void* device)
+void* AUD_JackDevice::runMixingThread(void* device)
 {
        ((AUD_JackDevice*)device)->updateRingBuffers();
        return NULL;
@@ -45,10 +45,24 @@ void AUD_JackDevice::updateRingBuffers()
        unsigned int channels = m_specs.channels;
        sample_t* buffer = m_buffer->getBuffer();
        float* deinterleave = m_deinterleavebuf->getBuffer();
+       jack_transport_state_t state;
+       jack_position_t position;
 
-       pthread_mutex_lock(&m_lock);
+       pthread_mutex_lock(&m_mixingLock);
        while(m_valid)
        {
+               if(m_sync > 1)
+               {
+                       if(m_syncFunc)
+                       {
+                               state = jack_transport_query(m_client, &position);
+                               m_syncFunc(m_syncFuncData, state != JackTransportStopped, position.frame / (float) m_specs.rate);
+                       }
+
+                       for(i = 0; i < channels; i++)
+                               jack_ringbuffer_reset(m_ringbuffers[i]);
+               }
+
                size = jack_ringbuffer_write_space(m_ringbuffers[0]);
                for(i = 1; i < channels; i++)
                        if((temp = jack_ringbuffer_write_space(m_ringbuffers[i])) < size)
@@ -71,9 +85,14 @@ void AUD_JackDevice::updateRingBuffers()
                                        size = temp;
                }
 
-               pthread_cond_wait(&m_condition, &m_lock);
+               if(m_sync > 1)
+               {
+                       m_sync = 3;
+               }
+
+               pthread_cond_wait(&m_mixingCondition, &m_mixingLock);
        }
-       pthread_mutex_unlock(&m_lock);
+       pthread_mutex_unlock(&m_mixingLock);
 }
 
 int AUD_JackDevice::jack_mix(jack_nframes_t length, void *data)
@@ -83,27 +102,67 @@ int AUD_JackDevice::jack_mix(jack_nframes_t length, void *data)
        int count = device->m_specs.channels;
        char* buffer;
 
-       size_t temp;
-       size_t readsamples = jack_ringbuffer_read_space(device->m_ringbuffers[0]);
-       for(i = 1; i < count; i++)
-               if((temp = jack_ringbuffer_read_space(device->m_ringbuffers[i])) < readsamples)
-                       readsamples = temp;
+       if(device->m_sync)
+       {
+               // play silence while syncing
+               for(unsigned int i = 0; i < count; i++)
+                       memset(jack_port_get_buffer(device->m_ports[i], length), 0, length * sizeof(float));
+       }
+       else
+       {
+               size_t temp;
+               size_t readsamples = jack_ringbuffer_read_space(device->m_ringbuffers[0]);
+               for(i = 1; i < count; i++)
+                       if((temp = jack_ringbuffer_read_space(device->m_ringbuffers[i])) < readsamples)
+                               readsamples = temp;
 
-       readsamples = AUD_MIN(readsamples / sizeof(float), length);
+               readsamples = AUD_MIN(readsamples / sizeof(float), length);
 
-       for(unsigned int i = 0; i < count; i++)
-       {
-               buffer = (char*)jack_port_get_buffer(device->m_ports[i], length);
-               jack_ringbuffer_read(device->m_ringbuffers[i], buffer, readsamples * sizeof(float));
-               if(readsamples < length)
-                       memset(buffer + readsamples * sizeof(float), 0, (length - readsamples) * sizeof(float));
+               for(unsigned int i = 0; i < count; i++)
+               {
+                       buffer = (char*)jack_port_get_buffer(device->m_ports[i], length);
+                       jack_ringbuffer_read(device->m_ringbuffers[i], buffer, readsamples * sizeof(float));
+                       if(readsamples < length)
+                               memset(buffer + readsamples * sizeof(float), 0, (length - readsamples) * sizeof(float));
+               }
+
+               if(pthread_mutex_trylock(&(device->m_mixingLock)) == 0)
+               {
+                       pthread_cond_signal(&(device->m_mixingCondition));
+                       pthread_mutex_unlock(&(device->m_mixingLock));
+               }
        }
 
-       if(pthread_mutex_trylock(&(device->m_lock)) == 0)
+       return 0;
+}
+
+int AUD_JackDevice::jack_sync(jack_transport_state_t state, jack_position_t* pos, void* data)
+{
+       AUD_JackDevice* device = (AUD_JackDevice*)data;
+
+       if(state == JackTransportStopped)
+               return 1;
+
+       if(pthread_mutex_trylock(&(device->m_mixingLock)) == 0)
        {
-               pthread_cond_signal(&(device->m_condition));
-               pthread_mutex_unlock(&(device->m_lock));
+               if(device->m_sync > 2)
+               {
+                       if(device->m_sync == 3)
+                       {
+                               device->m_sync = 0;
+                               pthread_mutex_unlock(&(device->m_mixingLock));
+                               return 1;
+                       }
+               }
+               else
+               {
+                       device->m_sync = 2;
+                       pthread_cond_signal(&(device->m_mixingCondition));
+               }
+               pthread_mutex_unlock(&(device->m_mixingLock));
        }
+       else if(!device->m_sync)
+               device->m_sync = 1;
 
        return 0;
 }
@@ -134,6 +193,7 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize)
        // set callbacks
        jack_set_process_callback(m_client, AUD_JackDevice::jack_mix, this);
        jack_on_shutdown(m_client, AUD_JackDevice::jack_shutdown, this);
+       jack_set_sync_callback(m_client, AUD_JackDevice::jack_sync, this);
 
        // register our output channels which are called ports in jack
        m_ports = new jack_port_t*[m_specs.channels]; AUD_NEW("jack_port")
@@ -170,6 +230,14 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize)
 
        create();
 
+       m_valid = true;
+       m_playing = false;
+       m_sync = 0;
+       m_syncFunc = NULL;
+
+       pthread_mutex_init(&m_mixingLock, NULL);
+       pthread_cond_init(&m_mixingCondition, NULL);
+
        try
        {
                // activate the client
@@ -185,6 +253,8 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize)
                for(unsigned int i = 0; i < specs.channels; i++)
                        jack_ringbuffer_free(m_ringbuffers[i]);
                delete[] m_ringbuffers; AUD_DELETE("jack_buffers")
+               pthread_mutex_destroy(&m_mixingLock);
+               pthread_cond_destroy(&m_mixingCondition);
                destroy();
                throw;
        }
@@ -199,16 +269,11 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize)
                free(ports);
        }
 
-       m_valid = true;
-
-       pthread_mutex_init(&m_lock, NULL);
-       pthread_cond_init(&m_condition, NULL);
-
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
 
-       pthread_create(&m_thread, &attr, runThread, this);
+       pthread_create(&m_mixingThread, &attr, runMixingThread, this);
 
        pthread_attr_destroy(&attr);
 }
@@ -221,13 +286,13 @@ AUD_JackDevice::~AUD_JackDevice()
 
        delete[] m_ports; AUD_DELETE("jack_port")
 
-       pthread_mutex_lock(&m_lock);
-       pthread_cond_signal(&m_condition);
-       pthread_mutex_unlock(&m_lock);
-       pthread_join(m_thread, NULL);
+       pthread_mutex_lock(&m_mixingLock);
+       pthread_cond_signal(&m_mixingCondition);
+       pthread_mutex_unlock(&m_mixingLock);
+       pthread_join(m_mixingThread, NULL);
 
-       pthread_cond_destroy(&m_condition);
-       pthread_mutex_destroy(&m_lock);
+       pthread_cond_destroy(&m_mixingCondition);
+       pthread_mutex_destroy(&m_mixingLock);
        delete m_buffer; AUD_DELETE("buffer");
        delete m_deinterleavebuf; AUD_DELETE("buffer");
        for(unsigned int i = 0; i < m_specs.channels; i++)
@@ -241,3 +306,37 @@ void AUD_JackDevice::playing(bool playing)
 {
        // Do nothing.
 }
+
+void AUD_JackDevice::startPlayback()
+{
+       jack_transport_start(m_client);
+}
+
+void AUD_JackDevice::stopPlayback()
+{
+       jack_transport_stop(m_client);
+}
+
+void AUD_JackDevice::seekPlayback(float time)
+{
+       if(time >= 0.0f)
+               jack_transport_locate(m_client, time * m_specs.rate);
+}
+
+void AUD_JackDevice::setSyncCallback(AUD_syncFunction sync, void* data)
+{
+       m_syncFunc = sync;
+       m_syncFuncData = data;
+}
+
+float AUD_JackDevice::getPlaybackPosition()
+{
+       jack_position_t position;
+       jack_transport_query(m_client, &position);
+       return position.frame / (float) m_specs.rate;
+}
+
+bool AUD_JackDevice::doesPlayback()
+{
+       return jack_transport_query(m_client, NULL) != JackTransportStopped;
+}
index 96388e1ee50f130cf0a949a8042458d62d409c88..58e34978c1ff789e80d04fe38911b93c70021820 100644 (file)
@@ -33,6 +33,8 @@ class AUD_Buffer;
 #include <jack.h>
 #include <ringbuffer.h>
 
+typedef void (*AUD_syncFunction)(void*, int, float);
+
 /**
  * This device plays back through Jack.
  */
@@ -56,6 +58,8 @@ private:
 
        AUD_Buffer* m_deinterleavebuf;
 
+       jack_ringbuffer_t** m_ringbuffers;
+
        /**
         * Whether the device is valid.
         */
@@ -75,20 +79,40 @@ private:
         */
        static int jack_mix(jack_nframes_t length, void *data);
 
-       static void* runThread(void* device);
+       static int jack_sync(jack_transport_state_t state, jack_position_t* pos, void* data);
 
-       void updateRingBuffers();
+       /**
+        * Last Jack Transport playing state.
+        */
+       bool m_playing;
 
-       jack_ringbuffer_t** m_ringbuffers;
+       /**
+        * Syncronisation state.
+        */
+       int m_sync;
 
        /**
-        * The streaming thread.
+        * External syncronisation callback function.
         */
-       pthread_t m_thread;
+       AUD_syncFunction m_syncFunc;
 
-       pthread_mutex_t m_lock;
+       /**
+        * Data for the sync function.
+        */
+       void* m_syncFuncData;
+
+       /**
+        * The mixing thread.
+        */
+       pthread_t m_mixingThread;
+
+       pthread_mutex_t m_mixingLock;
 
-       pthread_cond_t m_condition;
+       pthread_cond_t m_mixingCondition;
+
+       static void* runMixingThread(void* device);
+
+       void updateRingBuffers();
 
 protected:
        virtual void playing(bool playing);
@@ -105,6 +129,13 @@ public:
         * Closes the Jack client.
         */
        virtual ~AUD_JackDevice();
+
+       void startPlayback();
+       void stopPlayback();
+       void seekPlayback(float time);
+       void setSyncCallback(AUD_syncFunction sync, void* data);
+       float getPlaybackPosition();
+       bool doesPlayback();
 };
 
 #endif //AUD_JACKDEVICE
index 97a2adb6e6b28b9fca516dc80f47d4873695df79..fa035d62d6298ab67ebbe0f3681b49f8431ab0b8 100644 (file)
@@ -38,7 +38,7 @@ struct ListBase;
 struct Main;
 struct Sequence;
 
-void sound_init();
+void sound_init(struct Main *main);
 
 void sound_exit();
 
@@ -88,6 +88,8 @@ void sound_seek_scene(struct bContext *C);
 
 float sound_sync_scene(struct Scene *scene);
 
+int sound_scene_playing(struct Scene *scene);
+
 int sound_read_sound_buffer(struct bSound* sound, float* buffer, int length);
 
 #endif
index 2ee913a6b6bfa1156a92460bd0fee8db9967b203..98dbf83f032936608e7f87cd0192f5cd4374f2b6 100644 (file)
@@ -614,7 +614,7 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq)
                }
                seq->strip->len = seq->len;
        } else if (seq->type == SEQ_SOUND) {
-               seq->len = AUD_getInfo(seq->sound->playback_handle).length * FPS;
+               seq->len = ceil(AUD_getInfo(seq->sound->playback_handle).length * FPS);
                seq->len -= seq->anim_startofs;
                seq->len -= seq->anim_endofs;
                if (seq->len < 0) {
@@ -3848,7 +3848,7 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
 
        /* basic defaults */
        seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
-       strip->len = seq->len = (int) (info.length * FPS);
+       strip->len = seq->len = ceil(info.length * FPS);
        strip->us= 1;
 
        strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
index 4e08a52d992a0d3526a3ad8b1a528577e2b98a6d..a1a6880569b398476a4fb705abec1b9c43248d03 100644 (file)
 
 static int force_device = -1;
 
+static void sound_sync_callback(void* data, int mode, float time)
+{
+       struct Main* main = (struct Main*)data;
+       struct Scene* scene;
+
+       scene = main->scene.first;
+       while(scene)
+       {
+               if(scene->audio.flag & AUDIO_SYNC)
+               {
+                       if(mode)
+                               sound_play_scene(scene);
+                       else
+                               sound_stop_scene(scene);
+                       AUD_seek(scene->sound_scene_handle, time);
+               }
+               scene = scene->id.next;
+       }
+}
+
 int sound_define_from_str(char *str)
 {
        if (BLI_strcaseeq(str, "NULL"))
@@ -58,7 +78,7 @@ void sound_force_device(int device)
        force_device = device;
 }
 
-void sound_init()
+void sound_init(struct Main *main)
 {
        AUD_DeviceSpecs specs;
        int device, buffersize;
@@ -86,6 +106,7 @@ void sound_init()
 
        if(!AUD_init(device, specs, buffersize))
                AUD_init(AUD_NULL_DEVICE, specs, buffersize);
+       AUD_setSyncCallback(sound_sync_callback, main);
 }
 
 void sound_exit()
@@ -353,14 +374,24 @@ void sound_start_play_scene(struct Scene *scene)
 
 void sound_play_scene(struct Scene *scene)
 {
+       AUD_Status status;
        AUD_lock();
 
-       if(!scene->sound_scene_handle || AUD_getStatus(scene->sound_scene_handle) == AUD_STATUS_INVALID)
+       status = AUD_getStatus(scene->sound_scene_handle);
+
+       if(status == AUD_STATUS_INVALID)
                sound_start_play_scene(scene);
 
-       AUD_seek(scene->sound_scene_handle, CFRA / FPS);
        AUD_setLoop(scene->sound_scene_handle, -1, -1);
-       AUD_resume(scene->sound_scene_handle);
+
+       if(status != AUD_STATUS_PLAYING)
+       {
+               AUD_seek(scene->sound_scene_handle, CFRA / FPS);
+               AUD_resume(scene->sound_scene_handle);
+       }
+
+       if(scene->audio.flag & AUDIO_SYNC)
+               AUD_startPlayback();
 
        AUD_unlock();
 }
@@ -368,15 +399,21 @@ void sound_play_scene(struct Scene *scene)
 void sound_stop_scene(struct Scene *scene)
 {
        AUD_pause(scene->sound_scene_handle);
+
+       if(scene->audio.flag & AUDIO_SYNC)
+               AUD_stopPlayback();
 }
 
 void sound_seek_scene(struct bContext *C)
 {
        struct Scene *scene = CTX_data_scene(C);
+       AUD_Status status;
 
        AUD_lock();
 
-       if(!scene->sound_scene_handle || AUD_getStatus(scene->sound_scene_handle) == AUD_STATUS_INVALID)
+       status = AUD_getStatus(scene->sound_scene_handle);
+
+       if(status == AUD_STATUS_INVALID)
        {
                sound_start_play_scene(scene);
                AUD_pause(scene->sound_scene_handle);
@@ -385,21 +422,43 @@ void sound_seek_scene(struct bContext *C)
        if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer)
        {
                AUD_setLoop(scene->sound_scene_handle, -1, 1 / FPS);
-               AUD_seek(scene->sound_scene_handle, CFRA / FPS);
+               if(scene->audio.flag & AUDIO_SYNC)
+                       AUD_seekSequencer(scene->sound_scene_handle, CFRA / FPS);
+               else
+                       AUD_seek(scene->sound_scene_handle, CFRA / FPS);
                AUD_resume(scene->sound_scene_handle);
        }
        else
-               AUD_seek(scene->sound_scene_handle, CFRA / FPS);
+       {
+               if(scene->audio.flag & AUDIO_SYNC)
+                       AUD_seekSequencer(scene->sound_scene_handle, CFRA / FPS);
+               else
+               {
+                       if(status == AUD_STATUS_PLAYING)
+                               AUD_seek(scene->sound_scene_handle, CFRA / FPS);
+               }
+       }
 
        AUD_unlock();
 }
 
 float sound_sync_scene(struct Scene *scene)
 {
-       return AUD_getPosition(scene->sound_scene_handle);
+       if(scene->audio.flag & AUDIO_SYNC)
+               return AUD_getSequencerPosition(scene->sound_scene_handle);
+       else
+               return AUD_getPosition(scene->sound_scene_handle);
+}
+
+int sound_scene_playing(struct Scene *scene)
+{
+       if(scene->audio.flag & AUDIO_SYNC)
+               return AUD_doesPlayback();
+       else
+               return -1;
 }
 
-int sound_read_sound_buffer(bSound* sound, float* buffer, int length)
+int sound_read_sound_buffer(struct bSound* sound, float* buffer, int length)
 {
        return AUD_readSound(sound->cache, buffer, length);
 }
index 5121308c745d703e821e19dac910b11e445b5641..aae354b79fa6cf4cb942dcc241d8191c1b452770 100644 (file)
@@ -108,6 +108,7 @@ void        ED_screen_new_window(struct bContext *C, struct rcti *position, int type);
 /* anim */
 void   ED_update_for_newframe(const struct bContext *C, int mute);
 void   ED_refresh_viewport_fps(struct bContext *C);
+int ED_screen_animation_play(struct bContext *C, int sync, int mode);
 
 /* screen keymaps */
 void   ED_operatortypes_screen(void);
index fae7e7b6c40957846d9fe6cf2e77c4382714cede..0c958654722485a9b04e356f53dd35d127ab1469 100644 (file)
@@ -2537,11 +2537,11 @@ static void SCREEN_OT_animation_step(wmOperatorType *ot)
 /* ****************** anim player, starts or ends timer ***************** */
 
 /* toggle operator */
-static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
+int ED_screen_animation_play(bContext *C, int sync, int mode)
 {
        bScreen *screen= CTX_wm_screen(C);
        struct Scene* scene = CTX_data_scene(C);
-       
+
        if(screen->animtimer) {
                /* stop playback now */
                ED_screen_animation_timer(C, 0, 0, 0);
@@ -2549,45 +2549,52 @@ static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
        }
        else {
                ScrArea *sa= CTX_wm_area(C);
-               int mode= (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1;
-               int sync= -1;
+
                if(mode == 1) // XXX only play audio forwards!?
                        sound_play_scene(scene);
-               
-               if(RNA_property_is_set(op->ptr, "sync"))
-                       sync= (RNA_boolean_get(op->ptr, "sync"));
-               
+
                /* timeline gets special treatment since it has it's own menu for determining redraws */
                if ((sa) && (sa->spacetype == SPACE_TIME)) {
                        SpaceTime *stime= (SpaceTime *)sa->spacedata.first;
-                       
+
                        ED_screen_animation_timer(C, stime->redraws, sync, mode);
-                       
+
                        /* update region if TIME_REGION was set, to leftmost 3d window */
                        ED_screen_animation_timer_update(screen, stime->redraws);
                }
                else {
                        int redraws = TIME_REGION|TIME_ALL_3D_WIN;
-                       
+
                        /* XXX - would like a better way to deal with this situation - Campbell */
-                       if((sa) && (sa->spacetype == SPACE_SEQ)) {
+                       if((!sa) || (sa->spacetype == SPACE_SEQ)) {
                                redraws |= TIME_SEQ;
                        }
-                       
+
                        ED_screen_animation_timer(C, redraws, sync, mode);
-                       
+
                        if(screen->animtimer) {
                                wmTimer *wt= screen->animtimer;
                                ScreenAnimData *sad= wt->customdata;
-                               
+
                                sad->ar= CTX_wm_region(C);
                        }
                }
        }
-       
+
        return OPERATOR_FINISHED;
 }
 
+static int screen_animation_play_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       int mode= (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1;
+       int sync= -1;
+
+       if(RNA_property_is_set(op->ptr, "sync"))
+               sync= (RNA_boolean_get(op->ptr, "sync"));
+
+       return ED_screen_animation_play(C, sync, mode);
+}
+
 static void SCREEN_OT_animation_play(wmOperatorType *ot)
 {
        /* identifiers */
@@ -2596,12 +2603,12 @@ static void SCREEN_OT_animation_play(wmOperatorType *ot)
        ot->idname= "SCREEN_OT_animation_play";
        
        /* api callbacks */
-       ot->invoke= screen_animation_play;
+       ot->invoke= screen_animation_play_invoke;
        
        ot->poll= ED_operator_screenactive;
        
        RNA_def_boolean(ot->srna, "reverse", 0, "Play in Reverse", "Animation is played backwards");
-       RNA_def_boolean(ot->srna, "sync", 0, "Sync", "Drop frames to maintain framerate and stay in sync with audio.");
+       RNA_def_boolean(ot->srna, "sync", 0, "Sync", "Drop frames to maintain framerate");
 }
 
 static int screen_animation_cancel(bContext *C, wmOperator *op, wmEvent *event)
@@ -2619,7 +2626,7 @@ static int screen_animation_cancel(bContext *C, wmOperator *op, wmEvent *event)
                WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
                
                /* call the other "toggling" operator to clean up now */
-               return screen_animation_play(C, op, event);
+               return screen_animation_play_invoke(C, op, event);
        }
        
        return OPERATOR_PASS_THROUGH;
index 7cb7e69f0478493f7204e28cba5f3f0c740363d8..ee2c96bcbd2a011ec2f197ffaaf6d75b824463a5 100644 (file)
@@ -176,7 +176,7 @@ static PointerRNA rna_UserDef_system_get(PointerRNA *ptr)
 
 static void rna_UserDef_audio_update(Main *bmain, Scene *scene, PointerRNA *ptr)
 {
-       sound_init();
+       sound_init(bmain);
 }
 
 static void rna_UserDef_weight_color_update(Main *bmain, Scene *scene, PointerRNA *ptr)
index 4b07aa822391a9e6861a4ffa193a1265c9a70fc4..74679ce89a68920e62119758997f82f0a86d06d7 100644 (file)
@@ -50,6 +50,7 @@
 #include "BKE_scene.h"
 #include "BKE_screen.h"
 #include "BKE_utildefines.h"
+#include "BKE_sound.h"
 
 #include "ED_fileselect.h"
 #include "ED_info.h"
@@ -1530,6 +1531,28 @@ void wm_event_do_handlers(bContext *C)
                
                if( win->screen==NULL )
                        wm_event_free_all(win);
+               else
+               {
+                       if(win->screen->scene)
+                       {
+                               int playing = sound_scene_playing(win->screen->scene);
+                               if(playing != -1)
+                               {
+                                       if(((playing == 1) && (!win->screen->animtimer)) || ((playing == 0) && (win->screen->animtimer)))
+                                       {
+                                               CTX_wm_window_set(C, win);
+                                               CTX_wm_screen_set(C, win->screen);
+                                               CTX_data_scene_set(C, win->screen->scene);
+
+                                               ED_screen_animation_play(C, -1, 1);
+
+                                               CTX_data_scene_set(C, NULL);
+                                               CTX_wm_screen_set(C, NULL);
+                                               CTX_wm_window_set(C, NULL);
+                                       }
+                               }
+                       }
+               }
                
                while( (event= win->queue.first) ) {
                        int action = WM_HANDLER_CONTINUE;
index efa8aa7e8199c712ece78f059610de1aa48f43a4..16776517e40344129c855d6aa8d42ee82b71dff0 100644 (file)
@@ -236,11 +236,11 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist)
 }
 
 /* in case UserDef was read, we re-initialize all, and do versioning */
-static void wm_init_userdef()
+static void wm_init_userdef(bContext *C)
 {
        UI_init_userdef();
        MEM_CacheLimiter_set_maximum(U.memcachelimit * 1024 * 1024);
-       sound_init();
+       sound_init(CTX_data_main(C));
 }
 
 void WM_read_file(bContext *C, char *name, ReportList *reports)
@@ -269,7 +269,7 @@ void WM_read_file(bContext *C, char *name, ReportList *reports)
                
 // XXX         mainwindow_set_filename_to_title(G.main->name);
 
-               if(retval==2) wm_init_userdef();        // in case a userdef is read from regular .blend
+               if(retval==2) wm_init_userdef(C);       // in case a userdef is read from regular .blend
                
                if (retval!=0) {
                        G.relbase_valid = 1;
@@ -338,7 +338,7 @@ int WM_read_homefile(bContext *C, wmOperator *op)
 
        strcpy(G.sce, scestr); /* restore */
        
-       wm_init_userdef();
+       wm_init_userdef(C);
        
        /* When loading factory settings, the reset solid OpenGL lights need to be applied. */
        if (!G.background) GPU_default_lights();