Fix build warning
[platform/core/api/audio-io.git] / src / cpp / CAudioIO.cpp
index d543219..0de125b 100644 (file)
@@ -18,6 +18,7 @@
 #include <mm.h>
 #include <pthread.h>
 #include <assert.h>
+#include <glib.h>
 #include "CAudioIODef.h"
 
 using namespace std;
@@ -31,27 +32,33 @@ CAudioIO::CAudioIO() :
     mpAudioSessionHandler(NULL),
     mpPulseAudioClient(NULL),
     __mMutex(PTHREAD_MUTEX_INITIALIZER),
+    __mCondMutex(PTHREAD_MUTEX_INITIALIZER),
     __mCond(PTHREAD_COND_INITIALIZER),
     __mIsInit(false),
     __mForceIgnore(false) {
+    mInterruptCode = IAudioSessionEventListener::EInterruptCode::INTERRUPT_MAX;
     mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX;
     mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
     mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
     mByPolicy = false;
+    mIsInterrupted = false;
 }
 
 CAudioIO::CAudioIO(CAudioInfo& audioInfo) :
     mpAudioSessionHandler(NULL),
     mpPulseAudioClient(NULL),
     __mMutex(PTHREAD_MUTEX_INITIALIZER),
+    __mCondMutex(PTHREAD_MUTEX_INITIALIZER),
     __mCond(PTHREAD_COND_INITIALIZER),
     __mIsInit(false),
     __mForceIgnore(false) {
     mAudioInfo = audioInfo;
+    mInterruptCode = IAudioSessionEventListener::EInterruptCode::INTERRUPT_MAX;
     mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX;
     mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
     mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
     mByPolicy = false;
+    mIsInterrupted = false;
 }
 
 CAudioIO::~CAudioIO() {
@@ -77,8 +84,9 @@ void CAudioIO::internalLock() {
     if (pthread_mutex_lock(&__mMutex) != 0) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()");
     }
+
 #ifdef _AUDIO_IO_DEBUG_TIMING_
-    AUDIO_IO_LOGD(COLOR_RED "LOCK" COLOR_END);
+    AUDIO_IO_LOGD(COLOR_RED "%p LOCKED" COLOR_END, &__mMutex);
 #endif
 }
 
@@ -91,7 +99,7 @@ void CAudioIO::internalUnlock() {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()");
     }
 #ifdef _AUDIO_IO_DEBUG_TIMING_
-    AUDIO_IO_LOGD(COLOR_GREEN "UNLOCK" COLOR_END);
+    AUDIO_IO_LOGD(COLOR_GREEN "%p UNLOCKED" COLOR_END, &__mMutex);
 #endif
 }
 
@@ -104,7 +112,9 @@ void CAudioIO::internalWait() {
     AUDIO_IO_LOGD(COLOR_RED "WAIT" COLOR_END);
 #endif
 
-    pthread_cond_wait(&__mCond, &__mMutex);
+    pthread_mutex_lock(&__mCondMutex);
+    pthread_cond_wait(&__mCond, &__mCondMutex);
+    pthread_mutex_unlock(&__mCondMutex);
 }
 
 void CAudioIO::internalSignal() {
@@ -116,7 +126,9 @@ void CAudioIO::internalSignal() {
     AUDIO_IO_LOGD(COLOR_GREEN "SIGNAL" COLOR_END);
 #endif
 
+    pthread_mutex_lock(&__mCondMutex);
     pthread_cond_signal(&__mCond);
+    pthread_mutex_unlock(&__mCondMutex);
 }
 
 bool CAudioIO::isForceIgnore() {
@@ -150,16 +162,28 @@ void CAudioIO::finalize() {
 
     AUDIO_IO_LOGD("finalize");
 
+    bool error_occured = false;
     int ret = pthread_mutex_destroy(&__mMutex);
     if (ret != 0) {
-        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_mutex_destroy() ret:%d", ret);
+        AUDIO_IO_LOGE("Failed pthread_mutex_destroy(%p) errno:%d", &__mMutex, ret);
+        error_occured = true;
+    }
+    ret = pthread_mutex_destroy(&__mCondMutex);
+    if (ret != 0) {
+        AUDIO_IO_LOGE("Failed pthread_mutex_destroy(%p) errno:%d", &__mCondMutex, ret);
+        error_occured = true;
     }
 
+
     ret = pthread_cond_destroy(&__mCond);
     if (ret != 0) {
-        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_cond_destroy() ret:%d", ret);
+        AUDIO_IO_LOGE("Failed pthread_cond_destroy(%p) errno:%d", &__mCond, ret);
+        error_occured = true;
     }
 
+    if (error_occured)
+        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Finalize Failed");
+
     __mIsInit = false;
 }
 
@@ -210,7 +234,23 @@ CAudioInfo::EAudioIOState CAudioIO::getState() {
     return mState;
 }
 
-void CAudioIO::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) {
+int CAudioIO::sendInterrupt(void* user_data) {
+    CAudioIO *pCaudioIo = (CAudioIO *)user_data;
+
+    if (pCaudioIo && pCaudioIo->mInterruptCallback.onInterrupt) {
+        AUDIO_IO_LOGD("sending interrupt [%d]", static_cast<int>(pCaudioIo->mInterruptCode));
+        pCaudioIo->mInterruptCallback.onInterrupt(pCaudioIo->mInterruptCode, pCaudioIo->mInterruptCallback.mUserData);
+    }
+    return 0;
+}
+
+int caudio_gsource_callback(void *user_data) {
+    CAudioIO::sendInterrupt(user_data);
+    return 0;
+}
+
+void CAudioIO::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);
 
     int session_option = pHandler->getOptions();
@@ -226,30 +266,16 @@ void CAudioIO::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focu
         }
 
         if (state == FOCUS_IS_RELEASED) {
-            // Focus handle(id) of the other application was released, do resume if possible
-            internalLock();
-            if (mpPulseAudioClient) {
-                mpPulseAudioClient->cork(false);
-                onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING);
-            }
-            internalUnlock();
-
+            // Focus handle(id) of the other application was released, notify resume
             // Focus watch callback doesn't have focus handle, but it need to convert & report to application for convenience
             state = FOCUS_IS_ACQUIRED;
         } else if (state == FOCUS_IS_ACQUIRED) {
             // Focus handle(id) of the other application was acquired, do pause if possible
             internalLock();
             if (mpPulseAudioClient) {
-                /* FIXME: Skip this codes due to the blocking of drain() function
-                if (mpPulseAudioClient->getStreamDirection() == CPulseAudioClient::EStreamDirection::STREAM_DIRECTION_PLAYBACK) {
-                    if (mpPulseAudioClient->drain() == false) {
-                        AUDIO_IO_LOGE("Failed CPulseAudioClient::drain()");
-                    }
-                }
-                */
                 mpPulseAudioClient->cork(true);
-                onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED);
             }
