#include <mm.h>
#include <pthread.h>
#include <assert.h>
+#include <glib.h>
#include "CAudioIODef.h"
using namespace std;
mpAudioSessionHandler(NULL),
mpPulseAudioClient(NULL),
__mMutex(PTHREAD_MUTEX_INITIALIZER),
+ __mCondMutex(PTHREAD_MUTEX_INITIALIZER),
__mCond(PTHREAD_COND_INITIALIZER),
__mIsInit(false),
__mForceIgnore(false) {
+ mInterruptCode = IAudioSessionEventListener::EInterruptCode::INTERRUPT_MAX;
mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX;
mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
mByPolicy = false;
+ mIsInterrupted = false;
}
CAudioIO::CAudioIO(CAudioInfo& audioInfo) :
mpAudioSessionHandler(NULL),
mpPulseAudioClient(NULL),
__mMutex(PTHREAD_MUTEX_INITIALIZER),
+ __mCondMutex(PTHREAD_MUTEX_INITIALIZER),
__mCond(PTHREAD_COND_INITIALIZER),
__mIsInit(false),
__mForceIgnore(false) {
mAudioInfo = audioInfo;
+ mInterruptCode = IAudioSessionEventListener::EInterruptCode::INTERRUPT_MAX;
mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX;
mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
mByPolicy = false;
+ mIsInterrupted = false;
}
CAudioIO::~CAudioIO() {
if (pthread_mutex_lock(&__mMutex) != 0) {
THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()");
}
+
#ifdef _AUDIO_IO_DEBUG_TIMING_
- AUDIO_IO_LOGD(COLOR_RED "LOCK" COLOR_END);
+ AUDIO_IO_LOGD(COLOR_RED "%p LOCKED" COLOR_END, &__mMutex);
#endif
}
THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()");
}
#ifdef _AUDIO_IO_DEBUG_TIMING_
- AUDIO_IO_LOGD(COLOR_GREEN "UNLOCK" COLOR_END);
+ AUDIO_IO_LOGD(COLOR_GREEN "%p UNLOCKED" COLOR_END, &__mMutex);
#endif
}
AUDIO_IO_LOGD(COLOR_RED "WAIT" COLOR_END);
#endif
- pthread_cond_wait(&__mCond, &__mMutex);
+ pthread_mutex_lock(&__mCondMutex);
+ pthread_cond_wait(&__mCond, &__mCondMutex);
+ pthread_mutex_unlock(&__mCondMutex);
}
void CAudioIO::internalSignal() {
AUDIO_IO_LOGD(COLOR_GREEN "SIGNAL" COLOR_END);
#endif
+ pthread_mutex_lock(&__mCondMutex);
pthread_cond_signal(&__mCond);
+ pthread_mutex_unlock(&__mCondMutex);
}
bool CAudioIO::isForceIgnore() {
AUDIO_IO_LOGD("finalize");
+ bool error_occured = false;
int ret = pthread_mutex_destroy(&__mMutex);
if (ret != 0) {
- THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_mutex_destroy() ret:%d", ret);
+ AUDIO_IO_LOGE("Failed pthread_mutex_destroy(%p) errno:%d", &__mMutex, ret);
+ error_occured = true;
+ }
+ ret = pthread_mutex_destroy(&__mCondMutex);
+ if (ret != 0) {
+ AUDIO_IO_LOGE("Failed pthread_mutex_destroy(%p) errno:%d", &__mCondMutex, ret);
+ error_occured = true;
}
+
ret = pthread_cond_destroy(&__mCond);
if (ret != 0) {
- THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_cond_destroy() ret:%d", ret);
+ AUDIO_IO_LOGE("Failed pthread_cond_destroy(%p) errno:%d", &__mCond, ret);
+ error_occured = true;
}
+ if (error_occured)
+ THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Finalize Failed");
+
__mIsInit = false;
}
return mState;
}
-void CAudioIO::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info) {
+int CAudioIO::sendInterrupt(void* user_data) {
+ CAudioIO *pCaudioIo = (CAudioIO *)user_data;
+
+ if (pCaudioIo && pCaudioIo->mInterruptCallback.onInterrupt) {
+ AUDIO_IO_LOGD("sending interrupt [%d]", static_cast<int>(pCaudioIo->mInterruptCode));
+ pCaudioIo->mInterruptCallback.onInterrupt(pCaudioIo->mInterruptCode, pCaudioIo->mInterruptCallback.mUserData);
+ }
+ return 0;
+}
+
+int caudio_gsource_callback(void *user_data) {
+ CAudioIO::sendInterrupt(user_data);
+ return 0;
+}
+
+void CAudioIO::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focus_type_e focus_type,
+ mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info) {
assert(pHandler);
int session_option = pHandler->getOptions();
}
if (state == FOCUS_IS_RELEASED) {
- // Focus handle(id) of the other application was released, do resume if possible
- internalLock();
- if (mpPulseAudioClient) {
- mpPulseAudioClient->cork(false);
- onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING);
- }
- internalUnlock();
-
+ // Focus handle(id) of the other application was released, notify resume
// Focus watch callback doesn't have focus handle, but it need to convert & report to application for convenience
state = FOCUS_IS_ACQUIRED;
} else if (state == FOCUS_IS_ACQUIRED) {
// Focus handle(id) of the other application was acquired, do pause if possible
internalLock();
if (mpPulseAudioClient) {
- /* FIXME: Skip this codes due to the blocking of drain() function
- if (mpPulseAudioClient->getStreamDirection() == CPulseAudioClient::EStreamDirection::STREAM_DIRECTION_PLAYBACK) {
- if (mpPulseAudioClient->drain() == false) {
- AUDIO_IO_LOGE("Failed CPulseAudioClient::drain()");
- }
- }
- */
mpPulseAudioClient->cork(true);
- onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED);
}
+ mIsInterrupted = true;
internalUnlock();
// Focus watch callback doesn't have focus handle, but it need to convert & report to application for convenience
// Focus handle(id) was released, do pause here
internalLock();
if (mpPulseAudioClient) {
- /* FIXME: Skip this codes due to the blocking of drain() function
- if (mpPulseAudioClient->getStreamDirection() == CPulseAudioClient::EStreamDirection::STREAM_DIRECTION_PLAYBACK) {
- if (mpPulseAudioClient->drain() == false) {
- AUDIO_IO_LOGE("Failed CPulseAudioClient::drain()");
- }
- }
- */
mpPulseAudioClient->cork(true);
- onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED);
}
+
+ mIsInterrupted = true;
internalUnlock();
} else if (state == FOCUS_IS_ACQUIRED) {
// Focus handle(id) was acquired again,
// check reason_for_change ("call-voice","call-video","voip","alarm","notification", ...)
// do resume here and call interrupt completed callback to application.
- internalLock();
- if (mpPulseAudioClient) {
- mpPulseAudioClient->cork(false);
- onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING);
- }
- internalUnlock();
}
}
if (mInterruptCallback.onInterrupt != NULL) {
IAudioSessionEventListener::EInterruptCode e = IAudioSessionEventListener::EInterruptCode::INTERRUPT_COMPLETED;
e = IAudioSessionEventListener::convertInterruptedCode(state, reason_for_change);
- mInterruptCallback.onInterrupt(e, mInterruptCallback.mUserData);
+
+ if (EInterruptCode::INTERRUPT_COMPLETED == e) {
+ mInterruptCode = e;
+ g_idle_add(caudio_gsource_callback, this);
+ } else {
+ mInterruptCallback.onInterrupt(e, mInterruptCallback.mUserData);
+ }
}
}
if (__mIsInit == false) {
THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
}
-
+ if (mDirection == CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN) {
+ AUDIO_IO_LOGD("Prepare for Audio in");
+ } else if (mDirection == CAudioInfo::EAudioDirection::AUDIO_DIRECTION_OUT) {
+ AUDIO_IO_LOGD("Prepare for Audio Out");
+ }
try {
+ if (mIsInterrupted) {
+ AUDIO_IO_LOGE("This is preparing during interrupted!!!");
+ bool isSkip = mpAudioSessionHandler->isSkipSession();
+ if (__mForceIgnore == false && isSkip == false && mpAudioSessionHandler->getId() >= 0) {
+ AUDIO_IO_LOGE("Session updatePlaying!!!");
+ mpAudioSessionHandler->updatePlaying();
+ }
+
+ if (mpPulseAudioClient && mpPulseAudioClient->isCorked()) {
+ AUDIO_IO_LOGE("Uncork!");
+ mpPulseAudioClient->cork(false);
+ }
+ mIsInterrupted = false;
+ }
+
AUDIO_IO_LOGD("------> prepare done");
/* Do nothing */
} catch (CAudioError& e) {