X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fcpp%2FCAudioIO.cpp;h=0de125ba231209a37bf75776a9a4ee9298a24f25;hb=392fd6e4a444f76f2ec4c55bc196a8ae88daa957;hp=71f38fe64071bfee3eef4433f459181238e3cc8c;hpb=009097fb79fea3db5e6b7f257e127b6d00b77627;p=platform%2Fcore%2Fapi%2Faudio-io.git diff --git a/src/cpp/CAudioIO.cpp b/src/cpp/CAudioIO.cpp index 71f38fe..0de125b 100644 --- a/src/cpp/CAudioIO.cpp +++ b/src/cpp/CAudioIO.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "CAudioIODef.h" using namespace std; @@ -31,25 +32,33 @@ CAudioIO::CAudioIO() : 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() { @@ -67,7 +76,7 @@ bool CAudioIO::IsReady() { return ((mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING || mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED)? true : false); } -void CAudioIO::internalLock() throw(CAudioError) { +void CAudioIO::internalLock() { if (__mIsInit == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } @@ -75,12 +84,13 @@ void CAudioIO::internalLock() throw(CAudioError) { 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 } -void CAudioIO::internalUnlock() throw(CAudioError) { +void CAudioIO::internalUnlock() { if (__mIsInit == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } @@ -89,11 +99,11 @@ void CAudioIO::internalUnlock() throw(CAudioError) { 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 } -void CAudioIO::internalWait() throw(CAudioError) { +void CAudioIO::internalWait() { if (__mIsInit == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } @@ -102,10 +112,12 @@ void CAudioIO::internalWait() throw(CAudioError) { 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() throw(CAudioError) { +void CAudioIO::internalSignal() { if (__mIsInit == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } @@ -114,14 +126,16 @@ void CAudioIO::internalSignal() throw(CAudioError) { AUDIO_IO_LOGD(COLOR_GREEN "SIGNAL" COLOR_END); #endif + pthread_mutex_lock(&__mCondMutex); pthread_cond_signal(&__mCond); + pthread_mutex_unlock(&__mCondMutex); } bool CAudioIO::isForceIgnore() { return __mForceIgnore; } -void CAudioIO::initialize() throw(CAudioError) { +void CAudioIO::initialize() { if (__mIsInit == true) { return; } @@ -148,16 +162,28 @@ void CAudioIO::finalize() { 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; } @@ -189,7 +215,11 @@ void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state, bool byPolicy) { 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); + state_string[static_cast(mStatePrev)], + static_cast(mStatePrev), + state_string[static_cast(mState)], + static_cast(mState), + mByPolicy); if (mStateChangedCallback.onStateChanged != NULL) { mStateChangedCallback.onStateChanged(mState, mStatePrev, mByPolicy, mStateChangedCallback.mUserData); @@ -204,7 +234,23 @@ CAudioInfo::EAudioIOState CAudioIO::getState() { 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(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(); @@ -220,29 +266,16 @@ void CAudioIO::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focu } if (state == FOCUS_IS_RELEASED) { - // Focus handle(id) of the other application was released, do resume if possible - internalLock(); - - 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->getStreamDirection() == CPulseAudioClient::EStreamDirection::STREAM_DIRECTION_PLAYBACK) { - if (mpPulseAudioClient->drain() == false) { - AUDIO_IO_LOGE("Failed CPulseAudioClient::drain()"); - } + if (mpPulseAudioClient) { + mpPulseAudioClient->cork(true); } - - 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 @@ -265,34 +298,29 @@ void CAudioIO::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focu if (state == FOCUS_IS_RELEASED) { // Focus handle(id) was released, do pause here internalLock(); - - if (mpPulseAudioClient->getStreamDirection() == CPulseAudioClient::EStreamDirection::STREAM_DIRECTION_PLAYBACK) { - if (mpPulseAudioClient->drain() == false) { - AUDIO_IO_LOGE("Failed CPulseAudioClient::drain()"); - } + if (mpPulseAudioClient) { + mpPulseAudioClient->cork(true); } - 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(); - - 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); + } } } @@ -310,20 +338,39 @@ void CAudioIO::onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t s } } -void CAudioIO::prepare() throw(CAudioError) { +void CAudioIO::prepare() { 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) { - throw e; + } catch (CAudioError& e) { + throw; } } -void CAudioIO::unprepare() throw(CAudioError) { +void CAudioIO::unprepare() { if (__mIsInit == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } @@ -331,12 +378,12 @@ void CAudioIO::unprepare() throw(CAudioError) { try { AUDIO_IO_LOGD("unprepare ----->"); /* Do nothing */ - } catch (CAudioError e) { - throw e; + } catch (CAudioError& e) { + throw; } } -void CAudioIO::pause() throw(CAudioError) { +void CAudioIO::pause() { if (__mIsInit == false || IsReady() == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); } @@ -346,13 +393,13 @@ void CAudioIO::pause() throw(CAudioError) { AUDIO_IO_LOGD("pause"); mpPulseAudioClient->cork(true); internalUnlock(); - } catch (CAudioError e) { + } catch (CAudioError& e) { internalUnlock(); - throw e; + throw; } } -void CAudioIO::resume() throw(CAudioError) { +void CAudioIO::resume() { if (__mIsInit == false || IsReady() == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); } @@ -362,13 +409,13 @@ void CAudioIO::resume() throw(CAudioError) { AUDIO_IO_LOGD("resume"); mpPulseAudioClient->cork(false); internalUnlock(); - } catch (CAudioError e) { + } catch (CAudioError& e) { internalUnlock(); - throw e; + throw; } } -void CAudioIO::drain() throw(CAudioError) { +void CAudioIO::drain() { if (__mIsInit == false || IsReady() == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); } @@ -381,15 +428,15 @@ void CAudioIO::drain() throw(CAudioError) { mpPulseAudioClient->drain(); internalUnlock(); } - } catch (CAudioError e) { + } catch (CAudioError& e) { if (!mpPulseAudioClient->isInThread()) { internalUnlock(); } - throw e; + throw; } } -void CAudioIO::flush() throw(CAudioError) { +void CAudioIO::flush() { if (__mIsInit == false || IsReady() == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); } @@ -402,15 +449,15 @@ void CAudioIO::flush() throw(CAudioError) { mpPulseAudioClient->flush(); internalUnlock(); } - } catch (CAudioError e) { + } catch (CAudioError& e) { if (!mpPulseAudioClient->isInThread()) { internalUnlock(); } - throw e; + throw; } } -CAudioInfo& CAudioIO::getAudioInfo() throw(CAudioError) { +CAudioInfo& CAudioIO::getAudioInfo() { if (__mIsInit == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } @@ -418,7 +465,7 @@ CAudioInfo& CAudioIO::getAudioInfo() throw(CAudioError) { return mAudioInfo; } -void CAudioIO::setStreamCallback(SStreamCallback callback) throw(CAudioError) { +void CAudioIO::setStreamCallback(SStreamCallback callback) { if (__mIsInit == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } @@ -426,7 +473,7 @@ void CAudioIO::setStreamCallback(SStreamCallback callback) throw(CAudioError) { mStreamCallback = callback; } -CAudioIO::SStreamCallback CAudioIO::getStreamCallback() throw(CAudioError) { +CAudioIO::SStreamCallback CAudioIO::getStreamCallback() { if (__mIsInit == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } @@ -434,7 +481,7 @@ CAudioIO::SStreamCallback CAudioIO::getStreamCallback() throw(CAudioError) { return mStreamCallback; } -void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) throw(CAudioError) { +void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) { if (__mIsInit == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } @@ -442,7 +489,7 @@ void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) throw(CAu mStateChangedCallback = callback; } -CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() throw(CAudioError) { +CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() { if (__mIsInit == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } @@ -450,7 +497,7 @@ CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() throw(CAudio return mStateChangedCallback; } -void CAudioIO::setInterruptCallback(SInterruptCallback callback) throw(CAudioError) { +void CAudioIO::setInterruptCallback(SInterruptCallback callback) { if (__mIsInit == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } @@ -458,7 +505,7 @@ void CAudioIO::setInterruptCallback(SInterruptCallback callback) throw(CAudioErr mInterruptCallback = callback; } -CAudioIO::SInterruptCallback CAudioIO::getInterruptCallback() throw(CAudioError) { +CAudioIO::SInterruptCallback CAudioIO::getInterruptCallback() { if (__mIsInit == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } @@ -466,7 +513,7 @@ CAudioIO::SInterruptCallback CAudioIO::getInterruptCallback() throw(CAudioError) return mInterruptCallback; } -void CAudioIO::ignoreSession() throw(CAudioError) { +void CAudioIO::ignoreSession() { if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); @@ -476,21 +523,16 @@ void CAudioIO::ignoreSession() throw(CAudioError) { if (mpPulseAudioClient != NULL && mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING) THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "An Operation is not permitted while started"); - bool isSkip = mpAudioSessionHandler->isSkipSession(); - if (isSkip == false && mpAudioSessionHandler->getId() >= 0) - mpAudioSessionHandler->unregisterSound(); - - mpAudioSessionHandler->finalize(); - __mForceIgnore = true; + abandonInternalFocus(); internalUnlock(); - } catch (CAudioError e) { + } catch (CAudioError& e) { internalUnlock(); - throw e; + throw; } } -void CAudioIO::setStreamInfo(sound_stream_info_h stream_info) throw(CAudioError) { +void CAudioIO::setStreamInfo(sound_stream_info_h stream_info) { if (stream_info == NULL) THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_ARGUMENT, "stream_info is NULL"); @@ -501,6 +543,8 @@ void CAudioIO::setStreamInfo(sound_stream_info_h stream_info) throw(CAudioError) if (mState != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE) THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_STATE, "it is not permitted while started"); + abandonInternalFocus(); + int errorCode = SOUND_MANAGER_ERROR_NONE; CAudioInfo::EAudioType audioType = CAudioInfo::EAudioType::AUDIO_IN_TYPE_MEDIA; char *type = NULL; @@ -528,12 +572,12 @@ void CAudioIO::setStreamInfo(sound_stream_info_h stream_info) throw(CAudioError) getAudioInfo().setAudioIndex(index); AUDIO_IO_LOGD("stream info(%p) is set", stream_info); - } catch (CAudioError e) { - throw e; + } catch (CAudioError& e) { + throw; } } -void CAudioIO::setInternalStreamInfo() throw(CAudioError) { +void CAudioIO::setInternalStreamInfo() { if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); @@ -548,7 +592,22 @@ void CAudioIO::setInternalStreamInfo() throw(CAudioError) { AUDIO_IO_LOGD("get internal VOIP stream info(%p)", stream_info); setStreamInfo(stream_info); } - } catch (CAudioError e) { - throw e; + } catch (CAudioError& e) { + throw; + } +} + +void CAudioIO::abandonInternalFocus() { + bool isSkip = mpAudioSessionHandler->isSkipSession(); + int id = mpAudioSessionHandler->getId(); + + try { + if (isSkip == false && id >= 0) + mpAudioSessionHandler->unregisterSound(); + + mpAudioSessionHandler->finalize(); + __mForceIgnore = true; + } catch (CAudioError& e) { + throw; } }