X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fcpp%2FCAudioInput.cpp;h=e95918dd481cbe044a022a9277e6c5347d1ed38a;hb=7ede27fb2ad5039f60ca1ba961ea61f887299678;hp=a5ee5eef7196884a66a9a2a9ce6d854a374a856f;hpb=a504ae3c3756657e8bc4e7f34fa489795ef3c2ea;p=platform%2Fcore%2Fapi%2Faudio-io.git diff --git a/src/cpp/CAudioInput.cpp b/src/cpp/CAudioInput.cpp index a5ee5ee..e95918d 100644 --- a/src/cpp/CAudioInput.cpp +++ b/src/cpp/CAudioInput.cpp @@ -17,9 +17,9 @@ #include -#include #include "CAudioIODef.h" #include +#include "cpp_audio_in_privilege.h" #define RECORDER_PRIVILEGE "http://tizen.org/privilege/recorder" #define CLIENT_NAME "AUDIO_IO_PA_CLIENT" @@ -27,33 +27,15 @@ using namespace std; using namespace tizen_media_audio; -struct PrivilegeData { - bool isPrivilegeAllowed; - pa_threaded_mainloop *paMainloop; -}; - /** * class CAudioInput inherited by CAudioIO */ CAudioInput::CAudioInput(CAudioInfo& info) : CAudioIO(info), __mIsUsedSyncRead(true), - __mIsInit(false) { - mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN; -} - -CAudioInput::CAudioInput( - unsigned int sampleRate, - CAudioInfo::EChannel channel, - CAudioInfo::ESampleType type, - CAudioInfo::EAudioType audioType) : - __mIsUsedSyncRead(true), - __mIsInit(false) { + __mIsInit(false), + __mVolume(CAudioInfo::DEFAULT_RECORD_VOLUME) { mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN; - mAudioInfo = CAudioInfo(sampleRate, channel, type, audioType, -1); -} - -CAudioInput::~CAudioInput() { } void CAudioInput::onStream(CPulseAudioClient* pClient, size_t length) { @@ -63,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; } @@ -74,467 +56,289 @@ 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::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:%p], [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 CAudioInput::onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t signal, int value) { - assert(pHandler); - AUDIO_IO_LOGD("[pHandler:%p], [signal:%d], [value:%d]", pHandler, signal, value); - CAudioIO::onSignal(pHandler, signal, value); -} - -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(); } -static void __contextStateChangeCb(pa_context* c, void* user_data) { - pa_threaded_mainloop *paMainloop = static_cast(user_data); - assert(paMainloop); - assert(c); - - switch (pa_context_get_state(c)) { - case PA_CONTEXT_READY: - AUDIO_IO_LOGD("The context is ready"); - pa_threaded_mainloop_signal(paMainloop, 0); - break; - - case PA_CONTEXT_FAILED: - case PA_CONTEXT_TERMINATED: - AUDIO_IO_LOGD("The context is lost"); - pa_threaded_mainloop_signal(paMainloop, 0); - break; - - case PA_CONTEXT_UNCONNECTED: - case PA_CONTEXT_CONNECTING: - case PA_CONTEXT_AUTHORIZING: - case PA_CONTEXT_SETTING_NAME: - break; - } -} - -static void __checkPrivilegeCb(pa_context *c, int success, void *user_data) { - AUDIO_IO_LOGD("pa_context[%p], success[%d], user_data[%p]", c, success, user_data); - assert(c); - assert(user_data); - - PrivilegeData *prData = static_cast(user_data); - prData->isPrivilegeAllowed = success ? true : false; - - pa_threaded_mainloop_signal(prData->paMainloop, 0); -} - -static bool __IsPrivilegeAllowed() { - pa_operation *o; - pa_context *c; - int err = 0; - PrivilegeData prData; - - prData.paMainloop = pa_threaded_mainloop_new(); - if (prData.paMainloop == NULL) - THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pa_threaded_mainloop_new()"); - c = pa_context_new(pa_threaded_mainloop_get_api(prData.paMainloop), CLIENT_NAME); - if (c == NULL) - THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pa_context_new()"); - - pa_context_set_state_callback(c, __contextStateChangeCb, prData.paMainloop); - - if (pa_context_connect(c, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) - THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pa_context_connect()"); - - pa_threaded_mainloop_lock(prData.paMainloop); - - if (pa_threaded_mainloop_start(prData.paMainloop) < 0) { - pa_threaded_mainloop_unlock(prData.paMainloop); - THROW_ERROR_MSG(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed pa_threaded_mainloop_start()"); - } - - while (true) { - pa_context_state_t state; - state = pa_context_get_state(c); - - if (state == PA_CONTEXT_READY) - break; - - if (!PA_CONTEXT_IS_GOOD(state)) { - err = pa_context_errno(c); - pa_threaded_mainloop_unlock(prData.paMainloop); - THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, - "pa_context's state is not good : err[%d]", err); - } - - /* Wait until the context is ready */ - pa_threaded_mainloop_wait(prData.paMainloop); - } - - o = pa_context_check_privilege(c, RECORDER_PRIVILEGE, __checkPrivilegeCb, &prData); - if (!o) { - pa_threaded_mainloop_unlock(prData.paMainloop); - THROW_ERROR_MSG(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed to pa_context_check_privilege()"); - } - while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) - pa_threaded_mainloop_wait(prData.paMainloop); - pa_operation_unref(o); - - pa_threaded_mainloop_unlock(prData.paMainloop); - pa_threaded_mainloop_stop(prData.paMainloop); - pa_context_disconnect(c); - pa_context_unref(c); - pa_threaded_mainloop_free(prData.paMainloop); - - return prData.isPrivilegeAllowed; -} - -void CAudioInput::initialize() throw(CAudioError) { - if (__IsInit() == true) { +void CAudioInput::initialize() { + if (__IsInit()) return; - } + + if (!cpp_audio_in_has_record_privilege()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_PERMISSION_DENIED, "No privilege for record"); try { CAudioIO::initialize(); - if (__IsPrivilegeAllowed() == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_PERMISSION_DENIED, "No privilege for record"); - } - - // Create ASM Handler - mpAudioSessionHandler = new CAudioSessionHandler(CAudioSessionHandler::EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE, mAudioInfo, this); - - // Initialize ASM Handler - mpAudioSessionHandler->initialize(); - __setInit(true); - CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); - } catch (CAudioError err) { + } catch (const CAudioError& e) { +//LCOV_EXCL_START finalize(); - throw err; - } catch (std::bad_alloc&) { - finalize(); - THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed to allocate CAudioSessionHandler object"); + 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 } - SAFE_FINALIZE(mpAudioSessionHandler); - SAFE_DELETE(mpAudioSessionHandler); - CAudioIO::finalize(); - __setInit(false); + __mVolume = CAudioInfo::DEFAULT_RECORD_VOLUME; } -void CAudioInput::prepare() throw(CAudioError) { - if (__IsInit() == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); - } +void CAudioInput::prepare() { + std::lock_guard mutex(mMutex); - if (__IsReady() == true) { + if (!__IsInit()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); //LCOV_EXCL_LINE + + if (__IsReady()) { AUDIO_IO_LOGD("Already prepared CAudioInput"); + CAudioIO::prepare(); return; } + /* Check invalid AudioType */ + CAudioInfo::EAudioType audioType = mAudioInfo.getAudioType(); + if (audioType < CAudioInfo::EAudioType::AUDIO_IN_TYPE_MEDIA || + audioType >= CAudioInfo::EAudioType::AUDIO_OUT_TYPE_MEDIA) + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, + "The audioType is invalid [type:%d]", static_cast(audioType)); + try { - internalLock(); - - // Check to invalid AudioType - CAudioInfo::EAudioType audioType = mAudioInfo.getAudioType(); - if (audioType < CAudioInfo::EAudioType::AUDIO_IN_TYPE_MEDIA || audioType >= CAudioInfo::EAudioType::AUDIO_OUT_TYPE_MEDIA) { - 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() - // Check session to skip registration - if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSession() == false) { - // Register ASM Listener - AUDIO_IO_LOGD("Register ASM Listener"); - mpAudioSessionHandler->registerSound(); - } - } - - CAudioIO::setInternalStreamInfo(); - - // Init StreamSpec + /* 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); - // Create PulseAudio Handler mpPulseAudioClient = new CPulseAudioClient(CPulseAudioClient::EStreamDirection::STREAM_DIRECTION_RECORD, spec, this); - - // Initialize PulseAudio Handler mpPulseAudioClient->initialize(); - - if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSession() == false) - mpAudioSessionHandler->updatePlaying(); - - internalUnlock(); - - // Do Prepare + mpPulseAudioClient->applyRecordVolume(__mVolume); +#ifndef DISABLE_MOBILE_BACK_COMP + /* Uncork stream which is created with CORKED flag */ + mpPulseAudioClient->cork(false); +#endif CAudioIO::prepare(); - } catch (CAudioError e) { - internalUnlock(); - throw e; - } catch (std::bad_alloc&) { - internalUnlock(); + } catch (const CAudioError& e) { +//LCOV_EXCL_START + SAFE_FINALIZE(mpPulseAudioClient); + SAFE_DELETE(mpPulseAudioClient); + throw; +//LCOV_EXCL_STOP + } catch (const std::bad_alloc&) { THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed to allocate CPulseAudioClient object"); } } -void CAudioInput::unprepare() throw(CAudioError) { - if (__IsInit() == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize CAudioInput"); - } +void CAudioInput::unprepare() { + 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; } - try { - CAudioIO::unprepare(); - - internalLock(); + CAudioIO::unprepare(); - SAFE_FINALIZE(mpPulseAudioClient); - SAFE_DELETE(mpPulseAudioClient); + if (mpPulseAudioClient && mpPulseAudioClient->isInThread()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "Can't unprepare inside pulseaudio thread"); - internalUnlock(); + SAFE_FINALIZE(mpPulseAudioClient); + SAFE_DELETE(mpPulseAudioClient); - if (mpAudioSessionHandler->getId() >= 0) { - if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSession() == false) - mpAudioSessionHandler->updateStop(); + CAudioIO::setState(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); - if (mpAudioSessionHandler->isSkipSession() == false) - mpAudioSessionHandler->unregisterSound(); - } + mutex.unlock(); - CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); - } catch (CAudioError e) { - internalUnlock(); - throw e; - } + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); } -void CAudioInput::pause() throw(CAudioError) { - if (__IsInit() == false || __IsReady() == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize or prepare CAudioInput"); - } +void CAudioInput::pause() { + 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) { + 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 - try { - CAudioIO::pause(); - - internalLock(); + CAudioIO::pause(); + CAudioIO::setState(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED); - /* Updates ASM to STOP */ - if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSession() == false) { - mpAudioSessionHandler->updateStop(); - } + mutex.unlock(); - internalUnlock(); - - CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED); - } catch (CAudioError e) { - internalUnlock(); - throw e; - } + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED); } -void CAudioInput::resume() throw(CAudioError) { - if (__IsInit() == false || __IsReady() == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize or prepare CAudioInput"); - } +void CAudioInput::resume() { + 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) { + 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"); - } - - try { - internalLock(); - - if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSession() == false) - mpAudioSessionHandler->updatePlaying(); + if (mpPulseAudioClient->isInThread()) + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_OPERATION, "Can't resume in thread"); //LCOV_EXCL_LINE - internalUnlock(); + CAudioIO::resume(); + CAudioIO::setState(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING); - CAudioIO::resume(); + mutex.unlock(); - CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING); - } catch (CAudioError e) { - internalUnlock(); - throw e; - } + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING); } -void CAudioInput::drain() throw(CAudioError) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_SUPPORTED, "Did not support drain of CAudioInput"); -} +void CAudioInput::flush() { + std::lock_guard mutex(mMutex); -void CAudioInput::flush() throw(CAudioError) { - 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 - try { - CAudioIO::flush(); - } catch (CAudioError e) { - throw e; - } + CAudioIO::flush(); } -int CAudioInput::getBufferSize() throw(CAudioError) { - if (__IsInit() == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); - } +int CAudioInput::getBufferSize() { + 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) throw(CAudioError) { - if (__IsInit() == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); - } +void CAudioInput::setStreamCallback(SStreamCallback callback) { + if (!__IsInit()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); //LCOV_EXCL_LINE - if (callback.onStream == NULL) { - AUDIO_IO_LOGD("__mIsUsedSyncRead = true"); - __mIsUsedSyncRead = true; - } else { - AUDIO_IO_LOGD("__mIsUsedSyncRead = false"); - __mIsUsedSyncRead = false; - } + __mIsUsedSyncRead = (callback.onStream == nullptr); + + AUDIO_IO_LOGD("__mIsUsedSyncRead = %d", __mIsUsedSyncRead); CAudioIO::setStreamCallback(callback); } -size_t CAudioInput::read(void* buffer, size_t length) throw(CAudioError) { - if (__IsInit() == false || __IsReady() == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize or prepare CAudioInput"); - } - if (buffer == NULL) { +size_t CAudioInput::read(void* buffer, size_t length) { + 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) THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameters are NULL buffer:%p", buffer); - } - 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 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 e; - } + sched_yield(); return ret; } -int CAudioInput::peek(const void** buffer, size_t* length) throw(CAudioError) { - if (__IsInit() == false || __IsReady() == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize or prepare CAudioInput"); - } +int CAudioInput::peek(const void** buffer, size_t* length) { + 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"); - } - - int ret = 0; - try { - ret = mpPulseAudioClient->peek(buffer, length); - } catch (CAudioError e) { - throw e; - } - - return ret; + return mpPulseAudioClient->peek(buffer, length); } -int CAudioInput::drop() throw(CAudioError) { - if (__IsInit() == false || __IsReady() == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, - "Did not initialize or prepare CAudioInput"); - } +int CAudioInput::drop() { + 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"); - } - int ret = 0; + return mpPulseAudioClient->drop(); +} - try { - ret = mpPulseAudioClient->drop(); - } catch (CAudioError e) { - throw e; +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); } - return ret; + __mVolume = volume; +} + +double CAudioInput::getVolume() { + if (!__IsInit()) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Not initialized"); //LCOV_EXCL_LINE + + return __mVolume; }