diff options
author | Seungbae Shin <seungbae.shin@samsung.com> | 2012-08-21 17:59:19 +0900 |
---|---|---|
committer | Seungbae Shin <seungbae.shin@samsung.com> | 2012-08-21 20:51:34 +0900 |
commit | 4b557013c69aba50fe1197bf556d4c24dc9f96e3 (patch) | |
tree | 296377f274d9c20213753ec0710116a18f5745d4 /server/mm_sound_mgr_pulse.c | |
parent | 13c42beed719f9c7911c2d82c5c3b6b531a06e55 (diff) | |
download | libmm-sound-4b557013c69aba50fe1197bf556d4c24dc9f96e3.tar.gz libmm-sound-4b557013c69aba50fe1197bf556d4c24dc9f96e3.tar.bz2 libmm-sound-4b557013c69aba50fe1197bf556d4c24dc9f96e3.zip |
2.0 init
Change-Id: I1fccce4dee3e9a772dc8b9b3580296eaad513a77
Diffstat (limited to 'server/mm_sound_mgr_pulse.c')
-rw-r--r-- | server/mm_sound_mgr_pulse.c | 689 |
1 files changed, 244 insertions, 445 deletions
diff --git a/server/mm_sound_mgr_pulse.c b/server/mm_sound_mgr_pulse.c index d92655a..1fe93c2 100644 --- a/server/mm_sound_mgr_pulse.c +++ b/server/mm_sound_mgr_pulse.c @@ -33,178 +33,138 @@ #include <errno.h> #include "include/mm_sound_mgr_common.h" -#include "../include/mm_sound_msg.h" #include "../include/mm_sound_common.h" #include <mm_error.h> #include <mm_debug.h> -#include <audio-session-manager.h> -#include <avsys-audio.h> +//#include <audio-session-manager.h> +//#include <avsys-audio.h> +#include <pulse/pulseaudio.h> #include <pulse/ext-policy.h> #define SUPPORT_MONO_AUDIO -//#define BT_DISCONNECT_PAUSE -#include "include/mm_sound_mgr_pulse.h" +#define SUPPORT_BT_SCO_DETECT -#define SOUND_MSG_SET(sound_msg, x_msgtype, x_handle, x_code, x_msgid) \ -do { \ - sound_msg.msgtype = x_msgtype; \ - sound_msg.handle = x_handle; \ - sound_msg.code = x_code; \ - sound_msg.msgid = x_msgid; \ -} while(0) +#include "include/mm_sound_mgr_pulse.h" +#include "include/mm_sound_mgr_session.h" -pa_threaded_mainloop *g_m; -pa_context *g_context; +#include "include/mm_sound_msg.h" +#include "include/mm_sound_mgr_ipc.h" -pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; +#include <vconf.h> +#include <vconf-keys.h> -#ifdef BT_DISCONNECT_PAUSE -int g_asm_handle = -1; +#define MAX_STRING 64 -bool _asm_register_for_bt () +typedef struct _pulse_info { - int asm_error = 0; - if(!ASM_register_sound(-1, &g_asm_handle, ASM_EVENT_EARJACK_UNPLUG, ASM_STATE_NONE, NULL, NULL, ASM_RESOURCE_NONE, &asm_error)) - { - debug_warning("earjack event register failed with 0x%x\n", asm_error); - return false; - } - return true; -} + pa_threaded_mainloop *m; + pa_context *context; + char sink_to_find[MAX_STRING]; + bool init_bt_status; +}pulse_info_t; +pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; -int set_audio_route_to_default() -{ - int ret = MM_ERROR_NONE; - int codec_option = AVSYS_AUDIO_PATH_OPTION_JACK_AUTO; +pulse_info_t* pulse_info = NULL; - debug_msg("Set audio route to default by sound_server pulse mgr\n"); +/* -------------------------------- PULSEAUDIO --------------------------------------------*/ - if(MM_ERROR_NONE != __mm_sound_lock()) { - debug_error("Lock failed\n"); - return MM_ERROR_SOUND_INTERNAL; - } +static void server_info_cb(pa_context *c, const pa_server_info *i, void *userdata) +{ + int ret = 0; - 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 (!i) { + debug_error("error in server info callback\n"); - ret = avsys_audio_set_route_policy(AVSYS_AUDIO_ROUTE_POLICY_DEFAULT); - 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; - } + } else { + debug_msg ("We got default sink = [%s]\n", i->default_sink_name); - ret = vconf_set_int(ROUTE_VCONF_KEY, (int)AVSYS_AUDIO_ROUTE_POLICY_DEFAULT); - 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; + /* ToDo: Update server info */ + ret = MMSoundMgrSessionSetDefaultSink (i->default_sink_name); + if (ret != MM_ERROR_NONE) { + /* TODO : Error Handling */ + debug_error ("MMSoundMgrSessionSetDefaultSink failed....ret = [%x]\n", ret); } - return MM_ERROR_SOUND_INTERNAL; - } + } +} - if(MM_ERROR_NONE != __mm_sound_unlock()) { - debug_error("Unlock failed\n"); - return MM_ERROR_SOUND_INTERNAL; +static void init_card_info_cb (pa_context *c, const pa_card_info *i, int eol, void *userdata) +{ + pulse_info_t *pinfo = (pulse_info_t *)userdata; + if (eol || i == NULL) { + debug_msg ("signaling--------------\n"); + pa_threaded_mainloop_signal (pinfo->m, 0); + return; } - return MM_ERROR_NONE; + if (strstr (i->name, "bluez")) { + pinfo->init_bt_status = true; + } } -int process_asm_pause () +static void card_info_cb (pa_context *c, const pa_card_info *i, int eol, void *userdata) { - int asm_error = 0; - - // mute is not affecting now - //if(AVSYS_FAIL(avsys_audio_set_global_mute(AVSYS_AUDIO_MUTE))) - //debug_error("Set unmute failed\n"); - - if (g_asm_handle == -1) { - debug_msg ("ASM handle is not valid, try to register once more\n"); - /* This register should be success */ - if (_asm_register_for_bt ()) { - debug_msg("_asm_register_for_bt() success\n"); - } else { - debug_error("_asm_register_for_bt() failed\n"); - } - } + int ret = 0; + char* desc = NULL; - if(!ASM_set_sound_state(g_asm_handle, ASM_EVENT_EARJACK_UNPLUG, ASM_STATE_PLAYING, ASM_RESOURCE_NONE, &asm_error )) - debug_error("earjack event set sound state to playing failed with 0x%x\n", asm_error); + if (eol || i == NULL) { + return; + } - if(!ASM_set_sound_state(g_asm_handle, ASM_EVENT_EARJACK_UNPLUG, ASM_STATE_STOP, ASM_RESOURCE_NONE, &asm_error )) - debug_error("earjack event set sound state to stop failed with 0x%x\n", asm_error); + /* Get device name : eg. SBH-600 */ + desc = pa_proplist_gets(i->proplist, PA_PROP_DEVICE_DESCRIPTION); + debug_msg ("[%s][%d] card name is [%s], card.property.device.description = [%s]\n", __func__, __LINE__, i->name, desc); - //if(AVSYS_FAIL(avsys_audio_set_global_mute(AVSYS_AUDIO_UNMUTE))) - //debug_error("Set unmute failed\n"); + /* ToDo: Update Device */ + ret = MMSoundMgrSessionSetDeviceAvailable (DEVICE_BT_A2DP, AVAILABLE, 0, (desc)? desc : "NONAME"); + if (ret != MM_ERROR_NONE) { + /* TODO : Error Handling */ + debug_error ("MMSoundMgrSessionSetDeviceAvailable failed....ret = [%x]\n", ret); + } } -static void -context_subscribe_cb (pa_context * c, - pa_subscription_event_type_t t, uint32_t idx, void *userdata) +static void context_subscribe_cb (pa_context * c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { - debug_msg (">>>>>>>>> [%s][%d] type=(%d) idx=(%u)\n", __func__, __LINE__, t, idx); - - /* if event is "sink" index is not 0 (alsa) then bluetooth sink device is load/unloaded */ - /* FIXME : what if alsa index is not 0???? we have check more strictly*/ - if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK && idx != 0) { - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { /* unloaded */ - /* Check current policy */ - avsys_audio_route_policy_t cur_policy; - if (avsys_audio_get_route_policy(&cur_policy) == AVSYS_STATE_SUCCESS) { - /* We Do pause if policy is default, if not, do nothing */ - if (cur_policy == AVSYS_AUDIO_ROUTE_POLICY_DEFAULT) { - /* Do pause here */ - debug_msg("Do pause here"); - process_asm_pause(); - } else { - debug_msg("Policy is not default, Do nothing"); - } - } else { - debug_error ("avsys_audio_get_route_policy() failed"); - } - } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { /* loaded */ - /* Restore audio route policy to default */ - if(MM_ERROR_NONE != set_audio_route_to_default()) { - debug_error("set_audio_route_to_default() failed\n"); - } else { - debug_msg("set_audio_route_to_default() done.\n"); + debug_msg (">>>>>>>>> [%s][%d] type=(0x%x) idx=(%u)\n", __func__, __LINE__, t, idx); + + if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_CARD) { + /* FIXME: We assumed that card is bt, card new/remove = bt new/remove */ + + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { /* BT is removed */ + /* ToDo: Update Device */ + //MMSoundMgrSessionSetDeviceBT (STATUS_NONE, NULL); + MMSoundMgrSessionSetDeviceAvailable (DEVICE_BT_A2DP, NOT_AVAILABLE, 0, NULL); + + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { /* BT is loaded */ + /* Get Card info for BT name. Update device after that */ + pa_operation *o; + if (!(o = pa_context_get_card_info_by_index (c, idx, card_info_cb, NULL))) { + return; } + pa_operation_unref(o); + } - } + + } else if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SERVER) { + + pa_operation_unref(pa_context_get_server_info(c, server_info_cb, NULL)); + + + } else { + debug_msg ("[%s][%d] type=(0x%x) idx=(%u) is not card or server event, skip...\n", __func__, __LINE__, t, idx); + return; + } } -#endif -void context_state_cb (pa_context *c, void *userdata) +static void context_state_cb (pa_context *c, void *userdata) { - //g_print (">>>>>>>>> [%s][%d]\n", __func__, __LINE__); + pulse_info_t *pinfo = (pulse_info_t *)userdata; switch (pa_context_get_state(c)) { case PA_CONTEXT_UNCONNECTED: @@ -217,76 +177,60 @@ void context_state_cb (pa_context *c, void *userdata) case PA_CONTEXT_READY: { - //g_print ("PA_CONTEXT_READY\n"); - - if (g_context == c) { - -#ifdef BT_DISCONNECT_PAUSE - /* Do SINK Subscribe */ - pa_context_set_subscribe_callback(c, context_subscribe_cb, NULL); + if (pinfo->context == c) { + /* Do CARD and SERVER Subscribe */ + pa_context_set_subscribe_callback(c, context_subscribe_cb, pinfo); pa_operation *o; - if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t)PA_SUBSCRIPTION_MASK_SINK, NULL, NULL))) { - //g_print ("pa_context_subscribe() failed\n"); + if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t)PA_SUBSCRIPTION_MASK_CARD | PA_SUBSCRIPTION_MASK_SERVER, NULL, NULL))) { return; } pa_operation_unref(o); -#else - //pa_context_set_subscribe_callback(c, NULL, NULL); -#endif - /* Signal */ - debug_msg ("signaling--------------\n"); - pa_threaded_mainloop_signal (g_m, 0); + pa_operation_unref(pa_context_get_card_info_list (pinfo->context, init_card_info_cb, pinfo)); + + /* signaling will be done after get card info in card info callback */ } break; } } - - return; } -int pulse_init () +static int pulse_init (pulse_info_t * pinfo) { int res; debug_msg (">>>>>>>>> [%s][%d]\n", __func__, __LINE__); -#ifdef BT_DISCONNECT_PAUSE - /* Set audio route policy to default when sound server startup */ - if(MM_ERROR_NONE != set_audio_route_to_default()) - { - debug_error("Set audio route policy to default failed\n"); - } -#endif + /* Create new mainloop */ - g_m = pa_threaded_mainloop_new(); + pinfo->m = pa_threaded_mainloop_new(); //g_assert(g_m); - res = pa_threaded_mainloop_start (g_m); + res = pa_threaded_mainloop_start (pinfo->m); //g_assert (res == 0); /* LOCK thread */ - pa_threaded_mainloop_lock (g_m); + pa_threaded_mainloop_lock (pinfo->m); /* Get mainloop API */ - pa_mainloop_api *api = pa_threaded_mainloop_get_api(g_m); + pa_mainloop_api *api = pa_threaded_mainloop_get_api(pinfo->m); /* Create new Context */ - g_context = pa_context_new(api, "SOUND_SERVER_ROUTE_MANAGER"); + pinfo->context = pa_context_new(api, "SOUND_SERVER_ROUTE_MANAGER"); /* Set Callback */ - pa_context_set_state_callback (g_context, context_state_cb, NULL); + pa_context_set_state_callback (pinfo->context, context_state_cb, pinfo); /* Connect */ - if (pa_context_connect (g_context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) { + if (pa_context_connect (pinfo->context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) { debug_error ("connection error\n"); } for (;;) { pa_context_state_t state; - state = pa_context_get_state (g_context); + state = pa_context_get_state (pinfo->context); debug_msg ("context state is now %d\n", state); @@ -300,371 +244,226 @@ int pulse_init () /* Wait until the context is ready */ debug_msg ("waiting..................\n"); - pa_threaded_mainloop_wait (g_m); + pa_threaded_mainloop_wait (pinfo->m); } /* UNLOCK thread */ - pa_threaded_mainloop_unlock (g_m); + pa_threaded_mainloop_unlock (pinfo->m); debug_msg ("<<<<<<<<<< [%s][%d]\n", __func__, __LINE__); - return 0; + return res; } -int pulse_deinit () -{ - pa_threaded_mainloop_lock (g_m); - - if (g_context) { - pa_context_disconnect (g_context); - /* Make sure we don't get any further callbacks */ - pa_context_set_state_callback (g_context, NULL, NULL); - - pa_context_unref (g_context); - g_context = NULL; - } - pa_threaded_mainloop_unlock (g_m); - - pa_threaded_mainloop_stop (g_m); - pa_threaded_mainloop_free (g_m); - - debug_msg ("<<<<<<<<<< [%s][%d]\n", __func__, __LINE__); - - return 0; - -} +static void sink_info_cb (pa_context *c, const pa_sink_info *i, int is_last, void *userdata) +{ + pulse_info_t * pinfo = (pulse_info_t *)userdata; -void get_server_info_callback(pa_context *c, const pa_server_info *i, void *userdata) { - int ret; - mm_ipc_msg_t respmsg = {0,}; - server_struct *ss = (server_struct *)userdata; - if (ss == NULL) { - debug_error ("Input userdata is NULL\n"); + if (is_last || i == NULL || pinfo == NULL) { + if (is_last < 0) { + debug_error("Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c))); + } return; } - if (!i) { - debug_error("Error to MM_SOUND_MSG_REQ_GET_AUDIO_ROUTE.\n"); - SOUND_MSG_SET(respmsg.sound_msg, MM_SOUND_MSG_RES_ERROR, -1, 0, ss->msg->sound_msg.msgid); - } else { - debug_msg ("We got default sink = [%s]\n", i->default_sink_name); - SOUND_MSG_SET(respmsg.sound_msg, MM_SOUND_MSG_RES_GET_AUDIO_ROUTE, ss->msg->sound_msg.handle, 0, ss->msg->sound_msg.msgid); - if (strstr (i->default_sink_name, "alsa")) - respmsg.sound_msg.code = 0; - else if (strstr (i->default_sink_name, "bluez")) - respmsg.sound_msg.code = 1; - else - respmsg.sound_msg.code = 2; - } + if (i->name && i->proplist) { + const char *api_string = pa_proplist_gets (i->proplist, "device.api"); + if (api_string) { + debug_log ("sink name = [%s], api = [%s]\n", i->name, api_string); + if (strcmp (api_string, pinfo->sink_to_find) == 0) { + debug_log ("FOUND!!! set default sink to [%s]\n", i->name); + pa_operation_unref(pa_context_set_default_sink(pinfo->context, i->name, NULL, NULL)); - if (ss->func) { - ret = ss->func (&respmsg); - if (ret != MM_ERROR_NONE) { - debug_error ("Fail to send message [%x]\n", ret); - } else { - debug_msg("Sent msg to client msgid [%d] [codechandle %d][message type %d] (code 0x%08X)\n", - ss->msg->sound_msg.msgid, respmsg.sound_msg.handle, respmsg.sound_msg.msgtype, respmsg.sound_msg.code); + } else { + debug_warning ("No string [%s] match!!!!\n", pinfo->sink_to_find); + } } - } else { - debug_error ("No send function\n"); } +} - debug_msg("Ready to next msg\n"); - if (ss->msg) { - debug_msg ("free [%p]\n", ss->msg); - free (ss->msg); - ss->msg = NULL; - } - if (ss) { - free (ss); - ss = NULL; - } - pthread_mutex_unlock(&g_mutex); +static void pulse_set_default_sink (pulse_info_t * pinfo, char *default_sink_name) +{ + strcpy (pinfo->sink_to_find, default_sink_name); + pa_operation_unref(pa_context_get_sink_info_list(pinfo->context, sink_info_cb, pinfo)); } -void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) +static int pulse_deinit (pulse_info_t * pinfo) { - int ret; - mm_ipc_msg_t respmsg = {0,}; - sink_struct *ss = (sink_struct *)userdata; - if (ss == NULL) { - debug_error ("Input userdata is NULL\n"); - return; - } + pa_threaded_mainloop_lock (pinfo->m); + if (pinfo->context) { + pa_context_disconnect (pinfo->context); - if (is_last) { - if (is_last < 0) { /* ERROR */ - /* Compose Error Response */ - debug_error("Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c))); - debug_error("Error to MM_SOUND_MSG_REQ_SET_AUDIO_ROUTE.\n"); - SOUND_MSG_SET(respmsg.sound_msg, MM_SOUND_MSG_RES_ERROR, -1, 0, ss->msg->sound_msg.msgid); - } else { /* FINISHED WELL */ - /* Compose Response */ - SOUND_MSG_SET(respmsg.sound_msg, MM_SOUND_MSG_RES_SET_AUDIO_ROUTE, ss->msg->sound_msg.handle, ss->route_to, ss->msg->sound_msg.msgid); - - /* Do further action related with route request */ - /* ToDo : is this sync operation??? */ - if (ss->route_to == 0 && ss->is_speaker_on ) { - /* route to speaker and speaker is on */ - debug_msg ("Trying to set default sink to [%s] \n", ss->speaker_name); - pa_operation_unref(pa_context_set_default_sink(g_context, ss->speaker_name, NULL, NULL)); - } else if (ss->route_to == 1 && ss->is_bt_on) { - /* route to bt and bt is on */ - debug_msg ("Trying to set default sink to [%s] \n", ss->bt_name); - pa_operation_unref(pa_context_set_default_sink(g_context, ss->bt_name, NULL, NULL)); - } else { - /* Nothing to do.... */ - debug_warning ("No match for [%d] \n", ss->route_to); - respmsg.sound_msg.code = -1; // this means no exists - } - } - - if (ss) { - /* Send Response */ - if (ss->func) { - ret = ss->func (&respmsg); - if (ret != MM_ERROR_NONE) { - debug_error ("Fail to send message \n"); - } - debug_msg("Sent msg to client msgid [%d] [codechandle %d][message type %d] (code 0x%08X)\n", - ss->msg->sound_msg.msgid, respmsg.sound_msg.handle, respmsg.sound_msg.msgtype, respmsg.sound_msg.code); - } else { - debug_error ("No send function\n"); - } - - /* Cleanup */ - if (ss->msg) { - debug_msg ("free [%p]\n", ss->msg); - free (ss->msg); - ss->msg = NULL; - } - free (ss); - ss = NULL; - } - debug_msg("Ready to next msg\n"); - pthread_mutex_unlock(&g_mutex); - - return; - } - - //pa_assert(i); - - if (i->name) { - debug_msg("sink name = [%s]\n", i->name); - - if (strstr (i->name, "alsa_")) { - ss->is_speaker_on = 1; - strncpy (ss->speaker_name, i->name, sizeof(ss->speaker_name)-1); - } else if (strstr (i->name, "bluez")) { - ss->is_bt_on = 1; - strncpy (ss->bt_name, i->name, sizeof(ss->bt_name)-1); - } else - debug_warning("Unknown sink name!!!\n"); - } - -} + /* Make sure we don't get any further callbacks */ + pa_context_set_state_callback (pinfo->context, NULL, NULL); -void check_bt_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) -{ - int ret; - mm_ipc_msg_t respmsg = {0,}; - bt_struct *bs = (bt_struct *)userdata; - if (bs == NULL) { - debug_error ("Input userdata is NULL\n"); - return; + pa_context_unref (pinfo->context); + pinfo->context = NULL; } + pa_threaded_mainloop_unlock (pinfo->m); - if (is_last) { - if (is_last < 0) { /* ERROR */ - /* Compose Error Response */ - debug_error("Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c))); - debug_error("Error to MM_SOUND_MSG_RES_IS_BT_A2DP_ON.\n"); - SOUND_MSG_SET(respmsg.sound_msg, MM_SOUND_MSG_RES_ERROR, -1, 0, bs->msg->sound_msg.msgid); - } else { /* FINISHED WELL */ - /* Compose Response */ - SOUND_MSG_SET(respmsg.sound_msg, - MM_SOUND_MSG_RES_IS_BT_A2DP_ON, bs->msg->sound_msg.handle, (bs->bt_found)? 1:0, bs->msg->sound_msg.msgid); - strncpy (respmsg.sound_msg.filename, bs->bt_name, sizeof (respmsg.sound_msg.filename)-1); - } - - /* Send resone & clean up */ - if (bs) { - /* Send Response */ - if (bs->func) { - ret = bs->func (&respmsg); - if (ret != MM_ERROR_NONE) { - debug_error ("Fail to send message \n"); - } else { - debug_msg("Sent msg to client msgid [%d] [codechandle %d][message type %d] (code 0x%08X)\n", - bs->msg->sound_msg.msgid, respmsg.sound_msg.handle, respmsg.sound_msg.msgtype, respmsg.sound_msg.code); - } - } else { - debug_error ("No sendfunc!!!!\n"); - } + pa_threaded_mainloop_stop (pinfo->m); + pa_threaded_mainloop_free (pinfo->m); - /* clean up */ - if (bs->msg) { - debug_msg ("free [%p]\n", bs->msg); - free (bs->msg); - bs->msg = NULL; - } - free (bs); - bs = NULL; - } + debug_msg ("<<<<<<<<<< [%s][%d]\n", __func__, __LINE__); - debug_msg("Ready to next msg\n"); - pthread_mutex_unlock(&g_mutex); - return; - } + return 0; - //pa_assert(i); - - if (i->name) { - debug_msg("sink name = [%s]\n", i->name); - - if (strstr (i->name, "bluez")) { - char* desc = pa_proplist_gets(i->proplist, PA_PROP_DEVICE_DESCRIPTION); - if (desc && strlen(desc)>0) { - debug_msg ("sink device description = [%s]\n", desc); - bs->bt_found = 1; - strncpy (bs->bt_name, desc, strlen(desc)); - } else { - debug_warning ("No Description!!!!\n"); - } - } - } - } -int MMSoundMgrPulseHandleGetAudioRouteReq (mm_ipc_msg_t *msg, int (*sendfunc)(mm_ipc_msg_t*)) -{ - debug_enter("msg = %p , sendfunc = %p\n", msg, sendfunc); +/* -------------------------------- MONO AUDIO --------------------------------------------*/ +#ifdef SUPPORT_MONO_AUDIO +#define MONO_KEY VCONFKEY_SETAPPL_ACCESSIBILITY_MONO_AUDIO - pthread_mutex_lock(&g_mutex); +static void success_cb (pa_context *c, int success, void *userdata) +{ + debug_msg ("success = %d\n", success); +} - server_struct *ss = malloc (sizeof (server_struct)); - memset (ss, 0, sizeof (server_struct)); +static void mono_changed_cb(keynode_t* node, void* data) +{ + int key_value; + pulse_info_t* pinfo = (pulse_info_t*)data; - /* common setting */ - ss->msg = msg; - ss->func = sendfunc; + debug_msg ("%s changed callback called\n",vconf_keynode_get_name(node)); - /* Do async pulse operation */ - pa_operation_unref(pa_context_get_server_info(g_context, get_server_info_callback, ss)); + vconf_get_bool(MONO_KEY, &key_value); + debug_msg ("key value = %d\n", key_value); - debug_leave("\n"); + pa_operation_unref (pa_ext_policy_set_mono (pinfo->context, key_value, success_cb, NULL)); } -int MMSoundMgrPulseHandleSetAudioRouteReq (mm_ipc_msg_t *msg, int (*sendfunc)(mm_ipc_msg_t*)) +int MMSoundMgrPulseHandleRegisterMonoAudio (void* pinfo) { - debug_enter("\n"); + int ret = vconf_notify_key_changed(MONO_KEY, mono_changed_cb, pinfo); + debug_msg ("vconf [%s] set ret = %d\n", MONO_KEY, ret); + return ret; +} +#endif /* SUPPORT_MONO_AUDIO */ - pthread_mutex_lock(&g_mutex); - sink_struct *ss = malloc (sizeof (sink_struct)); - memset (ss, 0, sizeof(sink_struct)); +/* -------------------------------- BT SCO --------------------------------------------*/ +#ifdef SUPPORT_BT_SCO_DETECT - /* common setting */ - ss->msg = msg; - ss->func = sendfunc; +static void bt_changed_cb(keynode_t* node, void* data) +{ + int bt_status = VCONFKEY_BT_DEVICE_NONE; + int available = 0; + pulse_info_t* pinfo = (pulse_info_t*)data; - /* specific setting */ - ss->is_speaker_on = ss->is_bt_on = 0; - ss->route_to = msg->sound_msg.handle; + debug_msg ("[%s] changed callback called\n", vconf_keynode_get_name(node)); - /* Do async pulse operation */ - pa_operation_unref(pa_context_get_sink_info_list(g_context, get_sink_info_callback, ss)); + /* Get actual vconf value */ + vconf_get_int(VCONFKEY_BT_DEVICE, &bt_status); + debug_msg ("key value = 0x%x\n", bt_status); - debug_leave("\n"); + /* Set device available based on vconf key value */ + available = (bt_status & VCONFKEY_BT_DEVICE_HEADSET_CONNECTED)? AVAILABLE : NOT_AVAILABLE; + MMSoundMgrSessionSetDeviceAvailable (DEVICE_BT_SCO, available, 0, NULL); +} + +int MMSoundMgrPulseHandleRegisterBluetoothStatus (void* pinfo) +{ + /* set callback for vconf key change */ + int ret = vconf_notify_key_changed(VCONFKEY_BT_DEVICE , bt_changed_cb, pinfo); + debug_msg ("vconf [%s] set ret = %d\n", VCONFKEY_BT_DEVICE, ret); + return ret; } +#endif /* SUPPORT_BT_SCO_DETECT */ + +/* -------------------------------- MGR MAIN --------------------------------------------*/ int MMSoundMgrPulseHandleIsBtA2DPOnReq (mm_ipc_msg_t *msg, int (*sendfunc)(mm_ipc_msg_t*)) { + int ret = 0; + mm_ipc_msg_t respmsg = {0,}; + char* bt_name; + bool is_bt_on = false; + pthread_mutex_lock(&g_mutex); + debug_enter("msg = %p, sendfunc = %p\n", msg, sendfunc); - pthread_mutex_lock(&g_mutex); + bt_name = MMSoundMgrSessionGetBtA2DPName(); + if (bt_name && strlen(bt_name) > 0) { + is_bt_on = true; + } - bt_struct *bs = malloc (sizeof(bt_struct)); - memset (bs, 0, sizeof (bt_struct)); + debug_log ("is_bt_on = [%d], name = [%s]\n", is_bt_on, bt_name); - /* common setting */ - bs->msg = msg; - bs->func = sendfunc; + SOUND_MSG_SET(respmsg.sound_msg, + MM_SOUND_MSG_RES_IS_BT_A2DP_ON, msg->sound_msg.handle, is_bt_on, msg->sound_msg.msgid); + strncpy (respmsg.sound_msg.filename, bt_name, sizeof (respmsg.sound_msg.filename)-1); - /* specific setting */ - bs->bt_found = 0; + /* Send Response */ + ret = sendfunc (&respmsg); + if (ret != MM_ERROR_NONE) { + /* TODO : Error Handling */ + debug_error ("sendfunc failed....ret = [%x]\n", ret); + } - /* Do async pulse operation */ - pa_operation_unref(pa_context_get_sink_info_list(g_context, check_bt_sink_info_callback, bs)); + pthread_mutex_unlock(&g_mutex); debug_leave("\n"); -} -#ifdef SUPPORT_MONO_AUDIO -#define MONO_KEY "db/setting/accessibility/mono_audio" + return ret; +} -void success_cb (pa_context *c, int success, void *userdata) +void MMSoundMgrPulseSetDefaultSink (char* default_sink_name) { - debug_msg ("success = %d\n", success); + debug_enter("\n"); + + pulse_set_default_sink(pulse_info, default_sink_name); + + debug_leave("\n"); } -void mono_changed_cb(keynode_t* node, void* data) +void MMSoundMgrPulseGetInitialBTStatus (bool *a2dp, bool *sco) { - debug_msg ("%s changed callback called\n",vconf_keynode_get_name(node)); + int bt_status = VCONFKEY_BT_DEVICE_NONE; - int key_value; - vconf_get_bool(MONO_KEY, &key_value); + if (a2dp == NULL || sco == NULL) { + debug_error ("Invalide arguments!!!\n"); + return; + } - debug_msg ("key value = %d\n", key_value); + /* Get saved bt status */ + *a2dp = pulse_info->init_bt_status; - pa_operation_unref (pa_ext_policy_set_mono (g_context, key_value, success_cb, NULL)); -} + /* Get actual vconf value */ + vconf_get_int(VCONFKEY_BT_DEVICE, &bt_status); + debug_msg ("key value = 0x%x\n", bt_status); + *sco = (bt_status & VCONFKEY_BT_DEVICE_HEADSET_CONNECTED)? true : false; -int MMSoundMgrPulseHandleRegisterMonoAudio () -{ - int ret = vconf_notify_key_changed(MONO_KEY, mono_changed_cb, NULL); - debug_enter ("vconf set ret = %d\n", ret); - return ret; + debug_msg ("returning a2dp=[%d], sco=[%d]\n", *a2dp, *sco); } -#endif - -int MMSoundMgrPulseInit(void) +void* MMSoundMgrPulseInit(void) { + pulse_info = (pulse_info_t*) malloc (sizeof(pulse_info_t)); + memset (pulse_info, 0, sizeof(pulse_info_t)); + debug_enter("\n"); - pulse_init(); + pulse_init(pulse_info); #ifdef SUPPORT_MONO_AUDIO - MMSoundMgrPulseHandleRegisterMonoAudio(); + MMSoundMgrPulseHandleRegisterMonoAudio(pulse_info); #endif -#ifdef BT_DISCONNECT_PAUSE - /* This registeration can be failed when hibernation capture, because of security server */ - _asm_register_for_bt (); - +#ifdef SUPPORT_BT_SCO_DETECT + MMSoundMgrPulseHandleRegisterBluetoothStatus(pulse_info); #endif + debug_leave("\n"); - return MM_ERROR_NONE; + return pulse_info; } -int MMSoundMgrPulseFini(void) +int MMSoundMgrPulseFini(void* handle) { debug_enter("\n"); - pulse_deinit(); - -#ifdef BT_DISCONNECT_PAUSE - { - int asm_error = 0; - if(!ASM_unregister_sound(g_asm_handle, ASM_EVENT_EARJACK_UNPLUG, &asm_error)) - { - debug_error("earjack event unregister failed with 0x%x\n", asm_error); - } - } -#endif + pulse_deinit((pulse_info_t *)handle); debug_leave("\n"); return MM_ERROR_NONE; |