Move drain method to subclass CAudioOutput
[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 < static_cast<int>(CAudioInfo::MIN_SYSTEM_SAMPLERATE) ||
281         sample_rate > static_cast<int>(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 output:%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
791 /**
792  * Audio Out
793  */
794 int cpp_audio_out_create_new(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_out_h *output) {
795     audio_io_s* handle = nullptr;
796     try {
797         if (!output)
798             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
799                                    "Parameters are NULL output:%p", output);
800
801         __check_audio_param(sample_rate, channel, type, true);
802
803         AUDIO_IO_LOGD("samplerate:[%d] channel:[0x%x] sample_type:[0x%x]", sample_rate, channel, type);
804         CAudioInfo audioInfo = __generate_audio_output_info(sample_rate, channel, type, SOUND_TYPE_MEDIA);
805
806         handle = new audio_io_s;
807         handle->audioIoHandle = new CAudioOutput(audioInfo);
808         handle->audioIoHandle->initialize();
809
810         AUDIO_IO_LOGD("[%p] created", handle);
811         *output = handle;
812     } catch (const CAudioError& e) {
813         AUDIO_IO_LOGE("%s", e.getErrorMsg());
814         __handle_safe_free(handle, (void *)output, true);
815         return __convert_audio_io_error(e.getError());
816     } catch (const std::bad_alloc&) {
817 //LCOV_EXCL_START
818         AUDIO_IO_LOGE("Failed to allocate handle");
819         __handle_safe_free(handle, (void *)output, true);
820         return __convert_audio_io_error(CAudioError::EError::ERROR_OUT_OF_MEMORY);
821 //LCOV_EXCL_STOP
822     }
823
824     return AUDIO_IO_ERROR_NONE;
825 }
826
827 int cpp_audio_out_destroy(audio_out_h output) {
828     auto handle = static_cast<audio_io_s*>(output);
829
830     try {
831         if (!handle)
832             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
833                                    "Parameter is NULL output:%p", output);
834         assert(handle->audioIoHandle);
835         AUDIO_IO_LOGD("[%p]", handle);
836
837         /* Internal unprepare for backward compatibility */
838         handle->audioIoHandle->unprepare();
839
840         SAFE_FINALIZE(handle->audioIoHandle);
841         SAFE_DELETE(handle->audioIoHandle);
842         SAFE_DELETE(handle);
843     } catch (const CAudioError& e) {
844         AUDIO_IO_LOGE("%s", e.getErrorMsg());
845         return __convert_audio_io_error(e.getError());
846     }
847
848     AUDIO_IO_LOGD("[%p] destroyed", handle);
849
850     return AUDIO_IO_ERROR_NONE;
851 }
852
853 int cpp_audio_out_set_sound_stream_info(audio_out_h output, sound_stream_info_h stream_info) {
854     auto handle = static_cast<audio_io_s*>(output);
855
856     try {
857         if (!handle || !stream_info)
858             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
859                                    "Parameters are NULL output:%p, stream_info:%p", output, stream_info);
860         assert(handle->audioIoHandle);
861         AUDIO_IO_LOGD("[%p], stream_info:[%p]", handle, stream_info);
862
863         handle->audioIoHandle->setStreamInfo(stream_info);
864     } catch (const CAudioError& e) {
865         AUDIO_IO_LOGE("%s", e.getErrorMsg());
866         return __convert_audio_io_error(e.getError());
867     }
868
869     AUDIO_IO_LOGD("[%p] done", handle);
870
871     return AUDIO_IO_ERROR_NONE;
872 }
873
874 int cpp_audio_out_prepare(audio_out_h output) {
875     auto handle = static_cast<audio_io_s*>(output);
876
877     try {
878         if (!handle)
879             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
880                                    "Parameter is NULL output:%p", output);
881         assert(handle->audioIoHandle);
882         AUDIO_IO_LOGD("[%p]", handle);
883
884         handle->audioIoHandle->prepare();
885     } catch (const CAudioError& e) {
886         AUDIO_IO_LOGE("%s", e.getErrorMsg());
887         return __convert_audio_io_error(e.getError());
888     }
889
890     AUDIO_IO_LOGD("[%p] prepared", handle);
891
892     return AUDIO_IO_ERROR_NONE;
893 }
894
895 int cpp_audio_out_unprepare(audio_out_h output) {
896     auto handle = static_cast<audio_io_s*>(output);
897
898     try {
899         if (!handle)
900             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
901                                    "Parameter is NULL output:%p", output);
902         assert(handle->audioIoHandle);
903         AUDIO_IO_LOGD("[%p]", handle);
904
905         handle->audioIoHandle->unprepare();
906     } catch (const CAudioError& e) {
907         AUDIO_IO_LOGE("%s", e.getErrorMsg());
908         return __convert_audio_io_error(e.getError());
909     }
910
911     AUDIO_IO_LOGD("[%p] unprepared", handle);
912
913     return AUDIO_IO_ERROR_NONE;
914 }
915
916 int cpp_audio_out_pause(audio_out_h output) {
917     auto handle = static_cast<audio_io_s*>(output);
918
919     try {
920         if (!handle)
921             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
922                                    "Parameter is NULL output:%p", output);
923         assert(handle->audioIoHandle);
924         AUDIO_IO_LOGD("[%p]", handle);
925
926         handle->audioIoHandle->pause();
927     } catch (const CAudioError& e) {
928         AUDIO_IO_LOGE("%s", e.getErrorMsg());
929         return __convert_audio_io_error(e.getError());
930     }
931
932     AUDIO_IO_LOGD("[%p] paused", handle);
933
934     return AUDIO_IO_ERROR_NONE;
935 }
936
937 int cpp_audio_out_resume(audio_out_h output) {
938     auto handle = static_cast<audio_io_s*>(output);
939
940     try {
941         if (!handle)
942             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
943                                    "Parameter is NULL output:%p", output);
944         assert(handle->audioIoHandle);
945         AUDIO_IO_LOGD("[%p]", handle);
946
947         handle->audioIoHandle->resume();
948     } catch (const CAudioError& e) {
949         AUDIO_IO_LOGE("%s", e.getErrorMsg());
950         return __convert_audio_io_error(e.getError());
951     }
952
953     AUDIO_IO_LOGD("[%p] resumed", handle);
954
955     return AUDIO_IO_ERROR_NONE;
956 }
957
958 int cpp_audio_out_drain(audio_out_h output) {
959     auto handle = static_cast<audio_io_s*>(output);
960
961     try {
962         if (!handle)
963             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
964                                    "Parameter is NULL output:%p", output);
965         assert(handle->audioIoHandle);
966         AUDIO_IO_LOGD("[%p]", handle);
967
968         auto output_handle = dynamic_cast<CAudioOutput*>(handle->audioIoHandle);
969         if (output_handle == nullptr)
970             return __convert_audio_io_error(CAudioError::EError::ERROR_INVALID_HANDLE);
971
972         output_handle->drain();
973     } catch (const CAudioError& e) {
974         AUDIO_IO_LOGE("%s", e.getErrorMsg());
975         return __convert_audio_io_error(e.getError());
976     }
977
978     AUDIO_IO_LOGD("[%p] drained", handle);
979
980     return AUDIO_IO_ERROR_NONE;
981 }
982
983 int cpp_audio_out_flush(audio_out_h output) {
984     auto handle = static_cast<audio_io_s*>(output);
985
986     try {
987         if (!handle)
988             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
989                                    "Parameter is NULL output:%p", output);
990         assert(handle->audioIoHandle);
991         AUDIO_IO_LOGD("[%p]", handle);
992
993         handle->audioIoHandle->flush();
994     } catch (const CAudioError& e) {
995         AUDIO_IO_LOGE("%s", e.getErrorMsg());
996         return __convert_audio_io_error(e.getError());
997     }
998
999     AUDIO_IO_LOGD("[%p] flushed", handle);
1000
1001     return AUDIO_IO_ERROR_NONE;
1002 }
1003
1004 int cpp_audio_out_write(audio_out_h output, void *buffer, unsigned int length) {
1005     int ret = 0;
1006
1007     try {
1008         auto handle = static_cast<audio_io_s*>(output);
1009         if (!handle || !buffer)
1010             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1011                                    "Parameter is NULL output:%p, buffer:%p", output, buffer);
1012         assert(handle->audioIoHandle);
1013
1014         auto outputHandle = static_cast<CAudioOutput*>(handle->audioIoHandle);
1015         if (!outputHandle)
1016             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
1017
1018         auto written = outputHandle->write(buffer, static_cast<size_t>(length));
1019         ret = static_cast<int>(written);
1020 #ifdef _AUDIO_IO_DEBUG_TIMING_
1021         AUDIO_IO_LOGD("written:%zu", written);
1022 #endif
1023     } catch (const CAudioError& e) {
1024         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1025         return __convert_audio_io_error(e.getError());
1026     }
1027
1028     return ret;
1029 }
1030
1031 int cpp_audio_out_get_buffer_size(audio_out_h output, int *size) {
1032     try {
1033         auto handle = static_cast<audio_io_s*>(output);
1034         if (!handle || !size)
1035             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1036                                    "Parameters are NULL output:%p, size:%p", output, size);
1037         assert(handle->audioIoHandle);
1038
1039         auto outputHandle = static_cast<CAudioOutput*>(handle->audioIoHandle);
1040         if (!outputHandle)
1041             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
1042
1043         *size = outputHandle->getBufferSize();
1044     } catch (const CAudioError& e) {
1045         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1046         return __convert_audio_io_error(e.getError());
1047     }
1048
1049     return AUDIO_IO_ERROR_NONE;
1050 }
1051
1052 int cpp_audio_out_get_sample_rate(audio_out_h output, int *sample_rate) {
1053     try {
1054         auto handle = static_cast<audio_io_s*>(output);
1055         if (!handle || !sample_rate)
1056             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1057                                    "Parameters are NULL output:%p, sample_rate:%p", output, sample_rate);
1058         assert(handle->audioIoHandle);
1059
1060         *sample_rate = handle->audioIoHandle->getAudioInfo().getSampleRate();
1061     } catch (const CAudioError& e) {
1062         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1063         return __convert_audio_io_error(e.getError());
1064     }
1065
1066     return AUDIO_IO_ERROR_NONE;
1067 }
1068
1069 int cpp_audio_out_get_channel(audio_out_h output, audio_channel_e *channel) {
1070     try {
1071         auto handle = static_cast<audio_io_s*>(output);
1072         if (!handle || !channel)
1073             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1074                                    "Parameters are NULL output:%p, channel:%p", output, channel);
1075         assert(handle->audioIoHandle);
1076
1077         *channel = __convert_audio_info_channel_to_channel(handle->audioIoHandle->getAudioInfo().getChannel());
1078     } catch (const CAudioError& e) {
1079         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1080         return __convert_audio_io_error(e.getError());
1081     }
1082
1083     return AUDIO_IO_ERROR_NONE;
1084 }
1085
1086 int cpp_audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type) {
1087     try {
1088         auto handle = static_cast<audio_io_s*>(output);
1089         if (!handle || !type)
1090             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1091                                    "Parameters are NULL output:%p, type:%p", output, type);
1092         assert(handle->audioIoHandle);
1093
1094         *type = __convert_audio_info_sample_type_to_sample_type(handle->audioIoHandle->getAudioInfo().getSampleType());
1095     } catch (const CAudioError& e) {
1096         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1097         return __convert_audio_io_error(e.getError());
1098     }
1099
1100     return AUDIO_IO_ERROR_NONE;
1101 }
1102
1103 int cpp_audio_out_get_sound_type(audio_out_h output, sound_type_e *type) {
1104     auto handle = static_cast<audio_io_s*>(output);
1105
1106     try {
1107         if (!handle || !type)
1108             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1109                                    "Parameters are NULL output:%p, type:%p", output, type);
1110         assert(handle->audioIoHandle);
1111
1112         *type = __convert_audio_info_audio_type_to_sound_type(handle->audioIoHandle->getAudioInfo().getAudioType());
1113     } catch (const CAudioError& e) {
1114         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1115         return __convert_audio_io_error(e.getError());
1116     }
1117
1118     return AUDIO_IO_ERROR_NONE;
1119 }
1120
1121 int cpp_audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback, void* user_data) {
1122     auto handle = static_cast<audio_io_s*>(output);
1123
1124     try {
1125         if (!handle || !callback)
1126             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1127                                    "Parameters are NULL output:%p, callback:%p", output, callback);
1128         assert(handle->audioIoHandle);
1129         AUDIO_IO_LOGD("[%p], callback:[%p], user_data:[%p]", handle, callback, user_data);
1130
1131         handle->stream_callback.set(callback, user_data);
1132
1133         auto cb = handle->audioIoHandle->getStreamCallback();
1134         cb.set(__stream_cb_internal, static_cast<void*>(handle));
1135
1136         handle->audioIoHandle->setStreamCallback(cb);
1137     } catch (const CAudioError& e) {
1138         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1139         return __convert_audio_io_error(e.getError());
1140     }
1141
1142     AUDIO_IO_LOGD("[%p] done", handle);
1143
1144     return AUDIO_IO_ERROR_NONE;
1145 }
1146
1147 int cpp_audio_out_unset_stream_cb(audio_out_h output) {
1148     auto handle = static_cast<audio_io_s*>(output);
1149
1150     try {
1151         if (!handle)
1152             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1153                                    "Parameters are NULL output:%p", output);
1154         assert(handle->audioIoHandle);
1155         AUDIO_IO_LOGD("[%p]", handle);
1156
1157         handle->stream_callback.unset();
1158
1159         auto cb = handle->audioIoHandle->getStreamCallback();
1160         cb.unset();
1161
1162         handle->audioIoHandle->setStreamCallback(cb);
1163     } catch (const CAudioError& e) {
1164         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1165         return __convert_audio_io_error(e.getError());
1166     }
1167
1168     AUDIO_IO_LOGD("[%p] done", handle);
1169
1170     return AUDIO_IO_ERROR_NONE;
1171 }
1172
1173 int cpp_audio_out_set_state_changed_cb(audio_out_h output, audio_in_state_changed_cb callback, void* user_data) {
1174     auto handle = static_cast<audio_io_s*>(output);
1175
1176     try {
1177         if (!handle || !callback)
1178             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1179                                    "Parameters are NULL output:%p, callback:%p", output, callback);
1180         assert(handle->audioIoHandle);
1181         AUDIO_IO_LOGD("[%p], callback:[%p], user_data:[%p]", handle, callback, user_data);
1182
1183         handle->state_changed_callback.set(callback, user_data);
1184
1185         auto cb = handle->audioIoHandle->getStateChangedCallback();
1186         cb.set(__state_changed_cb_internal, static_cast<void*>(handle));
1187
1188         handle->audioIoHandle->setStateChangedCallback(cb);
1189     } catch (const CAudioError& e) {
1190         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1191         return __convert_audio_io_error(e.getError());
1192     }
1193
1194     AUDIO_IO_LOGD("[%p] done", handle);
1195
1196     return AUDIO_IO_ERROR_NONE;
1197 }
1198
1199 int cpp_audio_out_unset_state_changed_cb(audio_out_h output) {
1200     auto handle = static_cast<audio_io_s*>(output);
1201
1202     try {
1203         if (!handle)
1204             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1205                                    "Parameters are NULL output:%p", output);
1206         assert(handle->audioIoHandle);
1207         AUDIO_IO_LOGD("[%p]", handle);
1208
1209         handle->state_changed_callback.unset();
1210
1211         auto cb = handle->audioIoHandle->getStateChangedCallback();
1212         cb.unset();
1213
1214         handle->audioIoHandle->setStateChangedCallback(cb);
1215     } catch (const CAudioError& e) {
1216         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1217         return __convert_audio_io_error(e.getError());
1218     }
1219
1220     AUDIO_IO_LOGD("[%p] done", handle);
1221
1222     return AUDIO_IO_ERROR_NONE;
1223 }