Broadcast subscribing and callback handling 55/65455/9 accepted/tizen/common/20160419.143052 accepted/tizen/ivi/20160418.235733 accepted/tizen/mobile/20160418.235720 accepted/tizen/tv/20160418.235728 accepted/tizen/wearable/20160418.235715 submit/tizen/20160418.103710
authorMok Jeongho <jho.mok@samsung.com>
Thu, 3 Mar 2016 01:36:14 +0000 (10:36 +0900)
committerMok Jeongho <jho.mok@samsung.com>
Mon, 18 Apr 2016 08:46:22 +0000 (17:46 +0900)
[Version] Release 0.10.24
[Profile] Common
[Issue Type] Add Feature

Change-Id: I5a877e92f44f771fbc2fb860b307dadf2496a324

common/mm_sound_dbus.c
include/mm_sound_dbus.h
include/mm_sound_intf.h
mm_sound_client.c
mm_sound_proxy.c
packaging/libmm-sound.spec

index ec54d30..a55a56f 100644 (file)
@@ -134,6 +134,12 @@ const mm_sound_dbus_signal_info_t g_events[AUDIO_EVENT_MAX] = {
        },
        [AUDIO_EVENT_EMERGENT_EXIT] = {
                .name = "EmergentExit",
+       },
+       [AUDIO_EVENT_CLIENT_SUBSCRIBED] = {
+               .name = "ClientSubscribed",
+       },
+       [AUDIO_EVENT_CLIENT_HANDLED] = {
+               .name = "ClientSignalHandled",
        }
 };
 
