X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fcpp%2FCPulseAudioClient.cpp;h=0e0bb287ec9cb00a30fc0a1d652570a27a13155a;hb=988beac45f9052b97aad88d14079537c36f68d6a;hp=1ac1c0d6c324725325dad64eab3aac629e832c97;hpb=9699cfb8be7219bafc69f8a7d3fcb97d25b181b4;p=platform%2Fcore%2Fapi%2Faudio-io.git diff --git a/src/cpp/CPulseAudioClient.cpp b/src/cpp/CPulseAudioClient.cpp index 1ac1c0d..0e0bb28 100644 --- a/src/cpp/CPulseAudioClient.cpp +++ b/src/cpp/CPulseAudioClient.cpp @@ -15,7 +15,6 @@ */ -#include #include "CAudioIODef.h" #include #include @@ -52,7 +51,8 @@ CPulseAudioClient::CPulseAudioClient( __mSyncReadLength(0), __mIsUsedSyncRead(false), __mIsFirstStream(false), - __mIsDraining(false) { + __mIsDraining(false), + __mIsStarted(false) { } CPulseAudioClient::~CPulseAudioClient() { @@ -164,6 +164,15 @@ void CPulseAudioClient::__streamCaptureCb(pa_stream* s, size_t length, void* use pClient->__mpListener->onStream(pClient, length); } +#ifndef DISABLE_MOBILE_BACK_COMP +static void __dummy_write(pa_stream* s, size_t length) { + char* dummy = new char[length]; + memset(dummy, 0, length); + pa_stream_write(s, dummy, length, NULL, 0LL, PA_SEEK_RELATIVE); + delete [] dummy; +} +#endif + void CPulseAudioClient::__streamPlaybackCb(pa_stream* s, size_t length, void* user_data) { assert(s); assert(user_data); @@ -171,20 +180,31 @@ void CPulseAudioClient::__streamPlaybackCb(pa_stream* s, size_t length, void* us CPulseAudioClient* pClient = static_cast(user_data); assert(pClient->__mpListener); +#ifndef DISABLE_MOBILE_BACK_COMP + if (pClient->__mIsInit == false) { + AUDIO_IO_LOGD("Occurred this listener when an out stream is on the way to create : Write dummy, length[%d]", length); + __dummy_write(s, length); + return; + } + if (pClient->isCorked()) { + AUDIO_IO_LOGD("Occurred this listener when an out stream is CORKED : Write dummy, length[%d]", length); + __dummy_write(s, length); + return; + } +#endif + pClient->__mpListener->onStream(pClient, length); +#ifndef DISABLE_MOBILE_BACK_COMP /* If stream is not written in first callback during prepare, then write dummy data to ensure the start */ - if (pClient->__mIsFirstStream) { - AUDIO_IO_LOGD("Write dummy, length [%d]", length); - - char* dummy = new char[length]; - memset(dummy, 0, length); - pa_stream_write(s, dummy, length, NULL, 0LL, PA_SEEK_RELATIVE); - delete [] dummy; - + if (pClient->__mSpec.getStreamLatency() == CPulseStreamSpec::EStreamLatency::STREAM_LATENCY_OUTPUT_DEFAULT_ASYNC && + pClient->__mIsFirstStream) { + AUDIO_IO_LOGW("[async] Write dummy of length[%d] since not written in first callback during prepare", length); + __dummy_write(s, length); pClient->__mIsFirstStream = false; } +#endif } void CPulseAudioClient::__streamLatencyUpdateCb(pa_stream* s, void* user_data) { @@ -196,6 +216,28 @@ void CPulseAudioClient::__streamLatencyUpdateCb(pa_stream* s, void* user_data) { pa_threaded_mainloop_signal(pClient->__mpMainloop, 0); } +void CPulseAudioClient::__streamStartedCb(pa_stream* s, void* user_data) { + assert(s); + assert(user_data); + + CPulseAudioClient* pClient = static_cast(user_data); + + AUDIO_IO_LOGD("stream %p started.", pClient); + + pClient->__mIsStarted = true; +} + +void CPulseAudioClient::__streamUnderflowCb(pa_stream* s, void* user_data) { + assert(s); + assert(user_data); + + CPulseAudioClient* pClient = static_cast(user_data); + + AUDIO_IO_LOGD("stream %p UnderFlow...", pClient); + + pClient->__mIsStarted = false; +} + void CPulseAudioClient::__streamEventCb(pa_stream* s, const char *name, pa_proplist *pl, void *user_data) { assert(s); assert(user_data); @@ -338,6 +380,10 @@ void CPulseAudioClient::initialize() { pa_stream_set_write_callback(__mpStream, __streamPlaybackCb, this); pa_stream_set_latency_update_callback(__mpStream, __streamLatencyUpdateCb, this); pa_stream_set_event_callback(__mpStream, __streamEventCb, this); + if (__mDirection == EStreamDirection::STREAM_DIRECTION_PLAYBACK) { + pa_stream_set_started_callback(__mpStream, __streamStartedCb, this); + pa_stream_set_underflow_callback(__mpStream, __streamUnderflowCb, this); + } // Connect stream with PA Server @@ -345,6 +391,9 @@ void CPulseAudioClient::initialize() { pa_stream_flags_t flags = static_cast( PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | +#ifndef DISABLE_MOBILE_BACK_COMP + PA_STREAM_START_CORKED | +#endif PA_STREAM_AUTO_TIMING_UPDATE); ret = pa_stream_connect_playback(__mpStream, NULL, NULL, flags, NULL, NULL); @@ -352,6 +401,9 @@ void CPulseAudioClient::initialize() { pa_stream_flags_t flags = static_cast( PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | +#ifndef DISABLE_MOBILE_BACK_COMP + PA_STREAM_START_CORKED | +#endif PA_STREAM_AUTO_TIMING_UPDATE); ret = pa_stream_connect_record(__mpStream, NULL, NULL, flags); @@ -398,22 +450,21 @@ void CPulseAudioClient::initialize() { void CPulseAudioClient::finalize() { AUDIO_IO_LOGD(""); - if (__mIsInit == false) { - return; - } - if (isInThread() == false) + if (__mpMainloop && isInThread() == false) pa_threaded_mainloop_lock(__mpMainloop); /* clear callbacks */ - if (__mDirection == EStreamDirection::STREAM_DIRECTION_PLAYBACK) - pa_stream_set_write_callback(__mpStream, NULL, NULL); - else - pa_stream_set_read_callback(__mpStream, NULL, NULL); - pa_stream_set_latency_update_callback(__mpStream, NULL, NULL); - pa_stream_set_event_callback(__mpStream, NULL, NULL); - - if (isInThread() == false) + if (__mpStream) { + if (__mDirection == EStreamDirection::STREAM_DIRECTION_PLAYBACK) + pa_stream_set_write_callback(__mpStream, NULL, NULL); + else + pa_stream_set_read_callback(__mpStream, NULL, NULL); + pa_stream_set_latency_update_callback(__mpStream, NULL, NULL); + pa_stream_set_event_callback(__mpStream, NULL, NULL); + } + + if (__mpMainloop && isInThread() == false) pa_threaded_mainloop_unlock(__mpMainloop); /* Wait for drain complete if draining before finalize */ @@ -630,7 +681,7 @@ int CPulseAudioClient::write(const void* data, size_t length) { int ret = 0; #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("data[%p], length[%d]", data, length); + AUDIO_IO_LOGD("data[%p], length[%d], First[%d]", data, length, __mIsFirstStream); #endif if (pa_stream_is_corked(__mpStream)) { AUDIO_IO_LOGW("stream is corked...do uncork here first!!!!"); @@ -712,7 +763,9 @@ bool CPulseAudioClient::isCorked() { isCork = pa_stream_is_corked(__mpStream); } +#ifdef _AUDIO_IO_DEBUG_TIMING_ AUDIO_IO_LOGD("isCork[%d]", isCork); +#endif return static_cast(isCork); } @@ -723,8 +776,20 @@ bool CPulseAudioClient::drain() { checkRunningState(); - if (__mIsDraining) + if (isCorked()) { + AUDIO_IO_LOGW("Corked..."); + return true; + } + + if (__mIsDraining) { AUDIO_IO_LOGW("already draining..."); + return true; + } + + if (!__mIsStarted) { + AUDIO_IO_LOGW("stream not started yet...skip drain"); + return true; + } if (isInThread() == false) { AUDIO_IO_LOGD("drain"); @@ -736,6 +801,7 @@ bool CPulseAudioClient::drain() { } pa_operation_unref(o); pa_threaded_mainloop_unlock(__mpMainloop); + AUDIO_IO_LOGD("drain done"); } else { AUDIO_IO_LOGD("drain in thread"); pa_operation_unref(pa_stream_drain(__mpStream, __successDrainCbInThread, this));