alsa-ucm: Fix volume control based on review

- sync mixer logic added
- mixer path creation, empty set in mapping creation, paths added in path creation
- path creation moved inside new port creation as it might be called twice otherwise
- some comments added
This commit is contained in:
Jaska Uimonen 2019-10-01 18:34:17 +03:00 committed by Arun Raghavan
parent 3dfccada46
commit 9acacd9ba3
4 changed files with 50 additions and 55 deletions

View file

@ -1266,7 +1266,7 @@ static void sync_mixer(struct userdata *u, pa_device_port *port) {
/* port may be NULL, because if we use a synthesized mixer path, then the /* port may be NULL, because if we use a synthesized mixer path, then the
* sink has no ports. */ * sink has no ports. */
if (port) { if (port && !u->ucm_context) {
pa_alsa_port_data *data; pa_alsa_port_data *data;
data = PA_DEVICE_PORT_DATA(port); data = PA_DEVICE_PORT_DATA(port);
@ -1648,28 +1648,19 @@ static int sink_set_port_ucm_cb(pa_sink *s, pa_device_port *p) {
struct userdata *u = s->userdata; struct userdata *u = s->userdata;
pa_alsa_ucm_port_data *data; pa_alsa_ucm_port_data *data;
data = PA_DEVICE_PORT_DATA(p);
pa_assert(u); pa_assert(u);
pa_assert(p); pa_assert(p);
pa_assert(u->mixer_handle);
pa_assert(u->ucm_context); pa_assert(u->ucm_context);
u->mixer_path = data->path; data = PA_DEVICE_PORT_DATA(p);
pa_assert_se(u->mixer_path = data->path);
mixer_volume_init(u); mixer_volume_init(u);
if (u->mixer_path) { if (s->flags & PA_SINK_DEFERRED_VOLUME)
pa_alsa_path_select(u->mixer_path, NULL, u->mixer_handle, s->muted); pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_SYNC_MIXER, p, 0, NULL);
else
if (s->set_mute) sync_mixer(u, p);
s->set_mute(s);
if (s->flags & PA_SINK_DEFERRED_VOLUME) {
if (s->write_volume)
s->write_volume(s);
} else {
if (s->set_volume)
s->set_volume(s);
}
}
return pa_alsa_ucm_set_port(u->ucm_context, p, true); return pa_alsa_ucm_set_port(u->ucm_context, p, true);
} }
@ -2091,6 +2082,7 @@ static void set_sink_name(pa_sink_new_data *data, pa_modargs *ma, const char *de
} }
static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char *element, bool ignore_dB) { static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char *element, bool ignore_dB) {
if (!mapping && !element) if (!mapping && !element)
return; return;
@ -2099,11 +2091,6 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
return; return;
} }
if (u->ucm_context) {
/* We just want to open the device */
return;
}
if (element) { if (element) {
if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_OUTPUT))) if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_OUTPUT)))

View file

