From a532c2abdb85a098b6fd4d6f8be5b8c1ee8199bd Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 30 Nov 2023 17:40:48 +0100 Subject: [PATCH] acp: add support for hiding profiles and ports api.acp.hidden-ports and api.acp.hidden-profiles can be used to pass a json array of ports and profiles to hide. They will not show and will not be selectable. --- spa/plugins/alsa/acp/acp.c | 38 +++++++++++++++++++++++++++++- spa/plugins/alsa/acp/acp.h | 3 +++ spa/plugins/alsa/alsa-acp-device.c | 13 +++++++++- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/spa/plugins/alsa/acp/acp.c b/spa/plugins/alsa/acp/acp.c index 98f6326d1..95ef745c0 100644 --- a/spa/plugins/alsa/acp/acp.c +++ b/spa/plugins/alsa/acp/acp.c @@ -7,6 +7,7 @@ #include "alsa-ucm.h" #include +#include int _acp_log_level = 1; acp_log_func _acp_log_func; @@ -449,6 +450,24 @@ static int add_pro_profile(pa_card *impl, uint32_t index) return 0; } +static bool contains_string(const char *arr, const char *str) +{ + struct spa_json it[2]; + char v[256]; + + if (arr == NULL || str == NULL) + return false; + + spa_json_init(&it[0], arr, strlen(arr)); + if (spa_json_enter_array(&it[0], &it[1]) <= 0) + spa_json_init(&it[1], arr, strlen(arr)); + + while (spa_json_get_string(&it[1], v, sizeof(v)) > 0) { + if (spa_streq(v, str)) + return true; + } + return false; +} static void add_profiles(pa_card *impl) { @@ -459,6 +478,7 @@ static void add_profiles(pa_card *impl) pa_alsa_device *dev; int n_profiles, n_ports, n_devices; uint32_t idx; + const char *arr; n_devices = 0; pa_dynarray_init(&impl->out.devices, device_free); @@ -561,7 +581,10 @@ static void add_profiles(pa_card *impl) dev->device.ports = dev->port_array.array.data; dev->device.n_ports = pa_dynarray_size(&dev->port_array); } + arr = pa_proplist_gets(impl->proplist, "api.acp.hidden-ports"); PA_HASHMAP_FOREACH(dp, impl->ports, state) { + if (contains_string(arr, dp->name)) + dp->port.flags |= ACP_PORT_HIDDEN; dp->port.devices = dp->devices.array.data; dp->port.n_devices = pa_dynarray_size(&dp->devices); } @@ -570,7 +593,10 @@ static void add_profiles(pa_card *impl) n_profiles = 0; pa_dynarray_init(&impl->out.profiles, NULL); + arr = pa_proplist_gets(impl->proplist, "api.acp.hidden-profiles"); PA_HASHMAP_FOREACH(cp, impl->profiles, state) { + if (contains_string(arr, cp->name)) + cp->flags |= ACP_PROFILE_HIDDEN; cp->index = n_profiles++; pa_dynarray_append(&impl->out.profiles, cp); } @@ -1021,6 +1047,9 @@ uint32_t acp_card_find_best_profile_index(struct acp_card *card, const char *nam for (i = 0; i < card->n_profiles; i++) { struct acp_card_profile *p = profiles[i]; + if (SPA_FLAG_IS_SET(p->flags, ACP_PROFILE_HIDDEN)) + continue; + if (name) { if (spa_streq(name, p->name)) best = i; @@ -1440,9 +1469,11 @@ int acp_card_set_profile(struct acp_card *card, uint32_t new_index, uint32_t fla if (new_index >= card->n_profiles) return -EINVAL; - op = old_index != ACP_INVALID_INDEX ? (pa_alsa_profile*)profiles[old_index] : NULL; np = (pa_alsa_profile*)profiles[new_index]; + if (SPA_FLAG_IS_SET(np->profile.flags, ACP_PROFILE_HIDDEN)) + return -EINVAL; + op = old_index != ACP_INVALID_INDEX ? (pa_alsa_profile*)profiles[old_index] : NULL; if (op == np) return 0; @@ -1830,6 +1861,9 @@ uint32_t acp_device_find_best_port_index(struct acp_device *dev, const char *nam for (i = 0; i < dev->n_ports; i++) { struct acp_port *p = ports[i]; + if (SPA_FLAG_IS_SET(p->flags, ACP_PORT_HIDDEN)) + continue; + if (name) { if (spa_streq(name, p->name)) best = i; @@ -1869,6 +1903,8 @@ int acp_device_set_port(struct acp_device *dev, uint32_t port_index, uint32_t fl p = (pa_device_port*)impl->card.ports[port_index]; if (!pa_hashmap_get(d->ports, p->name)) return -EINVAL; + if (SPA_FLAG_IS_SET(p->port.flags, ACP_PORT_HIDDEN)) + return -EINVAL; p->port.flags = ACP_PORT_ACTIVE | flags; if (p == old) diff --git a/spa/plugins/alsa/acp/acp.h b/spa/plugins/alsa/acp/acp.h index 7d6bf3d60..cc6429b22 100644 --- a/spa/plugins/alsa/acp/acp.h +++ b/spa/plugins/alsa/acp/acp.h @@ -167,6 +167,7 @@ struct acp_port { uint32_t index; /**< unique index for this port */ #define ACP_PORT_ACTIVE (1<<0) #define ACP_PORT_SAVE (1<<1) /* if the port needs saving */ +#define ACP_PORT_HIDDEN (1<<2) uint32_t flags; /**< extra port flags */ const char *name; /**< Name of this port */ @@ -190,6 +191,7 @@ struct acp_device { #define ACP_DEVICE_HW_MUTE (1<<2) #define ACP_DEVICE_UCM_DEVICE (1<<3) #define ACP_DEVICE_IEC958 (1<<4) +#define ACP_DEVICE_HIDDEN (1<<5) uint32_t flags; const char *name; @@ -218,6 +220,7 @@ struct acp_card_profile { #define ACP_PROFILE_OFF (1<<1) /* the Off profile */ #define ACP_PROFILE_SAVE (1<<2) /* if the profile needs saving */ #define ACP_PROFILE_PRO (1<<3) /* the Pro profile */ +#define ACP_PROFILE_HIDDEN (1<<4) /* don't show the profile */ uint32_t flags; const char *name; diff --git a/spa/plugins/alsa/alsa-acp-device.c b/spa/plugins/alsa/alsa-acp-device.c index 8cc6b7687..ea6a63f9f 100644 --- a/spa/plugins/alsa/alsa-acp-device.c +++ b/spa/plugins/alsa/alsa-acp-device.c @@ -516,14 +516,17 @@ static int impl_enum_params(void *object, int seq, return 0; pr = card->profiles[result.index]; + if (SPA_FLAG_IS_SET(pr->flags, ACP_PROFILE_HIDDEN)) + goto next; param = build_profile(&b.b, id, pr, false); break; case SPA_PARAM_Profile: if (result.index > 0 || card->active_profile_index >= card->n_profiles) return 0; - pr = card->profiles[card->active_profile_index]; + if (SPA_FLAG_IS_SET(pr->flags, ACP_PROFILE_HIDDEN)) + goto next; param = build_profile(&b.b, id, pr, true); break; @@ -532,6 +535,8 @@ static int impl_enum_params(void *object, int seq, return 0; p = card->ports[result.index]; + if (SPA_FLAG_IS_SET(p->flags, ACP_PORT_HIDDEN)) + goto next; param = build_route(&b.b, id, p, NULL, SPA_ID_INVALID); break; @@ -541,6 +546,8 @@ static int impl_enum_params(void *object, int seq, return 0; dev = card->devices[result.index]; + if (SPA_FLAG_IS_SET(dev->flags, ACP_DEVICE_HIDDEN)) + goto next; if (SPA_FLAG_IS_SET(dev->flags, ACP_DEVICE_ACTIVE) && (p = find_port_for_device(card, dev)) != NULL) break; @@ -548,6 +555,8 @@ static int impl_enum_params(void *object, int seq, result.index++; } result.next = result.index + 1; + if (SPA_FLAG_IS_SET(p->flags, ACP_PORT_HIDDEN)) + goto next; param = build_route(&b.b, id, p, dev, card->active_profile_index); if (param == NULL) return -errno; @@ -754,6 +763,8 @@ static int impl_set_param(void *object, return -EINVAL; dev = this->card->devices[device]; + if (SPA_FLAG_IS_SET(dev->flags, ACP_DEVICE_HIDDEN)) + return -EINVAL; acp_device_set_port(dev, idx, save ? ACP_PORT_SAVE : 0); if (props) apply_device_props(this, dev, props);