mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-12-23 08:56:40 -05:00
alsa: Add separate sinks/sources for UCM modifiers if needed
Modifiers may have their own PlaybackPCM/CapturePCM and for these, we create separate sinks/sources. These are marked with the device.intended_roles property to let role-based routing take care if streams are tagged appropriately.
This commit is contained in:
parent
a08c85d299
commit
5c12ce5985
4 changed files with 195 additions and 10 deletions
|
|
@ -904,6 +904,8 @@ static int build_pollfd(struct userdata *u) {
|
||||||
|
|
||||||
/* Called from IO context */
|
/* Called from IO context */
|
||||||
static int suspend(struct userdata *u) {
|
static int suspend(struct userdata *u) {
|
||||||
|
const char *mod_name;
|
||||||
|
|
||||||
pa_assert(u);
|
pa_assert(u);
|
||||||
pa_assert(u->pcm_handle);
|
pa_assert(u->pcm_handle);
|
||||||
|
|
||||||
|
|
@ -914,6 +916,13 @@ static int suspend(struct userdata *u) {
|
||||||
snd_pcm_close(u->pcm_handle);
|
snd_pcm_close(u->pcm_handle);
|
||||||
u->pcm_handle = NULL;
|
u->pcm_handle = NULL;
|
||||||
|
|
||||||
|
if ((mod_name = pa_proplist_gets(u->sink->proplist, PA_ALSA_PROP_UCM_MODIFIER))) {
|
||||||
|
pa_log_info("Disable ucm modifier %s", mod_name);
|
||||||
|
|
||||||
|
if (snd_use_case_set(u->ucm_context->ucm->ucm_mgr, "_dismod", mod_name) < 0)
|
||||||
|
pa_log("Failed to disable ucm modifier %s", mod_name);
|
||||||
|
}
|
||||||
|
|
||||||
if (u->alsa_rtpoll_item) {
|
if (u->alsa_rtpoll_item) {
|
||||||
pa_rtpoll_item_free(u->alsa_rtpoll_item);
|
pa_rtpoll_item_free(u->alsa_rtpoll_item);
|
||||||
u->alsa_rtpoll_item = NULL;
|
u->alsa_rtpoll_item = NULL;
|
||||||
|
|
@ -1036,12 +1045,20 @@ static int unsuspend(struct userdata *u) {
|
||||||
pa_bool_t b, d;
|
pa_bool_t b, d;
|
||||||
snd_pcm_uframes_t period_size, buffer_size;
|
snd_pcm_uframes_t period_size, buffer_size;
|
||||||
char *device_name = NULL;
|
char *device_name = NULL;
|
||||||
|
const char *mod_name;
|
||||||
|
|
||||||
pa_assert(u);
|
pa_assert(u);
|
||||||
pa_assert(!u->pcm_handle);
|
pa_assert(!u->pcm_handle);
|
||||||
|
|
||||||
pa_log_info("Trying resume...");
|
pa_log_info("Trying resume...");
|
||||||
|
|
||||||
|
if ((mod_name = pa_proplist_gets(u->sink->proplist, PA_ALSA_PROP_UCM_MODIFIER))) {
|
||||||
|
pa_log_info("Enable ucm modifier %s", mod_name);
|
||||||
|
|
||||||
|
if (snd_use_case_set(u->ucm_context->ucm->ucm_mgr, "_enamod", mod_name) < 0)
|
||||||
|
pa_log("Failed to enable ucm modifier %s", mod_name);
|
||||||
|
}
|
||||||
|
|
||||||
if ((is_iec958(u) || is_hdmi(u)) && pa_sink_is_passthrough(u->sink)) {
|
if ((is_iec958(u) || is_hdmi(u)) && pa_sink_is_passthrough(u->sink)) {
|
||||||
/* Need to open device in NONAUDIO mode */
|
/* Need to open device in NONAUDIO mode */
|
||||||
int len = strlen(u->device_name) + 8;
|
int len = strlen(u->device_name) + 8;
|
||||||
|
|
@ -1977,7 +1994,7 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
|
||||||
pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, pa_alsa_mapping *mapping) {
|
pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, pa_alsa_mapping *mapping) {
|
||||||
|
|
||||||
struct userdata *u = NULL;
|
struct userdata *u = NULL;
|
||||||
const char *dev_id = NULL, *key;
|
const char *dev_id = NULL, *key, *mod_name;
|
||||||
pa_sample_spec ss;
|
pa_sample_spec ss;
|
||||||
uint32_t alternate_sample_rate;
|
uint32_t alternate_sample_rate;
|
||||||
pa_channel_map map;
|
pa_channel_map map;
|
||||||
|
|
@ -2110,6 +2127,13 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((mod_name = pa_proplist_gets(mapping->proplist, PA_ALSA_PROP_UCM_MODIFIER))) {
|
||||||
|
if (snd_use_case_set(u->ucm_context->ucm->ucm_mgr, "_enamod", mod_name) < 0)
|
||||||
|
pa_log("Failed to enable ucm modifier %s", mod_name);
|
||||||
|
else
|
||||||
|
pa_log_debug("Enabled ucm modifier %s", mod_name);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(u->pcm_handle = pa_alsa_open_by_device_id_mapping(
|
if (!(u->pcm_handle = pa_alsa_open_by_device_id_mapping(
|
||||||
dev_id,
|
dev_id,
|
||||||
&u->device_name,
|
&u->device_name,
|
||||||
|
|
|
||||||
|
|
@ -836,6 +836,8 @@ static int build_pollfd(struct userdata *u) {
|
||||||
|
|
||||||
/* Called from IO context */
|
/* Called from IO context */
|
||||||
static int suspend(struct userdata *u) {
|
static int suspend(struct userdata *u) {
|
||||||
|
const char *mod_name;
|
||||||
|
|
||||||
pa_assert(u);
|
pa_assert(u);
|
||||||
pa_assert(u->pcm_handle);
|
pa_assert(u->pcm_handle);
|
||||||
|
|
||||||
|
|
@ -845,6 +847,13 @@ static int suspend(struct userdata *u) {
|
||||||
snd_pcm_close(u->pcm_handle);
|
snd_pcm_close(u->pcm_handle);
|
||||||
u->pcm_handle = NULL;
|
u->pcm_handle = NULL;
|
||||||
|
|
||||||
|
if ((mod_name = pa_proplist_gets(u->source->proplist, PA_ALSA_PROP_UCM_MODIFIER))) {
|
||||||
|
pa_log_info("Disable ucm modifier %s", mod_name);
|
||||||
|
|
||||||
|
if (snd_use_case_set(u->ucm_context->ucm->ucm_mgr, "_dismod", mod_name) < 0)
|
||||||
|
pa_log("Failed to disable ucm modifier %s", mod_name);
|
||||||
|
}
|
||||||
|
|
||||||
if (u->alsa_rtpoll_item) {
|
if (u->alsa_rtpoll_item) {
|
||||||
pa_rtpoll_item_free(u->alsa_rtpoll_item);
|
pa_rtpoll_item_free(u->alsa_rtpoll_item);
|
||||||
u->alsa_rtpoll_item = NULL;
|
u->alsa_rtpoll_item = NULL;
|
||||||
|
|
@ -949,12 +958,20 @@ static int unsuspend(struct userdata *u) {
|
||||||
int err;
|
int err;
|
||||||
pa_bool_t b, d;
|
pa_bool_t b, d;
|
||||||
snd_pcm_uframes_t period_size, buffer_size;
|
snd_pcm_uframes_t period_size, buffer_size;
|
||||||
|
const char *mod_name;
|
||||||
|
|
||||||
pa_assert(u);
|
pa_assert(u);
|
||||||
pa_assert(!u->pcm_handle);
|
pa_assert(!u->pcm_handle);
|
||||||
|
|
||||||
pa_log_info("Trying resume...");
|
pa_log_info("Trying resume...");
|
||||||
|
|
||||||
|
if ((mod_name = pa_proplist_gets(u->source->proplist, PA_ALSA_PROP_UCM_MODIFIER))) {
|
||||||
|
pa_log_info("Enable ucm modifier %s", mod_name);
|
||||||
|
|
||||||
|
if (snd_use_case_set(u->ucm_context->ucm->ucm_mgr, "_enamod", mod_name) < 0)
|
||||||
|
pa_log("Failed to enable ucm modifier %s", mod_name);
|
||||||
|
}
|
||||||
|
|
||||||
if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE,
|
if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE,
|
||||||
SND_PCM_NONBLOCK|
|
SND_PCM_NONBLOCK|
|
||||||
SND_PCM_NO_AUTO_RESAMPLE|
|
SND_PCM_NO_AUTO_RESAMPLE|
|
||||||
|
|
@ -1714,7 +1731,7 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
|
||||||
pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, pa_alsa_mapping *mapping) {
|
pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, pa_alsa_mapping *mapping) {
|
||||||
|
|
||||||
struct userdata *u = NULL;
|
struct userdata *u = NULL;
|
||||||
const char *dev_id = NULL, *key;
|
const char *dev_id = NULL, *key, *mod_name;
|
||||||
pa_sample_spec ss;
|
pa_sample_spec ss;
|
||||||
uint32_t alternate_sample_rate;
|
uint32_t alternate_sample_rate;
|
||||||
pa_channel_map map;
|
pa_channel_map map;
|
||||||
|
|
@ -1840,6 +1857,13 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((mod_name = pa_proplist_gets(mapping->proplist, PA_ALSA_PROP_UCM_MODIFIER))) {
|
||||||
|
if (snd_use_case_set(u->ucm_context->ucm->ucm_mgr, "_enamod", mod_name) < 0)
|
||||||
|
pa_log("Failed to enable ucm modifier %s", mod_name);
|
||||||
|
else
|
||||||
|
pa_log_debug("Enabled ucm modifier %s", mod_name);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(u->pcm_handle = pa_alsa_open_by_device_id_mapping(
|
if (!(u->pcm_handle = pa_alsa_open_by_device_id_mapping(
|
||||||
dev_id,
|
dev_id,
|
||||||
&u->device_name,
|
&u->device_name,
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@
|
||||||
if (PA_UCM_PLAYBACK_PRIORITY_UNSET(device)) (device)->playback_priority = (priority); \
|
if (PA_UCM_PLAYBACK_PRIORITY_UNSET(device)) (device)->playback_priority = (priority); \
|
||||||
if (PA_UCM_CAPTURE_PRIORITY_UNSET(device)) (device)->capture_priority = (priority); \
|
if (PA_UCM_CAPTURE_PRIORITY_UNSET(device)) (device)->capture_priority = (priority); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
#define PA_UCM_IS_MODIFIER_MAPPING(m) ((pa_proplist_gets((m)->proplist, PA_ALSA_PROP_UCM_MODIFIER)) != NULL)
|
||||||
|
|
||||||
struct ucm_items {
|
struct ucm_items {
|
||||||
const char *id;
|
const char *id;
|
||||||
|
|
@ -1033,6 +1034,50 @@ static void alsa_mapping_add_ucm_device(pa_alsa_mapping *m, pa_alsa_ucm_device *
|
||||||
device->capture_mapping = m;
|
device->capture_mapping = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void alsa_mapping_add_ucm_modifier(pa_alsa_mapping *m, pa_alsa_ucm_modifier *modifier) {
|
||||||
|
char *cur_desc;
|
||||||
|
const char *new_desc, *mod_name, *channel_str;
|
||||||
|
uint32_t channels = 0;
|
||||||
|
|
||||||
|
pa_idxset_put(m->ucm_context.ucm_modifiers, modifier, NULL);
|
||||||
|
|
||||||
|
new_desc = pa_proplist_gets(modifier->proplist, PA_ALSA_PROP_UCM_DESCRIPTION);
|
||||||
|
cur_desc = m->description;
|
||||||
|
if (cur_desc)
|
||||||
|
m->description = pa_sprintf_malloc("%s + %s", cur_desc, new_desc);
|
||||||
|
else
|
||||||
|
m->description = pa_xstrdup(new_desc);
|
||||||
|
pa_xfree(cur_desc);
|
||||||
|
|
||||||
|
if (!m->description)
|
||||||
|
pa_xstrdup("");
|
||||||
|
|
||||||
|
/* Modifier sinks should not be routed to by default */
|
||||||
|
m->priority = 0;
|
||||||
|
|
||||||
|
mod_name = pa_proplist_gets(modifier->proplist, PA_ALSA_PROP_UCM_NAME);
|
||||||
|
pa_proplist_sets(m->proplist, PA_ALSA_PROP_UCM_MODIFIER, mod_name);
|
||||||
|
|
||||||
|
/* save mapping to ucm modifier */
|
||||||
|
if (m->direction == PA_ALSA_DIRECTION_OUTPUT) {
|
||||||
|
modifier->playback_mapping = m;
|
||||||
|
channel_str = pa_proplist_gets(modifier->proplist, PA_ALSA_PROP_UCM_PLAYBACK_CHANNELS);
|
||||||
|
} else {
|
||||||
|
modifier->capture_mapping = m;
|
||||||
|
channel_str = pa_proplist_gets(modifier->proplist, PA_ALSA_PROP_UCM_CAPTURE_CHANNELS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel_str) {
|
||||||
|
pa_assert_se(pa_atou(channel_str, &channels) == 0 && channels < PA_CHANNELS_MAX);
|
||||||
|
pa_log_debug("Got channel count %" PRIu32 " for modifier", channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channels)
|
||||||
|
pa_channel_map_init_extend(&m->channel_map, channels, PA_CHANNEL_MAP_ALSA);
|
||||||
|
else
|
||||||
|
pa_channel_map_init(&m->channel_map);
|
||||||
|
}
|
||||||
|
|
||||||
static int ucm_create_mapping_direction(
|
static int ucm_create_mapping_direction(
|
||||||
pa_alsa_ucm_config *ucm,
|
pa_alsa_ucm_config *ucm,
|
||||||
pa_alsa_profile_set *ps,
|
pa_alsa_profile_set *ps,
|
||||||
|
|
@ -1087,6 +1132,51 @@ static int ucm_create_mapping_direction(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ucm_create_mapping_for_modifier(
|
||||||
|
pa_alsa_ucm_config *ucm,
|
||||||
|
pa_alsa_profile_set *ps,
|
||||||
|
pa_alsa_profile *p,
|
||||||
|
pa_alsa_ucm_modifier *modifier,
|
||||||
|
const char *verb_name,
|
||||||
|
const char *mod_name,
|
||||||
|
const char *device_str,
|
||||||
|
bool is_sink) {
|
||||||
|
|
||||||
|
pa_alsa_mapping *m;
|
||||||
|
char *mapping_name;
|
||||||
|
|
||||||
|
mapping_name = pa_sprintf_malloc("Mapping %s: %s: %s", verb_name, device_str, is_sink ? "sink" : "source");
|
||||||
|
|
||||||
|
m = pa_alsa_mapping_get(ps, mapping_name);
|
||||||
|
if (!m) {
|
||||||
|
pa_log("no mapping for %s", mapping_name);
|
||||||
|
pa_xfree(mapping_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pa_log_info("ucm mapping: %s modifier %s", mapping_name, mod_name);
|
||||||
|
pa_xfree(mapping_name);
|
||||||
|
|
||||||
|
if (!m->ucm_context.ucm_devices && !m->ucm_context.ucm_modifiers) { /* new mapping */
|
||||||
|
m->ucm_context.ucm_devices = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
|
||||||
|
m->ucm_context.ucm_modifiers = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
|
||||||
|
m->ucm_context.ucm = ucm;
|
||||||
|
m->ucm_context.direction = is_sink ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT;
|
||||||
|
|
||||||
|
m->device_strings = pa_xnew0(char*, 2);
|
||||||
|
m->device_strings[0] = pa_xstrdup(device_str);
|
||||||
|
m->direction = is_sink ? PA_ALSA_DIRECTION_OUTPUT : PA_ALSA_DIRECTION_INPUT;
|
||||||
|
/* Modifier sinks should not be routed to by default */
|
||||||
|
m->priority = 0;
|
||||||
|
|
||||||
|
ucm_add_mapping(p, m);
|
||||||
|
} else if (!m->ucm_context.ucm_modifiers) /* share pcm with device */
|
||||||
|
m->ucm_context.ucm_modifiers = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
|
||||||
|
|
||||||
|
alsa_mapping_add_ucm_modifier(m, modifier);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int ucm_create_mapping(
|
static int ucm_create_mapping(
|
||||||
pa_alsa_ucm_config *ucm,
|
pa_alsa_ucm_config *ucm,
|
||||||
pa_alsa_profile_set *ps,
|
pa_alsa_profile_set *ps,
|
||||||
|
|
@ -1142,6 +1232,7 @@ static int ucm_create_profile(
|
||||||
|
|
||||||
pa_alsa_profile *p;
|
pa_alsa_profile *p;
|
||||||
pa_alsa_ucm_device *dev;
|
pa_alsa_ucm_device *dev;
|
||||||
|
pa_alsa_ucm_modifier *mod;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
const char *name, *sink, *source;
|
const char *name, *sink, *source;
|
||||||
char *verb_cmp, *c;
|
char *verb_cmp, *c;
|
||||||
|
|
@ -1197,6 +1288,20 @@ static int ucm_create_profile(
|
||||||
dev->input_jack = ucm_get_jack(ucm, name, PA_UCM_PRE_TAG_INPUT);
|
dev->input_jack = ucm_get_jack(ucm, name, PA_UCM_PRE_TAG_INPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now find modifiers that have their own PlaybackPCM and create
|
||||||
|
* separate sinks for them. */
|
||||||
|
PA_LLIST_FOREACH(mod, verb->modifiers) {
|
||||||
|
name = pa_proplist_gets(mod->proplist, PA_ALSA_PROP_UCM_NAME);
|
||||||
|
|
||||||
|
sink = pa_proplist_gets(mod->proplist, PA_ALSA_PROP_UCM_SINK);
|
||||||
|
source = pa_proplist_gets(mod->proplist, PA_ALSA_PROP_UCM_SOURCE);
|
||||||
|
|
||||||
|
if (sink)
|
||||||
|
ucm_create_mapping_for_modifier(ucm, ps, p, mod, verb_name, name, sink, TRUE);
|
||||||
|
else if (source)
|
||||||
|
ucm_create_mapping_for_modifier(ucm, ps, p, mod, verb_name, name, source, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
pa_alsa_profile_dump(p);
|
pa_alsa_profile_dump(p);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1234,23 +1339,23 @@ static void profile_finalize_probing(pa_alsa_profile *p) {
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
|
|
||||||
PA_IDXSET_FOREACH(m, p->output_mappings, idx) {
|
PA_IDXSET_FOREACH(m, p->output_mappings, idx) {
|
||||||
if (!m->output_pcm)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (p->supported)
|
if (p->supported)
|
||||||
m->supported++;
|
m->supported++;
|
||||||
|
|
||||||
|
if (!m->output_pcm)
|
||||||
|
continue;
|
||||||
|
|
||||||
snd_pcm_close(m->output_pcm);
|
snd_pcm_close(m->output_pcm);
|
||||||
m->output_pcm = NULL;
|
m->output_pcm = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PA_IDXSET_FOREACH(m, p->input_mappings, idx) {
|
PA_IDXSET_FOREACH(m, p->input_mappings, idx) {
|
||||||
if (!m->input_pcm)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (p->supported)
|
if (p->supported)
|
||||||
m->supported++;
|
m->supported++;
|
||||||
|
|
||||||
|
if (!m->input_pcm)
|
||||||
|
continue;
|
||||||
|
|
||||||
snd_pcm_close(m->input_pcm);
|
snd_pcm_close(m->input_pcm);
|
||||||
m->input_pcm = NULL;
|
m->input_pcm = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -1289,20 +1394,35 @@ static void ucm_probe_profile_set(pa_alsa_ucm_config *ucm, pa_alsa_profile_set *
|
||||||
PA_HASHMAP_FOREACH(p, ps->profiles, state) {
|
PA_HASHMAP_FOREACH(p, ps->profiles, state) {
|
||||||
/* change verb */
|
/* change verb */
|
||||||
pa_log_info("Set ucm verb to %s", p->name);
|
pa_log_info("Set ucm verb to %s", p->name);
|
||||||
|
|
||||||
if ((snd_use_case_set(ucm->ucm_mgr, "_verb", p->name)) < 0) {
|
if ((snd_use_case_set(ucm->ucm_mgr, "_verb", p->name)) < 0) {
|
||||||
pa_log("Failed to set verb %s", p->name);
|
pa_log("Failed to set verb %s", p->name);
|
||||||
p->supported = FALSE;
|
p->supported = FALSE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PA_IDXSET_FOREACH(m, p->output_mappings, idx) {
|
PA_IDXSET_FOREACH(m, p->output_mappings, idx) {
|
||||||
|
if (PA_UCM_IS_MODIFIER_MAPPING(m)) {
|
||||||
|
/* Skip jack probing on modifier PCMs since we expect this to
|
||||||
|
* only be controlled on the main device/verb PCM. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
m->output_pcm = mapping_open_pcm(ucm, m, SND_PCM_STREAM_PLAYBACK);
|
m->output_pcm = mapping_open_pcm(ucm, m, SND_PCM_STREAM_PLAYBACK);
|
||||||
if (!m->output_pcm) {
|
if (!m->output_pcm) {
|
||||||
p->supported = FALSE;
|
p->supported = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->supported) {
|
if (p->supported) {
|
||||||
PA_IDXSET_FOREACH(m, p->input_mappings, idx) {
|
PA_IDXSET_FOREACH(m, p->input_mappings, idx) {
|
||||||
|
if (PA_UCM_IS_MODIFIER_MAPPING(m)) {
|
||||||
|
/* Skip jack probing on modifier PCMs since we expect this to
|
||||||
|
* only be controlled on the main device/verb PCM. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
m->input_pcm = mapping_open_pcm(ucm, m, SND_PCM_STREAM_CAPTURE);
|
m->input_pcm = mapping_open_pcm(ucm, m, SND_PCM_STREAM_CAPTURE);
|
||||||
if (!m->input_pcm) {
|
if (!m->input_pcm) {
|
||||||
p->supported = FALSE;
|
p->supported = FALSE;
|
||||||
|
|
@ -1319,10 +1439,12 @@ static void ucm_probe_profile_set(pa_alsa_ucm_config *ucm, pa_alsa_profile_set *
|
||||||
pa_log_debug("Profile %s supported.", p->name);
|
pa_log_debug("Profile %s supported.", p->name);
|
||||||
|
|
||||||
PA_IDXSET_FOREACH(m, p->output_mappings, idx)
|
PA_IDXSET_FOREACH(m, p->output_mappings, idx)
|
||||||
ucm_mapping_jack_probe(m);
|
if (!PA_UCM_IS_MODIFIER_MAPPING(m))
|
||||||
|
ucm_mapping_jack_probe(m);
|
||||||
|
|
||||||
PA_IDXSET_FOREACH(m, p->input_mappings, idx)
|
PA_IDXSET_FOREACH(m, p->input_mappings, idx)
|
||||||
ucm_mapping_jack_probe(m);
|
if (!PA_UCM_IS_MODIFIER_MAPPING(m))
|
||||||
|
ucm_mapping_jack_probe(m);
|
||||||
|
|
||||||
profile_finalize_probing(p);
|
profile_finalize_probing(p);
|
||||||
}
|
}
|
||||||
|
|
@ -1413,6 +1535,7 @@ void pa_alsa_ucm_free(pa_alsa_ucm_config *ucm) {
|
||||||
|
|
||||||
void pa_alsa_ucm_mapping_context_free(pa_alsa_ucm_mapping_context *context) {
|
void pa_alsa_ucm_mapping_context_free(pa_alsa_ucm_mapping_context *context) {
|
||||||
pa_alsa_ucm_device *dev;
|
pa_alsa_ucm_device *dev;
|
||||||
|
pa_alsa_ucm_modifier *mod;
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
|
|
||||||
if (context->ucm_devices) {
|
if (context->ucm_devices) {
|
||||||
|
|
@ -1428,6 +1551,13 @@ void pa_alsa_ucm_mapping_context_free(pa_alsa_ucm_mapping_context *context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context->ucm_modifiers) {
|
if (context->ucm_modifiers) {
|
||||||
|
PA_IDXSET_FOREACH(mod, context->ucm_modifiers, idx) {
|
||||||
|
if (context->direction == PA_DIRECTION_OUTPUT)
|
||||||
|
mod->playback_mapping = NULL;
|
||||||
|
else
|
||||||
|
mod->capture_mapping = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
pa_idxset_free(context->ucm_modifiers, NULL, NULL);
|
pa_idxset_free(context->ucm_modifiers, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,9 @@
|
||||||
/** For devices: Quality of Service */
|
/** For devices: Quality of Service */
|
||||||
#define PA_ALSA_PROP_UCM_QOS "alsa.ucm.qos"
|
#define PA_ALSA_PROP_UCM_QOS "alsa.ucm.qos"
|
||||||
|
|
||||||
|
/** For devices: The modifier (if any) that this device corresponds to */
|
||||||
|
#define PA_ALSA_PROP_UCM_MODIFIER "alsa.ucm.modifier"
|
||||||
|
|
||||||
typedef struct pa_alsa_ucm_verb pa_alsa_ucm_verb;
|
typedef struct pa_alsa_ucm_verb pa_alsa_ucm_verb;
|
||||||
typedef struct pa_alsa_ucm_modifier pa_alsa_ucm_modifier;
|
typedef struct pa_alsa_ucm_modifier pa_alsa_ucm_modifier;
|
||||||
typedef struct pa_alsa_ucm_device pa_alsa_ucm_device;
|
typedef struct pa_alsa_ucm_device pa_alsa_ucm_device;
|
||||||
|
|
@ -140,6 +143,10 @@ struct pa_alsa_ucm_modifier {
|
||||||
pa_direction_t action_direction;
|
pa_direction_t action_direction;
|
||||||
|
|
||||||
char *media_role;
|
char *media_role;
|
||||||
|
|
||||||
|
/* Non-NULL if the modifier has its own PlaybackPCM/CapturePCM */
|
||||||
|
pa_alsa_mapping *playback_mapping;
|
||||||
|
pa_alsa_mapping *capture_mapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pa_alsa_ucm_verb {
|
struct pa_alsa_ucm_verb {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue