718f417bc6c79f6a13e8587fa9835f8fad657981
[platform/core/api/audio-io.git] / src / audio_io_private.c
1 /*
2 * Copyright (c) 2011 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 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <mm.h>
21 #include "audio_io_private.h"
22 #include <dlog.h>
23 /* TODO : it will be added after updating libmm-sound */
24 //#include <mm_sound_pcm_async.h>
25
26
27 #ifdef LOG_TAG
28 #undef LOG_TAG
29 #endif
30 #define LOG_TAG "TIZEN_N_AUDIO_IO"
31 /*
32 * Internal Implementation
33 */
34 int __convert_audio_io_error_code(int code, char *func_name)
35 {
36         int ret = AUDIO_IO_ERROR_INVALID_OPERATION;
37         char* msg = "AUDIO_IO_ERROR_INVALID_OPERATION";
38
39         switch(code)
40         {
41                 case MM_ERROR_NONE:
42                         ret = AUDIO_IO_ERROR_NONE;
43                         msg = "AUDIO_IO_ERROR_NONE";
44                         break;
45                 case MM_ERROR_INVALID_ARGUMENT:
46                 case MM_ERROR_SOUND_DEVICE_INVALID_SAMPLERATE:
47                 case MM_ERROR_SOUND_DEVICE_INVALID_CHANNEL:
48                 case MM_ERROR_SOUND_DEVICE_INVALID_FORMAT:
49                         ret = AUDIO_IO_ERROR_INVALID_PARAMETER;
50                         msg = "AUDIO_IO_ERROR_INVALID_PARAMETER";
51                         break;
52                 case MM_ERROR_SOUND_DEVICE_NOT_OPENED:
53                         ret = AUDIO_IO_ERROR_DEVICE_NOT_OPENED;
54                         msg = "AUDIO_IO_ERROR_DEVICE_NOT_OPENED";
55                         break;
56                 case MM_ERROR_SOUND_PERMISSION_DENIED:
57                         ret = AUDIO_IO_ERROR_PERMISSION_DENIED;
58                         msg = "AUDIO_IO_ERROR_PERMISSION_DENIED";
59                         break;
60                 case MM_ERROR_SOUND_INTERNAL:
61                         ret = AUDIO_IO_ERROR_INVALID_OPERATION;
62                         msg = "AUDIO_IO_ERROR_INVALID_OPERATION";
63                         break;
64                 case MM_ERROR_SOUND_INVALID_POINTER:
65                         ret = AUDIO_IO_ERROR_INVALID_BUFFER;
66                         msg = "AUDIO_IO_ERROR_INVALID_BUFFER";
67                         break;
68                 case MM_ERROR_POLICY_BLOCKED:
69                 case MM_ERROR_POLICY_INTERRUPTED:
70                 case MM_ERROR_POLICY_INTERNAL:
71                 case MM_ERROR_POLICY_DUPLICATED:
72                         ret = AUDIO_IO_ERROR_SOUND_POLICY;
73                         msg = "AUDIO_IO_ERROR_SOUND_POLICY";
74                         break;
75         } 
76         LOGE("[%s] %s(0x%08x) : core fw error(0x%x)",func_name,msg, ret, code);
77         return ret;
78 }
79
80 int __check_parameter(int sample_rate, audio_channel_e channel, audio_sample_type_e type)
81 {
82         if(sample_rate<8000 || sample_rate > 48000)     {
83                 LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) :  Invalid sample rate (8000~48000Hz) : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,sample_rate);
84                 return AUDIO_IO_ERROR_INVALID_PARAMETER;
85         }
86         if (channel < AUDIO_CHANNEL_MONO || channel > AUDIO_CHANNEL_STEREO) {
87                 LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) :  Invalid audio channel : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,channel);
88                 return AUDIO_IO_ERROR_INVALID_PARAMETER;
89         }
90         if (type < AUDIO_SAMPLE_TYPE_U8 || type > AUDIO_SAMPLE_TYPE_S16_LE) {
91                 LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) :  Invalid sample typel : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,type);
92                 return AUDIO_IO_ERROR_INVALID_PARAMETER;
93         }
94         return AUDIO_IO_ERROR_NONE;
95 }
96
97 audio_io_interrupted_code_e __translate_interrupted_code (int code)
98 {
99         audio_io_interrupted_code_e e = AUDIO_IO_INTERRUPTED_COMPLETED;
100
101         switch(code)
102         {
103         case MM_MSG_CODE_INTERRUPTED_BY_CALL_END:
104         case MM_MSG_CODE_INTERRUPTED_BY_ALARM_END:
105         case MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_END:
106         case MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_END:
107                 e = AUDIO_IO_INTERRUPTED_COMPLETED;
108                 break;
109
110         case MM_MSG_CODE_INTERRUPTED_BY_MEDIA:
111         case MM_MSG_CODE_INTERRUPTED_BY_OTHER_PLAYER_APP:
112                 e = AUDIO_IO_INTERRUPTED_BY_MEDIA;
113                 break;
114
115         case MM_MSG_CODE_INTERRUPTED_BY_CALL_START:
116                 e = AUDIO_IO_INTERRUPTED_BY_CALL;
117                 break;
118
119         case MM_MSG_CODE_INTERRUPTED_BY_EARJACK_UNPLUG:
120                 e = AUDIO_IO_INTERRUPTED_BY_EARJACK_UNPLUG;
121                 break;
122
123         case MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT:
124                 e = AUDIO_IO_INTERRUPTED_BY_RESOURCE_CONFLICT;
125                 break;
126
127         case MM_MSG_CODE_INTERRUPTED_BY_ALARM_START:
128                 e = AUDIO_IO_INTERRUPTED_BY_ALARM;
129                 break;
130
131         case MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_START:
132                 e = AUDIO_IO_INTERRUPTED_BY_NOTIFICATION;
133                 break;
134
135         case MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_START:
136                 e = AUDIO_IO_INTERRUPTED_BY_EMERGENCY;
137                 break;
138
139         case MM_MSG_CODE_INTERRUPTED_BY_RESUMABLE_MEDIA:
140                 e = AUDIO_IO_INTERRUPTED_BY_RESUMABLE_MEDIA;
141                 break;
142
143         case MM_MSG_CODE_INTERRUPTED_BY_RESUMABLE_CANCELED:
144                 e = AUDIO_IO_INTERRUPTED_BY_RESUMABLE_CANCELED;
145                 break;
146         }
147
148         return e;
149 }
150
151 int __mm_sound_pcm_capture_msg_cb (int message, void *param, void *user_param)
152 {
153         audio_io_interrupted_code_e e = AUDIO_IO_INTERRUPTED_COMPLETED;
154         audio_in_s *handle = (audio_in_s *) user_param;
155         MMMessageParamType *msg = (MMMessageParamType*)param;
156
157         LOGI("[%s] Got message type : 0x%x with code : %d" ,__FUNCTION__, message, msg->code);
158
159         if (handle->user_cb == NULL) {
160                 LOGI("[%s] No interrupt callback is set. Skip this" ,__FUNCTION__);
161                 return 0;
162         }
163
164         if (message == MM_MESSAGE_SOUND_PCM_INTERRUPTED) {
165                 e = __translate_interrupted_code (msg->code);
166         } else if (message == MM_MESSAGE_SOUND_PCM_CAPTURE_RESTRICTED) {
167                 /* TODO : handling restricted code is needed */
168                 /* e = _translate_restricted_code (msg->code); */
169         }
170
171         handle->user_cb (e, handle->user_data);
172
173         return 0;
174 }
175
176 static int __mm_sound_pcm_playback_msg_cb (int message, void *param, void *user_param)
177 {
178         audio_io_interrupted_code_e e = AUDIO_IO_INTERRUPTED_COMPLETED;
179         audio_out_s *handle = (audio_out_s *) user_param;
180         MMMessageParamType *msg = (MMMessageParamType*)param;
181
182         LOGI("[%s] Got message type : 0x%x with code : %d" ,__FUNCTION__, message, msg->code);
183
184         if (handle->user_cb == NULL) {
185                 LOGI("[%s] No interrupt callback is set. Skip this" ,__FUNCTION__);
186                 return 0;
187         }
188
189         if (message == MM_MESSAGE_SOUND_PCM_INTERRUPTED) {
190                 e = __translate_interrupted_code (msg->code);
191         }
192
193         handle->user_cb (e, handle->user_data);
194
195         return 0;
196 }
197
198 /* TODO : it will be added after updating libmm-sound */
199 //static int __audio_in_stream_cb (void* p, int nbytes, void* userdata)
200 //{
201 //      return 0;
202 //}
203
204 //static int __audio_out_stream_cb (void* p, int nbytes, void* userdata)
205 //{
206
207 //      return 0;
208 //}
209
210
211 int audio_in_create_private(int sample_rate, audio_channel_e channel, audio_sample_type_e type , audio_in_h* input)
212 {
213         int ret = 0;
214         audio_in_s *handle = NULL;
215
216         /* input condition check */
217         AUDIO_IO_NULL_ARG_CHECK(input);
218         if(__check_parameter(sample_rate, channel, type) != AUDIO_IO_ERROR_NONE)
219                 return AUDIO_IO_ERROR_INVALID_PARAMETER;
220
221         /* Create Handle & Fill information */
222         if ((handle = (audio_in_s*)malloc( sizeof(audio_in_s))) == NULL) {
223                 LOGE("ERROR :  AUDIO_IO_ERROR_OUT_OF_MEMORY(0x%08x)", AUDIO_IO_ERROR_OUT_OF_MEMORY);
224                 return AUDIO_IO_ERROR_OUT_OF_MEMORY;
225         }
226         memset(handle, 0, sizeof(audio_in_s));
227
228
229         /* Capture open */
230         if ((ret = mm_sound_pcm_capture_open( &handle->mm_handle,sample_rate, channel, type)) < 0) {
231                 LOGE("mm_sound_pcm_capture_open_ex() failed [0x%x]", ret);
232                 goto ERROR;
233         }
234         LOGI("mm_sound_pcm_capture_open_ex() success");
235
236         handle->_buffer_size = ret; /* return by pcm_open */
237         handle->_sample_rate = sample_rate;
238         handle->_channel     = channel;
239         handle->_type        = type;
240
241         /* Set message interrupt callback */
242         if ((ret = mm_sound_pcm_set_message_callback(handle->mm_handle, __mm_sound_pcm_capture_msg_cb, handle)) < 0) {
243                 LOGE("mm_sound_pcm_set_message_callback() failed [0x%x]", ret);
244                 goto ERROR;
245         }
246         LOGI("mm_sound_pcm_set_message_callback() success");
247
248         /* Handle assign */
249         *input = (audio_in_h)handle;
250
251         return AUDIO_IO_ERROR_NONE;
252
253 ERROR:
254         if (handle)
255                 free (handle);
256         return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
257 }
258
259 int audio_in_set_callback_private(audio_in_h input, audio_in_stream_cb callback, void* userdata)
260 {
261 /* TODO : it will be added after updating libmm-sound */
262
263         return AUDIO_IO_ERROR_NONE;
264 }
265
266 int audio_out_create_private(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h* output)
267 {
268         audio_out_s *handle = NULL;
269         int ret = 0;
270
271         /* input condition check */
272         AUDIO_IO_NULL_ARG_CHECK(output);
273         if(__check_parameter(sample_rate, channel, type)!=AUDIO_IO_ERROR_NONE)
274                 return AUDIO_IO_ERROR_INVALID_PARAMETER;
275         if(sound_type < SOUND_TYPE_SYSTEM || sound_type > SOUND_TYPE_CALL) {
276                 LOGE("ERROR :  AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid sample sound type : %d",
277                                 AUDIO_IO_ERROR_INVALID_PARAMETER,sound_type );
278                 return AUDIO_IO_ERROR_INVALID_PARAMETER;
279         }
280
281         /* Create Handle & Fill information */
282         if ((handle = (audio_out_s*)malloc( sizeof(audio_out_s))) == NULL) {
283                 LOGE("ERROR :  AUDIO_IO_ERROR_OUT_OF_MEMORY(0x%08x)", AUDIO_IO_ERROR_OUT_OF_MEMORY);
284                 return AUDIO_IO_ERROR_OUT_OF_MEMORY;
285         }
286         memset(handle, 0 , sizeof(audio_out_s));
287
288
289         if ((ret = mm_sound_pcm_play_open(&handle->mm_handle,sample_rate, channel, type, sound_type)) < 0) {
290                 LOGE("mm_sound_pcm_play_open() failed [0x%x]", ret);
291                 goto ERROR;
292         }
293         LOGI("mm_sound_pcm_play_open() success");
294
295
296         handle->_buffer_size = ret; /* return by pcm_open */
297         handle->_sample_rate = sample_rate;
298         handle->_channel     = channel;
299         handle->_type        = type;
300         handle->_sound_type  = sound_type;
301
302         /* Set message interrupt callback */
303         if ((ret = mm_sound_pcm_set_message_callback(handle->mm_handle, __mm_sound_pcm_playback_msg_cb, handle)) < 0) {
304                 LOGE("mm_sound_pcm_set_message_callback() failed [0x%x]", ret);
305                 goto ERROR;
306         }
307         LOGI("mm_sound_pcm_set_message_callback() success");
308
309         /* Handle assign */
310         *output = (audio_out_h)handle;
311
312         return AUDIO_IO_ERROR_NONE;
313
314 ERROR:
315         if (handle)
316                 free (handle);
317         return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
318 }
319
320 int audio_out_set_callback_private(audio_out_h output, audio_out_stream_cb callback, void* userdata)
321 {
322 /* TODO : it will be added after updating libmm-sound */
323
324         return AUDIO_IO_ERROR_NONE;
325 }