X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fcpp%2FCAudioOutput.cpp;h=f122752965693930067a3da3b6297d5747b90481;hb=ffd34c56a7091e7dd9bc5680ad718a4e1a263740;hp=e6a7d94dcbdbd01d7a3dbf25e9ff9fcdd4a49912;hpb=3f579b7861b3918cff454fa831f9e41d16c8b5e6;p=platform%2Fcore%2Fapi%2Faudio-io.git diff --git a/src/cpp/CAudioOutput.cpp b/src/cpp/CAudioOutput.cpp index e6a7d94..f122752 100644 --- a/src/cpp/CAudioOutput.cpp +++ b/src/cpp/CAudioOutput.cpp @@ -15,7 +15,10 @@ */ +#include + #include "CAudioIODef.h" +#include using namespace std; using namespace tizen_media_audio; @@ -23,23 +26,12 @@ using namespace tizen_media_audio; /** * class CAudioOutput */ + CAudioOutput::CAudioOutput(CAudioInfo& info) : CAudioIO(info), __mIsUsedSyncWrite(false), __mIsInit(false) { -} - -CAudioOutput::CAudioOutput( - unsigned int sampleRate, - CAudioInfo::EChannel channel, - CAudioInfo::ESampleType sampleType, - CAudioInfo::EAudioType audioType) : - __mIsUsedSyncWrite(false), - __mIsInit(false) { - mAudioInfo = CAudioInfo(sampleRate, channel, sampleType, audioType, -1); -} - -CAudioOutput::~CAudioOutput() { + mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_OUT; } void CAudioOutput::onStream(CPulseAudioClient* pClient, size_t length) { @@ -49,9 +41,9 @@ void CAudioOutput::onStream(CPulseAudioClient* pClient, size_t length) { * Does not call CAudioIO::onStream() for synchronization * if a user is using write() */ - if (__mIsUsedSyncWrite == true) { + if (__mIsUsedSyncWrite) { #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("Sync Write Mode! - signal! - pClient:[%p], length:[%d]", pClient, length); + AUDIO_IO_LOGD("Sync Write Mode! - signal! - pClient:[%p], length:[%zu]", pClient, length); #endif internalSignal(); return; @@ -61,309 +53,218 @@ void CAudioOutput::onStream(CPulseAudioClient* pClient, size_t length) { * Accrues callback function */ #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("pClient:[%p], length:[%d]", pClient, length); + AUDIO_IO_LOGD("pClient:[%p], length:[%zu]", pClient, length); #endif CAudioIO::onStream(pClient, length); } -void CAudioOutput::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); - AUDIO_IO_LOGD("[pHandler:0x%x], [focus_type:%d], [state:%d], [reason_for_change:%s], [additional_info:%s]", - pHandler, focus_type, state, reason_for_change, additional_info); - CAudioIO::onInterrupt(pHandler, id, focus_type, state, reason_for_change, additional_info); -} - -void CAudioOutput::onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t signal, int value) { - assert(pHandler); - AUDIO_IO_LOGD("[pHandler:0x%x], [signal:%d], [value:%d]", pHandler, signal, value); - CAudioIO::onSignal(pHandler, signal, value); -} - -void CAudioOutput::__setInit(bool flag) { +void CAudioOutput::__setInit(bool flag) noexcept { __mIsInit = flag; } -bool CAudioOutput::__IsInit() { - return (CAudioIO::isInit() == true && __mIsInit == true); +bool CAudioOutput::__IsInit() noexcept { + return (CAudioIO::isInit() && __mIsInit); } -bool CAudioOutput::__IsReady() { +bool CAudioOutput::__IsReady() noexcept { return CAudioIO::IsReady(); } -void CAudioOutput::initialize() throw(CAudioError) { - if (__IsInit() == true) { +void CAudioOutput::initialize() { + if (__IsInit()) return; - } try { CAudioIO::initialize(); - - // Create ASM Handler - mpAudioSessionHandler = new CAudioSessionHandler(CAudioSessionHandler::EAudioSessionType::AUDIO_SESSION_TYPE_PLAYBACK, mAudioInfo, this); - if (mpAudioSessionHandler == NULL) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, - "Failed to allocate CAudioSessionHandler object"); - } - - // Initialize ASM Handler - mpAudioSessionHandler->initialize(); - __setInit(true); - CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); - } catch (CAudioError err) { + } catch (CAudioError& e) { finalize(); - throw err; + throw; } + + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); } void CAudioOutput::finalize() { - if (__IsInit() == false) { + if (!__IsInit()) { AUDIO_IO_LOGD("Did not initialize"); return; } - SAFE_FINALIZE(mpAudioSessionHandler); - SAFE_DELETE(mpAudioSessionHandler); - CAudioIO::finalize(); __setInit(false); } -void CAudioOutput::prepare() throw(CAudioError) { - if (__IsInit() == false) { +void CAudioOutput::prepare() { + if (!__IsInit()) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioOutput"); - } - if (__IsReady() == true) { + if (__IsReady()) { AUDIO_IO_LOGD("Already prepared CAudioOutput"); + CAudioIO::prepare(); return; } - try { - internalLock(); - - // Check to invalid AudioType - CAudioInfo::EAudioType audioType = mAudioInfo.getAudioType(); - if (audioType < CAudioInfo::EAudioType::AUDIO_OUT_TYPE_MEDIA || audioType >= CAudioInfo::EAudioType::AUDIO_TYPE_MAX) { - THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, - "The audioType is invalid [type:%d]", static_cast(audioType)); - } + /* Check invalid AudioType */ + CAudioInfo::EAudioType audioType = mAudioInfo.getAudioType(); + if (audioType < CAudioInfo::EAudioType::AUDIO_OUT_TYPE_MEDIA || + audioType >= CAudioInfo::EAudioType::AUDIO_TYPE_MAX) + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, + "The audioType is invalid [type:%d]", static_cast(audioType)); - if (mpAudioSessionHandler->getId() < 0) { // Did not registerSound() - if (isForceIgnore() == false) { - // Register ASM Listener - AUDIO_IO_LOGD("Register ASM Listener"); - mpAudioSessionHandler->registerSound(); - } + try { + /* Init StreamSpec */ + CPulseStreamSpec::EStreamLatency streamSpec = CPulseStreamSpec::EStreamLatency::STREAM_LATENCY_OUTPUT_DEFAULT; +#ifndef DISABLE_MOBILE_BACK_COMP + if (!mStreamCallback.onStream) { + AUDIO_IO_LOGD("Set Stream Spec : CPulseStreamSpec::STREAM_LATENCY_OUTPUT_DEFAULT"); + streamSpec = CPulseStreamSpec::EStreamLatency::STREAM_LATENCY_OUTPUT_DEFAULT; + } else { + AUDIO_IO_LOGD("Set Stream Spec : CPulseStreamSpec::STREAM_LATENCY_OUTPUT_DEFAULT_ASYNC"); + streamSpec = CPulseStreamSpec::EStreamLatency::STREAM_LATENCY_OUTPUT_DEFAULT_ASYNC; } +#endif + /* Override the default value by audio type */ + if (audioType == CAudioInfo::EAudioType::AUDIO_OUT_TYPE_VOIP) + streamSpec = CPulseStreamSpec::EStreamLatency::STREAM_LATENCY_OUTPUT_VOIP; + else if (audioType == CAudioInfo::EAudioType::AUDIO_OUT_TYPE_MEDIA_NETWORK_SOURCE) + streamSpec = CPulseStreamSpec::EStreamLatency::STREAM_LATENCY_OUTPUT_HIGH; - // Init StreamSpec - AUDIO_IO_LOGD("Set Stream Spec : CPulseStreamSpec::STREAM_LATENCY_OUTPUT_DEFAULT"); - CPulseStreamSpec::EStreamLatency streamSpec = CPulseStreamSpec::EStreamLatency::STREAM_LATENCY_OUTPUT_DEFAULT; CPulseStreamSpec spec(streamSpec, mAudioInfo); - // Create PulseAudio Handler + internalLock(); mpPulseAudioClient = new CPulseAudioClient(CPulseAudioClient::EStreamDirection::STREAM_DIRECTION_PLAYBACK, spec, this); - if (mpPulseAudioClient == NULL) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, - "Failed to allocate CPulseAudioClient object"); - } - - // Initialize PulseAudio Handler mpPulseAudioClient->initialize(); - - if (isForceIgnore() == false && - mpAudioSessionHandler->isSkipSessionEvent() == false) { - /* Updates ASM to PLAYING */ - mpAudioSessionHandler->updatePlaying(); - } - +#ifndef DISABLE_MOBILE_BACK_COMP + /* Uncork stream which is created with CORKED flag */ + mpPulseAudioClient->cork(false); +#endif internalUnlock(); CAudioIO::prepare(); - } catch (CAudioError e) { + } catch (CAudioError& e) { + SAFE_FINALIZE(mpPulseAudioClient); + SAFE_DELETE(mpPulseAudioClient); internalUnlock(); - throw e; + throw; + } catch (const std::bad_alloc&) { +//LCOV_EXCL_START + internalUnlock(); + THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed to allocate CPulseAudioClient object"); +//LCOV_EXCL_STOP } } -void CAudioOutput::unprepare() throw(CAudioError) { - if (__IsInit() == false) { +void CAudioOutput::unprepare() { + if (!__IsInit()) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioOutput"); - } - if (__IsReady() == false) { + if (!__IsReady()) { AUDIO_IO_LOGD("Already unprepared"); return; } - try { - CAudioIO::unprepare(); + CAudioIO::unprepare(); + try { internalLock(); - + if (mpPulseAudioClient && mpPulseAudioClient->isInThread()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "Can't unprepare inside pulseaudio thread"); SAFE_FINALIZE(mpPulseAudioClient); SAFE_DELETE(mpPulseAudioClient); - - if (mpAudioSessionHandler->getId() >= 0) { - /* Updates ASM to STOP */ - if (isForceIgnore() == false && - mpAudioSessionHandler->isSkipSessionEvent() == false) { - mpAudioSessionHandler->updateStop(); - } - - bool isSkip = mpAudioSessionHandler->isSkipSessionEvent(); - if (isSkip == false) { - mpAudioSessionHandler->unregisterSound(); - } - } - internalUnlock(); - - CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); - } catch (CAudioError e) { + } catch (CAudioError& e) { internalUnlock(); - throw e; + throw; } + + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); } -void CAudioOutput::pause() throw(CAudioError) { - if (__IsInit() == false || __IsReady() == false) { +void CAudioOutput::pause() { + if (!__IsInit() || !__IsReady()) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioOutput"); - } - if (CAudioIO::getState() != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING) { + if (CAudioIO::getState() != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING) THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_STATE, "Can't pause if not in Running state"); - } - if (mpPulseAudioClient->isInThread() == true) { + if (mpPulseAudioClient->isInThread() ) THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_OPERATION, "Can't pause in thread"); - } - - try { - CAudioIO::pause(); - - internalLock(); - - /* Updates ASM to STOP */ - if (isForceIgnore() == false && - mpAudioSessionHandler->isSkipSessionEvent() == false) { - mpAudioSessionHandler->updateStop(); - } - - internalUnlock(); - CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED); - } catch (CAudioError e) { - internalUnlock(); - throw e; - } + CAudioIO::pause(); + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED); } -void CAudioOutput::resume() throw(CAudioError) { - if (__IsInit() == false || __IsReady() == false) { +void CAudioOutput::resume() { + if (!__IsInit() || !__IsReady()) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioOutput"); - } - if (CAudioIO::getState() != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED) { + if (CAudioIO::getState() != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED) THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_STATE, "Can't resume if not in Paused state"); - } - if (mpPulseAudioClient->isInThread() == true) { + if (mpPulseAudioClient->isInThread()) THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_OPERATION, "Can't resume in thread"); - } - - try { - internalLock(); - - if (isForceIgnore() == false && - mpAudioSessionHandler->isSkipSessionEvent() == false) { - /* Updates ASM to PLAYING */ - mpAudioSessionHandler->updatePlaying(); - } - - internalUnlock(); - CAudioIO::resume(); - - CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING); - } catch (CAudioError e) { - internalUnlock(); - throw e; - } + CAudioIO::resume(); + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING); } -void CAudioOutput::drain() throw(CAudioError) { - if (__IsInit() == false || __IsReady() == false) { +void CAudioOutput::drain() { + if (!__IsInit() || !__IsReady()) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioOutput"); - } - try { - CAudioIO::drain(); - } catch (CAudioError e) { - throw e; - } + if (mStreamCallback.onStream) + THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "async type don't support drain"); + + CAudioIO::drain(); } -void CAudioOutput::flush() throw(CAudioError) { - if (__IsInit() == false || __IsReady() == false) { +void CAudioOutput::flush() { + if (!__IsInit() || !__IsReady()) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioOutput"); - } - try { - CAudioIO::flush(); - } catch (CAudioError e) { - throw e; - } + CAudioIO::flush(); } -int CAudioOutput::getBufferSize() throw(CAudioError) { - if (__IsInit() == false) { +int CAudioOutput::getBufferSize() { + if (!__IsInit()) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioOutput"); - } /* FIXME : return calculated size here to satisfy backward compatibility */ return (mAudioInfo.getSampleRate() * DEFAULT_PERIOD_SIZE) / 1000 * mAudioInfo.getSampleSize(); } -size_t CAudioOutput::write(const void* buffer, size_t length) throw(CAudioError) { - if (__IsInit() == false || __IsReady() == false) { +size_t CAudioOutput::write(const void* buffer, size_t length) { + if (!__IsInit() || !__IsReady()) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioOutput"); - } - if (buffer == NULL) { + if (!buffer) THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameters are invalid - buffer:%p, length:%zu", buffer, length); - } - if (CAudioIO::getState() != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING) { + + if (CAudioIO::getState() != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING) THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "Can't write if not in Running state"); - } /* When write() is called in PulseAudio callback, bypass a pcm data to CPulseAudioClient (For Asynchronous) */ - if (mpPulseAudioClient->isInThread() == true) { + if (mpPulseAudioClient && mpPulseAudioClient->isInThread()) { int ret = mpPulseAudioClient->write(buffer, length); - if (ret < 0) { + if (ret < 0) THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, "The written result is invalid ret:%d", ret); - } - #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("CPulseAudioClient->write(buffer:%p, length:%d)", buffer, length); + AUDIO_IO_LOGD("CPulseAudioClient->write(buffer:%p, length:%zu)", buffer, length); #endif - return length; } @@ -372,7 +273,7 @@ size_t CAudioOutput::write(const void* buffer, size_t length) throw(CAudioError) internalLock(); // If another thread did call unprepare, do not write - if (mpPulseAudioClient == NULL) + if (!mpPulseAudioClient) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient"); @@ -386,24 +287,22 @@ size_t CAudioOutput::write(const void* buffer, size_t length) throw(CAudioError) while ((l = mpPulseAudioClient->getWritableSize()) == 0) { #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("writableSize is [%d].. wait", l); + AUDIO_IO_LOGD("writableSize is [%zu].. wait", l); #endif internalWait(); } - if (l > lengthIter) { + if (l > lengthIter) l = lengthIter; - } #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("CPulseAudioClient->write(buffer:%p, length:%d)", buffer, l); + AUDIO_IO_LOGD("CPulseAudioClient->write(buffer:%p, length:%zu)", buffer, l); #endif int ret = mpPulseAudioClient->write(buffer, l); - if (ret < 0) { - THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, - "The written result is invalid ret:%d", ret); - } + if (ret < 0) + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION,//LCOV_EXCL_LINE + "The written result is invalid ret:%d", ret); //LCOV_EXCL_LINE buffer = static_cast(buffer) + l; lengthIter -= l; @@ -411,10 +310,12 @@ size_t CAudioOutput::write(const void* buffer, size_t length) throw(CAudioError) __mIsUsedSyncWrite = false; internalUnlock(); - } catch (CAudioError e) { + + sched_yield(); + } catch (CAudioError& e) { __mIsUsedSyncWrite = false; internalUnlock(); - throw e; + throw; } return length;