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