@@ -512,7 +518,6 @@ int mm_sound_dbus_emit_signal(audio_provider_t provider, audio_event_t event, GV
        GDBusConnection *conn;
        GError *err = NULL;
        gboolean dbus_ret;
-       int ret = MM_ERROR_NONE;
 
        if (event < 0 || event >= AUDIO_EVENT_MAX) {
                debug_error ("emit signal failed, invalid argument, event_type(%d)", event);
@@ -521,8 +526,7 @@ int mm_sound_dbus_emit_signal(audio_provider_t provider, audio_event_t event, GV
 
        if (!(conn = _dbus_get_connection(G_BUS_TYPE_SYSTEM))) {
                debug_error("Get Dbus Connection Error");
-               ret = MM_ERROR_SOUND_INTERNAL;
-               goto end;
+               return MM_ERROR_SOUND_INTERNAL;
        }
 
        dbus_ret = g_dbus_connection_emit_signal (conn,
@@ -531,11 +535,42 @@ int mm_sound_dbus_emit_signal(audio_provider_t provider, audio_event_t event, GV
                                                  param, &err);
        if (!dbus_ret) {
                debug_error ("g_dbus_connection_emit_signal() error (%s)", err->message);
-               ret = MM_ERROR_SOUND_INTERNAL;
+               return MM_ERROR_SOUND_INTERNAL;
        }
+       g_dbus_connection_flush_sync(conn, NULL, NULL);
 
-end:
-       debug_msg ("emit signal for [%s]  %s", g_events[event].name, (ret == MM_ERROR_NONE ? "success" : "failed") );
-       return ret;
+       debug_msg ("emit signal for [%s]  success", g_events[event].name);
+       return MM_ERROR_NONE;
 }
 
+EXPORT_API
+int mm_sound_dbus_get_event_name(audio_event_t event, const char **event_name)
+{
+       if (!event_name) {
+               debug_error("Invalid Parameter, event_name NULL");
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+       if (event < 0 || event >= AUDIO_EVENT_MAX) {
+               debug_error("invalid event : %d", event);
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       *event_name = g_events[event].name;
+       return MM_ERROR_NONE;
+}
+
+EXPORT_API
+int mm_sound_dbus_get_method_name(audio_method_t method, const char **method_name)
+{
+       if (!method_name) {
+               debug_error("Invalid Parameter, method_name NULL");
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+       if (method < 0 || method >= AUDIO_METHOD_MAX) {
+               debug_error("invalid method : %d", method);
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       *method_name = g_methods[method].name;
+       return MM_ERROR_NONE;
+}
index 97d10cd..e9ddea2 100644 (file)
@@ -43,6 +43,9 @@ int mm_sound_dbus_signal_subscribe_to(audio_provider_t provider, audio_event_t e
 int mm_sound_dbus_signal_unsubscribe(unsigned subs_id);
 int mm_sound_dbus_emit_signal(audio_provider_t provider, audio_event_t event, GVariant *param);
 
+int mm_sound_dbus_get_event_name(audio_event_t event, const char **event_name);
+int mm_sound_dbus_get_method_name(audio_method_t method, const char **method_name);
+
 typedef void (*dbus_method_handler)(GDBusMethodInvocation *invocation);
 typedef int (*dbus_signal_sender)(GDBusConnection *conn, GVariant *parameter);
 
index 30f6f3d..d84ee94 100644 (file)
@@ -79,6 +79,8 @@ typedef enum audio_event {
        AUDIO_EVENT_FOCUS_CHANGED,
        AUDIO_EVENT_FOCUS_WATCH,
        AUDIO_EVENT_EMERGENT_EXIT,
+       AUDIO_EVENT_CLIENT_SUBSCRIBED, /* Clients send this signal when they subscribed some signal. */
+       AUDIO_EVENT_CLIENT_HANDLED, /* Clients send this siganl when they handled some signal. */
        AUDIO_EVENT_MAX
 } audio_event_t;
 
index 6199d76..b3fe160 100644 (file)
@@ -402,9 +402,12 @@ static void _mm_sound_stop_callback_wrapper_func(int ended_handle, void *userdat
 static void play_end_callback_data_free_func(void *data)
 {
        struct callback_data *cb_data = (struct callback_data*) data;
-       play_sound_end_callback_data_t *end_cb_data = (play_sound_end_callback_data_t*) cb_data->extra_data;
 
-       g_free(end_cb_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)
@@ -670,7 +673,7 @@ int mm_sound_client_add_device_connected_callback(int device_flags, mm_sound_dev
        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)
+       if (ret == MM_ERROR_NONE)
                g_need_emergent_exit = TRUE;
 
        debug_fleave();
index e0b67cc..be9f7f4 100644 (file)
@@ -1,3 +1,4 @@
+#include <stdint.h>
 #include <glib.h>
 
 #include <mm_error.h>
 struct callback_data {
        void *user_cb;
        void *user_data;
-       void *extra_data;
        mm_sound_proxy_userdata_free free_func;
+       uint32_t subs_id;
 };
 
-#define GET_CB_DATA(_cb_data, _func, _userdata, _freefunc, _extradata) \
+#define CB_DATA_NEW(_cb_data, _func, _userdata, _freefunc) \
        do { \
                _cb_data = (struct callback_data*) g_malloc0(sizeof(struct callback_data)); \
                _cb_data->user_cb = _func; \
                _cb_data->user_data = _userdata; \
                _cb_data->free_func = _freefunc; \
-               _cb_data->extra_data = _extradata; \
+               _cb_data->subs_id = 0; \
        } while (0)
 
+/* subscribe is true when add callback,
+ * false when remove callback */
+static int _notify_subscription(audio_event_t event, uint32_t subs_id, gboolean subscribe)
+{
+       int ret = MM_ERROR_NONE;
+       GVariant* params = NULL;
+       const char *event_name = NULL;
+
+       debug_fenter();
+
+       if ((ret = mm_sound_dbus_get_event_name(event, &event_name) != MM_ERROR_NONE)) {
+               debug_error("Failed to get event name");
+               return MM_ERROR_SOUND_INTERNAL;
+       }
+
+       if (!(params = g_variant_new("(sub)", event_name, subs_id, subscribe))) {
+               debug_error("Construct Param failed");
+               return MM_ERROR_SOUND_INTERNAL;
+       }
+
+       if ((ret = mm_sound_dbus_emit_signal(AUDIO_PROVIDER_AUDIO_CLIENT, AUDIO_EVENT_CLIENT_SUBSCRIBED, params))) {
+               debug_error("dbus send signal for client subscribed failed");
+       }
+
+       debug_fleave();
+       return ret;
+}
+
+static int _notify_signal_handled(audio_event_t event, uint32_t event_id, uint32_t subs_id, GVariant *signal_params)
+{
+       int ret = MM_ERROR_NONE;
+       GVariant* params = NULL;
+       const char *event_name = NULL;
+
+       debug_fenter();
+
+       if ((ret = mm_sound_dbus_get_event_name(event, &event_name) != MM_ERROR_NONE)) {
+               debug_error("Failed to get event name");
+               return MM_ERROR_SOUND_INTERNAL;
+       }
+
+       if (!(params = g_variant_new("(usuv)", event_id, event_name, subs_id, signal_params))) {
+               debug_error("Construct Param failed");
+               return MM_ERROR_SOUND_INTERNAL;
+       }
+
+       if ((ret = mm_sound_dbus_emit_signal(AUDIO_PROVIDER_AUDIO_CLIENT, AUDIO_EVENT_CLIENT_HANDLED, params))) {
+               debug_error("dbus send signal for client handled failed");
+       }
+
+       debug_fleave();
+       return ret;
+}
 
 /* This callback unmarshall general-formed paramters to subject specific parameters,
  * and call proper callback */
 static void dbus_callback(audio_event_t event, GVariant *params, void *userdata)
 {
        struct callback_data *cb_data  = (struct callback_data*) userdata;
+       uint32_t event_id;
 
-       if (event == AUDIO_EVENT_VOLUME_CHANGED) {
+       if (event == AUDIO_EVENT_VOLUME_CHANGED) {
                char *volume_type_str = NULL, *direction = NULL;
                unsigned volume_level;
 
@@ -48,15 +103,16 @@ static void dbus_callback(audio_event_t event, GVariant *params, void *userdata)
                gboolean is_connected = FALSE;
                int device_id, io_direction, state;
 
-               g_variant_get(params, "((i&sii&s)b)", &device_id, &device_type, &io_direction,
+               g_variant_get(params, "(u(i&sii&s)b)", &event_id, &device_id, &device_type, &io_direction,
                                        &state, &name, &is_connected);
                ((mm_sound_device_connected_wrapper_cb)(cb_data->user_cb))(device_id, device_type, io_direction, state, name, is_connected, cb_data->user_data);
+               _notify_signal_handled(event, event_id, cb_data->subs_id, g_variant_new("(ib)", device_id, is_connected));
        } else if (event == AUDIO_EVENT_DEVICE_INFO_CHANGED) {
                const char *name = NULL, *device_type = NULL;
                int changed_device_info_type = 0;
                int device_id, io_direction, state;
 
-               g_variant_get(params, "((i&sii&s)i)", &device_id, &device_type, &io_direction,
+               g_variant_get(params, "(u(i&sii&s)i)", &event_id, &device_id, &device_type, &io_direction,
                                        &state, &name, &changed_device_info_type);
                ((mm_sound_device_info_changed_wrapper_cb)(cb_data->user_cb))(device_id, device_type, io_direction, state, name, changed_device_info_type, cb_data->user_data);
        } else if (event == AUDIO_EVENT_FOCUS_CHANGED) {
@@ -74,12 +130,13 @@ static void dbus_callback(audio_event_t event, GVariant *params, void *userdata)
 
 static void simple_callback_data_free_func(void *data)
 {
-    struct callback_data *cb_data = (struct callback_data*) data;
-
-    if (cb_data->free_func)
-       cb_data->free_func(cb_data->user_data);
+       struct callback_data *cb_data = (struct callback_data*) data;
 
-    g_free(cb_data);
+       if (cb_data) {
+               if (cb_data->free_func)
+                       cb_data->free_func(cb_data->user_data);
+               g_free(cb_data);
+       }
 }
 
 int mm_sound_proxy_add_test_callback(mm_sound_test_cb func, void *userdata, mm_sound_proxy_userdata_free freefunc, unsigned *subs_id)
@@ -89,11 +146,12 @@ int mm_sound_proxy_add_test_callback(mm_sound_test_cb func, void *userdata, mm_s
 
        debug_fenter();
 
-       GET_CB_DATA(cb_data, func, userdata, freefunc, NULL);
+       CB_DATA_NEW(cb_data, func, userdata, freefunc);
 
-       if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_SOUND_SERVER, AUDIO_EVENT_TEST, dbus_callback, cb_data, simple_callback_data_free_func, subs_id)) != MM_ERROR_NONE) {
+       if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_SOUND_SERVER, AUDIO_EVENT_TEST, dbus_callback, cb_data, simple_callback_data_free_func, &cb_data->subs_id)) != MM_ERROR_NONE)
                debug_error("add test callback failed");
-       }
+       else
+               *subs_id = cb_data->subs_id;
 
        debug_fleave();
        return ret;
@@ -207,12 +265,21 @@ int mm_sound_proxy_add_device_connected_callback(int device_flags, mm_sound_devi
 
        debug_fenter();
 
-       GET_CB_DATA(cb_data, func, userdata, freefunc, NULL);
+       CB_DATA_NEW(cb_data, func, userdata, freefunc);
 
-       if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_DEVICE_MANAGER, AUDIO_EVENT_DEVICE_CONNECTED, dbus_callback, cb_data, simple_callback_data_free_func, subs_id)) != MM_ERROR_NONE) {
+       if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_DEVICE_MANAGER, AUDIO_EVENT_DEVICE_CONNECTED, dbus_callback, cb_data, simple_callback_data_free_func, &cb_data->subs_id)) != MM_ERROR_NONE) {
                debug_error("add device connected callback failed");
+               goto finish;
+       }
+
+       if ((ret = _notify_subscription(AUDIO_EVENT_DEVICE_CONNECTED, cb_data->subs_id, TRUE)) != MM_ERROR_NONE) {
+               debug_error("failed to notify subscription of device connected event");
+               goto finish;
        }
 
+       *subs_id = cb_data->subs_id;
+
+finish:
        debug_fleave();
        return ret;
 }
@@ -224,8 +291,13 @@ int mm_sound_proxy_remove_device_connected_callback(unsigned subs_id)
 
        if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE) {
                debug_error("remove device connected callback failed");
+               goto finish;
        }
 
+       if ((ret = _notify_subscription(AUDIO_EVENT_DEVICE_CONNECTED, subs_id, FALSE)) != MM_ERROR_NONE)
+               debug_error("failed to notify unsubscription of device connected event");
+
+finish:
        debug_fleave();
        return ret;
 }
@@ -237,11 +309,12 @@ int mm_sound_proxy_add_device_info_changed_callback(int device_flags, mm_sound_d
 
        debug_fenter();
 
-       GET_CB_DATA(cb_data, func, userdata, freefunc, NULL);
+       CB_DATA_NEW(cb_data, func, userdata, freefunc);
 
-       if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_DEVICE_MANAGER, AUDIO_EVENT_DEVICE_INFO_CHANGED, dbus_callback, cb_data, simple_callback_data_free_func, subs_id)) != MM_ERROR_NONE) {
+       if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_DEVICE_MANAGER, AUDIO_EVENT_DEVICE_INFO_CHANGED, dbus_callback, cb_data, simple_callback_data_free_func, &cb_data->subs_id)) != MM_ERROR_NONE)
                debug_error("Add device info changed callback failed");
