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