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