From 42ffa662d6e72e5fb5ce31759728adf53f5f7cff Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 24 Nov 2017 15:26:21 +0200 Subject: [PATCH] avrcp: Fix change-path AVRCP spec does allow duplicates folder names which would be exposed as different D-Bus path as their UID is different, the code however would attempt to set the folder by its name alone which resolve to the first item on the list rather then the exact UID. --- profiles/audio/avrcp.c | 7 ++- profiles/audio/player.c | 103 ++++++++++++++++++++++++---------------- profiles/audio/player.h | 3 +- 3 files changed, 71 insertions(+), 42 deletions(-) diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c index f440becb6..d5eba3964 100644 --- a/profiles/audio/avrcp.c +++ b/profiles/audio/avrcp.c @@ -245,6 +245,7 @@ struct avrcp_player { struct pending_list_items *p; char *change_path; + uint64_t change_uid; struct avrcp_player_cb *cb; void *user_data; @@ -2617,7 +2618,10 @@ done: player->change_path = NULL; } - media_player_change_folder_complete(mp, player->path, ret); + media_player_change_folder_complete(mp, player->path, + player->change_uid, ret); + + player->change_uid = 0; return FALSE; } @@ -3026,6 +3030,7 @@ static int ct_change_folder(struct media_player *mp, const char *path, session = player->sessions->data; set_ct_player(session, player); player->change_path = g_strdup(path); + player->change_uid = uid; direction = g_str_has_prefix(path, player->path) ? 0x01 : 0x00; diff --git a/profiles/audio/player.c b/profiles/audio/player.c index e499e6757..048f98f96 100644 --- a/profiles/audio/player.c +++ b/profiles/audio/player.c @@ -587,30 +587,6 @@ static void parse_folder_list(gpointer data, gpointer user_data) dbus_message_iter_close_container(array, &entry); } -void media_player_change_folder_complete(struct media_player *mp, - const char *path, int ret) -{ - struct media_folder *folder = mp->scope; - DBusMessage *reply; - - if (folder == NULL || folder->msg == NULL) - return; - - if (ret < 0) { - reply = btd_error_failed(folder->msg, strerror(-ret)); - goto done; - } - - media_player_set_folder(mp, path, ret); - - reply = g_dbus_create_reply(folder->msg, DBUS_TYPE_INVALID); - -done: - g_dbus_send_message(btd_get_dbus_connection(), reply); - dbus_message_unref(folder->msg); - folder->msg = NULL; -} - void media_player_list_complete(struct media_player *mp, GSList *items, int err) { @@ -1127,6 +1103,69 @@ static void media_player_set_scope(struct media_player *mp, return media_player_change_scope(mp, folder); } +static struct media_folder * +media_player_find_folder_by_uid(struct media_player *mp, uint64_t uid) +{ + struct media_folder *folder = mp->scope; + struct media_folder *parent = folder->parent; + GSList *l; + + if (parent && parent->item->uid == uid) + return parent; + + for (l = folder->subfolders; l; l = l->next) { + struct media_folder *folder = l->data; + + if (folder->item->uid == uid) + return folder; + } + + return NULL; +} + +static void media_player_set_folder_by_uid(struct media_player *mp, + uint64_t uid, uint32_t number_of_items) +{ + struct media_folder *folder; + + DBG("uid %" PRIu64 " number of items %u", uid, number_of_items); + + folder = media_player_find_folder_by_uid(mp, uid); + if (folder == NULL) { + error("Unknown folder: %" PRIu64, uid); + return; + } + + folder->number_of_items = number_of_items; + + media_player_set_scope(mp, folder); +} + +void media_player_change_folder_complete(struct media_player *mp, + const char *path, uint64_t uid, + int ret) +{ + struct media_folder *folder = mp->scope; + DBusMessage *reply; + + if (folder == NULL || folder->msg == NULL) + return; + + if (ret < 0) { + reply = btd_error_failed(folder->msg, strerror(-ret)); + goto done; + } + + media_player_set_folder_by_uid(mp, uid, ret); + + reply = g_dbus_create_reply(folder->msg, DBUS_TYPE_INVALID); + +done: + g_dbus_send_message(btd_get_dbus_connection(), reply); + dbus_message_unref(folder->msg); + folder->msg = NULL; +} + void media_player_destroy(struct media_player *mp) { DBG("%s", mp->path); @@ -1801,22 +1840,6 @@ struct media_item *media_player_create_item(struct media_player *mp, return media_folder_create_item(mp, mp->scope, name, type, uid); } -static struct media_folder * -media_player_find_folder_by_uid(struct media_player *mp, uint64_t uid) -{ - struct media_folder *folder = mp->scope; - GSList *l; - - for (l = folder->subfolders; l; l = l->next) { - struct media_folder *folder = l->data; - - if (folder->item->uid == uid) - return folder; - } - - return NULL; -} - struct media_item *media_player_create_folder(struct media_player *mp, const char *name, player_folder_type_t type, diff --git a/profiles/audio/player.h b/profiles/audio/player.h index a7c7d2a0d..536394ca6 100644 --- a/profiles/audio/player.h +++ b/profiles/audio/player.h @@ -107,7 +107,8 @@ void media_item_set_playable(struct media_item *item, bool value); void media_player_list_complete(struct media_player *mp, GSList *items, int err); void media_player_change_folder_complete(struct media_player *player, - const char *path, int ret); + const char *path, uint64_t uid, + int ret); void media_player_search_complete(struct media_player *mp, int ret); void media_player_total_items_complete(struct media_player *mp, uint32_t num_of_items); -- 2.47.3