X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=mm_sound_client.c;h=87a6bf8458e74045bb2ec1e3c6e461108ab33117;hb=5dd6576f693a4dbc38478ea97805a88fcbf551f1;hp=e2ef2df5914f0eacb1945f2fcd710030c8c8a9c5;hpb=8037a878c2bcdd9c5c31457ca166043d7308a973;p=platform%2Fcore%2Fmultimedia%2Flibmm-sound.git diff --git a/mm_sound_client.c b/mm_sound_client.c index e2ef2df..87a6bf8 100644 --- a/mm_sound_client.c +++ b/mm_sound_client.c @@ -19,39 +19,32 @@ * */ +#include #include #include -#include -#include +#include #include #include -#include -#include +#include #include +#include #include #include #include #include -//#include #include "include/mm_sound.h" -#include "include/mm_sound_msg.h" #include "include/mm_sound_client.h" -#include "include/mm_sound_client_dbus.h" +#include "include/mm_sound_proxy.h" #include "include/mm_sound_common.h" #include "include/mm_sound_device.h" -#ifdef USE_FOCUS -#include "include/mm_sound_focus.h" -#endif +#include "include/mm_sound_stream.h" #include #include -#define __DIRECT_CALLBACK__ -//#define __GIDLE_CALLBACK__ - #include #if defined(__GSOURCE_CALLBACK__) #include @@ -59,145 +52,201 @@ #define CLIENT_HANDLE_MAX 256 -/* global variables for device list */ -//static GList *g_device_list = NULL; -static mm_sound_device_list_t g_device_list_t; -static pthread_mutex_t g_device_list_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t g_id_mutex = PTHREAD_MUTEX_INITIALIZER; +#define FOCUS_HANDLE_MAX 512 +#define FOCUS_HANDLE_INIT_VAL -1 +#define CONFIG_ENABLE_RETCB + +#define VOLUME_TYPE_LEN 64 + +struct sigaction system_int_old_action; +struct sigaction system_abrt_old_action; +struct sigaction system_segv_old_action; +struct sigaction system_term_old_action; +struct sigaction system_sys_old_action; +struct sigaction system_xcpu_old_action; + +struct callback_data { + void *user_cb; + void *user_data; + void *extra_data; + guint subs_id; +}; + +#define GET_CB_DATA(_cb_data, _func, _userdata, _extradata) \ + do { \ + _cb_data = (struct callback_data*) g_malloc0(sizeof(struct callback_data)); \ + _cb_data->user_cb = _func; \ + _cb_data->user_data = _userdata; \ + _cb_data->extra_data = _extradata; \ + } while (0) +#ifdef USE_FOCUS +typedef struct { + int focus_tid; + int handle; + int focus_fd; + GSourceFuncs* g_src_funcs; + GPollFD* g_poll_fd; + GSource* focus_src; + bool is_used; + bool auto_reacquire; + GMutex focus_lock; + mm_sound_focus_changed_cb focus_callback; + mm_sound_focus_changed_watch_cb watch_callback; + void* user_data; + + bool is_for_session; /* will be removed when the session concept is completely left out*/ +} focus_sound_info_t; + +typedef struct { + int pid; + int handle; + int type; + int state; + char stream_type[MAX_STREAM_TYPE_LEN]; + char ext_info[MM_SOUND_NAME_NUM]; + int option; +} focus_cb_data_lib; + +typedef struct { + mm_sound_focus_session_interrupt_cb user_cb; + void* user_data; +} focus_session_interrupt_info_t; + +typedef gboolean (*focus_gLoopPollHandler_t)(gpointer d); + +GThread *g_focus_thread; +GMainLoop *g_focus_loop; +focus_sound_info_t g_focus_sound_handle[FOCUS_HANDLE_MAX]; +focus_session_interrupt_info_t g_focus_session_interrupt_info = {NULL, NULL}; +static pthread_mutex_t g_index_mutex = PTHREAD_MUTEX_INITIALIZER; guint g_focus_signal_handle = 0; +#endif -int mm_sound_client_initialize(void) -{ - int ret = MM_ERROR_NONE; - debug_fenter(); - - mm_sound_client_dbus_initialize(); - - debug_fleave(); - return ret; -} - -int mm_sound_client_finalize(void) -{ - int ret = MM_ERROR_NONE; - - debug_fenter(); - - ret = mm_sound_client_dbus_finalize(); +gboolean g_need_emergent_exit = FALSE; - debug_fleave(); - return ret; -} +typedef struct { + /* handle to watch end of playing */ + int watching_handle; + /* subscription id to unsubscribe when handle ended */ + unsigned subs_id; +} play_sound_end_callback_data_t; -int mm_sound_client_is_route_available(mm_sound_route route, bool *is_available) +void _system_signal_handler(int signo) { int ret = MM_ERROR_NONE; - debug_fenter(); - - ret = mm_sound_client_dbus_is_route_available(route, is_available); - - debug_fleave(); - return ret; - -} + sigset_t old_mask, all_mask; -int mm_sound_client_foreach_available_route_cb(mm_sound_available_route_cb available_route_cb, void *user_data) -{ - int ret = MM_ERROR_NONE; - debug_fenter(); + debug_warning("Got signal : signo(%d)", signo); - ret = mm_sound_client_dbus_foreach_available_route_cb(available_route_cb, user_data); + /* signal block */ - debug_fleave(); - return ret; -} + sigfillset(&all_mask); + sigprocmask(SIG_BLOCK, &all_mask, &old_mask); -int mm_sound_client_set_active_route(mm_sound_route route, bool need_broadcast) -{ - int ret = MM_ERROR_NONE; - debug_fenter(); + if (g_need_emergent_exit) { + ret = mm_sound_proxy_emergent_exit(getpid()); + if (ret == MM_ERROR_NONE) + debug_msg("[Client] Success to emergnet_exit\n"); + else + debug_error("[Client] Error occurred : 0x%x \n",ret); + } - ret = mm_sound_client_dbus_set_active_route(route, need_broadcast); + sigprocmask(SIG_SETMASK, &old_mask, NULL); + /* signal unblock */ - debug_fleave(); - return ret; + switch (signo) { + case SIGINT: + sigaction(SIGINT, &system_int_old_action, NULL); + raise( signo); + break; + case SIGABRT: + sigaction(SIGABRT, &system_abrt_old_action, NULL); + raise( signo); + break; + case SIGSEGV: + sigaction(SIGSEGV, &system_segv_old_action, NULL); + raise( signo); + break; + case SIGTERM: + sigaction(SIGTERM, &system_term_old_action, NULL); + raise( signo); + break; + case SIGSYS: + sigaction(SIGSYS, &system_sys_old_action, NULL); + raise( signo); + break; + case SIGXCPU: + sigaction(SIGXCPU, &system_xcpu_old_action, NULL); + raise( signo); + break; + default: + break; + } + debug_warning("signal handling end"); } -int mm_sound_client_set_active_route_auto(void) +int mm_sound_client_initialize(void) { int ret = MM_ERROR_NONE; debug_fenter(); - ret = mm_sound_client_dbus_set_active_route_auto(); - - debug_fleave(); - return ret; - -} - -int mm_sound_client_get_active_device(mm_sound_device_in *device_in, mm_sound_device_out *device_out) -{ - - int ret = MM_ERROR_NONE; - debug_fenter(); + mm_sound_proxy_initialize(); - ret = mm_sound_client_dbus_get_active_device(device_in, device_out); - debug_fleave(); - return ret; -} + struct sigaction system_action; + system_action.sa_handler = _system_signal_handler; + system_action.sa_flags = SA_NOCLDSTOP; -int mm_sound_client_add_active_device_changed_callback(const char *name, mm_sound_active_device_changed_cb func, void* user_data) -{ - int ret = MM_ERROR_NONE; - debug_fenter(); + sigemptyset(&system_action.sa_mask); - ret = mm_sound_client_dbus_add_active_device_changed_callback(name, func, user_data); + sigaction(SIGINT, &system_action, &system_int_old_action); + sigaction(SIGABRT, &system_action, &system_abrt_old_action); + sigaction(SIGSEGV, &system_action, &system_segv_old_action); + sigaction(SIGTERM, &system_action, &system_term_old_action); + sigaction(SIGSYS, &system_action, &system_sys_old_action); + sigaction(SIGXCPU, &system_action, &system_xcpu_old_action); debug_fleave(); return ret; } -int mm_sound_client_remove_active_device_changed_callback(const char *name) +int mm_sound_client_finalize(void) { int ret = MM_ERROR_NONE; - debug_fenter(); - - ret = mm_sound_client_dbus_remove_active_device_changed_callback(name); - debug_fleave(); - return ret; -} -int mm_sound_client_add_available_route_changed_callback(mm_sound_available_route_changed_cb func, void* user_data) -{ - int ret = MM_ERROR_NONE; debug_fenter(); - ret = mm_sound_client_dbus_add_available_route_changed_callback(func, user_data); + if (g_need_emergent_exit) { + ret = mm_sound_proxy_emergent_exit(getpid()); + if (ret == MM_ERROR_NONE) + debug_msg("[Client] Success to emergnet_exit\n"); + else + debug_error("[Client] Error occurred : 0x%x \n",ret); + } - debug_fleave(); - return ret; -} + sigaction(SIGINT, &system_int_old_action, NULL); + sigaction(SIGABRT, &system_abrt_old_action, NULL); + sigaction(SIGSEGV, &system_segv_old_action, NULL); + sigaction(SIGTERM, &system_term_old_action, NULL); + sigaction(SIGSYS, &system_sys_old_action, NULL); + sigaction(SIGXCPU, &system_xcpu_old_action, NULL); -int mm_sound_client_remove_available_route_changed_callback(void) -{ - int ret = MM_ERROR_NONE; - debug_fenter(); + ret = mm_sound_proxy_finalize(); - ret = mm_sound_client_dbus_remove_available_route_changed_callback(); - debug_fleave(); - return ret; -} +#ifdef USE_FOCUS -int mm_sound_client_set_sound_path_for_active_device(mm_sound_device_out device_out, mm_sound_device_in device_in) -{ - int ret = MM_ERROR_NONE; - debug_fenter(); + if (g_focus_thread) { + g_main_loop_quit(g_focus_loop); + g_thread_join(g_focus_thread); + debug_log("after thread join"); + g_main_loop_unref(g_focus_loop); + g_focus_thread = NULL; + } - ret = mm_sound_client_dbus_set_sound_path_for_active_device(device_out, device_in); +#endif debug_fleave(); return ret; @@ -207,57 +256,58 @@ void mm_sound_convert_volume_type_to_stream_type(int volume_type, char *stream_t { switch (volume_type) { case VOLUME_TYPE_SYSTEM: - strncpy(stream_type, "system", MM_SOUND_STREAM_TYPE_LEN); + MMSOUND_STRNCPY(stream_type, "system", MM_SOUND_STREAM_TYPE_LEN); break; case VOLUME_TYPE_NOTIFICATION: - strncpy(stream_type, "notification", MM_SOUND_STREAM_TYPE_LEN); + MMSOUND_STRNCPY(stream_type, "notification", MM_SOUND_STREAM_TYPE_LEN); break; case VOLUME_TYPE_ALARM: - strncpy(stream_type, "alarm", MM_SOUND_STREAM_TYPE_LEN); + MMSOUND_STRNCPY(stream_type, "alarm", MM_SOUND_STREAM_TYPE_LEN); break; case VOLUME_TYPE_RINGTONE: - strncpy(stream_type, "ringtone-voip", MM_SOUND_STREAM_TYPE_LEN); + MMSOUND_STRNCPY(stream_type, "ringtone-voip", MM_SOUND_STREAM_TYPE_LEN); break; case VOLUME_TYPE_MEDIA: - strncpy(stream_type, "media", MM_SOUND_STREAM_TYPE_LEN); + MMSOUND_STRNCPY(stream_type, "media", MM_SOUND_STREAM_TYPE_LEN); break; case VOLUME_TYPE_CALL: - strncpy(stream_type, "system", MM_SOUND_STREAM_TYPE_LEN); + MMSOUND_STRNCPY(stream_type, "call-voice", MM_SOUND_STREAM_TYPE_LEN); break; case VOLUME_TYPE_VOIP: - strncpy(stream_type, "voip", MM_SOUND_STREAM_TYPE_LEN); + MMSOUND_STRNCPY(stream_type, "voip", MM_SOUND_STREAM_TYPE_LEN); break; case VOLUME_TYPE_VOICE: - strncpy(stream_type, "voice-recognition", MM_SOUND_STREAM_TYPE_LEN); + MMSOUND_STRNCPY(stream_type, "voice-recognition", MM_SOUND_STREAM_TYPE_LEN); break; default: - strncpy(stream_type, "media", MM_SOUND_STREAM_TYPE_LEN); + MMSOUND_STRNCPY(stream_type, "media", MM_SOUND_STREAM_TYPE_LEN); break; } - debug_error("volume type (%d) converted to stream type (%s)", volume_type, stream_type); + debug_msg("volume type (%d) converted to stream type (%s)", volume_type, stream_type); } /***************************************************************************************** DBUS SUPPORTED FUNCTIONS ******************************************************************************************/ - +#ifdef USE_FOCUS void _mm_sound_client_focus_signal_callback(mm_sound_signal_name_t signal, int value, void *user_data) { int ret = MM_ERROR_NONE; debug_fenter(); - debug_error("focus signal received, value = %d", value); + debug_msg("focus signal received, value = %d", value); if (value == 1) { - ret = mm_sound_client_dbus_clear_focus(getpid()); + ret = mm_sound_proxy_clear_focus(getpid()); if (ret) debug_error("clear focus failed ret = 0x%x", ret); mm_sound_unsubscribe_signal(g_focus_signal_handle); g_focus_signal_handle = 0; } } +#endif int mm_sound_client_play_tone(int number, int volume_config, double volume, int time, int *handle, bool enable_session) { @@ -282,15 +332,12 @@ int mm_sound_client_play_tone(int number, int volume_config, double volume, int if (is_focus_registered) enable_session = false; - if (enable_session) - { - if (MM_ERROR_NONE != _mm_session_util_read_information(-1, &session_type, &session_options)) - { + if (enable_session) { + if (MM_ERROR_NONE != _mm_session_util_read_information(-1, &session_type, &session_options)) { debug_warning("[Client] Read Session Information failed. use default \"media\" type\n"); session_type = MM_SESSION_TYPE_MEDIA; - if(MM_ERROR_NONE != mm_session_init(session_type)) - { + if(MM_ERROR_NONE != mm_session_init(session_type)) { debug_critical("[Client] MMSessionInit() failed\n"); return MM_ERROR_POLICY_INTERNAL; } @@ -305,9 +352,9 @@ int mm_sound_client_play_tone(int number, int volume_config, double volume, int /* Send req memory */ mm_sound_convert_volume_type_to_stream_type(volume_type, stream_type); - ret = mm_sound_client_dbus_play_tone(number, time, volume, volume_config, + ret = mm_sound_proxy_play_tone(number, time, volume, volume_config, session_type, session_options, getpid(), enable_session, handle, stream_type, -1); - +#ifdef USE_FOCUS if (enable_session && !g_focus_signal_handle) { ret = mm_sound_subscribe_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &g_focus_signal_handle, _mm_sound_client_focus_signal_callback, NULL); if (ret) { @@ -315,6 +362,7 @@ int mm_sound_client_play_tone(int number, int volume_config, double volume, int return MM_ERROR_POLICY_INTERNAL; } } +#endif debug_fleave(); return ret; @@ -326,12 +374,47 @@ int mm_sound_client_play_tone_with_stream_info(int tone, char *stream_type, int debug_fenter(); - ret = mm_sound_client_dbus_play_tone_with_stream_info(getpid(), tone, stream_type, stream_id, volume, duration, handle); + ret = mm_sound_proxy_play_tone_with_stream_info(getpid(), tone, stream_type, stream_id, volume, duration, handle); debug_fleave(); return ret; } +static void _mm_sound_stop_callback_wrapper_func(int ended_handle, void *userdata) +{ + struct callback_data *cb_data = (struct callback_data*) userdata; + play_sound_end_callback_data_t *end_cb_data; + + debug_log("[Wrapper CB][Play Stop] ended_handle : %d", ended_handle); + + if (cb_data == NULL) { + debug_warning("stop callback data null"); + return; + } + + end_cb_data = (play_sound_end_callback_data_t*) cb_data->extra_data; + + if (ended_handle == end_cb_data->watching_handle) { + debug_log("Interested playing handle end : %d", ended_handle); + ((mm_sound_stop_callback_func)(cb_data->user_cb))(cb_data->user_data, ended_handle); + if (mm_sound_proxy_remove_play_sound_end_callback(end_cb_data->subs_id) != MM_ERROR_NONE) + debug_error("mm_sound_client_dbus_remove_play_file_end_callback failed"); + } else { + debug_log("Not interested playing handle : %d", ended_handle); + } +} + +static void play_end_callback_data_free_func(void *data) +{ + struct callback_data *cb_data = (struct callback_data*) data; + + if (cb_data) { + if (cb_data->extra_data) + g_free(cb_data->extra_data); + g_free(cb_data); + } +} + int mm_sound_client_play_sound(MMSoundPlayParam *param, int tone, int *handle) { int ret = MM_ERROR_NONE; @@ -341,6 +424,8 @@ int mm_sound_client_play_sound(MMSoundPlayParam *param, int tone, int *handle) // int instance = -1; /* instance is unique to communicate with server : client message queue filter type */ int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(param->volume_config); char stream_type[MM_SOUND_STREAM_TYPE_LEN] = {0, }; + struct callback_data *cb_data = NULL; + play_sound_end_callback_data_t *end_cb_data; debug_fenter(); @@ -356,31 +441,25 @@ int mm_sound_client_play_sound(MMSoundPlayParam *param, int tone, int *handle) param->skip_session = true; if (param->skip_session == false) { - if(MM_ERROR_NONE != _mm_session_util_read_information(-1, &session_type, &session_options)) - { + if(MM_ERROR_NONE != _mm_session_util_read_information(-1, &session_type, &session_options)) { debug_warning("[Client] Read MMSession Type failed. use default \"media\" type\n"); session_type = MM_SESSION_TYPE_MEDIA; - if(MM_ERROR_NONE != mm_session_init(session_type)) - { + if(MM_ERROR_NONE != mm_session_init(session_type)) { debug_critical("[Client] MMSessionInit() failed\n"); return MM_ERROR_POLICY_INTERNAL; } } } -// instance = getpid(); -// debug_msg("[Client] pid for client ::: [%d]\n", instance); - /* Send msg */ - if ((param->mem_ptr && param->mem_size)) - { + if ((param->mem_ptr && param->mem_size)) { // Play memory, deprecated return MM_ERROR_INVALID_ARGUMENT; } mm_sound_convert_volume_type_to_stream_type(volume_type, stream_type); - ret = mm_sound_client_dbus_play_sound(param->filename, tone, param->loop, param->volume, param->volume_config, + ret = mm_sound_proxy_play_sound(param->filename, tone, param->loop, param->volume, param->volume_config, param->priority, session_type, session_options, getpid(), param->handle_route, !param->skip_session, handle, stream_type, -1); if (ret != MM_ERROR_NONE) { @@ -388,11 +467,16 @@ int mm_sound_client_play_sound(MMSoundPlayParam *param, int tone, int *handle) goto failed; } if (param->callback) { - ret = mm_sound_client_dbus_add_play_sound_end_callback(*handle, param->callback, param->data); + end_cb_data = (play_sound_end_callback_data_t *) g_malloc0(sizeof(play_sound_end_callback_data_t)); + end_cb_data->watching_handle = *handle; + GET_CB_DATA(cb_data, param->callback, param->data, end_cb_data); + + ret = mm_sound_proxy_add_play_sound_end_callback(_mm_sound_stop_callback_wrapper_func, cb_data, play_end_callback_data_free_func, &end_cb_data->subs_id); if (ret != MM_ERROR_NONE) { debug_error("Add callback for play sound(%d) Failed", *handle); } } +#ifdef USE_FOCUS if (!param->skip_session && !g_focus_signal_handle) { ret = mm_sound_subscribe_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &g_focus_signal_handle, _mm_sound_client_focus_signal_callback, NULL); if (ret) { @@ -400,6 +484,7 @@ int mm_sound_client_play_sound(MMSoundPlayParam *param, int tone, int *handle) return MM_ERROR_POLICY_INTERNAL; } } +#endif failed: @@ -410,15 +495,21 @@ failed: int mm_sound_client_play_sound_with_stream_info(MMSoundPlayParam *param, int *handle, char* stream_type, int stream_id) { int ret = MM_ERROR_NONE; + struct callback_data *cb_data = NULL; + play_sound_end_callback_data_t *end_cb_data; - ret = mm_sound_client_dbus_play_sound_with_stream_info(param->filename, param->loop, param->volume, + ret = mm_sound_proxy_play_sound_with_stream_info(param->filename, param->loop, param->volume, param->priority, getpid(), param->handle_route, handle, stream_type, stream_id); if (ret != MM_ERROR_NONE) { debug_error("Play Sound Failed"); goto failed; } if (param->callback) { - ret = mm_sound_client_dbus_add_play_sound_end_callback(*handle, param->callback, param->data); + end_cb_data = (play_sound_end_callback_data_t *) g_malloc0(sizeof(play_sound_end_callback_data_t)); + end_cb_data->watching_handle = *handle; + GET_CB_DATA(cb_data, param->callback, param->data, end_cb_data); + + ret = mm_sound_proxy_add_play_sound_end_callback(_mm_sound_stop_callback_wrapper_func, cb_data, play_end_callback_data_free_func, &end_cb_data->subs_id); if (ret != MM_ERROR_NONE) { debug_error("Add callback for play sound(%d) Failed", *handle); } @@ -441,28 +532,12 @@ int mm_sound_client_stop_sound(int handle) return ret; } - ret = mm_sound_client_dbus_stop_sound(handle); + ret = mm_sound_proxy_stop_sound(handle); debug_fleave(); return ret; } -static int _mm_sound_client_device_list_clear () -{ - int ret = MM_ERROR_NONE; - - MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_list_mutex, MM_ERROR_SOUND_INTERNAL); - - if (g_device_list_t.list) { - g_list_free_full(g_device_list_t.list, g_free); - g_device_list_t.list = NULL; - } - - MMSOUND_LEAVE_CRITICAL_SECTION(&g_device_list_mutex); - - return ret; -} - static int _mm_sound_client_device_list_dump (GList *device_list) { int ret = MM_ERROR_NONE; @@ -487,250 +562,1416 @@ static int _mm_sound_client_device_list_dump (GList *device_list) return ret; } -int mm_sound_client_get_current_connected_device_list(int device_flags, mm_sound_device_list_t **device_list) +int mm_sound_client_get_current_connected_device_list(int device_flags, mm_sound_device_list_t *device_list) { int ret = MM_ERROR_NONE; debug_fenter(); - ret = _mm_sound_client_device_list_clear(); - if (ret) { - debug_error("[Client] failed to __mm_sound_client_device_list_clear(), ret[0x%x]\n", ret); - return ret; + if (!device_list) { + debug_error("Device list NULL"); + ret = MM_ERROR_COMMON_INVALID_ARGUMENT; + goto failed; } - if ((ret = mm_sound_client_dbus_get_current_connected_device_list(device_flags, &g_device_list_t.list)) != MM_ERROR_NONE) { + if ((ret = mm_sound_proxy_get_current_connected_device_list(device_flags, &device_list->list)) != MM_ERROR_NONE) { debug_error("[Client] failed to get current connected device list with dbus, ret[0x%x]", ret); goto failed; } - if (!g_device_list_t.list) { + if (!device_list->list) { debug_error("Got device list null"); ret = MM_ERROR_SOUND_NO_DATA; goto failed; } -// g_device_list_t.list = g_device_list; - _mm_sound_client_device_list_dump(g_device_list_t.list); - *device_list = &g_device_list_t; + _mm_sound_client_device_list_dump(device_list->list); failed: debug_fleave(); return ret; } -int mm_sound_client_add_device_connected_callback(int device_flags, mm_sound_device_connected_cb func, void* user_data) +static bool device_is_match_direction(int direction, int mask) { - int ret = MM_ERROR_NONE; + if (mask == DEVICE_IO_DIRECTION_FLAGS || mask == 0) + return true; - debug_fenter(); + if ((mask & MM_SOUND_DEVICE_IO_DIRECTION_IN_FLAG) && (direction & MM_SOUND_DEVICE_IO_DIRECTION_IN)) + return true; + if ((mask & MM_SOUND_DEVICE_IO_DIRECTION_OUT_FLAG) && (direction & MM_SOUND_DEVICE_IO_DIRECTION_OUT)) + return true; + if ((mask & MM_SOUND_DEVICE_IO_DIRECTION_BOTH_FLAG) && (direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH)) + return true; - ret = mm_sound_client_dbus_add_device_connected_callback(device_flags, func, user_data); + return false; +} - debug_fleave(); - return ret; +static bool device_is_match_state(int state, int mask) +{ + if (mask == DEVICE_STATE_FLAGS || mask == 0) + return true; + if ((mask & MM_SOUND_DEVICE_STATE_DEACTIVATED_FLAG) && (state == MM_SOUND_DEVICE_STATE_DEACTIVATED)) + return true; + if ((mask & MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG) && (state == MM_SOUND_DEVICE_STATE_ACTIVATED)) + return true; + + return false; } -int mm_sound_client_remove_device_connected_callback(void) +static bool device_is_match_type(const char *type, int mask) { - int ret = MM_ERROR_NONE; - debug_fenter(); + bool is_builtin; + const char *builtin_prefix = "builtin"; - ret = mm_sound_client_dbus_remove_device_connected_callback(); + if (mask == DEVICE_TYPE_FLAGS || mask == 0) + return true; - debug_fleave(); - return ret; + is_builtin = !strncmp(type, builtin_prefix, strlen(builtin_prefix)); + + if ((mask & MM_SOUND_DEVICE_TYPE_INTERNAL_FLAG) && (is_builtin)) + return true; + if ((mask & MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG) && (!is_builtin)) + return true; + + return false; } -int mm_sound_client_add_device_info_changed_callback(int device_flags, mm_sound_device_info_changed_cb func, void* user_data) +static bool device_is_match_with_mask(const char *type, int direction, int state, int mask) { - int ret = MM_ERROR_NONE; + if (mask == DEVICE_ALL_FLAG) + return true; - debug_fenter(); + return (device_is_match_direction(direction, mask & DEVICE_IO_DIRECTION_FLAGS) && + device_is_match_state(state, mask & DEVICE_STATE_FLAGS) && + device_is_match_type(type, mask & DEVICE_TYPE_FLAGS)); +} - ret = mm_sound_client_dbus_add_device_info_changed_callback(device_flags, func, user_data); +static int _fill_sound_device(mm_sound_device_t *device_h, int device_id, const char *device_type, + int direction, int state, const char *name, int *stream_id, int stream_num) +{ + int i; - debug_fleave(); - return ret; + if (stream_num > 0 && stream_id == NULL) { + debug_error("stream_num is %d, but stream_id is NULL", stream_num); + return -1; + } + + if (stream_num > MAX_STREAM_ON_DEVICE) { + debug_error("too many streams on this device"); + return -1; + } + + device_h->id = device_id; + device_h->io_direction = direction; + device_h->state = state; + MMSOUND_STRNCPY(device_h->name, name, MAX_DEVICE_NAME_NUM); + MMSOUND_STRNCPY(device_h->type, device_type, MAX_DEVICE_TYPE_STR_LEN); + + if (stream_num > 0) { + device_h->stream_num = stream_num; + debug_log("%d streams on this device", stream_num); + for (i = 0; i < stream_num; i++) { + debug_log(" stream_id : %d", stream_id[i]); + device_h->stream_id[i] = stream_id[i]; + } + } else { + device_h->stream_num = 0; + debug_log("There is no stream on this device"); + } + + return 0; } -int mm_sound_client_remove_device_info_changed_callback(void) +static void _mm_sound_device_connected_callback_wrapper_func(int device_id, const char *device_type, int io_direction, + int state, const char *name, int *stream_id, int stream_num, gboolean is_connected, void *userdata) { - int ret = MM_ERROR_NONE; - debug_fenter(); + mm_sound_device_t device_h; + struct callback_data *cb_data = (struct callback_data*) userdata; + int device_flags; - ret = mm_sound_client_dbus_remove_device_info_changed_callback(); + debug_log("[Device %s] id(%d) type(%s) direction(%d) state(%d) name(%s)", + is_connected ? "Connected" : "Disconnected", device_id, device_type, io_direction, + state, name, is_connected); - debug_fleave(); - return ret; + if (cb_data == NULL) { + debug_warning("device connected changed callback data null"); + return; + } + + device_flags = (int) cb_data->extra_data; + if (!device_is_match_with_mask(device_type, io_direction, state, device_flags)) + return; + + if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name, stream_id, stream_num) < 0) { + debug_error("Failed to fill sound device"); + return; + } + ((mm_sound_device_connected_cb)(cb_data->user_cb))(&device_h, is_connected, cb_data->user_data); } -int mm_sound_client_is_bt_a2dp_on (bool *connected, char** bt_name) + +int mm_sound_client_add_device_connected_callback(int device_flags, mm_sound_device_connected_cb func, void* userdata, unsigned int *subs_id) { int ret = MM_ERROR_NONE; + struct callback_data *cb_data = NULL; debug_fenter(); - ret = mm_sound_client_dbus_is_bt_a2dp_on(connected, bt_name); + GET_CB_DATA(cb_data, func, userdata, (void*) device_flags); + + ret = mm_sound_proxy_add_device_connected_callback(device_flags, _mm_sound_device_connected_callback_wrapper_func, cb_data, g_free, subs_id); + if (ret == MM_ERROR_NONE) + g_need_emergent_exit = TRUE; debug_fleave(); return ret; } -int mm_sound_client_set_volume_by_type(const int volume_type, const unsigned int volume_level) +int mm_sound_client_remove_device_connected_callback(unsigned int subs_id) { int ret = MM_ERROR_NONE; - debug_fenter(); - ret = mm_sound_client_dbus_set_volume_by_type(volume_type, volume_level); + ret = mm_sound_proxy_remove_device_connected_callback(subs_id); debug_fleave(); return ret; } -int mm_sound_client_add_volume_changed_callback(mm_sound_volume_changed_cb func, void* user_data) +static void _mm_sound_device_info_changed_callback_wrapper_func(int device_id, const char *device_type, int io_direction, + int state, const char *name, int *stream_id, int stream_num, int changed_device_info_type, void *userdata) +{ + mm_sound_device_t device_h; + struct callback_data *cb_data = (struct callback_data*) userdata; + int device_flags; + + debug_log("[Device Info Changed] id(%d) type(%s) direction(%d) state(%d) name(%s) changed_info_type(%d)", + device_id, device_type, io_direction, state, name, changed_device_info_type); + + if (cb_data == NULL) { + debug_warning("device info changed callback data null"); + return; + } + + device_flags = (int) cb_data->extra_data; + if (!device_is_match_with_mask(device_type, io_direction, state, device_flags)) + return; + + if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name, stream_id, stream_num) < 0) { + debug_error("Failed to fill sound device"); + return; + } + + ((mm_sound_device_info_changed_cb)(cb_data->user_cb))(&device_h, changed_device_info_type, cb_data->user_data); +} + +int mm_sound_client_add_device_info_changed_callback(int device_flags, mm_sound_device_info_changed_cb func, void *userdata, unsigned int *subs_id) { int ret = MM_ERROR_NONE; + struct callback_data *cb_data = (struct callback_data*) userdata; debug_fenter(); - ret = mm_sound_client_dbus_add_volume_changed_callback(func, user_data); + GET_CB_DATA(cb_data, func, userdata, (void *) device_flags); + + ret = mm_sound_proxy_add_device_info_changed_callback(device_flags, _mm_sound_device_info_changed_callback_wrapper_func, cb_data, g_free, subs_id); debug_fleave(); return ret; } -int mm_sound_client_remove_volume_changed_callback(void) +int mm_sound_client_remove_device_info_changed_callback(unsigned int subs_id) { int ret = MM_ERROR_NONE; debug_fenter(); - ret = mm_sound_client_dbus_remove_volume_changed_callback(); + ret = mm_sound_proxy_remove_device_info_changed_callback(subs_id); debug_fleave(); return ret; + } +static void _mm_sound_device_state_changed_callback_wrapper_func(int device_id, const char *device_type, int io_direction, + int state, const char *name, int *stream_id, int stream_num, void *userdata) +{ + mm_sound_device_t device_h; + struct callback_data *cb_data = (struct callback_data*) userdata; + int device_flags; + + debug_log("[Device State Changed] id(%d) type(%s) direction(%d) state(%d) name(%s)", + device_id, device_type, io_direction, state, name); + + if (cb_data == NULL) { + debug_warning("device state changed callback data null"); + return; + } + + device_flags = (int) cb_data->extra_data; + + if (!device_is_match_with_mask(device_type, io_direction, state, device_flags)) + return; + + if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name, stream_id, stream_num) < 0) { + debug_error("Failed to fill sound device"); + return; + } + + ((mm_sound_device_state_changed_cb)(cb_data->user_cb))(&device_h, state, cb_data->user_data); +} -int mm_sound_client_get_audio_path(mm_sound_device_in *device_in, mm_sound_device_out *device_out) +int mm_sound_client_add_device_state_changed_callback(int device_flags, mm_sound_device_state_changed_cb func, void *userdata, unsigned int *id) { int ret = MM_ERROR_NONE; + struct callback_data *cb_data = (struct callback_data*) userdata; debug_fenter(); - ret = mm_sound_client_dbus_get_audio_path(device_in, device_out); + GET_CB_DATA(cb_data, func, userdata, (void *) device_flags); - debug_fleave(); + ret = mm_sound_proxy_add_device_state_changed_callback(device_flags, _mm_sound_device_state_changed_callback_wrapper_func, cb_data, g_free, id); + debug_fleave(); return ret; } - -#ifdef USE_FOCUS -int mm_sound_client_get_uniq_id(int *id) +int mm_sound_client_remove_device_state_changed_callback(unsigned int id) { - static int uniq_id = 0; int ret = MM_ERROR_NONE; - - MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_id_mutex, MM_ERROR_SOUND_INTERNAL); debug_fenter(); - if (!id) - ret = MM_ERROR_INVALID_ARGUMENT; - else - *id = ++uniq_id; + ret = mm_sound_proxy_remove_device_state_changed_callback(id); debug_fleave(); - MMSOUND_LEAVE_CRITICAL_SECTION(&g_id_mutex); - return ret; } -int mm_sound_client_register_focus(int id, const char *stream_type, mm_sound_focus_changed_cb callback, void* user_data) +int mm_sound_client_is_stream_on_device(int stream_id, int device_id, bool *is_on) { int ret = MM_ERROR_NONE; debug_fenter(); - ret = mm_sound_client_dbus_register_focus(id, stream_type, callback, user_data); + if (!is_on) { + debug_error("Invalid Parameter"); + ret = MM_ERROR_COMMON_INVALID_ARGUMENT; + goto failed; + } + + if ((ret = mm_sound_proxy_is_stream_on_device(stream_id, device_id, is_on)) != MM_ERROR_NONE) { + debug_error("[Client] failed to query is stream on device, ret[0x%x]", ret); + goto failed; + } +failed: debug_fleave(); return ret; } -int mm_sound_client_unregister_focus(int id) +int __convert_volume_type_to_str(int volume_type, char **volume_type_str) { int ret = MM_ERROR_NONE; - debug_fenter(); - ret = mm_sound_client_dbus_unregister_focus(id); + if (!volume_type_str) { + return MM_ERROR_COMMON_INVALID_ARGUMENT; + } - debug_fleave(); + switch (volume_type) { + case VOLUME_TYPE_SYSTEM: + *volume_type_str = "system"; + break; + case VOLUME_TYPE_NOTIFICATION: + *volume_type_str = "notification"; + break; + case VOLUME_TYPE_ALARM: + *volume_type_str = "alarm"; + break; + case VOLUME_TYPE_RINGTONE: + *volume_type_str = "ringtone"; + break; + case VOLUME_TYPE_MEDIA: + *volume_type_str = "media"; + break; + case VOLUME_TYPE_CALL: + *volume_type_str = "call"; + break; + case VOLUME_TYPE_VOIP: + *volume_type_str = "voip"; + break; + case VOLUME_TYPE_VOICE: + *volume_type_str = "voice"; + break; + } + if (!strncmp(*volume_type_str,"", VOLUME_TYPE_LEN)) { + debug_error("could not find the volume_type[%d] in this switch case statement", volume_type); + ret = MM_ERROR_SOUND_INTERNAL; + } else { + debug_log("volume_type[%s]", *volume_type_str); + } return ret; } -int mm_sound_client_acquire_focus(int id, mm_sound_focus_type_e type, const char *option) +static int __convert_volume_type_to_int(const char *volume_type_str, volume_type_t *volume_type) { int ret = MM_ERROR_NONE; - debug_fenter(); - ret = mm_sound_client_dbus_acquire_focus(id, type, option); + if (!volume_type || !volume_type_str) { + return MM_ERROR_COMMON_INVALID_ARGUMENT; + } + + if (!strncmp(volume_type_str, "system", VOLUME_TYPE_LEN)) { + *volume_type = VOLUME_TYPE_SYSTEM; + } else if (!strncmp(volume_type_str, "notification", VOLUME_TYPE_LEN)) { + *volume_type = VOLUME_TYPE_NOTIFICATION; + } else if (!strncmp(volume_type_str, "alarm", VOLUME_TYPE_LEN)) { + *volume_type = VOLUME_TYPE_ALARM; + } else if (!strncmp(volume_type_str, "ringtone", VOLUME_TYPE_LEN)) { + *volume_type = VOLUME_TYPE_RINGTONE; + } else if (!strncmp(volume_type_str, "media", VOLUME_TYPE_LEN)) { + *volume_type = VOLUME_TYPE_MEDIA; + } else if (!strncmp(volume_type_str, "call", VOLUME_TYPE_LEN)) { + *volume_type = VOLUME_TYPE_CALL; + } else if (!strncmp(volume_type_str, "voip", VOLUME_TYPE_LEN)) { + *volume_type = VOLUME_TYPE_VOIP; + } else if (!strncmp(volume_type_str, "voice", VOLUME_TYPE_LEN)) { + *volume_type = VOLUME_TYPE_VOICE; + } else { + debug_log("Invalid volume type : [%s]", volume_type_str); + ret = MM_ERROR_SOUND_INTERNAL; + } - debug_fleave(); return ret; } -int mm_sound_client_release_focus(int id, mm_sound_focus_type_e type, const char *option) +int mm_sound_client_set_volume_by_type(const int volume_type, const unsigned int volume_level) { int ret = MM_ERROR_NONE; + char *type_str = NULL; debug_fenter(); - mm_sound_client_dbus_release_focus(id, type, option); + if ((ret = __convert_volume_type_to_str(volume_type, &type_str)) != MM_ERROR_NONE) { + debug_error("volume type convert failed"); + goto failed; + } + + ret = mm_sound_proxy_set_volume_by_type(type_str, volume_level); +failed: debug_fleave(); return ret; } -int mm_sound_client_set_focus_watch_callback(mm_sound_focus_type_e focus_type, mm_sound_focus_changed_watch_cb callback, void* user_data, int *id) +static void _mm_sound_volume_changed_callback_wrapper_func(const char *direction, const char *volume_type_str, int volume_level, void *userdata) +{ + volume_type_t volume_type = 0; + struct callback_data *cb_data = (struct callback_data *) userdata; + + debug_log("[Wrapper CB][Volume Changed] direction : %s, volume_type : %s, volume_level : %d", direction, volume_type_str, volume_level); + + if (cb_data == NULL) { + debug_warning("volume changed callback data null"); + return; + } + + if (__convert_volume_type_to_int(volume_type_str, &volume_type) != MM_ERROR_NONE) { + debug_error("volume type convert failed"); + return; + } + debug_log("Call volume changed user cb, direction : %s, vol_type : %s(%d), level : %u", direction, volume_type_str, volume_type, volume_level); + ((mm_sound_volume_changed_cb)(cb_data->user_cb))(volume_type, volume_level, cb_data->user_data); +} + +int mm_sound_client_add_volume_changed_callback(mm_sound_volume_changed_cb func, void* userdata, unsigned int *subs_id) { int ret = MM_ERROR_NONE; + struct callback_data *cb_data = NULL; + debug_fenter(); - mm_sound_client_dbus_set_focus_watch_callback(focus_type, callback, user_data, id); + GET_CB_DATA(cb_data, func, userdata, NULL); + + ret = mm_sound_proxy_add_volume_changed_callback(_mm_sound_volume_changed_callback_wrapper_func, cb_data, g_free, subs_id); debug_fleave(); + return ret; } -int mm_sound_client_unset_focus_watch_callback(int id) +int mm_sound_client_remove_volume_changed_callback(unsigned int subs_id) { int ret = MM_ERROR_NONE; debug_fenter(); - ret = mm_sound_client_dbus_unset_focus_watch_callback(id); + ret = mm_sound_proxy_remove_volume_changed_callback(subs_id); + + debug_fleave(); + return ret; +} + +#ifdef USE_FOCUS +int mm_sound_client_set_session_interrupt_callback(mm_sound_focus_session_interrupt_cb callback, void* user_data) +{ + int ret = MM_ERROR_NONE; + + debug_fenter(); + + if (!callback) + return MM_ERROR_INVALID_ARGUMENT; + + g_focus_session_interrupt_info.user_cb = callback; + g_focus_session_interrupt_info.user_data = user_data; + + debug_fleave(); + return ret; +} + +int mm_sound_client_unset_session_interrupt_callback(void) +{ + int ret = MM_ERROR_NONE; + + debug_fenter(); + + if (!g_focus_session_interrupt_info.user_cb) { + debug_error("no callback to unset"); + return MM_ERROR_SOUND_INTERNAL; + } + + g_focus_session_interrupt_info.user_cb = NULL; + g_focus_session_interrupt_info.user_data = NULL; + + debug_fleave(); + return ret; +} + +static gpointer _focus_thread_func(gpointer data) +{ + unsigned int thread_id = (unsigned int)pthread_self(); + debug_warning(">>> thread func..ID of this thread(%u), mainloop(%p)", thread_id, g_focus_loop); + if (g_focus_loop) + g_main_loop_run(g_focus_loop); + + debug_warning("<<< quit thread func..(%u), mainloop(%p)", thread_id, g_focus_loop); + return NULL; +} + +static gboolean _focus_fd_check(GSource * source) +{ + GSList *fd_list; + GPollFD *temp; + + if (!source) { + debug_error("GSource is null"); + return FALSE; + } + fd_list = source->poll_fds; + if (!fd_list) { + debug_error("fd_list is null"); + return FALSE; + } + do { + temp = (GPollFD*)fd_list->data; + if (!temp) { + debug_error("fd_list->data is null"); + return FALSE; + } + if (temp->revents & (POLLIN | POLLPRI)) { + return TRUE; + } + fd_list = fd_list->next; + } while (fd_list); + + return FALSE; /* there is no change in any fd state */ +} + +static gboolean _focus_fd_prepare(GSource *source, gint *timeout) +{ + return FALSE; +} + +static gboolean _focus_fd_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) +{ + callback(user_data); + return TRUE; +} + +static int _focus_find_index_by_handle(int handle) +{ + int i = 0; + for (i = 0; i < FOCUS_HANDLE_MAX; i++) { + if (g_focus_sound_handle[i].focus_callback && handle == g_focus_sound_handle[i].handle) { + /* debug_msg("found index(%d) for handle(%d)", i, handle);*/ + return (handle == FOCUS_HANDLE_INIT_VAL)? -1 : i; + } + } + return -1; +} + +static int _focus_watch_find_index_by_handle(int handle) +{ + int i = 0; + for (i = 0; i < FOCUS_HANDLE_MAX; i++) { + if (g_focus_sound_handle[i].watch_callback && handle == g_focus_sound_handle[i].handle) { + /* debug_msg("found index(%d) for watch handle(%d)", i, handle);*/ + return (handle == FOCUS_HANDLE_INIT_VAL)? -1 : i; + } + } + return -1; +} + +static gboolean _focus_callback_handler(gpointer d) +{ + GPollFD *data = (GPollFD*)d; + int count; + int tid = 0; + int focus_index = 0; + focus_cb_data_lib cb_data; + debug_log(">>> focus_callback_handler()..ID of this thread(%u)\n", (unsigned int)pthread_self()); + + memset(&cb_data, 0, sizeof(focus_cb_data_lib)); + + if (!data) { + debug_error("GPollFd is null"); + return FALSE; + } + if (data->revents & (POLLIN | POLLPRI)) { + int changed_state = -1; + + count = read(data->fd, &cb_data, sizeof(cb_data)); + if (count < 0){ + char str_error[256]; + strerror_r(errno, str_error, sizeof(str_error)); + debug_error("GpollFD read fail, errno=%d(%s)",errno, str_error); + return FALSE; + } + changed_state = cb_data.state; + focus_index = _focus_find_index_by_handle(cb_data.handle); + if (focus_index == -1) { + debug_error("Could not find index"); + return FALSE; + } + + g_mutex_lock(&g_focus_sound_handle[focus_index].focus_lock); + + tid = g_focus_sound_handle[focus_index].focus_tid; + + if (changed_state != -1) { + debug_msg("Got and start CB : TID(%d), handle(%d), type(%d), state(%d,(DEACTIVATED(0)/ACTIVATED(1)), trigger(%s)", tid, cb_data.handle, cb_data.type, cb_data.state, cb_data.stream_type); + if (g_focus_sound_handle[focus_index].focus_callback == NULL) { + debug_error("callback is null.."); + g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock); + return FALSE; + } + debug_msg("[CALLBACK(%p) START]",g_focus_sound_handle[focus_index].focus_callback); + (g_focus_sound_handle[focus_index].focus_callback)(cb_data.handle, cb_data.type, cb_data.state, cb_data.stream_type, cb_data.option, cb_data.ext_info, g_focus_sound_handle[focus_index].user_data); + debug_msg("[CALLBACK END]"); + if (g_focus_session_interrupt_info.user_cb) { + debug_msg("sending session interrupt callback(%p)", g_focus_session_interrupt_info.user_cb); + (g_focus_session_interrupt_info.user_cb)(cb_data.state, cb_data.stream_type, false, g_focus_session_interrupt_info.user_data); + } + } +#ifdef CONFIG_ENABLE_RETCB + { + int rett = 0; + int tmpfd = -1; + unsigned int buf = 0; + char *filename2 = g_strdup_printf("/tmp/FOCUS.%d.%dr", g_focus_sound_handle[focus_index].focus_tid, cb_data.handle); + tmpfd = open(filename2, O_WRONLY | O_NONBLOCK); + if (tmpfd < 0) { + char str_error[256]; + strerror_r(errno, str_error, sizeof(str_error)); + debug_warning("[RETCB][Failed(May Server Close First)]tid(%d) fd(%d) %s errno=%d(%s)\n", tid, tmpfd, filename2, errno, str_error); + g_free(filename2); + g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock); + return FALSE; + } + /* buf contains data as below, + * |<--12bits--><--4bits (reacquisition)--><--16bits (handle)-->| */ + buf = (unsigned int)((0x0000ffff & cb_data.handle) | (g_focus_sound_handle[focus_index].auto_reacquire << 16)); + rett = write(tmpfd, &buf, sizeof(buf)); + close(tmpfd); + g_free(filename2); + debug_msg("[RETCB] tid(%d) finishing CB (write=%d)\n", tid, rett); + } +#endif + } + + g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock); + + return TRUE; +} + +static gboolean _focus_watch_callback_handler(gpointer d) +{ + GPollFD *data = (GPollFD*)d; + int count; + int tid = 0; + int focus_index = 0; + focus_cb_data_lib cb_data; + + debug_fenter(); + + memset(&cb_data, 0, sizeof(focus_cb_data_lib)); + + if (!data) { + debug_error("GPollFd is null"); + return FALSE; + } + if (data->revents & (POLLIN | POLLPRI)) { + count = read(data->fd, &cb_data, sizeof(cb_data)); + if (count < 0){ + char str_error[256]; + strerror_r(errno, str_error, sizeof(str_error)); + debug_error("GpollFD read fail, errno=%d(%s)",errno, str_error); + return FALSE; + } + + focus_index = _focus_watch_find_index_by_handle(cb_data.handle); + if (focus_index == -1) { + debug_error("Could not find index"); + return FALSE; + } + + if (!g_focus_sound_handle[focus_index].is_used) { + debug_warning("unsetting watch calllback has been already requested"); + goto SKIP_CB_AND_RET; + } + + debug_msg("lock focus_lock = %p", &g_focus_sound_handle[focus_index].focus_lock); + g_mutex_lock(&g_focus_sound_handle[focus_index].focus_lock); + + tid = g_focus_sound_handle[focus_index].focus_tid; + + debug_msg("Got and start CB : TID(%d), handle(%d), type(%d), state(%d,(DEACTIVATED(0)/ACTIVATED(1)), trigger(%s)", tid, cb_data.handle, cb_data.type, cb_data.state, cb_data.stream_type); + + if (g_focus_sound_handle[focus_index].watch_callback == NULL) { + debug_msg("callback is null.."); + } else { + debug_msg("[CALLBACK(%p) START]",g_focus_sound_handle[focus_index].watch_callback); + (g_focus_sound_handle[focus_index].watch_callback)(cb_data.handle, cb_data.type, cb_data.state, cb_data.stream_type, cb_data.ext_info, g_focus_sound_handle[focus_index].user_data); + debug_msg("[CALLBACK END]"); + if (g_focus_session_interrupt_info.user_cb) { + debug_msg("sending session interrupt callback(%p)", g_focus_session_interrupt_info.user_cb); + (g_focus_session_interrupt_info.user_cb)(cb_data.state, cb_data.stream_type, true, g_focus_session_interrupt_info.user_data); + } + } + +SKIP_CB_AND_RET: +#ifdef CONFIG_ENABLE_RETCB + { + int rett = 0; + int tmpfd = -1; + int buf = -1; + char *filename2 = g_strdup_printf("/tmp/FOCUS.%d.%d.wchr", g_focus_sound_handle[focus_index].focus_tid, cb_data.handle); + tmpfd = open(filename2, O_WRONLY | O_NONBLOCK); + if (tmpfd < 0) { + char str_error[256]; + strerror_r(errno, str_error, sizeof(str_error)); + debug_warning("[RETCB][Failed(May Server Close First)]tid(%d) fd(%d) %s errno=%d(%s)\n", tid, tmpfd, filename2, errno, str_error); + g_free(filename2); + g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock); + return FALSE; + } + buf = cb_data.handle; + rett = write(tmpfd, &buf, sizeof(buf)); + close(tmpfd); + g_free(filename2); + debug_msg("[RETCB] tid(%d) finishing CB (write=%d)\n", tid, rett); + } +#endif + } + + if (g_focus_sound_handle[focus_index].is_used) { + debug_msg("unlock focus_lock = %p", &g_focus_sound_handle[focus_index].focus_lock); + g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock); + } + + debug_fleave(); + + return TRUE; +} + +static void _focus_open_callback(int index, bool is_for_watching) +{ + mode_t pre_mask; + char *filename; + + debug_fenter(); + + if (is_for_watching) { + filename = g_strdup_printf("/tmp/FOCUS.%d.%d.wch", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle); + } else { + filename = g_strdup_printf("/tmp/FOCUS.%d.%d", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle); + } + pre_mask = umask(0); + if (mknod(filename, S_IFIFO|0666, 0)) { + debug_error("mknod() failure, errno(%d)", errno); + } + umask(pre_mask); + g_focus_sound_handle[index].focus_fd = open(filename, O_RDWR|O_NONBLOCK); + if (g_focus_sound_handle[index].focus_fd == -1) { + debug_error("Open fail : index(%d), file open error(%d)", index, errno); + } else { + debug_log("Open success : index(%d), filename(%s), fd(%d)", index, filename, g_focus_sound_handle[index].focus_fd); + } + g_free(filename); + filename = NULL; + +#ifdef CONFIG_ENABLE_RETCB + char *filename2; + + if (is_for_watching) { + filename2 = g_strdup_printf("/tmp/FOCUS.%d.%d.wchr", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle); + } else { + filename2 = g_strdup_printf("/tmp/FOCUS.%d.%dr", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle); + } + pre_mask = umask(0); + if (mknod(filename2, S_IFIFO | 0666, 0)) { + debug_error("mknod() failure, errno(%d)", errno); + } + umask(pre_mask); + g_free(filename2); + filename2 = NULL; +#endif + debug_fleave(); + +} + +void _focus_close_callback(int index, bool is_for_watching) +{ + char *filename = NULL; + + debug_fenter(); + + if (g_focus_sound_handle[index].focus_fd < 0) { + debug_error("Close fail : index(%d)", index); + } else { + close(g_focus_sound_handle[index].focus_fd); + debug_log("Close Success : index(%d)", index); + } + + if (is_for_watching) { + filename = g_strdup_printf("/tmp/FOCUS.%d.%d.wch", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle); + } else { + filename = g_strdup_printf("/tmp/FOCUS.%d.%d", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle); + } + if (remove(filename)) { + debug_warning("remove(%s) failure (focus_server probably removed it in advance), errno(%d)", filename, errno); + } + g_free(filename); + filename = NULL; + +#ifdef CONFIG_ENABLE_RETCB + char *filename2; + + if (is_for_watching) { + filename2 = g_strdup_printf("/tmp/FOCUS.%d.%d.wchr", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle); + } else { + filename2 = g_strdup_printf("/tmp/FOCUS.%d.%dr", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle); + } + if (remove(filename2)) { + debug_warning("remove(%s) failure (focus_server probably removed it in advance), errno(%d)", filename2, errno); + } + g_free(filename2); + filename2 = NULL; + + debug_fleave(); +#endif + +} + +static bool _focus_add_sound_callback(int index, int fd, gushort events, focus_gLoopPollHandler_t p_gloop_poll_handler ) +{ + GSource* g_src = NULL; + GSourceFuncs *g_src_funcs = NULL; /* handler function */ + guint g_src_id = 0; + GPollFD *g_poll_fd = NULL; /* file descriptor */ + + debug_fenter(); + + g_mutex_init(&g_focus_sound_handle[index].focus_lock); + + /* 1. make GSource Object */ + g_src_funcs = (GSourceFuncs *)g_malloc(sizeof(GSourceFuncs)); + if (!g_src_funcs) { + debug_error("failed to g_malloc for g_src_funcs"); + goto ERROR; + } + + g_src_funcs->prepare = _focus_fd_prepare; + g_src_funcs->check = _focus_fd_check; + g_src_funcs->dispatch = _focus_fd_dispatch; + g_src_funcs->finalize = NULL; + g_src = g_source_new(g_src_funcs, sizeof(GSource)); + if (!g_src) { + debug_error("failed to g_source_new for g_src"); + goto ERROR; + } + + /* 2. add file description which used in g_loop() */ + g_poll_fd = (GPollFD *)g_malloc(sizeof(GPollFD)); + if (!g_poll_fd) { + debug_error("failed to g_malloc for g_poll_fd"); + goto ERROR; + } + g_poll_fd->fd = fd; + g_poll_fd->events = events; + + /* 3. combine g_source object and file descriptor */ + g_source_add_poll(g_src, g_poll_fd); + g_src_id = g_source_attach(g_src, g_main_loop_get_context(g_focus_loop)); + if (!g_src_id) { + debug_error("failed to attach the source to context"); + goto ERROR; + } + + /* 4. set callback */ + g_source_set_callback(g_src, p_gloop_poll_handler,(gpointer)g_poll_fd, NULL); + + debug_log("g_malloc : g_src_funcs(%p), g_poll_fd(%p)", g_src_funcs, g_poll_fd); + + /* 5. store to global handle */ + g_focus_sound_handle[index].focus_src = g_src; + g_focus_sound_handle[index].g_src_funcs = g_src_funcs; + g_focus_sound_handle[index].g_poll_fd = g_poll_fd; + + debug_fleave(); + return true; + +ERROR: + if (g_src_funcs) + g_free(g_src_funcs); + if (g_poll_fd) + g_free(g_poll_fd); + if (g_src) + g_source_unref(g_src); + + return false; +} + +static bool _focus_remove_sound_callback(int index, gushort events) +{ + bool ret = true; + + debug_fenter(); + + g_mutex_clear(&g_focus_sound_handle[index].focus_lock); + + GSourceFuncs *g_src_funcs = g_focus_sound_handle[index].g_src_funcs; + GPollFD *g_poll_fd = g_focus_sound_handle[index].g_poll_fd; /* store file descriptor */ + if (!g_poll_fd) { + debug_error("g_poll_fd is null.."); + ret = false; + goto RELEASE; + } + g_poll_fd->fd = g_focus_sound_handle[index].focus_fd; + g_poll_fd->events = events; + + if (!g_focus_sound_handle[index].focus_src) { + debug_error("g_focus_sound_handle[%d].focus_src is null..", index); + ret = false; + goto RELEASE; + } + g_source_remove_poll(g_focus_sound_handle[index].focus_src, g_poll_fd); + debug_log("g_source_remove_poll : fd(%d), event(%x)", g_poll_fd->fd, g_poll_fd->events); + +RELEASE: + if (g_focus_sound_handle[index].focus_src) + g_source_destroy(g_focus_sound_handle[index].focus_src); + + debug_log("g_free : g_src_funcs(%x), g_poll_fd(%x)", g_src_funcs, g_poll_fd); + if (g_src_funcs) { + g_free(g_src_funcs); + g_src_funcs = NULL; + } + if (g_poll_fd) { + g_free(g_poll_fd); + g_poll_fd = NULL; + } + + g_focus_sound_handle[index].g_src_funcs = NULL; + g_focus_sound_handle[index].g_poll_fd = NULL; + g_focus_sound_handle[index].focus_src = NULL; + g_focus_sound_handle[index].focus_callback = NULL; + g_focus_sound_handle[index].watch_callback = NULL; + + debug_fleave(); + return ret; +} + + +static void _focus_add_callback(int index, bool is_for_watching) +{ + debug_fenter(); + if (!is_for_watching) { + if (!_focus_add_sound_callback(index, g_focus_sound_handle[index].focus_fd, (gushort)POLLIN | POLLPRI, _focus_callback_handler)) { + debug_error("failed to _focus_add_sound_callback()"); + //return false; + } + } else { // need to check if it's necessary + if (!_focus_add_sound_callback(index, g_focus_sound_handle[index].focus_fd, (gushort)POLLIN | POLLPRI, _focus_watch_callback_handler)) { + debug_error("failed to _focus_add_sound_callback()"); + //return false; + } + } + debug_fleave(); +} + +static void _focus_remove_callback(int index) +{ + debug_fenter(); + if (!_focus_remove_sound_callback(index, (gushort)POLLIN | POLLPRI)) { + debug_error("failed to __focus_remove_sound_callback()"); + //return false; + } + debug_fleave(); +} + +static void _focus_init_callback(int index, bool is_for_watching) +{ + debug_fenter(); + _focus_open_callback(index, is_for_watching); + _focus_add_callback(index, is_for_watching); + debug_fleave(); +} + +static void _focus_destroy_callback(int index, bool is_for_watching) +{ + debug_fenter(); + _focus_remove_callback(index); + _focus_close_callback(index, is_for_watching); + debug_fleave(); +} + +int mm_sound_client_get_unique_id(int *id) +{ + int ret = MM_ERROR_NONE; + + debug_fenter(); + + if (!id) + ret = MM_ERROR_INVALID_ARGUMENT; + else + ret = mm_sound_proxy_get_unique_id(id); + + debug_fleave(); + + return ret; +} + +int mm_sound_client_is_focus_cb_thread(GThread *mine, bool *result) +{ + int ret = MM_ERROR_NONE; + + if (!mine || !result) + ret = MM_ERROR_INVALID_ARGUMENT; + else { + if (mine == g_focus_thread) + *result = true; + else + *result = false; + } + + return ret; +} + +int mm_sound_client_register_focus(int id, int pid, const char *stream_type, mm_sound_focus_changed_cb callback, bool is_for_session, void* user_data) +{ + int ret = MM_ERROR_NONE; + int instance; + int index = 0; + + debug_fenter(); + MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL); + + instance = pid; + + for (index = 0; index < FOCUS_HANDLE_MAX - 1; index++) { + if (g_focus_sound_handle[index].is_used == false) { + g_focus_sound_handle[index].is_used = true; + break; + } + } + + g_focus_sound_handle[index].focus_tid = instance; + g_focus_sound_handle[index].handle = id; + g_focus_sound_handle[index].focus_callback = callback; + g_focus_sound_handle[index].user_data = user_data; + g_focus_sound_handle[index].is_for_session = is_for_session; + g_focus_sound_handle[index].auto_reacquire = true; + + ret = mm_sound_proxy_register_focus(id, pid, stream_type, callback, is_for_session, user_data); + + if (ret == MM_ERROR_NONE) { + debug_msg("[Client] Success to register focus\n"); + g_need_emergent_exit = TRUE; + if (!g_focus_thread) { + GMainContext* focus_context = g_main_context_new (); + g_focus_loop = g_main_loop_new (focus_context, FALSE); + g_main_context_unref(focus_context); + if (g_focus_loop == NULL) { + debug_error("could not create mainloop.."); + ret = MM_ERROR_SOUND_INTERNAL; + goto cleanup; + } + + g_focus_thread = g_thread_new("focus-cb-thread", _focus_thread_func, NULL); + if (g_focus_thread == NULL) { + debug_error("could not create thread.."); + g_main_loop_unref(g_focus_loop); + ret = MM_ERROR_SOUND_INTERNAL; + goto cleanup; + } + } else { + debug_warning("focus thread(%p) with mainloop(%p) exists, skip thread creation", + g_focus_thread, g_focus_loop); + } + } else { + debug_error("[Client] Error occurred : 0x%x \n",ret); + goto cleanup; + } + + _focus_init_callback(index, false); + +cleanup: + + if (ret) { + g_focus_sound_handle[index].is_used = false; + } + + MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex); + debug_fleave(); + + return ret; +} + +int mm_sound_client_unregister_focus(int id) +{ + int ret = MM_ERROR_NONE; + int instance; + int index = -1; + + debug_fenter(); + MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL); + + index = _focus_find_index_by_handle(id); + if (index == -1) { + debug_error("Could not find index"); + ret = MM_ERROR_INVALID_ARGUMENT; + goto cleanup; + } + instance = g_focus_sound_handle[index].focus_tid; + + if (!g_mutex_trylock(&g_focus_sound_handle[index].focus_lock)) { + debug_warning("maybe focus_callback is being called, try one more time.."); + usleep(2500000); // 2.5 sec + if (g_mutex_trylock(&g_focus_sound_handle[index].focus_lock)) { + debug_msg("finally got focus_lock"); + } + } + + ret = mm_sound_proxy_unregister_focus(instance, id, g_focus_sound_handle[index].is_for_session); + + if (ret == MM_ERROR_NONE) + debug_msg("[Client] Success to unregister focus\n"); + else + debug_error("[Client] Error occurred : 0x%x \n",ret); + + g_mutex_unlock(&g_focus_sound_handle[index].focus_lock); + + _focus_destroy_callback(index, false); + g_focus_sound_handle[index].focus_fd = 0; + g_focus_sound_handle[index].focus_tid = 0; + g_focus_sound_handle[index].handle = 0; + g_focus_sound_handle[index].is_used = false; +cleanup: + MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex); + debug_fleave(); + return ret; +} + +int mm_sound_client_set_focus_reacquisition(int id, bool reacquisition) +{ + int ret = MM_ERROR_NONE; + int instance; + int index = -1; + bool result; + + debug_fenter(); + MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL); + + index = _focus_find_index_by_handle(id); + if (index == -1) { + debug_error("Could not find index"); + ret = MM_ERROR_INVALID_ARGUMENT; + goto cleanup; + } + instance = g_focus_sound_handle[index].focus_tid; + + ret = mm_sound_client_is_focus_cb_thread(g_thread_self(), &result); + if (ret) { + debug_error("[Client] mm_sound_client_is_focus_cb_thread failed"); + goto cleanup; + } else if (!result) { + ret = mm_sound_proxy_set_foucs_reacquisition(instance, id, reacquisition); + if (ret == MM_ERROR_NONE) { + debug_msg("[Client] Success to set focus reacquisition to [%d]\n", reacquisition); + } else { + debug_error("[Client] Error occurred : 0x%x \n",ret); + goto cleanup; + } + } else { + debug_warning("[Client] Inside the focus cb thread, set focus reacquisition to [%d]\n", reacquisition); + } + + g_focus_sound_handle[index].auto_reacquire = reacquisition; + +cleanup: + MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex); + debug_fleave(); + return ret; +} + +int mm_sound_client_get_focus_reacquisition(int id, bool *reacquisition) +{ + int ret = MM_ERROR_NONE; + int index = -1; + + debug_fenter(); + + if (!reacquisition) { + debug_error("Invalid parameter"); + return MM_ERROR_INVALID_ARGUMENT; + } + + MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL); + + index = _focus_find_index_by_handle(id); + if (index == -1) { + debug_error("Could not find index"); + ret = MM_ERROR_INVALID_ARGUMENT; + goto cleanup; + } + + *reacquisition = g_focus_sound_handle[index].auto_reacquire; + +cleanup: + MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex); + debug_fleave(); + return ret; +} + +int mm_sound_client_get_acquired_focus_stream_type(int focus_type, char **stream_type, int *option, char **ext_info) +{ + int ret = MM_ERROR_NONE; + char *ext_str = NULL; + + debug_fenter(); + + ret = mm_sound_proxy_get_acquired_focus_stream_type(focus_type, stream_type, option, &ext_str); + if (ret == MM_ERROR_NONE) { + debug_msg("[Client] Success to get stream type of acquired focus, stream_type(%s), ext_info(%s)\n", *stream_type, ext_str); + *ext_info = strdup(ext_str); + g_free(ext_str); + } else { + debug_error("[Client] Error occurred : 0x%x \n",ret); + } + + debug_fleave(); + return ret; +} + +int mm_sound_client_acquire_focus(int id, mm_sound_focus_type_e type, int option, const char *ext_info) +{ + int ret = MM_ERROR_NONE; + int instance; + int index = -1; + + debug_fenter(); + MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL); + + index = _focus_find_index_by_handle(id); + if (index == -1) { + debug_error("Could not find index"); + ret = MM_ERROR_INVALID_ARGUMENT; + goto cleanup; + } + instance = g_focus_sound_handle[index].focus_tid; + + ret = mm_sound_proxy_acquire_focus(instance, id, type, option, ext_info, g_focus_sound_handle[index].is_for_session); + if (ret == MM_ERROR_NONE) + debug_msg("[Client] Success to acquire focus\n"); + else + debug_error("[Client] Error occurred : 0x%x \n",ret); + +cleanup: + MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex); + debug_fleave(); + return ret; +} + +int mm_sound_client_release_focus(int id, mm_sound_focus_type_e type, int option, const char *ext_info) +{ + int ret = MM_ERROR_NONE; + int instance; + int index = -1; + + debug_fenter(); + MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL); + + index = _focus_find_index_by_handle(id); + if (index == -1) { + debug_error("Could not find index"); + ret = MM_ERROR_INVALID_ARGUMENT; + goto cleanup; + } + instance = g_focus_sound_handle[index].focus_tid; + + ret = mm_sound_proxy_release_focus(instance, id, type, option, ext_info, g_focus_sound_handle[index].is_for_session); + if (ret == MM_ERROR_NONE) + debug_msg("[Client] Success to release focus\n"); + else + debug_error("[Client] Error occurred : 0x%x \n",ret); + +cleanup: + MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex); + debug_fleave(); + return ret; +} + +int mm_sound_client_set_focus_watch_callback(int pid, mm_sound_focus_type_e focus_type, mm_sound_focus_changed_watch_cb callback, bool is_for_session, void* user_data, int *id) +{ + int ret = MM_ERROR_NONE; + int instance; + int index = 0; + + debug_fenter(); + + if (!id) + return MM_ERROR_INVALID_ARGUMENT; + + //pthread_mutex_lock(&g_thread_mutex2); + + instance = pid; + + ret = mm_sound_proxy_get_unique_id(id); + if (ret) + return ret; + + MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL); + + for (index = 0; index < FOCUS_HANDLE_MAX - 1; index++) { + if (g_focus_sound_handle[index].is_used == false) { + g_focus_sound_handle[index].is_used = true; + break; + } + } + + g_focus_sound_handle[index].focus_tid = instance; + g_focus_sound_handle[index].handle = *id; + g_focus_sound_handle[index].watch_callback = callback; + g_focus_sound_handle[index].user_data = user_data; + g_focus_sound_handle[index].is_for_session = is_for_session; + + ret = mm_sound_proxy_set_focus_watch_callback(pid, g_focus_sound_handle[index].handle, focus_type, callback, is_for_session, user_data); + + if (ret == MM_ERROR_NONE) { + debug_msg("[Client] Success to watch focus"); + g_need_emergent_exit = TRUE; + if (!g_focus_thread) { + GMainContext* focus_context = g_main_context_new (); + g_focus_loop = g_main_loop_new (focus_context, FALSE); + g_main_context_unref(focus_context); + if (g_focus_loop == NULL) { + debug_error("could not create mainloop.."); + ret = MM_ERROR_SOUND_INTERNAL; + goto cleanup; + } + + g_focus_thread = g_thread_new("focus-cb-thread", _focus_thread_func, NULL); + if (g_focus_thread == NULL) { + debug_error ("could not create thread.."); + g_main_loop_unref(g_focus_loop); + ret = MM_ERROR_SOUND_INTERNAL; + goto cleanup; + } + } else { + debug_warning("focus thread(%p) with mainloop(%p) exists, skip thread creation", + g_focus_thread, g_focus_loop); + } + } else { + debug_error("[Client] Error occurred : 0x%x",ret); + goto cleanup; + } + + _focus_init_callback(index, true); + +cleanup: + + if (ret) { + g_focus_sound_handle[index].is_used = false; + } + + MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex); + debug_fleave(); + return ret; +} + +int mm_sound_client_unset_focus_watch_callback(int id) +{ + int ret = MM_ERROR_NONE; + int index = -1; + debug_fenter(); + MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL); + + index = _focus_watch_find_index_by_handle(id); + if (index == -1) { + debug_error("Could not find index"); + ret = MM_ERROR_INVALID_ARGUMENT; + goto cleanup; + } + + g_mutex_lock(&g_focus_sound_handle[index].focus_lock); + + g_focus_sound_handle[index].is_used = false; + + ret = mm_sound_proxy_unset_focus_watch_callback(g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle, g_focus_sound_handle[index].is_for_session); + + if (ret == MM_ERROR_NONE) + debug_msg("[Client] Success to unwatch focus\n"); + else + debug_error("[Client] Error occurred : 0x%x \n",ret); + + + g_mutex_unlock(&g_focus_sound_handle[index].focus_lock); + _focus_destroy_callback(index, true); + g_focus_sound_handle[index].focus_fd = 0; + g_focus_sound_handle[index].focus_tid = 0; + g_focus_sound_handle[index].handle = 0; +cleanup: + MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex); debug_fleave(); return ret; } #endif -int mm_sound_client_add_test_callback(mm_sound_test_cb func, void* user_data) +int mm_sound_client_add_test_callback(mm_sound_test_cb func, void* user_data, unsigned int *subs_id) { int ret = MM_ERROR_NONE; debug_fenter(); - ret = mm_sound_client_dbus_add_test_callback(func, user_data); + ret = mm_sound_proxy_add_test_callback(func, user_data, g_free, subs_id); debug_fleave(); return ret; } -int mm_sound_client_remove_test_callback(void) +int mm_sound_client_remove_test_callback(unsigned int subs_id) { int ret = MM_ERROR_NONE; debug_fenter(); - ret = mm_sound_client_dbus_remove_test_callback(); + ret = mm_sound_proxy_remove_test_callback(subs_id); debug_fleave(); return ret; @@ -743,7 +1984,7 @@ int mm_sound_client_test(int a, int b, int* getv) debug_fenter(); - ret = mm_sound_client_dbus_test(a, b, getv); + ret = mm_sound_proxy_test(a, b, getv); debug_log("%d * %d -> result : %d", a, b, *getv); debug_fleave();