alsa-ucm: Rewrite conformant device group generation with idxsets

The existing code meant to generate device groups for combination ports
is tightly coupled to port creation. Similar functionality would be
useful to generate nonconflicting device groups for multiple profiles as
well, so this tries to rewrite it into a more reusable state.

Several things (e.g devices, mapping contexts) use idxsets to store a
device selection. This also switches this conformance check and device
group generation to using idxsets to make it easier to work with those,
with the eventual aim to unify device group representations.

Also try to adjust users of these functions to use idxsets these will
need/return, without causing too much interference.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
This commit is contained in:
Wim Taymans 2023-03-20 16:28:32 +01:00
parent 7e64680a65
commit 3a68905c7c
2 changed files with 150 additions and 100 deletions

View file

@ -74,7 +74,13 @@ static inline pa_idxset_item* pa_idxset_find(const pa_idxset *s, const void *ptr
{
pa_idxset_item *item;
pa_array_for_each(item, &s->array) {
if (item->ptr == ptr)
if (item->ptr == NULL) {
if (ptr == NULL)
return item;
else
continue;
}
if (s->compare_func(item->ptr, ptr) == 0)
return item;
}
return NULL;
@ -124,13 +130,25 @@ static inline unsigned pa_idxset_size(pa_idxset*s)
return count;
}
static inline void *pa_idxset_search(pa_idxset *s, uint32_t *idx)
static inline pa_idxset_item *pa_idxset_search(pa_idxset *s, uint32_t *idx)
{
pa_idxset_item *item;
for (item = pa_array_get_unchecked(&s->array, *idx, pa_idxset_item);
pa_array_check(&s->array, item); item++, (*idx)++) {
if (item->ptr != NULL)
return item->ptr;
return item;
}
*idx = PA_IDXSET_INVALID;
return NULL;
}
static inline pa_idxset_item *pa_idxset_reverse_search(pa_idxset *s, uint32_t *idx)
{
pa_idxset_item *item;
for (item = pa_array_get_unchecked(&s->array, *idx, pa_idxset_item);
pa_array_check(&s->array, item); item--, (*idx)--) {
if (item->ptr != NULL)
return item;
}
*idx = PA_IDXSET_INVALID;
return NULL;
@ -138,29 +156,93 @@ static inline void *pa_idxset_search(pa_idxset *s, uint32_t *idx)
static inline void *pa_idxset_next(pa_idxset *s, uint32_t *idx)
{
pa_idxset_item *item;
(*idx)++;;
return pa_idxset_search(s, idx);
item = pa_idxset_search(s, idx);
return item ? item->ptr : NULL;
}
static inline void* pa_idxset_first(pa_idxset *s, uint32_t *idx)
{
uint32_t i = 0;
void *ptr = pa_idxset_search(s, &i);
pa_idxset_item *item = pa_idxset_search(s, &i);
if (idx)
*idx = i;
return item ? item->ptr : NULL;
}
static inline void* pa_idxset_last(pa_idxset *s, uint32_t *idx)
{
uint32_t i = pa_array_get_len(&s->array, pa_idxset_item) - 1;
pa_idxset_item *item = pa_idxset_reverse_search(s, &i);
if (idx)
*idx = i;
return item ? item->ptr : NULL;
}
static inline void* pa_idxset_steal_last(pa_idxset *s, uint32_t *idx)
{
uint32_t i = pa_array_get_len(&s->array, pa_idxset_item) - 1;
void *ptr = NULL;
pa_idxset_item *item = pa_idxset_reverse_search(s, &i);
if (idx)
*idx = i;
if (item) {
ptr = item->ptr;
item->ptr = NULL;
pa_array_remove(&s->array, item);
}
return ptr;
}
static inline void* pa_idxset_get_by_data(pa_idxset*s, const void *p, uint32_t *idx)
{
pa_idxset_item *item = pa_idxset_find(s, p);
if (item == NULL)
if (item == NULL) {
if (idx)
*idx = PA_IDXSET_INVALID;
return NULL;
}
if (idx)
*idx = item - (pa_idxset_item*)s->array.data;
return item->ptr;
}
static inline bool pa_idxset_contains(pa_idxset *s, const void *p)
{
return pa_idxset_get_by_data(s, p, NULL) == p;
}
static inline bool pa_idxset_isdisjoint(pa_idxset *s, pa_idxset *t)
{
pa_idxset_item *item;
pa_array_for_each(item, &s->array) {
if (item->ptr && pa_idxset_contains(t, item->ptr))
return false;
}
return true;
}
static inline bool pa_idxset_issubset(pa_idxset *s, pa_idxset *t)
{
pa_idxset_item *item;
pa_array_for_each(item, &s->array) {
if (item->ptr && !pa_idxset_contains(t, item->ptr))
return false;
}
return true;
}
static inline bool pa_idxset_issuperset(pa_idxset *s, pa_idxset *t)
{
return pa_idxset_issubset(t, s);
}
static inline bool pa_idxset_equals(pa_idxset *s, pa_idxset *t)
{
return pa_idxset_issubset(s, t) && pa_idxset_issuperset(s, t);
}
static inline void* pa_idxset_get_by_index(pa_idxset*s, uint32_t idx)
{
pa_idxset_item *item;