309e73dd9a6d20bfc8c9f413398a5622842b4c3d
[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(NULL), onStream(NULL)
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(NULL), onStateChanged(NULL)
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(NULL)
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     default:
148         dst_channel = CAudioInfo::EChannel::CHANNEL_MONO;
149         break;
150     }
151 }
152
153 static void __convert_audio_info_channel_2_channel(const CAudioInfo::EChannel& src_channel,
154                                                    audio_channel_e& dst_channel) {
155     switch (src_channel) {
156     case CAudioInfo::EChannel::CHANNEL_MONO:
157         dst_channel = AUDIO_CHANNEL_MONO;
158         break;
159     case CAudioInfo::EChannel::CHANNEL_STEREO:
160         dst_channel = AUDIO_CHANNEL_STEREO;
161         break;
162     default:
163         dst_channel = AUDIO_CHANNEL_MONO;
164         break;
165     }
166 }
167
168 static void __convert_sample_type_2_audio_info_sample_type(const audio_sample_type_e& src_type,
169                                                            CAudioInfo::ESampleType& dst_type) {
170     switch (src_type) {
171     case AUDIO_SAMPLE_TYPE_U8:
172         dst_type = CAudioInfo::ESampleType::SAMPLE_TYPE_U8;
173         break;
174     case AUDIO_SAMPLE_TYPE_S16_LE:
175         dst_type = CAudioInfo::ESampleType::SAMPLE_TYPE_S16_LE;
176         break;
177     default:
178         dst_type = CAudioInfo::ESampleType::SAMPLE_TYPE_U8;
179         break;
180     }
181 }
182
183 static void __convert_audio_info_sample_type_2_sample_type(const CAudioInfo::ESampleType& src_type,
184                                                            audio_sample_type_e& dst_type) {
185     switch (src_type) {
186     case CAudioInfo::ESampleType::SAMPLE_TYPE_U8:
187         dst_type = AUDIO_SAMPLE_TYPE_U8;
188         break;
189     case CAudioInfo::ESampleType::SAMPLE_TYPE_S16_LE:
190         dst_type = AUDIO_SAMPLE_TYPE_S16_LE;
191         break;
192     default:
193         dst_type = AUDIO_SAMPLE_TYPE_U8;
194         break;
195     }
196 }
197
198 static void __convert_sound_type_2_audio_info_audio_type(const sound_type_e& src_type,
199                                                          CAudioInfo::EAudioType& dst_type) {
200     switch (src_type) {
201     case SOUND_TYPE_SYSTEM:
202         dst_type = CAudioInfo::EAudioType::AUDIO_OUT_TYPE_SYSTEM;
203         break;
204     case SOUND_TYPE_NOTIFICATION:
205         dst_type = CAudioInfo::EAudioType::AUDIO_OUT_TYPE_NOTIFICATION;
206         break;
207     case SOUND_TYPE_ALARM:
208         dst_type = CAudioInfo::EAudioType::AUDIO_OUT_TYPE_ALARM;
209         break;
210     case SOUND_TYPE_RINGTONE:
211         dst_type = CAudioInfo::EAudioType::AUDIO_OUT_TYPE_RINGTONE_VOIP;
212         break;
213     case SOUND_TYPE_MEDIA:
214         dst_type = CAudioInfo::EAudioType::AUDIO_OUT_TYPE_MEDIA;
215         break;
216     case SOUND_TYPE_CALL:
217         dst_type = CAudioInfo::EAudioType::AUDIO_OUT_TYPE_SYSTEM;
218         break;
219     case SOUND_TYPE_VOIP:
220         dst_type = CAudioInfo::EAudioType::AUDIO_OUT_TYPE_VOIP;
221         break;
222     case SOUND_TYPE_VOICE:
223         dst_type = CAudioInfo::EAudioType::AUDIO_OUT_TYPE_VOICE_INFORMATION;
224         break;
225     default:
226         dst_type = CAudioInfo::EAudioType::AUDIO_OUT_TYPE_MEDIA;
227         break;
228     }
229 }
230
231 static void __convert_audio_info_audio_type_2_sound_type(const CAudioInfo::EAudioType& src_type,
232                                                          sound_type_e& dst_type) {
233     switch (src_type) {
234     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_MEDIA:
235         dst_type = SOUND_TYPE_MEDIA;
236         break;
237     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_SYSTEM:
238         dst_type = SOUND_TYPE_SYSTEM;
239         break;
240     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_ALARM:
241         dst_type = SOUND_TYPE_ALARM;
242         break;
243     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_NOTIFICATION:
244     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_EMERGENCY:
245         dst_type = SOUND_TYPE_NOTIFICATION;
246         break;
247     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_VOICE_INFORMATION:
248         dst_type = SOUND_TYPE_VOICE;
249         break;
250     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_RINGTONE_VOIP:
251         dst_type = SOUND_TYPE_RINGTONE;
252         break;
253     case CAudioInfo::EAudioType::AUDIO_OUT_TYPE_VOIP:
254         dst_type = SOUND_TYPE_VOIP;
255         break;
256     default:
257         dst_type = SOUND_TYPE_MEDIA;
258         break;
259     }
260 }
261
262 static audio_io_state_e __convert_state_type(const CAudioInfo::EAudioIOState src_state) {
263     audio_io_state_e dst_state;
264
265     switch (src_state) {
266     case CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE:
267         dst_state = AUDIO_IO_STATE_IDLE;
268         break;
269     case CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE:
270         dst_state = AUDIO_IO_STATE_IDLE;
271         break;
272     case CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING:
273         dst_state = AUDIO_IO_STATE_RUNNING;
274         break;
275     case CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED:
276         dst_state = AUDIO_IO_STATE_PAUSED;
277         break;
278     default:
279         dst_state = AUDIO_IO_STATE_IDLE;
280         break;
281     }
282     return dst_state;
283 }
284
285 static void __check_audio_param(int sample_rate, audio_channel_e channel, audio_sample_type_e type) {
286     if (sample_rate < 0)
287         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid sample rate :%d", sample_rate);
288
289     if (channel != AUDIO_CHANNEL_MONO && channel != AUDIO_CHANNEL_STEREO)
290         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid channel :%d", channel);
291
292     if (type != AUDIO_SAMPLE_TYPE_U8 && type != AUDIO_SAMPLE_TYPE_S16_LE)
293         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid sample type :%d", type);
294 }
295
296 static void __check_audio_param(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type) {
297     __check_audio_param(sample_rate, channel, type);
298
299     if (sound_type < SOUND_TYPE_SYSTEM || sound_type > SOUND_TYPE_VOICE)
300         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Invalid sound type : %d", sound_type);
301 }
302
303 static CAudioInfo __generate_audio_input_info(int sampleRate, audio_channel_e channel, audio_sample_type_e sample_type) {
304     CAudioInfo::EChannel dstChannel;
305     CAudioInfo::ESampleType dstSampleType;
306     CAudioInfo::EAudioType dstAudioType = CAudioInfo::EAudioType::AUDIO_IN_TYPE_MEDIA;
307
308     __convert_channel_2_audio_info_channel(channel, dstChannel);
309     __convert_sample_type_2_audio_info_sample_type(sample_type, dstSampleType);
310
311     return CAudioInfo(sampleRate, dstChannel, dstSampleType, dstAudioType, -1);
312 }
313
314 static CAudioInfo __generate_audio_output_info(int sampleRate, audio_channel_e channel, audio_sample_type_e sample_type, sound_type_e sound_type) {
315     CAudioInfo::EChannel dstChannel;
316     CAudioInfo::ESampleType dstSampleType;
317     CAudioInfo::EAudioType dstAudioType;
318
319     __convert_channel_2_audio_info_channel(channel, dstChannel);
320     __convert_sample_type_2_audio_info_sample_type(sample_type, dstSampleType);
321     __convert_sound_type_2_audio_info_audio_type(sound_type, dstAudioType);
322
323     return CAudioInfo(sampleRate, dstChannel, dstSampleType, dstAudioType, -1);
324 }
325
326 static void __handle_safe_free(audio_io_s* handle, void *obj, bool is_output) {
327     VALID_POINTER_START(handle)
328         SAFE_FINALIZE(handle->audioIoHandle);
329         SAFE_DELETE(handle->audioIoHandle);
330         SAFE_DELETE(handle);
331     VALID_POINTER_END
332
333     VALID_POINTER_START(obj)
334         if (is_output)
335             *(audio_out_h *)obj = NULL;
336         else
337             *(audio_in_h *)obj = NULL;
338     VALID_POINTER_END
339 }
340
341 /**
342  * Implements CAPI functions
343  */
344 int cpp_audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_in_h *input) {
345     audio_io_s* handle = NULL;
346     bool mic_enable = false;
347     int ret = 0;
348     try {
349         if (input == NULL) {
350             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
351                                   "Parameters are NULL input:%p", input);
352         }
353
354         __check_audio_param(sample_rate, channel, type);
355
356         AUDIO_IO_LOGD("samplerate:[%d] channel:[0x%x] sample_type:[0x%x]", sample_rate, channel, type);
357
358         /* If MIC is not supported, return NOT_SUPPORTED error */
359         ret = system_info_get_platform_bool(FEATURE_MICROPHONE, &mic_enable);
360         AUDIO_IO_LOGD("system_info_platform [%s]=[%d], ret[%d]", FEATURE_MICROPHONE, mic_enable, ret);
361         if (ret != SYSTEM_INFO_ERROR_NONE || !mic_enable) {
362             THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_SUPPORTED, "System doesn't support microphone!");
363         }
364
365         CAudioInfo audioInfo = __generate_audio_input_info(sample_rate, channel, type);
366
367         handle = new audio_io_s;
368         handle->audioIoHandle = new CAudioInput(audioInfo);
369         handle->audioIoHandle->initialize();
370
371         AUDIO_IO_LOGD("[%p] created", handle);
372         *input = handle;
373     } catch (CAudioError& e) {
374         AUDIO_IO_LOGE("%s", e.getErrorMsg());
375         __handle_safe_free(handle, (void *)input, false);
376         return __convert_CAudioError(e);
377     } catch (const std::bad_alloc&) {
378         CAudioError e = CAudioError::EError::ERROR_OUT_OF_MEMORY;
379         AUDIO_IO_LOGE("Failed to allocate handle");
380         __handle_safe_free(handle, (void *)input, false);
381         return __convert_CAudioError(e);
382     }
383
384     return AUDIO_IO_ERROR_NONE;
385 }
386
387 int cpp_audio_in_create_loopback(int sample_rate, audio_channel_e channel, audio_sample_type_e type , audio_in_h* input) {
388     return AUDIO_IO_ERROR_NOT_SUPPORTED;
389 }
390
391 int cpp_audio_in_destroy(audio_in_h input) {
392     audio_io_s* handle = static_cast<audio_io_s*>(input);
393
394     try {
395         if (handle == NULL)
396             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
397                                   "Parameters are NULL input:%p", input);
398         assert(handle->audioIoHandle);
399         AUDIO_IO_LOGD("[%p]", handle);
400
401         /* Internal unprepare for backward compatibility */
402         handle->audioIoHandle->unprepare();
403
404         SAFE_FINALIZE(handle->audioIoHandle);
405         SAFE_DELETE(handle->audioIoHandle);
406         SAFE_DELETE(handle);
407     } catch (CAudioError& e) {
408         AUDIO_IO_LOGE("%s", e.getErrorMsg());
409         return __convert_CAudioError(e);
410     }
411
412     AUDIO_IO_LOGD("destroyed");
413
414     return AUDIO_IO_ERROR_NONE;
415 }
416
417 int cpp_audio_in_set_sound_stream_info(audio_in_h input, sound_stream_info_h stream_info) {
418     audio_io_s* handle = static_cast<audio_io_s*>(input);
419
420     try {
421         if (handle == NULL || stream_info == NULL)
422             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
423                                    "Parameters are NULL input:%p, stream_info:%p", input, stream_info);
424         assert(handle->audioIoHandle);
425         AUDIO_IO_LOGD("[%p], stream_info:[%p]", handle, stream_info);
426
427         handle->audioIoHandle->setStreamInfo(stream_info);
428     } catch (CAudioError& e) {
429         AUDIO_IO_LOGE("%s", e.getErrorMsg());
430         return __convert_CAudioError(e);
431     }
432
433     AUDIO_IO_LOGD("[%p] done", handle);
434
435     return AUDIO_IO_ERROR_NONE;
436 }
437
438 int cpp_audio_in_prepare(audio_in_h input) {
439     audio_io_s* handle = static_cast<audio_io_s*>(input);
440
441     try {
442         if (handle == NULL)
443             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
444                                    "Parameters are NULL input:%p", input);
445         assert(handle->audioIoHandle);
446         AUDIO_IO_LOGD("[%p]", handle);
447
448         handle->audioIoHandle->prepare();
449     } catch (CAudioError& e) {
450         AUDIO_IO_LOGE("%s", e.getErrorMsg());
451         return __convert_CAudioError(e);
452     }
453
454     AUDIO_IO_LOGD("[%p] prepared", handle);
455
456     return AUDIO_IO_ERROR_NONE;
457 }
458
459 int cpp_audio_in_unprepare(audio_in_h input) {
460     audio_io_s* handle = static_cast<audio_io_s*>(input);
461
462     try {
463         if (handle == NULL)
464             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
465                                    "Parameters are NULL input:%p", input);
466         assert(handle->audioIoHandle);
467         AUDIO_IO_LOGD("[%p]", handle);
468
469         handle->audioIoHandle->unprepare();
470     } catch (CAudioError& e) {
471         AUDIO_IO_LOGE("%s", e.getErrorMsg());
472         return __convert_CAudioError(e);
473     }
474
475     AUDIO_IO_LOGD("[%p] unprepared", handle);
476
477     return AUDIO_IO_ERROR_NONE;
478 }
479
480 int cpp_audio_in_pause(audio_in_h input) {
481     audio_io_s* handle = static_cast<audio_io_s*>(input);
482
483     try {
484         if (handle == NULL)
485             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
486                                    "Parameters are NULL input:%p", input);
487         assert(handle->audioIoHandle);
488         AUDIO_IO_LOGD("[%p]", handle);
489
490         handle->audioIoHandle->pause();
491     } catch (CAudioError& e) {
492         AUDIO_IO_LOGE("%s", e.getErrorMsg());
493         return __convert_CAudioError(e);
494     }
495
496     AUDIO_IO_LOGD("[%p] paused", handle);
497
498     return AUDIO_IO_ERROR_NONE;
499 }
500
501 int cpp_audio_in_resume(audio_in_h input) {
502     audio_io_s* handle = static_cast<audio_io_s*>(input);
503
504     try {
505         if (handle == NULL)
506             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
507                                    "Parameters are NULL input:%p", input);
508         assert(handle->audioIoHandle);
509         AUDIO_IO_LOGD("[%p]", handle);
510
511         handle->audioIoHandle->resume();
512     } catch (CAudioError& e) {
513         AUDIO_IO_LOGE("%s", e.getErrorMsg());
514         return __convert_CAudioError(e);
515     }
516
517     AUDIO_IO_LOGD("[%p] resumed", handle);
518
519     return AUDIO_IO_ERROR_NONE;
520 }
521
522 int cpp_audio_in_drain(audio_in_h input) {
523     audio_io_s* handle = static_cast<audio_io_s*>(input);
524
525     try {
526         if (handle == NULL)
527             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
528                                    "Parameters are NULL input:%p", input);
529         assert(handle->audioIoHandle);
530         AUDIO_IO_LOGD("[%p]", handle);
531
532         handle->audioIoHandle->drain();
533     } catch (CAudioError& e) {
534         AUDIO_IO_LOGE("%s", e.getErrorMsg());
535         return __convert_CAudioError(e);
536     }
537
538     AUDIO_IO_LOGD("[%p] drained", handle);
539
540     return AUDIO_IO_ERROR_NONE;
541 }
542
543 int cpp_audio_in_flush(audio_in_h input) {
544     audio_io_s* handle = static_cast<audio_io_s*>(input);
545
546     try {
547         if (handle == NULL)
548             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
549                                    "Parameters are NULL input:%p", input);
550         assert(handle->audioIoHandle);
551         AUDIO_IO_LOGD("[%p]", handle);
552
553         handle->audioIoHandle->flush();
554     } catch (CAudioError& e) {
555         AUDIO_IO_LOGE("%s", e.getErrorMsg());
556         return __convert_CAudioError(e);
557     }
558
559     AUDIO_IO_LOGD("[%p] flushed", handle);
560
561     return AUDIO_IO_ERROR_NONE;
562 }
563
564 int cpp_audio_in_read(audio_in_h input, void *buffer, unsigned int length) {
565     audio_io_s* handle = static_cast<audio_io_s*>(input);
566     int ret = 0;
567
568     try {
569         if (handle == NULL || buffer == NULL)
570             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
571                                    "Parameters are NULL input:%p, buffer:%p", input, buffer);
572         assert(handle->audioIoHandle);
573
574         CAudioInput* inputHandle = static_cast<CAudioInput*>(handle->audioIoHandle);
575         if (inputHandle == NULL) {
576             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
577         }
578
579         size_t readn = inputHandle->read(buffer, static_cast<size_t>(length));
580         ret = static_cast<int>(readn);
581 #ifdef _AUDIO_IO_DEBUG_TIMING_
582         AUDIO_IO_LOGD("readn:%d", readn);
583 #endif
584     } catch (CAudioError& e) {
585         AUDIO_IO_LOGE("%s", e.getErrorMsg());
586         return __convert_CAudioError(e);
587     }
588
589     return ret;
590 }
591
592 int cpp_audio_in_get_buffer_size(audio_in_h input, int *size) {
593     audio_io_s* handle = static_cast<audio_io_s*>(input);
594
595     try {
596         if (handle == NULL || size == NULL)
597             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
598                                    "Parameters are NULL input:%p, size:%p", input, size);
599         assert(handle->audioIoHandle);
600
601         CAudioIO* inputHandle = static_cast<CAudioInput*>(handle->audioIoHandle);
602         if (inputHandle == NULL) {
603             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
604         }
605         *size = inputHandle->getBufferSize();
606     } catch (CAudioError& e) {
607         AUDIO_IO_LOGE("%s", e.getErrorMsg());
608         return __convert_CAudioError(e);
609     }
610
611     return AUDIO_IO_ERROR_NONE;
612 }
613
614 int cpp_audio_in_get_sample_rate(audio_in_h input, int *sample_rate) {
615     audio_io_s* handle = static_cast<audio_io_s*>(input);
616
617     try {
618         if (handle == NULL || sample_rate == NULL)
619             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
620                                    "Parameters are NULL input:%p, sample_rate:%p", input, sample_rate);
621         assert(handle->audioIoHandle);
622
623         *sample_rate = handle->audioIoHandle->getAudioInfo().getSampleRate();
624     } catch (CAudioError& e) {
625         AUDIO_IO_LOGE("%s", e.getErrorMsg());
626         return __convert_CAudioError(e);
627     }
628
629     return AUDIO_IO_ERROR_NONE;
630 }
631
632 int cpp_audio_in_get_channel(audio_in_h input, audio_channel_e *channel) {
633     audio_io_s* handle = static_cast<audio_io_s*>(input);
634
635     try {
636         if (handle == NULL || channel == NULL)
637             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
638                                    "Parameters are NULL input:%p, channel:%p", input, channel);
639         assert(handle->audioIoHandle);
640
641         const CAudioInfo::EChannel srcChannel = handle->audioIoHandle->getAudioInfo().getChannel();
642         audio_channel_e dstChannel = AUDIO_CHANNEL_MONO;
643         __convert_audio_info_channel_2_channel(srcChannel, dstChannel);
644
645         *channel = dstChannel;
646     } catch (CAudioError& e) {
647         AUDIO_IO_LOGE("%s", e.getErrorMsg());
648         return __convert_CAudioError(e);
649     }
650
651     return AUDIO_IO_ERROR_NONE;
652 }
653
654 int cpp_audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type) {
655     audio_io_s* handle = static_cast<audio_io_s*>(input);
656
657     try {
658         if (handle == NULL || type == NULL)
659             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
660                                    "Parameters are NULL input:%p, type:%p", input, type);
661         assert(handle->audioIoHandle);
662
663         const CAudioInfo::ESampleType srcSampleType = handle->audioIoHandle->getAudioInfo().getSampleType();
664         audio_sample_type_e dstSampleType = AUDIO_SAMPLE_TYPE_U8;
665         __convert_audio_info_sample_type_2_sample_type(srcSampleType, dstSampleType);
666
667         *type = dstSampleType;
668     } catch (CAudioError& e) {
669         AUDIO_IO_LOGE("%s", e.getErrorMsg());
670         return __convert_CAudioError(e);
671     }
672
673     return AUDIO_IO_ERROR_NONE;
674 }
675
676 int cpp_audio_in_set_interrupted_cb(audio_in_h input, audio_io_interrupted_cb callback, void *user_data) {
677     return AUDIO_IO_ERROR_NOT_SUPPORTED;
678 }
679
680 int cpp_audio_in_unset_interrupted_cb(audio_in_h input) {
681     return AUDIO_IO_ERROR_NOT_SUPPORTED;
682 }
683
684 int cpp_audio_in_ignore_session(audio_in_h input) {
685     return AUDIO_IO_ERROR_NOT_SUPPORTED;
686 }
687
688 static void __stream_cb_internal(size_t nbytes, void *user_data) {
689     audio_io_s* audioIo = static_cast<audio_io_s*>(user_data);
690     assert(audioIo);
691
692     if (audioIo->stream_callback.onStream)
693         audioIo->stream_callback.onStream(audioIo, nbytes, audioIo->stream_callback.user_data);
694 }
695
696 static void __state_changed_cb_internal(CAudioInfo::EAudioIOState state,
697                                         CAudioInfo::EAudioIOState state_prev,
698                                         bool by_policy,
699                                         void *user_data) {
700     audio_io_s* audioIo = static_cast<audio_io_s*>(user_data);
701     assert(audioIo);
702
703     if (audioIo->state_changed_callback.onStateChanged)
704         audioIo->state_changed_callback.onStateChanged(audioIo, __convert_state_type(state_prev),
705                                                        __convert_state_type(state), by_policy,
706                                                        audioIo->state_changed_callback.user_data);
707 }
708
709 int cpp_audio_in_set_stream_cb(audio_in_h input, audio_in_stream_cb callback, void* user_data) {
710     audio_io_s* handle = static_cast<audio_io_s*>(input);
711
712     try {
713         if (handle == NULL || callback == NULL)
714             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
715                                    "Parameters are NULL input:%p, callback:%p", input, callback);
716         assert(handle->audioIoHandle);
717         AUDIO_IO_LOGD("[%p], callback:[%p], user_data:[%p]", handle, callback, user_data);
718
719         handle->stream_callback.onStream = callback;
720         handle->stream_callback.user_data = user_data;
721
722         CAudioIO::SStreamCallback cb = handle->audioIoHandle->getStreamCallback();
723         cb.mUserData = static_cast<void*>(handle);
724         cb.onStream  = __stream_cb_internal;
725
726         handle->audioIoHandle->setStreamCallback(cb);
727     } catch (CAudioError& e) {
728         AUDIO_IO_LOGE("%s", e.getErrorMsg());
729         return __convert_CAudioError(e);
730     }
731
732     AUDIO_IO_LOGD("[%p] done", handle);
733
734     return AUDIO_IO_ERROR_NONE;
735 }
736
737 int cpp_audio_in_unset_stream_cb(audio_in_h input) {
738     audio_io_s* handle = static_cast<audio_io_s*>(input);
739
740     try {
741         if (handle == NULL)
742             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
743                                    "Parameters are NULL input:%p", input);
744         assert(handle->audioIoHandle);
745         AUDIO_IO_LOGD("[%p]", handle);
746
747         handle->stream_callback.onStream = NULL;
748         handle->stream_callback.user_data = NULL;
749
750         CAudioIO::SStreamCallback cb = handle->audioIoHandle->getStreamCallback();
751         cb.mUserData = NULL;
752         cb.onStream  = NULL;
753
754         handle->audioIoHandle->setStreamCallback(cb);
755     } catch (CAudioError& e) {
756         AUDIO_IO_LOGE("%s", e.getErrorMsg());
757         return __convert_CAudioError(e);
758     }
759
760     AUDIO_IO_LOGD("[%p] done", handle);
761
762     return AUDIO_IO_ERROR_NONE;
763 }
764
765 int cpp_audio_in_peek(audio_in_h input, const void **buffer, unsigned int *length) {
766     audio_io_s* handle = static_cast<audio_io_s*>(input);
767     size_t _length = 0;
768
769     try {
770         if (handle == NULL || buffer == NULL)
771             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
772                                    "Parameters are NULL input:%p, buffer:%p", input, buffer);
773
774         CAudioInput* inputHandle = static_cast<CAudioInput*>(handle->audioIoHandle);
775         if (inputHandle == NULL)
776             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
777
778         inputHandle->peek(buffer, &_length);
779     } catch (CAudioError& e) {
780         AUDIO_IO_LOGE("%s", e.getErrorMsg());
781         return __convert_CAudioError(e);
782     }
783
784     *length = (unsigned int)_length;
785
786     return AUDIO_IO_ERROR_NONE;
787 }
788
789 int cpp_audio_in_drop(audio_in_h input) {
790     audio_io_s* handle = static_cast<audio_io_s*>(input);
791
792     try {
793         if (handle == NULL)
794             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
795                                    "Parameters are NULL input:%p", input);
796
797         CAudioInput* inputHandle = static_cast<CAudioInput*>(handle->audioIoHandle);
798         if (inputHandle == NULL)
799             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
800
801         inputHandle->drop();
802     } catch (CAudioError& e) {
803         AUDIO_IO_LOGE("%s", e.getErrorMsg());
804         return __convert_CAudioError(e);
805     }
806
807     return AUDIO_IO_ERROR_NONE;
808 }
809
810 int cpp_audio_in_set_state_changed_cb(audio_in_h input, audio_in_state_changed_cb callback, void* user_data) {
811     audio_io_s* handle = static_cast<audio_io_s*>(input);
812
813     try {
814         if (handle == NULL || callback == NULL)
815             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
816                                    "Parameters are NULL input:%p, callback:%p", input, callback);
817         assert(handle->audioIoHandle);
818         AUDIO_IO_LOGD("[%p], callback:[%p], user_data:[%p]", handle, callback, user_data);
819
820         handle->state_changed_callback.onStateChanged = callback;
821         handle->state_changed_callback.user_data = user_data;
822
823         CAudioIO::SStateChangedCallback cb = handle->audioIoHandle->getStateChangedCallback();
824         cb.mUserData = static_cast<void*>(handle);
825         cb.onStateChanged = __state_changed_cb_internal;
826
827         handle->audioIoHandle->setStateChangedCallback(cb);
828     } catch (CAudioError& e) {
829         AUDIO_IO_LOGE("%s", e.getErrorMsg());
830         return __convert_CAudioError(e);
831     }
832
833     AUDIO_IO_LOGD("[%p] done", handle);
834
835     return AUDIO_IO_ERROR_NONE;
836 }
837
838 int cpp_audio_in_unset_state_changed_cb(audio_in_h input) {
839     audio_io_s* handle = static_cast<audio_io_s*>(input);
840
841     try {
842         if (handle == NULL)
843             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
844                                    "Parameters are NULL output:%p", input);
845         assert(handle->audioIoHandle);
846         AUDIO_IO_LOGD("[%p]", handle);
847
848         handle->state_changed_callback.onStateChanged = NULL;
849         handle->state_changed_callback.user_data = NULL;
850
851         CAudioIO::SStateChangedCallback cb = handle->audioIoHandle->getStateChangedCallback();
852         cb.mUserData = NULL;
853         cb.onStateChanged  = NULL;
854
855         handle->audioIoHandle->setStateChangedCallback(cb);
856     } catch (CAudioError& e) {
857         AUDIO_IO_LOGE("%s", e.getErrorMsg());
858         return __convert_CAudioError(e);
859     }
860
861     AUDIO_IO_LOGD("[%p] done", handle);
862
863     return AUDIO_IO_ERROR_NONE;
864 }
865
866
867 /**
868  * Audio Out
869  */
870 int cpp_audio_out_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h *output) {
871     return AUDIO_IO_ERROR_NOT_SUPPORTED;
872 }
873
874 int cpp_audio_out_create_new(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_out_h *output) {
875     audio_io_s* handle = NULL;
876     try {
877         if (output == NULL)
878             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
879                                    "Parameters are NULL output:%p", output);
880
881         __check_audio_param(sample_rate, channel, type, SOUND_TYPE_SYSTEM /*default check */);
882
883         AUDIO_IO_LOGD("samplerate:[%d] channel:[0x%x] sample_type:[0x%x]", sample_rate, channel, type);
884         CAudioInfo audioInfo = __generate_audio_output_info(sample_rate, channel, type, SOUND_TYPE_MEDIA);
885
886         handle = new audio_io_s;
887         handle->audioIoHandle = new CAudioOutput(audioInfo);
888         handle->audioIoHandle->initialize();
889
890         AUDIO_IO_LOGD("[%p] created", handle);
891         *output = handle;
892     } catch (CAudioError& e) {
893         AUDIO_IO_LOGE("%s", e.getErrorMsg());
894         __handle_safe_free(handle, (void *)output, true);
895         return __convert_CAudioError(e);
896     } catch (const std::bad_alloc&) {
897         CAudioError e = CAudioError::EError::ERROR_OUT_OF_MEMORY;
898         AUDIO_IO_LOGE("Failed to allocate handle");
899         __handle_safe_free(handle, (void *)output, true);
900         return __convert_CAudioError(e);
901     }
902
903     return AUDIO_IO_ERROR_NONE;
904 }
905
906 int cpp_audio_out_destroy(audio_out_h output) {
907     audio_io_s* handle = static_cast<audio_io_s*>(output);
908
909     try {
910         if (handle == NULL)
911             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
912                                    "Parameter is NULL output:%p", output);
913         assert(handle->audioIoHandle);
914         AUDIO_IO_LOGD("[%p]", handle);
915
916         /* Internal unprepare for backward compatibility */
917         handle->audioIoHandle->unprepare();
918
919         SAFE_FINALIZE(handle->audioIoHandle);
920         SAFE_DELETE(handle->audioIoHandle);
921         SAFE_DELETE(handle);
922     } catch (CAudioError& e) {
923         AUDIO_IO_LOGE("%s", e.getErrorMsg());
924         return __convert_CAudioError(e);
925     }
926
927     AUDIO_IO_LOGD("destroyed");
928
929     return AUDIO_IO_ERROR_NONE;
930 }
931
932 int cpp_audio_out_set_sound_stream_info(audio_out_h output, sound_stream_info_h stream_info) {
933     audio_io_s* handle = static_cast<audio_io_s*>(output);
934
935     try {
936         if (handle == NULL || stream_info == NULL)
937             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
938                                    "Parameters are NULL output:%p, stream_info:%p", output, stream_info);
939         assert(handle->audioIoHandle);
940         AUDIO_IO_LOGD("[%p], stream_info:[%p]", handle, stream_info);
941
942         handle->audioIoHandle->setStreamInfo(stream_info);
943     } catch (CAudioError& e) {
944         AUDIO_IO_LOGE("%s", e.getErrorMsg());
945         return __convert_CAudioError(e);
946     }
947
948     AUDIO_IO_LOGD("[%p] done", handle);
949
950     return AUDIO_IO_ERROR_NONE;
951 }
952
953 int cpp_audio_out_prepare(audio_out_h output) {
954     audio_io_s* handle = static_cast<audio_io_s*>(output);
955
956     try {
957         if (handle == NULL)
958             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
959                                    "Parameter is NULL output:%p", output);
960         assert(handle->audioIoHandle);
961         AUDIO_IO_LOGD("[%p]", handle);
962
963         handle->audioIoHandle->prepare();
964     } catch (CAudioError& e) {
965         AUDIO_IO_LOGE("%s", e.getErrorMsg());
966         return __convert_CAudioError(e);
967     }
968
969     AUDIO_IO_LOGD("[%p] prepared", handle);
970
971     return AUDIO_IO_ERROR_NONE;
972 }
973
974 int cpp_audio_out_unprepare(audio_out_h output) {
975     audio_io_s* handle = static_cast<audio_io_s*>(output);
976
977     try {
978         if (handle == NULL)
979             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
980                                    "Parameter is NULL output:%p", output);
981         assert(handle->audioIoHandle);
982         AUDIO_IO_LOGD("[%p]", handle);
983
984         handle->audioIoHandle->unprepare();
985     } catch (CAudioError& e) {
986         AUDIO_IO_LOGE("%s", e.getErrorMsg());
987         return __convert_CAudioError(e);
988     }
989
990     AUDIO_IO_LOGD("[%p] unprepared", handle);
991
992     return AUDIO_IO_ERROR_NONE;
993 }
994
995 int cpp_audio_out_pause(audio_out_h output) {
996     audio_io_s* handle = static_cast<audio_io_s*>(output);
997
998     try {
999         if (handle == NULL)
1000             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1001                                    "Parameter is NULL output:%p", output);
1002         assert(handle->audioIoHandle);
1003         AUDIO_IO_LOGD("[%p]", handle);
1004
1005         handle->audioIoHandle->pause();
1006     } catch (CAudioError& e) {
1007         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1008         return __convert_CAudioError(e);
1009     }
1010
1011     AUDIO_IO_LOGD("[%p] paused", handle);
1012
1013     return AUDIO_IO_ERROR_NONE;
1014 }
1015
1016 int cpp_audio_out_resume(audio_out_h output) {
1017     audio_io_s* handle = static_cast<audio_io_s*>(output);
1018
1019     try {
1020         if (handle == NULL)
1021             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1022                                    "Parameter is NULL output:%p", output);
1023         assert(handle->audioIoHandle);
1024         AUDIO_IO_LOGD("[%p]", handle);
1025
1026         handle->audioIoHandle->resume();
1027     } catch (CAudioError& e) {
1028         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1029         return __convert_CAudioError(e);
1030     }
1031
1032     AUDIO_IO_LOGD("[%p] resumed", handle);
1033
1034     return AUDIO_IO_ERROR_NONE;
1035 }
1036
1037 int cpp_audio_out_drain(audio_out_h output) {
1038     audio_io_s* handle = static_cast<audio_io_s*>(output);
1039
1040     try {
1041         if (handle == NULL)
1042             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1043                                    "Parameter is NULL output:%p", output);
1044         assert(handle->audioIoHandle);
1045         AUDIO_IO_LOGD("[%p]", handle);
1046
1047         handle->audioIoHandle->drain();
1048     } catch (CAudioError& e) {
1049         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1050         return __convert_CAudioError(e);
1051     }
1052
1053     AUDIO_IO_LOGD("[%p] drained", handle);
1054
1055     return AUDIO_IO_ERROR_NONE;
1056 }
1057
1058 int cpp_audio_out_flush(audio_out_h output) {
1059     audio_io_s* handle = static_cast<audio_io_s*>(output);
1060
1061     try {
1062         if (handle == NULL)
1063             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1064                                    "Parameter is NULL output:%p", output);
1065         assert(handle->audioIoHandle);
1066         AUDIO_IO_LOGD("[%p]", handle);
1067
1068         handle->audioIoHandle->flush();
1069     } catch (CAudioError& e) {
1070         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1071         return __convert_CAudioError(e);
1072     }
1073
1074     AUDIO_IO_LOGD("[%p] flushed", handle);
1075
1076     return AUDIO_IO_ERROR_NONE;
1077 }
1078
1079 int cpp_audio_out_write(audio_out_h output, void *buffer, unsigned int length) {
1080     audio_io_s* handle = static_cast<audio_io_s*>(output);
1081     int ret = 0;
1082
1083     try {
1084         if (handle == NULL || buffer == NULL)
1085             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1086                                    "Parameter is NULL output:%p, buffer:%p", output, buffer);
1087         assert(handle->audioIoHandle);
1088
1089         CAudioOutput* outputHandle = static_cast<CAudioOutput*>(handle->audioIoHandle);
1090         if (outputHandle == NULL)
1091             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
1092
1093         size_t written = outputHandle->write(buffer, static_cast<size_t>(length));
1094         ret = static_cast<int>(written);
1095 #ifdef _AUDIO_IO_DEBUG_TIMING_
1096         AUDIO_IO_LOGD("written:%d", written);
1097 #endif
1098     } catch (CAudioError& e) {
1099         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1100         return __convert_CAudioError(e);
1101     }
1102
1103     return ret;
1104 }
1105
1106 int cpp_audio_out_get_buffer_size(audio_out_h output, int *size) {
1107     audio_io_s* handle = static_cast<audio_io_s*>(output);
1108
1109     try {
1110         if (handle == NULL || size == NULL)
1111             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1112                                    "Parameters are NULL output:%p, size:%p", output, size);
1113         assert(handle->audioIoHandle);
1114
1115         CAudioOutput* outputHandle = static_cast<CAudioOutput*>(handle->audioIoHandle);
1116         if (outputHandle == NULL)
1117             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL");
1118
1119         *size = outputHandle->getBufferSize();
1120     } catch (CAudioError& e) {
1121         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1122         return __convert_CAudioError(e);
1123     }
1124
1125     return AUDIO_IO_ERROR_NONE;
1126 }
1127
1128 int cpp_audio_out_get_sample_rate(audio_out_h output, int *sample_rate) {
1129     audio_io_s* handle = static_cast<audio_io_s*>(output);
1130
1131     try {
1132         if (handle == NULL || sample_rate == NULL)
1133             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1134                                    "Parameters are NULL output:%p, sample_rate:%p", output, sample_rate);
1135         assert(handle->audioIoHandle);
1136
1137         *sample_rate = handle->audioIoHandle->getAudioInfo().getSampleRate();
1138     } catch (CAudioError& e) {
1139         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1140         return __convert_CAudioError(e);
1141     }
1142
1143     return AUDIO_IO_ERROR_NONE;
1144 }
1145
1146 int cpp_audio_out_get_channel(audio_out_h output, audio_channel_e *channel) {
1147     audio_io_s* handle = static_cast<audio_io_s*>(output);
1148
1149     try {
1150         if (handle == NULL || channel == NULL)
1151             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1152                                    "Parameters are NULL output:%p, channel:%p", output, channel);
1153         assert(handle->audioIoHandle);
1154
1155         const CAudioInfo::EChannel srcChannel = handle->audioIoHandle->getAudioInfo().getChannel();
1156         audio_channel_e dstChannel = AUDIO_CHANNEL_MONO;
1157         __convert_audio_info_channel_2_channel(srcChannel, dstChannel);
1158
1159         *channel = dstChannel;
1160     } catch (CAudioError& e) {
1161         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1162         return __convert_CAudioError(e);
1163     }
1164
1165     return AUDIO_IO_ERROR_NONE;
1166 }
1167
1168 int cpp_audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type) {
1169     audio_io_s* handle = static_cast<audio_io_s*>(output);
1170
1171     try {
1172         if (handle == NULL || type == NULL)
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         const CAudioInfo::ESampleType srcSampleType = handle->audioIoHandle->getAudioInfo().getSampleType();
1178         audio_sample_type_e 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     audio_io_s* handle = static_cast<audio_io_s*>(output);
1192
1193     try {
1194         if (handle == NULL || type == NULL)
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         const CAudioInfo::EAudioType srcAudioType = handle->audioIoHandle->getAudioInfo().getAudioType();
1200         sound_type_e 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_interrupted_cb(audio_out_h output, audio_io_interrupted_cb callback, void *user_data) {
1213     return AUDIO_IO_ERROR_NOT_SUPPORTED;
1214 }
1215
1216 int cpp_audio_out_unset_interrupted_cb(audio_out_h output) {
1217     return AUDIO_IO_ERROR_NOT_SUPPORTED;
1218 }
1219
1220 int cpp_audio_out_ignore_session(audio_out_h output) {
1221     return AUDIO_IO_ERROR_NOT_SUPPORTED;
1222 }
1223
1224 int cpp_audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback, void* user_data) {
1225     audio_io_s* handle = static_cast<audio_io_s*>(output);
1226
1227     try {
1228         if (handle == NULL || callback == NULL)
1229             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1230                                    "Parameters are NULL output:%p, callback:%p", output, callback);
1231         assert(handle->audioIoHandle);
1232         AUDIO_IO_LOGD("[%p], callback:[%p], user_data:[%p]", handle, callback, user_data);
1233
1234         handle->stream_callback.onStream = callback;
1235         handle->stream_callback.user_data = user_data;
1236
1237         CAudioIO::SStreamCallback cb = handle->audioIoHandle->getStreamCallback();
1238         cb.mUserData = static_cast<void*>(handle);
1239         cb.onStream = __stream_cb_internal;
1240
1241         handle->audioIoHandle->setStreamCallback(cb);
1242     } catch (CAudioError& e) {
1243         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1244         return __convert_CAudioError(e);
1245     }
1246
1247     AUDIO_IO_LOGD("[%p] done", handle);
1248
1249     return AUDIO_IO_ERROR_NONE;
1250 }
1251
1252 int cpp_audio_out_unset_stream_cb(audio_out_h output) {
1253     audio_io_s* handle = static_cast<audio_io_s*>(output);
1254
1255     try {
1256         if (handle == NULL)
1257             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1258                                    "Parameters are NULL output:%p", output);
1259         assert(handle->audioIoHandle);
1260         AUDIO_IO_LOGD("[%p]", handle);
1261
1262         handle->stream_callback.onStream = NULL;
1263         handle->stream_callback.user_data = NULL;
1264
1265         CAudioIO::SStreamCallback cb = handle->audioIoHandle->getStreamCallback();
1266         cb.mUserData = NULL;
1267         cb.onStream = NULL;
1268
1269         handle->audioIoHandle->setStreamCallback(cb);
1270     } catch (CAudioError& e) {
1271         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1272         return __convert_CAudioError(e);
1273     }
1274
1275     AUDIO_IO_LOGD("[%p] done", handle);
1276
1277     return AUDIO_IO_ERROR_NONE;
1278 }
1279
1280 int cpp_audio_out_set_state_changed_cb(audio_out_h output, audio_in_state_changed_cb callback, void* user_data) {
1281     audio_io_s* handle = static_cast<audio_io_s*>(output);
1282
1283     try {
1284         if (handle == NULL || callback == NULL)
1285             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1286                                    "Parameters are NULL output:%p, callback:%p", output, callback);
1287         assert(handle->audioIoHandle);
1288         AUDIO_IO_LOGD("[%p], callback:[%p], user_data:[%p]", handle, callback, user_data);
1289
1290         handle->state_changed_callback.onStateChanged = callback;
1291         handle->state_changed_callback.user_data = user_data;
1292
1293         CAudioIO::SStateChangedCallback cb = handle->audioIoHandle->getStateChangedCallback();
1294         cb.mUserData = static_cast<void*>(handle);
1295         cb.onStateChanged = __state_changed_cb_internal;
1296
1297         handle->audioIoHandle->setStateChangedCallback(cb);
1298     } catch (CAudioError& e) {
1299         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1300         return __convert_CAudioError(e);
1301     }
1302
1303     AUDIO_IO_LOGD("[%p] done", handle);
1304
1305     return AUDIO_IO_ERROR_NONE;
1306 }
1307
1308 int cpp_audio_out_unset_state_changed_cb(audio_out_h output) {
1309     audio_io_s* handle = static_cast<audio_io_s*>(output);
1310
1311     try {
1312         if (handle == NULL)
1313             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT,
1314                                    "Parameters are NULL output:%p", output);
1315         assert(handle->audioIoHandle);
1316         AUDIO_IO_LOGD("[%p]", handle);
1317
1318         handle->state_changed_callback.onStateChanged = NULL;
1319         handle->state_changed_callback.user_data = NULL;
1320
1321         CAudioIO::SStateChangedCallback cb = handle->audioIoHandle->getStateChangedCallback();
1322         cb.mUserData = NULL;
1323         cb.onStateChanged = NULL;
1324
1325         handle->audioIoHandle->setStateChangedCallback(cb);
1326     } catch (CAudioError& e) {
1327         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1328         return __convert_CAudioError(e);
1329     }
1330
1331     AUDIO_IO_LOGD("[%p] done", handle);
1332
1333     return AUDIO_IO_ERROR_NONE;
1334 }