src/modules/alsa/alsa-mixer.c | 8 + src/modules/alsa/alsa-mixer.h | 3 src/modules/alsa/module-alsa-card.c | 2 src/modules/module-card-restore.c | 58 ++++++-- src/modules/module-switch-on-port-available.c | 179 ++++++++++++++++---------- src/pulsecore/card.c | 20 ++ src/pulsecore/card.h | 8 + src/pulsecore/device-port.c | 11 + src/pulsecore/device-port.h | 2 9 files changed, 212 insertions(+), 79 deletions(-)
New commits: commit bea37613ceda60c6843e2afc5e7c5859dbe570c1 Author: David Henningsson <[email protected]> Date: Tue Nov 17 15:10:36 2015 +0100 module-card-restore: Remove "version" from internal entry struct If we always write entries of the latest version, we can simplify code a little by only handling old versions in the "entry_read" function and assume we have the latest version everywhere else. Suggested-by: Tanu Kaskinen <[email protected]> Signed-off-by: David Henningsson <[email protected]> diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c index b30fa36..f906843 100644 --- a/src/modules/module-card-restore.c +++ b/src/modules/module-card-restore.c @@ -73,7 +73,6 @@ struct port_info { }; struct entry { - uint8_t version; char *profile; pa_hashmap *ports; /* Port name -> struct port_info */ }; @@ -110,7 +109,6 @@ static void port_info_free(struct port_info *p_info) { static struct entry* entry_new(void) { struct entry *r = pa_xnew0(struct entry, 1); - r->version = ENTRY_VERSION; r->ports = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) port_info_free); return r; } @@ -193,15 +191,14 @@ static bool entry_write(struct userdata *u, const char *name, const struct entry pa_assert(e); t = pa_tagstruct_new(); - pa_tagstruct_putu8(t, e->version); + pa_tagstruct_putu8(t, ENTRY_VERSION); pa_tagstruct_puts(t, e->profile); pa_tagstruct_putu32(t, pa_hashmap_size(e->ports)); PA_HASHMAP_FOREACH(p_info, e->ports, state) { pa_tagstruct_puts(t, p_info->name); pa_tagstruct_puts64(t, p_info->offset); - if (e->version >= 3) - pa_tagstruct_puts(t, p_info->profile); + pa_tagstruct_puts(t, p_info->profile); } key.data = (char *) name; @@ -258,6 +255,7 @@ static struct entry* entry_read(struct userdata *u, const char *name) { struct entry *e = NULL; pa_tagstruct *t = NULL; const char* profile; + uint8_t version; pa_assert(u); pa_assert(name); @@ -275,8 +273,8 @@ static struct entry* entry_read(struct userdata *u, const char *name) { t = pa_tagstruct_new_fixed(data.data, data.size); e = entry_new(); - if (pa_tagstruct_getu8(t, &e->version) < 0 || - e->version > ENTRY_VERSION || + if (pa_tagstruct_getu8(t, &version) < 0 || + version > ENTRY_VERSION || pa_tagstruct_gets(t, &profile) < 0) { goto fail; @@ -287,7 +285,7 @@ static struct entry* entry_read(struct userdata *u, const char *name) { e->profile = pa_xstrdup(profile); - if (e->version >= 2) { + if (version >= 2) { uint32_t port_count = 0; const char *port_name = NULL, *profile_name = NULL; int64_t port_offset = 0; @@ -303,7 +301,7 @@ static struct entry* entry_read(struct userdata *u, const char *name) { pa_hashmap_get(e->ports, port_name) || pa_tagstruct_gets64(t, &port_offset) < 0) goto fail; - if (e->version >= 3 && pa_tagstruct_gets(t, &profile_name) < 0) + if (version >= 3 && pa_tagstruct_gets(t, &profile_name) < 0) goto fail; p_info = port_info_new(NULL); @@ -399,7 +397,6 @@ static void update_profile_for_port(struct entry *entry, pa_card *card, pa_devic if (!pa_safe_streq(p_info->profile, p->preferred_profile)) { pa_xfree(p_info->profile); p_info->profile = pa_xstrdup(p->preferred_profile); - entry->version = ENTRY_VERSION; pa_log_info("Storing profile %s for port %s on card %s.", p_info->profile, p->name, card->name); } } commit e87100d41ef6d14f8dc7f803582191d9f8d8f183 Author: David Henningsson <[email protected]> Date: Tue Nov 17 15:10:35 2015 +0100 module-switch-on-port-available: Route to preferred profile This makes the routing slightly more aggressive: * It will try to route to another profile, if such a profile is preferred by the port. * It will allow changing profiles on transitions both to PA_AVAILABLE_YES and PA_AVAILABLE_NO To accommodate there is also some refactoring. Signed-off-by: David Henningsson <[email protected]> diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c index 8de68a3..5dd9786 100644 --- a/src/modules/module-switch-on-port-available.c +++ b/src/modules/module-switch-on-port-available.c @@ -74,22 +74,25 @@ static bool profile_good_for_input(pa_card_profile *profile) { static int try_to_switch_profile(pa_device_port *port) { pa_card_profile *best_profile = NULL, *profile; void *state; + unsigned best_prio = 0; - pa_log_debug("Finding best profile"); + pa_log_debug("Finding best profile for port %s, preferred = %s", + port->name, pa_strnull(port->preferred_profile)); PA_HASHMAP_FOREACH(profile, port->profiles, state) { bool good = false; - - if (best_profile && best_profile->priority >= profile->priority) - continue; + const char *name; + unsigned prio = profile->priority; /* We make a best effort to keep other direction unchanged */ switch (port->direction) { case PA_DIRECTION_OUTPUT: + name = profile->output_name; good = profile_good_for_output(profile); break; case PA_DIRECTION_INPUT: + name = profile->input_name; good = profile_good_for_input(profile); break; } @@ -97,7 +100,15 @@ static int try_to_switch_profile(pa_device_port *port) { if (!good) continue; + /* Give a high bonus in case this is the preferred profile */ + if (port->preferred_profile && pa_streq(name ? name : profile->name, port->preferred_profile)) + prio += 1000000; + + if (best_profile && best_prio >= prio) + continue; + best_profile = profile; + best_prio = prio; } if (!best_profile) { @@ -113,98 +124,125 @@ static int try_to_switch_profile(pa_device_port *port) { return 0; } -static void find_sink_and_source(pa_card *card, pa_device_port *port, pa_sink **si, pa_source **so) { - pa_sink *sink = NULL; - pa_source *source = NULL; +struct port_pointers { + pa_device_port *port; + pa_sink *sink; + pa_source *source; + bool is_possible_profile_active; + bool is_preferred_profile_active; + bool is_port_active; +}; + +static const char* profile_name_for_dir(pa_card_profile *cp, pa_direction_t dir) { + if (dir == PA_DIRECTION_OUTPUT && cp->output_name) + return cp->output_name; + if (dir == PA_DIRECTION_INPUT && cp->input_name) + return cp->input_name; + return cp->name; +} + +static struct port_pointers find_port_pointers(pa_device_port *port) { + struct port_pointers pp = { .port = port }; uint32_t state; + pa_card *card; + + pa_assert(port); + pa_assert_se(card = port->card); switch (port->direction) { case PA_DIRECTION_OUTPUT: - PA_IDXSET_FOREACH(sink, card->sinks, state) - if (port == pa_hashmap_get(sink->ports, port->name)) + PA_IDXSET_FOREACH(pp.sink, card->sinks, state) + if (port == pa_hashmap_get(pp.sink->ports, port->name)) break; break; case PA_DIRECTION_INPUT: - PA_IDXSET_FOREACH(source, card->sources, state) - if (port == pa_hashmap_get(source->ports, port->name)) + PA_IDXSET_FOREACH(pp.source, card->sources, state) + if (port == pa_hashmap_get(pp.source->ports, port->name)) break; break; } - *si = sink; - *so = source; -} + pp.is_possible_profile_active = + card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name); + pp.is_preferred_profile_active = pp.is_possible_profile_active && (!port->preferred_profile || + pa_safe_streq(port->preferred_profile, profile_name_for_dir(card->active_profile, port->direction))); + pp.is_port_active = (pp.sink && pp.sink->active_port == port) || (pp.source && pp.source->active_port == port); -static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) { - pa_card* card; - pa_sink *sink; - pa_source *source; - bool is_active_profile, is_active_port; + return pp; +} - if (port->available == PA_AVAILABLE_UNKNOWN) - return PA_HOOK_OK; +/* Switches to a port, switching profiles if necessary or preferred */ +static bool switch_to_port(pa_device_port *port) { + struct port_pointers pp = find_port_pointers(port); - card = port->card; + if (pp.is_port_active) + return true; /* Already selected */ - if (!card) { - pa_log_warn("Port %s does not have a card", port->name); - return PA_HOOK_OK; + pa_log_debug("Trying to switch to port %s", port->name); + if (!pp.is_preferred_profile_active) { + if (try_to_switch_profile(port) < 0) { + if (pp.is_possible_profile_active) + return false; + } + else + /* Now that profile has changed, our sink and source pointers must be updated */ + pp = find_port_pointers(port); } - if (pa_idxset_size(card->sinks) == 0 && pa_idxset_size(card->sources) == 0) - /* This card is not initialized yet. We'll handle it in - sink_new / source_new callbacks later. */ - return PA_HOOK_OK; + if (pp.source) + pa_source_set_port(pp.source, port->name, false); + if (pp.sink) + pa_sink_set_port(pp.sink, port->name, false); + return true; +} - find_sink_and_source(card, port, &sink, &source); +/* Switches away from a port, switching profiles if necessary or preferred */ +static bool switch_from_port(pa_device_port *port) { + struct port_pointers pp = find_port_pointers(port); + pa_device_port *p, *best_port = NULL; + void *state; - is_active_profile = card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name); - is_active_port = (sink && sink->active_port == port) || (source && source->active_port == port); + if (!pp.is_port_active) + return true; /* Already deselected */ - if (port->available == PA_AVAILABLE_NO && !is_active_port) - return PA_HOOK_OK; + /* Try to find a good enough port to switch to */ + PA_HASHMAP_FOREACH(p, port->card->ports, state) + if (p->direction == port->direction && p != port && p->available != PA_AVAILABLE_NO && + (!best_port || best_port->priority < p->priority)) + best_port = p; - if (port->available == PA_AVAILABLE_YES) { - if (is_active_port) - return PA_HOOK_OK; + pa_log_debug("Trying to switch away from port %s, found %s", port->name, best_port ? best_port->name : "no better option"); - if (!is_active_profile) { - if (try_to_switch_profile(port) < 0) - return PA_HOOK_OK; + if (best_port) + return switch_to_port(best_port); - pa_assert(card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name)); + return false; +} - /* Now that profile has changed, our sink and source pointers must be updated */ - find_sink_and_source(card, port, &sink, &source); - } - if (source) - pa_source_set_port(source, port->name, false); - if (sink) - pa_sink_set_port(sink, port->name, false); - } - - if (port->available == PA_AVAILABLE_NO) { - if (sink) { - pa_device_port *p2 = pa_device_port_find_best(sink->ports); +static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) { + pa_assert(port); - if (p2 && p2->available != PA_AVAILABLE_NO) - pa_sink_set_port(sink, p2->name, false); - else { - /* Maybe try to switch to another profile? */ - } - } + if (!port->card) { + pa_log_warn("Port %s does not have a card", port->name); + return PA_HOOK_OK; + } - if (source) { - pa_device_port *p2 = pa_device_port_find_best(source->ports); + if (pa_idxset_size(port->card->sinks) == 0 && pa_idxset_size(port->card->sources) == 0) + /* This card is not initialized yet. We'll handle it in + sink_new / source_new callbacks later. */ + return PA_HOOK_OK; - if (p2 && p2->available != PA_AVAILABLE_NO) - pa_source_set_port(source, p2->name, false); - else { - /* Maybe try to switch to another profile? */ - } - } + switch (port->available) { + case PA_AVAILABLE_YES: + switch_to_port(port); + break; + case PA_AVAILABLE_NO: + switch_from_port(port); + break; + default: + break; } return PA_HOOK_OK; commit 063a1d350fad1cb6fac28dbffe26a7e805626cb2 Author: David Henningsson <[email protected]> Date: Tue Nov 17 15:10:34 2015 +0100 module-switch-on-port-available: Use input and output names In case input or output names are filled in, we can use this to get a better match in the profile_good_for_input/output functions instead of guessing based on number of sources and channels. Signed-off-by: David Henningsson <[email protected]> diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c index eb8f2d7..8de68a3 100644 --- a/src/modules/module-switch-on-port-available.c +++ b/src/modules/module-switch-on-port-available.c @@ -23,6 +23,7 @@ #endif #include <pulsecore/core.h> +#include <pulsecore/core-util.h> #include <pulsecore/device-port.h> #include <pulsecore/hashmap.h> @@ -34,6 +35,9 @@ static bool profile_good_for_output(pa_card_profile *profile) { pa_assert(profile); + if (!pa_safe_streq(profile->card->active_profile->input_name, profile->input_name)) + return false; + if (profile->card->active_profile->n_sources != profile->n_sources) return false; @@ -55,6 +59,9 @@ static bool profile_good_for_output(pa_card_profile *profile) { static bool profile_good_for_input(pa_card_profile *profile) { pa_assert(profile); + if (!pa_safe_streq(profile->card->active_profile->output_name, profile->output_name)) + return false; + if (profile->card->active_profile->n_sinks != profile->n_sinks) return false; commit 9059fb3b4ed7ade607846f4846842c2b1ce699fa Author: David Henningsson <[email protected]> Date: Tue Nov 17 15:10:33 2015 +0100 card-restore: Save and restore "preferred profile" of port Signed-off-by: David Henningsson <[email protected]> diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c index 3725d30..b30fa36 100644 --- a/src/modules/module-card-restore.c +++ b/src/modules/module-card-restore.c @@ -64,11 +64,12 @@ struct userdata { pa_database *database; }; -#define ENTRY_VERSION 2 +#define ENTRY_VERSION 3 struct port_info { char *name; int64_t offset; + char *profile; }; struct entry { @@ -102,6 +103,7 @@ static void trigger_save(struct userdata *u) { static void port_info_free(struct port_info *p_info) { pa_assert(p_info); + pa_xfree(p_info->profile); pa_xfree(p_info->name); pa_xfree(p_info); } @@ -117,9 +119,11 @@ static struct port_info *port_info_new(pa_device_port *port) { struct port_info *p_info; if (port) { - p_info = pa_xnew(struct port_info, 1); + p_info = pa_xnew0(struct port_info, 1); p_info->name = pa_xstrdup(port->name); p_info->offset = port->latency_offset; + if (port->preferred_profile) + p_info->profile = pa_xstrdup(port->preferred_profile); } else p_info = pa_xnew0(struct port_info, 1); @@ -196,6 +200,8 @@ static bool entry_write(struct userdata *u, const char *name, const struct entry PA_HASHMAP_FOREACH(p_info, e->ports, state) { pa_tagstruct_puts(t, p_info->name); pa_tagstruct_puts64(t, p_info->offset); + if (e->version >= 3) + pa_tagstruct_puts(t, p_info->profile); } key.data = (char *) name; @@ -283,7 +289,7 @@ static struct entry* entry_read(struct userdata *u, const char *name) { if (e->version >= 2) { uint32_t port_count = 0; - const char *port_name = NULL; + const char *port_name = NULL, *profile_name = NULL; int64_t port_offset = 0; struct port_info *p_info; unsigned i; @@ -297,10 +303,14 @@ static struct entry* entry_read(struct userdata *u, const char *name) { pa_hashmap_get(e->ports, port_name) || pa_tagstruct_gets64(t, &port_offset) < 0) goto fail; + if (e->version >= 3 && pa_tagstruct_gets(t, &profile_name) < 0) + goto fail; p_info = port_info_new(NULL); p_info->name = pa_xstrdup(port_name); p_info->offset = port_offset; + if (profile_name) + p_info->profile = pa_xstrdup(profile_name); pa_assert_se(pa_hashmap_put(e->ports, p_info->name, p_info) >= 0); } @@ -375,8 +385,30 @@ finish: return PA_HOOK_OK; } +static void update_profile_for_port(struct entry *entry, pa_card *card, pa_device_port *p) { + struct port_info *p_info; + + if (p == NULL) + return; + + if (!(p_info = pa_hashmap_get(entry->ports, p->name))) { + p_info = port_info_new(p); + pa_assert_se(pa_hashmap_put(entry->ports, p_info->name, p_info) >= 0); + } + + if (!pa_safe_streq(p_info->profile, p->preferred_profile)) { + pa_xfree(p_info->profile); + p_info->profile = pa_xstrdup(p->preferred_profile); + entry->version = ENTRY_VERSION; + pa_log_info("Storing profile %s for port %s on card %s.", p_info->profile, p->name, card->name); + } +} + static pa_hook_result_t card_profile_changed_callback(pa_core *c, pa_card *card, struct userdata *u) { struct entry *entry; + pa_sink *sink; + pa_source *source; + uint32_t state; pa_assert(card); @@ -392,6 +424,11 @@ static pa_hook_result_t card_profile_changed_callback(pa_core *c, pa_card *card, show_full_info(card); } + PA_IDXSET_FOREACH(sink, card->sinks, state) + update_profile_for_port(entry, card, sink->active_port); + PA_IDXSET_FOREACH(source, card->sources, state) + update_profile_for_port(entry, card, source->active_port); + if (entry_write(u, card->name, entry)) trigger_save(u); @@ -508,9 +545,11 @@ static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new pa_log_info("Restoring port latency offsets for card %s.", new_data->name); PA_HASHMAP_FOREACH(p_info, e->ports, state) - if ((p = pa_hashmap_get(new_data->ports, p_info->name))) + if ((p = pa_hashmap_get(new_data->ports, p_info->name))) { p->latency_offset = p_info->offset; - + if (!p->preferred_profile && p_info->profile) + pa_device_port_set_preferred_profile(p, p_info->profile); + } entry_free(e); return PA_HOOK_OK; commit 5c545ba38be33bfc5334a70edacba24f06271af5 Author: David Henningsson <[email protected]> Date: Tue Nov 17 15:10:32 2015 +0100 card: Update preferred_profile for ports when profile changes Signed-off-by: David Henningsson <[email protected]> diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c index bb21d0f..0ca78bb 100644 --- a/src/pulsecore/card.c +++ b/src/pulsecore/card.c @@ -250,8 +250,19 @@ void pa_card_add_profile(pa_card *c, pa_card_profile *profile) { pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CARD_PROFILE_ADDED], profile); } +static const char* profile_name_for_dir(pa_card_profile *cp, pa_direction_t dir) { + if (dir == PA_DIRECTION_OUTPUT && cp->output_name) + return cp->output_name; + if (dir == PA_DIRECTION_INPUT && cp->input_name) + return cp->input_name; + return cp->name; +} + int pa_card_set_profile(pa_card *c, pa_card_profile *profile, bool save) { int r; + pa_sink *sink; + pa_source *source; + uint32_t state; pa_assert(c); pa_assert(profile); @@ -277,6 +288,13 @@ int pa_card_set_profile(pa_card *c, pa_card_profile *profile, bool save) { c->active_profile = profile; c->save_profile = save; + PA_IDXSET_FOREACH(sink, c->sinks, state) + if (sink->active_port) + pa_device_port_set_preferred_profile(sink->active_port, profile_name_for_dir(profile, PA_DIRECTION_OUTPUT)); + PA_IDXSET_FOREACH(source, c->sources, state) + if (source->active_port) + pa_device_port_set_preferred_profile(source->active_port, profile_name_for_dir(profile, PA_DIRECTION_INPUT)); + pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], c); return 0; commit b1d9b4f62c2f132292efaba862e8490114882ad2 Author: David Henningsson <[email protected]> Date: Tue Nov 17 15:10:31 2015 +0100 device-port: Add preferred_profile field to pa_device_port Signed-off-by: David Henningsson <[email protected]> diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c index 906ab1f..5807d3e 100644 --- a/src/pulsecore/device-port.c +++ b/src/pulsecore/device-port.c @@ -21,6 +21,7 @@ #include "device-port.h" #include <pulsecore/card.h> +#include <pulsecore/core-util.h> PA_DEFINE_PUBLIC_CLASS(pa_device_port, pa_object); @@ -65,6 +66,15 @@ void pa_device_port_new_data_done(pa_device_port_new_data *data) { pa_xfree(data->description); } +void pa_device_port_set_preferred_profile(pa_device_port *p, const char *new_pp) { + pa_assert(p); + + if (!pa_safe_streq(p->preferred_profile, new_pp)) { + pa_xfree(p->preferred_profile); + p->preferred_profile = pa_xstrdup(new_pp); + } +} + void pa_device_port_set_available(pa_device_port *p, pa_available_t status) { pa_assert(p); @@ -100,6 +110,7 @@ static void device_port_free(pa_object *o) { if (p->profiles) pa_hashmap_free(p->profiles); + pa_xfree(p->preferred_profile); pa_xfree(p->name); pa_xfree(p->description); pa_xfree(p); diff --git a/src/pulsecore/device-port.h b/src/pulsecore/device-port.h index f35d07c..e3224fd 100644 --- a/src/pulsecore/device-port.h +++ b/src/pulsecore/device-port.h @@ -43,6 +43,7 @@ struct pa_device_port { char *name; char *description; + char *preferred_profile; unsigned priority; pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */ @@ -80,6 +81,7 @@ pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, si void pa_device_port_set_available(pa_device_port *p, pa_available_t available); void pa_device_port_set_latency_offset(pa_device_port *p, int64_t offset); +void pa_device_port_set_preferred_profile(pa_device_port *p, const char *new_pp); pa_device_port *pa_device_port_find_best(pa_hashmap *ports); commit 2a71fd7597dd76eb6abab867cd3762429792f680 Author: David Henningsson <[email protected]> Date: Tue Nov 17 15:10:30 2015 +0100 alsa-mixer: Fill in input and output names Fill in input_name and output_name to make routing easier for routing modules. Signed-off-by: David Henningsson <[email protected]> diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index af7adea..3f51717 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -3473,6 +3473,8 @@ static void profile_free(pa_alsa_profile *p) { pa_xfree(p->name); pa_xfree(p->description); + pa_xfree(p->input_name); + pa_xfree(p->output_name); pa_xstrfreev(p->input_mapping_names); pa_xstrfreev(p->output_mapping_names); @@ -4123,6 +4125,7 @@ static void profile_set_add_auto_pair( p->name = name; if (m) { + p->output_name = pa_xstrdup(m->name); p->output_mappings = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); pa_idxset_put(p->output_mappings, m, NULL); p->priority += m->priority * 100; @@ -4130,6 +4133,7 @@ static void profile_set_add_auto_pair( } if (n) { + p->input_name = pa_xstrdup(n->name); p->input_mappings = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); pa_idxset_put(p->input_mappings, n, NULL); p->priority += n->priority; @@ -4292,9 +4296,11 @@ void pa_alsa_profile_dump(pa_alsa_profile *p) { pa_alsa_mapping *m; pa_assert(p); - pa_log_debug("Profile %s (%s), priority=%u, supported=%s n_input_mappings=%u, n_output_mappings=%u", + pa_log_debug("Profile %s (%s), input=%s, output=%s priority=%u, supported=%s n_input_mappings=%u, n_output_mappings=%u", p->name, pa_strnull(p->description), + pa_strnull(p->input_name), + pa_strnull(p->output_name), p->priority, pa_yes_no(p->supported), p->input_mappings ? pa_idxset_size(p->input_mappings) : 0, diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h index 621a71b..4ebf192 100644 --- a/src/modules/alsa/alsa-mixer.h +++ b/src/modules/alsa/alsa-mixer.h @@ -293,6 +293,9 @@ struct pa_alsa_profile { char *description; unsigned priority; + char *input_name; + char *output_name; + bool supported:1; bool fallback_input:1; bool fallback_output:1; diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index e173e51..286cfc9 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -143,6 +143,8 @@ static void add_profiles(struct userdata *u, pa_hashmap *h, pa_hashmap *ports) { cp = pa_card_profile_new(ap->name, ap->description, sizeof(struct profile_data)); cp->priority = ap->priority; + cp->input_name = pa_xstrdup(ap->input_name); + cp->output_name = pa_xstrdup(ap->output_name); if (ap->output_mappings) { cp->n_sinks = pa_idxset_size(ap->output_mappings); commit b9818b016f021a80ab8c4ca9f2360756eefe2a87 Author: David Henningsson <[email protected]> Date: Tue Nov 17 15:10:29 2015 +0100 card: Add variables for splitting up a profile It can be useful for routing modules to know a profile's input and output parts, in order to e g change output profile while keeping the input profile unchanged. For now filling in these fields is optional and a routing module must be able to handle NULL in these fields. Signed-off-by: David Henningsson <[email protected]> diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c index c8b97b7..bb21d0f 100644 --- a/src/pulsecore/card.c +++ b/src/pulsecore/card.c @@ -52,6 +52,8 @@ pa_card_profile *pa_card_profile_new(const char *name, const char *description, void pa_card_profile_free(pa_card_profile *c) { pa_assert(c); + pa_xfree(c->input_name); + pa_xfree(c->output_name); pa_xfree(c->name); pa_xfree(c->description); pa_xfree(c); diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h index 3e2c004..a72c8c2 100644 --- a/src/pulsecore/card.h +++ b/src/pulsecore/card.h @@ -40,6 +40,14 @@ typedef struct pa_card_profile { char *name; char *description; + /* Identifiers for the profile's input and output parts, i e, if two different profiles + have the same input_name string, they have the same source(s). + Same for output_name and sink(s). + Can be NULL (and in case of an input- or output- only profile, the other direction + will be NULL). */ + char *input_name; + char *output_name; + unsigned priority; pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */ _______________________________________________ pulseaudio-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/pulseaudio-commits
