Currently, card ports, device prototypes and profiles are all created together in an "interleaved" manner. My goal is to split that process so that first all ports are created, then all device prototypes are created and finally all profiles are created. This patch is the first major step in that refactoring: all ports are created in pa_alsa_profile_set_create_ports() before any device prototypes or profiles are created. Most of the code in device_port_alsa_init() is moved to create_port(). --- src/modules/alsa/alsa-mixer.c | 160 ++++++++++++++++++++++++------------ src/modules/alsa/alsa-mixer.h | 3 +- src/modules/alsa/module-alsa-card.c | 5 +- 3 files changed, 111 insertions(+), 57 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index 4645817..bd243ba 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -4483,61 +4483,21 @@ static pa_device_port* device_port_alsa_init(pa_hashmap *ports, /* card ports */ pa_alsa_path *path, pa_alsa_setting *setting, pa_card_profile *cp, - pa_hashmap *extra, /* sink/source ports */ - pa_core *core) { + pa_hashmap *extra /* sink/source ports */) { char *name = NULL; - char *description = NULL; pa_device_port *p; pa_assert(path); - if (setting) { + if (setting) name = pa_sprintf_malloc("%s;%s", path->name, setting->name); - - if (setting->description[0]) - description = pa_sprintf_malloc("%s / %s", path->description, setting->description); - else - description = pa_xstrdup(path->description); - } else { + else name = pa_xstrdup(path->name); - description = pa_xstrdup(path->description); - } p = pa_hashmap_get(ports, name); - - if (!p) { - pa_alsa_port_data *data; - pa_device_port_new_data port_data; - - pa_device_port_new_data_init(&port_data); - pa_device_port_new_data_set_name(&port_data, name); - pa_device_port_new_data_set_description(&port_data, description); - pa_device_port_new_data_set_direction(&port_data, path->direction == PA_ALSA_DIRECTION_OUTPUT ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT); - pa_node_new_data_set_fallback_name_prefix(&port_data.node_data, "alsa"); - - p = pa_device_port_new(core, &port_data, sizeof(pa_alsa_port_data)); - pa_device_port_new_data_done(&port_data); - - if (!p) { - pa_log("Failed to create port %s.", name); - goto finish; - } - - p->priority = path->priority * 100; - - if (setting) - p->priority += setting->priority; - - pa_hashmap_put(ports, p->name, p); - pa_proplist_update(p->proplist, PA_UPDATE_REPLACE, path->proplist); - - data = PA_DEVICE_PORT_DATA(p); - data->path = path; - data->setting = setting; - - pa_dynarray_append(path->ports, p); - } + pa_assert(p); + pa_xfree(name); if (cp) pa_hashmap_put(p->profiles, cp->name, cp); @@ -4547,10 +4507,6 @@ static pa_device_port* device_port_alsa_init(pa_hashmap *ports, /* card ports */ pa_device_port_ref(p); } -finish: - pa_xfree(description); - pa_xfree(name); - return p; } @@ -4558,8 +4514,7 @@ void pa_alsa_path_set_add_ports( pa_alsa_path_set *ps, pa_card_profile *cp, pa_hashmap *ports, /* card ports */ - pa_hashmap *extra, /* sink/source ports */ - pa_core *core) { + pa_hashmap *extra /* sink/source ports */) { pa_alsa_path *path; void *state; @@ -4573,11 +4528,11 @@ void pa_alsa_path_set_add_ports( if (!path->settings || !path->settings->next) /* If there is no or just one setting we only need a * single entry */ - device_port_alsa_init(ports, path, path->settings, cp, extra, core); + device_port_alsa_init(ports, path, path->settings, cp, extra); else { pa_alsa_setting *s; PA_LLIST_FOREACH(s, path->settings) - device_port_alsa_init(ports, path, s, cp, extra, core); + device_port_alsa_init(ports, path, s, cp, extra); } } } @@ -4595,8 +4550,105 @@ void pa_alsa_add_ports(void *sink_or_source_new_data, pa_alsa_path_set *ps, pa_c if (ps->paths && pa_hashmap_size(ps->paths) > 0) { pa_assert(card); - pa_alsa_path_set_add_ports(ps, NULL, card->ports, ports, card->core); + pa_alsa_path_set_add_ports(ps, NULL, card->ports, ports); } pa_log_debug("Added %u ports", pa_hashmap_size(ports)); } + +static pa_device_port *create_port(pa_core *core, pa_alsa_path *path, pa_alsa_setting *setting) { + char *name = NULL; + char *description = NULL; + pa_device_port_new_data port_data; + pa_device_port *port; + pa_alsa_port_data *data; + + pa_assert(core); + pa_assert(path); + + if (setting) { + name = pa_sprintf_malloc("%s;%s", path->name, setting->name); + + if (setting->description[0]) + description = pa_sprintf_malloc("%s / %s", path->description, setting->description); + else + description = pa_xstrdup(path->description); + } else { + name = pa_xstrdup(path->name); + description = pa_xstrdup(path->description); + } + + pa_device_port_new_data_init(&port_data); + pa_device_port_new_data_set_name(&port_data, name); + pa_device_port_new_data_set_description(&port_data, description); + pa_device_port_new_data_set_direction(&port_data, + path->direction == PA_ALSA_DIRECTION_OUTPUT ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT); + pa_node_new_data_set_fallback_name_prefix(&port_data.node_data, "alsa"); + + port = pa_device_port_new(core, &port_data, sizeof(pa_alsa_port_data)); + pa_device_port_new_data_done(&port_data); + + if (!port) { + pa_log("Failed to create port %s.", name); + goto finish; + } + + port->priority = path->priority * 100; + + if (setting) + port->priority += setting->priority; + + pa_proplist_update(port->proplist, PA_UPDATE_REPLACE, path->proplist); + + data = PA_DEVICE_PORT_DATA(port); + data->path = path; + data->setting = setting; + + pa_dynarray_append(path->ports, port); + +finish: + pa_xfree(description); + pa_xfree(name); + + return port; +} + +static void path_create_ports(pa_core *core, pa_alsa_path *path, pa_hashmap *ports) { + pa_device_port *port; + + pa_assert(core); + pa_assert(path); + pa_assert(ports); + + if (!path->settings || !path->settings->next) { + /* If there is no or just one setting we only need a single entry. */ + port = create_port(core, path, NULL); + + if (port) + pa_hashmap_put(ports, port->name, port); + } else { + pa_alsa_setting *setting; + + PA_LLIST_FOREACH(setting, path->settings) { + port = create_port(core, path, setting); + + if (port) + pa_hashmap_put(ports, port->name, port); + } + } +} + +void pa_alsa_profile_set_create_ports(pa_core *core, pa_alsa_profile_set *profile_set, pa_hashmap *ports) { + pa_alsa_path *path; + void *state; + + pa_assert(core); + pa_assert(profile_set); + pa_assert(ports); + + PA_HASHMAP_FOREACH(path, profile_set->output_paths, state) + path_create_ports(core, path, ports); + + PA_HASHMAP_FOREACH(path, profile_set->input_paths, state) + path_create_ports(core, path, ports); +} diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h index 7a27ac3..a39befe 100644 --- a/src/modules/alsa/alsa-mixer.h +++ b/src/modules/alsa/alsa-mixer.h @@ -355,6 +355,7 @@ struct pa_alsa_port_data { }; void pa_alsa_add_ports(void *sink_or_source_new_data, pa_alsa_path_set *ps, pa_card *card); -void pa_alsa_path_set_add_ports(pa_alsa_path_set *ps, pa_card_profile *cp, pa_hashmap *ports, pa_hashmap *extra, pa_core *core); +void pa_alsa_path_set_add_ports(pa_alsa_path_set *ps, pa_card_profile *cp, pa_hashmap *ports, pa_hashmap *extra); +void pa_alsa_profile_set_create_ports(pa_core *core, pa_alsa_profile_set *profile_set, pa_hashmap *ports); #endif diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index 7576043..4b09c95 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -163,7 +163,7 @@ static void add_profiles(struct userdata *u, pa_card_new_data *data) { if (u->use_ucm) pa_alsa_ucm_add_ports_combination(NULL, &m->ucm_context, true, data->ports, cp, u->core); else - pa_alsa_path_set_add_ports(m->output_path_set, cp, data->ports, NULL, u->core); + pa_alsa_path_set_add_ports(m->output_path_set, cp, data->ports, NULL); if (m->channel_map.channels > cp->max_sink_channels) cp->max_sink_channels = m->channel_map.channels; } @@ -179,7 +179,7 @@ static void add_profiles(struct userdata *u, pa_card_new_data *data) { if (u->use_ucm) pa_alsa_ucm_add_ports_combination(NULL, &m->ucm_context, false, data->ports, cp, u->core); else - pa_alsa_path_set_add_ports(m->input_path_set, cp, data->ports, NULL, u->core); + pa_alsa_path_set_add_ports(m->input_path_set, cp, data->ports, NULL); if (m->channel_map.channels > cp->max_source_channels) cp->max_source_channels = m->channel_map.channels; } @@ -711,6 +711,7 @@ int pa__init(pa_module *m) { if ((description = pa_proplist_gets(data.proplist, PA_PROP_DEVICE_DESCRIPTION))) pa_reserve_wrapper_set_application_device_name(reserve, description); + pa_alsa_profile_set_create_ports(u->core, u->profile_set, data.ports); add_profiles(u, &data); if (pa_hashmap_isempty(data.profiles)) { -- 1.8.3.1