+            mIsInterrupted = true;
             internalUnlock();
 
             // Focus watch callback doesn't have focus handle, but it need to convert & report to application for convenience
@@ -273,34 +299,28 @@ void CAudioIO::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focu
             // Focus handle(id) was released, do pause here
             internalLock();
             if (mpPulseAudioClient) {
-                /* FIXME: Skip this codes due to the blocking of drain() function
-                if (mpPulseAudioClient->getStreamDirection() == CPulseAudioClient::EStreamDirection::STREAM_DIRECTION_PLAYBACK) {
-                    if (mpPulseAudioClient->drain() == false) {
-                        AUDIO_IO_LOGE("Failed CPulseAudioClient::drain()");
-                    }
-                }
-                */
                 mpPulseAudioClient->cork(true);
-                onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED);
             }
+
+            mIsInterrupted = true;
             internalUnlock();
         } else if (state == FOCUS_IS_ACQUIRED) {
             // Focus handle(id) was acquired again,
             // check reason_for_change ("call-voice","call-video","voip","alarm","notification", ...)
             // do resume here and call interrupt completed callback to application.
-            internalLock();
-            if (mpPulseAudioClient) {
-                mpPulseAudioClient->cork(false);
-                onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING);
-            }
-            internalUnlock();
         }
     }
 
     if (mInterruptCallback.onInterrupt != NULL) {
         IAudioSessionEventListener::EInterruptCode e = IAudioSessionEventListener::EInterruptCode::INTERRUPT_COMPLETED;
         e = IAudioSessionEventListener::convertInterruptedCode(state, reason_for_change);
-        mInterruptCallback.onInterrupt(e, mInterruptCallback.mUserData);
+
+        if (EInterruptCode::INTERRUPT_COMPLETED == e) {
+            mInterruptCode = e;
+            g_idle_add(caudio_gsource_callback, this);
+        } else {
+            mInterruptCallback.onInterrupt(e, mInterruptCallback.mUserData);
+        }
     }
 }
 
@@ -322,8 +342,27 @@ void CAudioIO::prepare() {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
-
+    if (mDirection == CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN) {
+        AUDIO_IO_LOGD("Prepare for Audio in");
+    } else if (mDirection == CAudioInfo::EAudioDirection::AUDIO_DIRECTION_OUT) {
+        AUDIO_IO_LOGD("Prepare for Audio Out");
+    }
     try {
+        if (mIsInterrupted) {
+            AUDIO_IO_LOGE("This is preparing during interrupted!!!");
+            bool isSkip = mpAudioSessionHandler->isSkipSession();
+            if (__mForceIgnore == false && isSkip == false && mpAudioSessionHandler->getId() >= 0) {
+                AUDIO_IO_LOGE("Session updatePlaying!!!");
+                mpAudioSessionHandler->updatePlaying();
+            }
+
+            if (mpPulseAudioClient && mpPulseAudioClient->isCorked()) {
+                AUDIO_IO_LOGE("Uncork!");
+                mpPulseAudioClient->cork(false);
+            }
+            mIsInterrupted = false;
+        }
+
         AUDIO_IO_LOGD("------> prepare done");
         /* Do nothing */
     } catch (CAudioError& e) {