mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
alsa: rework UCM open
Use _alibpref to check if a device needs a UCM local config. Mark the device as such and use this to set the OPEN_UCM property on the device. Open the UCM for a card when the device has the property set. Use the same logic for loading the UCM as the acp code. See #1251
This commit is contained in:
parent
58d0e44664
commit
35e81fbfdc
8 changed files with 61 additions and 18 deletions
|
|
@ -60,6 +60,7 @@ extern "C" {
|
|||
#define SPA_KEY_API_ALSA_CARD "api.alsa.card" /**< alsa card number */
|
||||
#define SPA_KEY_API_ALSA_USE_UCM "api.alsa.use-ucm" /**< if UCM should be used */
|
||||
#define SPA_KEY_API_ALSA_IGNORE_DB "api.alsa.ignore-dB" /**< if decibel info should be ignored */
|
||||
#define SPA_KEY_API_ALSA_OPEN_UCM "api.alsa.open.ucm" /**< if UCM should be opened card */
|
||||
|
||||
/** info from alsa card_info */
|
||||
#define SPA_KEY_API_ALSA_CARD_ID "api.alsa.card.id" /**< id from card_info */
|
||||
|
|
|
|||
|
|
@ -241,8 +241,20 @@ static void init_device(pa_card *impl, pa_alsa_device *dev, pa_alsa_direction_t
|
|||
|
||||
dev->ports = pa_hashmap_new(pa_idxset_string_hash_func,
|
||||
pa_idxset_string_compare_func);
|
||||
if (m->ucm_context.ucm)
|
||||
if (m->ucm_context.ucm) {
|
||||
const char *alibpref;
|
||||
dev->ucm_context = &m->ucm_context;
|
||||
if ((snd_use_case_get(impl->ucm.ucm_mgr, "_alibpref", &alibpref) == 0)) {
|
||||
char **d;
|
||||
for (d = m->device_strings; *d; d++) {
|
||||
if (pa_startswith(*d, alibpref)) {
|
||||
dev->device.flags |= ACP_DEVICE_UCM_DEVICE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free((void*)alibpref);
|
||||
}
|
||||
}
|
||||
pa_dynarray_init(&dev->port_array, NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ struct acp_device {
|
|||
#define ACP_DEVICE_ACTIVE (1<<0)
|
||||
#define ACP_DEVICE_HW_VOLUME (1<<1)
|
||||
#define ACP_DEVICE_HW_MUTE (1<<2)
|
||||
#define ACP_DEVICE_UCM_DEVICE (1<<3)
|
||||
uint32_t flags;
|
||||
|
||||
const char *name;
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ static int emit_node(struct impl *this, struct acp_device *dev)
|
|||
const struct acp_dict_item *it;
|
||||
uint32_t n_items, i;
|
||||
char device_name[128], path[180], channels[16], ch[12], routes[16];
|
||||
char card_id[16], *p;
|
||||
char card_index[16], *p;
|
||||
char positions[SPA_AUDIO_MAX_CHANNELS * 12];
|
||||
struct spa_device_object_info info;
|
||||
struct acp_card *card = this->card;
|
||||
|
|
@ -168,10 +168,10 @@ static int emit_node(struct impl *this, struct acp_device *dev)
|
|||
|
||||
info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
|
||||
|
||||
n_items = dev->props.n_items + 7;
|
||||
items = alloca(n_items * sizeof(*items));
|
||||
items = alloca((dev->props.n_items + 8) * sizeof(*items));
|
||||
n_items = 0;
|
||||
|
||||
snprintf(card_id, sizeof(card), "%d", card->index);
|
||||
snprintf(card_index, sizeof(card_index), "%d", card->index);
|
||||
|
||||
devstr = dev->device_strings[0];
|
||||
p = strstr(devstr, "%f");
|
||||
|
|
@ -182,25 +182,27 @@ static int emit_node(struct impl *this, struct acp_device *dev)
|
|||
} else {
|
||||
snprintf(device_name, sizeof(device_name), "%s", devstr);
|
||||
}
|
||||
snprintf(path, sizeof(path), "alsa:pcm:%s:%s:%s", card_id, device_name, stream);
|
||||
items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_OBJECT_PATH, path);
|
||||
items[1] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PATH, device_name);
|
||||
items[2] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_CARD, card_id);
|
||||
items[3] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_STREAM, stream);
|
||||
snprintf(path, sizeof(path), "alsa:pcm:%s:%s:%s", card_index, device_name, stream);
|
||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_OBJECT_PATH, path);
|
||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PATH, device_name);
|
||||
if (dev->flags & ACP_DEVICE_UCM_DEVICE)
|
||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_OPEN_UCM, "true");
|
||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_CARD, card_index);
|
||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_STREAM, stream);
|
||||
|
||||
snprintf(channels, sizeof(channels), "%d", dev->format.channels);
|
||||
items[4] = SPA_DICT_ITEM_INIT(SPA_KEY_AUDIO_CHANNELS, channels);
|
||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_AUDIO_CHANNELS, channels);
|
||||
|
||||
p = positions;
|
||||
for (i = 0; i < dev->format.channels; i++) {
|
||||
p += snprintf(p, 12, "%s%s", i == 0 ? "" : ",",
|
||||
acp_channel_str(ch, sizeof(ch), dev->format.map[i]));
|
||||
}
|
||||
items[5] = SPA_DICT_ITEM_INIT(SPA_KEY_AUDIO_POSITION, positions);
|
||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_AUDIO_POSITION, positions);
|
||||
|
||||
snprintf(routes, sizeof(routes), "%d", dev->n_ports);
|
||||
items[6] = SPA_DICT_ITEM_INIT("device.routes", routes);
|
||||
n_items = 7;
|
||||
items[n_items++] = SPA_DICT_ITEM_INIT("device.routes", routes);
|
||||
|
||||
acp_dict_for_each(it, &dev->props)
|
||||
items[n_items++] = SPA_DICT_ITEM_INIT(it->key, it->value);
|
||||
|
||||
|
|
|
|||
|
|
@ -811,6 +811,10 @@ impl_init(const struct spa_handle_factory *factory,
|
|||
const char *s = info->items[i].value;
|
||||
if (spa_streq(k, SPA_KEY_API_ALSA_PATH)) {
|
||||
snprintf(this->props.device, 63, "%s", s);
|
||||
} else if (spa_streq(k, SPA_KEY_API_ALSA_PCM_CARD)) {
|
||||
this->card_index = atoi(s);
|
||||
} else if (spa_streq(k, SPA_KEY_API_ALSA_OPEN_UCM)) {
|
||||
this->open_ucm = spa_atob(s);
|
||||
} else if (spa_streq(k, SPA_KEY_AUDIO_CHANNELS)) {
|
||||
this->default_channels = atoi(s);
|
||||
} else if (spa_streq(k, SPA_KEY_AUDIO_RATE)) {
|
||||
|
|
|
|||
|
|
@ -829,6 +829,10 @@ impl_init(const struct spa_handle_factory *factory,
|
|||
const char *s = info->items[i].value;
|
||||
if (spa_streq(k, SPA_KEY_API_ALSA_PATH)) {
|
||||
snprintf(this->props.device, 63, "%s", s);
|
||||
} else if (spa_streq(k, SPA_KEY_API_ALSA_PCM_CARD)) {
|
||||
this->card_index = atoi(s);
|
||||
} else if (spa_streq(k, SPA_KEY_API_ALSA_OPEN_UCM)) {
|
||||
this->open_ucm = spa_atob(s);
|
||||
} else if (spa_streq(k, SPA_KEY_AUDIO_CHANNELS)) {
|
||||
this->default_channels = atoi(s);
|
||||
} else if (spa_streq(k, SPA_KEY_AUDIO_RATE)) {
|
||||
|
|
|
|||
|
|
@ -21,11 +21,28 @@ int spa_alsa_init(struct state *state)
|
|||
|
||||
snd_config_update_free_global();
|
||||
|
||||
if (strncmp(state->props.device, "_ucm", 4) == 0 &&
|
||||
strlen(state->props.device) >= 12 &&
|
||||
state->props.device[8] == '.') {
|
||||
if ((err = snd_use_case_mgr_open(&state->ucm, &state->props.device[9])) < 0)
|
||||
if (state->open_ucm) {
|
||||
char card_name[64];
|
||||
|
||||
snprintf(card_name, sizeof(card_name), "hw:%i", state->card_index);
|
||||
err = snd_use_case_mgr_open(&state->ucm, card_name);
|
||||
if (err < 0) {
|
||||
char *name;
|
||||
err = snd_card_get_name(state->card_index, &name);
|
||||
if (err < 0) {
|
||||
spa_log_error(state->log,
|
||||
"can't get card name from index %d",
|
||||
state->card_index);
|
||||
return err;
|
||||
}
|
||||
snprintf(card_name, sizeof(card_name), "%s", name);
|
||||
free(name);
|
||||
}
|
||||
err = snd_use_case_mgr_open(&state->ucm, card_name);
|
||||
if (err < 0) {
|
||||
spa_log_error(state->log, "UCM not available for card %s", card_name);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ struct state {
|
|||
struct spa_system *data_system;
|
||||
struct spa_loop *data_loop;
|
||||
|
||||
int card_index;
|
||||
snd_pcm_stream_t stream;
|
||||
snd_output_t *output;
|
||||
|
||||
|
|
@ -181,6 +182,7 @@ struct state {
|
|||
unsigned int use_mmap:1;
|
||||
unsigned int planar:1;
|
||||
unsigned int freewheel:1;
|
||||
unsigned int open_ucm:1;
|
||||
|
||||
int64_t sample_count;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue