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