Revise focus callback context 32/116432/3 accepted/tizen/3.0/common/20170302.075649 accepted/tizen/3.0/ivi/20170302.034033 accepted/tizen/3.0/mobile/20170302.033906 accepted/tizen/3.0/tv/20170302.033952 accepted/tizen/3.0/wearable/20170302.034012 submit/tizen_3.0/20170228.000412
authorSangchul Lee <sc11.lee@samsung.com>
Fri, 24 Feb 2017 08:39:21 +0000 (17:39 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Mon, 27 Feb 2017 07:40:48 +0000 (16:40 +0900)
Make new focus callback context for each focus handle

[Version] 0.10.95
[Profile] Common
[Issue Type] Enhancement

Change-Id: I4097198a18e0c0cab69e41a7c24bc227ee8fd21a
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
mm_sound.c
mm_sound_client.c
mm_sound_focus.c
packaging/libmm-sound.spec

index f3b5825..bc5d325 100644 (file)
@@ -691,8 +691,6 @@ error:
 EXPORT_API
 void mm_sound_unsubscribe_signal(unsigned int subscribe_id)
 {
-       subscribe_cb_t *subscribe_cb = NULL;
-
        debug_fenter();
 
        MMSOUND_ENTER_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
index 1180060..b629d33 100644 (file)
@@ -85,12 +85,14 @@ typedef struct {
        int focus_tid;
        int handle;
        int focus_fd;
-       GSourceFuncsg_src_funcs;
-       GPollFDg_poll_fd;
-       GSource* focus_src;
+       GSourceFuncs *g_src_funcs;
+       GPollFD *g_poll_fd;
+       GSource *g_src;
        bool is_used;
        bool auto_reacquire;
        GMutex focus_lock;
+       GThread *focus_cb_thread;
+       GMainLoop *focus_loop;
        mm_sound_focus_changed_cb focus_callback;
        mm_sound_focus_changed_watch_cb watch_callback;
        void* user_data;
@@ -115,8 +117,6 @@ typedef struct {
 
 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;
@@ -243,23 +243,12 @@ int mm_sound_client_finalize(void)
 
        ret = mm_sound_proxy_finalize();
 
-
 #ifdef USE_FOCUS
-
-       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;
-       }
-
        if (g_idle_event_src > 0) {
                MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_event_mutex, MM_ERROR_SOUND_INTERNAL);
                g_source_remove(g_idle_event_src);
                MMSOUND_LEAVE_CRITICAL_SECTION(&g_event_mutex);
        }
-
 #endif
 
        debug_fleave();
@@ -1056,11 +1045,13 @@ int mm_sound_client_unset_session_interrupt_callback(void)
 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);
+       GMainLoop *focus_loop = (GMainLoop*)data;
+
+       debug_warning(">>> thread func : thread id(%u), mainloop[%p]", thread_id, focus_loop);
+       if (focus_loop)
+               g_main_loop_run(focus_loop);
+       debug_warning("<<< quit thread func : thread id(%u), mainloop[%p]", thread_id, focus_loop);
 
-       debug_warning("<<< quit thread func..(%u), mainloop(%p)", thread_id, g_focus_loop);
        return NULL;
 }
 
@@ -1135,7 +1126,7 @@ static gboolean _focus_callback_handler(gpointer d)
        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());
+       debug_log(">>> focus_callback_handler()..this thread id(%u)\n", (unsigned int)pthread_self());
 
        memset(&cb_data, 0, sizeof(focus_cb_data_lib));
 
@@ -1399,7 +1390,7 @@ void _focus_close_callback(int index, bool is_for_watching)
 
 }
 
