diff --git a/client/player.c b/client/player.c
index f93c9d9..464a9cc 100644
--- a/client/player.c
+++ b/client/player.c
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;
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;
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);
static void select_reply(DBusMessage *message, void *user_data)
{
DBusError error;
+ struct endpoint *ep = user_data;
dbus_error_init(&error);
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)
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)
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);
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)
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",
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++) {
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[])