X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fcpp%2FCAudioInput.cpp;h=e95918dd481cbe044a022a9277e6c5347d1ed38a;hb=7ede27fb2ad5039f60ca1ba961ea61f887299678;hp=6c365e62584d072849084eca27dbfc0568f0dbb9;hpb=4d0fed17af4a54e451772f5c1227b0ed9541b9a7;p=platform%2Fcore%2Fapi%2Faudio-io.git diff --git a/src/cpp/CAudioInput.cpp b/src/cpp/CAudioInput.cpp index 6c365e6..e95918d 100644 --- a/src/cpp/CAudioInput.cpp +++ b/src/cpp/CAudioInput.cpp @@ -33,24 +33,11 @@ using namespace tizen_media_audio; CAudioInput::CAudioInput(CAudioInfo& info) : CAudioIO(info), __mIsUsedSyncRead(true), - __mIsInit(false) { + __mIsInit(false), + __mVolume(CAudioInfo::DEFAULT_RECORD_VOLUME) { mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN; } -CAudioInput::CAudioInput( - unsigned int sampleRate, - CAudioInfo::EChannel channel, - CAudioInfo::ESampleType type, - CAudioInfo::EAudioType audioType) : - __mIsUsedSyncRead(true), - __mIsInit(false) { - mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN; - mAudioInfo = CAudioInfo(sampleRate, channel, type, audioType, -1); -} - -CAudioInput::~CAudioInput() { -} - void CAudioInput::onStream(CPulseAudioClient* pClient, size_t length) { assert(pClient); @@ -58,9 +45,9 @@ void CAudioInput::onStream(CPulseAudioClient* pClient, size_t length) { * Does not call CAudioIO::onStream() for synchronization * if a user is using read() */ - if (__mIsUsedSyncRead == true) { + if (__mIsUsedSyncRead) { #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("Sync Read Mode! - pClient:[%p], length:[%d]", pClient, length); + AUDIO_IO_LOGD("Sync Read Mode! - pClient:[%p], length:[%zu]", pClient, length); #endif return; } @@ -69,57 +56,64 @@ void CAudioInput::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 CAudioInput::__setInit(bool flag) { +void CAudioInput::__setInit(bool flag) noexcept { __mIsInit = flag; } -bool CAudioInput::__IsInit() { - return (CAudioIO::isInit() == true && __mIsInit == true); +bool CAudioInput::__IsInit() noexcept { + return (CAudioIO::isInit() && __mIsInit); } -bool CAudioInput::__IsReady() { +bool CAudioInput::__IsReady() noexcept { return CAudioIO::IsReady(); } void CAudioInput::initialize() { - if (__IsInit() == true) + if (__IsInit()) return; - if (cpp_audio_in_has_record_privilege() == false) + if (!cpp_audio_in_has_record_privilege()) THROW_ERROR_MSG(CAudioError::EError::ERROR_PERMISSION_DENIED, "No privilege for record"); try { CAudioIO::initialize(); __setInit(true); - } catch (CAudioError& e) { + } catch (const CAudioError& e) { +//LCOV_EXCL_START finalize(); throw; +//LCOV_EXCL_STOP } + CAudioIO::setState(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); } void CAudioInput::finalize() { - if (__IsInit() == false) { + if (!__IsInit()) { +//LCOV_EXCL_START AUDIO_IO_LOGD("Did not initialize"); return; +//LCOV_EXCL_STOP } CAudioIO::finalize(); - __setInit(false); + __mVolume = CAudioInfo::DEFAULT_RECORD_VOLUME; } void CAudioInput::prepare() { - if (__IsInit() == false) - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); + std::lock_guard mutex(mMutex); + + if (!__IsInit()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); //LCOV_EXCL_LINE - if (__IsReady() == true) { + if (__IsReady()) { AUDIO_IO_LOGD("Already prepared CAudioInput"); CAudioIO::prepare(); return; @@ -136,127 +130,139 @@ void CAudioInput::prepare() { /* Init StreamSpec */ AUDIO_IO_LOGD("Set Stream Spec : CPulseStreamSpec::STREAM_LATENCY_INPUT_DEFAULT"); CPulseStreamSpec::EStreamLatency streamSpec = CPulseStreamSpec::EStreamLatency::STREAM_LATENCY_INPUT_DEFAULT; + /* Override the default value by audio type */ + if (audioType == CAudioInfo::EAudioType::AUDIO_IN_TYPE_VOIP) + streamSpec = CPulseStreamSpec::EStreamLatency::STREAM_LATENCY_INPUT_VOIP; + CPulseStreamSpec spec(streamSpec, mAudioInfo); - internalLock(); mpPulseAudioClient = new CPulseAudioClient(CPulseAudioClient::EStreamDirection::STREAM_DIRECTION_RECORD, spec, this); mpPulseAudioClient->initialize(); + mpPulseAudioClient->applyRecordVolume(__mVolume); #ifndef DISABLE_MOBILE_BACK_COMP /* Uncork stream which is created with CORKED flag */ mpPulseAudioClient->cork(false); #endif - internalUnlock(); - CAudioIO::prepare(); - } catch (CAudioError& e) { + } catch (const CAudioError& e) { +//LCOV_EXCL_START SAFE_FINALIZE(mpPulseAudioClient); SAFE_DELETE(mpPulseAudioClient); - internalUnlock(); throw; +//LCOV_EXCL_STOP } catch (const std::bad_alloc&) { - internalUnlock(); THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed to allocate CPulseAudioClient object"); } } void CAudioInput::unprepare() { - if (__IsInit() == false) - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize CAudioInput"); + std::unique_lock mutex(mMutex); + + if (!__IsInit()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, //LCOV_EXCL_LINE + "Did not initialize CAudioInput"); //LCOV_EXCL_LINE - if (__IsReady() == false) { + if (!__IsReady()) { AUDIO_IO_LOGD("Already unprepared"); return; } 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); - internalUnlock(); - } catch (CAudioError& e) { - internalUnlock(); - throw; - } + if (mpPulseAudioClient && mpPulseAudioClient->isInThread()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "Can't unprepare inside pulseaudio thread"); + + SAFE_FINALIZE(mpPulseAudioClient); + SAFE_DELETE(mpPulseAudioClient); + + CAudioIO::setState(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); + + mutex.unlock(); CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); } void CAudioInput::pause() { - if (__IsInit() == false || __IsReady() == false) - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize or prepare CAudioInput"); + std::unique_lock mutex(mMutex); + + if (!__IsInit() || !__IsReady()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, //LCOV_EXCL_LINE + "Did not initialize or prepare CAudioInput"); //LCOV_EXCL_LINE 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) - THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_OPERATION, "Can't pause in thread"); + if (mpPulseAudioClient->isInThread()) + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_OPERATION, "Can't pause in thread"); //LCOV_EXCL_LINE CAudioIO::pause(); + CAudioIO::setState(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED); + + mutex.unlock(); + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED); } void CAudioInput::resume() { - if (__IsInit() == false || __IsReady() == false) - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize or prepare CAudioInput"); + std::unique_lock mutex(mMutex); + + if (!__IsInit() || !__IsReady()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, //LCOV_EXCL_LINE + "Did not initialize or prepare CAudioInput"); //LCOV_EXCL_LINE 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) - THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_OPERATION, "Can't resume in thread"); + if (mpPulseAudioClient->isInThread()) + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_OPERATION, "Can't resume in thread"); //LCOV_EXCL_LINE CAudioIO::resume(); - CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING); -} + CAudioIO::setState(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING); -void CAudioInput::drain() { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_SUPPORTED, "Did not support drain of CAudioInput"); + mutex.unlock(); + + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING); } void CAudioInput::flush() { - if (__IsInit() == false || __IsReady() == false) - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize or prepare CAudioInput"); + std::lock_guard mutex(mMutex); + + if (!__IsInit() || !__IsReady()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, //LCOV_EXCL_LINE + "Did not initialize or prepare CAudioInput"); //LCOV_EXCL_LINE CAudioIO::flush(); } int CAudioInput::getBufferSize() { - if (__IsInit() == false) - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); + if (!__IsInit()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); //LCOV_EXCL_LINE /* FIXME : return calculated size here to satisfy backward compatibility */ return (mAudioInfo.getSampleRate() * DEFAULT_PERIOD_SIZE) / 1000 * mAudioInfo.getSampleSize(); } void CAudioInput::setStreamCallback(SStreamCallback callback) { - if (__IsInit() == false) - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); + if (!__IsInit()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); //LCOV_EXCL_LINE + + __mIsUsedSyncRead = (callback.onStream == nullptr); - if (callback.onStream == NULL) - __mIsUsedSyncRead = true; - else - __mIsUsedSyncRead = false; AUDIO_IO_LOGD("__mIsUsedSyncRead = %d", __mIsUsedSyncRead); CAudioIO::setStreamCallback(callback); } size_t CAudioInput::read(void* buffer, size_t length) { - if (__IsInit() == false || __IsReady() == false) - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize or prepare CAudioInput"); + std::unique_lock mutex(mMutex); + + if (!__IsInit() || !__IsReady()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, //LCOV_EXCL_LINE + "Did not initialize or prepare CAudioInput"); //LCOV_EXCL_LINE - if (buffer == NULL) + if (!buffer) THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameters are NULL buffer:%p", buffer); @@ -265,44 +271,37 @@ size_t CAudioInput::read(void* buffer, size_t length) { "Can't read if not in Running state"); /* Checks synchronous flag */ - if (__mIsUsedSyncRead == false) + if (!__mIsUsedSyncRead) THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "Invalid operation of read() if receive stream callback"); int ret = 0; - try { - internalLock(); + // If another thread did call unprepare, do not read + if (!mpPulseAudioClient) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, //LCOV_EXCL_LINE + "Did not initialize CPulseAudioClient"); //LCOV_EXCL_LINE - // If another thread did call unprepare, do not read - if (mpPulseAudioClient == NULL) - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize CPulseAudioClient"); + // Block until read done + ret = mpPulseAudioClient->read(buffer, length); + mutex.unlock(); - // Block until read done - ret = mpPulseAudioClient->read(buffer, length); - internalUnlock(); - - sched_yield(); - } catch (CAudioError& e) { - internalUnlock(); - throw; - } + sched_yield(); return ret; } int CAudioInput::peek(const void** buffer, size_t* length) { - if (__IsInit() == false || __IsReady() == false) - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize or prepare CAudioInput"); + if (!__IsInit() || !__IsReady()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, //LCOV_EXCL_LINE + "Did not initialize or prepare CAudioInput"); //LCOV_EXCL_LINE - if (buffer == NULL || length == NULL) - THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, - "Parameters are NULL buffer:%p, length:%p", buffer, length); + if (buffer == nullptr || length == nullptr) + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, //LCOV_EXCL_LINE + "Parameters are NULL buffer:%p, length:%p", buffer, length); //LCOV_EXCL_LINE /* Checks synchronous flag */ - if (__mIsUsedSyncRead == true) + if (__mIsUsedSyncRead) THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "Invalid operation of peek() if does not receive a stream callback"); @@ -310,14 +309,36 @@ int CAudioInput::peek(const void** buffer, size_t* length) { } int CAudioInput::drop() { - if (__IsInit() == false || __IsReady() == false) - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize or prepare CAudioInput"); + if (!__IsInit() || !__IsReady()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, //LCOV_EXCL_LINE + "Did not initialize or prepare CAudioInput"); //LCOV_EXCL_LINE /* Checks synchronous flag */ - if (__mIsUsedSyncRead == true) + if (__mIsUsedSyncRead) THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "Invalid operation of drop() if does not receive a stream callback"); return mpPulseAudioClient->drop(); } + +void CAudioInput::setVolume(double volume) { + if (!__IsInit()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Not initialized"); //LCOV_EXCL_LINE + + if (__IsReady()) { + std::unique_lock defer_mutex(mMutex, std::defer_lock); + if (!mpPulseAudioClient->isInThread()) + defer_mutex.lock(); + + mpPulseAudioClient->applyRecordVolume(volume); + } + + __mVolume = volume; +} + +double CAudioInput::getVolume() { + if (!__IsInit()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Not initialized"); //LCOV_EXCL_LINE + + return __mVolume; +}