From e4fd2dc5aa959ba430ee0038e4d135e1a7530ad4 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 20 Jun 2022 15:22:52 -0700 Subject: [PATCH] client/player: Enable acquiring multiple transports This enables acquiring multiple transports simultaneously. --- client/player.c | 216 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 145 insertions(+), 71 deletions(-) diff --git a/client/player.c b/client/player.c index c2c10e7e2..2ba05c43c 100644 --- a/client/player.c +++ b/client/player.c @@ -77,17 +77,16 @@ static GList *items = NULL; static GList *endpoints = NULL; static GList *local_endpoints = NULL; static GList *transports = NULL; +static struct queue *ios = NULL; struct transport { + GDBusProxy *proxy; int sk; - int mtu[2]; + uint16_t mtu[2]; char *filename; int fd; struct io *io; uint32_t seq; -} transport = { - .sk = -1, - .fd = -1, }; static void endpoint_unregister(void *data) @@ -2208,19 +2207,38 @@ static struct endpoint *find_ep_by_transport(const char *path) return NULL; } +static void transport_close(struct transport *transport) +{ + if (transport->fd < 0) + return; + + close(transport->fd); + free(transport->filename); +} + +static void transport_free(void *data) +{ + struct transport *transport = data; + + io_destroy(transport->io); + free(transport); +} + static bool transport_disconnected(struct io *io, void *user_data) { + struct transport *transport = user_data; + bt_shell_printf("Transport fd disconnected\n"); - io_destroy(transport.io); - transport.io = NULL; - transport.sk = -1; + if (queue_remove(ios, transport)) + transport_free(transport); return false; } static bool transport_recv(struct io *io, void *user_data) { + struct transport *transport = user_data; uint8_t buf[1024]; int ret, len; @@ -2231,12 +2249,12 @@ static bool transport_recv(struct io *io, void *user_data) return true; } - bt_shell_printf("[seq %d] recv: %u bytes\n", transport.seq, ret); + bt_shell_printf("[seq %d] recv: %u bytes\n", transport->seq, ret); - transport.seq++; + transport->seq++; - if (transport.fd) { - len = write(transport.fd, buf, ret); + if (transport->fd) { + len = write(transport->fd, buf, ret); if (len < 0) bt_shell_printf("Unable to write: %s (%d)", strerror(errno), -errno); @@ -2245,9 +2263,34 @@ static bool transport_recv(struct io *io, void *user_data) return true; } +static void transport_new(GDBusProxy *proxy, int sk, uint16_t mtu[2]) +{ + struct transport *transport; + + transport = new0(struct transport, 1); + transport->proxy = proxy; + transport->sk = sk; + transport->mtu[0] = mtu[0]; + transport->mtu[1] = mtu[1]; + transport->io = io_new(sk); + transport->fd = -1; + + io_set_disconnect_handler(transport->io, transport_disconnected, + transport, NULL); + io_set_read_handler(transport->io, transport_recv, transport, NULL); + + if (!ios) + ios = queue_new(); + + queue_push_tail(ios, transport); +} + static void acquire_reply(DBusMessage *message, void *user_data) { + GDBusProxy *proxy = user_data; DBusError error; + int sk; + uint16_t mtu[2]; dbus_error_init(&error); @@ -2258,9 +2301,9 @@ static void acquire_reply(DBusMessage *message, void *user_data) } if (!dbus_message_get_args(message, &error, - DBUS_TYPE_UNIX_FD, &transport.sk, - DBUS_TYPE_UINT16, &transport.mtu[0], - DBUS_TYPE_UINT16, &transport.mtu[1], + DBUS_TYPE_UNIX_FD, &sk, + DBUS_TYPE_UINT16, &mtu[0], + DBUS_TYPE_UINT16, &mtu[1], DBUS_TYPE_INVALID)) { bt_shell_printf("Failed to parse Acquire() reply: %s", error.name); @@ -2268,15 +2311,10 @@ static void acquire_reply(DBusMessage *message, void *user_data) return bt_shell_noninteractive_quit(EXIT_FAILURE); } - bt_shell_printf("Acquire successful: fd %d MTU %d:%d\n", transport.sk, - transport.mtu[0], transport.mtu[1]); + bt_shell_printf("Acquire successful: fd %d MTU %u:%u\n", sk, mtu[0], + mtu[1]); - io_destroy(transport.io); - transport.io = io_new(transport.sk); - - io_set_disconnect_handler(transport.io, transport_disconnected, NULL, - NULL); - io_set_read_handler(transport.io, transport_recv, NULL, NULL); + transport_new(proxy, sk, mtu); return bt_shell_noninteractive_quit(EXIT_FAILURE); } @@ -2287,7 +2325,7 @@ static void transport_acquire(const char *input, void *user_data) if (!strcasecmp(input, "y") || !strcasecmp(input, "yes")) { if (!g_dbus_proxy_method_call(proxy, "Acquire", NULL, - acquire_reply, NULL, NULL)) + acquire_reply, proxy, NULL)) bt_shell_printf("Failed acquire transport\n"); } } @@ -2320,7 +2358,7 @@ static void transport_property_changed(GDBusProxy *proxy, const char *name, if (ep->auto_accept) { bt_shell_printf("Auto Accepting...\n"); if (!g_dbus_proxy_method_call(proxy, "Acquire", NULL, - acquire_reply, NULL, NULL)) + acquire_reply, proxy, NULL)) bt_shell_printf("Failed acquire transport\n"); return; } @@ -2390,16 +2428,23 @@ static void cmd_show_transport(int argc, char *argv[]) return bt_shell_noninteractive_quit(EXIT_SUCCESS); } +static bool match_proxy(const void *data, const void *user_data) +{ + const struct transport *transport = data; + const GDBusProxy *proxy = user_data; + + return transport->proxy == proxy; +} + +static struct transport *find_transport(GDBusProxy *proxy) +{ + return queue_find(ios, match_proxy, proxy); +} + static void cmd_acquire_transport(int argc, char *argv[]) { GDBusProxy *proxy; - if (transport.sk >= 0) { - bt_shell_printf("Transport socked %d already acquired\n", - transport.sk); - return bt_shell_noninteractive_quit(EXIT_FAILURE); - } - proxy = g_dbus_proxy_lookup(transports, NULL, argv[1], BLUEZ_MEDIA_TRANSPORT_INTERFACE); if (!proxy) { @@ -2407,8 +2452,13 @@ static void cmd_acquire_transport(int argc, char *argv[]) return bt_shell_noninteractive_quit(EXIT_FAILURE); } + if (find_transport(proxy)) { + bt_shell_printf("Transport %s already acquired\n", argv[1]); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + if (!g_dbus_proxy_method_call(proxy, "Acquire", NULL, - acquire_reply, NULL, NULL)) { + acquire_reply, proxy, NULL)) { bt_shell_printf("Failed acquire transport\n"); return bt_shell_noninteractive_quit(EXIT_FAILURE); } @@ -2418,6 +2468,7 @@ static void cmd_acquire_transport(int argc, char *argv[]) static void release_reply(DBusMessage *message, void *user_data) { + struct transport *transport = user_data; DBusError error; dbus_error_init(&error); @@ -2428,8 +2479,8 @@ static void release_reply(DBusMessage *message, void *user_data) return bt_shell_noninteractive_quit(EXIT_FAILURE); } - close(transport.sk); - transport.sk = -1; + if (queue_remove(ios, transport)) + transport_free(transport); bt_shell_printf("Release successful\n"); @@ -2439,11 +2490,7 @@ static void release_reply(DBusMessage *message, void *user_data) static void cmd_release_transport(int argc, char *argv[]) { GDBusProxy *proxy; - - if (transport.sk < 0) { - bt_shell_printf("No Transport Socked found\n"); - return bt_shell_noninteractive_quit(EXIT_FAILURE); - } + struct transport *transport; proxy = g_dbus_proxy_lookup(transports, NULL, argv[1], BLUEZ_MEDIA_TRANSPORT_INTERFACE); @@ -2452,8 +2499,14 @@ static void cmd_release_transport(int argc, char *argv[]) return bt_shell_noninteractive_quit(EXIT_FAILURE); } + transport = find_transport(proxy); + if (!transport) { + bt_shell_printf("Transport %s not acquired\n", argv[1]); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + if (!g_dbus_proxy_method_call(proxy, "Release", NULL, - release_reply, NULL, NULL)) { + release_reply, transport, NULL)) { bt_shell_printf("Failed release transport\n"); return bt_shell_noninteractive_quit(EXIT_FAILURE); } @@ -2479,21 +2532,21 @@ static int open_file(const char *filename, int flags) return fd; } -static int transport_send(int fd) +static int transport_send(struct transport *transport, int fd) { uint8_t *buf; - buf = malloc(transport.mtu[1]); + buf = malloc(transport->mtu[1]); if (!buf) { bt_shell_printf("malloc: %s (%d)", strerror(errno), errno); return -ENOMEM; } - for (transport.seq = 0; ; transport.seq++) { + for (transport->seq = 0; ; transport->seq++) { ssize_t ret; int queued; - ret = read(fd, buf, transport.mtu[1]); + ret = read(fd, buf, transport->mtu[1]); if (ret <= 0) { if (ret < 0) bt_shell_printf("read failed: %s (%d)", @@ -2502,18 +2555,18 @@ static int transport_send(int fd) return ret; } - ret = send(transport.sk, buf, ret, 0); + ret = send(transport->sk, buf, ret, 0); if (ret <= 0) { bt_shell_printf("Send failed: %s (%d)", strerror(errno), errno); return -errno; } - ioctl(transport.sk, TIOCOUTQ, &queued); + ioctl(transport->sk, TIOCOUTQ, &queued); bt_shell_printf("[seq %d] send: %zd bytes " "(TIOCOUTQ %d bytes)\n", - transport.seq, ret, queued); + transport->seq, ret, queued); } free(buf); @@ -2521,17 +2574,33 @@ static int transport_send(int fd) static void cmd_send_transport(int argc, char *argv[]) { + GDBusProxy *proxy; + struct transport *transport; int fd, err; - if (transport.sk < 0) { + proxy = g_dbus_proxy_lookup(transports, NULL, argv[1], + BLUEZ_MEDIA_TRANSPORT_INTERFACE); + if (!proxy) { + bt_shell_printf("Transport %s not found\n", argv[1]); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + transport = find_transport(proxy); + if (!transport) { + bt_shell_printf("Transport %s not acquired\n", argv[1]); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + if (transport->sk < 0) { bt_shell_printf("No Transport Socked found\n"); return bt_shell_noninteractive_quit(EXIT_FAILURE); } - fd = open_file(argv[1], O_RDONLY); + fd = open_file(argv[2], O_RDONLY); bt_shell_printf("Sending ...\n"); - err = transport_send(fd); + + err = transport_send(transport, fd); close(fd); @@ -2541,34 +2610,39 @@ static void cmd_send_transport(int argc, char *argv[]) return bt_shell_noninteractive_quit(EXIT_SUCCESS); } -static void transport_close(void) -{ - if (transport.fd < 0) - return; - - close(transport.fd); - transport.fd = -1; - - free(transport.filename); - transport.filename = NULL; -} static void cmd_receive_transport(int argc, char *argv[]) { - if (argc == 1) { - bt_shell_printf("Filename: %s\n", transport.filename); - return bt_shell_noninteractive_quit(EXIT_SUCCESS); + GDBusProxy *proxy; + struct transport *transport; + + proxy = g_dbus_proxy_lookup(transports, NULL, argv[1], + BLUEZ_MEDIA_TRANSPORT_INTERFACE); + if (!proxy) { + bt_shell_printf("Transport %s not found\n", argv[1]); + return bt_shell_noninteractive_quit(EXIT_FAILURE); } - transport_close(); + transport = find_transport(proxy); + if (!transport) { + bt_shell_printf("Transport %s not acquired\n", argv[1]); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } - transport.fd = open_file(argv[1], O_RDWR | O_CREAT); - if (transport.fd < 0) + if (transport->sk < 0) { + bt_shell_printf("No Transport Socked found\n"); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + transport_close(transport); + + transport->fd = open_file(argv[2], O_RDWR | O_CREAT); + if (transport->fd < 0) return bt_shell_noninteractive_quit(EXIT_FAILURE); - transport.filename = strdup(argv[1]); + transport->filename = strdup(argv[2]); - bt_shell_printf("Filename: %s\n", transport.filename); + bt_shell_printf("Filename: %s\n", transport->filename); return bt_shell_noninteractive_quit(EXIT_SUCCESS); } @@ -2633,9 +2707,9 @@ static const struct bt_shell_menu transport_menu = { { "release", "", cmd_release_transport, "Release Transport", transport_generator }, - { "send", "", cmd_send_transport, + { "send", " ", cmd_send_transport, "Send contents of a file" }, - { "receive", "[filename]", cmd_receive_transport, + { "receive", " [filename]", cmd_receive_transport, "Get/Set file to receive" }, { "volume", " [value]", cmd_volume_transport, "Get/Set transport volume", @@ -2665,5 +2739,5 @@ void player_add_submenu(void) void player_remove_submenu(void) { g_dbus_client_unref(client); - transport_close(); + queue_destroy(ios, transport_free); }