diff --git a/spa/plugins/alsa/acp/acp.c b/spa/plugins/alsa/acp/acp.c index 90af053f2..2b004ece8 100644 --- a/spa/plugins/alsa/acp/acp.c +++ b/spa/plugins/alsa/acp/acp.c @@ -56,12 +56,20 @@ const char *acp_direction_str(enum acp_direction direction) return "error"; } -static void profile_free(void *data) -{ -} - static void port_free(void *data) { + pa_device_port *dp = data; + pa_dynarray_clear(&dp->devices); + pa_dynarray_clear(&dp->prof); + pa_device_port_free(dp); +} + +static void device_free(void *data) +{ + pa_alsa_device *dev = data; + pa_dynarray_clear(&dev->port_array); + pa_proplist_free(dev->proplist); + pa_hashmap_free(dev->ports); } static void init_device(pa_card *impl, pa_alsa_device *dev, pa_alsa_direction_t direction, @@ -101,13 +109,11 @@ static void init_device(pa_card *impl, pa_alsa_device *dev, pa_alsa_direction_t pa_proplist_setf(dev->proplist, "card.profile.device", "%u", index); pa_proplist_as_dict(dev->proplist, &dev->device.props); - dev->ports = pa_hashmap_new_full(pa_idxset_string_hash_func, - pa_idxset_string_compare_func, NULL, - (pa_free_cb_t) port_free); + dev->ports = pa_hashmap_new(pa_idxset_string_hash_func, + pa_idxset_string_compare_func); if (m->ucm_context.ucm) dev->ucm_context = &m->ucm_context; pa_dynarray_init(&dev->port_array, NULL); - } static int compare_profile(const void *a, const void *b) @@ -124,6 +130,17 @@ static int compare_profile(const void *a, const void *b) return p2->profile.priority - p1->profile.priority; } +static void profile_free(void *data) +{ + pa_alsa_profile *ap = data; + pa_dynarray_clear(&ap->out.devices); + if (ap->profile.flags & ACP_PROFILE_OFF) { + free(ap->name); + free(ap->description); + free(ap); + } +} + static void add_profiles(pa_card *impl) { pa_alsa_profile *ap; @@ -135,7 +152,7 @@ static void add_profiles(pa_card *impl) uint32_t idx; n_devices = 0; - pa_dynarray_init(&impl->out.devices, NULL); + pa_dynarray_init(&impl->out.devices, device_free); ap = pa_xnew0(pa_alsa_profile, 1); ap->profile.name = ap->name = pa_xstrdup("off"); @@ -1248,6 +1265,21 @@ void acp_card_add_listener(struct acp_card *card, void acp_card_destroy(struct acp_card *card) { pa_card *impl = (pa_card *)card; + if (impl->profiles) + pa_hashmap_free(impl->profiles); + if (impl->ports) + pa_hashmap_free(impl->ports); + pa_dynarray_clear(&impl->out.devices); + pa_dynarray_clear(&impl->out.profiles); + pa_dynarray_clear(&impl->out.ports); + if (impl->ucm.mixers) + pa_hashmap_free(impl->ucm.mixers); + if (impl->jacks) + pa_hashmap_free(impl->jacks); + if (impl->profile_set) + pa_alsa_profile_set_free(impl->profile_set); + pa_alsa_ucm_free(&impl->ucm); + pa_proplist_free(impl->proplist); pa_alsa_refcnt_dec(); free(impl); } diff --git a/spa/plugins/alsa/acp/alsa-mixer.c b/spa/plugins/alsa/acp/alsa-mixer.c index f0bac46c1..f8935c572 100644 --- a/spa/plugins/alsa/acp/alsa-mixer.c +++ b/spa/plugins/alsa/acp/alsa-mixer.c @@ -3760,6 +3760,9 @@ static void mapping_free(pa_alsa_mapping *m) { if (m->output_path_set) pa_alsa_path_set_free(m->output_path_set); + pa_proplist_free(m->input_proplist); + pa_proplist_free(m->output_proplist); + pa_assert(!m->input_pcm); pa_assert(!m->output_pcm); diff --git a/spa/plugins/alsa/acp/compat.c b/spa/plugins/alsa/acp/compat.c index b2d27d871..3ce032a6a 100644 --- a/spa/plugins/alsa/acp/compat.c +++ b/spa/plugins/alsa/acp/compat.c @@ -146,6 +146,16 @@ pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, si return p; } +void pa_device_port_free(pa_device_port *port) +{ + pa_xfree(port->name); + pa_xfree(port->description); + pa_xfree(port->availability_group); + pa_hashmap_free(port->profiles); + pa_proplist_free(port->proplist); + free(port); +} + void pa_device_port_set_available(pa_device_port *p, pa_available_t status) { pa_available_t old = p->available; diff --git a/spa/plugins/alsa/acp/device-port.h b/spa/plugins/alsa/acp/device-port.h index 2cf3fc214..ee640b38f 100644 --- a/spa/plugins/alsa/acp/device-port.h +++ b/spa/plugins/alsa/acp/device-port.h @@ -108,6 +108,7 @@ void pa_device_port_new_data_set_type(pa_device_port_new_data *data, pa_device_p void pa_device_port_new_data_done(pa_device_port_new_data *data); pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, size_t extra); +void pa_device_port_free(pa_device_port *port); void pa_device_port_set_available(pa_device_port *p, pa_available_t status); diff --git a/spa/plugins/alsa/acp/hashmap.h b/spa/plugins/alsa/acp/hashmap.h index 093aba6f6..d35d304ae 100644 --- a/spa/plugins/alsa/acp/hashmap.h +++ b/spa/plugins/alsa/acp/hashmap.h @@ -67,9 +67,9 @@ static inline pa_hashmap *pa_hashmap_new_full(pa_hash_func_t hash_func, pa_compa static inline void pa_hashmap_item_free(pa_hashmap *h, pa_hashmap_item *item) { - if (h->key_free_func) + if (h->key_free_func && item->key) h->key_free_func(item->key); - if (h->value_free_func) + if (h->value_free_func && item->value) h->value_free_func(item->value); } diff --git a/spa/plugins/alsa/alsa-acp-device.c b/spa/plugins/alsa/alsa-acp-device.c index 71e7a43d9..b032bf452 100644 --- a/spa/plugins/alsa/alsa-acp-device.c +++ b/spa/plugins/alsa/alsa-acp-device.c @@ -835,6 +835,10 @@ static int impl_clear(struct spa_handle *handle) { struct impl *this = (struct impl *) handle; remove_sources(this); + if (this->card) { + acp_card_destroy(this->card); + this->card = NULL; + } return 0; } diff --git a/spa/plugins/alsa/alsa-pcm-sink.c b/spa/plugins/alsa/alsa-pcm-sink.c index 3176b7703..450ecd73a 100644 --- a/spa/plugins/alsa/alsa-pcm-sink.c +++ b/spa/plugins/alsa/alsa-pcm-sink.c @@ -681,6 +681,10 @@ static int impl_get_interface(struct spa_handle *handle, const char *type, void static int impl_clear(struct spa_handle *handle) { + struct state *this; + spa_return_val_if_fail(handle != NULL, -EINVAL); + this = (struct state *) handle; + spa_alsa_close(this); return 0; } diff --git a/spa/plugins/alsa/alsa-pcm-source.c b/spa/plugins/alsa/alsa-pcm-source.c index 4be8dc846..2773ab153 100644 --- a/spa/plugins/alsa/alsa-pcm-source.c +++ b/spa/plugins/alsa/alsa-pcm-source.c @@ -704,6 +704,10 @@ static int impl_get_interface(struct spa_handle *handle, const char *type, void static int impl_clear(struct spa_handle *handle) { + struct state *this; + spa_return_val_if_fail(handle != NULL, -EINVAL); + this = (struct state *) handle; + spa_alsa_close(this); return 0; }