summaryrefslogtreecommitdiff
path: root/mm_sound.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm_sound.c')
-rw-r--r--mm_sound.c1487
1 files changed, 1487 insertions, 0 deletions
diff --git a/mm_sound.c b/mm_sound.c
new file mode 100644
index 0000000..e5d6988
--- /dev/null
+++ b/mm_sound.c
@@ -0,0 +1,1487 @@
+/*
+ * libmm-sound
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Seungbae Shin <seungbae.shin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <memory.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include <sys/stat.h>
+#include <errno.h>
+#include <avsystem.h>
+
+#include <vconf.h>
+#include <mm_types.h>
+#include <mm_error.h>
+#include <mm_message.h>
+#include <mm_debug.h>
+#include "include/mm_sound_private.h"
+#include "include/mm_sound.h"
+#include "include/mm_sound_client.h"
+#include "include/mm_ipc.h"
+#include "include/mm_sound_common.h"
+
+
+#include <audio-session-manager.h>
+#include <mm_session.h>
+#include <mm_session_private.h>
+
+#define MAX_FILE_LENGTH 256
+#define MAX_MEMORY_SIZE 1048576 /* Max memory size 1024*1024 (1MB) */
+#define _MIN_SYSTEM_SAMPLERATE 8000
+#define _MAX_SYSTEM_SAMPLERATE 44100
+#define MIN_TONE_PLAY_TIME 300
+
+typedef struct {
+ volume_callback_fn func;
+ void* data;
+ volume_type_t type;
+}volume_cb_param;
+
+volume_cb_param g_volume_param[VOLUME_TYPE_MAX];
+
+static pthread_mutex_t _volume_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int _validate_volume(volume_type_t type, int value)
+{
+ if (value < 0)
+ return -1;
+
+ switch (type)
+ {
+
+ case VOLUME_TYPE_ALARM:
+ case VOLUME_TYPE_CALL:
+ if (value >= AVSYS_AUDIO_VOLUME_MAX_BASIC)
+ {
+ return -1;
+ }
+ break;
+ case VOLUME_TYPE_SYSTEM:
+ case VOLUME_TYPE_MEDIA:
+ case VOLUME_TYPE_EXT_JAVA:
+ case VOLUME_TYPE_NOTIFICATION:
+ case VOLUME_TYPE_RINGTONE:
+ if (value >= AVSYS_AUDIO_VOLUME_MAX_MULTIMEDIA)
+ {
+ return -1;
+ }
+ break;
+ case VOLUME_TYPE_EXT_ANDROID:
+ if (value >= AVSYS_AUDIO_VOLUME_MAX_SINGLE)
+ {
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ break;
+ }
+ return 0;
+}
+
+void volume_changed_cb(keynode_t* node, void* data)
+{
+ volume_cb_param* param = (volume_cb_param*) data;
+
+ debug_msg("%s changed callback called\n",vconf_keynode_get_name(node));
+
+ MMSOUND_ENTER_CRITICAL_SECTION( &_volume_mutex )
+
+ if(param && (param->func != NULL)) {
+ debug_msg("funcion 0x%x\n", param->func);
+ ((volume_callback_fn)param->func)(param->data);
+ }
+
+ MMSOUND_LEAVE_CRITICAL_SECTION( &_volume_mutex )
+}
+
+EXPORT_API
+int mm_sound_volume_add_callback(volume_type_t type, volume_callback_fn func, void* user_data)
+{
+ char *keystr[] = {VCONF_KEY_VOLUME_TYPE_SYSTEM, VCONF_KEY_VOLUME_TYPE_NOTIFICATION, VCONF_KEY_VOLUME_TYPE_ALARM,
+ VCONF_KEY_VOLUME_TYPE_RINGTONE, VCONF_KEY_VOLUME_TYPE_MEDIA, VCONF_KEY_VOLUME_TYPE_CALL,
+ VCONF_KEY_VOLUME_TYPE_ANDROID,VCONF_KEY_VOLUME_TYPE_JAVA};
+ debug_fenter();
+
+ if(type < VOLUME_TYPE_SYSTEM || type >=VOLUME_TYPE_MAX) {
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if(!func) {
+ debug_warning("callback function is null\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN( &_volume_mutex, MM_ERROR_SOUND_INTERNAL )
+
+ g_volume_param[type].func = func;
+ g_volume_param[type].data = user_data;
+ g_volume_param[type].type = type;
+
+ MMSOUND_LEAVE_CRITICAL_SECTION( &_volume_mutex )
+
+ return vconf_notify_key_changed(keystr[type], volume_changed_cb, (void*)&g_volume_param[type]);
+}
+
+EXPORT_API
+int mm_sound_volume_remove_callback(volume_type_t type)
+{
+ char *keystr[] = {VCONF_KEY_VOLUME_TYPE_SYSTEM, VCONF_KEY_VOLUME_TYPE_NOTIFICATION, VCONF_KEY_VOLUME_TYPE_ALARM,
+ VCONF_KEY_VOLUME_TYPE_RINGTONE, VCONF_KEY_VOLUME_TYPE_MEDIA, VCONF_KEY_VOLUME_TYPE_CALL,
+ VCONF_KEY_VOLUME_TYPE_ANDROID,VCONF_KEY_VOLUME_TYPE_JAVA};
+ debug_fenter();
+
+ if(type < VOLUME_TYPE_SYSTEM || type >=VOLUME_TYPE_MAX) {
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN( &_volume_mutex, MM_ERROR_SOUND_INTERNAL )
+
+ g_volume_param[type].func = NULL;
+ g_volume_param[type].data = NULL;
+ g_volume_param[type].type = type;
+
+ MMSOUND_LEAVE_CRITICAL_SECTION( &_volume_mutex )
+
+ return vconf_ignore_key_changed(keystr[type], volume_changed_cb);
+}
+
+EXPORT_API
+int mm_sound_get_volume_step(volume_type_t type, int *step)
+{
+ printf("\n**********\n\nTHIS FUNCTION HAS DEFPRECATED [%s]\n\n \
+ use mm_sound_volume_get_step() instead\n\n**********\n", __func__);
+ return mm_sound_volume_get_step(type, step);
+}
+
+EXPORT_API
+int mm_sound_volume_get_step(volume_type_t type, int *step)
+{
+ int err;
+ debug_fenter();
+ if(step == NULL)
+ {
+ debug_error("second parameter is null\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+ if(type < VOLUME_TYPE_SYSTEM || type >= VOLUME_TYPE_MAX)
+ {
+ debug_error("Invalid type value %d\n", (int)type);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+ err = avsys_audio_get_volume_max_ex((int)type, step);
+
+ if (AVSYS_FAIL(err))
+ {
+ err = MM_ERROR_INVALID_ARGUMENT;
+ }
+ return MM_ERROR_NONE;
+}
+
+EXPORT_API
+int mm_sound_volume_set_value(volume_type_t type, const unsigned int value)
+{
+ int ret = MM_ERROR_NONE;
+ char *keystr[] = {VCONF_KEY_VOLUME_TYPE_SYSTEM, VCONF_KEY_VOLUME_TYPE_NOTIFICATION, VCONF_KEY_VOLUME_TYPE_ALARM,
+ VCONF_KEY_VOLUME_TYPE_RINGTONE, VCONF_KEY_VOLUME_TYPE_MEDIA, VCONF_KEY_VOLUME_TYPE_CALL,
+ VCONF_KEY_VOLUME_TYPE_ANDROID,VCONF_KEY_VOLUME_TYPE_JAVA};
+
+ debug_fenter();
+ if(0 > _validate_volume(type, (int)value)) {
+ debug_error("invalid volume type %d, value %u\n", type, value);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if(vconf_set_int(keystr[type], value)){
+ debug_error("Can not set %s as %d\n", keystr[type], value);
+ ret = MM_ERROR_SOUND_INTERNAL;
+ }
+ else {
+ //update shared memory value
+ ret = avsys_audio_set_volume_by_type(type, value);
+ if(AVSYS_FAIL(ret)) {
+ debug_error("Can not set volume to shared memory 0x%x\n", ret);
+ }
+ }
+
+ return ret;
+}
+
+EXPORT_API
+int mm_sound_volume_get_value(volume_type_t type, unsigned int *value)
+{
+ int ret = MM_ERROR_NONE;
+ char *keystr[] = {VCONF_KEY_VOLUME_TYPE_SYSTEM, VCONF_KEY_VOLUME_TYPE_NOTIFICATION, VCONF_KEY_VOLUME_TYPE_ALARM,
+ VCONF_KEY_VOLUME_TYPE_RINGTONE, VCONF_KEY_VOLUME_TYPE_MEDIA, VCONF_KEY_VOLUME_TYPE_CALL,
+ VCONF_KEY_VOLUME_TYPE_ANDROID,VCONF_KEY_VOLUME_TYPE_JAVA};
+
+ debug_fenter();
+ if(value == NULL)
+ return MM_ERROR_INVALID_ARGUMENT;
+
+ if(type < 0 || type >= VOLUME_TYPE_MAX) {
+ debug_error("invalid volume type value %d\n", type);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if(vconf_get_int(keystr[type], (int*)value)) {
+ debug_error("Can not get value of %s\n", keystr[type]);
+ ret = MM_ERROR_SOUND_INTERNAL;
+ }
+
+ return ret;
+}
+
+EXPORT_API
+int mm_sound_volume_primary_type_set(volume_type_t type)
+{
+ pid_t mypid;
+ int ret = MM_ERROR_NONE;
+
+ if(type < VOLUME_TYPE_SYSTEM || type >= VOLUME_TYPE_MAX)
+ return MM_ERROR_INVALID_ARGUMENT;
+
+ debug_fenter();
+ mypid = getpid();
+ if(AVSYS_FAIL(avsys_audio_set_primary_volume((int)mypid, type)))
+ {
+ debug_error("Can not set primary volume [%d, %d]\n", mypid, type);
+ ret = MM_ERROR_SOUND_INTERNAL;
+ }
+
+ return ret;
+}
+
+EXPORT_API
+int mm_sound_volume_primary_type_clear()
+{
+ pid_t mypid;
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+ mypid = getpid();
+ if(AVSYS_FAIL(avsys_audio_clear_primary_volume((int)mypid)))
+ {
+ debug_error("Can not clear primary volume [%d]\n", mypid);
+ ret = MM_ERROR_SOUND_INTERNAL;
+ }
+
+ return ret;
+}
+
+EXPORT_API
+int mm_sound_volume_get_current_playing_type(volume_type_t *type)
+{
+ int result = AVSYS_STATE_SUCCESS;
+ int voltype = AVSYS_AUDIO_VOLUME_TYPE_SYSTEM;
+
+ debug_fenter();
+ if(type == NULL) {
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ result = avsys_audio_get_current_playing_volume_type(&voltype);
+ if(result == AVSYS_STATE_SUCCESS) {
+ *type = voltype;
+ return MM_ERROR_NONE;
+ }
+ else if(result ==AVSYS_STATE_ERR_ALLOCATION ) {
+ return MM_ERROR_SOUND_VOLUME_NO_INSTANCE;
+ }
+ else if(result == AVSYS_STATE_ERR_INVALID_MODE) {
+ return MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY;
+ }
+ else {
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+}
+
+///////////////////////////////////
+//// MMSOUND PCM APIs
+///////////////////////////////////
+
+typedef struct {
+ avsys_handle_t audio_handle;
+ int asm_handle;
+ ASM_sound_events_t asm_event;
+ int asm_valid_flag;
+} mm_sound_pcm_t;
+
+int _get_asm_event_type(ASM_sound_events_t *type)
+{
+ int sessionType = MM_SESSION_TYPE_SHARE;
+ ASM_sound_events_t asm_event;
+
+ if(type == NULL)
+ return MM_ERROR_SOUND_INVALID_POINTER;
+
+ // read session type
+ if(_mm_session_util_read_type(-1, &sessionType) < 0)
+ {
+ debug_error("Read Session Type failed. Set default \"Share\" type\n");
+ sessionType = MM_SESSION_TYPE_SHARE;
+ if(mm_session_init(sessionType) < 0)
+ {
+ debug_error("mm_session_init() failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ }
+
+ // convert MM_SESSION_TYPE to ASM_EVENT_TYPE
+ switch(sessionType)
+ {
+ case MM_SESSION_TYPE_SHARE:
+ asm_event = ASM_EVENT_SHARE_MMSOUND;
+ break;
+ case MM_SESSION_TYPE_EXCLUSIVE:
+ asm_event = ASM_EVENT_EXCLUSIVE_MMSOUND;
+ break;
+ case MM_SESSION_TYPE_NOTIFY:
+ asm_event = ASM_EVENT_NOTIFY;
+ break;
+ case MM_SESSION_TYPE_ALARM:
+ asm_event = ASM_EVENT_ALARM;
+ break;
+ case MM_SESSION_TYPE_CALL:
+ asm_event = ASM_EVENT_CALL;
+ break;
+ case MM_SESSION_TYPE_VIDEOCALL:
+ asm_event = ASM_EVENT_VIDEOCALL;
+ break;
+ default:
+ debug_error("Unexpected %d\n", sessionType);
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ *type = asm_event;
+ return MM_ERROR_NONE;
+}
+
+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)
+{
+ mm_sound_pcm_t *pcmHandle = NULL;
+
+ ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
+
+ pcmHandle = (mm_sound_pcm_t*)cb_data;
+ if(pcmHandle == NULL)
+ {
+ debug_error("sound_pcm_asm_callback cb_data is null\n");
+ return cb_res;
+ }
+
+ debug_log ("command = %d, handle = %p, asm_valid_flag = %d\n",command, pcmHandle, pcmHandle->asm_valid_flag);
+ switch(command)
+ {
+ case ASM_COMMAND_STOP:
+ case ASM_COMMAND_PAUSE:
+ pcmHandle->asm_valid_flag = 0;
+ cb_res = ASM_CB_RES_PAUSE;
+ break;
+ case ASM_COMMAND_PLAY:
+ case ASM_COMMAND_RESUME:
+ pcmHandle->asm_valid_flag = 1;
+ cb_res = ASM_CB_RES_PLAYING;
+ break;
+ }
+
+ return cb_res;
+}
+
+EXPORT_API
+int mm_sound_pcm_capture_open(MMSoundPcmHandle_t *handle, const unsigned int rate, MMSoundPcmChannel_t channel, MMSoundPcmFormat_t format)
+{
+ avsys_audio_param_t param;
+ mm_sound_pcm_t *pcmHandle = NULL;
+ int size = 0;
+ int result = AVSYS_STATE_SUCCESS;
+ int errorcode = 0;
+
+ memset(&param, 0, sizeof(avsys_audio_param_t));
+
+ if(rate < _MIN_SYSTEM_SAMPLERATE || rate > _MAX_SYSTEM_SAMPLERATE)
+ {
+ debug_error("unsupported sample rate %u", rate);
+ return MM_ERROR_SOUND_DEVICE_INVALID_SAMPLERATE;
+ }
+ else
+ {
+ param.samplerate = rate;
+ }
+
+ switch(channel)
+ {
+ case MMSOUND_PCM_MONO:
+ param.channels = 1;
+ break;
+ case MMSOUND_PCM_STEREO:
+ debug_error("Capture does not support stereo for now\n");
+ break;
+
+ default:
+ debug_error("Unsupported channel type\n");
+ return MM_ERROR_SOUND_DEVICE_INVALID_CHANNEL;
+ }
+
+ switch(format)
+ {
+ case MMSOUND_PCM_U8:
+ param.format = AVSYS_AUDIO_FORMAT_8BIT;
+ break;
+ case MMSOUND_PCM_S16_LE:
+ param.format = AVSYS_AUDIO_FORMAT_16BIT;
+ break;
+ default:
+ debug_error("Unsupported format type\n");
+ return MM_ERROR_SOUND_DEVICE_INVALID_FORMAT;
+ }
+
+ pcmHandle = calloc(sizeof(mm_sound_pcm_t), 1);
+ if(pcmHandle == NULL)
+ return MM_ERROR_OUT_OF_MEMORY;
+
+ //get session type
+ if(MM_ERROR_NONE != _get_asm_event_type(&pcmHandle->asm_event)) {
+ free(pcmHandle);
+ return MM_ERROR_POLICY_INTERNAL;
+ }
+ //register asm as playing
+ if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
+ if(!ASM_register_sound(-1, &pcmHandle->asm_handle, pcmHandle->asm_event,
+ ASM_STATE_PLAYING, sound_pcm_asm_callback, (void*)pcmHandle, ASM_RESOURCE_NONE, &errorcode))
+ {
+ debug_error("ASM_register_sound() failed 0x%x\n", errorcode);
+ free(pcmHandle);
+ return MM_ERROR_POLICY_BLOCKED;
+ }
+ }
+ //set asm valid flag
+ pcmHandle->asm_valid_flag = 1;
+
+ param.mode = AVSYS_AUDIO_MODE_INPUT;
+ param.vol_type = AVSYS_AUDIO_VOLUME_TYPE_SYSTEM; //dose not effect at capture mode
+ param.priority = AVSYS_AUDIO_PRIORITY_0; //This does not affect anymore.
+
+ result = avsys_audio_open(&param, &pcmHandle->audio_handle, &size);
+ if(AVSYS_FAIL(result))
+ {
+ debug_error("Device Open Error 0x%x\n", result);
+ free(pcmHandle);
+ return MM_ERROR_SOUND_DEVICE_NOT_OPENED;
+ }
+
+ *handle = (MMSoundPcmHandle_t)pcmHandle;
+
+ return size;
+}
+
+EXPORT_API
+int mm_sound_pcm_capture_read(MMSoundPcmHandle_t handle, void *buffer, const unsigned int length )
+{
+ mm_sound_pcm_t *pcmHandle = NULL;
+
+ pcmHandle = (mm_sound_pcm_t*)handle;
+ if(pcmHandle == NULL)
+ return MM_ERROR_INVALID_ARGUMENT;
+
+ if(buffer == NULL)
+ {
+ debug_error("Invalid buffer pointer\n");
+ return MM_ERROR_SOUND_INVALID_POINTER;
+ }
+
+ if(!pcmHandle->asm_valid_flag)
+ {
+ return MM_ERROR_POLICY_INTERRUPTED;
+ }
+
+ if(length == 0 )
+ return 0;
+
+ return avsys_audio_read(pcmHandle->audio_handle, buffer, length);
+}
+
+EXPORT_API
+int mm_sound_pcm_capture_close(MMSoundPcmHandle_t handle)
+{
+ int result = MM_ERROR_NONE;
+ mm_sound_pcm_t *pcmHandle = NULL;
+ int errorcode = 0;
+
+ pcmHandle = (mm_sound_pcm_t*)handle;
+ if(pcmHandle==NULL)
+ return MM_ERROR_INVALID_ARGUMENT;
+
+ result = avsys_audio_close(pcmHandle->audio_handle);
+ if(AVSYS_FAIL(result))
+ {
+ debug_error("handle close failed 0x%X", result);
+ result = MM_ERROR_SOUND_INTERNAL;
+ }
+
+ if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL)
+ {
+ if(!ASM_unregister_sound(pcmHandle->asm_handle, pcmHandle->asm_event, &errorcode))
+ {
+ debug_error("ASM_unregister failed in %s with 0x%x\n", __func__, errorcode);
+ }
+ pcmHandle->asm_valid_flag = 0;
+ }
+ free(pcmHandle); pcmHandle= NULL;
+
+ return result;
+}
+
+
+EXPORT_API
+int mm_sound_pcm_play_open_ex (MMSoundPcmHandle_t *handle, const unsigned int rate, MMSoundPcmChannel_t channel, MMSoundPcmFormat_t format, const volume_type_t vol_type, ASM_sound_events_t asm_event)
+{
+ avsys_audio_param_t param;
+ mm_sound_pcm_t *pcmHandle = NULL;
+ int size = 0;
+ int result = AVSYS_STATE_SUCCESS;
+ int lvol_type = vol_type;
+ int errorcode = 0;
+
+ debug_fenter();
+ memset(&param, 0, sizeof(avsys_audio_param_t));
+
+ if(vol_type < 0) {
+ debug_error("Volume type should not be negative value\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+
+ if(vol_type >= VOLUME_TYPE_MAX) {
+ debug_error("Volume type should be under VOLUME_TYPE_MAX\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if(rate < _MIN_SYSTEM_SAMPLERATE || rate > _MAX_SYSTEM_SAMPLERATE)
+ {
+ debug_error("unsupported sample rate %u", rate);
+ return MM_ERROR_SOUND_DEVICE_INVALID_SAMPLERATE;
+ }
+ else
+ {
+ param.samplerate = rate;
+ }
+
+ switch(channel)
+ {
+ case MMSOUND_PCM_MONO:
+ param.channels = 1;
+ break;
+ case MMSOUND_PCM_STEREO:
+ param.channels = 2;
+ break;
+ default:
+ debug_error("Unsupported channel type\n");
+ return MM_ERROR_SOUND_DEVICE_INVALID_CHANNEL;
+ }
+
+ switch(format)
+ {
+ case MMSOUND_PCM_U8:
+ param.format = AVSYS_AUDIO_FORMAT_8BIT;
+ break;
+ case MMSOUND_PCM_S16_LE:
+ param.format = AVSYS_AUDIO_FORMAT_16BIT;
+ break;
+ default:
+ debug_error("Unsupported format type\n");
+ return MM_ERROR_SOUND_DEVICE_INVALID_FORMAT;
+ }
+
+ pcmHandle = calloc(sizeof(mm_sound_pcm_t),1);
+ if(pcmHandle == NULL)
+ return MM_ERROR_OUT_OF_MEMORY;
+
+ debug_log ("session start : input asm_event = %d-------------\n", asm_event);
+ //get session type
+ if (asm_event == ASM_EVENT_NONE) {
+
+ if(MM_ERROR_NONE != _get_asm_event_type(&pcmHandle->asm_event)) {
+ free(pcmHandle);
+ return MM_ERROR_POLICY_INTERNAL;
+ }
+ //register asm as playing
+ if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
+ if(!ASM_register_sound(-1, &pcmHandle->asm_handle, pcmHandle->asm_event,
+ ASM_STATE_PLAYING, sound_pcm_asm_callback, (void*)pcmHandle, ASM_RESOURCE_NONE, &errorcode))
+ {
+ debug_error("ASM_register_sound() failed 0x%x\n", errorcode);
+ free(pcmHandle);
+ return MM_ERROR_POLICY_BLOCKED;
+ }
+ }
+ } else {
+ if(!ASM_register_sound(-1, &pcmHandle->asm_handle, asm_event,
+ ASM_STATE_PLAYING, NULL, (void*)pcmHandle, ASM_RESOURCE_NONE, &errorcode))
+ {
+ debug_error("ASM_register_sound() failed 0x%x\n", errorcode);
+ free(pcmHandle);
+ return MM_ERROR_POLICY_BLOCKED;
+ }
+ }
+ //set asm valid flag
+ pcmHandle->asm_valid_flag = 1;
+
+ param.mode = AVSYS_AUDIO_MODE_OUTPUT;
+ param.vol_type = lvol_type;
+ param.priority = AVSYS_AUDIO_PRIORITY_0;
+
+// avsys_audio_ampon();
+
+ debug_log ("avsys open -------------\n");
+ result = avsys_audio_open(&param, &pcmHandle->audio_handle, &size);
+ if(AVSYS_FAIL(result))
+ {
+ debug_error("Device Open Error 0x%x\n", result);
+ free(pcmHandle);
+ return MM_ERROR_SOUND_DEVICE_NOT_OPENED;
+ }
+
+ *handle = (MMSoundPcmHandle_t)pcmHandle;
+
+ debug_fleave();
+
+ return size;
+}
+
+EXPORT_API
+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)
+{
+ return mm_sound_pcm_play_open_ex (handle, rate, channel, format, vol_type, ASM_EVENT_NONE);
+}
+
+EXPORT_API
+int mm_sound_pcm_play_write(MMSoundPcmHandle_t handle, void* ptr, unsigned int length_byte)
+{
+ mm_sound_pcm_t *pcmHandle = NULL;
+
+ pcmHandle = (mm_sound_pcm_t*)handle;
+ if(pcmHandle == NULL)
+ return MM_ERROR_INVALID_ARGUMENT;
+
+ if(ptr == NULL)
+ {
+ debug_error("Invalid buffer pointer\n");
+ return MM_ERROR_SOUND_INVALID_POINTER;
+ }
+
+ if(!pcmHandle->asm_valid_flag)
+ return MM_ERROR_POLICY_INTERRUPTED;
+
+ if(length_byte == 0 )
+ return 0;
+
+ return avsys_audio_write(pcmHandle->audio_handle, ptr, length_byte);
+}
+
+EXPORT_API
+int mm_sound_pcm_play_close(MMSoundPcmHandle_t handle)
+{
+ int result = AVSYS_STATE_SUCCESS;
+ mm_sound_pcm_t *pcmHandle = NULL;
+ int errorcode = 0;
+
+ pcmHandle = (mm_sound_pcm_t*)handle;
+ if(pcmHandle == NULL)
+ return MM_ERROR_INVALID_ARGUMENT;
+
+ if(AVSYS_FAIL(avsys_audio_drain(pcmHandle->audio_handle)))
+ {
+ debug_error("drain failed\n");
+ }
+
+ result = avsys_audio_close(pcmHandle->audio_handle);
+ if(AVSYS_FAIL(result))
+ {
+ debug_error("handle close failed 0x%X", result);
+ result = MM_ERROR_SOUND_INTERNAL;
+ }
+
+ if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL)
+ {
+ if(!ASM_unregister_sound(pcmHandle->asm_handle, pcmHandle->asm_event, &errorcode))
+ {
+ debug_error("ASM_unregister failed in %s with 0x%x\n",__func__, errorcode);
+ }
+ pcmHandle->asm_valid_flag = 0;
+ }
+ free(pcmHandle); pcmHandle= NULL;
+ return result;
+}
+
+///////////////////////////////////
+//// MMSOUND PLAY APIs
+///////////////////////////////////
+EXPORT_API
+int mm_sound_play_loud_solo_sound(const char *filename, const volume_type_t volume_type, mm_sound_stop_callback_func callback, void *data, int *handle)
+{
+ MMSoundParamType param = { 0, };
+ int err;
+ int lhandle = -1;
+ int lvol_type = volume_type;
+
+ debug_fenter();
+
+ if(filename == NULL)
+ {
+ debug_error("filename is NULL\n");
+ return MM_ERROR_SOUND_FILE_NOT_FOUND;
+ }
+
+ if(volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
+ debug_error("Volume type should not be negative value\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ param.filename = filename;
+ param.volume = 0; //volume value dose not effect anymore
+ param.callback = callback;
+ param.data = data;
+ param.loop = 1;
+ param.volume_table = lvol_type;
+ param.priority = AVSYS_AUDIO_PRIORITY_SOLO;
+ param.bluetooth = MMSOUNDPARAM_SPEAKER_ONLY;
+
+ err = MMSoundClientPlaySound(&param, 0, 0, &lhandle);
+
+ if (err < 0) {
+ debug_error("Failed to play sound\n");
+ return err;
+ }
+
+ debug_fleave();
+ if (handle) {
+ *handle = lhandle;
+ }
+ else {
+ debug_critical("The sound handle cannot be get [%d]\n", lhandle);
+ }
+
+ return MM_ERROR_NONE;
+}
+
+EXPORT_API
+int mm_sound_play_solo_sound(const char *filename, const volume_type_t volume_type, mm_sound_stop_callback_func callback, void *data, int *handle)
+{
+ MMSoundParamType param = { 0, };
+ int err;
+ int lhandle = -1;
+ int lvol_type = volume_type;
+
+ debug_fenter();
+
+ if(filename == NULL)
+ {
+ debug_error("filename is NULL\n");
+ return MM_ERROR_SOUND_FILE_NOT_FOUND;
+ }
+
+ if(volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
+ debug_error("Volume type should not be negative value\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ param.filename = filename;
+ param.volume = 0; //volume value dose not effect anymore
+ param.callback = callback;
+ param.data = data;
+ param.loop = 1;
+ param.volume_table = lvol_type;
+ param.priority = AVSYS_AUDIO_PRIORITY_SOLO;
+ param.bluetooth = MMSOUNDPARAM_FOLLOWING_ROUTE_POLICY;
+
+ err = MMSoundClientPlaySound(&param, 0, 0, &lhandle);
+ if (err < 0) {
+ debug_error("Failed to play sound\n");
+ return err;
+ }
+
+ if (handle) {
+ *handle = lhandle;
+ }
+ else {
+ debug_critical("The sound handle cannot be get [%d]\n", lhandle);
+ }
+ debug_fleave();
+ return MM_ERROR_NONE;
+}
+
+
+EXPORT_API
+int mm_sound_play_sound(const char *filename, const volume_type_t volume_type, mm_sound_stop_callback_func callback, void *data, int *handle)
+{
+ MMSoundParamType param = { 0, };
+ int err;
+ int lhandle = -1;
+ int lvol_type = volume_type;
+
+ debug_fenter();
+
+ if(filename == NULL)
+ {
+ debug_error("filename is NULL\n");
+ return MM_ERROR_SOUND_FILE_NOT_FOUND;
+ }
+
+ if(volume_type < 0) {
+ debug_error("Volume type should not be negative value\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if(volume_type >= VOLUME_TYPE_MAX) {
+ debug_error("Volume type should be under VOLUME_TYPE_MAX\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ param.filename = filename;
+ param.volume = 0; //volume value dose not effect anymore
+ param.callback = callback;
+ param.data = data;
+ param.loop = 1;
+ param.volume_table = lvol_type;
+ param.priority = AVSYS_AUDIO_PRIORITY_NORMAL;
+ param.bluetooth = AVSYS_AUDIO_HANDLE_ROUTE_FOLLOWING_POLICY;
+
+ err = MMSoundClientPlaySound(&param, 0, 0, &lhandle);
+
+ if (err < 0) {
+ debug_error("Failed to play sound\n");
+ return err;
+ }
+
+ if (handle) {
+ *handle = lhandle;
+ }
+ else {
+ debug_critical("The sound handle cannot be get [%d]\n", lhandle);
+ }
+ debug_fleave();
+ return MM_ERROR_NONE;
+}
+
+
+EXPORT_API
+int mm_sound_play_sound_ex(MMSoundParamType *param, int *handle)
+{
+ int err;
+ int lhandle = -1;
+
+ debug_fenter();
+
+ if (param == NULL) {
+ debug_error("param is null\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ err = MMSoundClientPlaySound(param, 0, 0, &lhandle);
+
+ if (err < 0) {
+ debug_error("Failed to play sound\n");
+ return err;
+ }
+
+ if (handle) {
+ *handle = lhandle;
+ }
+ else {
+ debug_critical("The sound hadle cannot be get [%d]\n", lhandle);
+ }
+ debug_fleave();
+ return MM_ERROR_NONE;
+}
+
+
+EXPORT_API
+int mm_sound_stop_sound(int handle)
+{
+ int err;
+
+ debug_fenter();
+
+ err = MMSoundClientStopSound(handle);
+
+ if (err < 0)
+ {
+ debug_error("Fail to stop sound\n");
+ return err;
+ }
+
+ debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+
+
+///////////////////////////////////
+//// MMSOUND DTMF APIs
+///////////////////////////////////
+#define NUMBER_OF_DTMF 12
+
+EXPORT_API
+int mm_sound_play_dtmf(MMSoundDtmf_t num, const volume_type_t vol_type, const sound_time_msec_t time)
+{
+ int *handle = NULL;
+ int lhandle = -1;
+ int err = MM_ERROR_NONE;
+ sound_time_msec_t ltime = 0;
+ debug_fenter();
+ if(num < MM_SOUND_DTMF_0 || num > MM_SOUND_DTMF_SHARP) {
+ debug_error("number is invalid %d\n", num);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+ if(time < 110 || time > 5000)
+ {
+ debug_error("time is invalid, time set to 200\n");
+ ltime = 153;
+ }
+ else {
+ ltime = time;
+ }
+
+ err = MMSoundClientPlayDTMF(num, vol_type, ltime, &lhandle);
+
+ if (err < 0) {
+ debug_error("Failed to play sound\n");
+ return err;
+ }
+
+ debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+///////////////////////////////////
+//// MMSOUND BEEP APIs
+///////////////////////////////////
+EXPORT_API
+int mm_sound_play_beep (const volume_type_t vol_type, const int duration, int *handle)
+{
+ int lhandle = -1;
+ int err = MM_ERROR_NONE;
+ debug_fenter();
+
+ if(duration < -1) {
+ debug_error("number is invalid %d\n", duration);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ /* call play dtmf with num -1 (this means beep) */
+ err = MMSoundClientPlayDTMF (-1, vol_type, duration, handle);
+
+ if (err < 0) {
+ debug_error("Failed to play sound\n");
+ return err;
+ }
+
+ if (handle)
+ *handle = lhandle;
+ else
+ debug_critical("The sound handle cannot be get [%d]\n", lhandle);
+ debug_fleave();
+ return MM_ERROR_NONE;
+}
+
+///////////////////////////////////
+//// MMSOUND TONE APIs
+///////////////////////////////////
+EXPORT_API
+int mm_sound_play_tone (MMSoundTone_t num, const volume_type_t vol_type, const double volume, const int duration, int *handle)
+{
+ int lhandle = -1;
+ int err = MM_ERROR_NONE;
+ debug_fenter();
+
+ if(duration < -1) {
+ debug_error("number is invalid %d\n", duration);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if(num < MM_SOUND_TONE_DTMF_0 || num >= MM_SOUND_TONE_NUM)
+ {
+ debug_error("TONE Value is invalid %d\n", num);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if(vol_type < VOLUME_TYPE_SYSTEM || vol_type >= VOLUME_TYPE_MAX)
+ {
+ debug_error("Volume Type is invalid %d\n", vol_type);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if(volume < 0.0 || volume > 1.0)
+ {
+ debug_error("Volume Value is invalid %d\n", vol_type);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ debug_msg("Call MMSoundClientPlayDTMF\n");
+ err = MMSoundClientPlayTONE (num, vol_type, volume, duration, &lhandle);
+
+ if (err < 0) {
+ debug_error("Failed to play sound\n");
+ return err;
+ }
+
+ if (handle)
+ *handle = lhandle;
+ else
+ debug_critical("The sound handle cannot be get [%d]\n", lhandle);
+ debug_fleave();
+ return MM_ERROR_NONE;
+}
+
+///////////////////////////////////
+//// MMSOUND ROUTING APIs
+///////////////////////////////////
+#define UID_ROOT 0
+#define UID_INHOUSE 5000
+#define CHECK_PRIVILEGE(x) ((x==UID_ROOT || x==UID_INHOUSE)?1:0)
+
+EXPORT_API
+int mm_sound_set_path(int gain, int output, int input, int option)
+{
+ int err;
+
+ debug_fenter();
+
+ debug_msg("gain: 0x%02X, output: %d, input: %d, option: 0x%x\n", gain, output, input, option);
+
+ err = avsys_audio_set_path_ex( gain, output, input, option);
+
+ if (err < 0) {
+ debug_error("avsys_audio_set_path() failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+EXPORT_API
+int mm_sound_get_path(int *gain, int *output, int *input, int *option)
+{
+ int err;
+
+ debug_fenter();
+
+ err = avsys_audio_get_path_ex( gain, output, input, option);
+ if (err < 0) {
+ debug_error("SoundCtlPathGet() failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ debug_msg("gain: 0x%02X, output: %d, input: %d, option: 0x%x\n", *gain, *output, *input, *option);
+ debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+#ifdef PULSE_CLIENT
+enum {
+ USE_PA_SINK_ALSA = 0,
+ USE_PA_SINK_A2DP,
+};
+EXPORT_API
+int mm_sound_route_set_system_policy (system_audio_route_t route)
+{
+ int ret = MM_ERROR_NONE;
+ int pa_sink = USE_PA_SINK_ALSA;
+ int codec_option = AVSYS_AUDIO_PATH_OPTION_JACK_AUTO;
+ int current_route;
+ int gain, out, in, option;
+
+ debug_fenter();
+
+ debug_log ("route = %d\n", route);
+ switch(route)
+ {
+ case SYSTEM_AUDIO_ROUTE_POLICY_IGNORE_A2DP:
+ codec_option = AVSYS_AUDIO_PATH_OPTION_JACK_AUTO;
+ pa_sink = USE_PA_SINK_ALSA;
+ break;
+ case SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY:
+ codec_option = AVSYS_AUDIO_PATH_OPTION_NONE;
+ pa_sink = USE_PA_SINK_ALSA;
+ break;
+ case SYSTEM_AUDIO_ROUTE_POLICY_DEFAULT:
+ codec_option = AVSYS_AUDIO_PATH_OPTION_JACK_AUTO;
+ pa_sink = USE_PA_SINK_A2DP;
+ break;
+ default:
+ debug_error("Unknown route %d\n", route);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if(MM_ERROR_NONE != __mm_sound_lock()) {
+ debug_error("Lock failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ /* Vconf check */
+ ret = vconf_get_int(ROUTE_VCONF_KEY, &current_route);
+ if(ret < 0) {
+ debug_error("Can not get current route policy\n");
+ current_route = SYSTEM_AUDIO_ROUTE_POLICY_DEFAULT;
+ if(0 > vconf_set_int(ROUTE_VCONF_KEY, current_route)) {
+ debug_error("Can not save current audio route policy to %s\n", ROUTE_VCONF_KEY);
+ if(MM_ERROR_NONE != __mm_sound_unlock()) {
+ debug_error("Unlock failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ }
+
+ /* If same as before, do nothing */
+ if(current_route == route)
+ {
+ debug_warning("Same route policy with current. Skip setting\n");
+ if(MM_ERROR_NONE != __mm_sound_unlock()) {
+ debug_error("Unlock failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ return MM_ERROR_NONE;
+ }
+
+ /* Get Current gain */
+ avsys_audio_get_path_ex(&gain, &out, &in, &option);
+ debug_msg ("gain = %x, out = %x, in = %x, option = %x\n", gain, out, in, option);
+ if (gain == AVSYS_AUDIO_GAIN_EX_FMRADIO) {
+ int output_path = 0 ,res = 0;
+
+ debug_msg ("This is FM radio gain mode.....\n");
+
+ /* select output path from policy */
+ if (route == SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY)
+ output_path = AVSYS_AUDIO_PATH_EX_SPK;
+ else if (route == SYSTEM_AUDIO_ROUTE_POLICY_DEFAULT || route == SYSTEM_AUDIO_ROUTE_POLICY_IGNORE_A2DP)
+ output_path = AVSYS_AUDIO_PATH_EX_HEADSET;
+
+ /* Do set path */
+ res = avsys_audio_set_path_ex( AVSYS_AUDIO_GAIN_EX_FMRADIO,
+ output_path,
+ AVSYS_AUDIO_PATH_EX_FMINPUT,
+ AVSYS_AUDIO_PATH_OPTION_NONE );
+ if(AVSYS_FAIL(ret)) {
+ debug_error("Can not set playback sound path, error=0x%x\n", ret);
+ if(MM_ERROR_NONE != __mm_sound_unlock()) {
+ debug_error("Unlock failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ return ret;
+ }
+ } else {
+
+ /* Try to change default sink */
+ ret = MMSoundClientSetAudioRoute(pa_sink);
+ if (ret < 0) {
+ debug_error("MMSoundClientsetAudioRoute() Failed for sink [%d]\n", pa_sink);
+ if(pa_sink == USE_PA_SINK_ALSA) {
+ //PA_A2DP_SINK can be return error;
+ if(MM_ERROR_NONE != __mm_sound_unlock()) {
+ debug_error("Unlock failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ return ret;
+ }
+ }
+
+ /* Do Set path if (IGNORE A2DP or HANDSET) or (DEFAULT with no BT) */
+ if(pa_sink == USE_PA_SINK_ALSA || (pa_sink == USE_PA_SINK_A2DP && ret != MM_ERROR_NONE))
+ {
+ ret = avsys_audio_set_path_ex(AVSYS_AUDIO_GAIN_EX_KEYTONE, AVSYS_AUDIO_PATH_EX_SPK, AVSYS_AUDIO_PATH_EX_NONE, codec_option);
+ if(AVSYS_FAIL(ret)) {
+ debug_error("Can not set playback sound path 0x%x\n", ret);
+ if(MM_ERROR_NONE != __mm_sound_unlock()) {
+ debug_error("Unlock failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ return ret;
+ }
+ ret = avsys_audio_set_path_ex(AVSYS_AUDIO_GAIN_EX_VOICEREC, AVSYS_AUDIO_PATH_EX_NONE, AVSYS_AUDIO_PATH_EX_MIC, codec_option);
+ if(AVSYS_FAIL(ret)) {
+ debug_error("Can not set capture sound path 0x%x\n", ret);
+ if(MM_ERROR_NONE != __mm_sound_unlock()) {
+ debug_error("Unlock failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ return ret;
+ }
+ }
+
+ } /* if (gain == AVSYS_AUDIO_GAIN_EX_FMRADIO) {} else {} */
+
+ /* Set route policy */
+ ret = avsys_audio_set_route_policy((avsys_audio_route_policy_t)route);
+ if(AVSYS_FAIL(ret)) {
+ debug_error("Can not set route policy to avsystem 0x%x\n", ret);
+ if(MM_ERROR_NONE != __mm_sound_unlock()) {
+ debug_error("Unlock failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ return ret;
+ }
+
+ /* update vconf */
+ ret = vconf_set_int(ROUTE_VCONF_KEY, (int)route);
+ if(ret < 0) {
+ debug_error("Can not set route policy to vconf %s\n", ROUTE_VCONF_KEY);
+ if(MM_ERROR_NONE != __mm_sound_unlock()) {
+ debug_error("Unlock failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ /* clean up */
+ if(MM_ERROR_NONE != __mm_sound_unlock()) {
+ debug_error("Unlock failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ debug_fleave();
+ return MM_ERROR_NONE;
+}
+
+
+EXPORT_API
+int mm_sound_route_get_system_policy (system_audio_route_t *route)
+{
+ int ret = MM_ERROR_NONE;
+ int lv_route = 0;
+ if(route == NULL) {
+ debug_error("Null pointer\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if(MM_ERROR_NONE != __mm_sound_lock()) {
+ debug_error("Lock failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ ret = vconf_get_int(ROUTE_VCONF_KEY, &lv_route);
+ if(ret < 0 ) {
+ debug_error("Can not get route policy from vconf. set default\n");
+ if(0> vconf_set_int(ROUTE_VCONF_KEY, SYSTEM_AUDIO_ROUTE_POLICY_DEFAULT))
+ {
+ debug_error("Set audio route policy to default failed\n");
+ ret = MM_ERROR_SOUND_INTERNAL;
+ }
+ else {
+ *route = SYSTEM_AUDIO_ROUTE_POLICY_DEFAULT;
+ }
+ }
+ else {
+ *route = lv_route;
+ }
+
+ if(ret == MM_ERROR_NONE) {
+ avsys_audio_route_policy_t av_route;
+ ret = avsys_audio_get_route_policy((avsys_audio_route_policy_t*)&av_route);
+ if(AVSYS_FAIL(ret)) {
+ debug_error("Can not get route policy to avsystem 0x%x\n", ret);
+ av_route = -1;
+ }
+ if(av_route != *route) {
+ //match vconf & shared mem info
+ ret = avsys_audio_set_route_policy(*route);
+ if(AVSYS_FAIL(ret)) {
+ debug_error("avsys_audio_set_route_policy failed 0x%x\n", ret);
+ }
+ }
+ }
+
+ if(MM_ERROR_NONE != __mm_sound_unlock()) {
+ debug_error("Unlock failed\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ return ret;
+}
+
+
+EXPORT_API
+int mm_sound_route_get_a2dp_status (int* connected, char** bt_name)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+
+ if (connected == NULL || bt_name == NULL) {
+ debug_error ("argument is not valid\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ ret = MMSoundClientIsBtA2dpOn (connected, bt_name);
+ debug_msg ("connected=[%d] bt_name[%s]\n", *connected, *bt_name);
+ if (ret < 0) {
+ debug_error("MMSoundClientIsBtA2dpOn() Failed\n");
+ return ret;
+ }
+
+ debug_fleave();
+
+ return ret;
+}
+
+EXPORT_API
+int mm_sound_route_get_playing_device(system_audio_route_device_t *dev)
+{
+ avsys_audio_playing_devcie_t status;
+
+ if(!dev)
+ return MM_ERROR_INVALID_ARGUMENT;
+
+ if(AVSYS_FAIL(avsys_audio_get_playing_device_info(&status)))
+ {
+ debug_error("Can not get playing device info\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ switch(status)
+ {
+ case AVSYS_AUDIO_ROUTE_DEVICE_HANDSET:
+ *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_HANDSET;
+ break;
+ case AVSYS_AUDIO_ROUTE_DEVICE_BLUETOOTH:
+ *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_BLUETOOTH;
+ break;
+ case AVSYS_AUDIO_ROUTE_DEVICE_EARPHONE:
+ *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_EARPHONE;
+ break;
+ default:
+ *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_NONE;
+ break;
+ }
+
+ return MM_ERROR_NONE;
+}
+
+
+typedef struct {
+ audio_route_policy_changed_callback_fn func;
+ void* data;
+}route_change_cb_param;
+
+route_change_cb_param g_route_param;
+
+
+void route_change_vconf_cb(keynode_t* node, void* data)
+{
+ int ret = MM_ERROR_NONE;
+ int lv_route = 0;
+ route_change_cb_param* param = (route_change_cb_param*) data;
+
+ debug_msg("%s changed callback called\n", vconf_keynode_get_name(node));
+ ret = vconf_get_int(ROUTE_VCONF_KEY, &lv_route);
+ if(ret<0) {
+ debug_error("Can not get route info from vconf..(in cb func)\n");
+ return;
+ }
+
+ if(param && (param->func != NULL)) {
+ ((audio_route_policy_changed_callback_fn)param->func)(param->data, (system_audio_route_t)lv_route);
+ }
+ return;
+}
+
+EXPORT_API
+int mm_sound_route_add_change_callback(audio_route_policy_changed_callback_fn func, void* user_data)
+{
+ int ret = MM_ERROR_NONE;
+
+ g_route_param.func = func;
+ g_route_param.data = user_data;
+
+ ret = vconf_notify_key_changed(ROUTE_VCONF_KEY, route_change_vconf_cb, (void*)&g_route_param);
+ if(ret < 0) {
+ debug_error("Can not add callback - vconf error\n");
+ ret = MM_ERROR_SOUND_INTERNAL;
+ }
+ return ret;
+}
+
+EXPORT_API
+int mm_sound_route_remove_change_callback()
+{
+ int ret = MM_ERROR_NONE;
+
+ g_route_param.func = NULL;
+ g_route_param.data = NULL;
+
+ ret = vconf_ignore_key_changed(ROUTE_VCONF_KEY, route_change_vconf_cb);
+ if(ret < 0) {
+ debug_error("Can not add callback - vconf error\n");
+ ret = MM_ERROR_SOUND_INTERNAL;
+ }
+ return ret;
+}
+
+#endif // PULSE_CLIENT
+
+EXPORT_API
+int mm_sound_system_get_capture_status(system_audio_capture_status_t *status)
+{
+ int err = AVSYS_STATE_SUCCESS;
+ int on_capture = 0;
+
+ if(!status)
+ return MM_ERROR_INVALID_ARGUMENT;
+
+ err = avsys_audio_get_capture_status(&on_capture);
+ if(err < 0) {
+ debug_error("Can not get capture status with 0x%x\n", err);
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ if(on_capture)
+ *status = SYSTEM_AUDIO_CAPTURE_ACTIVE;
+ else
+ *status = SYSTEM_AUDIO_CAPTURE_NONE;
+
+ return MM_ERROR_NONE;
+}
+
+__attribute__ ((destructor))
+void __mmfsnd_finalize(void)
+{
+ debug_fenter();
+
+ MMSoundClientCallbackFini();
+
+ debug_fleave();
+}
+
+__attribute__ ((constructor))
+void __mmfsnd_initialize(void)
+{
+ /* Will be Fixed */
+}