Check invalid parameter and operation
[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 "audio_io.h"
19 #include "cpp_audio_io.h"
20 #include "CAudioIODef.h"
21 #include <sound_manager_internal.h>
22
23
24 using namespace std;
25 using namespace tizen_media_audio;
26
27
28 /**
29  * Defines Structures
30  * type : struct
31  * Name : audio_io_interrupted_cb_s
32  * Declaration : Keeps user callback pointer and user data for delivering an interrupt event
33  */
34 typedef struct audio_io_interrupted_cb_s {
35     void* user_data;
36     audio_io_interrupted_cb onInterrupt;
37
38     audio_io_interrupted_cb_s() : user_data(NULL), onInterrupt(NULL)
39     {/* Empty Body */}
40 }   audio_io_interrupted_cb_s;
41
42 /**
43  * Defines Structures
44  * type : struct
45  * Name : audio_io_stream_cb_s
46  * Declaration : Keeps user callback pointer and user data for delivering an stream event
47  */
48 typedef struct audio_io_stream_cb_s {
49     void* user_data;
50     audio_in_stream_cb onStream;
51
52     audio_io_stream_cb_s() : user_data(NULL), onStream(NULL)
53     {/* Empty Body */}
54 }   audio_io_stream_cb_s;
55
56 /**
57  * Defines Structures
58  * type : struct
59  * Name : audio_io_state_changed_cb_s
60  * Declaration : Keeps user callback pointer and user data for delivering an state changed event
61  */
62 typedef struct audio_io_state_changed_cb_s {
63     void* user_data;
64     audio_in_state_changed_cb onStateChanged;
65
66     audio_io_state_changed_cb_s() : user_data(NULL), onStateChanged(NULL)
67     {/* Empty Body */}
68 }   audio_io_state_changed_cb_s;
69
70 /**
71  * Defines Structures
72  * type : struct
73  * Name : audio_io_s
74  * Declaration : An handle of AudioIO
75  * The handle has two struct for user callback
76  * And the handle has a pointer of private audioIO object
77  * The CAudioIO is a abstract class object about Input and Output
78  */
79 typedef struct audio_io_s {
80     CAudioIO*                    audioIoHandle;
81     audio_io_interrupted_cb_s    interrupt_callback;
82     audio_io_stream_cb_s         stream_callback;
83     audio_io_state_changed_cb_s  state_changed_callback;
84
85     audio_io_s() : audioIoHandle(NULL)
86     {/* Empty Body */}
87 }   audio_io_s;
88
89
90 /**
91  * Internal functions
92  */
93 static audio_io_error_e _convert_CAudioError(CAudioError& error) {
94     audio_io_error_e    ret = AUDIO_IO_ERROR_NONE;
95     CAudioError::EError err = error.getError();
96
97     switch(err)
98     {
99     case CAudioError::ERROR_NONE:
100         ret = AUDIO_IO_ERROR_NONE;
101         break;
102
103     case CAudioError::ERROR_INVALID_ARGUMENT:
104     case CAudioError::ERROR_INVALID_HANDLE:
105     case CAudioError::ERROR_INVALID_SAMPLERATE:
106     case CAudioError::ERROR_INVALID_CHANNEL:
107     case CAudioError::ERROR_INVALID_FORMAT:
108         ret = AUDIO_IO_ERROR_INVALID_PARAMETER;
109         break;
110
111     case CAudioError::ERROR_DEVICE_NOT_OPENED:
112         ret = AUDIO_IO_ERROR_DEVICE_NOT_OPENED;
113         break;
114
115     case CAudioError::ERROR_DEVICE_NOT_CLOSED:
116         ret = AUDIO_IO_ERROR_DEVICE_NOT_CLOSED;
117         break;
118
119     case CAudioError::ERROR_PERMISSION_DENIED:
120         ret = AUDIO_IO_ERROR_PERMISSION_DENIED;
121         break;
122
123     case CAudioError::ERROR_NOT_SUPPORTED:
124         ret = AUDIO_IO_ERROR_NOT_SUPPORTED;
125         break;
126
127     case CAudioError::ERROR_MAX:
128     case CAudioError::ERROR_INTERNAL_OPERATION:
129     case CAudioError::ERROR_NOT_INITIALIZED:
130     case CAudioError::ERROR_FAILED_OPERATION:
131     case CAudioError::ERROR_INVALID_OPERATION:
132         ret = AUDIO_IO_ERROR_INVALID_OPERATION;
133         break;
134
135     case CAudioError::ERROR_OUT_OF_MEMORY:
136     case CAudioError::ERROR_INVALID_POINTER:
137         ret = AUDIO_IO_ERROR_INVALID_BUFFER;
138         break;
139
140     case CAudioError::ERROR_POLICY_BLOCKED:
141     case CAudioError::ERROR_POLICY_INTERRUPTED:
142     case CAudioError::ERROR_POLICY_DUPLICATED:
143         ret = AUDIO_IO_ERROR_SOUND_POLICY;
144         break;
145     }
146     return ret;
147
148 }
149
150 static void _convert_channel_2_audio_info_channel(const audio_channel_e& src_channel, CAudioInfo::EChannel& dst_channel) {
151     switch (src_channel) {
152     case AUDIO_CHANNEL_MONO:
153         dst_channel = CAudioInfo::CHANNEL_MONO;
154         break;
155     case AUDIO_CHANNEL_STEREO:
156         dst_channel = CAudioInfo::CHANNEL_STEREO;
157         break;
158     default:
159         dst_channel = CAudioInfo::CHANNEL_MONO;
160     }
161 }
162
163 static void _convert_audio_info_channel_2_channel(const CAudioInfo::EChannel& src_channel, audio_channel_e& dst_channel) {
164     switch (src_channel) {
165     case CAudioInfo::CHANNEL_MONO:
166         dst_channel = AUDIO_CHANNEL_MONO;
167         break;
168     case CAudioInfo::CHANNEL_STEREO:
169         dst_channel = AUDIO_CHANNEL_STEREO;
170         break;
171     default:
172         dst_channel = AUDIO_CHANNEL_MONO;
173     }
174 }
175
176 static void _convert_sample_type_2_audio_info_sample_type(const audio_sample_type_e& src_type, CAudioInfo::ESampleType& dst_type) {
177     switch (src_type) {
178     case AUDIO_SAMPLE_TYPE_U8:
179         dst_type = CAudioInfo::SAMPLE_TYPE_U8;
180         break;
181     case AUDIO_SAMPLE_TYPE_S16_LE:
182         dst_type = CAudioInfo::SAMPLE_TYPE_S16_LE;
183         break;
184     default:
185         dst_type = CAudioInfo::SAMPLE_TYPE_U8;
186     }
187 }
188
189 static void _convert_audio_info_sample_type_2_sample_type(const CAudioInfo::ESampleType& src_type, audio_sample_type_e& dst_type) {
190     switch (src_type) {
191     case CAudioInfo::SAMPLE_TYPE_U8:
192         dst_type = AUDIO_SAMPLE_TYPE_U8;
193         break;
194     case CAudioInfo::SAMPLE_TYPE_S16_LE:
195         dst_type = AUDIO_SAMPLE_TYPE_S16_LE;
196         break;
197     default:
198         dst_type = AUDIO_SAMPLE_TYPE_U8;
199     }
200 }
201
202 static void _convert_sound_type_2_audio_info_audio_type(const sound_type_e& src_type, CAudioInfo::EAudioType& dst_type) {
203     switch (src_type) {
204         case SOUND_TYPE_SYSTEM:
205             dst_type = CAudioInfo::AUDIO_OUT_TYPE_SYSTEM;
206             break;
207         case SOUND_TYPE_NOTIFICATION:
208             dst_type = CAudioInfo::AUDIO_OUT_TYPE_NOTIFICATION;
209             break;
210         case SOUND_TYPE_ALARM:
211             dst_type = CAudioInfo::AUDIO_OUT_TYPE_ALARM;
212             break;
213         case SOUND_TYPE_RINGTONE:
214             dst_type = CAudioInfo::AUDIO_OUT_TYPE_RINGTONE_VOIP;
215             break;
216         case SOUND_TYPE_MEDIA:
217             dst_type = CAudioInfo::AUDIO_OUT_TYPE_MEDIA;
218             break;
219         case SOUND_TYPE_CALL:
220             dst_type = CAudioInfo::AUDIO_OUT_TYPE_SYSTEM;
221             break;
222         case SOUND_TYPE_VOIP:
223             dst_type = CAudioInfo::AUDIO_OUT_TYPE_VOIP;
224             break;
225         case SOUND_TYPE_VOICE:
226             dst_type = CAudioInfo::AUDIO_OUT_TYPE_VOICE_INFORMATION;
227             break;
228         default:
229             dst_type = CAudioInfo::AUDIO_OUT_TYPE_MEDIA;
230             break;
231         }
232 }
233
234 static void _convert_audio_info_audio_type_2_sound_type(const CAudioInfo::EAudioType& src_type, sound_type_e& dst_type) {
235     switch (src_type) {
236         case CAudioInfo::AUDIO_OUT_TYPE_MEDIA:
237             dst_type = SOUND_TYPE_MEDIA;
238             break;
239         case CAudioInfo::AUDIO_OUT_TYPE_SYSTEM:
240             dst_type = SOUND_TYPE_SYSTEM;
241             break;
242         case CAudioInfo::AUDIO_OUT_TYPE_ALARM:
243             dst_type = SOUND_TYPE_ALARM;
244             break;
245         case CAudioInfo::AUDIO_OUT_TYPE_NOTIFICATION:
246         case CAudioInfo::AUDIO_OUT_TYPE_EMERGENCY:
247             dst_type = SOUND_TYPE_NOTIFICATION;
248             break;
249         case CAudioInfo::AUDIO_OUT_TYPE_VOICE_INFORMATION:
250         case CAudioInfo::AUDIO_OUT_TYPE_VOICE_RECOGNITION:
251             dst_type = SOUND_TYPE_VOICE;
252             break;
253         case CAudioInfo::AUDIO_OUT_TYPE_RINGTONE_VOIP:
254             dst_type = SOUND_TYPE_RINGTONE;
255             break;
256         case CAudioInfo::AUDIO_OUT_TYPE_VOIP:
257             dst_type = SOUND_TYPE_VOIP;
258             break;
259         default:
260             dst_type = SOUND_TYPE_MEDIA;
261             break;
262         }
263 }
264
265 static audio_io_state_e _convert_state_type(const CAudioInfo::EAudioIOState src_state) {
266     audio_io_state_e dst_state;
267     switch (src_state) {
268     case CAudioInfo::AUDIO_IO_STATE_NONE:
269         dst_state = AUDIO_IO_STATE_IDLE;
270         break;
271     case CAudioInfo::AUDIO_IO_STATE_IDLE:
272         dst_state = AUDIO_IO_STATE_IDLE;
273         break;
274     case CAudioInfo::AUDIO_IO_STATE_RUNNING:
275         dst_state = AUDIO_IO_STATE_RUNNING;
276         break;
277     case CAudioInfo::AUDIO_IO_STATE_PAUSED:
278         dst_state = AUDIO_IO_STATE_PAUSED;
279         break;
280     default:
281         dst_state = AUDIO_IO_STATE_IDLE;
282     }
283     return dst_state;
284 }
285
286 static void _check_audio_param(int sample_rate, audio_channel_e channel, audio_sample_type_e type)  throw (CAudioError) {
287
288     if (sample_rate < 0) {
289         THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Invalid sample rate :%d", sample_rate);
290     }
291
292     if (channel != AUDIO_CHANNEL_MONO && channel != AUDIO_CHANNEL_STEREO) {
293         THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Invalid channel :%d", channel);
294     }
295
296     if (type != AUDIO_SAMPLE_TYPE_U8 && type != AUDIO_SAMPLE_TYPE_S16_LE) {
297         THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Invalid sample type :%d", type);
298     }
299 }
300
301 static void _check_audio_param(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type) throw (CAudioError) {
302
303     _check_audio_param(sample_rate, channel, type);
304
305     if (sound_type < SOUND_TYPE_SYSTEM || sound_type > SOUND_TYPE_VOICE) {
306         THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Invalid sound type : %d", sound_type);
307     }
308 }
309
310 static CAudioInfo _generate_audio_input_info(int sampleRate, audio_channel_e channel, audio_sample_type_e sample_type) throw (CAudioError) {
311     CAudioInfo::EChannel     dstChannel;
312     CAudioInfo::ESampleType dstSampleType;
313     CAudioInfo::EAudioType  dstAudioType = CAudioInfo::AUDIO_IN_TYPE_MEDIA;
314
315     _convert_channel_2_audio_info_channel(channel, dstChannel);
316     _convert_sample_type_2_audio_info_sample_type(sample_type, dstSampleType);
317
318     return CAudioInfo(sampleRate, dstChannel, dstSampleType, dstAudioType, -1);
319 }
320
321 static CAudioInfo _generate_audio_input_loopback_info(int sampleRate, audio_channel_e channel, audio_sample_type_e sample_type) throw (CAudioError) {
322     CAudioInfo::EChannel     dstChannel;
323     CAudioInfo::ESampleType dstSampleType;
324     CAudioInfo::EAudioType  dstAudioType = CAudioInfo::AUDIO_IN_TYPE_LOOPBACK;
325
326     _convert_channel_2_audio_info_channel(channel, dstChannel);
327     _convert_sample_type_2_audio_info_sample_type(sample_type, dstSampleType);
328
329     return CAudioInfo(sampleRate, dstChannel, dstSampleType, dstAudioType, -1);
330 }
331
332 static CAudioInfo _generate_audio_output_info(int sampleRate, audio_channel_e channel, audio_sample_type_e sample_type, sound_type_e sound_type) throw (CAudioError) {
333     CAudioInfo::EChannel     dstChannel;
334     CAudioInfo::ESampleType dstSampleType;
335     CAudioInfo::EAudioType  dstAudioType;
336
337     _convert_channel_2_audio_info_channel(channel, dstChannel);
338     _convert_sample_type_2_audio_info_sample_type(sample_type, dstSampleType);
339     _convert_sound_type_2_audio_info_audio_type(sound_type, dstAudioType);
340
341     return CAudioInfo(sampleRate, dstChannel, dstSampleType, dstAudioType, -1);
342 }
343
344 static audio_io_interrupted_code_e _convert_interrupted_code(IAudioSessionEventListener::EInterruptCode code) {
345     switch (code) {
346     case IAudioSessionEventListener::INTERRUPT_COMPLETED:
347         return AUDIO_IO_INTERRUPTED_COMPLETED;
348     case IAudioSessionEventListener::INTERRUPT_BY_CALL:
349         return AUDIO_IO_INTERRUPTED_BY_CALL;
350     case IAudioSessionEventListener::INTERRUPT_BY_EARJACK_UNPLUG:
351         return AUDIO_IO_INTERRUPTED_BY_EARJACK_UNPLUG;
352     case IAudioSessionEventListener::INTERRUPT_BY_RESOURCE_CONFLICT:
353         return AUDIO_IO_INTERRUPTED_BY_RESOURCE_CONFLICT;
354     case IAudioSessionEventListener::INTERRUPT_BY_ALARM:
355         return AUDIO_IO_INTERRUPTED_BY_ALARM;
356     case IAudioSessionEventListener::INTERRUPT_BY_EMERGENCY:
357         return AUDIO_IO_INTERRUPTED_BY_EMERGENCY;
358     case IAudioSessionEventListener::INTERRUPT_BY_NOTIFICATION:
359         return AUDIO_IO_INTERRUPTED_BY_NOTIFICATION;
360     case IAudioSessionEventListener::INTERRUPT_BY_MEDIA:
361     case IAudioSessionEventListener::INTERRUPT_MAX:
362     default:
363         return AUDIO_IO_INTERRUPTED_BY_MEDIA;
364     }
365 }
366
367 /**
368  * Implements CAPI functions
369  */
370 int cpp_audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_in_h *input) {
371     audio_io_s* handle = NULL;
372     try {
373         if (input == NULL) {
374             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
375         }
376
377         _check_audio_param(sample_rate, channel, type);
378
379         handle = new audio_io_s;
380         if (handle == NULL) {
381             THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation handle");
382         }
383
384         CAudioInfo audioInfo = _generate_audio_input_info(sample_rate, channel, type);
385
386         handle->audioIoHandle = new CAudioInput(audioInfo);
387         if (handle == NULL) {
388             THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation internal handle");
389         }
390
391         handle->audioIoHandle->initialize();
392
393         *input = handle;
394     } catch (CAudioError e) {
395         AUDIO_IO_LOGE("%s", e.getErrorMsg());
396
397         VALID_POINTER_START(handle)
398             SAFE_FINALIZE(handle->audioIoHandle);
399             SAFE_DELETE(handle->audioIoHandle);
400             SAFE_DELETE(handle);
401         VALID_POINTER_END
402
403         VALID_POINTER_START(input)
404             *input = NULL;
405         VALID_POINTER_END
406
407         return _convert_CAudioError(e);
408     }
409
410     return AUDIO_IO_ERROR_NONE;
411
412 }
413
414 int cpp_audio_in_create_loopback(int sample_rate, audio_channel_e channel, audio_sample_type_e type , audio_in_h* input) {
415     audio_io_s* handle = NULL;
416     try {
417         if (input == NULL) {
418             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
419         }
420
421         handle = new audio_io_s;
422         if (handle == NULL) {
423             THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation handle");
424         }
425
426         CAudioInfo audioInfo = _generate_audio_input_loopback_info(sample_rate, channel, type);
427
428         handle->audioIoHandle = new CAudioInput(audioInfo);
429         if (handle == NULL) {
430             THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation internal handle");
431         }
432
433         handle->audioIoHandle->initialize();
434
435         *input = handle;
436     } catch (CAudioError e) {
437         AUDIO_IO_LOGE("%s", e.getErrorMsg());
438
439         VALID_POINTER_START(handle)
440             SAFE_FINALIZE(handle->audioIoHandle);
441             SAFE_DELETE(handle->audioIoHandle);
442             SAFE_DELETE(handle);
443         VALID_POINTER_END
444
445         VALID_POINTER_START(input)
446             *input = NULL;
447         VALID_POINTER_END
448
449         return _convert_CAudioError(e);
450     }
451
452     return AUDIO_IO_ERROR_NONE;
453 }
454
455 int cpp_audio_in_destroy(audio_in_h input) {
456     audio_io_s* handle = static_cast<audio_io_s*>(input);
457
458     try {
459         if (handle == NULL) {
460             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
461         }
462
463         assert(handle->audioIoHandle);
464
465         SAFE_FINALIZE(handle->audioIoHandle);
466         SAFE_DELETE(handle->audioIoHandle);
467         SAFE_DELETE(handle);
468     } catch (CAudioError e) {
469         AUDIO_IO_LOGE("%s", e.getErrorMsg());
470         return _convert_CAudioError(e);
471     }
472
473     return AUDIO_IO_ERROR_NONE;
474 }
475
476 int cpp_audio_in_set_stream_info(audio_in_h input, sound_stream_info_h stream_info) {
477     audio_io_s* handle = static_cast<audio_io_s*>(input);
478
479     try {
480         if (handle == NULL || stream_info == NULL) {
481             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, stream_info:%p", input, stream_info);
482         }
483
484         assert(handle->audioIoHandle);
485
486         int errorCode = SOUND_MANAGER_ERROR_NONE;
487         CAudioInfo::EAudioType AudioType = CAudioInfo::AUDIO_IN_TYPE_MEDIA;
488         char *type = NULL;
489         int index = -1;
490
491         if ((errorCode = sound_manager_get_type_from_stream_information (stream_info, &type)) != SOUND_MANAGER_ERROR_NONE) {
492             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->stream_type is invalid [ret:%d]", errorCode);
493         }
494         handle->audioIoHandle->getAudioInfo().convertStreamType2AudioType(type, &AudioType);
495         handle->audioIoHandle->getAudioInfo().setAudioType(AudioType);
496
497         if ((errorCode = sound_manager_get_index_from_stream_information (stream_info, &index)) != SOUND_MANAGER_ERROR_NONE) {
498             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->index is invalid [ret:%d]", errorCode);
499         }
500         handle->audioIoHandle->getAudioInfo().setAudioIndex(index);
501     } catch (CAudioError e) {
502         AUDIO_IO_LOGE("%s", e.getErrorMsg());
503         return _convert_CAudioError(e);
504     }
505
506     return AUDIO_IO_ERROR_NONE;
507 }
508
509 int cpp_audio_in_prepare(audio_in_h input) {
510     audio_io_s* handle = static_cast<audio_io_s*>(input);
511
512     try {
513         if (handle == NULL) {
514             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
515         }
516
517         assert(handle->audioIoHandle);
518
519         handle->audioIoHandle->prepare();
520     } catch (CAudioError e) {
521         AUDIO_IO_LOGE("%s", e.getErrorMsg());
522         return _convert_CAudioError(e);
523     }
524
525     return AUDIO_IO_ERROR_NONE;
526 }
527
528 int cpp_audio_in_unprepare(audio_in_h input) {
529     audio_io_s* handle = static_cast<audio_io_s*>(input);
530
531     try {
532         if (handle == NULL) {
533             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
534         }
535
536         assert(handle->audioIoHandle);
537
538         handle->audioIoHandle->unprepare();
539     } catch (CAudioError e) {
540         AUDIO_IO_LOGE("%s", e.getErrorMsg());
541         return _convert_CAudioError(e);
542     }
543
544     return AUDIO_IO_ERROR_NONE;
545 }
546
547 int cpp_audio_in_pause(audio_in_h input) {
548     audio_io_s* handle = static_cast<audio_io_s*>(input);
549
550     try {
551         if (handle == NULL) {
552             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
553         }
554
555         assert(handle->audioIoHandle);
556
557         handle->audioIoHandle->pause();
558     } catch (CAudioError e) {
559         AUDIO_IO_LOGE("%s", e.getErrorMsg());
560         return _convert_CAudioError(e);
561     }
562
563     return AUDIO_IO_ERROR_NONE;
564 }
565
566 int cpp_audio_in_resume(audio_in_h input) {
567     audio_io_s* handle = static_cast<audio_io_s*>(input);
568
569     try {
570         if (handle == NULL) {
571             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
572         }
573
574         assert(handle->audioIoHandle);
575
576         handle->audioIoHandle->resume();
577     } catch (CAudioError e) {
578         AUDIO_IO_LOGE("%s", e.getErrorMsg());
579         return _convert_CAudioError(e);
580     }
581
582     return AUDIO_IO_ERROR_NONE;
583 }
584
585 int cpp_audio_in_drain(audio_in_h input) {
586     audio_io_s* handle = static_cast<audio_io_s*>(input);
587
588     try {
589         if (handle == NULL) {
590             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
591         }
592
593         assert(handle->audioIoHandle);
594
595         handle->audioIoHandle->drain();
596     } catch (CAudioError e) {
597         AUDIO_IO_LOGE("%s", e.getErrorMsg());
598         return _convert_CAudioError(e);
599     }
600
601     return AUDIO_IO_ERROR_NONE;
602 }
603
604 int cpp_audio_in_flush(audio_in_h input) {
605     audio_io_s* handle = static_cast<audio_io_s*>(input);
606
607     try {
608         if (handle == NULL) {
609             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
610         }
611
612         assert(handle->audioIoHandle);
613
614         handle->audioIoHandle->flush();
615     } catch (CAudioError e) {
616         AUDIO_IO_LOGE("%s", e.getErrorMsg());
617         return _convert_CAudioError(e);
618     }
619
620     return AUDIO_IO_ERROR_NONE;
621 }
622
623 int cpp_audio_in_read(audio_in_h input, void *buffer, unsigned int length) {
624     audio_io_s* handle = static_cast<audio_io_s*>(input);
625     int ret = 0;
626
627     try {
628         if (handle == NULL) {
629             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
630         }
631
632         assert(handle->audioIoHandle);
633
634         CAudioInput* inputHandle = dynamic_cast<CAudioInput*>(handle->audioIoHandle);
635         ret = inputHandle->read(buffer, length);
636 #ifdef _AUDIO_IO_DEBUG_TIMING_
637         AUDIO_IO_LOGD("ret:%d", ret);
638 #endif
639     } catch (CAudioError e) {
640         AUDIO_IO_LOGE("%s", e.getErrorMsg());
641         return _convert_CAudioError(e);
642     }
643
644     return ret;
645 }
646
647 int cpp_audio_in_get_buffer_size(audio_in_h input, int *size) {
648     audio_io_s* handle = static_cast<audio_io_s*>(input);
649
650     try {
651         if (handle == NULL || size == NULL) {
652             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, size:%p", input, size);
653         }
654
655         assert(handle->audioIoHandle);
656
657         CAudioIO* inputHandle = dynamic_cast<CAudioInput*>(handle->audioIoHandle);
658         *size = inputHandle->getBufferSize();
659     } catch (CAudioError e) {
660         AUDIO_IO_LOGE("%s", e.getErrorMsg());
661         return _convert_CAudioError(e);
662     }
663
664     return AUDIO_IO_ERROR_NONE;
665 }
666
667 int cpp_audio_in_get_sample_rate(audio_in_h input, int *sample_rate) {
668     audio_io_s* handle = static_cast<audio_io_s*>(input);
669
670     try {
671         if (handle == NULL || sample_rate == NULL) {
672             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, sample_rate:%p", input, sample_rate);
673         }
674
675         assert(handle->audioIoHandle);
676         *sample_rate = handle->audioIoHandle->getAudioInfo().getSampleRate();
677     } catch (CAudioError e) {
678         AUDIO_IO_LOGE("%s", e.getErrorMsg());
679         return _convert_CAudioError(e);
680     }
681
682     return AUDIO_IO_ERROR_NONE;
683 }
684
685 int cpp_audio_in_get_channel(audio_in_h input, audio_channel_e *channel) {
686     audio_io_s* handle = static_cast<audio_io_s*>(input);
687
688     try {
689         if (handle == NULL || channel == NULL) {
690             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, channel:%p", input, channel);
691         }
692
693         assert(handle->audioIoHandle);
694
695         const CAudioInfo::EChannel srcChannel = handle->audioIoHandle->getAudioInfo().getChannel();
696         audio_channel_e dstChannel = AUDIO_CHANNEL_MONO;
697         _convert_audio_info_channel_2_channel(srcChannel, dstChannel);
698
699         *channel = dstChannel;
700     } catch (CAudioError e) {
701         AUDIO_IO_LOGE("%s", e.getErrorMsg());
702         return _convert_CAudioError(e);
703     }
704
705     return AUDIO_IO_ERROR_NONE;
706 }
707
708 int cpp_audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type) {
709     audio_io_s* handle = static_cast<audio_io_s*>(input);
710
711     try {
712         if (handle == NULL || type == NULL) {
713             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, type:%p", input, type);
714         }
715
716         assert(handle->audioIoHandle);
717
718         const CAudioInfo::ESampleType srcSampleType = handle->audioIoHandle->getAudioInfo().getSampleType();
719         audio_sample_type_e     dstSampleType = AUDIO_SAMPLE_TYPE_U8;
720         _convert_audio_info_sample_type_2_sample_type(srcSampleType, dstSampleType);
721
722         *type = dstSampleType;
723     } catch (CAudioError e) {
724         AUDIO_IO_LOGE("%s", e.getErrorMsg());
725         return _convert_CAudioError(e);
726     }
727
728     return AUDIO_IO_ERROR_NONE;
729 }
730
731 static void _interrupt_cb_internal(IAudioSessionEventListener::EInterruptCode _code, void* user_data) {
732     audio_io_s* handle = static_cast<audio_io_s*>(user_data);
733     audio_io_interrupted_code_e code = _convert_interrupted_code(_code);
734
735     assert(handle);
736
737     if (handle->interrupt_callback.onInterrupt != NULL) {
738         handle->interrupt_callback.onInterrupt(code, handle->interrupt_callback.user_data);
739     }
740 }
741
742 int cpp_audio_in_set_interrupted_cb(audio_in_h input, audio_io_interrupted_cb callback, void *user_data) {
743     audio_io_s* handle = static_cast<audio_io_s*>(input);
744
745     try {
746         if (handle == NULL || callback == NULL) {
747             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, callback:%p", input, callback);
748         }
749
750         assert(handle->audioIoHandle);
751
752         handle->interrupt_callback.onInterrupt = callback;
753         handle->interrupt_callback.user_data    = user_data;
754
755         CAudioIO::SInterruptCallback cb = handle->audioIoHandle->getInterruptCallback();
756         cb.mUserData   = static_cast<void*>(handle);
757         cb.onInterrupt = _interrupt_cb_internal;
758
759         handle->audioIoHandle->setInterruptCallback(cb);
760     } catch (CAudioError e) {
761         AUDIO_IO_LOGE("%s", e.getErrorMsg());
762         return _convert_CAudioError(e);
763     }
764
765     return AUDIO_IO_ERROR_NONE;
766 }
767
768 int cpp_audio_in_unset_interrupted_cb(audio_in_h input) {
769     audio_io_s* handle = static_cast<audio_io_s*>(input);
770
771     try {
772         if (handle == NULL) {
773             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
774         }
775
776         assert(handle->audioIoHandle);
777
778         handle->interrupt_callback.onInterrupt = NULL;
779         handle->interrupt_callback.user_data    = NULL;
780
781         CAudioIO::SInterruptCallback cb = handle->audioIoHandle->getInterruptCallback();
782         cb.mUserData   = NULL;
783         cb.onInterrupt = NULL;
784
785         handle->audioIoHandle->setInterruptCallback(cb);
786     } catch (CAudioError e) {
787         AUDIO_IO_LOGE("%s", e.getErrorMsg());
788         return _convert_CAudioError(e);
789     }
790
791     return AUDIO_IO_ERROR_NONE;
792 }
793
794 int cpp_audio_in_ignore_session(audio_in_h input) {
795     audio_io_s* handle = static_cast<audio_io_s*>(input);
796
797     try {
798         if (handle == NULL) {
799             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
800         }
801
802         if (handle->stream_callback.onStream) {
803             THROW_ERROR_MSG(CAudioError::ERROR_INVALID_OPERATION, "Not support ignore session in async mode");
804         }
805
806         assert(handle->audioIoHandle);
807
808         handle->audioIoHandle->ignoreSession();
809     } catch (CAudioError e) {
810         AUDIO_IO_LOGE("%s", e.getErrorMsg());
811         return _convert_CAudioError(e);
812     }
813
814     return AUDIO_IO_ERROR_NONE;
815 }
816
817 static void _stream_cb_internal(size_t nbytes, void *user_data) {
818     audio_io_s* audioIo = static_cast<audio_io_s*>(user_data);
819     assert(audioIo);
820
821     if (audioIo->stream_callback.onStream != NULL) {
822         audioIo->stream_callback.onStream(audioIo, nbytes, audioIo->stream_callback.user_data);
823     }
824 }
825
826 static void _state_changed_cb_internal(CAudioInfo::EAudioIOState state, CAudioInfo::EAudioIOState state_prev, bool by_policy, void *user_data) {
827     audio_io_s* audioIo = static_cast<audio_io_s*>(user_data);
828     assert(audioIo);
829
830     if (audioIo->state_changed_callback.onStateChanged != NULL) {
831         audioIo->state_changed_callback.onStateChanged(audioIo, _convert_state_type(state_prev), _convert_state_type(state), by_policy, audioIo->state_changed_callback.user_data);
832     }
833 }
834
835 int cpp_audio_in_set_stream_cb(audio_in_h input, audio_in_stream_cb callback, void* user_data) {
836     audio_io_s* handle = static_cast<audio_io_s*>(input);
837
838     try {
839         if (handle == NULL || callback == NULL) {
840             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, callback:%p", input, callback);
841         }
842
843         assert(handle->audioIoHandle);
844
845         handle->stream_callback.onStream = callback;
846         handle->stream_callback.user_data = user_data;
847
848         CAudioIO::SStreamCallback cb = handle->audioIoHandle->getStreamCallback();
849         cb.mUserData = static_cast<void*>(handle);
850         cb.onStream  = _stream_cb_internal;
851
852         handle->audioIoHandle->setStreamCallback(cb);
853     } catch (CAudioError e) {
854         AUDIO_IO_LOGE("%s", e.getErrorMsg());
855         return _convert_CAudioError(e);
856     }
857
858     return AUDIO_IO_ERROR_NONE;
859 }
860
861 int cpp_audio_in_unset_stream_cb(audio_in_h input) {
862     audio_io_s* handle = static_cast<audio_io_s*>(input);
863
864     try {
865         if (handle == NULL) {
866             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
867         }
868
869         assert(handle->audioIoHandle);
870
871         handle->stream_callback.onStream = NULL;
872         handle->stream_callback.user_data = NULL;
873
874         CAudioIO::SStreamCallback cb = handle->audioIoHandle->getStreamCallback();
875         cb.mUserData = NULL;
876         cb.onStream  = NULL;
877
878         handle->audioIoHandle->setStreamCallback(cb);
879     } catch (CAudioError e) {
880         AUDIO_IO_LOGE("%s", e.getErrorMsg());
881         return _convert_CAudioError(e);
882     }
883
884     return AUDIO_IO_ERROR_NONE;
885 }
886
887 int cpp_audio_in_peek(audio_in_h input, const void **buffer, unsigned int *length) {
888     audio_io_s* handle = static_cast<audio_io_s*>(input);
889
890     try {
891         if (handle == NULL) {
892             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
893         }
894
895         CAudioInput* inputHandle = dynamic_cast<CAudioInput*>(handle->audioIoHandle);
896         assert(inputHandle);
897
898         inputHandle->peek(buffer, length);
899     } catch (CAudioError e) {
900         AUDIO_IO_LOGE("%s", e.getErrorMsg());
901         return _convert_CAudioError(e);
902     }
903
904     return AUDIO_IO_ERROR_NONE;
905 }
906
907 int cpp_audio_in_drop(audio_in_h input) {
908     audio_io_s* handle = static_cast<audio_io_s*>(input);
909
910     try {
911         if (handle == NULL) {
912             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
913         }
914
915         CAudioInput* inputHandle = dynamic_cast<CAudioInput*>(handle->audioIoHandle);
916         assert(inputHandle);
917
918         inputHandle->drop();
919     } catch (CAudioError e) {
920         AUDIO_IO_LOGE("%s", e.getErrorMsg());
921         return _convert_CAudioError(e);
922     }
923
924     return AUDIO_IO_ERROR_NONE;
925 }
926
927 int cpp_audio_in_set_state_changed_cb(audio_in_h input, audio_in_state_changed_cb callback, void* user_data) {
928     audio_io_s* handle = static_cast<audio_io_s*>(input);
929
930     try {
931         if (handle == NULL) {
932             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, callback:%p", input, callback);
933         }
934
935         assert(handle->audioIoHandle);
936
937         handle->state_changed_callback.onStateChanged = callback;
938         handle->state_changed_callback.user_data = user_data;
939
940         CAudioIO::SStateChangedCallback cb = handle->audioIoHandle->getStateChangedCallback();
941         cb.mUserData = static_cast<void*>(handle);
942         cb.onStateChanged = _state_changed_cb_internal;
943
944         handle->audioIoHandle->setStateChangedCallback(cb);
945     } catch (CAudioError e) {
946         AUDIO_IO_LOGE("%s", e.getErrorMsg());
947         return _convert_CAudioError(e);
948     }
949
950     return AUDIO_IO_ERROR_NONE;
951 }
952
953 int cpp_audio_in_unset_state_changed_cb(audio_in_h input) {
954     audio_io_s* handle = static_cast<audio_io_s*>(input);
955
956     try {
957         if (handle == NULL) {
958             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p", input);
959         }
960
961         assert(handle->audioIoHandle);
962
963         handle->state_changed_callback.onStateChanged = NULL;
964         handle->state_changed_callback.user_data = NULL;
965
966         CAudioIO::SStateChangedCallback cb = handle->audioIoHandle->getStateChangedCallback();
967         cb.mUserData = NULL;
968         cb.onStateChanged  = NULL;
969
970         handle->audioIoHandle->setStateChangedCallback(cb);
971     } catch (CAudioError e) {
972         AUDIO_IO_LOGE("%s", e.getErrorMsg());
973         return _convert_CAudioError(e);
974     }
975
976     return AUDIO_IO_ERROR_NONE;
977 }
978
979
980 /**
981  * Audio Out
982  */
983 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) {
984     audio_io_s* handle = NULL;
985     try {
986         handle = new audio_io_s;
987         if (handle == NULL) {
988             THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation handle");
989         }
990
991         _check_audio_param(sample_rate, channel, type, sound_type);
992
993         CAudioInfo audioInfo = _generate_audio_output_info(sample_rate, channel, type, sound_type);
994
995         handle->audioIoHandle = new CAudioOutput(audioInfo);
996         if (handle == NULL) {
997             THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation internal handle");
998         }
999
1000         handle->audioIoHandle->initialize();
1001
1002         *output = handle;
1003     } catch (CAudioError e) {
1004         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1005
1006         VALID_POINTER_START(handle)
1007             SAFE_FINALIZE(handle->audioIoHandle);
1008             SAFE_DELETE(handle->audioIoHandle);
1009             SAFE_DELETE(handle);
1010         VALID_POINTER_END
1011
1012         VALID_POINTER_START(output)
1013         *output = NULL;
1014         VALID_POINTER_END
1015
1016         return _convert_CAudioError(e);
1017     }
1018
1019     return AUDIO_IO_ERROR_NONE;
1020 }
1021
1022 int cpp_audio_out_create_new(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_out_h *output) {
1023     audio_io_s* handle = NULL;
1024     try {
1025         handle = new audio_io_s;
1026         if (handle == NULL) {
1027             THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation handle");
1028         }
1029
1030         CAudioInfo audioInfo = _generate_audio_output_info(sample_rate, channel, type, SOUND_TYPE_MEDIA /* default sound_tyoe */);
1031
1032         handle->audioIoHandle = new CAudioOutput(audioInfo);
1033         if (handle == NULL) {
1034             THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation internal handle");
1035         }
1036
1037         handle->audioIoHandle->initialize();
1038
1039         *output = handle;
1040     } catch (CAudioError e) {
1041         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1042
1043         VALID_POINTER_START(handle)
1044             SAFE_FINALIZE(handle->audioIoHandle);
1045             SAFE_DELETE(handle->audioIoHandle);
1046             SAFE_DELETE(handle);
1047         VALID_POINTER_END
1048
1049         VALID_POINTER_START(output)
1050         *output = NULL;
1051         VALID_POINTER_END
1052
1053         return _convert_CAudioError(e);
1054     }
1055
1056     return AUDIO_IO_ERROR_NONE;
1057 }
1058
1059 int cpp_audio_out_destroy(audio_out_h output) {
1060     audio_io_s* handle = static_cast<audio_io_s*>(output);
1061
1062     try {
1063         if (handle == NULL) {
1064             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
1065         }
1066
1067         assert(handle->audioIoHandle);
1068
1069         SAFE_FINALIZE(handle->audioIoHandle);
1070         SAFE_DELETE(handle->audioIoHandle);
1071         SAFE_DELETE(handle);
1072     } catch (CAudioError e) {
1073         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1074         return _convert_CAudioError(e);
1075     }
1076
1077     return AUDIO_IO_ERROR_NONE;
1078 }
1079
1080 int cpp_audio_out_set_stream_info(audio_out_h output, sound_stream_info_h stream_info) {
1081     audio_io_s* handle = static_cast<audio_io_s*>(output);
1082
1083     try {
1084         if (handle == NULL || stream_info == NULL) {
1085             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, stream_info:%p", output, stream_info);
1086         }
1087
1088         assert(handle->audioIoHandle);
1089
1090         int errorCode = SOUND_MANAGER_ERROR_NONE;
1091         CAudioInfo::EAudioType AudioType = CAudioInfo::AUDIO_OUT_TYPE_MEDIA;
1092         char *type = NULL;
1093         int index = -1;
1094
1095         if ((errorCode = sound_manager_get_type_from_stream_information (stream_info, &type)) != SOUND_MANAGER_ERROR_NONE) {
1096             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->stream_type is invalid [ret:%d]", errorCode);
1097         }
1098         handle->audioIoHandle->getAudioInfo().convertStreamType2AudioType(type, &AudioType);
1099         handle->audioIoHandle->getAudioInfo().setAudioType(AudioType);
1100
1101         if ((errorCode = sound_manager_get_index_from_stream_information (stream_info, &index)) != SOUND_MANAGER_ERROR_NONE) {
1102             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->index is invalid [ret:%d]", errorCode);
1103         }
1104         handle->audioIoHandle->getAudioInfo().setAudioIndex(index);
1105     } catch (CAudioError e) {
1106         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1107         return _convert_CAudioError(e);
1108     }
1109
1110     return AUDIO_IO_ERROR_NONE;
1111 }
1112
1113 int cpp_audio_out_prepare(audio_out_h output) {
1114     audio_io_s* handle = static_cast<audio_io_s*>(output);
1115
1116     try {
1117         if (handle == NULL) {
1118             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
1119         }
1120
1121         assert(handle->audioIoHandle);
1122
1123         handle->audioIoHandle->prepare();
1124     } catch (CAudioError e) {
1125         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1126         return _convert_CAudioError(e);
1127     }
1128
1129     return AUDIO_IO_ERROR_NONE;
1130 }
1131
1132 int cpp_audio_out_unprepare(audio_out_h output) {
1133     audio_io_s* handle = static_cast<audio_io_s*>(output);
1134
1135     try {
1136         if (handle == NULL) {
1137             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
1138         }
1139
1140         assert(handle->audioIoHandle);
1141
1142         handle->audioIoHandle->unprepare();
1143     } catch (CAudioError e) {
1144         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1145         return _convert_CAudioError(e);
1146     }
1147
1148     return AUDIO_IO_ERROR_NONE;
1149 }
1150
1151 int cpp_audio_out_pause(audio_out_h output) {
1152     audio_io_s* handle = static_cast<audio_io_s*>(output);
1153
1154     try {
1155         if (handle == NULL) {
1156             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
1157         }
1158
1159         assert(handle->audioIoHandle);
1160
1161         handle->audioIoHandle->pause();
1162     } catch (CAudioError e) {
1163         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1164         return _convert_CAudioError(e);
1165     }
1166
1167     return AUDIO_IO_ERROR_NONE;
1168 }
1169
1170 int cpp_audio_out_resume(audio_out_h output) {
1171     audio_io_s* handle = static_cast<audio_io_s*>(output);
1172
1173     try {
1174         if (handle == NULL) {
1175             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
1176         }
1177
1178         assert(handle->audioIoHandle);
1179
1180         handle->audioIoHandle->resume();
1181     } catch (CAudioError e) {
1182         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1183         return _convert_CAudioError(e);
1184     }
1185
1186     return AUDIO_IO_ERROR_NONE;
1187 }
1188
1189 int cpp_audio_out_drain(audio_out_h output) {
1190     audio_io_s* handle = static_cast<audio_io_s*>(output);
1191
1192     try {
1193         if (handle == NULL) {
1194             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
1195         }
1196
1197         assert(handle->audioIoHandle);
1198
1199         handle->audioIoHandle->drain();
1200     } catch (CAudioError e) {
1201         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1202         return _convert_CAudioError(e);
1203     }
1204
1205     return AUDIO_IO_ERROR_NONE;
1206 }
1207
1208 int cpp_audio_out_flush(audio_out_h output) {
1209     audio_io_s* handle = static_cast<audio_io_s*>(output);
1210
1211     try {
1212         if (handle == NULL) {
1213             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
1214         }
1215
1216         assert(handle->audioIoHandle);
1217
1218         handle->audioIoHandle->flush();
1219     } catch (CAudioError e) {
1220         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1221         return _convert_CAudioError(e);
1222     }
1223
1224     return AUDIO_IO_ERROR_NONE;
1225 }
1226
1227 int cpp_audio_out_write(audio_out_h output, void *buffer, unsigned int length) {
1228     audio_io_s* handle = static_cast<audio_io_s*>(output);
1229     int ret = 0;
1230
1231     try {
1232         if (handle == NULL) {
1233             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
1234         }
1235
1236         assert(handle->audioIoHandle);
1237
1238         CAudioOutput* outputHandle = dynamic_cast<CAudioOutput*>(handle->audioIoHandle);
1239         ret = outputHandle->write(buffer, length);
1240 #ifdef _AUDIO_IO_DEBUG_TIMING_
1241         AUDIO_IO_LOGD("ret:%d", ret);
1242 #endif
1243     } catch (CAudioError e) {
1244         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1245         return _convert_CAudioError(e);
1246     }
1247
1248     return ret;
1249 }
1250
1251 int cpp_audio_out_get_buffer_size(audio_out_h output, int *size) {
1252     audio_io_s* handle = static_cast<audio_io_s*>(output);
1253
1254     try {
1255         if (handle == NULL || size == NULL) {
1256             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, size:%p", output, size);
1257         }
1258
1259         assert(handle->audioIoHandle);
1260
1261         CAudioOutput* outputHandle = dynamic_cast<CAudioOutput*>(handle->audioIoHandle);
1262         *size = outputHandle->getBufferSize();
1263     } catch (CAudioError e) {
1264         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1265         return _convert_CAudioError(e);
1266     }
1267
1268     return AUDIO_IO_ERROR_NONE;
1269 }
1270
1271 int cpp_audio_out_get_sample_rate(audio_out_h output, int *sample_rate) {
1272     audio_io_s* handle = static_cast<audio_io_s*>(output);
1273
1274     try {
1275         if (handle == NULL || sample_rate == NULL) {
1276             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, sample_rate:%p", output, sample_rate);
1277         }
1278
1279         assert(handle->audioIoHandle);
1280         *sample_rate = handle->audioIoHandle->getAudioInfo().getSampleRate();
1281     } catch (CAudioError e) {
1282         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1283         return _convert_CAudioError(e);
1284     }
1285
1286     return AUDIO_IO_ERROR_NONE;
1287 }
1288
1289 int cpp_audio_out_get_channel(audio_out_h output, audio_channel_e *channel) {
1290     audio_io_s* handle = static_cast<audio_io_s*>(output);
1291
1292     try {
1293         if (handle == NULL || channel == NULL) {
1294             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, channel:%p", output, channel);
1295         }
1296
1297         assert(handle->audioIoHandle);
1298
1299         const CAudioInfo::EChannel srcChannel = handle->audioIoHandle->getAudioInfo().getChannel();
1300         audio_channel_e dstChannel = AUDIO_CHANNEL_MONO;
1301         _convert_audio_info_channel_2_channel(srcChannel, dstChannel);
1302
1303         *channel = dstChannel;
1304     } catch (CAudioError e) {
1305         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1306         return _convert_CAudioError(e);
1307     }
1308
1309     return AUDIO_IO_ERROR_NONE;
1310 }
1311
1312 int cpp_audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type) {
1313     audio_io_s* handle = static_cast<audio_io_s*>(output);
1314
1315     try {
1316         if (handle == NULL || type == NULL) {
1317             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, type:%p", output, type);
1318         }
1319
1320         assert(handle->audioIoHandle);
1321
1322         const CAudioInfo::ESampleType srcSampleType = handle->audioIoHandle->getAudioInfo().getSampleType();
1323         audio_sample_type_e     dstSampleType = AUDIO_SAMPLE_TYPE_U8;
1324         _convert_audio_info_sample_type_2_sample_type(srcSampleType, dstSampleType);
1325
1326         *type = dstSampleType;
1327     } catch (CAudioError e) {
1328         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1329         return _convert_CAudioError(e);
1330     }
1331
1332     return AUDIO_IO_ERROR_NONE;
1333 }
1334
1335 int cpp_audio_out_get_sound_type(audio_out_h output, sound_type_e *type) {
1336     audio_io_s* handle = static_cast<audio_io_s*>(output);
1337
1338     try {
1339         if (handle == NULL || type == NULL) {
1340             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, type:%p", output, type);
1341         }
1342
1343         assert(handle->audioIoHandle);
1344
1345         const CAudioInfo::EAudioType srcAudioType = handle->audioIoHandle->getAudioInfo().getAudioType();
1346         sound_type_e                 dstSoundType = SOUND_TYPE_MEDIA;
1347         _convert_audio_info_audio_type_2_sound_type(srcAudioType, dstSoundType);
1348
1349         *type = dstSoundType;
1350     } catch (CAudioError e) {
1351         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1352         return _convert_CAudioError(e);
1353     }
1354
1355     return AUDIO_IO_ERROR_NONE;
1356 }
1357
1358 int cpp_audio_out_set_interrupted_cb(audio_out_h output, audio_io_interrupted_cb callback, void *user_data) {
1359     audio_io_s* handle = static_cast<audio_io_s*>(output);
1360
1361     try {
1362         if (handle == NULL || callback == NULL) {
1363             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, callback:%p", output, callback);
1364         }
1365
1366         assert(handle->audioIoHandle);
1367
1368         handle->interrupt_callback.onInterrupt = callback;
1369         handle->interrupt_callback.user_data    = user_data;
1370
1371         CAudioIO::SInterruptCallback cb = handle->audioIoHandle->getInterruptCallback();
1372         cb.mUserData   = static_cast<void*>(handle);
1373         cb.onInterrupt = _interrupt_cb_internal;
1374
1375         handle->audioIoHandle->setInterruptCallback(cb);
1376     } catch (CAudioError e) {
1377         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1378         return _convert_CAudioError(e);
1379     }
1380
1381     return AUDIO_IO_ERROR_NONE;
1382 }
1383
1384 int cpp_audio_out_unset_interrupted_cb(audio_out_h output) {
1385     audio_io_s* handle = static_cast<audio_io_s*>(output);
1386
1387     try {
1388         if (handle == NULL) {
1389             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p", output);
1390         }
1391
1392         assert(handle->audioIoHandle);
1393
1394         handle->interrupt_callback.onInterrupt = NULL;
1395         handle->interrupt_callback.user_data    = NULL;
1396
1397         CAudioIO::SInterruptCallback cb = handle->audioIoHandle->getInterruptCallback();
1398         cb.mUserData   = NULL;
1399         cb.onInterrupt = NULL;
1400
1401         handle->audioIoHandle->setInterruptCallback(cb);
1402     } catch (CAudioError e) {
1403         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1404         return _convert_CAudioError(e);
1405     }
1406
1407     return AUDIO_IO_ERROR_NONE;
1408 }
1409
1410 int cpp_audio_out_ignore_session(audio_out_h output) {
1411     audio_io_s* handle = static_cast<audio_io_s*>(output);
1412
1413     try {
1414         if (handle == NULL) {
1415             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p", output);
1416         }
1417
1418         if (handle->stream_callback.onStream) {
1419             THROW_ERROR_MSG(CAudioError::ERROR_INVALID_OPERATION, "Not support ignore session in async mode");
1420         }
1421
1422         assert(handle->audioIoHandle);
1423
1424         handle->audioIoHandle->ignoreSession();
1425     } catch (CAudioError e) {
1426         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1427         return _convert_CAudioError(e);
1428     }
1429
1430     return AUDIO_IO_ERROR_NONE;
1431 }
1432
1433 int cpp_audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback, void* user_data) {
1434     audio_io_s* handle = static_cast<audio_io_s*>(output);
1435
1436     try {
1437         if (handle == NULL) {
1438             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, callback:%p", output, callback);
1439         }
1440
1441         assert(handle->audioIoHandle);
1442
1443         handle->stream_callback.onStream = callback;
1444         handle->stream_callback.user_data = user_data;
1445
1446         CAudioIO::SStreamCallback cb = handle->audioIoHandle->getStreamCallback();
1447         cb.mUserData = static_cast<void*>(handle);
1448         cb.onStream  = _stream_cb_internal;
1449
1450         handle->audioIoHandle->setStreamCallback(cb);
1451     } catch (CAudioError e) {
1452         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1453         return _convert_CAudioError(e);
1454     }
1455
1456     return AUDIO_IO_ERROR_NONE;
1457 }
1458
1459 int cpp_audio_out_unset_stream_cb(audio_out_h output) {
1460     audio_io_s* handle = static_cast<audio_io_s*>(output);
1461
1462     try {
1463         if (handle == NULL) {
1464             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p", output);
1465         }
1466
1467         assert(handle->audioIoHandle);
1468
1469         handle->stream_callback.onStream = NULL;
1470         handle->stream_callback.user_data = NULL;
1471
1472         CAudioIO::SStreamCallback cb = handle->audioIoHandle->getStreamCallback();
1473         cb.mUserData = NULL;
1474         cb.onStream  = NULL;
1475
1476         handle->audioIoHandle->setStreamCallback(cb);
1477     } catch (CAudioError e) {
1478         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1479         return _convert_CAudioError(e);
1480     }
1481
1482     return AUDIO_IO_ERROR_NONE;
1483 }
1484
1485 int cpp_audio_out_set_state_changed_cb(audio_out_h output, audio_in_state_changed_cb callback, void* user_data) {
1486     audio_io_s* handle = static_cast<audio_io_s*>(output);
1487
1488     try {
1489         if (handle == NULL) {
1490             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, callback:%p", output, callback);
1491         }
1492
1493         assert(handle->audioIoHandle);
1494
1495         handle->state_changed_callback.onStateChanged = callback;
1496         handle->state_changed_callback.user_data = user_data;
1497
1498         CAudioIO::SStateChangedCallback cb = handle->audioIoHandle->getStateChangedCallback();
1499         cb.mUserData = static_cast<void*>(handle);
1500         cb.onStateChanged = _state_changed_cb_internal;
1501
1502         handle->audioIoHandle->setStateChangedCallback(cb);
1503     } catch (CAudioError e) {
1504         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1505         return _convert_CAudioError(e);
1506     }
1507
1508     return AUDIO_IO_ERROR_NONE;
1509 }
1510
1511 int cpp_audio_out_unset_state_changed_cb(audio_out_h output) {
1512     audio_io_s* handle = static_cast<audio_io_s*>(output);
1513
1514     try {
1515         if (handle == NULL) {
1516             THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p", output);
1517         }
1518
1519         assert(handle->audioIoHandle);
1520
1521         handle->state_changed_callback.onStateChanged = NULL;
1522         handle->state_changed_callback.user_data = NULL;
1523
1524         CAudioIO::SStateChangedCallback cb = handle->audioIoHandle->getStateChangedCallback();
1525         cb.mUserData = NULL;
1526         cb.onStateChanged  = NULL;
1527
1528         handle->audioIoHandle->setStateChangedCallback(cb);
1529     } catch (CAudioError e) {
1530         AUDIO_IO_LOGE("%s", e.getErrorMsg());
1531         return _convert_CAudioError(e);
1532     }
1533
1534     return AUDIO_IO_ERROR_NONE;
1535 }