-       }
+       else
+               *subs_id = cb_data->subs_id;
 
        debug_fleave();
        return ret;
@@ -303,11 +376,13 @@ int mm_sound_proxy_add_volume_changed_callback(mm_sound_volume_changed_wrapper_c
 
        debug_fenter();
 
-       GET_CB_DATA(cb_data, func, userdata, freefunc, NULL);
+       CB_DATA_NEW(cb_data, func, userdata, freefunc);
 
-       if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_STREAM_MANAGER, AUDIO_EVENT_VOLUME_CHANGED, dbus_callback, cb_data, simple_callback_data_free_func, subs_id)) != MM_ERROR_NONE) {
+       if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_STREAM_MANAGER, AUDIO_EVENT_VOLUME_CHANGED, dbus_callback, cb_data, simple_callback_data_free_func, &cb_data->subs_id)) != MM_ERROR_NONE)
                debug_error("Add Volume changed callback failed");
-       }
+       else
+               *subs_id = cb_data->subs_id;
+
 
        debug_fleave();
 
@@ -545,11 +620,12 @@ int mm_sound_proxy_add_play_sound_end_callback(mm_sound_stop_callback_wrapper_fu
 
        debug_fenter();
 
-       GET_CB_DATA(cb_data, func, userdata, freefunc, NULL);
+       CB_DATA_NEW(cb_data, func, userdata, freefunc);
 
-       if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_SOUND_SERVER, AUDIO_EVENT_PLAY_FILE_END, dbus_callback, cb_data, simple_callback_data_free_func, subs_id)) != MM_ERROR_NONE) {
+       if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_SOUND_SERVER, AUDIO_EVENT_PLAY_FILE_END, dbus_callback, cb_data, simple_callback_data_free_func, &cb_data->subs_id)) != MM_ERROR_NONE)
                debug_error("add play sound end callback failed");