-static bool _focus_add_sound_callback(int index, int fd, gushort events, focus_gLoopPollHandler_t p_gloop_poll_handler )
+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 */
@@ -1438,7 +1429,7 @@ static bool _focus_add_sound_callback(int index, int fd, gushort events, focus_g
 
        /* 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));
+       g_src_id = g_source_attach(g_src, g_main_loop_get_context(g_focus_sound_handle[index].focus_loop));
        if (!g_src_id) {
                debug_error("failed to attach the source to context");
                goto ERROR;
@@ -1450,7 +1441,7 @@ static bool _focus_add_sound_callback(int index, int fd, gushort events, focus_g
        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 = g_src;
        g_focus_sound_handle[index].g_src_funcs = g_src_funcs;
        g_focus_sound_handle[index].g_poll_fd = g_poll_fd;
 
@@ -1480,20 +1471,20 @@ static bool _focus_remove_sound_callback(int index)
 
        h = &g_focus_sound_handle[index];
 
-       if (h->focus_src && h->g_poll_fd) {
+       if (h->g_src && h->g_poll_fd) {
                debug_log("g_source_remove_poll : fd(%d), event(0x%x)",
                                h->g_poll_fd->fd, h->g_poll_fd->events);
-               g_source_remove_poll(h->focus_src, h->g_poll_fd);
+               g_source_remove_poll(h->g_src, h->g_poll_fd);
        } else {
-               debug_error("[%d] focus_src[%p], g_poll_fd[%p]",
-                                       index, h->focus_src, h->g_poll_fd);
+               debug_error("[%d] g_src[%p], g_poll_fd[%p]",
+                                       index, h->g_src, h->g_poll_fd);
                ret = false;
        }
 
-       if (h->focus_src) {
-               g_source_destroy(h->focus_src);
-               g_source_unref(h->focus_src);
-               h->focus_src = NULL;
+       if (h->g_src) {
+               g_source_destroy(h->g_src);
+               g_source_unref(h->g_src);
+               h->g_src = NULL;
        }
 
        debug_log("g_free : g_src_funcs(%p), g_poll_fd(%p)",
@@ -1553,7 +1544,7 @@ static void _focus_init_callback(int index, bool is_for_watching)
        debug_fleave();
 }
 
-static void _focus_destroy_callback(int index, bool is_for_watching)
+static void _focus_deinit_callback(int index, bool is_for_watching)
 {
        debug_fenter();
        _focus_remove_callback(index);
@@ -1561,6 +1552,68 @@ static void _focus_destroy_callback(int index, bool is_for_watching)
        debug_fleave();
 }
 
+static int _focus_init_context(int index)
+{
+       GMainContext *focus_context;
+
+       debug_fenter();
+
+       if (index < 0 || index >= FOCUS_HANDLE_MAX) {
+               debug_error("index(%d) is not valid", index);
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       focus_context = g_main_context_new();
+       g_focus_sound_handle[index].focus_loop = g_main_loop_new(focus_context, FALSE);
+       g_main_context_unref(focus_context);
+       if (g_focus_sound_handle[index].focus_loop == NULL) {
+               debug_error("could not create mainloop..");
+               return MM_ERROR_SOUND_INTERNAL;
+       }
+
+       g_focus_sound_handle[index].focus_cb_thread = g_thread_new("focus-cb-thread",
+                                                                       _focus_thread_func,
+                                                                       g_focus_sound_handle[index].focus_loop);
+       if (g_focus_sound_handle[index].focus_cb_thread == NULL) {
+               debug_error("could not create thread..");
+               g_main_loop_unref(g_focus_sound_handle[index].focus_loop);
+               return MM_ERROR_SOUND_INTERNAL;
+       }
+
+       debug_warning("focus cb thread[%p] with mainloop[%p] is created for index(%d)",
+                               g_focus_sound_handle[index].focus_cb_thread, g_focus_sound_handle[index].focus_loop, index);
+
+       debug_fleave();
+
+       return MM_ERROR_NONE;
+}
+
+static void _focus_deinit_context(int index)
+{
+       debug_fenter();
+
+       if (index < 0 || index >= FOCUS_HANDLE_MAX) {
+               debug_error("index(%d) is not valid", index);
+               return;
+       }
+
+       if (!g_focus_sound_handle[index].focus_loop || !g_focus_sound_handle[index].focus_cb_thread) {
+               debug_error("focus_loop[%p] or focus_cb_thread[%p] is null",
+                               g_focus_sound_handle[index].focus_loop, g_focus_sound_handle[index].focus_cb_thread);
+               return;
+       }
+
+       g_main_loop_quit(g_focus_sound_handle[index].focus_loop);
+       g_thread_join(g_focus_sound_handle[index].focus_cb_thread);
+       debug_warning("after thread join, thread[%p], mainloop[%p] for index(%d)",
+                       g_focus_sound_handle[index].focus_cb_thread, g_focus_sound_handle[index].focus_loop, index);
+       g_main_loop_unref(g_focus_sound_handle[index].focus_loop);
+       g_focus_sound_handle[index].focus_loop = NULL;
+       g_focus_sound_handle[index].focus_cb_thread = NULL;
+
+       debug_fleave();
+}
+
 int mm_sound_client_get_unique_id(int *id)
 {
        int ret = MM_ERROR_NONE;
@@ -1580,14 +1633,20 @@ int mm_sound_client_get_unique_id(int *id)
 int mm_sound_client_is_focus_cb_thread(GThread *mine, bool *result)
 {
        int ret = MM_ERROR_NONE;
+       int i = 0;
 
        if (!mine || !result)
                ret = MM_ERROR_INVALID_ARGUMENT;
        else {
-               if (mine == g_focus_thread)
-                       *result = true;
-               else
-                       *result = false;
+               *result = false;
+               for (i = 0; i < FOCUS_HANDLE_MAX; i++) {
+                       if (!g_focus_sound_handle[i].is_used)
+                               continue;
+                       if (g_focus_sound_handle[i].focus_cb_thread == mine) {
+                               *result = true;
+                               break;
+                       }
+               }
        }
 
        return ret;
@@ -1619,30 +1678,12 @@ int mm_sound_client_register_focus(int id, int pid, const char *stream_type, mm_
        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);
+               if (_focus_init_context(index)) {
+                       ret = MM_ERROR_SOUND_INTERNAL;
+                       goto cleanup;
                }
        } else {
                debug_error("[Client] Error occurred : 0x%x \n",ret);
@@ -1652,7 +1693,6 @@ int mm_sound_client_register_focus(int id, int pid, const char *stream_type, mm_
        _focus_init_callback(index, false);
 
 cleanup:
-
        if (ret) {
                g_focus_sound_handle[index].is_used = false;
        }
@@ -1689,7 +1729,6 @@ int mm_sound_client_unregister_focus(int id)
        }
 
        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
@@ -1697,11 +1736,13 @@ int mm_sound_client_unregister_focus(int id)
 
        g_mutex_unlock(&g_focus_sound_handle[index].focus_lock);
 
-       _focus_destroy_callback(index, false);
+       _focus_deinit_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;
+       _focus_deinit_context(index);
+
 cleanup:
        MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
        debug_fleave();
@@ -1896,26 +1937,9 @@ int mm_sound_client_set_focus_watch_callback(int pid, mm_sound_focus_type_e focu
        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);
+               if (_focus_init_context(index)) {
+                       ret = MM_ERROR_SOUND_INTERNAL;
+                       goto cleanup;
                }
        } else {
                debug_error("[Client] Error occurred : 0x%x",ret);
@@ -1925,7 +1949,6 @@ int mm_sound_client_set_focus_watch_callback(int pid, mm_sound_focus_type_e focu
        _focus_init_callback(index, true);
 
 cleanup:
-
        if (ret) {
                g_focus_sound_handle[index].is_used = false;
        }
@@ -1963,10 +1986,12 @@ int mm_sound_client_unset_focus_watch_callback(int id)
 
        g_mutex_unlock(&g_focus_sound_handle[index].focus_lock);
 
-       _focus_destroy_callback(index, true);
+       _focus_deinit_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;
+       _focus_deinit_context(index);
+
 cleanup:
        MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
        debug_fleave();
index 9cec2e9..fd59962 100644 (file)
@@ -34,7 +34,7 @@
        ret = mm_sound_client_is_focus_cb_thread(x_thread, &result); \
        if (ret) \
                return ret; \
-       else if (result) { \
+       if (result) { \
                debug_error("it might be called in the thread of focus callback, it is not allowed\n"); \
                return MM_ERROR_SOUND_INVALID_OPERATION; \
        } \
index 360d790..f582f6e 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-sound
 Summary:    MMSound Package contains client lib and sound_server binary
-Version:    0.10.94
+Version:    0.10.95
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0