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