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