From 38ef2df8f72fe3289beb42284b1f2f3162636519 Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Sun, 21 Feb 2010 18:01:41 +0000 Subject: 2.5 Audio: * Jack Transport support! * Minor sequencer audio corrections. --- intern/audaspace/intern/AUD_C-API.cpp | 63 ++++++++ intern/audaspace/intern/AUD_C-API.h | 13 ++ intern/audaspace/jack/AUD_JackDevice.cpp | 161 +++++++++++++++++---- intern/audaspace/jack/AUD_JackDevice.h | 45 +++++- source/blender/blenkernel/BKE_sound.h | 4 +- source/blender/blenkernel/intern/sequencer.c | 4 +- source/blender/blenkernel/intern/sound.c | 77 ++++++++-- source/blender/editors/include/ED_screen.h | 1 + source/blender/editors/screen/screen_ops.c | 45 +++--- source/blender/makesrna/intern/rna_userdef.c | 2 +- .../blender/windowmanager/intern/wm_event_system.c | 23 +++ source/blender/windowmanager/intern/wm_files.c | 8 +- 12 files changed, 372 insertions(+), 74 deletions(-) diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp index 3c29b5d9e08..d2540d59eda 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -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_device); + if(device) + device->startPlayback(); +#endif +} + +void AUD_stopPlayback() +{ +#ifdef WITH_JACK + AUD_JackDevice* device = dynamic_cast(AUD_device); + if(device) + device->stopPlayback(); +#endif +} + +void AUD_seekSequencer(AUD_Handle* handle, float time) +{ +#ifdef WITH_JACK + AUD_JackDevice* device = dynamic_cast(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_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_device); + if(device) + device->setSyncCallback(function, data); +#endif +} + +int AUD_doesPlayback() +{ +#ifdef WITH_JACK + AUD_JackDevice* device = dynamic_cast(AUD_device); + if(device) + return device->doesPlayback(); +#endif + return -1; +} + #ifdef AUD_DEBUG_MEMORY int AUD_References(int count, const char* text) { diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h index ce1791886de..a252ad904b6 100644 --- a/intern/audaspace/intern/AUD_C-API.h +++ b/intern/audaspace/intern/AUD_C-API.h @@ -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 diff --git a/intern/audaspace/jack/AUD_JackDevice.cpp b/intern/audaspace/jack/AUD_JackDevice.cpp index dfb2a60d629..ae7725be81c 100644 --- a/intern/audaspace/jack/AUD_JackDevice.cpp +++ b/intern/audaspace/jack/AUD_JackDevice.cpp @@ -31,7 +31,7 @@ #include #include -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; +} diff --git a/intern/audaspace/jack/AUD_JackDevice.h b/intern/audaspace/jack/AUD_JackDevice.h index 96388e1ee50..58e34978c1f 100644 --- a/intern/audaspace/jack/AUD_JackDevice.h +++ b/intern/audaspace/jack/AUD_JackDevice.h @@ -33,6 +33,8 @@ class AUD_Buffer; #include #include +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 diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 97a2adb6e6b..fa035d62d62 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -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 diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 2ee913a6b6b..98dbf83f032 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -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"); diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 4e08a52d992..a1a6880569b 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -39,6 +39,26 @@ 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); } diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 5121308c745..aae354b79fa 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -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); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index fae7e7b6c40..0c958654722 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -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; diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 7cb7e69f047..ee2c96bcbd2 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -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) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 4b07aa82239..74679ce89a6 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -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; diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index efa8aa7e819..16776517e40 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -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(); -- cgit v1.2.3