From 50092f916c339e4e2b3b133abd00560b8ace8283 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Mon, 15 May 2017 12:59:55 -0700 Subject: binding: bluetooth: add support for avrcp metadata reporting Add binding support for reporting avrcp metadata, and status events. Bug-AGL: SPEC-596 Change-Id: I33a1045db5aa421a01e28c7bda254085b107e4f1 Signed-off-by: Matt Ranostay --- bluetooth-api.c | 67 ++++++++++++++++++++++++++++++- bluetooth-api.h | 5 +++ bluetooth-manager.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++- bluetooth-manager.h | 6 +++ bluez-client.c | 13 +++--- 5 files changed, 194 insertions(+), 8 deletions(-) diff --git a/bluetooth-api.c b/bluetooth-api.c index 520d9e2..31d179a 100644 --- a/bluetooth-api.c +++ b/bluetooth-api.c @@ -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); diff --git a/bluetooth-api.h b/bluetooth-api.h index 07e1875..93629d9 100644 --- a/bluetooth-api.h +++ b/bluetooth-api.h @@ -33,6 +33,11 @@ #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 ----------------- */ diff --git a/bluetooth-manager.c b/bluetooth-manager.c index b870e6f..a6c4472 100644 --- a/bluetooth-manager.c +++ b/bluetooth-manager.c @@ -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) diff --git a/bluetooth-manager.h b/bluetooth-manager.h index 896d213..4a86533 100644 --- a/bluetooth-manager.h +++ b/bluetooth-manager.h @@ -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; diff --git a/bluez-client.c b/bluez-client.c index 3b97fef..e70df91 100644 --- a/bluez-client.c +++ b/bluez-client.c @@ -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, -- cgit 1.2.3-korg