Modify the avrcp and implement avrcp register function 37/22937/1
authorwu zheng <wu.zheng@intel.com>
Fri, 13 Jun 2014 09:17:56 +0000 (05:17 -0400)
committerwu zheng <wu.zheng@intel.com>
Fri, 13 Jun 2014 09:17:56 +0000 (05:17 -0400)
Change-Id: Id1cf35cf43b1d78dd61bf9bbecb730c4473ed031
Signed-off-by: Wu Zheng <wu.zheng@intel.com>
capi/bluetooth.c
doc/bluetooth-service.txt
include/bluetooth-service.h
include/bluez.h
lib/bluetooth-service.c
lib/bluez.c
src/media.c

index b4aeabb..f132153 100644 (file)
 #define CONNMAN_BLUETOOTH_TECHNOLOGY_PATH "/net/connman/technology/bluetooth"
 #define CONNMAN_BLUETOTOH_TECHNOLOGY_INTERFACE "net.connman.Technology"
 
+#define BLUEZ_AGENT_SERVICE "org.bluezlib.agent"
+#define AGENT_INTERFACE "org.bluez.Agent1"
+#define AGENT_OBJECT_PATH "/org/bluezlib/agent"
+
 static bool initialized;
 static bool bt_service_init;
 
+static guint bluetooth_agent_id;
+static guint profile_id;
+static GDBusConnection *conn;
+
 static bluez_adapter_t *default_adapter;
 
 static void profile_connect_callback(bluez_device_t *device,
@@ -52,6 +60,9 @@ static void profile_connect_callback(bluez_device_t *device,
 static void profile_disconnect_callback(bluez_device_t *device,
                                        enum device_profile_state state);
 
+static int request_name_on_dbus(const char *name);
+static void release_name_on_dbus(const char *name);
+
 struct device_connect_cb_node {
        bt_device_gatt_state_changed_cb cb;
        void *user_data;
@@ -944,15 +955,6 @@ static void _bt_update_bluetooth_callbacks(void)
                                        bluez_avrcp_target_state_changed,
                                        avrcp_target_state_node);
 
-       if (avrcp_repeat_node)
-               bluez_set_avrcp_repeat_changed_cb(
-                                       bluez_avrcp_repeat_changed,
-                                       avrcp_repeat_node);
-
-       if (avrcp_shuffle_node)
-               bluez_set_avrcp_shuffle_changed_cb(
-                                       bluez_avrcp_shuffle_changed,
-                                       avrcp_shuffle_node);
        if (device_connect_node)
                bluez_set_device_connect_changed_cb(
                                        bluez_device_connect_changed,
@@ -2441,11 +2443,121 @@ int bt_audio_unset_connection_state_changed_cb(void)
        return BT_SUCCESS;
 }
 
+static gboolean media_handle_set_property(GDBusConnection *connection,
+                               const gchar *sender,
+                               const gchar *object_path,
+                               const gchar *interface_name,
+                               const gchar *property_name,
+                               GVariant *value,
+                               GError **error,
+                               gpointer user_data)
+{
+       DBG("property_name = %s", property_name);
+
+       if (g_strcmp0(property_name, "LoopStatus") == 0) {
+               const gchar *loopstatus = g_variant_get_string(value, NULL);
+               DBG("loopstatus = %s", loopstatus);
+
+               if (avrcp_repeat_node)
+                       bluez_avrcp_repeat_changed(loopstatus,
+                                                       avrcp_repeat_node);
+       } else if (g_strcmp0(property_name, "Shuffle") == 0) {
+               gboolean shuffle_mode = g_variant_get_boolean(value);
+               if (shuffle_mode == TRUE)
+                       DBG("shuffle_mode TRUE");
+               else
+                       DBG("shuffle_mode FALSE");
+
+               if (avrcp_shuffle_node)
+                       bluez_avrcp_shuffle_changed(shuffle_mode,
+                                                       avrcp_shuffle_node);
+       }
+
+       return *error == NULL;
+}
+
+static const gchar media_xml[] =
+"<node>"
+"  <interface name='org.mpris.MediaPlayer2.Player'>"
+"    <property type='b' name='Shuffle' access='readwrite'/>"
+"    <property type='s' name='LoopStatus' access='readwrite'/>"
+"  </interface>"
+"</node>";
+
+static const GDBusInterfaceVTable media_handle = {
+       NULL,
+       NULL,
+       media_handle_set_property
+};
+
+static GDBusNodeInfo *media_data;
+static int bluetooth_media_agent_id;
+
+static int destory_media_agent(void)
+{
+       if (bluetooth_media_agent_id > 0) {
+               comms_bluetooth_unregister_media_agent(AGENT_OBJECT_PATH,
+                                                       NULL, NULL);
+
+               g_dbus_connection_unregister_object(conn,
+                                               bluetooth_media_agent_id);
+
+               bluetooth_media_agent_id = 0;
+
+               release_name_on_dbus(BLUEZ_AGENT_SERVICE);
+       }
+
+       return 0;
+}
+
+static int create_media_agent(void)
+{
+       int ret;
+
+       if (bluetooth_media_agent_id)
+               return BT_ERROR_ALREADY_DONE;
+
+       media_data =
+               g_dbus_node_info_new_for_xml(media_xml, NULL);
+
+       ret = request_name_on_dbus(BLUEZ_AGENT_SERVICE);
+       if (ret != 0)
+               return -1;
+
+       DBG("%s requested success", BLUEZ_AGENT_SERVICE);
+
+       bluetooth_media_agent_id = g_dbus_connection_register_object(
+                                               conn,
+                                               AGENT_OBJECT_PATH,
+                                               media_data->
+                                                       interfaces[0],
+                                               &media_handle,
+                                               NULL,
+                                               NULL,
+                                               NULL);
+
+       if (bluetooth_media_agent_id == 0)
+               return BT_ERROR_OPERATION_FAILED;
+
+       ret = comms_bluetooth_register_media_agent_sync(AGENT_OBJECT_PATH,
+                                                               NULL);
+
+       DBG("ret = %d", ret);
+
+       if (ret != BT_SUCCESS) {
+               destory_media_agent();
+               return BT_ERROR_OPERATION_FAILED;
+       }
+
+       return BT_SUCCESS;
+}
+
 int bt_avrcp_target_initialize(
                        bt_avrcp_target_connection_state_changed_cb callback,
                        void *user_data)
 {
        struct avrcp_target_connection_state_changed_node *node_data = NULL;
+       int ret;
 
        DBG("default_adpater: %p", default_adapter);
 
@@ -2460,6 +2572,11 @@ int bt_avrcp_target_initialize(
                return BT_ERROR_ALREADY_DONE;
        }
 
+       ret = create_media_agent();
+
+       if (ret != BT_SUCCESS)
+               return ret;
+
        node_data =
                g_new0(struct avrcp_target_connection_state_changed_node, 1);
        if (node_data == NULL) {
@@ -2492,6 +2609,8 @@ int bt_avrcp_target_deinitialize(void)
        g_free(avrcp_target_state_node);
        avrcp_target_state_node = NULL;
 
+       destory_media_agent();
+
        return BT_SUCCESS;
 }
 
@@ -2525,8 +2644,6 @@ int bt_avrcp_set_repeat_mode_changed_cb(
 
        avrcp_repeat_node = node_data;
 
-       _bt_update_bluetooth_callbacks();
-
        return BT_SUCCESS;
 }
 
@@ -2540,8 +2657,6 @@ int bt_avrcp_unset_repeat_mode_changed_cb(void)
        if (!avrcp_repeat_node)
                return BT_SUCCESS;
 
-       bluez_unset_avrcp_repeat_changed_cb();
-
        g_free(avrcp_repeat_node);
        avrcp_repeat_node = NULL;
 
@@ -2578,8 +2693,6 @@ int bt_avrcp_set_shuffle_mode_changed_cb(
 
        avrcp_shuffle_node = node_data;
 
-       _bt_update_bluetooth_callbacks();
-
        return BT_SUCCESS;
 }
 
@@ -2593,8 +2706,6 @@ int bt_avrcp_unset_shuffle_mode_changed_cb(void)
        if (!avrcp_shuffle_node)
                return BT_SUCCESS;
 
-       bluez_unset_avrcp_shuffle_changed_cb();
-
        g_free(avrcp_shuffle_node);
        avrcp_shuffle_node = NULL;
 
@@ -2995,10 +3106,6 @@ static struct spp_context *find_spp_context_from_fd(int fd)
 
 /* Agent Function */
 
-#define BLUEZ_AGENT_SERVICE "org.bluezlib.agent"
-#define AGENT_INTERFACE "org.bluez.Agent1"
-#define AGENT_OBJECT_PATH "/org/bluezlib/agent"
-
 static bt_agent *this_agent;
 
 static GDBusNodeInfo *introspection_data;
@@ -3361,9 +3468,6 @@ static const GDBusInterfaceVTable interface_handle = {
        NULL
 };
 
-static guint bluetooth_agent_id;
-static guint profile_id;
-static GDBusConnection *conn;
 
 static void release_dbus_connection(void)
 {
index a60b6de..8bcc657 100644 (file)
@@ -149,7 +149,22 @@ Service         org.tizen.comms
 Interface       org.tizen.comms.mediaplayer
 Object path     /org/tizen/comms/bluetooth
 
-Methods         void MediaPlayerChangeProperty(uint32 type, uint32 value)
+Methods                void RegisterMediaAgent(object agent)
+
+               Registers an Media agent handler.
+
+                       Object path agent defines the path of the agent
+                       that will be called when authorize each received object
+
+                       Possible errors: org.bluez.Error.AlreadyExists
+
+               void UnregisterMediaAgent(object agent)
+
+                       Unregisters the registiered Media agent.
+
+                       Possible errors: org.bluez.Error.DoesNotExist
+
+               void MediaPlayerChangeProperty(uint32 type, uint32 value)
 
                        Set AVRCP property.
 
index ba0850b..31d0082 100644 (file)
@@ -59,6 +59,10 @@ void comms_bluetooth_register_pairing_agent(
                        bluetooth_simple_callback cb,
                        void *user_data);
 
+int comms_bluetooth_register_pairing_agent_sync(
+                                       const char *agent_path,
+                                       void *user_data);
+
 void comms_bluetooth_unregister_pairing_agent(
                        const char *agent_path,
                        bluetooth_simple_callback cb,
@@ -69,6 +73,10 @@ void comms_bluetooth_register_opp_agent(
                        bluetooth_simple_callback cb,
                        void *user_data);
 
+int comms_bluetooth_register_opp_agent_sync(
+                       const char *agent_path,
+                       void *user_data);
+
 void comms_bluetooth_unregister_opp_agent(
                        const char *agent_path,
                        bluetooth_simple_callback cb,
@@ -95,4 +103,18 @@ int comms_bluetooth_avrcp_change_track(
                        void *track_data,
                        bluetooth_simple_callback cb,
                        void *user_data);
+
+void comms_bluetooth_register_media_agent(
+                       const char *agent_path,
+                       bluetooth_simple_callback cb,
+                       void *user_data);
+
+int comms_bluetooth_register_media_agent_sync(
+                       const char *agent_path,
+                       void *user_data);
+
+void comms_bluetooth_unregister_media_agent(
+                       const char *agent_path,
+                       bluetooth_simple_callback cb,
+                       void *user_data);
 #endif
index 45dda69..9e6a63e 100644 (file)
@@ -340,25 +340,6 @@ void bluez_set_hdp_state_changed_cb(
 
 void bluez_unset_hdp_state_changed_cb(struct _bluez_device *device);
 
-typedef void (*bluez_avrcp_repeat_changed_cb_t)(
-                               const gchar *repeat,
-                               gpointer user_data);
-
-void bluez_set_avrcp_repeat_changed_cb(
-                               bluez_avrcp_repeat_changed_cb_t cb,
-                               gpointer user_data);
-
-void bluez_unset_avrcp_repeat_changed_cb();
-
-typedef void (*bluez_avrcp_shuffle_changed_cb_t)(
-                               gboolean shuffle_mode,
-                               gpointer user_data);
-
-void bluez_set_avrcp_shuffle_changed_cb(
-                               bluez_avrcp_shuffle_changed_cb_t cb,
-                               gpointer user_data);
-void bluez_unset_avrcp_shuffle_changed_cb();
-
 typedef void (*bluez_avrcp_target_cb_t)(
                                const char *remote_address,
                                gboolean connected,
index 9c94a8b..e56869e 100644 (file)
@@ -767,6 +767,30 @@ void comms_bluetooth_register_pairing_agent(const char *agent_path,
                                        async_result_node);
 }
 
+int comms_bluetooth_register_pairing_agent_sync(const char *agent_path,
+                                                void *user_data)
+{
+       GError *error = NULL;
+
+       if (this_bluetooth == NULL) {
+               ERROR("bluetooth not register");
+               return BT_ERROR_OPERATION_FAILED;
+       }
+
+       g_dbus_proxy_call_sync(this_bluetooth->pairing.proxy,
+                                       "RegisterPairingAgent",
+                                       g_variant_new("(o)", agent_path),
+                                       0, -1, NULL, &error);
+
+       if (error) {
+               ERROR("%s", error->message);
+               g_error_free(error);
+               return BT_ERROR_OPERATION_FAILED;
+       }
+
+       return BT_SUCCESS;
+}
+
 void comms_bluetooth_unregister_pairing_agent(const char *agent_path,
                                        bluetooth_simple_callback cb,
                                        void *user_data)
@@ -795,6 +819,86 @@ void comms_bluetooth_unregister_pairing_agent(const char *agent_path,
                                async_result_node);
 }
 
+void comms_bluetooth_register_media_agent(const char *agent_path,
+                                       bluetooth_simple_callback cb,
+                                       void *user_data)
+{
+       struct _bluetooth_simple_async_result *async_result_node;
+
+       if (this_bluetooth == NULL) {
+               ERROR("bluetooth not register");
+               return;
+       }
+
+       async_result_node = g_new0(struct _bluetooth_simple_async_result, 1);
+       if (async_result_node == NULL) {
+               ERROR("no memory");
+               return;
+       }
+
+       async_result_node->callback = cb;
+       async_result_node->user_data = user_data;
+
+       g_dbus_proxy_call(this_bluetooth->mediaplayer.proxy,
+                               "RegisterMediaAgent",
+                               g_variant_new("(o)", agent_path),
+                               0, -1, NULL,
+                               bluetooth_simple_async_cb,
+                               async_result_node);
+}
+
+int comms_bluetooth_register_media_agent_sync(const char *agent_path,
+                                               void *user_data)
+{
+       GError *error = NULL;
+
+       if (this_bluetooth == NULL) {
+               ERROR("bluetooth not register");
+               return BT_ERROR_OPERATION_FAILED;
+       }
+
+       g_dbus_proxy_call_sync(this_bluetooth->mediaplayer.proxy,
+                                       "RegisterMediaAgent",
+                                       g_variant_new("(o)", agent_path),
+                                       0, -1, NULL, &error);
+
+       if (error) {
+               ERROR("%s", error->message);
+               g_error_free(error);
+               return BT_ERROR_OPERATION_FAILED;
+       }
+
+       return BT_SUCCESS;
+}
+
+void comms_bluetooth_unregister_media_agent(const char *agent_path,
+                                       bluetooth_simple_callback cb,
+                                       void *user_data)
+{
+       struct _bluetooth_simple_async_result *async_result_node;
+
+       if (this_bluetooth == NULL) {
+               ERROR("bluetooth not register");
+               return;
+       }
+
+       async_result_node = g_new0(struct _bluetooth_simple_async_result, 1);
+       if (async_result_node == NULL) {
+               ERROR("no memory");
+               return;
+       }
+
+       async_result_node->callback = cb;
+       async_result_node->user_data = user_data;
+
+       g_dbus_proxy_call(this_bluetooth->mediaplayer.proxy,
+                               "UnregisterMediaAgent",
+                               g_variant_new("(o)", agent_path),
+                               0, -1, NULL,
+                               bluetooth_simple_async_cb,
+                               async_result_node);
+}
+
 void comms_bluetooth_register_opp_agent(const char *agent_path,
                                        bluetooth_simple_callback cb,
                                        void *user_data)
@@ -823,6 +927,30 @@ void comms_bluetooth_register_opp_agent(const char *agent_path,
                                async_result_node);
 }
 
+int comms_bluetooth_register_opp_agent_sync(const char *agent_path,
+                                               void *user_data)
+{
+       GError *error = NULL;
+
+       if (this_bluetooth == NULL) {
+               ERROR("bluetooth not register");
+               return BT_ERROR_OPERATION_FAILED;
+       }
+
+       g_dbus_proxy_call_sync(this_bluetooth->opp.proxy,
+                                       "RegisterObexAgent",
+                                       g_variant_new("(o)", agent_path),
+                                       0, -1, NULL, &error);
+
+       if (error) {
+               ERROR("%s", error->message);
+               g_error_free(error);
+               return -1;
+       }
+
+       return BT_SUCCESS;
+}
+
 void comms_bluetooth_unregister_opp_agent(const char *agent_path,
                                        bluetooth_simple_callback cb,
                                        void *user_data)
index 1e4f76f..bf64511 100644 (file)
@@ -138,10 +138,6 @@ static bluez_adapter_added_cb_t adapter_added_cb;
 static gpointer adapter_added_cb_data;
 static bluez_agent_added_cb_t agent_added_cb;
 static gpointer agent_added_cb_data;
-static bluez_avrcp_repeat_changed_cb_t avrcp_repeat_changed_cb;
-static gpointer avrcp_repeat_changed_data;
-static bluez_avrcp_shuffle_changed_cb_t avrcp_shuffle_changed_cb;
-static gpointer avrcp_shuffle_changed_data;
 static bluez_avrcp_target_cb_t avrcp_target_cb;
 static gpointer avrcp_target_cb_data;
 static bluez_audio_state_cb_t audio_state_cb;
@@ -151,9 +147,6 @@ static gpointer dev_connect_data;
 static device_disconnect_cb_t dev_disconnect_cb;
 static gpointer dev_disconnect_data;
 
-static GDBusNodeInfo *introspection_data;
-static guint bt_register_avrcp_property(struct _bluez_adapter *adapter);
-
 static struct _bluez_object *get_object_from_path(const char *path)
 {
        return g_hash_table_lookup(bluez_object_hash, (gpointer) path);
@@ -1042,32 +1035,6 @@ void bluez_set_device_disconnect_changed_cb(device_disconnect_cb_t cb,
        dev_disconnect_data = user_data;
 }
 
-void bluez_set_avrcp_repeat_changed_cb(bluez_avrcp_repeat_changed_cb_t cb,
-                                               gpointer user_data)
-{
-       avrcp_repeat_changed_cb = cb;
-       avrcp_repeat_changed_data = user_data;
-}
-
-void bluez_unset_avrcp_repeat_changed_cb()
-{
-       avrcp_repeat_changed_cb = NULL;
-       avrcp_repeat_changed_data = NULL;
-}
-
-void bluez_set_avrcp_shuffle_changed_cb(bluez_avrcp_shuffle_changed_cb_t cb,
-                                               gpointer user_data)
-{
-       avrcp_shuffle_changed_cb = cb;
-       avrcp_shuffle_changed_data = user_data;
-}
-
-void bluez_unset_avrcp_shuffle_changed_cb()
-{
-       avrcp_shuffle_changed_cb = NULL;
-       avrcp_shuffle_changed_data = NULL;
-}
-
 void bluez_set_avrcp_target_cb(bluez_avrcp_target_cb_t cb,
                                                gpointer user_data)
 {
@@ -2671,217 +2638,6 @@ int bluez_media_player_set_properties(struct _bluez_adapter *adapter,
        return BT_SUCCESS;
 }
 
-static void handle_media_proxy_cb(GObject *source_object,
-                                       GAsyncResult *res,
-                                       gpointer user_data)
-{
-       GVariant *ret;
-       GError *error = NULL;
-       enum bluez_error_type error_type = ERROR_NONE;
-       gchar *adapter_object_path = user_data;
-       struct _bluez_adapter *adapter;
-
-       DBG("");
-
-       if (!adapter_object_path)
-               return;
-
-       adapter = g_hash_table_lookup(bluez_adapter_hash,
-                                       adapter_object_path);
-
-       if (adapter == NULL)
-               goto done;
-
-       ret = g_dbus_proxy_call_finish(adapter->media_proxy, res,
-                                                       &error);
-       if (ret == NULL) {
-               error_type = get_error_type(error);
-               DBG("error_type = %d", error_type);
-               g_error_free(error);
-       } else
-               g_variant_unref(ret);
-
-done:
-       g_free(adapter_object_path);
-}
-
-void bt_media_register_player(struct _bluez_adapter *adapter)
-{
-       GVariant *str_array[1];
-       GVariant *val_array;
-       GVariant *val_metadata;
-
-       GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
-       GVariantBuilder *builder_array =
-                               g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
-
-       GVariant *val = g_variant_new("s", "None");
-       g_variant_builder_add(builder, "{sv}", "LoopStatus", val);
-
-       val = g_variant_new("b", FALSE);
-       g_variant_builder_add(builder, "{sv}", "Shuffle", val);
-
-       val = g_variant_new("s", "Stopped");
-       g_variant_builder_add(builder, "{sv}", "PlaybackStatus", val);
-
-       val = g_variant_new("x", 0);
-       g_variant_builder_add(builder, "{sv}", "Position", val);
-
-       val = g_variant_new_string("\0");
-       str_array[0] = val;
-       val_array = g_variant_new_array(G_VARIANT_TYPE_STRING, str_array, 1);
-       g_variant_builder_add(builder_array, "{sv}", "xesam:artist", val_array);
-
-       val = g_variant_new_string("\0");
-       str_array[0] = val;
-       val_array = g_variant_new_array(G_VARIANT_TYPE_STRING, str_array, 1);
-       g_variant_builder_add(builder_array, "{sv}", "xesam:genre", val_array);
-
-       val = g_variant_new("s", "\0");
-       g_variant_builder_add(builder_array, "{sv}", "xesam:title", val);
-
-       val = g_variant_new("i", 0);
-       g_variant_builder_add(builder_array, "{sv}", "xesam:trackNumber", val);
-
-       val = g_variant_new("s", "\0");
-       g_variant_builder_add(builder_array, "{sv}", "xesam:album", val);
-
-       val = g_variant_new("x", 0);
-       g_variant_builder_add(builder_array, "{sv}", "mpris:length", val);
-
-       val_metadata = g_variant_new("a{sv}", builder_array);
-       g_variant_builder_add(builder, "{sv}", "Metadata", val_metadata);
-
-       DBG("+");
-
-       if (adapter == NULL) {
-               ERROR("adapter is NULL");
-               return;
-       }
-
-       if (adapter->media_proxy == NULL) {
-               ERROR("adapter->mediaprooxy is NULL");
-               return;
-       }
-
-       if (adapter->avrcp_registration_id == 0)
-               adapter->avrcp_registration_id =
-                               bt_register_avrcp_property(adapter);
-
-       g_dbus_proxy_call(adapter->media_proxy,
-                       "RegisterPlayer",
-                       g_variant_new("(oa{sv})",
-                               BT_MEDIA_OBJECT_PATH, builder),
-                       0, -1, NULL,
-                       handle_media_proxy_cb,
-                       g_strdup(adapter->object_path));
-
-       DBG("-");
-       return;
-}
-
-void bt_media_unregister_player(struct _bluez_adapter *adapter)
-{
-       GDBusConnection  *conn;
-
-       DBG("+");
-
-       if (adapter == NULL) {
-               ERROR("adapter is NULL");
-               return;
-       }
-
-       if (adapter->media_proxy == NULL) {
-               ERROR("adapter->mediaprooxy is NULL");
-               return;
-       }
-
-       g_dbus_proxy_call(adapter->media_proxy,
-                       "UnregisterPlayer",
-                       g_variant_new("(o)", BT_MEDIA_OBJECT_PATH),
-                       0, -1, NULL,
-                       handle_media_proxy_cb,
-                       g_strdup(adapter->object_path));
-
-       conn = g_dbus_proxy_get_connection(adapter->media_proxy);
-
-       g_dbus_connection_unregister_object(conn,
-                       adapter->avrcp_registration_id);
-
-       adapter->avrcp_registration_id = 0;
-
-       DBG("-");
-       return;
-}
-
-static const gchar introspection_xml[] =
-"<node>"
-"  <interface name='org.mpris.MediaPlayer2.Player'>"
-"    <property type='b' name='Shuffle' access='readwrite'/>"
-"    <property type='s' name='LoopStatus' access='readwrite'/>"
-"  </interface>"
-"</node>";
-
-static gboolean handle_set_property(GDBusConnection *connection,
-                               const gchar *sender,
-                               const gchar *object_path,
-                               const gchar *interface_name,
-                               const gchar *property_name,
-                               GVariant *value,
-                               GError **error,
-                               gpointer user_data)
-{
-       DBG("property_name = %s", property_name);
-
-       if (g_strcmp0(property_name, "LoopStatus") == 0) {
-               const gchar *loopstatus = g_variant_get_string(value, NULL);
-               DBG("loopstatus = %s", loopstatus);
-
-               if (avrcp_repeat_changed_cb)
-                       avrcp_repeat_changed_cb(loopstatus,
-                                       avrcp_repeat_changed_data);
-
-       } else if (g_strcmp0(property_name, "Shuffle") == 0) {
-               gboolean shuffle_mode = g_variant_get_boolean(value);
-               if (shuffle_mode == TRUE)
-                       DBG("shuffle_mode TRUE");
-               else
-                       DBG("shuffle_mode FALSE");
-
-               if (avrcp_shuffle_changed_cb)
-                       avrcp_shuffle_changed_cb(shuffle_mode,
-                                       avrcp_shuffle_changed_data);
-       }
-
-       return *error == NULL;
-}
-
-static const GDBusInterfaceVTable interface_vtable = {
-       NULL,
-       NULL,
-       handle_set_property
-};
-
-static guint bt_register_avrcp_property(struct _bluez_adapter *adapter)
-{
-       guint rid;
-       GDBusConnection  *conn;
-
-       conn = g_dbus_proxy_get_connection(adapter->media_proxy);
-
-       introspection_data = g_dbus_node_info_new_for_xml(introspection_xml,
-                                                               NULL);
-
-       rid = g_dbus_connection_register_object(conn, BT_MEDIA_OBJECT_PATH,
-                                       introspection_data->interfaces[0],
-                                       &interface_vtable,
-                                       NULL,
-                                       NULL,
-                                       NULL);
-
-       return rid;
-}
-
 static void bluez_device_connect_cb(GObject *source_object,
                                                GAsyncResult *res,
                                                gpointer user_data)
index bb1dcf3..adef4ea 100644 (file)
 #include "vertical.h"
 
 #define BLUETOOTH_OBJECT "/org/tizen/comms/bluetooth"
+#define BT_MEDIA_OBJECT_PATH "/Musicplayer"
+#define MEDIA_PLAYER_INTERFACE  "org.mpris.MediaPlayer2.Player"
+
+struct agent {
+       gchar *owner;
+       gchar *object_path;
+       guint watch_id;
+};
+
+struct _bluez_adapter {
+       char *interface_name;
+       char *object_path;
+       GDBusInterface *interface;
+       GDBusInterface *media_interface;
+       guint avrcp_registration_id;
+       GDBusProxy *proxy;
+       GDBusProxy *media_proxy;
+       struct _bluez_object *parent;
+       struct _device_head *device_head;
+       bluez_adapter_powered_cb_t powered_cb;
+       gpointer powered_cb_data;
+       bluez_adapter_device_cb_t device_created_cb;
+       gpointer device_created_data;
+       bluez_adapter_device_cb_t device_removed_cb;
+       gpointer device_removed_data;
+       bluez_adapter_alias_cb_t alias_cb;
+       gpointer alias_cb_data;
+       bluez_adapter_discovering_cb_t discovering_cb;
+       gpointer discovering_cb_data;
+       bluez_adapter_discoverable_cb_t discoverable_cb;
+       gpointer discoverable_cb_data;
+       bluez_adapter_discoverable_tm_cb_t discoverable_timeout_cb;
+       gpointer discoverable_timeout_cb_data;
+};
+
+static struct agent *relay_agent;
 
 static const GDBusMethodInfo *_media_method_info_pointers[] =
 {
+       GDBUS_METHOD("RegisterMediaAgent",
+                               GDBUS_ARGS(_ARG("agent", "o")), NULL),
+       GDBUS_METHOD("UnregisterMediaAgent",
+                               GDBUS_ARGS(_ARG("agent", "o")), NULL),
        GDBUS_METHOD("MediaPlayerChangeProperty",
                                GDBUS_ARGS(_ARG("type", "u"),
                                _ARG("value", "u")), NULL),
@@ -86,6 +126,107 @@ static void bt_media_unregister_dbus_interface()
                                                media_interface);
 }
 
+static void free_relay_agent(struct agent *agent)
+{
+       g_free(agent->owner);
+       g_free(agent->object_path);
+
+       g_free(agent);
+}
+
+static void relay_agent_disconnected(GDBusConnection *connection,
+                               const gchar *name, gpointer user_data)
+{
+       DBG("");
+
+       if (!relay_agent)
+               return;
+
+       free_relay_agent(relay_agent);
+
+       relay_agent = NULL;
+}
+
+static struct agent *create_relay_agent(const gchar *sender,
+                                       const gchar *path,
+                                       guint watch_id)
+{
+       struct agent *agent;
+
+       agent = g_new0(struct agent, 1);
+       if (agent == NULL) {
+               ERROR("no memory");
+               return NULL;
+       }
+
+       agent->owner = g_strdup(sender);
+       agent->object_path = g_strdup(path);
+       agent->watch_id = watch_id;
+
+       return agent;
+}
+
+static void register_relay_agent_handler(
+                                       GDBusConnection *connection,
+                                       GVariant *parameters,
+                                       GDBusMethodInvocation *invocation,
+                                       gpointer user_data)
+{
+       const gchar *sender;
+       gchar *agent_path;
+       guint relay_agent_watch_id;
+
+       DBG("");
+
+       if (relay_agent)
+               return comms_error_already_exists(invocation);
+
+       g_variant_get(parameters, "(o)", &agent_path);
+       if (agent_path == NULL)
+               return comms_error_invalid_args(invocation);
+
+       sender = g_dbus_method_invocation_get_sender(invocation);
+
+       relay_agent_watch_id =
+                       g_bus_watch_name_on_connection(connection, sender,
+                                       G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
+                                       NULL, relay_agent_disconnected,
+                                       NULL, NULL);
+
+       relay_agent = create_relay_agent(sender, agent_path,
+                                               relay_agent_watch_id);
+
+       g_dbus_method_invocation_return_value(invocation, NULL);
+}
+
+static void unregister_relay_agent_handler(
+                                       GDBusConnection *connection,
+                                       GVariant *parameters,
+                                       GDBusMethodInvocation *invocation,
+                                       gpointer user_data)
+{
+       gchar *relay_agent_path;
+
+       DBG("");
+
+       if (relay_agent == NULL)
+               return comms_error_does_not_exist(invocation);
+
+       g_variant_get(parameters, "(o)", &relay_agent_path);
+       if (relay_agent_path == NULL)
+               return comms_error_invalid_args(invocation);
+
+       if (g_strcmp0(relay_agent_path, relay_agent->object_path))
+               return comms_error_does_not_exist(invocation);
+
+       g_free(relay_agent_path);
+
+       free_relay_agent(relay_agent);
+       relay_agent = NULL;
+
+       g_dbus_method_invocation_return_value(invocation, NULL);
+}
+
 static void handle_change_track(GVariant *parameters)
 {
        GVariantIter *valueIter;
@@ -153,7 +294,15 @@ static void media_skeleton_handle_method_call(GDBusConnection *connection,
                return;
        }
 
-       if (g_strcmp0(method_name, "MediaPlayerChangeProperty") == 0) {
+       if (g_strcmp0(method_name, "RegisterMediaAgent") == 0) {
+               register_relay_agent_handler(connection, parameters,
+                                               invocation, user_data);
+               return;
+       } else if (g_strcmp0(method_name, "UnregisterMediaAgent") == 0) {
+               unregister_relay_agent_handler(connection, parameters,
+                                               invocation, user_data);
+               return;
+       } else if (g_strcmp0(method_name, "MediaPlayerChangeProperty") == 0) {
                guint32 type, value;
 
                g_variant_get(parameters, "(uu)", &type, &value);
@@ -232,6 +381,248 @@ MediaSkeleton *bt_service_media_new(void)
        return (MediaSkeleton *)g_object_new(TYPE_MEDIA_SKELETON, NULL);
 }
 
+static gboolean handle_set_property(GDBusConnection *connection,
+                               const gchar *sender,
+                               const gchar *object_path,
+                               const gchar *interface_name,
+                               const gchar *property_name,
+                               GVariant *value,
+                               GError **error,
+                               gpointer user_data)
+{
+       GVariantBuilder *builder;
+       GVariant *val, *signal_variant;
+
+       DBG("property_name = %s", property_name);
+
+       if (relay_agent == NULL) {
+               DBG("relay_agent == NULL");
+               return false;
+       }
+
+       if (g_strcmp0(property_name, "LoopStatus") == 0) {
+               const gchar *loopstatus = g_variant_get_string(value, NULL);
+               DBG("loopstatus = %s", loopstatus);
+
+               val = g_variant_new("s", loopstatus);
+               builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
+               g_variant_builder_add(builder, "{sv}", "LoopStatus", val);
+
+               signal_variant = g_variant_ref_sink(g_variant_new("(sa{sv}as)",
+                                       MEDIA_PLAYER_INTERFACE,
+                                       builder, NULL));
+
+               g_dbus_connection_emit_signal(connection, NULL,
+                                       relay_agent->object_path,
+                                       "org.freedesktop.DBus.Properties",
+                                       "PropertiesChanged",
+                                       signal_variant, NULL);
+
+               g_variant_unref(signal_variant);
+       } else if (g_strcmp0(property_name, "Shuffle") == 0) {
+               gboolean shuffle_mode = g_variant_get_boolean(value);
+               if (shuffle_mode == TRUE)
+                       DBG("shuffle_mode TRUE");
+               else
+                       DBG("shuffle_mode FALSE");
+
+               val = g_variant_new("b", shuffle_mode);
+               builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
+               g_variant_builder_add(builder, "{sv}", "Shuffle", val);
+
+               signal_variant = g_variant_ref_sink(g_variant_new("(sa{sv}as)",
+                                       MEDIA_PLAYER_INTERFACE,
+                                       builder, NULL));
+
+               g_dbus_connection_emit_signal(connection, NULL,
+                                       relay_agent->object_path,
+                                       "org.freedesktop.DBus.Properties",
+                                       "PropertiesChanged",
+                                       signal_variant, NULL);
+
+               g_variant_unref(signal_variant);
+       }
+
+       return *error == NULL;
+}
+
+static const gchar introspection_xml[] =
+"<node>"
+"  <interface name='org.mpris.MediaPlayer2.Player'>"
+"    <property type='b' name='Shuffle' access='readwrite'/>"
+"    <property type='s' name='LoopStatus' access='readwrite'/>"
+"  </interface>"
+"</node>";
+
+static const GDBusInterfaceVTable interface_vtable = {
+       NULL,
+       NULL,
+       handle_set_property
+};
+
+static GDBusNodeInfo *introspection_data;
+
+static guint bt_register_avrcp_property(struct _bluez_adapter *adapter)
+{
+       guint rid;
+       GDBusConnection  *conn;
+
+       conn = g_dbus_proxy_get_connection(adapter->media_proxy);
+
+       introspection_data = g_dbus_node_info_new_for_xml(introspection_xml,
+                                                               NULL);
+
+       rid = g_dbus_connection_register_object(conn, BT_MEDIA_OBJECT_PATH,
+                                       introspection_data->interfaces[0],
+                                       &interface_vtable,
+                                       NULL,
+                                       NULL,
+                                       NULL);
+
+       return rid;
+}
+
+static void bt_unregister_avrcp_property(struct _bluez_adapter *adapter,
+                                               int avrcp_registration_id)
+{
+       GDBusConnection  *conn;
+
+       conn = g_dbus_proxy_get_connection(adapter->media_proxy);
+
+       g_dbus_connection_unregister_object(conn,
+                                       avrcp_registration_id);
+}
+
+static void handle_media_proxy_cb(GObject *source_object,
+                                       GAsyncResult *res,
+                                       gpointer user_data)
+{
+       GVariant *ret;
+       GError *error = NULL;
+       struct _bluez_adapter *adapter = user_data;
+       enum bluez_error_type error_type = ERROR_NONE;
+
+       DBG("");
+
+       if (adapter == NULL)
+               return;
+
+       ret = g_dbus_proxy_call_finish(adapter->media_proxy, res,
+                                                       &error);
+       if (ret == NULL) {
+               error_type = get_error_type(error);
+               DBG("error_type = %d", error_type);
+               g_error_free(error);
+       } else
+               g_variant_unref(ret);
+}
+
+void bt_media_register_player(struct _bluez_adapter *adapter)
+{
+       GVariant *str_array[1];
+       GVariant *val_array;
+       GVariant *val_metadata;
+
+       GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
+       GVariantBuilder *builder_array =
+                               g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
+
+       GVariant *val = g_variant_new("s", "None");
+       g_variant_builder_add(builder, "{sv}", "LoopStatus", val);
+
+       val = g_variant_new("b", FALSE);
+       g_variant_builder_add(builder, "{sv}", "Shuffle", val);
+
+       val = g_variant_new("s", "Stopped");
+       g_variant_builder_add(builder, "{sv}", "PlaybackStatus", val);
+
+       val = g_variant_new("x", 0);
+       g_variant_builder_add(builder, "{sv}", "Position", val);
+
+       val = g_variant_new_string("\0");
+       str_array[0] = val;
+       val_array = g_variant_new_array(G_VARIANT_TYPE_STRING, str_array, 1);
+       g_variant_builder_add(builder_array, "{sv}", "xesam:artist", val_array);
+
+       val = g_variant_new_string("\0");
+       str_array[0] = val;
+       val_array = g_variant_new_array(G_VARIANT_TYPE_STRING, str_array, 1);
+       g_variant_builder_add(builder_array, "{sv}", "xesam:genre", val_array);
+
+       val = g_variant_new("s", "\0");
+       g_variant_builder_add(builder_array, "{sv}", "xesam:title", val);
+
+       val = g_variant_new("i", 0);
+       g_variant_builder_add(builder_array, "{sv}", "xesam:trackNumber", val);
+
+       val = g_variant_new("s", "\0");
+       g_variant_builder_add(builder_array, "{sv}", "xesam:album", val);
+
+       val = g_variant_new("x", 0);
+       g_variant_builder_add(builder_array, "{sv}", "mpris:length", val);
+
+       val_metadata = g_variant_new("a{sv}", builder_array);
+       g_variant_builder_add(builder, "{sv}", "Metadata", val_metadata);
+
+       DBG("+");
+
+       if (adapter == NULL) {
+               ERROR("adapter is NULL");
+               return;
+       }
+
+       if (adapter->media_proxy == NULL) {
+               ERROR("adapter->mediaprooxy is NULL");
+               return;
+       }
+
+       if (adapter->avrcp_registration_id == 0)
+               adapter->avrcp_registration_id =
+                       bt_register_avrcp_property(adapter);
+
+       g_dbus_proxy_call(adapter->media_proxy,
+                       "RegisterPlayer",
+                       g_variant_new("(oa{sv})",
+                               BT_MEDIA_OBJECT_PATH, builder),
+                       0, -1, NULL,
+                       handle_media_proxy_cb,
+                       adapter);
+
+       DBG("-");
+       return;
+}
+
+void bt_media_unregister_player(struct _bluez_adapter *adapter)
+{
+       DBG("+");
+
+       if (adapter == NULL) {
+               ERROR("adapter is NULL");
+               return;
+       }
+
+       if (adapter->media_proxy == NULL) {
+               ERROR("adapter->mediaprooxy is NULL");
+               return;
+       }
+
+       g_dbus_proxy_call(adapter->media_proxy,
+                       "UnregisterPlayer",
+                       g_variant_new("(o)", BT_MEDIA_OBJECT_PATH),
+                       0, -1, NULL,
+                       handle_media_proxy_cb,
+                       adapter);
+
+       if (adapter->avrcp_registration_id)
+               bt_unregister_avrcp_property(adapter,
+                               adapter->avrcp_registration_id);
+
+       adapter->avrcp_registration_id = 0;
+
+       DBG("-");
+       return;
+}
+
 void bt_service_media_init(GDBusObjectSkeleton *gdbus_object_skeleton,
                                                GDBusConnection *connection,
                                                bluez_adapter_t *adapter)