4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Seungbae Shin <seungbae.shin@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
27 #include <sys/types.h>
37 #include <mm_message.h>
39 #include "include/mm_sound_private.h"
40 #include "include/mm_sound.h"
41 #include "include/mm_sound_utils.h"
42 #include "include/mm_sound_client.h"
43 #include "include/mm_ipc.h"
44 #include "include/mm_sound_common.h"
47 #include <audio-session-manager.h>
48 #include <mm_session.h>
49 #include <mm_session_private.h>
51 #define MAX_FILE_LENGTH 256
52 #define MAX_MEMORY_SIZE 1048576 /* Max memory size 1024*1024 (1MB) */
53 #define _MIN_SYSTEM_SAMPLERATE 8000
54 #define _MAX_SYSTEM_SAMPLERATE 48000
55 #define MIN_TONE_PLAY_TIME 300
58 volume_callback_fn func;
63 volume_cb_param g_volume_param[VOLUME_TYPE_MAX];
65 static pthread_mutex_t _volume_mutex = PTHREAD_MUTEX_INITIALIZER;
67 #define PCM_LOCK_INTERNAL(LOCK) do { pthread_mutex_lock(LOCK); } while (0)
68 #define PCM_UNLOCK_INTERNAL(LOCK) do { pthread_mutex_unlock(LOCK); } while (0)
69 #define PCM_LOCK_DESTROY_INTERNAL(LOCK) do { pthread_mutex_destroy(LOCK); } while (0)
72 avsys_handle_t audio_handle;
74 ASM_sound_events_t asm_event;
79 pthread_mutex_t pcm_mutex_internal;
80 MMMessageCallback msg_cb;
86 static int _pcm_sound_start (MMSoundPcmHandle_t handle);
87 static int _pcm_sound_stop_internal (MMSoundPcmHandle_t handle);
88 static int _pcm_sound_stop(MMSoundPcmHandle_t handle);
90 static void __sound_pcm_send_message (mm_sound_pcm_t *pcmHandle, int message, int code);
91 static int _pcm_sound_ignore_session (MMSoundPcmHandle_t handle);
93 static int __validate_volume(volume_type_t type, int value)
100 case VOLUME_TYPE_CALL:
101 case VOLUME_TYPE_VOIP:
102 if (value >= AVSYS_AUDIO_VOLUME_MAX_BASIC) {
106 case VOLUME_TYPE_SYSTEM:
107 case VOLUME_TYPE_MEDIA:
108 case VOLUME_TYPE_ALARM:
109 case VOLUME_TYPE_EXT_JAVA:
110 case VOLUME_TYPE_NOTIFICATION:
111 case VOLUME_TYPE_RINGTONE:
112 if (value >= AVSYS_AUDIO_VOLUME_MAX_MULTIMEDIA) {
116 case VOLUME_TYPE_EXT_ANDROID:
117 if (value >= AVSYS_AUDIO_VOLUME_MAX_SINGLE) {
128 static void volume_changed_cb(keynode_t* node, void* data)
130 volume_cb_param* param = (volume_cb_param*) data;
132 debug_msg("%s changed callback called\n",vconf_keynode_get_name(node));
134 MMSOUND_ENTER_CRITICAL_SECTION( &_volume_mutex )
136 if(param && (param->func != NULL)) {
137 debug_msg("funcion 0x%x\n", param->func);
138 ((volume_callback_fn)param->func)(param->data);
141 MMSOUND_LEAVE_CRITICAL_SECTION( &_volume_mutex )
145 int mm_sound_volume_add_callback(volume_type_t type, volume_callback_fn func, void* user_data)
149 /* Check input param */
150 if (type < 0 || type >= VOLUME_TYPE_MAX) {
151 return MM_ERROR_INVALID_ARGUMENT;
154 debug_warning("callback function is null\n");
155 return MM_ERROR_INVALID_ARGUMENT;
158 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN( &_volume_mutex, MM_ERROR_SOUND_INTERNAL );
160 g_volume_param[type].func = func;
161 g_volume_param[type].data = user_data;
162 g_volume_param[type].type = type;
164 MMSOUND_LEAVE_CRITICAL_SECTION( &_volume_mutex );
166 return _mm_sound_volume_add_callback(type, volume_changed_cb, (void*)&g_volume_param[type]);
170 int mm_sound_volume_remove_callback(volume_type_t type)
174 if(type < 0 || type >=VOLUME_TYPE_MAX) {
175 return MM_ERROR_INVALID_ARGUMENT;
178 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN( &_volume_mutex, MM_ERROR_SOUND_INTERNAL );
180 g_volume_param[type].func = NULL;
181 g_volume_param[type].data = NULL;
182 g_volume_param[type].type = type;
184 MMSOUND_LEAVE_CRITICAL_SECTION( &_volume_mutex );
186 return _mm_sound_volume_remove_callback(type, volume_changed_cb);
190 int mm_sound_get_volume_step(volume_type_t type, int *step)
192 printf("\n**********\n\nTHIS FUNCTION HAS DEFPRECATED [%s]\n\n \
193 use mm_sound_volume_get_step() instead\n\n**********\n", __func__);
194 return mm_sound_volume_get_step(type, step);
198 int mm_sound_volume_get_step(volume_type_t type, int *step)
204 /* Check input param */
206 debug_error("second parameter is null\n");
207 return MM_ERROR_INVALID_ARGUMENT;
209 if (type < 0 || type >= VOLUME_TYPE_MAX) {
210 debug_error("Invalid type value %d\n", (int)type);
211 return MM_ERROR_INVALID_ARGUMENT;
214 err = avsys_audio_get_volume_max_ex((int)type, step);
215 if (AVSYS_FAIL(err)) {
216 return MM_ERROR_INVALID_ARGUMENT;
220 return MM_ERROR_NONE;
224 int mm_sound_volume_set_value(volume_type_t type, const unsigned int value)
226 int ret = MM_ERROR_NONE;
230 debug_warning ("%s : type=[%d], value=[%d]\n", __func__, type, value);
232 /* Check input param */
233 if (0 > __validate_volume(type, (int)value)) {
234 debug_error("invalid volume type %d, value %u\n", type, value);
235 return MM_ERROR_INVALID_ARGUMENT;
238 ret = _mm_sound_volume_set_value_by_type(type, value);
239 if (ret == MM_ERROR_NONE) {
240 /* update shared memory value */
241 if (AVSYS_FAIL(avsys_audio_set_volume_by_type(type, (int)value))) {
242 debug_error("Can not set volume to shared memory 0x%x\n", ret);
251 int mm_sound_volume_get_value(volume_type_t type, unsigned int *value)
253 int ret = MM_ERROR_NONE;
257 /* Check input param */
259 return MM_ERROR_INVALID_ARGUMENT;
260 if (type < 0 || type >= VOLUME_TYPE_MAX) {
261 debug_error("invalid volume type value %d\n", type);
262 return MM_ERROR_INVALID_ARGUMENT;
265 ret = _mm_sound_volume_get_value_by_type(type, value);
272 int mm_sound_volume_primary_type_set(volume_type_t type)
275 int ret = MM_ERROR_NONE;
277 /* Check input param */
278 if(type < 0 || type >= VOLUME_TYPE_MAX)
279 return MM_ERROR_INVALID_ARGUMENT;
284 if(AVSYS_FAIL(avsys_audio_set_primary_volume((int)mypid, type))) {
285 debug_error("Can not set primary volume [%d, %d]\n", mypid, type);
286 ret = MM_ERROR_SOUND_INTERNAL;
294 int mm_sound_volume_primary_type_clear()
297 int ret = MM_ERROR_NONE;
302 if(AVSYS_FAIL(avsys_audio_clear_primary_volume((int)mypid))) {
303 debug_error("Can not clear primary volume [%d]\n", mypid);
304 ret = MM_ERROR_SOUND_INTERNAL;
312 int mm_sound_volume_get_current_playing_type(volume_type_t *type)
314 int result = AVSYS_STATE_SUCCESS;
315 int voltype = AVSYS_AUDIO_VOLUME_TYPE_RINGTONE;
316 int ret = MM_ERROR_NONE;
320 /* Check input param */
322 return MM_ERROR_INVALID_ARGUMENT;
325 result = avsys_audio_get_current_playing_volume_type(&voltype);
328 case AVSYS_STATE_SUCCESS:
331 case AVSYS_STATE_ERR_ALLOCATION:
332 ret = MM_ERROR_SOUND_VOLUME_NO_INSTANCE;
334 case AVSYS_STATE_ERR_INVALID_MODE:
335 ret = MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY;
338 ret = MM_ERROR_SOUND_INTERNAL;
341 debug_log("avsys_audio_get_current_playing_volume_type() = %x, ret = %x, type = %d\n", result, ret, *type);
347 ///////////////////////////////////
348 //// MMSOUND PCM APIs
349 ///////////////////////////////////
352 int _get_asm_event_type(ASM_sound_events_t *type)
354 int sessionType = MM_SESSION_TYPE_SHARE;
355 ASM_sound_events_t asm_event;
358 return MM_ERROR_SOUND_INVALID_POINTER;
360 /* read session type */
361 if(_mm_session_util_read_type(-1, &sessionType) < 0) {
362 debug_log("Read Session Type failed. Set default \"Share\" type\n");
363 sessionType = MM_SESSION_TYPE_SHARE;
364 if(mm_session_init(sessionType) < 0) {
365 debug_error("mm_session_init() failed\n");
366 return MM_ERROR_SOUND_INTERNAL;
370 /* convert MM_SESSION_TYPE to ASM_EVENT_TYPE */
373 case MM_SESSION_TYPE_SHARE:
374 asm_event = ASM_EVENT_SHARE_MMSOUND;
376 case MM_SESSION_TYPE_EXCLUSIVE:
377 asm_event = ASM_EVENT_EXCLUSIVE_MMSOUND;
379 case MM_SESSION_TYPE_NOTIFY:
380 asm_event = ASM_EVENT_NOTIFY;
382 case MM_SESSION_TYPE_ALARM:
383 asm_event = ASM_EVENT_ALARM;
385 case MM_SESSION_TYPE_CALL:
386 asm_event = ASM_EVENT_CALL;
388 case MM_SESSION_TYPE_VIDEOCALL:
389 asm_event = ASM_EVENT_VIDEOCALL;
391 case MM_SESSION_TYPE_RICH_CALL:
392 asm_event = ASM_EVENT_RICH_CALL;
394 case MM_SESSION_TYPE_EMERGENCY:
395 asm_event = ASM_EVENT_EMERGENCY;
398 debug_error("Unexpected %d\n", sessionType);
399 return MM_ERROR_SOUND_INTERNAL;
403 return MM_ERROR_NONE;
406 static void __sound_pcm_send_message (mm_sound_pcm_t *pcmHandle, int message, int code)
409 if (pcmHandle->msg_cb) {
410 MMMessageParamType msg;
411 msg.union_type = MM_MSG_UNION_CODE;
414 debug_log ("calling msg callback(%p) with message(%d), code(%d), msg callback param(%p)\n",
415 pcmHandle->msg_cb, message, msg.code, pcmHandle->msg_cb_param);
416 ret = pcmHandle->msg_cb(message, &msg, pcmHandle->msg_cb_param);
417 debug_log ("msg callback returned (%d)\n", ret);
419 debug_log ("No pcm msg callback\n");
423 ASM_cb_result_t sound_pcm_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void *cb_data)
425 mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t *)cb_data;
426 ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
428 /* Check input param */
429 if(pcmHandle == NULL) {
430 debug_error("sound_pcm_asm_callback cb_data is null\n");
434 debug_log ("command = %d, handle = %p, is_started = %d\n",command, pcmHandle, pcmHandle->is_started);
437 case ASM_COMMAND_STOP:
439 PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
440 _pcm_sound_stop_internal (pcmHandle);
441 PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
442 cb_res = ASM_CB_RES_PAUSE;
445 case ASM_COMMAND_RESUME:
446 cb_res = ASM_CB_RES_IGNORE;
449 case ASM_COMMAND_PAUSE:
450 case ASM_COMMAND_PLAY:
451 case ASM_COMMAND_NONE:
452 debug_error ("Not an expected case!!!!\n");
456 /* execute user callback if callback available */
457 __sound_pcm_send_message (pcmHandle, MM_MESSAGE_SOUND_PCM_INTERRUPTED, event_src);
462 static int _pcm_sound_ignore_session (MMSoundPcmHandle_t handle)
464 int result = MM_ERROR_NONE;
465 mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
470 /* Check input param */
471 if(pcmHandle == NULL) {
472 debug_error ("Handle is null, return Invalid Argument\n");
473 result = MM_ERROR_INVALID_ARGUMENT;
477 if (pcmHandle->is_started) {
478 debug_error ("Operation is not permitted while started\n");
479 result = MM_ERROR_SOUND_INVALID_STATE;
483 PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
486 if (pcmHandle->skip_session == false && pcmHandle->asm_handle) {
487 if(!ASM_unregister_sound(pcmHandle->asm_handle, pcmHandle->asm_event, &errorcode)) {
488 debug_error("ASM_unregister failed in %s with 0x%x\n", __func__, errorcode);
489 result = MM_ERROR_SOUND_INTERNAL;
491 pcmHandle->skip_session = true;
492 pcmHandle->asm_handle = 0;
495 PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
503 int mm_sound_pcm_capture_open(MMSoundPcmHandle_t *handle, const unsigned int rate, MMSoundPcmChannel_t channel, MMSoundPcmFormat_t format)
505 avsys_audio_param_t param;
506 mm_sound_pcm_t *pcmHandle = NULL;
508 int result = AVSYS_STATE_SUCCESS;
513 debug_warning ("%s enter : rate=[%d], channel=[%x], format=[%x]\n", __func__, rate, channel, format);
515 memset(¶m, 0, sizeof(avsys_audio_param_t));
518 if (rate < _MIN_SYSTEM_SAMPLERATE || rate > _MAX_SYSTEM_SAMPLERATE) {
519 debug_error("unsupported sample rate %u", rate);
520 return MM_ERROR_SOUND_DEVICE_INVALID_SAMPLERATE;
522 param.samplerate = rate;
527 case MMSOUND_PCM_MONO:
530 case MMSOUND_PCM_STEREO:
535 debug_error("Unsupported channel type\n");
536 return MM_ERROR_SOUND_DEVICE_INVALID_CHANNEL;
542 param.format = AVSYS_AUDIO_FORMAT_8BIT;
544 case MMSOUND_PCM_S16_LE:
545 param.format = AVSYS_AUDIO_FORMAT_16BIT;
548 debug_error("Unsupported format type\n");
549 return MM_ERROR_SOUND_DEVICE_INVALID_FORMAT;
552 pcmHandle = calloc(sizeof(mm_sound_pcm_t), 1);
553 if(pcmHandle == NULL)
554 return MM_ERROR_OUT_OF_MEMORY;
556 ret_mutex = pthread_mutex_init(&pcmHandle->pcm_mutex_internal, NULL);
560 return MM_ERROR_OUT_OF_MEMORY;
564 /* get session type */
565 if(MM_ERROR_NONE != _get_asm_event_type(&pcmHandle->asm_event)) {
566 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
568 return MM_ERROR_POLICY_INTERNAL;
571 if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
572 if(!ASM_register_sound(-1, &pcmHandle->asm_handle, pcmHandle->asm_event,
573 /* ASM_STATE_PLAYING */ ASM_STATE_NONE, sound_pcm_asm_callback, (void*)pcmHandle, ASM_RESOURCE_NONE, &errorcode))
575 debug_error("ASM_register_sound() failed 0x%x\n", errorcode);
576 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
578 return MM_ERROR_POLICY_BLOCKED;
583 param.mode = AVSYS_AUDIO_MODE_INPUT;
584 param.vol_type = AVSYS_AUDIO_VOLUME_TYPE_SYSTEM; //dose not effect at capture mode
585 param.priority = AVSYS_AUDIO_PRIORITY_0; //This does not affect anymore.
586 result = avsys_audio_open(¶m, &pcmHandle->audio_handle, &size);
587 if(AVSYS_FAIL(result)) {
588 debug_error("Device Open Error 0x%x\n", result);
589 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
591 return MM_ERROR_SOUND_DEVICE_NOT_OPENED;
594 pcmHandle->is_playback = false;
596 /* Set handle to return */
597 *handle = (MMSoundPcmHandle_t)pcmHandle;
599 debug_warning ("%s success : handle=[%p]\n", __func__, handle);
605 int mm_sound_pcm_capture_ignore_session(MMSoundPcmHandle_t *handle)
607 return _pcm_sound_ignore_session(handle);
610 static int _pcm_sound_start (MMSoundPcmHandle_t handle)
612 mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
618 /* Check input param */
619 if(pcmHandle == NULL) {
620 debug_error ("Handle is null, return Invalid Argument\n");
621 ret = MM_ERROR_INVALID_ARGUMENT;
625 PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
627 if (pcmHandle->skip_session == false) {
628 /* ASM set state to PLAYING */
629 if (!ASM_set_sound_state(pcmHandle->asm_handle, pcmHandle->asm_event, ASM_STATE_PLAYING, ASM_RESOURCE_NONE, &errorcode)) {
630 debug_error("ASM_set_sound_state(PLAYING) failed 0x%x\n", errorcode);
631 ret = MM_ERROR_POLICY_BLOCKED;
637 pcmHandle->is_started = true;
640 ret = avsys_audio_cork(pcmHandle->audio_handle, 0);
643 PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
652 int mm_sound_pcm_capture_start(MMSoundPcmHandle_t handle)
654 int ret = MM_ERROR_NONE;
657 debug_warning ("%s enter : handle=[%p]\n", __func__, handle);
659 ret = _pcm_sound_start (handle);
660 if (ret != MM_ERROR_NONE) {
661 debug_error ("_pcm_sound_start() failed (%x)\n", ret);
666 debug_warning ("%s success : handle=[%p]\n", __func__, handle);
672 static int _pcm_sound_stop_internal (MMSoundPcmHandle_t handle)
674 mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
676 /* Check input param */
677 if(pcmHandle == NULL)
678 return MM_ERROR_INVALID_ARGUMENT;
681 if (pcmHandle->is_started == false) {
682 debug_warning ("Can't stop because not started\n");
683 return MM_ERROR_SOUND_INVALID_STATE;
686 /* Drain if playback mode */
687 if (pcmHandle->is_playback) {
688 if(AVSYS_FAIL(avsys_audio_drain(pcmHandle->audio_handle))) {
689 debug_error("drain failed\n");
694 pcmHandle->is_started = false;
697 return avsys_audio_cork(pcmHandle->audio_handle, 1);
700 static int _pcm_sound_stop(MMSoundPcmHandle_t handle)
702 mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
704 int ret = MM_ERROR_NONE;
708 /* Check input param */
709 if(pcmHandle == NULL) {
710 debug_error ("Handle is null, return Invalid Argument\n");
711 ret = MM_ERROR_INVALID_ARGUMENT;
715 PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
717 /* Do stop procedure */
718 ret = _pcm_sound_stop_internal(handle);
719 if (ret == MM_ERROR_NONE) {
720 /* Set ASM State to STOP */
721 if (pcmHandle->skip_session == false) {
722 if (!ASM_set_sound_state(pcmHandle->asm_handle, pcmHandle->asm_event, ASM_STATE_STOP, ASM_RESOURCE_NONE, &errorcode)) {
723 debug_error("ASM_set_sound_state(STOP) failed 0x%x\n", errorcode);
724 ret = MM_ERROR_POLICY_BLOCKED;
730 debug_log ("pcm sound [%p] stopped success!!!\n", handle);
733 PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
741 int mm_sound_pcm_capture_stop(MMSoundPcmHandle_t handle)
746 debug_warning ("%s enter : handle=[%p]\n", __func__, handle);
748 ret = _pcm_sound_stop(handle);
750 debug_warning ("%s success : handle=[%p]\n", __func__, handle);
758 int mm_sound_pcm_capture_read(MMSoundPcmHandle_t handle, void *buffer, const unsigned int length )
761 mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
763 /* Check input param */
764 if(pcmHandle == NULL) {
765 debug_error ("Handle is null, return Invalid Argument\n");
766 ret = MM_ERROR_INVALID_ARGUMENT;
769 PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
772 debug_error("Invalid buffer pointer\n");
773 ret = MM_ERROR_SOUND_INVALID_POINTER;
777 debug_error ("length is 0, return 0\n");
782 /* Check State : return fail if not started */
783 if (!pcmHandle->is_started) {
784 /* not started, return fail */
785 debug_error ("Not started yet, return Invalid State \n");
786 ret = MM_ERROR_SOUND_INVALID_STATE;
791 ret = avsys_audio_read(pcmHandle->audio_handle, buffer, length);
794 PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
800 int mm_sound_pcm_capture_close(MMSoundPcmHandle_t handle)
802 int result = MM_ERROR_NONE;
803 mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
808 debug_warning ("%s enter : handle=[%p]\n", __func__, handle);
810 /* Check input param */
811 if(pcmHandle == NULL) {
812 debug_error ("Handle is null, return Invalid Argument\n");
813 result = MM_ERROR_INVALID_ARGUMENT;
816 PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
818 result = avsys_audio_close(pcmHandle->audio_handle);
819 if(AVSYS_FAIL(result)) {
820 debug_error("handle close failed 0x%X", result);
821 result = MM_ERROR_SOUND_INTERNAL;
826 if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
827 if(!ASM_unregister_sound(pcmHandle->asm_handle, pcmHandle->asm_event, &errorcode)) {
828 debug_error("ASM_unregister failed in %s with 0x%x\n", __func__, errorcode);
829 result = MM_ERROR_SOUND_INTERNAL;
834 debug_log ("pcm capture sound [%p] closed success!!!\n", handle);
837 PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
841 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
845 debug_warning ("%s success : handle=[%p]\n", __func__, handle);
851 int mm_sound_pcm_set_message_callback (MMSoundPcmHandle_t handle, MMMessageCallback callback, void *user_param)
853 mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
855 if(pcmHandle == NULL || callback == NULL)
856 return MM_ERROR_INVALID_ARGUMENT;
858 pcmHandle->msg_cb = callback;
859 pcmHandle->msg_cb_param = user_param;
861 debug_log ("set pcm message callback (%p,%p)\n", callback, user_param);
863 return MM_ERROR_NONE;
868 int mm_sound_pcm_play_open_ex (MMSoundPcmHandle_t *handle, const unsigned int rate, MMSoundPcmChannel_t channel, MMSoundPcmFormat_t format, int volume_config, ASM_sound_events_t asm_event)
870 avsys_audio_param_t param;
871 mm_sound_pcm_t *pcmHandle = NULL;
873 int result = AVSYS_STATE_SUCCESS;
875 int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(volume_config);
879 debug_warning ("%s enter : rate=[%d], channel=[%x], format=[%x]\n", __func__, rate, channel, format);
881 memset(¶m, 0, sizeof(avsys_audio_param_t));
883 /* Check input param */
884 if (volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
885 debug_error("Volume type is invalid %d\n", volume_type);
886 return MM_ERROR_INVALID_ARGUMENT;
888 if (rate < _MIN_SYSTEM_SAMPLERATE || rate > _MAX_SYSTEM_SAMPLERATE) {
889 debug_error("unsupported sample rate %u", rate);
890 return MM_ERROR_SOUND_DEVICE_INVALID_SAMPLERATE;
892 param.samplerate = rate;
897 case MMSOUND_PCM_MONO:
900 case MMSOUND_PCM_STEREO:
904 debug_error("Unsupported channel type\n");
905 return MM_ERROR_SOUND_DEVICE_INVALID_CHANNEL;
911 param.format = AVSYS_AUDIO_FORMAT_8BIT;
913 case MMSOUND_PCM_S16_LE:
914 param.format = AVSYS_AUDIO_FORMAT_16BIT;
917 debug_error("Unsupported format type\n");
918 return MM_ERROR_SOUND_DEVICE_INVALID_FORMAT;
921 pcmHandle = calloc(sizeof(mm_sound_pcm_t),1);
922 if(pcmHandle == NULL)
923 return MM_ERROR_OUT_OF_MEMORY;
925 ret_mutex = pthread_mutex_init(&pcmHandle->pcm_mutex_internal, NULL);
929 return MM_ERROR_OUT_OF_MEMORY;
933 debug_log ("session start : input asm_event = %d-------------\n", asm_event);
934 if (asm_event == ASM_EVENT_MONITOR) {
935 debug_log ("Skip SESSION for event (%d)\n", asm_event);
936 pcmHandle->skip_session = true;
937 } else if (asm_event == ASM_EVENT_NONE) {
938 /* get session type */
939 if(MM_ERROR_NONE != _get_asm_event_type(&pcmHandle->asm_event)) {
940 debug_error ("_get_asm_event_type failed....\n");
941 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
943 return MM_ERROR_POLICY_INTERNAL;
946 if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
948 if(!ASM_register_sound(-1, &pcmHandle->asm_handle, pcmHandle->asm_event,
949 ASM_STATE_NONE, sound_pcm_asm_callback, (void*)pcmHandle, ASM_RESOURCE_NONE, &errorcode)) {
950 debug_error("ASM_register_sound() failed 0x%x\n", errorcode);
951 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
953 return MM_ERROR_POLICY_BLOCKED;
957 /* register asm using asm_event input */
958 if(!ASM_register_sound(-1, &pcmHandle->asm_handle, asm_event,
959 ASM_STATE_NONE, NULL, (void*)pcmHandle, ASM_RESOURCE_NONE, &errorcode)) {
960 debug_error("ASM_register_sound() failed 0x%x\n", errorcode);
961 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
963 return MM_ERROR_POLICY_BLOCKED;
967 param.mode = AVSYS_AUDIO_MODE_OUTPUT;
968 param.vol_type = volume_config;
969 param.priority = AVSYS_AUDIO_PRIORITY_0;
971 // avsys_audio_ampon();
974 debug_log ("avsys open -------------\n");
975 result = avsys_audio_open(¶m, &pcmHandle->audio_handle, &size);
976 if(AVSYS_FAIL(result)) {
977 debug_error("Device Open Error 0x%x\n", result);
978 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
980 return MM_ERROR_SOUND_DEVICE_NOT_OPENED;
983 pcmHandle->is_playback = true;
985 /* Set handle to return */
986 *handle = (MMSoundPcmHandle_t)pcmHandle;
988 debug_warning ("%s success : handle=[%p]\n", __func__, handle);
994 int mm_sound_pcm_play_open_no_session(MMSoundPcmHandle_t *handle, const unsigned int rate, MMSoundPcmChannel_t channel, MMSoundPcmFormat_t format)
996 return mm_sound_pcm_play_open_ex (handle, rate, channel, format, VOLUME_TYPE_SYSTEM, ASM_EVENT_MONITOR);
1000 int mm_sound_pcm_play_open(MMSoundPcmHandle_t *handle, const unsigned int rate, MMSoundPcmChannel_t channel, MMSoundPcmFormat_t format, const volume_type_t vol_type)
1002 return mm_sound_pcm_play_open_ex (handle, rate, channel, format, vol_type, ASM_EVENT_NONE);
1006 int mm_sound_pcm_play_start(MMSoundPcmHandle_t handle)
1010 debug_warning ("%s enter : handle=[%p]\n", __func__, handle);
1011 ret = _pcm_sound_start (handle);
1012 debug_warning ("%s success : handle=[%p]\n", __func__, handle);
1020 int mm_sound_pcm_play_stop(MMSoundPcmHandle_t handle)
1024 debug_warning ("%s enter : handle=[%p]\n", __func__, handle);
1025 ret = _pcm_sound_stop(handle);
1026 debug_warning ("%s success : handle=[%p]\n", __func__, handle);
1033 int mm_sound_pcm_play_write(MMSoundPcmHandle_t handle, void* ptr, unsigned int length_byte)
1036 mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
1038 /* Check input param */
1039 if(pcmHandle == NULL) {
1040 debug_error ("Handle is null, return Invalid Argument\n");
1041 ret = MM_ERROR_INVALID_ARGUMENT;
1045 PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
1048 debug_error("Invalid buffer pointer\n");
1049 ret = MM_ERROR_SOUND_INVALID_POINTER;
1052 if(length_byte == 0 ) {
1053 debug_error ("length is 0, return 0\n");
1058 /* Check State : return fail if not started */
1059 if (!pcmHandle->is_started) {
1060 /* not started, return fail */
1061 debug_error ("Not started yet, return Invalid State \n");
1062 ret = MM_ERROR_SOUND_INVALID_STATE;
1067 ret = avsys_audio_write(pcmHandle->audio_handle, ptr, length_byte);
1070 PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
1076 int mm_sound_pcm_play_close(MMSoundPcmHandle_t handle)
1078 int result = MM_ERROR_NONE;
1079 mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
1083 debug_warning ("%s enter : handle=[%p]\n", __func__, handle);
1085 /* Check input param */
1086 if(pcmHandle == NULL) {
1087 debug_error ("Handle is null, return Invalid Argument\n");
1088 result = MM_ERROR_INVALID_ARGUMENT;
1091 PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
1092 /* Drain if needed */
1093 if (pcmHandle->is_started) {
1094 /* stop() is not called before close(), drain is needed */
1095 if(AVSYS_FAIL(avsys_audio_drain(pcmHandle->audio_handle))) {
1096 debug_error("drain failed\n");
1097 result = MM_ERROR_SOUND_INTERNAL;
1101 pcmHandle->is_started = false;
1103 result = avsys_audio_close(pcmHandle->audio_handle);
1104 if(AVSYS_FAIL(result)) {
1105 debug_error("handle close failed 0x%X", result);
1106 result = MM_ERROR_SOUND_INTERNAL;
1110 if (pcmHandle->skip_session == false) {
1111 /* Unregister ASM */
1112 if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
1113 if(!ASM_unregister_sound(pcmHandle->asm_handle, pcmHandle->asm_event, &errorcode)) {
1114 debug_error("ASM_unregister failed in %s with 0x%x\n",__func__, errorcode);
1115 result = MM_ERROR_SOUND_INTERNAL;
1121 debug_log ("pcm play sound [%p] closed success!!!\n", handle);
1125 PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
1129 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
1133 debug_warning ("%s success : handle=[%p]\n", __func__, handle);
1139 int mm_sound_pcm_play_ignore_session(MMSoundPcmHandle_t *handle)
1141 return _pcm_sound_ignore_session(handle);
1145 ///////////////////////////////////
1146 //// MMSOUND PLAY APIs
1147 ///////////////////////////////////
1148 static inline void _mm_sound_fill_play_param(MMSoundPlayParam *param, const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int priority, int handle_route)
1150 param->filename = filename;
1151 param->volume = 0; //volume value dose not effect anymore
1152 param->callback = callback;
1155 param->volume_config = volume_config;
1156 param->priority = priority;
1157 param->handle_route = handle_route;
1161 int mm_sound_play_loud_solo_sound_no_restore(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
1163 MMSoundPlayParam param = { 0, };
1165 _mm_sound_fill_play_param(¶m, filename, volume_config, callback, data, AVSYS_AUDIO_PRIORITY_SOLO, MM_SOUND_HANDLE_ROUTE_SPEAKER_NO_RESTORE);
1166 return mm_sound_play_sound_ex(¶m, handle);
1170 int mm_sound_play_loud_solo_sound(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
1172 MMSoundPlayParam param = { 0, };
1174 _mm_sound_fill_play_param(¶m, filename, volume_config, callback, data, AVSYS_AUDIO_PRIORITY_SOLO, MM_SOUND_HANDLE_ROUTE_SPEAKER);
1175 return mm_sound_play_sound_ex(¶m, handle);
1179 int mm_sound_play_solo_sound(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
1181 MMSoundPlayParam param = { 0, };
1183 _mm_sound_fill_play_param(¶m, filename, volume_config, callback, data, AVSYS_AUDIO_PRIORITY_SOLO, MM_SOUND_HANDLE_ROUTE_USING_CURRENT);
1184 return mm_sound_play_sound_ex(¶m, handle);
1188 int mm_sound_play_sound(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
1190 MMSoundPlayParam param = { 0, };
1192 _mm_sound_fill_play_param(¶m, filename, volume_config, callback, data, AVSYS_AUDIO_PRIORITY_NORMAL, MM_SOUND_HANDLE_ROUTE_USING_CURRENT);
1193 return mm_sound_play_sound_ex(¶m, handle);
1197 int mm_sound_play_sound_ex(MMSoundPlayParam *param, int *handle)
1201 int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(param->volume_config);
1205 /* Check input param */
1206 if (param == NULL) {
1207 debug_error("param is null\n");
1208 return MM_ERROR_INVALID_ARGUMENT;
1210 if (param->filename == NULL) {
1211 debug_error("filename is NULL\n");
1212 return MM_ERROR_SOUND_FILE_NOT_FOUND;
1214 if (volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
1215 debug_error("Volume type is invalid %d\n", volume_type);
1216 return MM_ERROR_INVALID_ARGUMENT;
1219 debug_warning ("%s enter : priority=[%d], handle_route=[%d]\n", __func__, param->priority, param->handle_route);
1222 err = MMSoundClientPlaySound(param, 0, 0, &lhandle);
1224 debug_error("Failed to play sound\n");
1228 /* Set handle to return */
1232 debug_critical("The sound hadle cannot be get [%d]\n", lhandle);
1235 debug_warning ("%s success : handle=[%p]\n", __func__, handle);
1237 return MM_ERROR_NONE;
1242 int mm_sound_stop_sound(int handle)
1247 debug_warning ("%s enter : handle=[%p]\n", __func__, handle);
1249 err = MMSoundClientStopSound(handle);
1251 debug_error("Fail to stop sound\n");
1254 debug_warning ("%s success : handle=[%p]\n", __func__, handle);
1256 return MM_ERROR_NONE;
1259 ///////////////////////////////////
1260 //// MMSOUND TONE APIs
1261 ///////////////////////////////////
1263 int mm_sound_play_tone (MMSoundTone_t num, int volume_config, const double volume, const int duration, int *handle)
1266 int err = MM_ERROR_NONE;
1267 int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(volume_config);
1271 /* Check input param */
1272 if (duration < -1) {
1273 debug_error("number is invalid %d\n", duration);
1274 return MM_ERROR_INVALID_ARGUMENT;
1276 if (num < MM_SOUND_TONE_DTMF_0 || num >= MM_SOUND_TONE_NUM) {
1277 debug_error("TONE Value is invalid %d\n", num);
1278 return MM_ERROR_INVALID_ARGUMENT;
1280 if (volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
1281 debug_error("Volume type is invalid %d\n", volume_type);
1282 return MM_ERROR_INVALID_ARGUMENT;
1284 if (volume < 0.0 || volume > 1.0) {
1285 debug_error("Volume Value is invalid %d\n", volume);
1286 return MM_ERROR_INVALID_ARGUMENT;
1290 debug_msg("Call MMSoundClientPlayTone\n");
1291 err = MMSoundClientPlayTone(num, volume_config, volume, duration, &lhandle);
1293 debug_error("Failed to play sound\n");
1297 /* Set handle to return */
1301 debug_critical("The sound handle cannot be get [%d]\n", lhandle);
1304 return MM_ERROR_NONE;
1307 ///////////////////////////////////
1308 //// MMSOUND ROUTING APIs
1309 ///////////////////////////////////
1311 int mm_sound_set_path(int gain, int output, int input, int option)
1317 debug_msg("gain: 0x%02X, output: %d, input: %d, option: 0x%x\n", gain, output, input, option);
1319 err = avsys_audio_set_path_ex( gain, output, input, option);
1321 debug_error("avsys_audio_set_path() failed\n");
1322 return MM_ERROR_SOUND_INTERNAL;
1326 return MM_ERROR_NONE;
1330 int mm_sound_get_path(int *gain, int *output, int *input, int *option)
1336 err = avsys_audio_get_path_ex( gain, output, input, option);
1338 debug_error("SoundCtlPathGet() failed\n");
1339 return MM_ERROR_SOUND_INTERNAL;
1342 debug_msg("gain: 0x%02X, output: %d, input: %d, option: 0x%x\n", *gain, *output, *input, *option);
1345 return MM_ERROR_NONE;
1350 USE_PA_SINK_ALSA = 0,
1354 int mm_sound_route_set_system_policy (system_audio_route_t route)
1356 return MM_ERROR_NONE;
1361 int mm_sound_route_get_system_policy (system_audio_route_t *route)
1363 return MM_ERROR_NONE;
1368 int mm_sound_route_get_a2dp_status (bool *connected, char **bt_name)
1370 int ret = MM_ERROR_NONE;
1374 if (connected == NULL || bt_name == NULL) {
1375 debug_error ("argument is not valid\n");
1376 return MM_ERROR_INVALID_ARGUMENT;
1379 ret = MMSoundClientIsBtA2dpOn (connected, bt_name);
1380 debug_msg ("connected=[%d] bt_name[%s]\n", *connected, *bt_name);
1382 debug_error("MMSoundClientIsBtA2dpOn() Failed\n");
1392 int mm_sound_route_get_playing_device(system_audio_route_device_t *dev)
1394 mm_sound_device_in device_in = MM_SOUND_DEVICE_IN_NONE;
1395 mm_sound_device_out device_out = MM_SOUND_DEVICE_OUT_NONE;
1398 return MM_ERROR_INVALID_ARGUMENT;
1400 if(MM_ERROR_NONE != mm_sound_get_active_device(&device_in, &device_out)) {
1401 debug_error("Can not get active device info\n");
1402 return MM_ERROR_SOUND_INTERNAL;
1407 case MM_SOUND_DEVICE_OUT_SPEAKER:
1408 *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_HANDSET;
1410 case MM_SOUND_DEVICE_OUT_BT_A2DP:
1411 *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_BLUETOOTH;
1413 case MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY:
1414 *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_EARPHONE;
1417 *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_NONE;
1421 return MM_ERROR_NONE;
1425 int mm_sound_route_add_change_callback(audio_route_policy_changed_callback_fn func, void *user_data)
1428 return MM_ERROR_NONE;
1432 int mm_sound_route_remove_change_callback()
1435 return MM_ERROR_NONE;
1438 #endif /* PULSE_CLIENT */
1441 int mm_sound_system_get_capture_status(system_audio_capture_status_t *status)
1443 int err = AVSYS_STATE_SUCCESS;
1447 return MM_ERROR_INVALID_ARGUMENT;
1449 err = avsys_audio_get_capture_status(&on_capture);
1451 debug_error("Can not get capture status with 0x%x\n", err);
1452 return MM_ERROR_SOUND_INTERNAL;
1456 *status = SYSTEM_AUDIO_CAPTURE_ACTIVE;
1458 *status = SYSTEM_AUDIO_CAPTURE_NONE;
1460 return MM_ERROR_NONE;
1464 int mm_sound_is_route_available(mm_sound_route route, bool *is_available)
1466 int ret = MM_ERROR_NONE;
1469 debug_warning ("%s enter : route=[%x]\n", __func__, route);
1470 if (!_mm_sound_is_route_valid(route)) {
1471 debug_error("route is invalid %d\n", route);
1472 return MM_ERROR_INVALID_ARGUMENT;
1476 debug_error("is_available is invalid\n");
1477 return MM_ERROR_INVALID_ARGUMENT;
1480 ret = _mm_sound_client_is_route_available(route, is_available);
1482 debug_error("Can not check given route is available\n");
1484 debug_warning ("%s success : route=[%x], available=[%d]\n", __func__, route, *is_available);
1490 int mm_sound_foreach_available_route_cb(mm_sound_available_route_cb available_route_cb, void *user_data)
1492 int ret = MM_ERROR_NONE;
1496 if (!available_route_cb)
1498 debug_error("available_route_cb is invalid\n");
1499 return MM_ERROR_INVALID_ARGUMENT;
1502 ret = _mm_sound_client_foreach_available_route_cb(available_route_cb, user_data);
1504 debug_error("Can not set foreach available route callback\n");
1512 int mm_sound_set_active_route(mm_sound_route route)
1514 int ret = MM_ERROR_NONE;
1517 debug_warning ("%s enter : route=[%x]\n", __func__, route);
1518 if (!_mm_sound_is_route_valid(route)) {
1519 debug_error("route is invalid %d\n", route);
1520 return MM_ERROR_INVALID_ARGUMENT;
1523 ret = _mm_sound_client_set_active_route(route);
1525 debug_error("Can not set active route\n");
1527 debug_warning ("%s success : route=[%x]\n", __func__, route);
1534 int mm_sound_get_active_device(mm_sound_device_in *device_in, mm_sound_device_out *device_out)
1536 int ret = MM_ERROR_NONE;
1539 debug_warning ("%s enter\n", __func__);
1540 if (device_in == NULL || device_out == NULL) {
1541 debug_error("argument is not valid\n");
1542 return MM_ERROR_INVALID_ARGUMENT;
1545 ret = _mm_sound_client_get_active_device(device_in, device_out);
1547 debug_error("Can not add active device callback\n");
1549 debug_warning ("%s success : in=[%x], out=[%x]\n", __func__, *device_in, *device_out);
1555 int mm_sound_add_active_device_changed_callback(mm_sound_active_device_changed_cb func, void *user_data)
1557 int ret = MM_ERROR_NONE;
1562 debug_error("argument is not valid\n");
1563 return MM_ERROR_INVALID_ARGUMENT;
1566 ret = _mm_sound_client_add_active_device_changed_callback(func, user_data);
1568 debug_error("Can not add active device changed callback\n");
1576 int mm_sound_remove_active_device_changed_callback(void)
1578 int ret = MM_ERROR_NONE;
1582 ret = _mm_sound_client_remove_active_device_changed_callback();
1584 debug_error("Can not remove active device changed callback\n");
1592 int mm_sound_add_available_route_changed_callback(mm_sound_available_route_changed_cb func, void *user_data)
1594 int ret = MM_ERROR_NONE;
1599 debug_error("argument is not valid\n");
1600 return MM_ERROR_INVALID_ARGUMENT;
1603 ret = _mm_sound_client_add_available_route_changed_callback(func, user_data);
1605 debug_error("Can not add available route changed callback\n");
1613 int mm_sound_remove_available_route_changed_callback(void)
1615 int ret = MM_ERROR_NONE;
1619 ret = _mm_sound_client_remove_available_route_changed_callback();
1621 debug_error("Can not remove available route changed callback\n");
1628 __attribute__ ((destructor))
1629 void __mmfsnd_finalize(void)
1633 MMSoundClientCallbackFini();
1638 __attribute__ ((constructor))
1639 void __mmfsnd_initialize(void)