@ -1137,7 +1137,7 @@ static void sync_mixer(struct userdata *u, pa_device_port *port) {
/* port may be NULL, because if we use a synthesized mixer path, then the /* port may be NULL, because if we use a synthesized mixer path, then the
* source has no ports. */ * source has no ports. */
if (port) { if (port && !u->ucm_context) {
pa_alsa_port_data *data; pa_alsa_port_data *data;
data = PA_DEVICE_PORT_DATA(port); data = PA_DEVICE_PORT_DATA(port);
@ -1523,24 +1523,17 @@ static int source_set_port_ucm_cb(pa_source *s, pa_device_port *p) {
pa_assert(u); pa_assert(u);
pa_assert(p); pa_assert(p);
pa_assert(u->mixer_handle);
pa_assert(u->ucm_context); pa_assert(u->ucm_context);
u->mixer_path = data->path; data = PA_DEVICE_PORT_DATA(p);
pa_assert_se(u->mixer_path = data->path);
mixer_volume_init(u); mixer_volume_init(u);
if (u->mixer_path) { if (s->flags & PA_SOURCE_DEFERRED_VOLUME)
pa_alsa_path_select(u->mixer_path, NULL, u->mixer_handle, s->muted); pa_asyncmsgq_send(u->source->asyncmsgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_SYNC_MIXER, p, 0, NULL);
else
if (s->set_mute) sync_mixer(u, p);
s->set_mute(s);
if (s->flags & PA_SOURCE_DEFERRED_VOLUME) {
if (s->write_volume)
s->write_volume(s);
} else {
if (s->set_volume)
s->set_volume(s);
}
}
return pa_alsa_ucm_set_port(u->ucm_context, p, false); return pa_alsa_ucm_set_port(u->ucm_context, p, false);
} }
@ -1805,11 +1798,6 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
return; return;
} }
if (u->ucm_context) {
/* We just want to open the device */
return;
}
if (element) { if (element) {
if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_INPUT))) if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_INPUT)))
@ -2404,6 +2392,7 @@ static void userdata_free(struct userdata *u) {
if (u->mixer_fdl) if (u->mixer_fdl)
pa_alsa_fdlist_free(u->mixer_fdl); pa_alsa_fdlist_free(u->mixer_fdl);
/* Only free the mixer_path if the sink owns it */
if (u->mixer_path && !u->mixer_path_set && !u->ucm_context) if (u->mixer_path && !u->mixer_path_set && !u->ucm_context)
pa_alsa_path_free(u->mixer_path); pa_alsa_path_free(u->mixer_path);

View file

@ -852,21 +852,29 @@ static void ucm_add_port_combination(
pa_hashmap_put(ports, port->name, port); pa_hashmap_put(ports, port->name, port);
pa_log_debug("Add port %s: %s", port->name, port->description); pa_log_debug("Add port %s: %s", port->name, port->description);
}
if (num == 1) { if (num == 1) {
/* To keep things simple and not worry about stacking controls, we only support hardware volumes on non-combination /* To keep things simple and not worry about stacking controls, we only support hardware volumes on non-combination
* ports. */ * ports. */
data = PA_DEVICE_PORT_DATA(port); data = PA_DEVICE_PORT_DATA(port);
PA_HASHMAP_FOREACH_KV(profile, volume_element, is_sink ? dev->playback_volumes : dev->capture_volumes, state) { PA_HASHMAP_FOREACH_KV(profile, volume_element, is_sink ? dev->playback_volumes : dev->capture_volumes, state) {
pa_alsa_path *path = pa_alsa_path_synthesize(volume_element, pa_alsa_path *path = pa_alsa_path_synthesize(volume_element,
is_sink ? PA_ALSA_DIRECTION_OUTPUT : PA_ALSA_DIRECTION_INPUT); is_sink ? PA_ALSA_DIRECTION_OUTPUT : PA_ALSA_DIRECTION_INPUT);
if (!path) if (!path)
pa_log_warn("Failed to set up volume control: %s", volume_element); pa_log_warn("Failed to set up volume control: %s", volume_element);
else else {
pa_hashmap_put(data->paths, pa_xstrdup(profile), path); pa_hashmap_put(data->paths, pa_xstrdup(profile), path);
/* Add path also to already created empty path set */
dev = sorted[0];
if (is_sink)
pa_hashmap_put(dev->playback_mapping->output_path_set->paths, pa_xstrdup(volume_element), path);
else
pa_hashmap_put(dev->capture_mapping->input_path_set->paths, pa_xstrdup(volume_element), path);
}
}
} }
} }
@ -1185,16 +1193,27 @@ int pa_alsa_ucm_set_port(pa_alsa_ucm_mapping_context *context, pa_device_port *p
static void ucm_add_mapping(pa_alsa_profile *p, pa_alsa_mapping *m) { static void ucm_add_mapping(pa_alsa_profile *p, pa_alsa_mapping *m) {
pa_alsa_path_set *ps;
/* create empty path set for the future path additions */
ps = pa_xnew0(pa_alsa_path_set, 1);
ps->direction = m->direction;
ps->paths = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
switch (m->direction) { switch (m->direction) {
case PA_ALSA_DIRECTION_ANY: case PA_ALSA_DIRECTION_ANY:
pa_idxset_put(p->output_mappings, m, NULL); pa_idxset_put(p->output_mappings, m, NULL);
pa_idxset_put(p->input_mappings, m, NULL); pa_idxset_put(p->input_mappings, m, NULL);
m->output_path_set = ps;
m->input_path_set = ps;
break; break;
case PA_ALSA_DIRECTION_OUTPUT: case PA_ALSA_DIRECTION_OUTPUT:
pa_idxset_put(p->output_mappings, m, NULL); pa_idxset_put(p->output_mappings, m, NULL);
m->output_path_set = ps;
break; break;
case PA_ALSA_DIRECTION_INPUT: case PA_ALSA_DIRECTION_INPUT:
pa_idxset_put(p->input_mappings, m, NULL); pa_idxset_put(p->input_mappings, m, NULL);
m->input_path_set = ps;
break; break;
} }
} }

View file

@ -240,7 +240,7 @@ struct pa_alsa_ucm_port_data {
* a combination of devices. */ * a combination of devices. */
pa_dynarray *devices; /* pa_alsa_ucm_device */ pa_dynarray *devices; /* pa_alsa_ucm_device */
/* profile -> pa_alsa_path for volume control */ /* profile name -> pa_alsa_path for volume control */
pa_hashmap *paths; pa_hashmap *paths;
/* Current path, set when activating profile */ /* Current path, set when activating profile */
pa_alsa_path *path; pa_alsa_path *path;