[ACR-1664] Add new enum for channel type (up-to 16 channels for recording)
[platform/core/api/audio-io.git] / src / cpp / cpp_audio_io.cpp
index 77c8f4f..86fbf78 100644 (file)
@@ -22,6 +22,7 @@
 #include "CAudioIODef.h"
 
 #include <system_info.h>
+#include <cassert>
 
 #define FEATURE_MICROPHONE          "http://tizen.org/feature/microphone"
 
@@ -96,8 +97,8 @@ typedef struct audio_io_s {
 /**
  * Internal functions
  */
-static audio_io_error_e __convert_CAudioError(CAudioError& error) {
-    switch (error.getError()) {
+static audio_io_error_e __convert_audio_io_error(CAudioError::EError error) {
+    switch (error) {
     case CAudioError::EError::ERROR_NONE:
         return AUDIO_IO_ERROR_NONE;
     case CAudioError::EError::ERROR_INVALID_ARGUMENT:
@@ -136,83 +137,35 @@ static audio_io_error_e __convert_CAudioError(CAudioError& error) {
 }
 
 static CAudioInfo::EChannel __convert_channel_to_audio_info_channel(const audio_channel_e &src_channel) {
-    switch (src_channel) {
-    case AUDIO_CHANNEL_MONO:
-        return CAudioInfo::EChannel::CHANNEL_MONO;
-    case AUDIO_CHANNEL_STEREO:
-        return CAudioInfo::EChannel::CHANNEL_STEREO;
-    case AUDIO_CHANNEL_MULTI_3:
-        return CAudioInfo::EChannel::CHANNEL_MULTI_3;
-    case AUDIO_CHANNEL_MULTI_4:
-        return CAudioInfo::EChannel::CHANNEL_MULTI_4;
-    case AUDIO_CHANNEL_MULTI_5:
-        return CAudioInfo::EChannel::CHANNEL_MULTI_5;
-    case AUDIO_CHANNEL_MULTI_6:
-        return CAudioInfo::EChannel::CHANNEL_MULTI_6;
-    case AUDIO_CHANNEL_MULTI_7:
-        return CAudioInfo::EChannel::CHANNEL_MULTI_7;
-    case AUDIO_CHANNEL_MULTI_8:
-        return CAudioInfo::EChannel::CHANNEL_MULTI_8;
-    default:
-        return CAudioInfo::EChannel::CHANNEL_MONO;
-    }
+    if (src_channel < AUDIO_CHANNEL_MONO ||
+        src_channel > AUDIO_CHANNEL_MULTI_16)
+        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid src_channel:%d", src_channel);
+
+    return static_cast<CAudioInfo::EChannel>(src_channel - AUDIO_CHANNEL_MONO + 1);
 }
 
 static audio_channel_e __convert_audio_info_channel_to_channel(const CAudioInfo::EChannel& src_channel) {
-    switch (src_channel) {
-    case CAudioInfo::EChannel::CHANNEL_MONO:
-        return AUDIO_CHANNEL_MONO;
-    case CAudioInfo::EChannel::CHANNEL_STEREO:
-        return AUDIO_CHANNEL_STEREO;
-    case CAudioInfo::EChannel::CHANNEL_MULTI_3:
-        return AUDIO_CHANNEL_MULTI_3;
-    case CAudioInfo::EChannel::CHANNEL_MULTI_4:
-        return AUDIO_CHANNEL_MULTI_4;
-    case CAudioInfo::EChannel::CHANNEL_MULTI_5:
-        return AUDIO_CHANNEL_MULTI_5;
-    case CAudioInfo::EChannel::CHANNEL_MULTI_6:
-        return AUDIO_CHANNEL_MULTI_6;
-    case CAudioInfo::EChannel::CHANNEL_MULTI_7:
-        return AUDIO_CHANNEL_MULTI_7;
-    case CAudioInfo::EChannel::CHANNEL_MULTI_8:
-        return AUDIO_CHANNEL_MULTI_8;
-    default:
-        return AUDIO_CHANNEL_MONO;
-    }
+    if (src_channel < CAudioInfo::EChannel::CHANNEL_MONO ||
+        src_channel >= CAudioInfo::EChannel::CHANNEL_MAX)
+        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid src_channel:%d", static_cast<int>(src_channel));
+
+    return static_cast<audio_channel_e>(static_cast<int>(src_channel) + AUDIO_CHANNEL_MONO - 1);
 }
 
 static CAudioInfo::ESampleType __convert_sample_type_to_audio_info_sample_type(const audio_sample_type_e& src_type) {
-    switch (src_type) {
-    case AUDIO_SAMPLE_TYPE_U8:
-        return CAudioInfo::ESampleType::SAMPLE_TYPE_U8;
-    case AUDIO_SAMPLE_TYPE_S16_LE:
-        return CAudioInfo::ESampleType::SAMPLE_TYPE_S16_LE;
-    case AUDIO_SAMPLE_TYPE_S24_LE:
-        return CAudioInfo::ESampleType::SAMPLE_TYPE_S24_LE;
-    case AUDIO_SAMPLE_TYPE_S24_32_LE:
-        return CAudioInfo::ESampleType::SAMPLE_TYPE_S24_32_LE;
-    case AUDIO_SAMPLE_TYPE_S32_LE:
-        return CAudioInfo::ESampleType::SAMPLE_TYPE_S32_LE;
-    default:
-        return CAudioInfo::ESampleType::SAMPLE_TYPE_U8;
-    }
+    if (src_type < AUDIO_SAMPLE_TYPE_U8 ||
+        src_type > AUDIO_SAMPLE_TYPE_S32_LE)
+        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid src_type:%d", src_type);
+
+    return static_cast<CAudioInfo::ESampleType>(static_cast<int>(src_type) - AUDIO_SAMPLE_TYPE_U8 + 1);
 }
 
 static audio_sample_type_e __convert_audio_info_sample_type_to_sample_type(const CAudioInfo::ESampleType &src_type) {
-    switch (src_type) {
-    case CAudioInfo::ESampleType::SAMPLE_TYPE_U8:
-        return AUDIO_SAMPLE_TYPE_U8;
-    case CAudioInfo::ESampleType::SAMPLE_TYPE_S16_LE:
-        return AUDIO_SAMPLE_TYPE_S16_LE;
-    case CAudioInfo::ESampleType::SAMPLE_TYPE_S24_LE:
-        return AUDIO_SAMPLE_TYPE_S24_LE;
-    case CAudioInfo::ESampleType::SAMPLE_TYPE_S24_32_LE:
-        return AUDIO_SAMPLE_TYPE_S24_32_LE;
-    case CAudioInfo::ESampleType::SAMPLE_TYPE_S32_LE:
-        return AUDIO_SAMPLE_TYPE_S32_LE;
-    default:
-        return AUDIO_SAMPLE_TYPE_U8;
-    }
+    if (src_type < CAudioInfo::ESampleType::SAMPLE_TYPE_U8 ||
+        src_type >= CAudioInfo::ESampleType::SAMPLE_TYPE_MAX)
+        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid src_type:%d", static_cast<int>(src_type));
+
+    return static_cast<audio_sample_type_e>(static_cast<int>(src_type) + AUDIO_SAMPLE_TYPE_U8 - 1);
 }
 
 static  CAudioInfo::EAudioType __convert_sound_type_to_audio_info_audio_type(const sound_type_e &src_type) {
@@ -276,17 +229,17 @@ static audio_io_state_e __convert_state_type(const CAudioInfo::EAudioIOState src
 }
 
 static void __check_audio_param(int sample_rate, audio_channel_e channel, audio_sample_type_e type, bool is_output) {
-    if (sample_rate < static_cast<int>(CAudioInfo::MIN_SYSTEM_SAMPLERATE) ||
-        sample_rate > static_cast<int>(CAudioInfo::MAX_SYSTEM_SAMPLERATE))
+    if (sample_rate < CAudioInfo::MIN_SYSTEM_SAMPLERATE ||
+        sample_rate > CAudioInfo::MAX_SYSTEM_SAMPLERATE)
         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid sample rate :%d", sample_rate);
 
     if (channel < AUDIO_CHANNEL_MONO ||
-        channel > ((is_output) ? AUDIO_CHANNEL_STEREO : AUDIO_CHANNEL_MULTI_8))
+        channel > ((is_output) ? AUDIO_CHANNEL_STEREO : AUDIO_CHANNEL_MULTI_16))
         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid channel :%d", channel);
 
     if (type < AUDIO_SAMPLE_TYPE_U8 ||
         type > AUDIO_SAMPLE_TYPE_S32_LE)
-        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid sample type :%d", type);
+        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid sample type :0x%x", type);
 }
 
 static CAudioInfo __generate_audio_input_info(int sampleRate, audio_channel_e channel, audio_sample_type_e sample_type) {
@@ -350,15 +303,15 @@ int cpp_audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_t
 
         AUDIO_IO_LOGD("[%p] created", handle);
         *input = handle;
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
         __handle_safe_free(handle, (void *)input, false);
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     } catch (const std::bad_alloc&) {
-        CAudioError e(CAudioError::EError::ERROR_OUT_OF_MEMORY);
+//LCOV_EXCL_START
         AUDIO_IO_LOGE("Failed to allocate handle");
         __handle_safe_free(handle, (void *)input, false);
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(CAudioError::EError::ERROR_OUT_OF_MEMORY);
 //LCOV_EXCL_STOP
     }
 
@@ -373,17 +326,19 @@ int cpp_audio_in_destroy(audio_in_h input) {
             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
                                   "Parameters are NULL input:%p", input);
         assert(handle->audioIoHandle);
-        AUDIO_IO_LOGD("[%p]", handle);
+        AUDIO_IO_LOGD("unpreparing [%p]", handle);
 
         /* Internal unprepare for backward compatibility */
         handle->audioIoHandle->unprepare();
 
+        AUDIO_IO_LOGD("try to destroy [%p]", handle);
+
         SAFE_FINALIZE(handle->audioIoHandle);
         SAFE_DELETE(handle->audioIoHandle);
         SAFE_DELETE(handle);
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("destroyed");
@@ -402,9 +357,9 @@ int cpp_audio_in_set_sound_stream_info(audio_in_h input, sound_stream_info_h str
         AUDIO_IO_LOGD("[%p], stream_info:[%p]", handle, stream_info);
 
         handle->audioIoHandle->setStreamInfo(stream_info);
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] done", handle);
@@ -423,9 +378,9 @@ int cpp_audio_in_prepare(audio_in_h input) {
         AUDIO_IO_LOGD("[%p]", handle);
 
         handle->audioIoHandle->prepare();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] prepared", handle);
@@ -444,9 +399,9 @@ int cpp_audio_in_unprepare(audio_in_h input) {
         AUDIO_IO_LOGD("[%p]", handle);
 
         handle->audioIoHandle->unprepare();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] unprepared", handle);
@@ -465,9 +420,9 @@ int cpp_audio_in_pause(audio_in_h input) {
         AUDIO_IO_LOGD("[%p]", handle);
 
         handle->audioIoHandle->pause();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] paused", handle);
@@ -486,9 +441,9 @@ int cpp_audio_in_resume(audio_in_h input) {
         AUDIO_IO_LOGD("[%p]", handle);
 
         handle->audioIoHandle->resume();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] resumed", handle);
@@ -507,9 +462,9 @@ int cpp_audio_in_flush(audio_in_h input) {
         AUDIO_IO_LOGD("[%p]", handle);
 
         handle->audioIoHandle->flush();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] flushed", handle);
@@ -536,9 +491,9 @@ int cpp_audio_in_read(audio_in_h input, void *buffer, unsigned int length) {
 #ifdef _AUDIO_IO_DEBUG_TIMING_
         AUDIO_IO_LOGD("readn:%zu", readn);
 #endif
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     return ret;
@@ -557,9 +512,9 @@ int cpp_audio_in_get_buffer_size(audio_in_h input, int *size) {
             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
 
         *size = inputHandle->getBufferSize();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     return AUDIO_IO_ERROR_NONE;
@@ -574,9 +529,9 @@ int cpp_audio_in_get_sample_rate(audio_in_h input, int *sample_rate) {
         assert(handle->audioIoHandle);
 
         *sample_rate = handle->audioIoHandle->getAudioInfo().getSampleRate();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     return AUDIO_IO_ERROR_NONE;
@@ -591,9 +546,9 @@ int cpp_audio_in_get_channel(audio_in_h input, audio_channel_e *channel) {
         assert(handle->audioIoHandle);
 
         *channel = __convert_audio_info_channel_to_channel(handle->audioIoHandle->getAudioInfo().getChannel());
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     return AUDIO_IO_ERROR_NONE;
@@ -608,9 +563,9 @@ int cpp_audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type) {
         assert(handle->audioIoHandle);
 
         *type = __convert_audio_info_sample_type_to_sample_type(handle->audioIoHandle->getAudioInfo().getSampleType());
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     return AUDIO_IO_ERROR_NONE;
@@ -655,9 +610,9 @@ int cpp_audio_in_set_stream_cb(audio_in_h input, audio_in_stream_cb callback, vo
         cb.set(__stream_cb_internal, static_cast<void*>(handle));
 
         handle->audioIoHandle->setStreamCallback(cb);
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] done", handle);
@@ -680,9 +635,9 @@ int cpp_audio_in_unset_stream_cb(audio_in_h input) {
         cb.unset();
 
         handle->audioIoHandle->setStreamCallback(cb);
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] done", handle);
@@ -701,12 +656,12 @@ int cpp_audio_in_peek(audio_in_h input, const void **buffer, unsigned int *lengt
 
         auto inputHandle = static_cast<CAudioInput*>(handle->audioIoHandle);
         if (!inputHandle)
-            THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
+            THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL"); // LCOV_EXCL_LINE
 
         inputHandle->peek(buffer, &_length);
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     *length = (unsigned int)_length;
@@ -723,12 +678,12 @@ int cpp_audio_in_drop(audio_in_h input) {
 
         auto inputHandle = static_cast<CAudioInput*>(handle->audioIoHandle);
         if (!inputHandle)
-            THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
+            THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL"); // LCOV_EXCL_LINE
 
         inputHandle->drop();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     return AUDIO_IO_ERROR_NONE;
@@ -750,9 +705,9 @@ int cpp_audio_in_set_state_changed_cb(audio_in_h input, audio_in_state_changed_c
         cb.set(__state_changed_cb_internal, static_cast<void*>(handle));
 
         handle->audioIoHandle->setStateChangedCallback(cb);
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] done", handle);
@@ -766,7 +721,7 @@ int cpp_audio_in_unset_state_changed_cb(audio_in_h input) {
     try {
         if (!handle)
             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
-                                   "Parameters are NULL output:%p", input);
+                                   "Parameters are NULL input:%p", input);
         assert(handle->audioIoHandle);
         AUDIO_IO_LOGD("[%p]", handle);
 
@@ -776,9 +731,34 @@ int cpp_audio_in_unset_state_changed_cb(audio_in_h input) {
         cb.unset();
 
         handle->audioIoHandle->setStateChangedCallback(cb);
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return __convert_audio_io_error(e.getError());
+    }
+
+    AUDIO_IO_LOGD("[%p] done", handle);
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_get_volume(audio_in_h input, double *volume) {
+    auto handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (!handle || !volume)
+            THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
+                                   "Parameters are NULL input:%p, volume:%p", input, volume);
+        assert(handle->audioIoHandle);
+        AUDIO_IO_LOGD("[%p]", handle);
+
+        auto input_handle = dynamic_cast<CAudioInput*>(handle->audioIoHandle);
+        if (input_handle == nullptr)
+            return __convert_audio_io_error(CAudioError::EError::ERROR_INVALID_HANDLE);
+
+        *volume = input_handle->getVolume();
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] done", handle);
@@ -786,6 +766,34 @@ int cpp_audio_in_unset_state_changed_cb(audio_in_h input) {
     return AUDIO_IO_ERROR_NONE;
 }
 
+int cpp_audio_in_set_volume(audio_in_h input, double volume) {
+    auto handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (!handle)
+            THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
+                                   "Parameters are NULL input:%p", input);
+
+        if (volume < CAudioInfo::MIN_RECORD_VOLUME || volume > CAudioInfo::MAX_RECORD_VOLUME)
+            THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid volume: %f", volume);
+
+        assert(handle->audioIoHandle);
+        AUDIO_IO_LOGD("[%p]", handle);
+
+        auto input_handle = dynamic_cast<CAudioInput*>(handle->audioIoHandle);
+        if (input_handle == nullptr)
+            return __convert_audio_io_error(CAudioError::EError::ERROR_INVALID_HANDLE);
+
+        input_handle->setVolume(volume);
+    } catch (const CAudioError& e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return __convert_audio_io_error(e.getError());
+    }
+
+    AUDIO_IO_LOGD("[%p] done", handle);
+
+    return AUDIO_IO_ERROR_NONE;
+}
 
 /**
  * Audio Out
@@ -808,15 +816,15 @@ int cpp_audio_out_create_new(int sample_rate, audio_channel_e channel, audio_sam
 
         AUDIO_IO_LOGD("[%p] created", handle);
         *output = handle;
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
         __handle_safe_free(handle, (void *)output, true);
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     } catch (const std::bad_alloc&) {
-        CAudioError e(CAudioError::EError::ERROR_OUT_OF_MEMORY);
+//LCOV_EXCL_START
         AUDIO_IO_LOGE("Failed to allocate handle");
         __handle_safe_free(handle, (void *)output, true);
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(CAudioError::EError::ERROR_OUT_OF_MEMORY);
 //LCOV_EXCL_STOP
     }
 
@@ -831,20 +839,22 @@ int cpp_audio_out_destroy(audio_out_h output) {
             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
                                    "Parameter is NULL output:%p", output);
         assert(handle->audioIoHandle);
-        AUDIO_IO_LOGD("[%p]", handle);
+        AUDIO_IO_LOGD("unpreparing [%p]", handle);
 
         /* Internal unprepare for backward compatibility */
         handle->audioIoHandle->unprepare();
 
+        AUDIO_IO_LOGD("try to destroy [%p]", handle);
+
         SAFE_FINALIZE(handle->audioIoHandle);
         SAFE_DELETE(handle->audioIoHandle);
         SAFE_DELETE(handle);
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
-    AUDIO_IO_LOGD("[%p] destroyed", handle);
+    AUDIO_IO_LOGD("destroyed");
 
     return AUDIO_IO_ERROR_NONE;
 }
@@ -860,9 +870,9 @@ int cpp_audio_out_set_sound_stream_info(audio_out_h output, sound_stream_info_h
         AUDIO_IO_LOGD("[%p], stream_info:[%p]", handle, stream_info);
 
         handle->audioIoHandle->setStreamInfo(stream_info);
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] done", handle);
@@ -881,9 +891,9 @@ int cpp_audio_out_prepare(audio_out_h output) {
         AUDIO_IO_LOGD("[%p]", handle);
 
         handle->audioIoHandle->prepare();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] prepared", handle);
@@ -902,9 +912,9 @@ int cpp_audio_out_unprepare(audio_out_h output) {
         AUDIO_IO_LOGD("[%p]", handle);
 
         handle->audioIoHandle->unprepare();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] unprepared", handle);
@@ -923,9 +933,9 @@ int cpp_audio_out_pause(audio_out_h output) {
         AUDIO_IO_LOGD("[%p]", handle);
 
         handle->audioIoHandle->pause();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] paused", handle);
@@ -944,9 +954,9 @@ int cpp_audio_out_resume(audio_out_h output) {
         AUDIO_IO_LOGD("[%p]", handle);
 
         handle->audioIoHandle->resume();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] resumed", handle);
@@ -964,10 +974,14 @@ int cpp_audio_out_drain(audio_out_h output) {
         assert(handle->audioIoHandle);
         AUDIO_IO_LOGD("[%p]", handle);
 
-        handle->audioIoHandle->drain();
-    } catch (CAudioError& e) {
+        auto output_handle = dynamic_cast<CAudioOutput*>(handle->audioIoHandle);
+        if (output_handle == nullptr)
+            return __convert_audio_io_error(CAudioError::EError::ERROR_INVALID_HANDLE);
+
+        output_handle->drain();
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] drained", handle);
@@ -986,9 +1000,9 @@ int cpp_audio_out_flush(audio_out_h output) {
         AUDIO_IO_LOGD("[%p]", handle);
 
         handle->audioIoHandle->flush();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] flushed", handle);
@@ -1015,9 +1029,9 @@ int cpp_audio_out_write(audio_out_h output, void *buffer, unsigned int length) {
 #ifdef _AUDIO_IO_DEBUG_TIMING_
         AUDIO_IO_LOGD("written:%zu", written);
 #endif
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     return ret;
@@ -1036,9 +1050,9 @@ int cpp_audio_out_get_buffer_size(audio_out_h output, int *size) {
             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
 
         *size = outputHandle->getBufferSize();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     return AUDIO_IO_ERROR_NONE;
@@ -1053,9 +1067,9 @@ int cpp_audio_out_get_sample_rate(audio_out_h output, int *sample_rate) {
         assert(handle->audioIoHandle);
 
         *sample_rate = handle->audioIoHandle->getAudioInfo().getSampleRate();
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     return AUDIO_IO_ERROR_NONE;
@@ -1070,9 +1084,9 @@ int cpp_audio_out_get_channel(audio_out_h output, audio_channel_e *channel) {
         assert(handle->audioIoHandle);
 
         *channel = __convert_audio_info_channel_to_channel(handle->audioIoHandle->getAudioInfo().getChannel());
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     return AUDIO_IO_ERROR_NONE;
@@ -1087,9 +1101,9 @@ int cpp_audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type)
         assert(handle->audioIoHandle);
 
         *type = __convert_audio_info_sample_type_to_sample_type(handle->audioIoHandle->getAudioInfo().getSampleType());
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     return AUDIO_IO_ERROR_NONE;
@@ -1105,9 +1119,9 @@ int cpp_audio_out_get_sound_type(audio_out_h output, sound_type_e *type) {
         assert(handle->audioIoHandle);
 
         *type = __convert_audio_info_audio_type_to_sound_type(handle->audioIoHandle->getAudioInfo().getAudioType());
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     return AUDIO_IO_ERROR_NONE;
@@ -1129,9 +1143,9 @@ int cpp_audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback
         cb.set(__stream_cb_internal, static_cast<void*>(handle));
 
         handle->audioIoHandle->setStreamCallback(cb);
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] done", handle);
@@ -1155,9 +1169,9 @@ int cpp_audio_out_unset_stream_cb(audio_out_h output) {
         cb.unset();
 
         handle->audioIoHandle->setStreamCallback(cb);
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] done", handle);
@@ -1181,9 +1195,9 @@ int cpp_audio_out_set_state_changed_cb(audio_out_h output, audio_in_state_change
         cb.set(__state_changed_cb_internal, static_cast<void*>(handle));
 
         handle->audioIoHandle->setStateChangedCallback(cb);
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] done", handle);
@@ -1207,9 +1221,9 @@ int cpp_audio_out_unset_state_changed_cb(audio_out_h output) {
         cb.unset();
 
         handle->audioIoHandle->setStateChangedCallback(cb);
-    } catch (CAudioError& e) {
+    } catch (const CAudioError& e) {
         AUDIO_IO_LOGE("%s", e.getErrorMsg());
-        return __convert_CAudioError(e);
+        return __convert_audio_io_error(e.getError());
     }
 
     AUDIO_IO_LOGD("[%p] done", handle);