Diff between e83d3021e1308a0ad3a84df0cf49b71ee1b1a7c6 and d3018fe2dc589dd0ac1e3d3ef45e40106769f579

Changed Files

File Additions Deletions Status
client/player.c +127 -32 modified

Full Patch

diff --git a/client/player.c b/client/player.c
index f93c9d9..464a9cc 100644
--- a/client/player.c
+++ b/client/player.c
@@ -115,6 +115,8 @@ struct endpoint {
 	uint8_t iso_group;
 	uint8_t iso_stream;
 	struct queue *acquiring;
+	struct queue *links;
+	struct queue *selecting;
 	struct queue *transports;
 	DBusMessage *msg;
 	struct preset *preset;
@@ -148,6 +150,9 @@ struct transport {
 	int num;
 };
 
+static void transport_set_links(struct endpoint *ep, GDBusProxy *proxy);
+static void transport_select(GDBusProxy *proxy);
+
 static void endpoint_unregister(void *data)
 {
 	struct endpoint *ep = data;
@@ -2918,6 +2923,8 @@ static void endpoint_free(void *data)
 		free(ep->preset);
 
 	queue_destroy(ep->acquiring, NULL);
+	queue_destroy(ep->links, NULL);
+	queue_destroy(ep->selecting, NULL);
 	queue_destroy(ep->transports, free);
 
 	g_free(ep->path);
@@ -4887,6 +4894,7 @@ static void acquire_reply(DBusMessage *message, void *user_data)
 static void select_reply(DBusMessage *message, void *user_data)
 {
 	DBusError error;
+	struct endpoint *ep = user_data;
 
 	dbus_error_init(&error);
 
@@ -4898,7 +4906,13 @@ static void select_reply(DBusMessage *message, void *user_data)
 
 	bt_shell_printf("Select successful\n");
 
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	if (queue_isempty(ep->selecting)) {
+		/* All links have been selected */
+		queue_destroy(ep->selecting, NULL);
+		ep->selecting = NULL;
+
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	}
 }
 
 static void unselect_reply(DBusMessage *message, void *user_data)
@@ -5170,9 +5184,7 @@ static void set_bcode_cb(const DBusError *error, void *user_data)
 
 	bt_shell_printf("Setting broadcast code succeeded\n");
 
-	if (!g_dbus_proxy_method_call(proxy, "Select", NULL,
-				select_reply, proxy, NULL))
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	transport_select(proxy);
 }
 
 static void set_bcode(const char *input, void *user_data)
@@ -5197,15 +5209,35 @@ static void set_bcode(const char *input, void *user_data)
 	g_free(bcode);
 }
 
-static void transport_select(void *data, void *user_data)
+static void transport_select(GDBusProxy *proxy)
+{
+	struct endpoint *ep;
+	GDBusProxy *link;
+
+	ep = find_ep_by_transport(g_dbus_proxy_get_path(proxy));
+	if (!ep)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	if (!g_dbus_proxy_method_call(proxy, "Select", NULL,
+					select_reply, ep, NULL)) {
+		bt_shell_printf("Failed select transport\n");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	/* Select next link */
+	link = queue_pop_head(ep->selecting);
+	if (link)
+		transport_select(link);
+}
+
+static void transport_set_bcode(GDBusProxy *proxy)
 {
-	GDBusProxy *proxy = data;
 	DBusMessageIter iter, array, entry, value;
 	unsigned char encryption;
 	const char *key;
 
 	if (g_dbus_proxy_get_property(proxy, "QoS", &iter) == FALSE)
-		return;
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 
 	dbus_message_iter_recurse(&iter, &array);
 
@@ -5229,11 +5261,10 @@ static void transport_select(void *data, void *user_data)
 		dbus_message_iter_next(&array);
 	}
 
-	if (!g_dbus_proxy_method_call(proxy, "Select", NULL,
-					select_reply, proxy, NULL)) {
-		bt_shell_printf("Failed select transport\n");
-		return;
-	}
+	/* Go straight to selecting transport, if Broadcast Code
+	 * is not required.
+	 */
+	transport_select(proxy);
 }
 
 static void transport_unselect(GDBusProxy *proxy, bool prompt)
