fixup! Reset dump values when pause function is called
[platform/core/api/audio-io.git] / src / cpp / CPulseAudioClient.cpp
index 34f769a..e18c69e 100644 (file)
@@ -61,20 +61,7 @@ CPulseAudioClient::CPulseAudioClient(
         IPulseStreamListener* listener) :
     __mDirection(direction),
     __mSpec(spec),
-    __mpListener(listener),
-    __mpMainloop(nullptr),
-    __mpContext(nullptr),
-    __mpStream(nullptr),
-    __mpPropList(nullptr),
-    __mIsInit(false),
-    __mIsOperationSuccess(false),
-    __mpSyncReadDataPtr(nullptr),
-    __mSyncReadIndex(0),
-    __mSyncReadLength(0),
-    __mIsUsedSyncRead(false),
-    __mIsFirstStream(false),
-    __mIsDraining(false),
-    __mIsStarted(false) {
+    __mpListener(listener) {
 }
 
 CPulseAudioClient::~CPulseAudioClient() {
@@ -294,17 +281,50 @@ void CPulseAudioClient::__streamEventCb(pa_stream* s, const char* name, pa_propl
 
     AUDIO_IO_LOGW("pClient[%p] pa_stream[%p] : name[%s], proplist[%p]", pClient, s, name, pl);
 
-    if (strcmp(name, PA_STREAM_EVENT_POP_TIMEOUT) == 0) {
-        pa_operation* o = pa_stream_cork(pClient->__mpStream, 1, NULL, NULL);
-        if (!o) {
-            AUDIO_IO_LOGE("pa_stream[%p] : cork failed", pClient->__mpStream);
-            return;
-        }
-        pa_operation_unref(o);
-    }
+    if (strcmp(name, PA_STREAM_EVENT_POP_TIMEOUT) != 0)
+        return;
+
+    if (!pClient->streamCork(true, __successCorkCb, pClient))
+        AUDIO_IO_LOGE("pa_stream[%p] : cork failed", pClient->__mpStream);
 }
 //LCOV_EXCL_STOP
 
+void CPulseAudioClient::notifyCorkStatus() {
+    assert(__mpListener);
+    assert(__mpStream);
+
+    __mpListener->onCorked(this, static_cast<bool>(pa_stream_is_corked(__mpStream)));
+}
+
+void CPulseAudioClient::__successCorkCb(pa_stream* s, int success, void* user_data) {
+    assert(s);
+    assert(user_data);
+
+    auto pClient = static_cast<CPulseAudioClient*>(user_data);
+
+    AUDIO_IO_LOGD("pClient[%p] pa_stream[%p] success[%d] user_data[%p]", pClient, s, success, user_data);
+
+    if (success)
+        pClient->notifyCorkStatus();
+}
+
+void CPulseAudioClient::__successCorkCbSignal(pa_stream* s, int success, void* user_data) {
+    assert(s);
+    assert(user_data);
+
+    auto pClient = static_cast<CPulseAudioClient*>(user_data);
+
+    AUDIO_IO_LOGD("pClient[%p] pa_stream[%p] success[%d] user_data[%p]", pClient, s, success, user_data);
+
+    if (success)
+        pClient->notifyCorkStatus();
+
+    pClient->__mIsOperationSuccess = static_cast<bool>(success);
+
+    /* FIXME : verify following action without any waiting */
+    pa_threaded_mainloop_signal(pClient->__mpMainloop, 0);
+}
+
 void CPulseAudioClient::__successStreamCb(pa_stream* s, int success, void* user_data) {
     assert(s);
     assert(user_data);
@@ -405,21 +425,26 @@ void CPulseAudioClient::initialize() {
             THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pa_proplist_new()"); //LCOV_EXCL_LINE
 
         // Adds values on proplist for delivery to PULSEAUDIO
-        pa_proplist_sets(__mpPropList, PA_PROP_MEDIA_ROLE, __mSpec.getAudioInfo().getConvertedStreamType());
+        auto [ streamType, streamIndex ] = __mSpec.getAudioInfo().getStreamProperties();
 
-        int index = __mSpec.getAudioInfo().getAudioIndex();
-        if (index >= 0)
-            pa_proplist_setf(__mpPropList, PA_PROP_MEDIA_PARENT_ID, "%u", (unsigned int) index);
+        pa_proplist_sets(__mpPropList, PA_PROP_MEDIA_ROLE, streamType);
+        if (streamIndex >= 0)
+            pa_proplist_setf(__mpPropList, PA_PROP_MEDIA_PARENT_ID, "%d", streamIndex);
 
         if (__mDirection == EStreamDirection::STREAM_DIRECTION_RECORD) {
-            int reference_id = __mSpec.getAudioInfo().getEchoCancelReferenceDeviceId();
-            if (reference_id > 0) {
-                pa_proplist_setf(__mpPropList, PA_PROP_MEDIA_ECHO_CANCEL_REFERENCE_DEVICE, "%d", reference_id);
-            }
+            /* Noise-suppression effect should be set first. */
+            std::string ns_method = __mSpec.getAudioInfo().getEffectNoiseSuppressionMethod();
+            auto [ method_reference, device_id ] = __mSpec.getAudioInfo().getEffectMethodWithReference();
+            std::string agc_method = __mSpec.getAudioInfo().getEffectAutomaticGainControlMethod();
 
-            if (!__mSpec.getAudioInfo().getProcessorProperty().empty())
-                pa_proplist_setf(__mpPropList, PA_PROP_MEDIA_PREPROCESSOR_METHOD, "%s",
-                                    __mSpec.getAudioInfo().getProcessorProperty().c_str());
+            std::string method_all = ns_method + method_reference + agc_method;
+
+            if (!method_all.empty()) {
+                pa_proplist_setf(__mpPropList, PA_PROP_MEDIA_PREPROCESSOR_METHOD, "%s", method_all.c_str());
+                pa_proplist_setf(__mpPropList, PA_PROP_MEDIA_ECHO_CANCEL_REFERENCE_DEVICE, "%d", device_id);
+
+                AUDIO_IO_LOGD("preprocess will be set. method[%s], device_id[%d]", method_all.c_str(), device_id);
+            }
         }
 
         // Adds latency on proplist for delivery to PULSEAUDIO
@@ -755,11 +780,8 @@ int CPulseAudioClient::write(const void* data, size_t length) {
         CPulseThreadLocker locker{__mpMainloop};
         if (pa_stream_is_corked(__mpStream)) {
             AUDIO_IO_LOGW("pa_stream[%p] is corked...do uncork here first!!!!", __mpStream);
-            pa_operation* o = pa_stream_cork(__mpStream, 0, NULL, NULL);
-            if (!o)
+            if (!streamCork(false, __successCorkCb, this))
                 AUDIO_IO_LOGE("pa_stream[%p] : uncork failed", __mpStream);
-            else
-                pa_operation_unref(o);
         }
 
         ret = pa_stream_write(__mpStream, data, length, NULL, 0LL, PA_SEEK_RELATIVE);
@@ -767,11 +789,9 @@ int CPulseAudioClient::write(const void* data, size_t length) {
 // LCOV_EXCL_START
         if (pa_stream_is_corked(__mpStream)) {
             AUDIO_IO_LOGW("pa_stream[%p] is corked...do uncork here first!!!!", __mpStream);
-            pa_operation* o = pa_stream_cork(__mpStream, 0, NULL, NULL);
-            if (!o)
+
+            if (!streamCork(false, __successCorkCb, this))
                 AUDIO_IO_LOGE("pa_stream[%p] : uncork failed", __mpStream);
-            else
-                pa_operation_unref(o);
         }
 
         if (__mIsFirstStream) {
@@ -796,6 +816,15 @@ int CPulseAudioClient::write(const void* data, size_t length) {
     return ret;
 }
 
+bool CPulseAudioClient::streamCork(bool cork, pa_stream_success_cb_t cb, void* user_data) {
+    pa_operation* o = pa_stream_cork(__mpStream, static_cast<int>(cork), cb, user_data);
+    if (!o)
+        return false;
+    pa_operation_unref(o);
+
+    return true;
+}
+
 void CPulseAudioClient::cork(bool cork) {
     AUDIO_IO_LOGD("cork[%d]", cork);
 
@@ -814,13 +843,15 @@ void CPulseAudioClient::cork(bool cork) {
     CPulseThreadLocker locker{__mpMainloop};
 
     /* FIXME: wait for completion like drain? */
-    pa_operation* o = pa_stream_cork(__mpStream, static_cast<int>(cork), __successStreamCb, this);
-    if (!o) {
+    if (!streamCork(cork, __successCorkCbSignal, this)) {
         AUDIO_IO_LOGE("pa_stream[%p] : cork[%d] failed", __mpStream, cork);
         return;
     }
-    pa_operation_unref(o);
-    AUDIO_IO_LOGD("cork[%d] done", cork);
+
+    AUDIO_IO_LOGD("cork[%d] requested, is-stream-started[%d]", cork, __mIsStarted);
+
+    /* FIXME: need to consider manual pa_stream_trigger() when uncorking but stream is not started yet,
+              because even uncorked here, it is still prebuf state so, empty-pop will not be checked in this situation */
 }
 
 bool CPulseAudioClient::isCorked() {