X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fcpp%2FCAudioInput.cpp;h=9a07ad72690a3fe83c81934fdf0ff87d6add7e02;hb=3640dbe797b8043586b5cf8f25c13c98c2045296;hp=3887ddb6eb4d2dbf082e7268841e8b38b7a9c97f;hpb=3fb18ff5f2ad35c39e2f16148f5dc87f191dabff;p=platform%2Fcore%2Fapi%2Faudio-io.git diff --git a/src/cpp/CAudioInput.cpp b/src/cpp/CAudioInput.cpp index 3887ddb..9a07ad7 100644 --- a/src/cpp/CAudioInput.cpp +++ b/src/cpp/CAudioInput.cpp @@ -15,8 +15,11 @@ */ +#include + #include #include "CAudioIODef.h" +#include #define RECORDER_PRIVILEGE "http://tizen.org/privilege/recorder" #define CLIENT_NAME "AUDIO_IO_PA_CLIENT" @@ -36,6 +39,7 @@ CAudioInput::CAudioInput(CAudioInfo& info) : CAudioIO(info), __mIsUsedSyncRead(true), __mIsInit(false) { + mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN; } CAudioInput::CAudioInput( @@ -45,6 +49,7 @@ CAudioInput::CAudioInput( CAudioInfo::EAudioType audioType) : __mIsUsedSyncRead(true), __mIsInit(false) { + mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN; mAudioInfo = CAudioInfo(sampleRate, channel, type, audioType, -1); } @@ -74,15 +79,19 @@ void CAudioInput::onStream(CPulseAudioClient* pClient, size_t length) { 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) { +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:0x%x], [focus_type:%d], [state:%d], [reason_for_change:%s], [additional_info:%s]", pHandler, focus_type, state, reason_for_change, additional_info); + 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:0x%x], [signal:%d], [value:%d]", pHandler, signal, value); + AUDIO_IO_LOGD("[pHandler:%p], [signal:%d], [value:%d]", pHandler, signal, value); + CAudioIO::onSignal(pHandler, signal, value); } @@ -143,6 +152,7 @@ static bool __IsPrivilegeAllowed() { 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()"); @@ -169,7 +179,8 @@ static bool __IsPrivilegeAllowed() { 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); + 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 */ @@ -177,8 +188,13 @@ static bool __IsPrivilegeAllowed() { } 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); @@ -189,32 +205,37 @@ static bool __IsPrivilegeAllowed() { return prData.isPrivilegeAllowed; } -void CAudioInput::initialize() throw(CAudioError) { - if (__IsInit() == true) { +void CAudioInput::initialize() { + if (__IsInit() == true) return; - } try { CAudioIO::initialize(); - if (__IsPrivilegeAllowed() == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_PERMISSION_DENIED, "No privilege for record"); - } + } catch (CAudioError& e) { + finalize(); + throw; + } - // Create ASM Handler - mpAudioSessionHandler = new CAudioSessionHandler(CAudioSessionHandler::EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE, mAudioInfo, this); - if (mpAudioSessionHandler == NULL) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed to allocate CAudioSessionHandler object"); - } + if (__IsPrivilegeAllowed() == false) + THROW_ERROR_MSG(CAudioError::EError::ERROR_PERMISSION_DENIED, "No privilege for record"); - // Initialize ASM Handler + try { + internalSessionLock(); + mpAudioSessionHandler = new CAudioSessionHandler(CAudioSessionHandler::EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE, mAudioInfo, this); mpAudioSessionHandler->initialize(); - - __setInit(true); - CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); - } catch (CAudioError err) { + internalSessionUnlock(); + } catch (CAudioError& e) { + internalSessionUnlock(); finalize(); - throw err; + throw; + } catch (const std::bad_alloc&) { + internalSessionUnlock(); + finalize(); + THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed to allocate CAudioSessionHandler object"); } + + __setInit(true); + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); } void CAudioInput::finalize() { @@ -223,298 +244,257 @@ void CAudioInput::finalize() { return; } + internalSessionLock(); SAFE_FINALIZE(mpAudioSessionHandler); SAFE_DELETE(mpAudioSessionHandler); + internalSessionUnlock(); CAudioIO::finalize(); __setInit(false); } -void CAudioInput::prepare() throw(CAudioError) { - if (__IsInit() == false) { +void CAudioInput::prepare() { + if (__IsInit() == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); - } if (__IsReady() == true) { AUDIO_IO_LOGD("Already prepared CAudioInput"); + CAudioIO::prepare(); return; } - try { - internalLock(); - - // Check to invalid AudioType - CAudioInfo::EAudioType audioType = mAudioInfo.getAudioType(); - if (audioType < CAudioInfo::EAudioType::AUDIO_IN_TYPE_MEDIA || audioType > CAudioInfo::EAudioType::AUDIO_IN_TYPE_LOOPBACK) { - 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_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->isSkipSessionEvent() == false) { - // Register ASM Listener + try { + internalSessionLock(); + if (mpAudioSessionHandler && + mpAudioSessionHandler->getId() < 0) { // Did not registerSound() + if (isForceIgnore() == false && + mpAudioSessionHandler->isSkipSession() == false) { AUDIO_IO_LOGD("Register ASM Listener"); mpAudioSessionHandler->registerSound(); } } + internalSessionUnlock(); + } catch (CAudioError& e) { + internalSessionUnlock(); + throw; + } + + CAudioIO::setInternalStreamInfo(); + + try { + internalSessionLock(); + if (isSessionEnabled() && isForceIgnore() == false) + mpAudioSessionHandler->updatePlaying(); + internalSessionUnlock(); + } catch (CAudioError& e) { + internalSessionUnlock(); + throw; + } - // Init StreamSpec + try { + /* Init StreamSpec */ AUDIO_IO_LOGD("Set Stream Spec : CPulseStreamSpec::STREAM_LATENCY_INPUT_DEFAULT"); CPulseStreamSpec::EStreamLatency streamSpec = CPulseStreamSpec::EStreamLatency::STREAM_LATENCY_INPUT_DEFAULT; CPulseStreamSpec spec(streamSpec, mAudioInfo); - // Create PulseAudio Handler + internalLock(); mpPulseAudioClient = new CPulseAudioClient(CPulseAudioClient::EStreamDirection::STREAM_DIRECTION_RECORD, 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(); - // Do Prepare CAudioIO::prepare(); - } catch (CAudioError e) { + } catch (CAudioError& e) { + SAFE_FINALIZE(mpPulseAudioClient); + SAFE_DELETE(mpPulseAudioClient); + internalUnlock(); + throw; + } catch (const std::bad_alloc&) { internalUnlock(); - throw e; + 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() { + if (__IsInit() == false) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, + "Did not initialize CAudioInput"); if (__IsReady() == false) { AUDIO_IO_LOGD("Already unprepared"); return; } - try { - // Do unprepare - CAudioIO::unprepare(); + CAudioIO::unprepare(); + try { internalLock(); - 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(); + } catch (CAudioError& e) { + internalUnlock(); + throw; + } + + try { + internalSessionLock(); + if (isSessionEnabled() && isForceIgnore() == false) + mpAudioSessionHandler->updateStop(); + internalSessionUnlock(); CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); - } catch (CAudioError e) { - internalUnlock(); - throw e; + } catch (CAudioError& e) { + internalSessionUnlock(); + throw; } } -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() { + if (__IsInit() == false || __IsReady() == false) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, + "Did not initialize or prepare CAudioInput"); - 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() == true) 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 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() { + if (__IsInit() == false || __IsReady() == false) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, + "Did not initialize or prepare CAudioInput"); - 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() == true) 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 CAudioInput::drain() throw(CAudioError) { +void CAudioInput::drain() { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_SUPPORTED, "Did not support drain of CAudioInput"); } -void CAudioInput::flush() throw(CAudioError) { - if (__IsInit() == false || __IsReady() == false) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput"); - } +void CAudioInput::flush() { + if (__IsInit() == false || __IsReady() == false) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, + "Did not initialize or prepare CAudioInput"); - try { - CAudioIO::flush(); - } catch (CAudioError e) { - throw e; - } + CAudioIO::flush(); } -int CAudioInput::getBufferSize() throw(CAudioError) { - if (__IsInit() == false) { +int CAudioInput::getBufferSize() { + if (__IsInit() == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); - } /* 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) { +void CAudioInput::setStreamCallback(SStreamCallback callback) { + if (__IsInit() == false) THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); - } - if (callback.onStream == NULL) { - AUDIO_IO_LOGD("__mIsUsedSyncRead = true"); + if (callback.onStream == NULL) __mIsUsedSyncRead = true; - } else { - AUDIO_IO_LOGD("__mIsUsedSyncRead = false"); + else __mIsUsedSyncRead = false; - } + 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"); - } +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"); - if (buffer == NULL) { - 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 (buffer == NULL) + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, + "Parameters are NULL buffer:%p", buffer); + + 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) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "Invalid operation of read() if receive stream callback"); - } + if (__mIsUsedSyncRead == false) + THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, + "Invalid operation of read() if receive stream callback"); int ret = 0; try { internalLock(); + if (mIsInterrupted) + THROW_ERROR_MSG(CAudioError::EError::ERROR_POLICY_BLOCKED, "audio-io is interrupted"); // If another thread did call unprepare, do not read if (mpPulseAudioClient == NULL) - THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient"); + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, + "Did not initialize CPulseAudioClient"); // Block until read done ret = mpPulseAudioClient->read(buffer, length); - internalUnlock(); - } catch (CAudioError e) { + + sched_yield(); + } catch (CAudioError& e) { internalUnlock(); - throw e; + throw; } 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() == false || __IsReady() == false) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, + "Did not initialize or prepare CAudioInput"); - 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 == NULL || length == NULL) + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, + "Parameters are NULL buffer:%p, length:%p", buffer, length); /* Checks synchronous flag */ - if (__mIsUsedSyncRead == true) { - 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; - } + if (__mIsUsedSyncRead == true) + THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, + "Invalid operation of peek() if does not receive a stream callback"); - 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() == false || __IsReady() == false) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, + "Did not initialize or prepare CAudioInput"); /* Checks synchronous flag */ - if (__mIsUsedSyncRead == true) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "Invalid operation of drop() if does not receive a stream callback"); - } - - int ret = 0; - - try { - ret = mpPulseAudioClient->drop(); - } catch (CAudioError e) { - throw e; - } + if (__mIsUsedSyncRead == true) + THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, + "Invalid operation of drop() if does not receive a stream callback"); - return ret; + return mpPulseAudioClient->drop(); }