2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <audio_io_private.h>
28 #define LOG_TAG "TIZEN_N_AUDIO_IO"
33 #define AUDIO_IO_CHECK_CONDITION(condition,error,msg) \
34 if(condition) {} else \
35 { LOGE("[%s] %s(0x%08x)",__FUNCTION__, msg,error); return error;}; \
37 #define AUDIO_IO_NULL_ARG_CHECK(arg) \
38 AUDIO_IO_CHECK_CONDITION(arg != NULL, AUDIO_IO_ERROR_INVALID_PARAMETER, "AUDIO_IO_ERROR_INVALID_PARAMETER" )
41 * Internal Implementation
43 static int __convert_error_code(int code, char *func_name)
45 int ret = AUDIO_IO_ERROR_NONE;
46 char* msg = "AUDIO_IO_ERROR_NONE";
51 ret = AUDIO_IO_ERROR_NONE;
52 msg = "AUDIO_IO_ERROR_NONE";
54 case MM_ERROR_INVALID_ARGUMENT:
55 case MM_ERROR_SOUND_DEVICE_INVALID_SAMPLERATE:
56 case MM_ERROR_SOUND_DEVICE_INVALID_CHANNEL:
57 case MM_ERROR_SOUND_DEVICE_INVALID_FORMAT:
58 ret = AUDIO_IO_ERROR_INVALID_PARAMETER;
59 msg = "AUDIO_IO_ERROR_INVALID_PARAMETER";
61 case MM_ERROR_SOUND_DEVICE_NOT_OPENED:
62 ret = AUDIO_IO_ERROR_DEVICE_NOT_OPENED;
63 msg = "AUDIO_IO_ERROR_DEVICE_NOT_OPENED";
65 case MM_ERROR_SOUND_INTERNAL:
66 ret = AUDIO_IO_ERROR_DEVICE_NOT_CLOSED;
67 msg = "AUDIO_IO_ERROR_DEVICE_NOT_CLOSED";
69 case MM_ERROR_SOUND_INVALID_POINTER:
70 ret = AUDIO_IO_ERROR_INVALID_BUFFER;
71 msg = "AUDIO_IO_ERROR_INVALID_BUFFER";
73 case MM_ERROR_POLICY_BLOCKED:
74 case MM_ERROR_POLICY_INTERRUPTED:
75 case MM_ERROR_POLICY_INTERNAL:
76 case MM_ERROR_POLICY_DUPLICATED:
77 ret = AUDIO_IO_ERROR_SOUND_POLICY;
78 msg = "AUDIO_IO_ERROR_SOUND_POLICY";
81 LOGE("[%s] %s(0x%08x) : core fw error(0x%x)",func_name,msg, ret, code);
85 static int __check_parameter(int sample_rate, audio_channel_e channel, audio_sample_type_e type)
87 if(sample_rate<8000 || sample_rate > 48000) {
88 LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid sample rate (8000~48000Hz) : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,sample_rate);
89 return AUDIO_IO_ERROR_INVALID_PARAMETER;
91 if (channel < AUDIO_CHANNEL_MONO || channel > AUDIO_CHANNEL_STEREO) {
92 LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid audio channel : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,channel);
93 return AUDIO_IO_ERROR_INVALID_PARAMETER;
95 if (type < AUDIO_SAMPLE_TYPE_U8 || type > AUDIO_SAMPLE_TYPE_S16_LE) {
96 LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid sample typel : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,type);
97 return AUDIO_IO_ERROR_INVALID_PARAMETER;
99 return AUDIO_IO_ERROR_NONE;
103 static audio_io_interrupted_code_e __translate_interrupted_code (int code)
105 audio_io_interrupted_code_e e = AUDIO_IO_INTERRUPTED_COMPLETED;
109 case MM_MSG_CODE_INTERRUPTED_BY_ALARM_END:
110 case MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_END:
111 e = AUDIO_IO_INTERRUPTED_COMPLETED;
114 case MM_MSG_CODE_INTERRUPTED_BY_MEDIA:
115 case MM_MSG_CODE_INTERRUPTED_BY_OTHER_PLAYER_APP:
116 e = AUDIO_IO_INTERRUPTED_BY_MEDIA;
119 case MM_MSG_CODE_INTERRUPTED_BY_CALL_START:
120 e = AUDIO_IO_INTERRUPTED_BY_CALL;
123 case MM_MSG_CODE_INTERRUPTED_BY_EARJACK_UNPLUG:
124 e = AUDIO_IO_INTERRUPTED_BY_EARJACK_UNPLUG;
127 case MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT:
128 e = AUDIO_IO_INTERRUPTED_BY_RESOURCE_CONFLICT;
131 case MM_MSG_CODE_INTERRUPTED_BY_ALARM_START:
132 e = AUDIO_IO_INTERRUPTED_BY_ALARM;
135 case MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_START:
136 e = AUDIO_IO_INTERRUPTED_BY_EMERGENCY;
139 case MM_MSG_CODE_INTERRUPTED_BY_RESUMABLE_MEDIA:
140 e = AUDIO_IO_INTERRUPTED_BY_RESUMABLE_MEDIA;
147 static int __mm_sound_pcm_capture_msg_cb (int message, void *param, void *user_param)
149 audio_io_interrupted_code_e e = AUDIO_IO_INTERRUPTED_COMPLETED;
150 audio_in_s *handle = (audio_in_s *) user_param;
151 MMMessageParamType *msg = (MMMessageParamType*)param;
153 LOGI("[%s] Got message type : 0x%x with code : %d" ,__FUNCTION__, message, msg->code);
155 if (handle->user_cb == NULL) {
156 LOGI("[%s] No interrupt callback is set. Skip this" ,__FUNCTION__);
160 if (message == MM_MESSAGE_SOUND_PCM_INTERRUPTED) {
161 e = __translate_interrupted_code (msg->code);
162 } else if (message == MM_MESSAGE_SOUND_PCM_CAPTURE_RESTRICTED) {
163 /* TODO : handling restricted code is needed */
164 /* e = _translate_restricted_code (msg->code); */
167 handle->user_cb (e, handle->user_data);
172 static int __mm_sound_pcm_playback_msg_cb (int message, void *param, void *user_param)
174 audio_io_interrupted_code_e e = AUDIO_IO_INTERRUPTED_COMPLETED;
175 audio_out_s *handle = (audio_out_s *) user_param;
176 MMMessageParamType *msg = (MMMessageParamType*)param;
178 LOGI("[%s] Got message type : 0x%x with code : %d" ,__FUNCTION__, message, msg->code);
180 if (handle->user_cb == NULL) {
181 LOGI("[%s] No interrupt callback is set. Skip this" ,__FUNCTION__);
185 if (message == MM_MESSAGE_SOUND_PCM_INTERRUPTED) {
186 e = __translate_interrupted_code (msg->code);
189 handle->user_cb (e, handle->user_data);
196 * Public Implementation
200 int audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type , audio_in_h* input)
203 audio_in_s *handle = NULL;
205 /* input condition check */
206 AUDIO_IO_NULL_ARG_CHECK(input);
207 if(__check_parameter(sample_rate, channel, type) != AUDIO_IO_ERROR_NONE)
208 return AUDIO_IO_ERROR_INVALID_PARAMETER;
211 handle = (audio_in_s*)malloc( sizeof(audio_in_s));
212 if (handle != NULL) {
213 memset(handle, 0, sizeof(audio_in_s));
215 LOGE("[%s] ERROR : AUDIO_IO_ERROR_OUT_OF_MEMORY(0x%08x)" ,__FUNCTION__, AUDIO_IO_ERROR_OUT_OF_MEMORY );
216 return AUDIO_IO_ERROR_OUT_OF_MEMORY;
219 ret = mm_sound_pcm_capture_open( &handle->mm_handle,sample_rate, channel, type);
222 return __convert_error_code(ret, (char*)__FUNCTION__);
224 LOGI("[%s] mm_sound_pcm_capture_open() success",__FUNCTION__);
226 /* Fill information */
227 *input = (audio_in_h)handle;
228 handle->_buffer_size= ret;
229 handle->_sample_rate= sample_rate;
230 handle->_channel= channel;
233 /* Set message interrupt callback */
234 ret = mm_sound_pcm_set_message_callback(handle->mm_handle, __mm_sound_pcm_capture_msg_cb, handle);
236 return __convert_error_code(ret, (char*)__FUNCTION__);
238 LOGI("[%s] mm_sound_pcm_set_message_callback() success",__FUNCTION__);
240 return AUDIO_IO_ERROR_NONE;
243 int audio_in_destroy(audio_in_h input)
245 AUDIO_IO_NULL_ARG_CHECK(input);
246 audio_in_s *handle = (audio_in_s *) input;
248 int ret = mm_sound_pcm_capture_close(handle->mm_handle);
249 if (ret != MM_ERROR_NONE) {
250 return __convert_error_code(ret, (char*)__FUNCTION__);
254 LOGI("[%s] mm_sound_pcm_capture_close() success",__FUNCTION__);
255 return AUDIO_IO_ERROR_NONE;
258 int audio_in_prepare(audio_in_h input)
260 AUDIO_IO_NULL_ARG_CHECK(input);
261 audio_in_s *handle = (audio_in_s *) input;
263 int ret = mm_sound_pcm_capture_start(handle->mm_handle);
264 if (ret != MM_ERROR_NONE) {
265 return __convert_error_code(ret, (char*)__FUNCTION__);
268 LOGI("[%s] mm_sound_pcm_capture_start() success",__FUNCTION__);
269 return AUDIO_IO_ERROR_NONE;
272 int audio_in_unprepare(audio_in_h input)
274 AUDIO_IO_NULL_ARG_CHECK(input);
275 audio_in_s *handle = (audio_in_s *) input;
277 int ret = mm_sound_pcm_capture_stop(handle->mm_handle);
278 if (ret != MM_ERROR_NONE) {
279 return __convert_error_code(ret, (char*)__FUNCTION__);
282 LOGI("[%s] mm_sound_pcm_capture_stop() success",__FUNCTION__);
283 return AUDIO_IO_ERROR_NONE;
286 int audio_in_read(audio_in_h input, void *buffer, unsigned int length )
288 AUDIO_IO_NULL_ARG_CHECK(input);
289 AUDIO_IO_NULL_ARG_CHECK(buffer);
290 audio_in_s *handle = (audio_in_s *) input;
294 ret = mm_sound_pcm_capture_read(handle->mm_handle, (void*) buffer, length);
296 LOGI("[%s] (%d/%d) bytes read" ,__FUNCTION__, ret, length);
302 case MM_ERROR_SOUND_INVALID_STATE:
303 result = AUDIO_IO_ERROR_INVALID_OPERATION;
304 LOGE("[%s] (0x%08x) : Not recording started yet.",(char*)__FUNCTION__, AUDIO_IO_ERROR_INVALID_OPERATION);
307 result = __convert_error_code(ret, (char*)__FUNCTION__);
313 int audio_in_get_buffer_size(audio_in_h input, int *size)
315 AUDIO_IO_NULL_ARG_CHECK(input);
316 AUDIO_IO_NULL_ARG_CHECK(size);
317 audio_in_s *handle = (audio_in_s *) input;
319 *size = handle->_buffer_size;
321 LOGI("[%s] buffer size = %d",__FUNCTION__, *size);
322 return AUDIO_IO_ERROR_NONE;
325 int audio_in_get_sample_rate(audio_in_h input, int *sample_rate)
327 AUDIO_IO_NULL_ARG_CHECK(input);
328 AUDIO_IO_NULL_ARG_CHECK(sample_rate);
329 audio_in_s *handle = (audio_in_s *) input;
331 *sample_rate = handle->_sample_rate;
333 LOGI("[%s] sample rate = %d",__FUNCTION__, *sample_rate);
334 return AUDIO_IO_ERROR_NONE;
338 int audio_in_get_channel(audio_in_h input, audio_channel_e *channel)
340 AUDIO_IO_NULL_ARG_CHECK(input);
341 AUDIO_IO_NULL_ARG_CHECK(channel);
342 audio_in_s *handle = (audio_in_s *) input;
344 *channel = handle->_channel;
346 LOGI("[%s] channel = %d",__FUNCTION__, *channel);
347 return AUDIO_IO_ERROR_NONE;
350 int audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type)
352 AUDIO_IO_NULL_ARG_CHECK(input);
353 AUDIO_IO_NULL_ARG_CHECK(type);
354 audio_in_s *handle = (audio_in_s *) input;
356 *type = handle->_type;
358 LOGI("[%s] sample type = %d",__FUNCTION__, *type);
359 return AUDIO_IO_ERROR_NONE;
362 int audio_in_set_interrupted_cb(audio_in_h input, audio_io_interrupted_cb callback, void *user_data)
364 AUDIO_IO_NULL_ARG_CHECK(input);
365 AUDIO_IO_NULL_ARG_CHECK(callback);
366 audio_in_s *handle = (audio_in_s *) input;
368 handle->user_cb = callback;
369 handle->user_data = user_data;
371 LOGI("[%s] current interrupted cb (%p) / data (%p)",__FUNCTION__, handle->user_cb, handle->user_data);
372 return AUDIO_IO_ERROR_NONE;
375 int audio_in_unset_interrupted_cb(audio_in_h input)
377 AUDIO_IO_NULL_ARG_CHECK(input);
378 audio_in_s * handle = (audio_in_s *) input;
380 handle->user_cb = NULL;
381 handle->user_data = NULL;
383 LOGI("[%s] current interrupted cb (%p) / data (%p)",__FUNCTION__, handle->user_cb, handle->user_data);
384 return AUDIO_IO_ERROR_NONE;
387 int audio_in_ignore_session(audio_in_h input)
389 AUDIO_IO_NULL_ARG_CHECK(input);
390 audio_in_s * handle = (audio_in_s *) input;
393 ret = mm_sound_pcm_capture_ignore_session(handle->mm_handle);
394 if (ret != MM_ERROR_NONE) {
395 return __convert_error_code(ret, (char*)__FUNCTION__);
398 LOGI("[%s] mm_sound_pcm_capture_ignore_session() success",__FUNCTION__);
399 return AUDIO_IO_ERROR_NONE;
403 int audio_out_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h* output)
405 audio_out_s *handle = NULL;
408 /* input condition check */
409 AUDIO_IO_NULL_ARG_CHECK(output);
410 if(__check_parameter(sample_rate, channel, type)!=AUDIO_IO_ERROR_NONE)
411 return AUDIO_IO_ERROR_INVALID_PARAMETER;
412 if(sound_type < SOUND_TYPE_SYSTEM || sound_type > SOUND_TYPE_CALL) {
413 LOGE("[%s] ERROR : AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid sample sound type : %d" ,__FUNCTION__,AUDIO_IO_ERROR_INVALID_PARAMETER,sound_type );
414 return AUDIO_IO_ERROR_INVALID_PARAMETER;
418 handle = (audio_out_s*)malloc( sizeof(audio_out_s));
419 if (handle != NULL) {
420 memset(handle, 0 , sizeof(audio_out_s));
422 LOGE("[%s] ERROR : AUDIO_IO_ERROR_OUT_OF_MEMORY(0x%08x)" ,__FUNCTION__,AUDIO_IO_ERROR_OUT_OF_MEMORY );
423 return AUDIO_IO_ERROR_OUT_OF_MEMORY;
425 ret = mm_sound_pcm_play_open(&handle->mm_handle,sample_rate, channel, type, sound_type);
428 return __convert_error_code(ret, (char*)__FUNCTION__);
430 LOGI("[%s] mm_sound_pcm_play_open() success",__FUNCTION__);
432 /* Fill information */
433 *output = (audio_out_h)handle;
434 handle->_buffer_size = ret;
435 handle->_sample_rate = sample_rate;
436 handle->_channel = channel;
437 handle->_type = type;
438 handle->_sound_type = sound_type;
440 /* Set message interrupt callback */
441 ret = mm_sound_pcm_set_message_callback(handle->mm_handle, __mm_sound_pcm_playback_msg_cb, handle);
443 return __convert_error_code(ret, (char*)__FUNCTION__);
445 LOGI("[%s] mm_sound_pcm_set_message_callback() success",__FUNCTION__);
447 return AUDIO_IO_ERROR_NONE;
450 int audio_out_destroy(audio_out_h output)
452 AUDIO_IO_NULL_ARG_CHECK(output);
453 audio_out_s *handle = (audio_out_s *) output;
455 int ret = mm_sound_pcm_play_close(handle->mm_handle);
456 if (ret != MM_ERROR_NONE) {
457 return __convert_error_code(ret, (char*)__FUNCTION__);
461 LOGI("[%s] mm_sound_pcm_play_close() success",__FUNCTION__);
462 return AUDIO_IO_ERROR_NONE;
465 int audio_out_prepare(audio_out_h output)
467 AUDIO_IO_NULL_ARG_CHECK(output);
468 audio_out_s *handle = (audio_out_s *) output;
470 int ret = mm_sound_pcm_play_start(handle->mm_handle);
471 if (ret != MM_ERROR_NONE) {
472 return __convert_error_code(ret, (char*)__FUNCTION__);
475 LOGI("[%s] mm_sound_pcm_play_start() success",__FUNCTION__);
476 return AUDIO_IO_ERROR_NONE;
479 int audio_out_unprepare(audio_out_h output)
481 AUDIO_IO_NULL_ARG_CHECK(output);
482 audio_out_s *handle = (audio_out_s *) output;
484 int ret = mm_sound_pcm_play_stop(handle->mm_handle);
485 if (ret != MM_ERROR_NONE) {
486 return __convert_error_code(ret, (char*)__FUNCTION__);
489 LOGI("[%s] mm_sound_pcm_play_stop() success",__FUNCTION__);
490 return AUDIO_IO_ERROR_NONE;
493 int audio_out_write(audio_out_h output, void* buffer, unsigned int length)
495 AUDIO_IO_NULL_ARG_CHECK(output);
496 AUDIO_IO_NULL_ARG_CHECK(buffer);
497 audio_out_s *handle = (audio_out_s *) output;
499 int ret = mm_sound_pcm_play_write(handle->mm_handle, (void*) buffer, length);
501 LOGI("[%s] (%d/%d) bytes written" ,__FUNCTION__, ret, length);
506 case MM_ERROR_SOUND_INVALID_STATE:
507 ret = AUDIO_IO_ERROR_INVALID_OPERATION;
508 LOGE("[%s] (0x%08x) : Not playing started yet.",(char*)__FUNCTION__, AUDIO_IO_ERROR_INVALID_OPERATION);
511 ret = __convert_error_code(ret, (char*)__FUNCTION__);
518 int audio_out_get_buffer_size(audio_out_h output, int *size)
520 AUDIO_IO_NULL_ARG_CHECK(output);
521 AUDIO_IO_NULL_ARG_CHECK(size);
522 audio_out_s *handle = (audio_out_s *) output;
524 *size = handle->_buffer_size;
526 LOGI("[%s] buffer size = %d",__FUNCTION__, *size);
527 return AUDIO_IO_ERROR_NONE;
531 int audio_out_get_sample_rate(audio_out_h output, int *sample_rate)
533 AUDIO_IO_NULL_ARG_CHECK(output);
534 AUDIO_IO_NULL_ARG_CHECK(sample_rate);
535 audio_out_s *handle = (audio_out_s *) output;
537 *sample_rate = handle->_sample_rate;
539 LOGI("[%s] sample rate = %d",__FUNCTION__, *sample_rate);
540 return AUDIO_IO_ERROR_NONE;
544 int audio_out_get_channel(audio_out_h output, audio_channel_e *channel)
546 AUDIO_IO_NULL_ARG_CHECK(output);
547 AUDIO_IO_NULL_ARG_CHECK(channel);
548 audio_out_s *handle = (audio_out_s *) output;
550 *channel = handle->_channel;
552 LOGI("[%s] channel = %d",__FUNCTION__, *channel);
553 return AUDIO_IO_ERROR_NONE;
557 int audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type)
559 AUDIO_IO_NULL_ARG_CHECK(output);
560 AUDIO_IO_NULL_ARG_CHECK(type);
561 audio_out_s *handle = (audio_out_s *) output;
563 *type = handle->_type;
565 LOGI("[%s] sample type = %d",__FUNCTION__, *type);
566 return AUDIO_IO_ERROR_NONE;
570 int audio_out_get_sound_type(audio_out_h output, sound_type_e *type)
572 AUDIO_IO_NULL_ARG_CHECK(output);
573 AUDIO_IO_NULL_ARG_CHECK(type);
574 audio_out_s *handle = (audio_out_s *) output;
576 *type = handle->_sound_type;
578 LOGI("[%s] sound type = %d",__FUNCTION__, *type);
579 return AUDIO_IO_ERROR_NONE;
582 int audio_out_set_interrupted_cb(audio_out_h output, audio_io_interrupted_cb callback, void *user_data)
584 AUDIO_IO_NULL_ARG_CHECK(output);
585 AUDIO_IO_NULL_ARG_CHECK(callback);
586 audio_out_s *handle = (audio_out_s *) output;
588 handle->user_cb = callback;
589 handle->user_data = user_data;
591 LOGI("[%s] current interrupted cb (%p) / data (%p)",__FUNCTION__, handle->user_cb, handle->user_data);
592 return AUDIO_IO_ERROR_NONE;
595 int audio_out_unset_interrupted_cb(audio_out_h output)
597 AUDIO_IO_NULL_ARG_CHECK(output);
598 audio_out_s *handle = (audio_out_s *) output;
600 handle->user_cb = NULL;
601 handle->user_data = NULL;
603 LOGI("[%s] current interrupted cb (%p) / data (%p)",__FUNCTION__, handle->user_cb, handle->user_data);
604 return AUDIO_IO_ERROR_NONE;
607 int audio_out_ignore_session(audio_out_h output)
609 AUDIO_IO_NULL_ARG_CHECK(output);
610 audio_out_s *handle = (audio_out_s *) output;
613 ret = mm_sound_pcm_play_ignore_session(handle->mm_handle);
614 if (ret != MM_ERROR_NONE) {
615 return __convert_error_code(ret, (char*)__FUNCTION__);
617 LOGI("[%s] mm_sound_pcm_play_ignore_session() success",__FUNCTION__);
619 return AUDIO_IO_ERROR_NONE;