[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
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #include <new>
19
20 #include "cpp_audio_io.h"
21 #include "audio_io.h"
22 #include "CAudioIODef.h"
23
24 #include <system_info.h>
25 #include <cassert>
26
27 #define FEATURE_MICROPHONE          "http://tizen.org/feature/microphone"
28
29 using namespace std;
30 using namespace tizen_media_audio;
31
32 /**
33  * Defines Structures
34  * type : struct
35  * Name : audio_io_stream_cb_s
36  * Declaration : Keeps user callback pointer and user data for delivering an stream event
37  */
38 typedef struct audio_io_stream_cb_s {
39     void* user_data;
40     audio_in_stream_cb onStream;
41
42     audio_io_stream_cb_s() : user_data(nullptr), onStream(nullptr) { }
43
44     void set(audio_in_stream_cb callback, void* userdata) {
45         onStream = callback;
46         user_data = userdata;
47     }
48
49     void unset() {
50         onStream = nullptr;
51         user_data = nullptr;
52     }
53 }   audio_io_stream_cb_s;
54
55 /**
56  * Defines Structures
57  * type : struct
58  * Name : audio_io_state_changed_cb_s
59  * Declaration : Keeps user callback pointer and user data for delivering an state changed event
60  */
61 typedef struct audio_io_state_changed_cb_s {
62     void* user_data;
63     audio_in_state_changed_cb onStateChanged;
64
65     audio_io_state_changed_cb_s() : user_data(nullptr), onStateChanged(nullptr) { }
66
67     void set(audio_in_state_changed_cb callback, void* userdata) {
68         onStateChanged = callback;
69         user_data = userdata;
70     }
71
72     void unset() {
73         onStateChanged = nullptr;
74         user_data = nullptr;
75     }
76
77 }   audio_io_state_changed_cb_s;
78
79 /**
80  * Defines Structures
81  * type : struct
82  * Name : audio_io_s
83  * Declaration : An handle of AudioIO
84  * The handle has two struct for user callback
85  * And the handle has a pointer of private audioIO object
86  * The CAudioIO is a abstract class object about Input and Output
87  */
88 typedef struct audio_io_s {
89     CAudioIO* audioIoHandle;
90     audio_io_stream_cb_s stream_callback;
91     audio_io_state_changed_cb_s state_changed_callback;
92
93     audio_io_s() : audioIoHandle(nullptr) { }
94 }   audio_io_s;
95
96
97 /**
98  * Internal functions
99  */
100 static audio_io_error_e __convert_audio_io_error(CAudioError::EError error) {
101     switch (error) {
102     case CAudioError::EError::ERROR_NONE:
103         return AUDIO_IO_ERROR_NONE;
104     case CAudioError::EError::ERROR_INVALID_ARGUMENT:
105     case CAudioError::EError::ERROR_INVALID_HANDLE:
106         return AUDIO_IO_ERROR_INVALID_PARAMETER;
107     case CAudioError::EError::ERROR_DEVICE_NOT_OPENED:
108         return AUDIO_IO_ERROR_DEVICE_NOT_OPENED;
109     case CAudioError::EError::ERROR_DEVICE_NOT_CLOSED:
110         return AUDIO_IO_ERROR_DEVICE_NOT_CLOSED;
111     case CAudioError::EError::ERROR_PERMISSION_DENIED:
112         return AUDIO_IO_ERROR_PERMISSION_DENIED;
113     case CAudioError::EError::ERROR_DEVICE_POLICY_RESTRICTION:
114         return AUDIO_IO_ERROR_DEVICE_POLICY_RESTRICTION;
115     case CAudioError::EError::ERROR_NOT_SUPPORTED:
116         return AUDIO_IO_ERROR_NOT_SUPPORTED;
117     case CAudioError::EError::ERROR_NOT_SUPPORTED_TYPE:
118         return AUDIO_IO_ERROR_NOT_SUPPORTED_TYPE;
119     case CAudioError::EError::ERROR_MAX:
120     case CAudioError::EError::ERROR_INTERNAL_OPERATION:
121     case CAudioError::EError::ERROR_NOT_INITIALIZED:
122     case CAudioError::EError::ERROR_FAILED_OPERATION:
123     case CAudioError::EError::ERROR_INVALID_OPERATION:
124         return AUDIO_IO_ERROR_INVALID_OPERATION;
125     case CAudioError::EError::ERROR_INVALID_STATE:
126         return AUDIO_IO_ERROR_INVALID_STATE;
127     case CAudioError::EError::ERROR_OUT_OF_MEMORY:
128     case CAudioError::EError::ERROR_INVALID_POINTER:
129         return AUDIO_IO_ERROR_INVALID_BUFFER;
130     case CAudioError::EError::ERROR_POLICY_BLOCKED:
131     case CAudioError::EError::ERROR_POLICY_INTERRUPTED:
132     case CAudioError::EError::ERROR_POLICY_DUPLICATED:
133         return AUDIO_IO_ERROR_SOUND_POLICY;
134     default:
135         return AUDIO_IO_ERROR_NONE;
136     }
137 }
138
139 static CAudioInfo::EChannel __convert_channel_to_audio_info_channel(const audio_channel_e &src_channel) {
140     if (src_channel < AUDIO_CHANNEL_MONO ||
141         src_channel > AUDIO_CHANNEL_MULTI_16)
142         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid src_channel:%d", src_channel);
143
144     return static_cast<CAudioInfo::EChannel>(src_channel - AUDIO_CHANNEL_MONO + 1);
145 }
146
147 static audio_channel_e __convert_audio_info_channel_to_channel(const CAudioInfo::EChannel& src_channel) {
148     if (src_channel < CAudioInfo::EChannel::CHANNEL_MONO ||
149         src_channel >= CAudioInfo::EChannel::CHANNEL_MAX)
150         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid src_channel:%d", static_cast<int>(src_channel));
151
152     return static_cast<audio_channel_e>(static_cast<int>(src_channel) + AUDIO_CHANNEL_MONO - 1);
153 }
154
155 static CAudioInfo::ESampleType __convert_sample_type_to_audio_info_sample_type(const audio_sample_type_e& src_type) {
156     if (src_type < AUDIO_SAMPLE_TYPE_U8 ||
157         src_type > AUDIO_SAMPLE_TYPE_S32_LE)
158         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid src_type:%d", src_type);
159
160     return static_cast<CAudioInfo::ESampleType>(static_cast<int>(src_type) - AUDIO_SAMPLE_TYPE_U8 + 1);
161 }
162
163 static audio_sample_type_e __convert_audio_info_sample_type_to_sample_type(const CAudioInfo::ESampleType &src_type) {
164     if (src_type < CAudioInfo::ESampleType::SAMPLE_TYPE_U8 ||
165         src_type >= CAudioInfo::ESampleType::SAMPLE_TYPE_MAX)
166         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid src_type:%d", static_cast<int>(src_type));
167
168     return static_cast<audio_sample_type_e>(static_cast<int>(src_type) + AUDIO_SAMPLE_TYPE_U8 - 1);
169 }
170
171 static  CAudioInfo::EAudioType __convert_sound_type_to_audio_info_audio_type(const sound_type_e &src_type) {
172     switch (src_type) {
173     case SOUND_TYPE_SYSTEM:
174         return CAudioInfo::EAudioType::AUDIO_OUT_TYPE_SYSTEM;
175     case SOUND_TYPE_NOTIFICATION:
176         return CAudioInfo::EAudioType::AUDIO_OUT_TYPE_NOTIFICATION;
177     case SOUND_TYPE_ALARM:
178         return CAudioInfo::EAudioType::AUDIO_OUT_TYPE_ALARM;
179     case SOUND_TYPE_RINGTONE:
180         return CAudioInfo::EAudioType::AUDIO_OUT_TYPE_RINGTONE_VOIP;
181     case SOUND_TYPE_MEDIA:
182         return CAudioInfo::EAudioType::AUDIO_OUT_TYPE_MEDIA;
183     case SOUND_TYPE_CALL:
184         return CAudioInfo::EAudioType::AUDIO_OUT_TYPE_SYSTEM;
185     case SOUND_TYPE_VOIP:
186         return CAudioInfo::EAudioType::AUDIO_OUT_TYPE_VOIP;
187     case SOUND_TYPE_VOICE:
188         return CAudioInfo::EAudioType::AUDIO_OUT_TYPE_VOICE_INFORMATION;
189     default:
190         return CAudioInfo::EAudioType::AUDIO_OUT_TYPE_MEDIA;
191     }
192 }
193
194 static sound_type_e __convert_audio_info_audio_type_to_sound_type(const CAudioInfo::EAudioType &src_type) {
195     switch (src_type) {
196     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_MEDIA:
197         return SOUND_TYPE_MEDIA;
198     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_SYSTEM:
199         return SOUND_TYPE_SYSTEM;
200     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_ALARM:
201         return SOUND_TYPE_ALARM;
202     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_NOTIFICATION:
203     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_EMERGENCY:
204         return SOUND_TYPE_NOTIFICATION;
205     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_VOICE_INFORMATION:
206         return SOUND_TYPE_VOICE;
207     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_RINGTONE_VOIP:
208         return SOUND_TYPE_RINGTONE;
209     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_VOIP:
210         return SOUND_TYPE_VOIP;
211     default:
212         return SOUND_TYPE_MEDIA;
213     }
214 }
215
216 static audio_io_state_e __convert_state_type(const CAudioInfo::EAudioIOState src_state) {
217     switch (src_state) {
218     case CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE:
219         return AUDIO_IO_STATE_IDLE;
220     case CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE:
221         return AUDIO_IO_STATE_IDLE;
222     case CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING:
223         return AUDIO_IO_STATE_RUNNING;
224     case CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED:
225         return AUDIO_IO_STATE_PAUSED;
226     default:
227         return AUDIO_IO_STATE_IDLE;
228     }
229 }
230
231 static void __check_audio_param(int sample_rate, audio_channel_e channel, audio_sample_type_e type, bool is_output) {
232     if (sample_rate < CAudioInfo::MIN_SYSTEM_SAMPLERATE ||
233         sample_rate > CAudioInfo::MAX_SYSTEM_SAMPLERATE)
234         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid sample rate :%d", sample_rate);
235
236     if (channel < AUDIO_CHANNEL_MONO ||
237         channel > ((is_output) ? AUDIO_CHANNEL_STEREO : AUDIO_CHANNEL_MULTI_16))
238         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid channel :%d", channel);
239
240     if (type < AUDIO_SAMPLE_TYPE_U8 ||
241         type > AUDIO_SAMPLE_TYPE_S32_LE)
242         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid sample type :0x%x", type);
243 }
244
245 static CAudioInfo __generate_audio_input_info(int sampleRate, audio_channel_e channel, audio_sample_type_e sample_type) {
246     return CAudioInfo(sampleRate,
247             __convert_channel_to_audio_info_channel(channel),
248             __convert_sample_type_to_audio_info_sample_type(sample_type),
249             CAudioInfo::EAudioType::AUDIO_IN_TYPE_MEDIA,
250             -1);
251 }
252
253 static CAudioInfo __generate_audio_output_info(int sampleRate, audio_channel_e channel, audio_sample_type_e sample_type, sound_type_e sound_type) {
254     return CAudioInfo(sampleRate,
255                       __convert_channel_to_audio_info_channel(channel),
256                       __convert_sample_type_to_audio_info_sample_type(sample_type),
257                       __convert_sound_type_to_audio_info_audio_type(sound_type),
258                       -1);
259 }
260
261 static void __handle_safe_free(audio_io_s* handle, void *obj, bool is_output) {
262     VALID_POINTER_START(handle)
263         SAFE_FINALIZE(handle->audioIoHandle);
264         SAFE_DELETE(handle->audioIoHandle);
265         SAFE_DELETE(handle);
266     VALID_POINTER_END
267
268     VALID_POINTER_START(obj)
269         if (is_output)
270             *(audio_out_h *)obj = nullptr;
271         else
272             *(audio_in_h *)obj = nullptr;
273     VALID_POINTER_END
274 }
275
276 /**
277  * Implements CAPI functions
278  */
279 int cpp_audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_in_h *input) {
280     audio_io_s* handle = nullptr;
281     bool mic_enable = false;
282
283     try {
284         if (!input)
285             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
286                                   "Parameters are NULL input:%p", input);
287
288         __check_audio_param(sample_rate, channel, type, false);
289
290         AUDIO_IO_LOGD("samplerate:[%d] channel:[0x%x] sample_type:[0x%x]", sample_rate, channel, type);
291
292         /* If MIC is not supported, return NOT_SUPPORTED error */
293         int ret = system_info_get_platform_bool(FEATURE_MICROPHONE, &mic_enable);
294         AUDIO_IO_LOGD("system_info_platform [%s]=[%d], ret[%d]", FEATURE_MICROPHONE, mic_enable, ret);
295         if (ret != SYSTEM_INFO_ERROR_NONE || !mic_enable)
296             THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_SUPPORTED, "System doesn't support microphone!");
297
298         CAudioInfo audioInfo = __generate_audio_input_info(sample_rate, channel, type);
299
300         handle = new audio_io_s;
301         handle->audioIoHandle = new CAudioInput(audioInfo);
302         handle->audioIoHandle->initialize();
303
304         AUDIO_IO_LOGD("[%p] created", handle);
305         *input = handle;
306     } catch (const CAudioError& e) {
307         AUDIO_IO_LOGE("%s", e.getErrorMsg());
308         __handle_safe_free(handle, (void *)input, false);
309         return __convert_audio_io_error(e.getError());
310     } catch (const std::bad_alloc&) {
311 //LCOV_EXCL_START
312         AUDIO_IO_LOGE("Failed to allocate handle");
313         __handle_safe_free(handle, (void *)input, false);
314         return __convert_audio_io_error(CAudioError::EError::ERROR_OUT_OF_MEMORY);
315 //LCOV_EXCL_STOP
316     }
317
318     return AUDIO_IO_ERROR_NONE;
319 }
320
321 int cpp_audio_in_destroy(audio_in_h input) {
322     auto handle = static_cast<audio_io_s*>(input);
323
324     try {
325         if (!handle)
326             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
327                                   "Parameters are NULL input:%p", input);
328         assert(handle->audioIoHandle);
329         AUDIO_IO_LOGD("unpreparing [%p]", handle);
330
331         /* Internal unprepare for backward compatibility */
332         handle->audioIoHandle->unprepare();
333
334         AUDIO_IO_LOGD("try to destroy [%p]", handle);
335
336         SAFE_FINALIZE(handle->audioIoHandle);
337         SAFE_DELETE(handle->audioIoHandle);
338         SAFE_DELETE(handle);
339     } catch (const CAudioError& e) {
340         AUDIO_IO_LOGE("%s", e.getErrorMsg());
341         return __convert_audio_io_error(e.getError());
342     }
343
344     AUDIO_IO_LOGD("destroyed");
345
346     return AUDIO_IO_ERROR_NONE;
347 }
348
349 int cpp_audio_in_set_sound_stream_info(audio_in_h input, sound_stream_info_h stream_info) {
350     auto handle = static_cast<audio_io_s*>(input);
351
352     try {
353         if (!handle || !stream_info)
354             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
355                                    "Parameters are NULL input:%p, stream_info:%p", input, stream_info);
356         assert(handle->audioIoHandle);
357         AUDIO_IO_LOGD("[%p], stream_info:[%p]", handle, stream_info);
358
359         handle->audioIoHandle->setStreamInfo(stream_info);
360     } catch (const CAudioError& e) {
361         AUDIO_IO_LOGE("%s", e.getErrorMsg());
362         return __convert_audio_io_error(e.getError());
363     }
364
365     AUDIO_IO_LOGD("[%p] done", handle);
366
367     return AUDIO_IO_ERROR_NONE;
368 }
369
370 int cpp_audio_in_prepare(audio_in_h input) {
371     auto handle = static_cast<audio_io_s*>(input);
372
373     try {
374         if (!handle)
375             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
376                                    "Parameters are NULL input:%p", input);
377         assert(handle->audioIoHandle);
378         AUDIO_IO_LOGD("[%p]", handle);
379
380         handle->audioIoHandle->prepare();
381     } catch (const CAudioError& e) {
382         AUDIO_IO_LOGE("%s", e.getErrorMsg());
383         return __convert_audio_io_error(e.getError());
384     }
385
386     AUDIO_IO_LOGD("[%p] prepared", handle);
387
388     return AUDIO_IO_ERROR_NONE;
389 }
390
391 int cpp_audio_in_unprepare(audio_in_h input) {
392     auto handle = static_cast<audio_io_s*>(input);
393
394     try {
395         if (!handle)
396             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
397                                    "Parameters are NULL input:%p", input);
398         assert(handle->audioIoHandle);
399         AUDIO_IO_LOGD("[%p]", handle);
400
401         handle->audioIoHandle->unprepare();
402     } catch (const CAudioError& e) {
403         AUDIO_IO_LOGE("%s", e.getErrorMsg());
404         return __convert_audio_io_error(e.getError());
405     }
406
407     AUDIO_IO_LOGD("[%p] unprepared", handle);
408
409     return AUDIO_IO_ERROR_NONE;
410 }
411
412 int cpp_audio_in_pause(audio_in_h input) {
413     auto handle = static_cast<audio_io_s*>(input);
414
415     try {
416         if (!handle)
417             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
418                                    "Parameters are NULL input:%p", input);
419         assert(handle->audioIoHandle);
420         AUDIO_IO_LOGD("[%p]", handle);
421
422         handle->audioIoHandle->pause();
423     } catch (const CAudioError& e) {
424         AUDIO_IO_LOGE("%s", e.getErrorMsg());
425         return __convert_audio_io_error(e.getError());
426     }
427
428     AUDIO_IO_LOGD("[%p] paused", handle);
429
430     return AUDIO_IO_ERROR_NONE;
431 }
432
433 int cpp_audio_in_resume(audio_in_h input) {
434     auto handle = static_cast<audio_io_s*>(input);
435
436     try {
437         if (!handle)
438             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
439                                    "Parameters are NULL input:%p", input);
440         assert(handle->audioIoHandle);
441         AUDIO_IO_LOGD("[%p]", handle);
442
443         handle->audioIoHandle->resume();
444     } catch (const CAudioError& e) {
445         AUDIO_IO_LOGE("%s", e.getErrorMsg());
446         return __convert_audio_io_error(e.getError());
447     }
448
449     AUDIO_IO_LOGD("[%p] resumed", handle);
450
451     return AUDIO_IO_ERROR_NONE;
452 }
453
454 int cpp_audio_in_flush(audio_in_h input) {
455     auto handle = static_cast<audio_io_s*>(input);
456
457     try {
458         if (!handle)
459             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
460                                    "Parameters are NULL input:%p", input);
461         assert(handle->audioIoHandle);
462         AUDIO_IO_LOGD("[%p]", handle);
463
464         handle->audioIoHandle->flush();
465     } catch (const CAudioError& e) {
466         AUDIO_IO_LOGE("%s", e.getErrorMsg());
467         return __convert_audio_io_error(e.getError());
468     }
469
470     AUDIO_IO_LOGD("[%p] flushed", handle);
471
472     return AUDIO_IO_ERROR_NONE;
473 }
474
475 int cpp_audio_in_read(audio_in_h input, void *buffer, unsigned int length) {
476     int ret = 0;
477
478     try {
479         auto handle = static_cast<audio_io_s*>(input);
480         if (!handle || !buffer)
481             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
482                                    "Parameters are NULL input:%p, buffer:%p", input, buffer);
483         assert(handle->audioIoHandle);
484
485         auto inputHandle = static_cast<CAudioInput*>(handle->audioIoHandle);
486         if (!inputHandle)
487             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
488
489         auto readn = inputHandle->read(buffer, static_cast<size_t>(length));
490         ret = static_cast<int>(readn);
491 #ifdef _AUDIO_IO_DEBUG_TIMING_
492         AUDIO_IO_LOGD("readn:%zu", readn);
493 #endif
494     } catch (const CAudioError& e) {
495         AUDIO_IO_LOGE("%s", e.getErrorMsg());
496         return __convert_audio_io_error(e.getError());
497     }
498
499     return ret;
500 }
501
502 int cpp_audio_in_get_buffer_size(audio_in_h input, int *size) {
503     try {
504         auto handle = static_cast<audio_io_s*>(input);
505         if (!handle || !size)
506             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
507                                    "Parameters are NULL input:%p, size:%p", input, size);
508         assert(handle->audioIoHandle);
509
510         auto inputHandle = static_cast<CAudioInput*>(handle->audioIoHandle);
511         if (!inputHandle)
512             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
513
514         *size = inputHandle->getBufferSize();
515     } catch (const CAudioError& e) {
516         AUDIO_IO_LOGE("%s", e.getErrorMsg());
517         return __convert_audio_io_error(e.getError());
518     }
519
520     return AUDIO_IO_ERROR_NONE;
521 }
522
523 int cpp_audio_in_get_sample_rate(audio_in_h input, int *sample_rate) {
524     try {
525         auto handle = static_cast<audio_io_s*>(input);
526         if (!handle || !sample_rate)
527             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
528                                    "Parameters are NULL input:%p, sample_rate:%p", input, sample_rate);
529         assert(handle->audioIoHandle);
530
531         *sample_rate = handle->audioIoHandle->getAudioInfo().getSampleRate();
532     } catch (const CAudioError& e) {
533         AUDIO_IO_LOGE("%s", e.getErrorMsg());
534         return __convert_audio_io_error(e.getError());
535     }
536
537     return AUDIO_IO_ERROR_NONE;
538 }
539
540 int cpp_audio_in_get_channel(audio_in_h input, audio_channel_e *channel) {
541     try {
542         auto handle = static_cast<audio_io_s*>(input);
543         if (!handle || !channel)
544             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
545                                    "Parameters are NULL input:%p, channel:%p", input, channel);
546         assert(handle->audioIoHandle);
547
548         *channel = __convert_audio_info_channel_to_channel(handle->audioIoHandle->getAudioInfo().getChannel());
549     } catch (const CAudioError& e) {
550         AUDIO_IO_LOGE("%s", e.getErrorMsg());
551         return __convert_audio_io_error(e.getError());
552     }
553
554     return AUDIO_IO_ERROR_NONE;
555 }
556
557 int cpp_audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type) {
558     try {
559         auto handle = static_cast<audio_io_s*>(input);
560         if (!handle || !type)
561             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
562                                    "Parameters are NULL input:%p, type:%p", input, type);
563         assert(handle->audioIoHandle);
564
565         *type = __convert_audio_info_sample_type_to_sample_type(handle->audioIoHandle->getAudioInfo().getSampleType());
566     } catch (const CAudioError& e) {
567         AUDIO_IO_LOGE("%s", e.getErrorMsg());
568         return __convert_audio_io_error(e.getError());
569     }
570
571     return AUDIO_IO_ERROR_NONE;
572 }
573
574 static void __stream_cb_internal(size_t nbytes, void *user_data) {
575     auto audioIo = static_cast<audio_io_s*>(user_data);
576     assert(audioIo);
577
578     if (audioIo->stream_callback.onStream)
579         audioIo->stream_callback.onStream(audioIo, nbytes, audioIo->stream_callback.user_data);
580 }
581
582 //LCOV_EXCL_START
583 static void __state_changed_cb_internal(CAudioInfo::EAudioIOState state,
584                                         CAudioInfo::EAudioIOState state_prev,
585                                         bool by_policy,
586                                         void *user_data) {
587     auto audioIo = static_cast<audio_io_s*>(user_data);
588     assert(audioIo);
589
590     if (audioIo->state_changed_callback.onStateChanged)
591         audioIo->state_changed_callback.onStateChanged(audioIo, __convert_state_type(state_prev),
592                                                        __convert_state_type(state), by_policy,
593                                                        audioIo->state_changed_callback.user_data);
594 }
595 //LCOV_EXCL_STOP
596
597 int cpp_audio_in_set_stream_cb(audio_in_h input, audio_in_stream_cb callback, void* user_data) {
598     auto handle = static_cast<audio_io_s*>(input);
599
600     try {
601         if (!handle || !callback)
602             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
603                                    "Parameters are NULL input:%p, callback:%p", input, callback);
604         assert(handle->audioIoHandle);
605         AUDIO_IO_LOGD("[%p], callback:[%p], user_data:[%p]", handle, callback, user_data);
606
607         handle->stream_callback.set(callback, user_data);
608
609         auto cb = handle->audioIoHandle->getStreamCallback();
610         cb.set(__stream_cb_internal, static_cast<void*>(handle));
611
612         handle->audioIoHandle->setStreamCallback(cb);
613     } catch (const CAudioError& e) {
614         AUDIO_IO_LOGE("%s", e.getErrorMsg());
615         return __convert_audio_io_error(e.getError());
616     }
617
618     AUDIO_IO_LOGD("[%p] done", handle);
619
620     return AUDIO_IO_ERROR_NONE;
621 }
622
623 int cpp_audio_in_unset_stream_cb(audio_in_h input) {
624     auto handle = static_cast<audio_io_s*>(input);
625     try {
626         if (!handle)
627             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
628                                    "Parameters are NULL input:%p", input);
629         assert(handle->audioIoHandle);
630         AUDIO_IO_LOGD("[%p]", handle);
631
632         handle->stream_callback.unset();
633
634         auto cb = handle->audioIoHandle->getStreamCallback();
635         cb.unset();
636
637         handle->audioIoHandle->setStreamCallback(cb);
638     } catch (const CAudioError& e) {
639         AUDIO_IO_LOGE("%s", e.getErrorMsg());
640         return __convert_audio_io_error(e.getError());
641     }
642
643     AUDIO_IO_LOGD("[%p] done", handle);
644
645     return AUDIO_IO_ERROR_NONE;
646 }
647
648 int cpp_audio_in_peek(audio_in_h input, const void **buffer, unsigned int *length) {
649     size_t _length = 0;
650
651     try {
652         auto handle = static_cast<audio_io_s*>(input);
653         if (!handle || !buffer)
654             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
655                                    "Parameters are NULL input:%p, buffer:%p", input, buffer);
656
657         auto inputHandle = static_cast<CAudioInput*>(handle->audioIoHandle);
658         if (!inputHandle)
659             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL"); // LCOV_EXCL_LINE
660
661         inputHandle->peek(buffer, &_length);
662     } catch (const CAudioError& e) {
663         AUDIO_IO_LOGE("%s", e.getErrorMsg());
664         return __convert_audio_io_error(e.getError());
665     }
666
667     *length = (unsigned int)_length;
668
669     return AUDIO_IO_ERROR_NONE;
670 }
671
672 int cpp_audio_in_drop(audio_in_h input) {
673     try {
674         auto handle = static_cast<audio_io_s*>(input);
675         if (!handle)
676             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
677                                    "Parameters are NULL input:%p", input);
678
679         auto inputHandle = static_cast<CAudioInput*>(handle->audioIoHandle);
680         if (!inputHandle)
681             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL"); // LCOV_EXCL_LINE
682
683         inputHandle->drop();
684     } catch (const CAudioError& e) {
685         AUDIO_IO_LOGE("%s", e.getErrorMsg());
686         return __convert_audio_io_error(e.getError());
687     }
688
689     return AUDIO_IO_ERROR_NONE;
690 }
691
692 int cpp_audio_in_set_state_changed_cb(audio_in_h input, audio_in_state_changed_cb callback, void* user_data) {
693     auto handle = static_cast<audio_io_s*>(input);
694
695     try {
696         if (!handle || !callback)
697             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
698                                    "Parameters are NULL input:%p, callback:%p", input, callback);
699         assert(handle->audioIoHandle);
700         AUDIO_IO_LOGD("[%p], callback:[%p], user_data:[%p]", handle, callback, user_data);
701
702         handle->state_changed_callback.set(callback, user_data);
703
704         auto cb = handle->audioIoHandle->getStateChangedCallback();
705         cb.set(__state_changed_cb_internal, static_cast<void*>(handle));
706
707         handle->audioIoHandle->setStateChangedCallback(cb);
708     } catch (const CAudioError& e) {
709         AUDIO_IO_LOGE("%s", e.getErrorMsg());
710         return __convert_audio_io_error(e.getError());
711     }
712
713     AUDIO_IO_LOGD("[%p] done", handle);
714
715     return AUDIO_IO_ERROR_NONE;
716 }
717
718 int cpp_audio_in_unset_state_changed_cb(audio_in_h input) {
719     auto handle = static_cast<audio_io_s*>(input);
720
721     try {
722         if (!handle)
723             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
724                                    "Parameters are NULL input:%p", input);
725         assert(handle->audioIoHandle);
726         AUDIO_IO_LOGD("[%p]", handle);
727
728         handle->state_changed_callback.unset();
729
730         auto cb = handle->audioIoHandle->getStateChangedCallback();
731         cb.unset();
732
733         handle->audioIoHandle->setStateChangedCallback(cb);
734     } catch (const CAudioError& e) {
735         AUDIO_IO_LOGE("%s", e.getErrorMsg());
736         return __convert_audio_io_error(e.getError());
737     }
738
739     AUDIO_IO_LOGD("[%p] done", handle);
740
741     return AUDIO_IO_ERROR_NONE;
742 }
743
744 int cpp_audio_in_get_volume(audio_in_h input, double *volume) {
745     auto handle = static_cast<audio_io_s*>(input);
746
747     try {
748         if (!handle || !volume)
749             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
750                                    "Parameters are NULL input:%p, volume:%p", input, volume);
751         assert(handle->audioIoHandle);
752         AUDIO_IO_LOGD("[%p]", handle);
753
754         auto input_handle = dynamic_cast<CAudioInput*>(handle->audioIoHandle);
755         if (input_handle == nullptr)
756             return __convert_audio_io_error(CAudioError::EError::ERROR_INVALID_HANDLE);
757
758         *volume = input_handle->getVolume();
759     } catch (const CAudioError& e) {
760         AUDIO_IO_LOGE("%s", e.getErrorMsg());
761         return __convert_audio_io_error(e.getError());
762     }
763
764     AUDIO_IO_LOGD("[%p] done", handle);
765
766     return AUDIO_IO_ERROR_NONE;
767 }
768
769 int cpp_audio_in_set_volume(audio_in_h input, double volume) {
770     auto handle = static_cast<audio_io_s*>(input);
771
772     try {
773         if (!handle)
774             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
775                                    "Parameters are NULL input:%p", input);
776
777         if (volume < CAudioInfo::MIN_RECORD_VOLUME || volume > CAudioInfo::MAX_RECORD_VOLUME)
778             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid volume: %f", volume);
779
780         assert(handle->audioIoHandle);
781         AUDIO_IO_LOGD("[%p]", handle);
782
783         auto input_handle = dynamic_cast<CAudioInput*>(handle->audioIoHandle);
784         if (input_handle == nullptr)
785             return __convert_audio_io_error(CAudioError::EError::ERROR_INVALID_HANDLE);
786
787         input_handle->setVolume(volume);
788     } catch (const CAudioError& e) {
789         AUDIO_IO_LOGE("%s", e.getErrorMsg());
790         return __convert_audio_io_error(e.getError());
791     }
792
793     AUDIO_IO_LOGD("[%p] done", handle);
794
795     return AUDIO_IO_ERROR_NONE;
796 }
797
798 /**
799  * Audio Out
800  */
801 int cpp_audio_out_create_new(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_out_h *output) {
802     audio_io_s* handle = nullptr;
803     try {
804         if (!output)
805             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
806                                    "Parameters are NULL output:%p", output);
807
808         __check_audio_param(sample_rate, channel, type, true);
809
810         AUDIO_IO_LOGD("samplerate:[%d] channel:[0x%x] sample_type:[0x%x]", sample_rate, channel, type);
811         CAudioInfo audioInfo = __generate_audio_output_info(sample_rate, channel, type, SOUND_TYPE_MEDIA);
812
813         handle = new audio_io_s;
814         handle->audioIoHandle = new CAudioOutput(audioInfo);
815         handle->audioIoHandle->initialize();
816
817         AUDIO_IO_LOGD("[%p] created", handle);
818         *output = handle;
819     } catch (const CAudioError& e) {
820         AUDIO_IO_LOGE("%s", e.getErrorMsg());
821         __handle_safe_free(handle, (void *)output, true);
822         return __convert_audio_io_error(e.getError());
823     } catch (const std::bad_alloc&) {
824 //LCOV_EXCL_START
825         AUDIO_IO_LOGE("Failed to allocate handle");
826         __handle_safe_free(handle, (void *)output, true);
827         return __convert_audio_io_error(CAudioError::EError::ERROR_OUT_OF_MEMORY);
828 //LCOV_EXCL_STOP
829     }
830
831     return AUDIO_IO_ERROR_NONE;
832 }
833
834 int cpp_audio_out_destroy(audio_out_h output) {
835     auto handle = static_cast<audio_io_s*>(output);
836
837     try {
838         if (!handle)
839             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
840                                    "Parameter is NULL output:%p", output);
841         assert(handle->audioIoHandle);
842         AUDIO_IO_LOGD("unpreparing [%p]", handle);
843
844         /* Internal unprepare for backward compatibility */
845         handle->audioIoHandle->unprepare();
846
847         AUDIO_IO_LOGD("try to destroy [%p]", handle);
848
849         SAFE_FINALIZE(handle->audioIoHandle);
850         SAFE_DELETE(handle->audioIoHandle);
851         SAFE_DELETE(handle);
852     } catch (const CAudioError& e) {
853         AUDIO_IO_LOGE("%s", e.getErrorMsg());
854         return __convert_audio_io_error(e.getError());
855     }
856
857     AUDIO_IO_LOGD("destroyed");
858
859     return AUDIO_IO_ERROR_NONE;
860 }
861
862 int cpp_audio_out_set_sound_stream_info(audio_out_h output, sound_stream_info_h stream_info) {
863     auto handle = static_cast<audio_io_s*>(output);
864
865     try {
866         if (!handle || !stream_info)
867             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
868                                    "Parameters are NULL output:%p, stream_info:%p", output, stream_info);
869         assert(handle->audioIoHandle);
870         AUDIO_IO_LOGD("[%p], stream_info:[%p]", handle, stream_info);
871
872         handle->audioIoHandle->setStreamInfo(stream_info);
873     } catch (const CAudioError& e) {
874         AUDIO_IO_LOGE("%s", e.getErrorMsg());
875         return __convert_audio_io_error(e.getError());
876     }
877
878     AUDIO_IO_LOGD("[%p] done", handle);
879
880     return AUDIO_IO_ERROR_NONE;
881 }
882
883 int cpp_audio_out_prepare(audio_out_h output) {
884     auto handle = static_cast<audio_io_s*>(output);
885
886     try {
887         if (!handle)
888             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
889                                    "Parameter is NULL output:%p", output);
890         assert(handle->audioIoHandle);
891         AUDIO_IO_LOGD("[%p]", handle);
892
893         handle->audioIoHandle->prepare();
894     } catch (const CAudioError& e) {
895         AUDIO_IO_LOGE("%s", e.getErrorMsg());
896         return __convert_audio_io_error(e.getError());
897     }
898
899     AUDIO_IO_LOGD("[%p] prepared", handle);
900
901     return AUDIO_IO_ERROR_NONE;
902 }
903
904 int cpp_audio_out_unprepare(audio_out_h output) {
905     auto handle = static_cast<audio_io_s*>(output);
906
907     try {
908         if (!handle)
909             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
910                                    "Parameter is NULL output:%p", output);
911         assert(handle->audioIoHandle);
912         AUDIO_IO_LOGD("[%p]", handle);
913
914         handle->audioIoHandle->unprepare();
915     } catch (const CAudioError& e) {
916         AUDIO_IO_LOGE("%s", e.getErrorMsg());
917         return __convert_audio_io_error(e.getError());
918     }
919
920     AUDIO_IO_LOGD("[%p] unprepared", handle);
921
922     return AUDIO_IO_ERROR_NONE;
923 }
924
925 int cpp_audio_out_pause(audio_out_h output) {
926     auto handle = static_cast<audio_io_s*>(output);
927
928     try {
929         if (!handle)
930             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
931                                    "Parameter is NULL output:%p", output);
932         assert(handle->audioIoHandle);
933         AUDIO_IO_LOGD("[%p]", handle);
934
935         handle->audioIoHandle->pause();
936     } catch (const CAudioError& e) {
937         AUDIO_IO_LOGE("%s", e.getErrorMsg());
938         return __convert_audio_io_error(e.getError());
939     }
940
941     AUDIO_IO_LOGD("[%p] paused", handle);
942
943     return AUDIO_IO_ERROR_NONE;
944 }
945
946 int cpp_audio_out_resume(audio_out_h output) {
947     auto handle = static_cast<audio_io_s*>(output);
948
949     try {
950         if (!handle)
951             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
952                                    "Parameter is NULL output:%p", output);
953         assert(handle->audioIoHandle);
954         AUDIO_IO_LOGD("[%p]", handle);
955
956         handle->audioIoHandle->resume();
957     } catch (const CAudioError& e) {
958         AUDIO_IO_LOGE("%s", e.getErrorMsg());
959         return __convert_audio_io_error(e.getError());
960     }
961
962     AUDIO_IO_LOGD("[%p] resumed", handle);
963
964     return AUDIO_IO_ERROR_NONE;
965 }
966
967 int cpp_audio_out_drain(audio_out_h output) {
968     auto handle = static_cast<audio_io_s*>(output);
969
970     try {
971         if (!handle)
972             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
973                                    "Parameter is NULL output:%p", output);
974         assert(handle->audioIoHandle);
975         AUDIO_IO_LOGD("[%p]", handle);
976
977         auto output_handle = dynamic_cast<CAudioOutput*>(handle->audioIoHandle);
978         if (output_handle == nullptr)
979             return __convert_audio_io_error(CAudioError::EError::ERROR_INVALID_HANDLE);
980
981         output_handle->drain();
982     } catch (const CAudioError& e) {
983         AUDIO_IO_LOGE("%s", e.getErrorMsg());
984         return __convert_audio_io_error(e.getError());
985     }
986
987     AUDIO_IO_LOGD("[%p] drained", handle);
988
989     return AUDIO_IO_ERROR_NONE;
990 }
991
992 int cpp_audio_out_flush(audio_out_h output) {
993     auto handle = static_cast<audio_io_s*>(output);
994
995     try {
996         if (!handle)
997             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
998                                    "Parameter is NULL output:%p", output);
999         assert(handle->audioIoHandle);
1000         AUDIO_IO_LOGD("[%p]", handle);
1001
1002         handle->audioIoHandle->flush();
1003     } catch (const CAudioError& e) {
1004         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1005         return __convert_audio_io_error(e.getError());
1006     }
1007
1008     AUDIO_IO_LOGD("[%p] flushed", handle);
1009
1010     return AUDIO_IO_ERROR_NONE;
1011 }
1012
1013 int cpp_audio_out_write(audio_out_h output, void *buffer, unsigned int length) {
1014     int ret = 0;
1015
1016     try {
1017         auto handle = static_cast<audio_io_s*>(output);
1018         if (!handle || !buffer)
1019             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1020                                    "Parameter is NULL output:%p, buffer:%p", output, buffer);
1021         assert(handle->audioIoHandle);
1022
1023         auto outputHandle = static_cast<CAudioOutput*>(handle->audioIoHandle);
1024         if (!outputHandle)
1025             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
1026
1027         auto written = outputHandle->write(buffer, static_cast<size_t>(length));
1028         ret = static_cast<int>(written);
1029 #ifdef _AUDIO_IO_DEBUG_TIMING_
1030         AUDIO_IO_LOGD("written:%zu", written);
1031 #endif
1032     } catch (const CAudioError& e) {
1033         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1034         return __convert_audio_io_error(e.getError());
1035     }
1036
1037     return ret;
1038 }
1039
1040 int cpp_audio_out_get_buffer_size(audio_out_h output, int *size) {
1041     try {
1042         auto handle = static_cast<audio_io_s*>(output);
1043         if (!handle || !size)
1044             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1045                                    "Parameters are NULL output:%p, size:%p", output, size);
1046         assert(handle->audioIoHandle);
1047
1048         auto outputHandle = static_cast<CAudioOutput*>(handle->audioIoHandle);
1049         if (!outputHandle)
1050             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
1051
1052         *size = outputHandle->getBufferSize();
1053     } catch (const CAudioError& e) {
1054         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1055         return __convert_audio_io_error(e.getError());
1056     }
1057
1058     return AUDIO_IO_ERROR_NONE;
1059 }
1060
1061 int cpp_audio_out_get_sample_rate(audio_out_h output, int *sample_rate) {
1062     try {
1063         auto handle = static_cast<audio_io_s*>(output);
1064         if (!handle || !sample_rate)
1065             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1066                                    "Parameters are NULL output:%p, sample_rate:%p", output, sample_rate);
1067         assert(handle->audioIoHandle);
1068
1069         *sample_rate = handle->audioIoHandle->getAudioInfo().getSampleRate();
1070     } catch (const CAudioError& e) {
1071         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1072         return __convert_audio_io_error(e.getError());
1073     }
1074
1075     return AUDIO_IO_ERROR_NONE;
1076 }
1077
1078 int cpp_audio_out_get_channel(audio_out_h output, audio_channel_e *channel) {
1079     try {
1080         auto handle = static_cast<audio_io_s*>(output);
1081         if (!handle || !channel)
1082             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1083                                    "Parameters are NULL output:%p, channel:%p", output, channel);
1084         assert(handle->audioIoHandle);
1085
1086         *channel = __convert_audio_info_channel_to_channel(handle->audioIoHandle->getAudioInfo().getChannel());
1087     } catch (const CAudioError& e) {
1088         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1089         return __convert_audio_io_error(e.getError());
1090     }
1091
1092     return AUDIO_IO_ERROR_NONE;
1093 }
1094
1095 int cpp_audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type) {
1096     try {
1097         auto handle = static_cast<audio_io_s*>(output);
1098         if (!handle || !type)
1099             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1100                                    "Parameters are NULL output:%p, type:%p", output, type);
1101         assert(handle->audioIoHandle);
1102
1103         *type = __convert_audio_info_sample_type_to_sample_type(handle->audioIoHandle->getAudioInfo().getSampleType());
1104     } catch (const CAudioError& e) {
1105         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1106         return __convert_audio_io_error(e.getError());
1107     }
1108
1109     return AUDIO_IO_ERROR_NONE;
1110 }
1111
1112 int cpp_audio_out_get_sound_type(audio_out_h output, sound_type_e *type) {
1113     auto handle = static_cast<audio_io_s*>(output);
1114
1115     try {
1116         if (!handle || !type)
1117             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1118                                    "Parameters are NULL output:%p, type:%p", output, type);
1119         assert(handle->audioIoHandle);
1120
1121         *type = __convert_audio_info_audio_type_to_sound_type(handle->audioIoHandle->getAudioInfo().getAudioType());
1122     } catch (const CAudioError& e) {
1123         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1124         return __convert_audio_io_error(e.getError());
1125     }
1126
1127     return AUDIO_IO_ERROR_NONE;
1128 }
1129
1130 int cpp_audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback, void* user_data) {
1131     auto handle = static_cast<audio_io_s*>(output);
1132
1133     try {
1134         if (!handle || !callback)
1135             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1136                                    "Parameters are NULL output:%p, callback:%p", output, callback);
1137         assert(handle->audioIoHandle);
1138         AUDIO_IO_LOGD("[%p], callback:[%p], user_data:[%p]", handle, callback, user_data);
1139
1140         handle->stream_callback.set(callback, user_data);
1141
1142         auto cb = handle->audioIoHandle->getStreamCallback();
1143         cb.set(__stream_cb_internal, static_cast<void*>(handle));
1144
1145         handle->audioIoHandle->setStreamCallback(cb);
1146     } catch (const CAudioError& e) {
1147         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1148         return __convert_audio_io_error(e.getError());
1149     }
1150
1151     AUDIO_IO_LOGD("[%p] done", handle);
1152
1153     return AUDIO_IO_ERROR_NONE;
1154 }
1155
1156 int cpp_audio_out_unset_stream_cb(audio_out_h output) {
1157     auto handle = static_cast<audio_io_s*>(output);
1158
1159     try {
1160         if (!handle)
1161             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1162                                    "Parameters are NULL output:%p", output);
1163         assert(handle->audioIoHandle);
1164         AUDIO_IO_LOGD("[%p]", handle);
1165
1166         handle->stream_callback.unset();
1167
1168         auto cb = handle->audioIoHandle->getStreamCallback();
1169         cb.unset();
1170
1171         handle->audioIoHandle->setStreamCallback(cb);
1172     } catch (const CAudioError& e) {
1173         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1174         return __convert_audio_io_error(e.getError());
1175     }
1176
1177     AUDIO_IO_LOGD("[%p] done", handle);
1178
1179     return AUDIO_IO_ERROR_NONE;
1180 }
1181
1182 int cpp_audio_out_set_state_changed_cb(audio_out_h output, audio_in_state_changed_cb callback, void* user_data) {
1183     auto handle = static_cast<audio_io_s*>(output);
1184
1185     try {
1186         if (!handle || !callback)
1187             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1188                                    "Parameters are NULL output:%p, callback:%p", output, callback);
1189         assert(handle->audioIoHandle);
1190         AUDIO_IO_LOGD("[%p], callback:[%p], user_data:[%p]", handle, callback, user_data);
1191
1192         handle->state_changed_callback.set(callback, user_data);
1193
1194         auto cb = handle->audioIoHandle->getStateChangedCallback();
1195         cb.set(__state_changed_cb_internal, static_cast<void*>(handle));
1196
1197         handle->audioIoHandle->setStateChangedCallback(cb);
1198     } catch (const CAudioError& e) {
1199         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1200         return __convert_audio_io_error(e.getError());
1201     }
1202
1203     AUDIO_IO_LOGD("[%p] done", handle);
1204
1205     return AUDIO_IO_ERROR_NONE;
1206 }
1207
1208 int cpp_audio_out_unset_state_changed_cb(audio_out_h output) {
1209     auto handle = static_cast<audio_io_s*>(output);
1210
1211     try {
1212         if (!handle)
1213             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1214                                    "Parameters are NULL output:%p", output);
1215         assert(handle->audioIoHandle);
1216         AUDIO_IO_LOGD("[%p]", handle);
1217
1218         handle->state_changed_callback.unset();
1219
1220         auto cb = handle->audioIoHandle->getStateChangedCallback();
1221         cb.unset();
1222
1223         handle->audioIoHandle->setStateChangedCallback(cb);
1224     } catch (const CAudioError& e) {
1225         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1226         return __convert_audio_io_error(e.getError());
1227     }
1228
1229     AUDIO_IO_LOGD("[%p] done", handle);
1230
1231     return AUDIO_IO_ERROR_NONE;
1232 }