binding: bluetooth: add support for avrcp metadata reporting 97/9397/1
authorMatt Ranostay <matt.ranostay@konsulko.com>
Mon, 15 May 2017 19:59:55 +0000 (12:59 -0700)
committerMatt Ranostay <matt.ranostay@konsulko.com>
Tue, 16 May 2017 02:51:02 +0000 (19:51 -0700)
Add binding support for reporting avrcp metadata, and status events.

Bug-AGL: SPEC-596
Change-Id: I33a1045db5aa421a01e28c7bda254085b107e4f1
Signed-off-by: Matt Ranostay <matt.ranostay@konsulko.com>
binding-bluetooth/bluetooth-api.c
binding-bluetooth/bluetooth-api.h
binding-bluetooth/bluetooth-manager.c
binding-bluetooth/bluetooth-manager.h
binding-bluetooth/bluez-client.c

index 520d9e2..31d179a 100644 (file)
@@ -115,6 +115,65 @@ static int event_push(struct json_object *args, const char *tag)
        return e ? afb_event_push(e->event, json_object_get(args)) : -1;
 }
 
+static json_object *new_json_object_parse_avrcp(struct btd_device *BDdevice, unsigned int filter)
+{
+    json_object *jresp = json_object_new_object();
+    json_object *jstring = NULL;
+
+    if (BD_AVRCP_TITLE & filter)
+    {
+        if (BDdevice->avrcp_title)
+        {
+            jstring = json_object_new_string(BDdevice->avrcp_title);
+        }
+        else
+        {
+            jstring = json_object_new_string("");
+        }
+        json_object_object_add(jresp, "Title", jstring);
+    }
+
+    if (BD_AVRCP_ARTIST & filter)
+    {
+        if (BDdevice->avrcp_artist)
+        {
+            jstring = json_object_new_string(BDdevice->avrcp_artist);
+        }
+        else
+        {
+            jstring = json_object_new_string("");
+        }
+        json_object_object_add(jresp, "Artist", jstring);
+    }
+
+    if (BD_AVRCP_STATUS & filter)
+    {
+        if (BDdevice->avrcp_status)
+        {
+            jstring = json_object_new_string(BDdevice->avrcp_status);
+        }
+        else
+        {
+            jstring = json_object_new_string("");
+        }
+        json_object_object_add(jresp, "Status", jstring);
+    }
+
+    if (BD_AVRCP_DURATION & filter)
+    {
+        json_object_object_add(jresp, "Duration",
+                               json_object_new_int(BDdevice->avrcp_duration));
+    }
+
+    if (BD_AVRCP_POSITION & filter)
+    {
+        json_object_object_add(jresp, "Position",
+                               json_object_new_int(BDdevice->avrcp_position));
+    }
+
+    return jresp;
+}
+
 /* create device json object*/
 static json_object *new_json_object_from_device(struct btd_device *BDdevice, unsigned int filter)
 {
@@ -186,6 +245,12 @@ static json_object *new_json_object_from_device(struct btd_device *BDdevice, uns
         jstring = (TRUE == BDdevice->avconnected) ?
             json_object_new_string("True"):json_object_new_string("False");
         json_object_object_add(jresp, "AVPConnected", jstring);
+
+        if (BDdevice->avconnected)
+        {
+            jstring = new_json_object_parse_avrcp(BDdevice, filter);
+            json_object_object_add(jresp, "Metadata", jstring);
+        }
     }
 
     if (BD_HFPCONNECTED & filter)
@@ -638,7 +703,7 @@ void bt_broadcast_device_removed(struct btd_device *BDdevice)
 void bt_broadcast_device_properties_change(struct btd_device *BDdevice)
 {
 
-    unsigned int filter = BD_ADDER|BD_NAME|BD_PAIRED|BD_ACLCONNECTED|BD_AVCONNECTED|BD_HFPCONNECTED;
+    unsigned int filter = BD_ADDER|BD_NAME|BD_PAIRED|BD_ACLCONNECTED|BD_AVCONNECTED|BD_HFPCONNECTED|BD_AVRCP_TITLE|BD_AVRCP_ARTIST|BD_AVRCP_STATUS|BD_AVRCP_DURATION|BD_AVRCP_POSITION;
     int ret;
     json_object *jresp = new_json_object_from_device(BDdevice, filter);
 
index 07e1875..93629d9 100644 (file)
 #define BD_HFPCONNECTED LEFT_SHIFT(9)
 #define BD_LEGACYPAIRING LEFT_SHIFT(10)
 #define BD_RSSI LEFT_SHIFT(11)
+#define BD_AVRCP_TITLE LEFT_SHIFT(12)
+#define BD_AVRCP_ARTIST LEFT_SHIFT(13)
+#define BD_AVRCP_STATUS LEFT_SHIFT(14)
+#define BD_AVRCP_DURATION LEFT_SHIFT(15)
+#define BD_AVRCP_POSITION LEFT_SHIFT(16)
 
 
 /* -------------- PLUGIN DEFINITIONS ----------------- */
index b870e6f..a6c4472 100644 (file)
@@ -58,7 +58,7 @@ void devices_list_unlock(void)
 
 static int device_path_cmp(struct btd_device * device, const gchar* pPath )
 {
-    return g_strcmp0 (device->path, pPath);
+    return !g_str_has_prefix (pPath, device->path);
 }
 
 /*
@@ -255,7 +255,112 @@ static int device_update_from_MediaControl1(struct btd_device *device,
     return 0;
 }
 
+static int device_update_from_Track(struct btd_device *device,
+                                                     GVariant *value)
+{
+    GVariantIter iter;
+    const gchar *key;
+    GVariant *subValue;
+
+    if ((NULL==device) || (NULL==value))
+    {
+        return -1;
+    }
+
+    g_variant_iter_init (&iter, value);
+    while (g_variant_iter_next (&iter, "{&sv}", &key, &subValue))
+    {
+        //gchar *s = g_variant_print (subValue, TRUE);
+        //g_print ("  %s -> %s\n", key, s);
+        //g_free (s);
+
+        gboolean value_b  =  FALSE;//b gboolean
+        //gchar value_c = 0;
+        //guchar value_y  =  0;//y guchar
+        //gint16 value_n  =  0;//n gint16
+        //guint16 value_q  =  0;//q guint16
+        //gint32 value_i  =  0;//i gint32
+        guint32 value_u  =  0;//u guint32
+        //gint64 value_x  =  0;//x gint64
+        //guint64 value_t  =  0;//t guint64
+        //gint32 value_h  = 0;//h gint32
+        //gdouble value_d = 0.0;//d gdouble
+        gchar *str;//d gdouble
+
+        if (0==g_strcmp0(key,"Title")) {
+            g_variant_get(subValue, "s", &str);
+            D_PRINTF("Title %s\n", str);
+            if (device->avrcp_title)
+                free(device->avrcp_title);
+            device->avrcp_title = g_strdup(str);
+        } else if (0==g_strcmp0(key,"Artist")) {
+            g_variant_get(subValue, "s", &str);
+            D_PRINTF("Artist %s\n", str);
+            if (device->avrcp_artist)
+                free(device->avrcp_artist);
+            device->avrcp_artist = g_strdup(str);
+        } else if (0==g_strcmp0(key,"Duration")) {
+            g_variant_get(subValue, "u", &value_u);
+            D_PRINTF("Duration %u\n", value_u);
+            device->avrcp_duration = value_u;
+        }
+    }
+
+    return 0;
+}
+
+/*
+ * update device from Interface org.bluez.MediaPlayer1 properties
+ */
+static int device_update_from_MediaPlayer1(struct btd_device *device,
+                                                     GVariant *value)
+{
+    GVariantIter iter;
+    const gchar *key;
+    GVariant *subValue;
 
+    if ((NULL==device) || (NULL==value))
+    {
+        return -1;
+    }
+
+    g_variant_iter_init (&iter, value);
+    while (g_variant_iter_next (&iter, "{&sv}", &key, &subValue))
+    {
+        //gchar *s = g_variant_print (subValue, TRUE);
+        //g_print ("  %s -> %s\n", key, s);
+        //g_free (s);
+
+        gboolean value_b  =  FALSE;//b gboolean
+        //gchar value_c = 0;
+        //guchar value_y  =  0;//y guchar
+        //gint16 value_n  =  0;//n gint16
+        //guint16 value_q  =  0;//q guint16
+        //gint32 value_i  =  0;//i gint32
+        guint32 value_u  =  0;//u guint32
+        //gint64 value_x  =  0;//x gint64
+        //guint64 value_t  =  0;//t guint64
+        //gint32 value_h  = 0;//h gint32
+        //gdouble value_d = 0.0;//d gdouble
+        gchar *str;//d gdouble
+
+        if (0==g_strcmp0(key,"Status")) {
+            g_variant_get(subValue, "s", &str);
+            D_PRINTF("Status %s\n", str);
+            if (device->avrcp_status)
+                free(device->avrcp_status);
+            device->avrcp_status = g_strdup(str);
+        } else if (0==g_strcmp0(key,"Position")) {
+            g_variant_get(subValue, "u", &value_u);
+            D_PRINTF("Position %d\n", value_u);
+            device->avrcp_position = value_u;
+        } else if (0==g_strcmp0(key,"Track")) {
+            device_update_from_Track(device, subValue);
+        }
+    }
+
+    return 0;
+}
 
 /*
  * update device from Interfcace org.bluez.Device1 properties
@@ -556,6 +661,10 @@ bluez_device_properties_changed_cb (const gchar *pObjecPath,
 
         device_update_from_MediaControl1(device, properties);
 
+    } else if (0 == g_strcmp0(pInterface, MEDIA_PLAYER1_INTERFACE)) {
+
+        device_update_from_MediaPlayer1(device, properties);
+
     }
 
     if (g_RegisterCallback.binding_device_properties_changed)
index 896d213..4a86533 100644 (file)
@@ -88,6 +88,7 @@
 #define MAP_MSG_INTERFACE           "org.bluez.obex.Message"
 
 #define MEDIA_PLAYER_INTERFACE      "org.bluez.MediaPlayer"
+#define MEDIA_PLAYER1_INTERFACE     "org.bluez.MediaPlayer1"
 #define MEDIA_FOLDER_INTERFACE      "org.bluez.MediaFolder"
 #define MEDIA_ITEM_INTERFACE        "org.bluez.MediaItem"
 #define MEDIA_TRANSPORT_INTERFACE   "org.bluez.MediaTransport"
@@ -133,6 +134,11 @@ struct btd_device {
     gchar   *path;
     gchar   *bdaddr;
     gchar   *name;
+    gchar   *avrcp_title;
+    gchar   *avrcp_artist;
+    gchar   *avrcp_status;
+    guint32 avrcp_duration;
+    guint32 avrcp_position;
     gboolean    paired;
     gboolean    trusted;
     gboolean    connected;
index 3b97fef..e70df91 100644 (file)
@@ -594,6 +594,11 @@ static void on_object_removed (GDBusObjectManager *manager,
 
     dbusObjecPath = g_dbus_object_get_object_path (object);
 
+    if ((37 != strlen(dbusObjecPath))
+        || (NULL == g_strrstr_len(dbusObjecPath, 19,ADAPTER_PATH"/dev"))) {
+        return;
+    }
+
     if (NULL != bluez_RegisterCallback.device_removed)
     {
         bluez_RegisterCallback.device_removed(dbusObjecPath);
@@ -646,16 +651,12 @@ on_interface_proxy_properties_changed (GDBusObjectManagerClient *manager,
 #endif
 
     //ObjectPath is /org/bluez/hci0/dev_xx_xx_xx_xx_xx_xx
-    if ((37 != strlen(pObjecPath))
-        || (NULL == g_strrstr_len(pObjecPath, 19,
-                                  ADAPTER_PATH"/dev"))) {
-        return;
-    }
 
     LOGD("%s\n",pObjecPath);
 
     if( (0 == g_strcmp0(pInterface, DEVICE_INTERFACE)) ||
-        (0 == g_strcmp0(pInterface, MEDIA_CONTROL1_INTERFACE))) {
+        (0 == g_strcmp0(pInterface, MEDIA_CONTROL1_INTERFACE)) ||
+        (0 == g_strcmp0(pInterface, MEDIA_PLAYER1_INTERFACE))) {
 
         if (bluez_RegisterCallback.device_properties_changed)
             bluez_RegisterCallback.device_properties_changed(pObjecPath,