X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fcpp%2FCAudioInput.cpp;h=8b644934252313b869c693a765a2d243c3b0896b;hb=20b14df3ee6f2addbc5fed71dde71ed5c1ebce3e;hp=93a5b90b9de3a959dba6b6c1ed6818e1c2ba9f2a;hpb=7e9f563ebfc3c1b8b575d7c053ca4826b5a116a5;p=platform%2Fcore%2Fapi%2Faudio-io.git diff --git a/src/cpp/CAudioInput.cpp b/src/cpp/CAudioInput.cpp index 93a5b90..8b64493 100644 --- a/src/cpp/CAudioInput.cpp +++ b/src/cpp/CAudioInput.cpp @@ -15,33 +15,39 @@ */ +#include #include "CAudioIODef.h" +#include +#define RECORDER_PRIVILEGE "http://tizen.org/privilege/recorder" +#define CLIENT_NAME "AUDIO_IO_PA_CLIENT" 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), - mpSyncReadDataPtr(NULL), - mSyncReadIndex(0), - mSyncReadLength(0), - mIsUsedSyncRead(true) { +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) - : mpSyncReadDataPtr(NULL), - mSyncReadIndex(0), - mSyncReadLength(0), - mIsUsedSyncRead(true) { + CAudioInfo::EAudioType audioType) : + __mIsUsedSyncRead(true), + __mIsInit(false) { + mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN; mAudioInfo = CAudioInfo(sampleRate, channel, type, audioType, -1); } @@ -55,11 +61,10 @@ 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 == true) { #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("Sync Read Mode! - signal! - pClient:[%p], length:[%d]", pClient, length); + AUDIO_IO_LOGD("Sync Read Mode! - pClient:[%p], length:[%d]", pClient, length); #endif - internalSignal(); return; } @@ -72,49 +77,151 @@ 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); } -void CAudioInput::setInit(bool flag) { - mIsInit = flag; +void CAudioInput::__setInit(bool flag) { + __mIsInit = flag; } -bool CAudioInput::IsInit() { - return (CAudioIO::isInit() == true && mIsInit == true); +bool CAudioInput::__IsInit() { + return (CAudioIO::isInit() == true && __mIsInit == true); } -bool CAudioInput::IsReady() { +bool CAudioInput::__IsReady() { return CAudioIO::IsReady(); } -void CAudioInput::initialize() throw (CAudioError) { - if (IsInit() == true) { +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) { return; } 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::AUDIO_SESSION_TYPE_CAPTURE, mAudioInfo, this); + mpAudioSessionHandler = new CAudioSessionHandler(CAudioSessionHandler::EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE, mAudioInfo, this); if (mpAudioSessionHandler == NULL) { - THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed to allocate CAudioSessionHandler object"); + THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed to allocate CAudioSessionHandler object"); } // Initialize ASM Handler mpAudioSessionHandler->initialize(); - setInit(true); - CAudioIO::onStateChanged(CAudioInfo::AUDIO_IO_STATE_IDLE); + __setInit(true); + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); } catch (CAudioError err) { finalize(); throw err; @@ -122,7 +229,7 @@ void CAudioInput::initialize() throw (CAudioError) { } void CAudioInput::finalize() { - if (IsInit() == false) { + if (__IsInit() == false) { AUDIO_IO_LOGD("Did not initialize"); return; } @@ -132,15 +239,15 @@ void CAudioInput::finalize() { CAudioIO::finalize(); - setInit(false); + __setInit(false); } -void CAudioInput::prepare() throw (CAudioError) { - if (IsInit() == false) { - THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); +void CAudioInput::prepare() throw(CAudioError) { + if (__IsInit() == false) { + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); } - if (IsReady() == true) { + if (__IsReady() == true) { AUDIO_IO_LOGD("Already prepared CAudioInput"); return; } @@ -150,37 +257,39 @@ void CAudioInput::prepare() throw (CAudioError) { // Check to invalid AudioType CAudioInfo::EAudioType audioType = mAudioInfo.getAudioType(); - if (audioType < CAudioInfo::AUDIO_IN_TYPE_MEDIA || audioType > CAudioInfo::AUDIO_IN_TYPE_LOOPBACK) { - THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "The audioType is invalid [type:%d]", static_cast(audioType)); + 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)); } - if (mpAudioSessionHandler->getId() < 0) { //Did not registerSound() + if (mpAudioSessionHandler->getId() < 0) { // Did not registerSound() // Check session to skip registration - if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSessionEvent() == false) { + if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSession() == false) { // Register ASM Listener AUDIO_IO_LOGD("Register ASM Listener"); mpAudioSessionHandler->registerSound(); } } + CAudioIO::setInternalStreamInfo(); + // Init StreamSpec - AUDIO_IO_LOGD("Set Strem Spec : CPulseStreamSpec::STREAM_LATENCY_INPUT_MID"); - CPulseStreamSpec::EStreamLatency streamSpec = CPulseStreamSpec::STREAM_LATENCY_INPUT_MID; + 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 - mpPulseAudioClient = new CPulseAudioClient(CPulseAudioClient::STREAM_DIRECTION_RECORD, spec, this); + mpPulseAudioClient = new CPulseAudioClient(CPulseAudioClient::EStreamDirection::STREAM_DIRECTION_RECORD, spec, this); if (mpPulseAudioClient == NULL) { - THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed to allocate CPulseAudioClient object"); + 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 */ + if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSession() == false) mpAudioSessionHandler->updatePlaying(); - } internalUnlock(); @@ -192,18 +301,18 @@ void CAudioInput::prepare() throw (CAudioError) { } } -void CAudioInput::unprepare() throw (CAudioError) { - if (IsInit() == false) { - THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); +void CAudioInput::unprepare() throw(CAudioError) { + if (__IsInit() == false) { + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, + "Did not initialize CAudioInput"); } - if (IsReady() == false) { + if (__IsReady() == false) { AUDIO_IO_LOGD("Already unprepared"); return; } - try{ - // Do unprepare + try { CAudioIO::unprepare(); internalLock(); @@ -211,282 +320,218 @@ void CAudioInput::unprepare() throw (CAudioError) { SAFE_FINALIZE(mpPulseAudioClient); SAFE_DELETE(mpPulseAudioClient); + internalUnlock(); + if (mpAudioSessionHandler->getId() >= 0) { - /* Updates ASM to STOP */ - if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSessionEvent() == false) { + if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSession() == false) mpAudioSessionHandler->updateStop(); - } - bool isSkip = mpAudioSessionHandler->isSkipSessionEvent(); - if (isSkip == false) { + if (mpAudioSessionHandler->isSkipSession() == false) mpAudioSessionHandler->unregisterSound(); - } } - internalUnlock(); - - CAudioIO::onStateChanged(CAudioInfo::AUDIO_IO_STATE_IDLE); + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE); } catch (CAudioError e) { internalUnlock(); throw e; } } -void CAudioInput::pause() throw (CAudioError) { - if (IsInit() == false || IsReady() == false) { - THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput"); +void CAudioInput::pause() throw(CAudioError) { + 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) { + THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_STATE, + "Can't pause if not in Running state"); } - try{ + 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) { + if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSession() == false) { mpAudioSessionHandler->updateStop(); } internalUnlock(); - CAudioIO::onStateChanged(CAudioInfo::AUDIO_IO_STATE_PAUSED); + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED); } catch (CAudioError e) { internalUnlock(); throw e; } } -void CAudioInput::resume() throw (CAudioError) { - if (IsInit() == false || IsReady() == false) { - THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput"); +void CAudioInput::resume() throw(CAudioError) { + 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) { + 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->isSkipSessionEvent() == false) { - - /* Updates ASM to PLAYING */ + if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSession() == false) mpAudioSessionHandler->updatePlaying(); - } internalUnlock(); CAudioIO::resume(); - CAudioIO::onStateChanged(CAudioInfo::AUDIO_IO_STATE_RUNNING); + CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING); } catch (CAudioError e) { internalUnlock(); throw e; } } -void CAudioInput::drain() throw (CAudioError) { - if (IsInit() == false || IsReady() == false) { - THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput"); - } - - try{ - CAudioIO::drain(); - } catch (CAudioError e) { - internalUnlock(); - throw e; - } +void CAudioInput::drain() throw(CAudioError) { + 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::ERROR_NOT_INITIALIZED, "Did not initialize or prepare 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"); } try { CAudioIO::flush(); } catch (CAudioError e) { - internalUnlock(); throw e; } } -int CAudioInput::getBufferSize() throw (CAudioError) { - if (IsInit() == false) { - THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); - } - - if (IsReady() == false) { - AUDIO_IO_LOGD("Warning: Did not prepare CAudioInput, then return zero"); - return 0; - } - - int size = 0; - - try { - internalLock(); - size = mpPulseAudioClient->getBufferSize(); - internalUnlock(); - } catch (CAudioError err) { - internalUnlock(); - throw err; +int CAudioInput::getBufferSize() throw(CAudioError) { + if (__IsInit() == false) { + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); } - return size; + /* 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::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); +void CAudioInput::setStreamCallback(SStreamCallback callback) throw(CAudioError) { + if (__IsInit() == false) { + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); } - internalLock(); if (callback.onStream == NULL) { - AUDIO_IO_LOGD("mIsUsedSyncRead = true"); - mIsUsedSyncRead = true; + AUDIO_IO_LOGD("__mIsUsedSyncRead = true"); + __mIsUsedSyncRead = true; } else { - AUDIO_IO_LOGD("mIsUsedSyncRead = false"); - mIsUsedSyncRead = false; + AUDIO_IO_LOGD("__mIsUsedSyncRead = false"); + __mIsUsedSyncRead = false; } - internalUnlock(); CAudioIO::setStreamCallback(callback); } -size_t CAudioInput::read(void* buffer, size_t length) throw (CAudioError) { - if (IsInit() == false || IsReady() == false) { - THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput"); +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) { - THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are invalid - buffer:%p, length:%zu", buffer, length); + 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::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"); } - internalLock(); - - size_t lengthIter = length; int ret = 0; try { - while (lengthIter > 0) { - size_t l; - - while (mpSyncReadDataPtr == NULL) { - ret = mpPulseAudioClient->peek(&mpSyncReadDataPtr, &mSyncReadLength); - if (ret != 0) { - THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INTERNAL_OPERATION, "Failed CPulseAudioClient::peek() ret:[%d]", ret); - } - - if (mSyncReadLength <= 0) { -#ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("readLength(%d byte) is not valid.. wait..", mSyncReadLength); -#endif - internalWait(); - } else if (mpSyncReadDataPtr == NULL) { - /* There's a hole in the stream, skip it. We could generate - * silence, but that wouldn't work for compressed streams. - */ - ret = mpPulseAudioClient->drop(); - if (ret != 0) { - THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INTERNAL_OPERATION, "Failed CPulseAudioClient::drop() ret:[%d]", ret); - } - } else { - mSyncReadIndex = 0; - } - }//end of while (pReadData == NULL) - - if (mSyncReadLength < lengthIter) { - l = mSyncReadLength; - } else { - l = lengthIter; - } - - // Copy partial pcm data on out parameter -#ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("memcpy() that a peeked buffer(%p), index(%d), length(%d), on out buffer", (const uint8_t*)(mpSyncReadDataPtr) + mSyncReadIndex, mSyncReadIndex, l); -#endif - memcpy(buffer, (const uint8_t*)mpSyncReadDataPtr + mSyncReadIndex, l); + internalLock(); - // Move next position - buffer = (uint8_t*)buffer + l; - lengthIter -= l; + // If another thread did call unprepare, do not read + if (mpPulseAudioClient == NULL) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, + "Did not initialize CPulseAudioClient"); - // Adjusts the rest length - mSyncReadIndex += l; - mSyncReadLength -= l; + // Block until read done + ret = mpPulseAudioClient->read(buffer, length); - if (mSyncReadLength == 0) { -#ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("mSyncReadLength is zero - Do drop()"); -#endif - ret = mpPulseAudioClient->drop(); - if (ret != 0) { - THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INTERNAL_OPERATION, "Failed CPulseAudioClient::drop() ret:[%d]", ret); - } - - // Reset the internal pointer - mpSyncReadDataPtr = NULL; - mSyncReadLength = 0; - mSyncReadIndex = 0; - } - }//end of while (length > 0) + internalUnlock(); + sched_yield(); } catch (CAudioError e) { internalUnlock(); throw e; } - internalUnlock(); - - return length; + return ret; } -int CAudioInput::peek(const void** buffer, size_t* length) throw (CAudioError) { - if (IsInit() == false || IsReady() == false) { - THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput"); +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"); } if (buffer == NULL || length == NULL) { - THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL buffer:%p, length:%p", buffer, length); + 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::ERROR_INVALID_OPERATION, "Invalid operation of peek() if does not receive a stream callback"); + 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 { - internalLock(); ret = mpPulseAudioClient->peek(buffer, length); - internalUnlock(); } catch (CAudioError e) { - internalUnlock(); throw e; } return ret; } -int CAudioInput::drop() throw (CAudioError) { - if (IsInit() == false || IsReady() == false) { - THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput"); +int CAudioInput::drop() throw(CAudioError) { + 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::ERROR_INVALID_OPERATION, "Invalid operation of drop() if does not receive a stream callback"); + 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 { - internalLock(); ret = mpPulseAudioClient->drop(); - internalUnlock(); } catch (CAudioError e) { - internalUnlock(); throw e; }