#include <assert.h>
#include "CAudioIODef.h"
-#define AUDIO_IO_DEBUG
-
using namespace std;
using namespace tizen_media_audio;
if (mState == mStatePrev)
return;
- AUDIO_IO_LOGD("current(%d), previous(%d), by_policy(%d)", mState, mStatePrev, mByPolicy);
+ const char* state_string[] = { "NONE", "IDLE", "RUNNING", "PAUSED" };
+
+ AUDIO_IO_LOGD("previous(%s,%d) ===> current(%s,%d), by_policy(%d)",
+ state_string[(int)mStatePrev], mStatePrev, state_string[(int)mState], mState, mByPolicy);
if (mStateChangedCallback.onStateChanged != NULL) {
mStateChangedCallback.onStateChanged(mState, mStatePrev, mByPolicy, mStateChangedCallback.mUserData);
}
try {
- AUDIO_IO_LOGD("prepare");
+ AUDIO_IO_LOGD("------> prepare done");
/* Do nothing */
} catch (CAudioError e) {
throw e;
}
try {
- AUDIO_IO_LOGD("unprepare");
+ AUDIO_IO_LOGD("unprepare ----->");
/* Do nothing */
} catch (CAudioError e) {
throw e;
}
try {
- internalLock();
- AUDIO_IO_LOGD("drain");
- mpPulseAudioClient->drain();
- internalUnlock();
+ if (mpPulseAudioClient->isInThread()) {
+ mpPulseAudioClient->drain();
+ } else {
+ internalLock();
+ mpPulseAudioClient->drain();
+ internalUnlock();
+ }
} catch (CAudioError e) {
- internalUnlock();
+ if (!mpPulseAudioClient->isInThread()) {
+ internalUnlock();
+ }
throw e;
}
}
}
try {
- internalLock();
- AUDIO_IO_LOGD("flush");
- mpPulseAudioClient->flush();
- internalUnlock();
+ if (mpPulseAudioClient->isInThread()) {
+ mpPulseAudioClient->flush();
+ } else {
+ internalLock();
+ mpPulseAudioClient->flush();
+ internalUnlock();
+ }
} catch (CAudioError e) {
- internalUnlock();
+ if (!mpPulseAudioClient->isInThread()) {
+ internalUnlock();
+ }
throw e;
}
}
#include <mm.h>
#include "CAudioIODef.h"
+#include <unistd.h>
#ifdef ENABLE_DPM
#include <dpm/restriction.h>
#endif
* class CPulseAudioClient
*/
const char* CPulseAudioClient::CLIENT_NAME = "AUDIO_IO_PA_CLIENT";
+static const unsigned int drain_wait_interval = 10000;
+static const unsigned int drain_wait_max_count = 30;
CPulseAudioClient::CPulseAudioClient(
EStreamDirection direction,
__mSyncReadIndex(0),
__mSyncReadLength(0),
__mIsUsedSyncRead(false),
- __mIsFirstStream(false) {
+ __mIsFirstStream(false),
+ __mIsDraining(false) {
}
CPulseAudioClient::~CPulseAudioClient() {
pa_threaded_mainloop_signal(pClient->__mpMainloop, 0);
}
+void CPulseAudioClient::__successDrainCbInThread(pa_stream* s, int success, void* user_data) {
+ AUDIO_IO_LOGD("pa_stream[%p], success[%d], user_data[%p]", s, success, user_data);
+ assert(s);
+ assert(user_data);
+
+ CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
+ pClient->__mIsOperationSuccess = static_cast<bool>(success);
+ pClient->__mIsDraining = false;
+}
+
+void CPulseAudioClient::__successDrainCb(pa_stream* s, int success, void* user_data) {
+ AUDIO_IO_LOGD("pa_stream[%p], success[%d], user_data[%p]", s, success, user_data);
+ assert(s);
+ assert(user_data);
+
+ CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
+ pClient->__mIsOperationSuccess = static_cast<bool>(success);
+ pClient->__mIsDraining = false;
+
+ pa_threaded_mainloop_signal(pClient->__mpMainloop, 0);
+}
+
void CPulseAudioClient::initialize() throw(CAudioError) {
- AUDIO_IO_LOGD("");
if (__mIsInit == true) {
return;
}
return;
}
+ /* 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);
+
+ /* Wait for drain complete if draining before finalize */
+ if (__mIsDraining) {
+ unsigned int drain_wait_count = 0;
+ while (__mIsDraining && drain_wait_count++ < drain_wait_max_count) {
+ usleep(drain_wait_interval);
+ }
+ AUDIO_IO_LOGD("wait for drain complete!!!! [%d * %d usec]",
+ drain_wait_count, drain_wait_interval);
+ }
+
if (__mpMainloop != NULL) {
pa_threaded_mainloop_stop(__mpMainloop);
}
delete [] dummy;
}
__mIsFirstStream = false;
- AUDIO_IO_LOGD("FIRST STREAM CALLBACK : length[%d], prebuf[%d], dummy[%d]", length, prebuf, (length < prebuf) ? prebuf - length : 0);
+ AUDIO_IO_LOGW("FIRST STREAM CALLBACK : length[%d], prebuf[%d], dummy[%d]",
+ length, prebuf, (length < prebuf) ? prebuf - length : 0);
}
ret = pa_stream_write(__mpStream, data, length, NULL, 0LL, PA_SEEK_RELATIVE);
}
}
bool CPulseAudioClient::drain() throw(CAudioError) {
- AUDIO_IO_LOGD("drain");
-
if (__mIsInit == false) {
THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
}
checkRunningState();
+ if (__mIsDraining)
+ AUDIO_IO_LOGW("already draining...");
+
if (isInThread() == false) {
+ AUDIO_IO_LOGD("drain");
pa_threaded_mainloop_lock(__mpMainloop);
- pa_operation_unref(pa_stream_drain(__mpStream, __successStreamCb, this));
+ pa_operation* o = pa_stream_drain(__mpStream, __successDrainCb, this);
+ __mIsDraining = true;
+ while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
+ pa_threaded_mainloop_wait(__mpMainloop);
+ }
pa_threaded_mainloop_unlock(__mpMainloop);
} else {
- pa_operation_unref(pa_stream_drain(__mpStream, __successStreamCb, this));
+ AUDIO_IO_LOGD("drain in thread");
+ pa_operation_unref(pa_stream_drain(__mpStream, __successDrainCbInThread, this));
+ __mIsDraining = true;
}
return true;
}
bool CPulseAudioClient::flush() throw(CAudioError) {
- AUDIO_IO_LOGD("flush");
-
if (__mIsInit == false) {
THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
}
checkRunningState();
if (isInThread() == false) {
+ AUDIO_IO_LOGD("flush");
pa_threaded_mainloop_lock(__mpMainloop);
pa_operation_unref(pa_stream_flush(__mpStream, __successStreamCb, this));
pa_threaded_mainloop_unlock(__mpMainloop);
} else {
+ AUDIO_IO_LOGD("flush in thread");
pa_operation_unref(pa_stream_flush(__mpStream, __successStreamCb, this));
}