@@ -5247,7 +5278,23 @@ static void transport_unselect(GDBusProxy *proxy, bool prompt)
 
 static void set_links_cb(const DBusError *error, void *user_data)
 {
-	GDBusProxy *link = user_data;
+	GDBusProxy *proxy = user_data;
+	const char *path = g_dbus_proxy_get_path(proxy);
+	struct endpoint *ep;
+	GDBusProxy *link;
+
+	ep = find_ep_by_transport(path);
+	if (!ep) {
+		bt_shell_printf("Local endpoint not found\n");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	link = queue_pop_head(ep->links);
+
+	if (queue_isempty(ep->links)) {
+		queue_destroy(ep->links, NULL);
+		ep->links = NULL;
+	}
 
 	if (dbus_error_is_set(error)) {
 		bt_shell_printf("Failed to set link %s: %s\n",
@@ -5258,13 +5305,60 @@ static void set_links_cb(const DBusError *error, void *user_data)
 
 	bt_shell_printf("Successfully linked transport %s\n",
 						g_dbus_proxy_get_path(link));
+
+	if (!ep->selecting)
+		ep->selecting = queue_new();
+
+	/* Enqueue link to mark that it is ready to be selected */
+	queue_push_tail(ep->selecting, link);
+
+	/* Continue setting the remanining links */
+	transport_set_links(ep, proxy);
+}
+
+static void transport_set_links(struct endpoint *ep, GDBusProxy *proxy)
+{
+	GDBusProxy *link;
+	const char *path;
+
+	link = queue_peek_head(ep->links);
+	if (link) {
+		path = g_dbus_proxy_get_path(link);
+
+		if (g_dbus_proxy_set_property_array(proxy, "Links",
+					DBUS_TYPE_OBJECT_PATH,
+					&path, 1, set_links_cb,
+					proxy, NULL) == FALSE) {
+			bt_shell_printf("Linking transport %s failed\n", path);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		return;
+	}
+
+	/* If all links have been set, check is transport requires the
+	 * user to provide a Broadcast Code.
+	 */
+	transport_set_bcode(proxy);
+}
+
+static void endpoint_set_links(struct endpoint *ep)
+{
+	GDBusProxy *proxy = queue_pop_head(ep->links);
+
+	if (!proxy) {
+		bt_shell_printf("No transport to set links for\n");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	transport_set_links(ep, proxy);
 }
 
 static void cmd_select_transport(int argc, char *argv[])
 {
-	GDBusProxy *proxy = NULL, *link;
+	GDBusProxy *link = NULL;
 	struct queue *links = queue_new();
-	const char *path;
+	struct endpoint *ep;
 	int i;
 
 	for (i = 1; i < argc; i++) {
@@ -5272,35 +5366,36 @@ static void cmd_select_transport(int argc, char *argv[])
 					BLUEZ_MEDIA_TRANSPORT_INTERFACE);
 		if (!link) {
 			bt_shell_printf("Transport %s not found\n", argv[i]);
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+			goto fail;
 		}
 
 		if (find_transport(link)) {
 			bt_shell_printf("Transport %s already acquired\n",
 					argv[i]);
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+			goto fail;
 		}
 
+		/* Enqueue all links */
 		queue_push_tail(links, link);
+	}
 
-		if (!proxy) {
-			proxy = link;
-			continue;
-		}
+	/* Get reference to local endpoint */
+	ep = find_ep_by_transport(g_dbus_proxy_get_path(link));
+	if (!ep) {
+		bt_shell_printf("Local endpoint not found\n");
+		goto fail;
+	}
 
-		path = g_dbus_proxy_get_path(link);
+	ep->links = links;
 
-		if (g_dbus_proxy_set_property_array(proxy, "Links",
-					DBUS_TYPE_OBJECT_PATH,
-					&path, 1, set_links_cb,
-					link, NULL) == FALSE) {
-			bt_shell_printf("Linking transport %s failed\n",
-								argv[i]);
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
+	/* Link streams before selecting one by one */
+	endpoint_set_links(ep);
+
+	return;
 
-	queue_foreach(links, transport_select, NULL);
+fail:
+	queue_destroy(links, NULL);
+	return bt_shell_noninteractive_quit(EXIT_FAILURE);
 }
 
 static void cmd_unselect_transport(int argc, char *argv[])