-       }
+       else
+               *subs_id = cb_data->subs_id;
 
        debug_fleave();
 
@@ -578,7 +654,7 @@ int mm_sound_proxy_emergent_exit(int exit_pid)
 
        params = g_variant_new("(i)", exit_pid);
        if (params) {
-           if ((ret = mm_sound_dbus_emit_signal(AUDIO_PROVIDER_AUDIO_CLIENT, AUDIO_EVENT_EMERGENT_EXIT, params)) != MM_ERROR_NONE) {
+               if ((ret = mm_sound_dbus_emit_signal(AUDIO_PROVIDER_AUDIO_CLIENT, AUDIO_EVENT_EMERGENT_EXIT, params)) != MM_ERROR_NONE) {
                        debug_error("dbus emergent exit failed");
                        goto cleanup;
                }
@@ -698,7 +774,7 @@ int mm_sound_proxy_register_focus(int id, int instance, const char *stream_type,
                debug_error("Construct Param for method call failed");
        }
 
-       if(ret != MM_ERROR_NONE)
+       if (ret != MM_ERROR_NONE)
                g_variant_get(result, "(i)",  &ret);
        if (result)
                g_variant_unref(result);
index 377cf50..37f327d 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-sound
 Summary:    MMSound Package contains client lib and sound_server binary
-Version:    0.10.23
+Version:    0.10.24
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0