[PATCH BlueZ] client/player: Add codec as parameter to endpoint.presets

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>

This changes endpoint.presets command to take codec as parameter.
---
 client/player.c | 240 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 175 insertions(+), 65 deletions(-)

diff --git a/client/player.c b/client/player.c
index 58e14654ffb0..a9f56fb94b9b 100644
--- a/client/player.c
+++ b/client/player.c
@@ -78,6 +78,7 @@ struct endpoint {
 	uint8_t cis;
 	char *transport;
 	DBusMessage *msg;
+	struct preset *preset;
 };
 
 static DBusConnection *dbus_conn;
@@ -1166,7 +1167,7 @@ struct codec_qos {
 };
 
 struct codec_preset {
-	const char *name;
+	char *name;
 	const struct iovec data;
 	const struct codec_qos qos;
 	uint8_t target_latency;
@@ -1410,9 +1411,10 @@ static struct codec_preset lc3_presets[] = {
 			LC3_10_UNFRAMED(155u, 13u, 100u, 40000u)),
 };
 
-#define PRESET(_uuid, _presets, _default_index) \
+#define PRESET(_uuid, _codec, _presets, _default_index) \
 	{ \
 		.uuid = _uuid, \
+		.codec = _codec, \
 		.custom = { .name = "custom" }, \
 		.default_preset = &_presets[_default_index], \
 		.presets = _presets, \
@@ -1421,46 +1423,142 @@ static struct codec_preset lc3_presets[] = {
 
 static struct preset {
 	const char *uuid;
+	uint8_t codec;
+	uint16_t cid;
+	uint16_t vid;
 	struct codec_preset custom;
 	struct codec_preset *default_preset;
 	struct codec_preset *presets;
 	size_t num_presets;
 } presets[] = {
-	PRESET(A2DP_SOURCE_UUID, sbc_presets, 6),
-	PRESET(A2DP_SINK_UUID, sbc_presets, 6),
-	PRESET(PAC_SINK_UUID, lc3_presets, 3),
-	PRESET(PAC_SOURCE_UUID, lc3_presets, 3),
+	PRESET(A2DP_SOURCE_UUID, A2DP_CODEC_SBC, sbc_presets, 6),
+	PRESET(A2DP_SINK_UUID, A2DP_CODEC_SBC, sbc_presets, 6),
+	PRESET(PAC_SINK_UUID, LC3_ID, lc3_presets, 3),
+	PRESET(PAC_SOURCE_UUID, LC3_ID, lc3_presets, 3),
 };
 
-static struct codec_preset *find_preset(const char *uuid, const char *name)
+static void parse_vendor_codec(const char *codec, uint16_t *vid, uint16_t *cid)
+{
+	char **list;
+	char *endptr = NULL;
+
+	if (!codec)
+		return;
+
+	list = g_strsplit(codec, ":", 2);
+
+	if (vid)
+		*vid = strtol(list[0], &endptr, 0);
+
+	if (cid)
+		*cid = strtol(list[1], &endptr, 0);
+
+	g_strfreev(list);
+}
+
+static struct preset *find_presets(const char *uuid, uint8_t codec,
+					uint16_t vid, uint16_t cid)
 {
 	size_t i;
 
+	if (codec == 0xff) {
+		GList *l;
+
+		for (l = local_endpoints; l; l = g_list_next(l)) {
+			struct endpoint *ep = l->data;
+
+			if (strcasecmp(ep->uuid, uuid) || ep->codec != codec)
+				continue;
+
+			if (ep->codec == 0xff && (ep->vid != vid ||
+							ep->cid != cid))
+				continue;
+
+			return ep->preset;
+		}
+
+		return NULL;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(presets); i++) {
 		struct preset *preset = &presets[i];
 
-		if (!strcasecmp(preset->uuid, uuid)) {
-			size_t j;
+		if (preset->codec != codec)
+			continue;
 
-			if (!name)
-				return preset->default_preset;
-			else if (!strcmp(name, "custom"))
-				return &preset->custom;
-
-			for (j = 0; j < preset->num_presets; j++) {
-				struct codec_preset *p;
-
-				p = &preset->presets[j];
-
-				if (!strcmp(p->name, name))
-					return p;
-			}
-		}
+		if (!strcasecmp(preset->uuid, uuid))
+			return preset;
 	}
 
 	return NULL;
 }
 
+static struct preset *find_vendor_presets(const char *uuid, const char *codec)
+{
+	uint16_t cid;
+	uint16_t vid;
+
+	if (!uuid || !codec)
+		return NULL;
+
+	parse_vendor_codec(codec, &vid, &cid);
+
+	return find_presets(uuid, 0xff, vid, cid);
+}
+
+static struct preset *find_presets_name(const char *uuid, const char *codec)
+{
+	uint8_t id;
+	char *endptr = NULL;
+
+	if (!uuid || !codec)
+		return NULL;
+
+	if (strrchr(codec, ':'))
+		return find_vendor_presets(uuid, codec);
+
+	id = strtol(codec, &endptr, 0);
+
+	return find_presets(uuid, id, 0x0000, 0x0000);
+}
+
+static struct codec_preset *preset_find_name(struct preset *preset,
+						const char *name)
+{
+	size_t i;
+
+	if (!preset)
+		return NULL;
+
+	if (!name)
+		return preset->default_preset;
+	else if (!strcmp(name, "custom"))
+		return &preset->custom;
+
+	for (i = 0; i < preset->num_presets; i++) {
+		struct codec_preset *p;
+
+		p = &preset->presets[i];
+
+		if (!strcmp(p->name, name))
+			return p;
+	}
+
+	return NULL;
+}
+
+static struct codec_preset *find_preset(const char *uuid, const char *codec,
+					const char *name)
+{
+	struct preset *preset;
+
+	preset = find_presets_name(uuid, codec);
+	if (!preset)
+		return NULL;
+
+	return preset_find_name(preset, name);
+}
+
 static DBusMessage *endpoint_select_config_reply(DBusMessage *msg,
 						 uint8_t *data, size_t len)
 {
@@ -1525,7 +1623,7 @@ static void select_config_response(const char *input, void *user_data)
 	uint8_t *data;
 	size_t len;
 
-	p = find_preset(ep->uuid, input);
+	p = preset_find_name(ep->preset, input);
 	if (p) {
 		data = p->data.iov_base;
 		len = p->data.iov_len;
@@ -1580,7 +1678,7 @@ static DBusMessage *endpoint_select_configuration(DBusConnection *conn,
 		return NULL;
 	}
 
-	p = find_preset(ep->uuid, NULL);
+	p = preset_find_name(ep->preset, NULL);
 	if (!p) {
 		reply = g_dbus_create_error(msg, "org.bluez.Error.Rejected",
 								NULL);
@@ -1755,7 +1853,7 @@ static void select_properties_response(const char *input, void *user_data)
 	struct codec_preset *p;
 	DBusMessage *reply;
 
-	p = find_preset(ep->uuid, input);
+	p = preset_find_name(ep->preset, input);
 	if (p) {
 		reply = endpoint_select_properties_reply(ep, ep->msg, p);
 		goto done;
@@ -1797,9 +1895,9 @@ static DBusMessage *endpoint_select_properties(DBusConnection *conn,
 		return NULL;
 	}
 
-	p = find_preset(ep->uuid, NULL);
+	p = preset_find_name(ep->preset, NULL);
 	if (!p)
-		NULL;
+		return NULL;
 
 	reply = endpoint_select_properties_reply(ep, msg, p);
 	if (!reply)
@@ -1903,6 +2001,11 @@ static void endpoint_free(void *data)
 	if (ep->msg)
 		dbus_message_unref(ep->msg);
 
+	if (ep->codec == 0xff) {
+		free(ep->preset->custom.name);
+		free(ep->preset);
+	}
+
 	g_free(ep->path);
 	g_free(ep->uuid);
 	g_free(ep);
@@ -2312,7 +2415,6 @@ static void cmd_register_endpoint(int argc, char *argv[])
 {
 	struct endpoint *ep;
 	char *endptr = NULL;
-	char **list;
 
 	ep = g_new0(struct endpoint, 1);
 	ep->uuid = g_strdup(argv[1]);
@@ -2324,12 +2426,13 @@ static void cmd_register_endpoint(int argc, char *argv[])
 	local_endpoints = g_list_append(local_endpoints, ep);
 
 	if (strrchr(argv[2], ':')) {
-		list = g_strsplit(argv[2], ":", 2);
-
 		ep->codec = 0xff;
-		ep->vid = strtol(list[0], &endptr, 0);
-		endptr = NULL;
-		ep->cid = strtol(list[1], &endptr, 0);
+		parse_vendor_codec(argv[2], &ep->cid, &ep->vid);
+		ep->preset = new0(struct preset, 1);
+		ep->preset->custom.name = strdup("custom");
+		ep->preset->default_preset = &ep->preset->custom;
+	} else {
+		ep->preset = find_presets_name(ep->uuid, argv[2]);
 	}
 
 	if (argc > 3)
@@ -2489,7 +2592,7 @@ static void cmd_config_endpoint(int argc, char *argv[])
 	}
 
 	if (argc > 3) {
-		preset = find_preset(cfg->ep->uuid, argv[3]);
+		preset = preset_find_name(cfg->ep->preset, argv[3]);
 		if (!preset) {
 			bt_shell_printf("Preset %s not found\n", argv[3]);
 			goto fail;
@@ -2835,46 +2938,50 @@ static void custom_frequency(const char *input, void *user_data)
 				custom_duration, user_data);
 }
 
-static void cmd_presets_endpoint(int argc, char *argv[])
+static void print_presets(struct preset *preset)
 {
 	size_t i;
+	struct codec_preset *p;
+
+	p = &preset->custom;
+
+	bt_shell_printf("%s%s\n", p == preset->default_preset ? "*" : "",
+								p->name);
+
+	for (i = 0; i < preset->num_presets; i++) {
+		p = &preset->presets[i];
+		bt_shell_printf("%s%s\n", p == preset->default_preset ?
+						"*" : "", p->name);
+	}
+}
+
+static void cmd_presets_endpoint(int argc, char *argv[])
+{
+	struct preset *preset;
 	struct codec_preset *default_preset = NULL;
 
-	if (argc > 2) {
-		default_preset = find_preset(argv[1], argv[2]);
+	if (argc > 3) {
+		default_preset = find_preset(argv[1], argv[2], argv[3]);
 		if (!default_preset) {
-			bt_shell_printf("Preset %s not found\n", argv[2]);
+			bt_shell_printf("Preset %s not found\n", argv[3]);
 			return bt_shell_noninteractive_quit(EXIT_FAILURE);
 		}
 	}
 
-	for (i = 0; i < ARRAY_SIZE(presets); i++) {
-		struct preset *preset = &presets[i];
-
-		if (!strcasecmp(preset->uuid, argv[1])) {
-			size_t j;
-			struct codec_preset *p;
-
-			if (default_preset) {
-				preset->default_preset = default_preset;
-				break;
-			}
-
-			p = &preset->custom;
-
-			bt_shell_printf("%s%s\n", p == preset->default_preset ?
-						"*" : "", p->name);
-
-			for (j = 0; j < preset->num_presets; j++) {
-				p = &preset->presets[j];
-
-				bt_shell_printf("%s%s\n",
-						p == preset->default_preset ?
-						"*" : "", p->name);
-			}
-		}
+	preset = find_presets_name(argv[1], argv[2]);
+	if (!preset) {
+		bt_shell_printf("No preset found\n");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
+	if (default_preset) {
+		preset->default_preset = default_preset;
+		goto done;
+	}
+
+	print_presets(preset);
+
+done:
 	if (default_preset && !strcmp(default_preset->name, "custom")) {
 		bt_shell_prompt_input("Codec", "Enter frequency (Khz):",
 					custom_frequency, default_preset);
@@ -2904,7 +3011,8 @@ static const struct bt_shell_menu endpoint_menu = {
 						cmd_config_endpoint,
 						"Configure Endpoint",
 						endpoint_generator },
-	{ "presets",      "<UUID> [default]", cmd_presets_endpoint,
+	{ "presets",      "<UUID> <codec[:company]> [default]",
+						cmd_presets_endpoint,
 						"List available presets",
 						uuid_generator },
 	{} },
@@ -2938,6 +3046,8 @@ static void register_endpoints(GDBusProxy *proxy)
 			continue;
 
 		ep = endpoint_new(cap);
+		ep->preset = find_presets(ep->uuid, ep->codec, ep->vid,
+								ep->cid);
 		ep->max_transports = UINT8_MAX;
 		ep->auto_accept = true;
 		ep->cig = BT_ISO_QOS_CIG_UNSET;
-- 
2.40.0




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux