X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fcpp%2FCAudioIO.cpp;h=8d8cf893cfb5081bae827302a5f2fe81d5faec0f;hb=2284d1d4a0df0ad04a52045eeb5dcfc9c18d835a;hp=479608ce1b47acca82615ebb9d028bc3c1b3e44a;hpb=82fb9a1ddddaf648935fdeea00913ced6663c081;p=platform%2Fcore%2Fapi%2Faudio-io.git diff --git a/src/cpp/CAudioIO.cpp b/src/cpp/CAudioIO.cpp index 479608c..8d8cf89 100644 --- a/src/cpp/CAudioIO.cpp +++ b/src/cpp/CAudioIO.cpp @@ -18,9 +18,9 @@ #include #include #include +#include #include "CAudioIODef.h" - -#define AUDIO_IO_DEBUG +#include using namespace std; using namespace tizen_media_audio; @@ -30,17 +30,25 @@ using namespace tizen_media_audio; * class CAudioIO */ CAudioIO::CAudioIO() : - mpAudioSessionHandler(NULL), mpPulseAudioClient(NULL), - __mIsInit(false), - __mForceIgnore(false) { + __mMutex(PTHREAD_MUTEX_INITIALIZER), + __mCondMutex(PTHREAD_MUTEX_INITIALIZER), + __mCond(PTHREAD_COND_INITIALIZER), + __mIsInit(false) { + mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX; mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE; mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE; mByPolicy = false; } -CAudioIO::CAudioIO(CAudioInfo& audioInfo) : mpAudioSessionHandler(NULL), mpPulseAudioClient(NULL), __mIsInit(false), __mForceIgnore(false) { +CAudioIO::CAudioIO(CAudioInfo& audioInfo) : + mpPulseAudioClient(NULL), + __mMutex(PTHREAD_MUTEX_INITIALIZER), + __mCondMutex(PTHREAD_MUTEX_INITIALIZER), + __mCond(PTHREAD_COND_INITIALIZER), + __mIsInit(false) { mAudioInfo = audioInfo; + mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX; mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE; mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE; mByPolicy = false; @@ -58,100 +66,105 @@ bool CAudioIO::isInit() { } bool CAudioIO::IsReady() { - return ((mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING || mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED)? true : false); + return ((mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING || + mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED)? true : false); } -void CAudioIO::internalLock() throw (CAudioError) { - if (__mIsInit == false) { +void CAudioIO::internalLock() { + if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } - if (pthread_mutex_lock(&__mMutex) != 0) { + 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) { - if (__mIsInit == false) { +void CAudioIO::internalUnlock() { + if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } - if (pthread_mutex_unlock(&__mMutex) != 0) { + if (pthread_mutex_unlock(&__mMutex) != 0) 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) { - if (__mIsInit == false) { +void CAudioIO::internalWait() { + if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } #ifdef _AUDIO_IO_DEBUG_TIMING_ 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) { - if (__mIsInit == false) { +void CAudioIO::internalSignal() { + if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } #ifdef _AUDIO_IO_DEBUG_TIMING_ 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) { - if (__mIsInit == true) { +void CAudioIO::initialize() { + if (__mIsInit == true) return; - } AUDIO_IO_LOGD("initialize"); int ret = pthread_mutex_init(&__mMutex, NULL); - if (ret != 0) { + if (ret != 0) THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_mutex_init()"); - } ret = pthread_cond_init(&__mCond, NULL); - if (ret != 0) { + if (ret != 0) THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_cond_init()"); - } __mIsInit = true; } void CAudioIO::finalize() { - if (__mIsInit == false) { + if (__mIsInit == false) return; - } 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 cond 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; } @@ -164,9 +177,8 @@ void CAudioIO::onStream(CPulseAudioClient* pClient, size_t length) { AUDIO_IO_LOGD("mStreamCallback.onStream(%p), pClient(%p), length(%zu)", mStreamCallback.onStream, pClient, length); #endif - if (mStreamCallback.onStream != NULL) { + if (mStreamCallback.onStream != NULL) mStreamCallback.onStream(length, mStreamCallback.mUserData); - } } void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state, bool byPolicy) { @@ -174,294 +186,181 @@ void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state, bool byPolicy) { assert(state >= CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE && state < CAudioInfo::EAudioIOState::AUDIO_IO_STATE_MAX); mStatePrev = mState; - mState = state; - mByPolicy = byPolicy; + mState = state; + mByPolicy = byPolicy; - AUDIO_IO_LOGD("current(%d), previous(%d), by_policy(%d)", mState, mStatePrev, mByPolicy); + if (mState == mStatePrev) + return; + + const char* state_string[] = { "NONE", "IDLE", "RUNNING", "PAUSED" }; - if (mStateChangedCallback.onStateChanged != NULL) { + AUDIO_IO_LOGD("previous(%s,%d) ===> current(%s,%d), by_policy(%d)", + 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); - } } void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state) { onStateChanged(state, false); } -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 (id == -1) { - /////////////////////////////////////// - // Triggered by 'focus watch callback' - /////////////////////////////////////// - - if (session_option & (MM_SESSION_OPTION_PAUSE_OTHERS | MM_SESSION_OPTION_UNINTERRUPTIBLE)) { - AUDIO_IO_LOGD("Session option is pausing others or uninterruptible, skip..."); - return; - } - - 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 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()"); - } - } - - mpPulseAudioClient->cork(true); - onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED); - - internalUnlock(); - - // Focus watch callback doesn't have focus handle, but it need to convert & report to application for convenience - state = FOCUS_IS_RELEASED; - } - } else { - /////////////////////////////////////// - // Triggered by 'focus callback' - /////////////////////////////////////// - - if (pHandler->getId() != id) { - AUDIO_IO_LOGW("Id is different, why? [mId : %d]", pHandler->getId()); - } - - if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) { - AUDIO_IO_LOGD("Session option is uninterruptible, skip..."); - return; - } - - 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()"); - } - } - - mpPulseAudioClient->cork(true); - onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED); - - 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); - } -} - -void CAudioIO::onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t signal, int value) { - assert(pHandler); - - if (signal == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS) { - if (value == 1 && pHandler->getSubscribeId() >= 0) { - // Unregister focus watch callback & disable session handler - pHandler->disableSessionHandler(); - AUDIO_IO_LOGD("Session handler disabled by signal"); - } else if (value == 0) { - // Currently do nothing... - } - } +CAudioInfo::EAudioIOState CAudioIO::getState() { + return mState; } -void CAudioIO::prepare() throw (CAudioError) { - if (__mIsInit == false) { +void CAudioIO::prepare() { + if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } - - try { - AUDIO_IO_LOGD("prepare"); - /* Do nothing */ - } catch (CAudioError e) { - throw e; - } } -void CAudioIO::unprepare() throw (CAudioError) { - if (__mIsInit == false) { +void CAudioIO::unprepare() { + if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } - - try { - AUDIO_IO_LOGD("unprepare"); - /* Do nothing */ - } catch (CAudioError e) { - throw e; - } } -void CAudioIO::pause() throw (CAudioError) { - if (__mIsInit == false || IsReady() == false) { +void CAudioIO::pause() { + if (__mIsInit == false || IsReady() == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); - } try { internalLock(); AUDIO_IO_LOGD("pause"); mpPulseAudioClient->cork(true); internalUnlock(); - } catch (CAudioError e) { + } catch (CAudioError& e) { internalUnlock(); - throw e; + throw; } } -void CAudioIO::resume() throw (CAudioError) { - if (__mIsInit == false || IsReady() == false) { +void CAudioIO::resume() { + if (__mIsInit == false || IsReady() == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); - } try { internalLock(); AUDIO_IO_LOGD("resume"); mpPulseAudioClient->cork(false); internalUnlock(); - } catch (CAudioError e) { + } catch (CAudioError& e) { internalUnlock(); - throw e; + throw; } } -void CAudioIO::drain() throw (CAudioError) { - if (__mIsInit == false || IsReady() == false) { +void CAudioIO::drain() { + if (__mIsInit == false || IsReady() == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); - } try { - internalLock(); - AUDIO_IO_LOGD("drain"); - mpPulseAudioClient->drain(); - internalUnlock(); - } catch (CAudioError e) { - internalUnlock(); - throw e; + if (mpPulseAudioClient->isInThread()) { + mpPulseAudioClient->drain(); + } else { + internalLock(); + mpPulseAudioClient->drain(); + internalUnlock(); + } + } catch (CAudioError& e) { + if (!mpPulseAudioClient->isInThread()) + internalUnlock(); + throw; } } -void CAudioIO::flush() throw (CAudioError) { - if (__mIsInit == false || IsReady() == false) { +void CAudioIO::flush() { + if (__mIsInit == false || IsReady() == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); - } try { - internalLock(); - AUDIO_IO_LOGD("flush"); - mpPulseAudioClient->flush(); - internalUnlock(); - } catch (CAudioError e) { - internalUnlock(); - throw e; + if (mpPulseAudioClient->isInThread()) { + mpPulseAudioClient->flush(); + } else { + internalLock(); + mpPulseAudioClient->flush(); + internalUnlock(); + } + } catch (CAudioError& e) { + if (!mpPulseAudioClient->isInThread()) + internalUnlock(); + throw; } } -CAudioInfo& CAudioIO::getAudioInfo() throw (CAudioError) { - if (__mIsInit == false) { +CAudioInfo& CAudioIO::getAudioInfo() { + if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } return mAudioInfo; } -void CAudioIO::setStreamCallback(SStreamCallback callback) throw (CAudioError) { - if (__mIsInit == false) { +void CAudioIO::setStreamCallback(SStreamCallback callback) { + if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } mStreamCallback = callback; } -CAudioIO::SStreamCallback CAudioIO::getStreamCallback() throw (CAudioError) { - if (__mIsInit == false) { +CAudioIO::SStreamCallback CAudioIO::getStreamCallback() { + if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } return mStreamCallback; } -void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) throw (CAudioError) { - if (__mIsInit == false) { +void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) { + if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } mStateChangedCallback = callback; } -CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() throw (CAudioError) { - if (__mIsInit == false) { +CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() { + if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } return mStateChangedCallback; } -void CAudioIO::setInterruptCallback(SInterruptCallback callback) throw (CAudioError) { - if (__mIsInit == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } +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"); - mInterruptCallback = callback; -} - -CAudioIO::SInterruptCallback CAudioIO::getInterruptCallback() throw (CAudioError) { - if (__mIsInit == false) { + if (__mIsInit == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } - - return mInterruptCallback; -} - - -void CAudioIO::ignoreSession() throw (CAudioError) { - if (__mIsInit == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); - } try { - internalLock(); - - if (mpPulseAudioClient != NULL && mpPulseAudioClient->isCorked() == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "An Operation is not permitted while started"); - } - - bool isSkip = mpAudioSessionHandler->isSkipSessionEvent(); - if (isSkip == false && mpAudioSessionHandler->getId() >= 0) { - mpAudioSessionHandler->unregisterSound(); - __mForceIgnore = true; - } - - internalUnlock(); - } catch (CAudioError e) { - internalUnlock(); - throw e; + if (mState != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE) + THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_STATE, "it is not permitted while started"); + + int errorCode = SOUND_MANAGER_ERROR_NONE; + CAudioInfo::EAudioType audioType = CAudioInfo::EAudioType::AUDIO_IN_TYPE_MEDIA; + char *type = NULL; + int index = -1; + bool avail = false; + + if ((errorCode = sound_manager_is_available_stream_information(stream_info, NATIVE_API_AUDIO_IO, &avail)) != SOUND_MANAGER_ERROR_NONE) + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info is invalid [ret:%d]", errorCode); + if (!avail) + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_NOT_SUPPORTED_TYPE, "Input stream is not supported"); + + if ((errorCode = sound_manager_get_type_from_stream_information(stream_info, &type)) != SOUND_MANAGER_ERROR_NONE) + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->stream_type is invalid [ret:%d]", errorCode); + if (mDirection == CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN) + getAudioInfo().convertInputStreamType2AudioType(type, &audioType); + else + getAudioInfo().convertOutputStreamType2AudioType(type, &audioType); + getAudioInfo().setAudioType(audioType); + + if ((errorCode = sound_manager_get_index_from_stream_information(stream_info, &index)) != SOUND_MANAGER_ERROR_NONE) + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->index is invalid [ret:%d]", errorCode); + getAudioInfo().setAudioIndex(index); + + } catch (CAudioError& e) { + throw; } }