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