This simplifies profile creation, and the ownership of device prototypes is clearer. --- src/modules/alsa/alsa-mixer.c | 18 +++++++++++++++ src/modules/alsa/alsa-mixer.h | 1 + src/modules/alsa/module-alsa-card.c | 29 ++++++++++++++++++++----- src/modules/bluetooth/module-bluetooth-device.c | 18 +++++++-------- src/pulsecore/card.c | 25 ++++++--------------- src/pulsecore/card.h | 13 ++++++----- 6 files changed, 64 insertions(+), 40 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index 14bfd88..1e08ec3 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -3382,6 +3382,24 @@ pa_alsa_mapping *pa_alsa_mapping_get(pa_alsa_profile_set *ps, const char *name) return m; } +pa_device_prototype *pa_alsa_mapping_create_device_prototype(pa_alsa_mapping *mapping, pa_direction_t direction) { + pa_device_prototype *prototype; + + pa_assert(mapping); + + prototype = pa_device_prototype_new(direction); + + if (direction == PA_DIRECTION_OUTPUT) { + pa_assert(!mapping->sink_prototype); + mapping->sink_prototype = prototype; + } else { + pa_assert(!mapping->source_prototype); + mapping->source_prototype = prototype; + } + + return prototype; +} + static pa_alsa_profile *profile_get(pa_alsa_profile_set *ps, const char *name) { pa_alsa_profile *p; diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h index 6869261..0a2a4e5 100644 --- a/src/modules/alsa/alsa-mixer.h +++ b/src/modules/alsa/alsa-mixer.h @@ -328,6 +328,7 @@ void pa_alsa_mapping_dump(pa_alsa_mapping *m); void pa_alsa_profile_dump(pa_alsa_profile *p); void pa_alsa_decibel_fix_dump(pa_alsa_decibel_fix *db_fix); pa_alsa_mapping *pa_alsa_mapping_get(pa_alsa_profile_set *ps, const char *name); +pa_device_prototype *pa_alsa_mapping_create_device_prototype(pa_alsa_mapping *mapping, pa_direction_t direction); pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus); void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss, unsigned default_n_fragments, unsigned default_fragment_size_msec); diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index 4b09c95..c427386 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -137,6 +137,28 @@ struct profile_data { pa_alsa_profile *profile; }; +static void add_device_prototypes(struct userdata *u, pa_card_new_data *data) { + pa_alsa_mapping *mapping; + void *state; + + pa_assert(u); + pa_assert(data); + + PA_HASHMAP_FOREACH(mapping, u->profile_set->mappings, state) { + pa_device_prototype *prototype; + + if (mapping->direction == PA_ALSA_DIRECTION_ANY || mapping->direction == PA_ALSA_DIRECTION_OUTPUT) { + prototype = pa_alsa_mapping_create_device_prototype(mapping, PA_DIRECTION_OUTPUT); + pa_card_new_data_add_device_prototype(data, prototype); + } + + if (mapping->direction == PA_ALSA_DIRECTION_ANY || mapping->direction == PA_ALSA_DIRECTION_INPUT) { + prototype = pa_alsa_mapping_create_device_prototype(mapping, PA_DIRECTION_INPUT); + pa_card_new_data_add_device_prototype(data, prototype); + } + } +} + static void add_profiles(struct userdata *u, pa_card_new_data *data) { pa_alsa_profile *ap; void *state; @@ -155,9 +177,6 @@ static void add_profiles(struct userdata *u, pa_card_new_data *data) { if (ap->output_mappings) { PA_IDXSET_FOREACH(m, ap->output_mappings, idx) { - if (!m->sink_prototype) - m->sink_prototype = pa_device_prototype_new(PA_DIRECTION_OUTPUT); - pa_hashmap_put(cp->sink_prototypes, m->sink_prototype, m->sink_prototype); if (u->use_ucm) @@ -171,9 +190,6 @@ static void add_profiles(struct userdata *u, pa_card_new_data *data) { if (ap->input_mappings) { PA_IDXSET_FOREACH(m, ap->input_mappings, idx) { - if (!m->source_prototype) - m->source_prototype = pa_device_prototype_new(PA_DIRECTION_INPUT); - pa_hashmap_put(cp->source_prototypes, m->source_prototype, m->source_prototype); if (u->use_ucm) @@ -712,6 +728,7 @@ int pa__init(pa_module *m) { pa_reserve_wrapper_set_application_device_name(reserve, description); pa_alsa_profile_set_create_ports(u->core, u->profile_set, data.ports); + add_device_prototypes(u, &data); add_profiles(u, &data); if (pa_hashmap_isempty(data.profiles)) { diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index 59acaf8..f44eb2f 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -2203,16 +2203,6 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid else if (pa_streq(uuid, HFP_AG_UUID)) profile = PROFILE_HFGW; - if (profile == PROFILE_A2DP || (!USE_SCO_OVER_PCM(u) && (profile == PROFILE_HSP || profile == PROFILE_HFGW))) { - if (!u->sink_prototype) - u->sink_prototype = pa_device_prototype_new(PA_DIRECTION_OUTPUT); - } - - if (profile == PROFILE_A2DP_SOURCE || (!USE_SCO_OVER_PCM(u) && (profile == PROFILE_HSP || profile == PROFILE_HFGW))) { - if (!u->source_prototype) - u->source_prototype = pa_device_prototype_new(PA_DIRECTION_INPUT); - } - if (profile == PROFILE_A2DP) { p = pa_card_profile_new("a2dp", _("High Fidelity Playback (A2DP)"), sizeof(enum profile)); p->priority = 10; @@ -2326,6 +2316,14 @@ static int add_card(struct userdata *u) { return -1; } + /* We create prototypes for both directions even if the device only + * supports one direction, because it makes the code simpler. Having an + * extra prototype does no harm. */ + u->sink_prototype = pa_device_prototype_new(PA_DIRECTION_OUTPUT); + pa_card_new_data_add_device_prototype(&data, u->sink_prototype); + u->source_prototype = pa_device_prototype_new(PA_DIRECTION_INPUT); + pa_card_new_data_add_device_prototype(&data, u->source_prototype); + PA_LLIST_FOREACH(uuid, device->uuids) { p = create_card_profile(u, uuid->uuid, data.ports); diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c index 32e1652..7f57e02 100644 --- a/src/pulsecore/card.c +++ b/src/pulsecore/card.c @@ -131,20 +131,18 @@ void pa_card_new_data_set_name(pa_card_new_data *data, const char *name) { data->name = pa_xstrdup(name); } -void pa_card_new_data_add_profile(pa_card_new_data *data, pa_card_profile *profile) { - pa_device_prototype *prototype; - void *state; +void pa_card_new_data_add_device_prototype(pa_card_new_data *data, pa_device_prototype *prototype) { + pa_assert(data); + pa_assert(prototype); + + pa_hashmap_put(data->device_prototypes, prototype, prototype); +} +void pa_card_new_data_add_profile(pa_card_new_data *data, pa_card_profile *profile) { pa_assert(data); pa_assert(profile); pa_assert_se(pa_hashmap_put(data->profiles, profile->name, profile) >= 0); - - PA_HASHMAP_FOREACH(prototype, profile->sink_prototypes, state) - pa_hashmap_put(data->device_prototypes, prototype, prototype); - - PA_HASHMAP_FOREACH(prototype, profile->source_prototypes, state) - pa_hashmap_put(data->device_prototypes, prototype, prototype); } void pa_card_new_data_set_profile(pa_card_new_data *data, const char *profile) { @@ -299,9 +297,6 @@ void pa_card_free(pa_card *c) { } void pa_card_add_profile(pa_card *c, pa_card_profile *profile) { - pa_device_prototype *prototype; - void *state; - pa_assert(c); pa_assert(profile); @@ -309,12 +304,6 @@ void pa_card_add_profile(pa_card *c, pa_card_profile *profile) { pa_assert_se(pa_hashmap_put(c->profiles, profile->name, profile) >= 0); profile->card = c; - PA_HASHMAP_FOREACH(prototype, profile->sink_prototypes, state) - pa_hashmap_put(c->device_prototypes, prototype, prototype); - - PA_HASHMAP_FOREACH(prototype, profile->source_prototypes, state) - pa_hashmap_put(c->device_prototypes, prototype, prototype); - pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, c->index); pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CARD_PROFILE_ADDED], profile); diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h index ce1cb22..850dfa1 100644 --- a/src/pulsecore/card.h +++ b/src/pulsecore/card.h @@ -64,10 +64,6 @@ typedef struct pa_card_profile { unsigned priority; pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */ - /* When populating these hashmaps, note that you initially own the device - * prototype objects that you add, but once you call - * pa_card_new_data_add_profile(), the prototype ownership moves to - * pa_card_new_data (and later to pa_card). */ pa_hashmap *sink_prototypes; /* pa_device_prototype -> pa_device_prototype (hashmap-as-a-set) */ pa_hashmap *source_prototypes; /* pa_device_prototype -> pa_device_prototype (hashmap-as-a-set) */ @@ -119,8 +115,6 @@ typedef struct pa_card_new_data { const char *driver; pa_module *module; - /* Don't populate this manually. pa_card_new_data_add_profile() will - * automatically add the prototypes from the added profile. */ pa_hashmap *device_prototypes; /* pa_device_prototype -> pa_device_prototype (hashmap-as-a-set) */ pa_hashmap *profiles; @@ -156,7 +150,13 @@ void pa_card_profile_set_available(pa_card_profile *c, pa_available_t available) pa_card_new_data *pa_card_new_data_init(pa_card_new_data *data); void pa_card_new_data_set_name(pa_card_new_data *data, const char *name); + +/* The ownership of the prototype moves to pa_card_new_data. */ +void pa_card_new_data_add_device_prototype(pa_card_new_data *data, pa_device_prototype *prototype); + +/* The ownership of the profile moves to pa_card_new_data. */ void pa_card_new_data_add_profile(pa_card_new_data *data, pa_card_profile *profile); + void pa_card_new_data_set_profile(pa_card_new_data *data, const char *profile); void pa_card_new_data_set_recreate_devices_on_profile_switch(pa_card_new_data *data, bool recreate); void pa_card_new_data_done(pa_card_new_data *data); @@ -164,6 +164,7 @@ void pa_card_new_data_done(pa_card_new_data *data); pa_card *pa_card_new(pa_core *c, pa_card_new_data *data); void pa_card_free(pa_card *c); +/* The ownership of the profile moves to pa_card. */ void pa_card_add_profile(pa_card *c, pa_card_profile *profile); int pa_card_set_profile(pa_card *c, pa_card_profile *profile, bool save, bool bypass_router); -- 1.8.3.1