mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	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:
		
							parent
							
								
									3dfccada46
								
							
						
					
					
						commit
						9acacd9ba3
					
				
					 4 changed files with 50 additions and 55 deletions
				
			
		| 
						 | 
					@ -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)))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -852,7 +852,6 @@ 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
 | 
				
			||||||
| 
						 | 
					@ -865,8 +864,17 @@ static void ucm_add_port_combination(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue