static void devices_add(struct pa_classify_device **p_devices, const char *type, const char *prop, enum pa_classify_method method, const char *arg, pa_hashmap *ports, uint32_t flags) { struct pa_classify_device *devs; struct pa_classify_device_def *d; size_t newsize; const char *method_name; char *ports_string = NULL; /* Just for log output. */ pa_strbuf *buf; /* For building ports_string. */ pa_assert(p_devices); pa_assert_se((devs = *p_devices)); newsize = sizeof(*devs) + sizeof(devs->defs[0]) * (devs->ndef + 1); devs = *p_devices = pa_xrealloc(devs, newsize); d = devs->defs + devs->ndef; memset(d+1, 0, sizeof(devs->defs[0])); d->type = pa_xstrdup(type); d->prop = pa_xstrdup(prop); buf = pa_strbuf_new(); if (ports && !pa_hashmap_isempty(ports)) { struct pa_classify_port_entry *port; void *state; pa_bool_t first = TRUE; /* Copy the ports hashmap to d->data.ports. */ d->data.ports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); PA_HASHMAP_FOREACH(port, ports, state) { struct pa_classify_port_entry *port_copy = pa_xnew(struct pa_classify_port_entry, 1); port_copy->device_name = pa_xstrdup(port->device_name); port_copy->port_name = pa_xstrdup(port->port_name); pa_hashmap_put(d->data.ports, port_copy->device_name, port_copy); if (!first) { pa_strbuf_putc(buf, ','); } first = FALSE; pa_strbuf_printf(buf, "%s:%s", port->device_name, port->port_name); } } d->data.flags = flags; switch (method) { case pa_method_equals: method_name = "equals"; d->method = pa_classify_method_equals; d->arg.string = pa_xstrdup(arg); break; case pa_method_startswith: method_name = "startswidth"; d->method = pa_classify_method_startswith; d->arg.string = pa_xstrdup(arg); break; case pa_method_matches: method_name = "matches"; if (regcomp(&d->arg.rexp, arg, 0) == 0) { d->method = pa_classify_method_matches; break; } /* intentional fall trough */ default: pa_log("%s: invalid device definition %s", __FUNCTION__, type); memset(d, 0, sizeof(*d)); pa_strbuf_free(buf); return; } devs->ndef++; ports_string = pa_strbuf_tostring_free(buf); pa_log_info("device '%s' added (%s|%s|%s|%s|0x%04x)", type, d->prop, method_name, arg, ports_string, d->data.flags); pa_xfree(ports_string); }
static void core_free(pa_object *o) { pa_core *c = PA_CORE(o); int j; pa_assert(c); c->state = PA_CORE_SHUTDOWN; /* Note: All modules and samples in the cache should be unloaded before * we get here */ pa_assert(pa_idxset_isempty(c->scache)); pa_idxset_free(c->scache, NULL); pa_assert(pa_idxset_isempty(c->modules)); pa_idxset_free(c->modules, NULL); pa_assert(pa_idxset_isempty(c->clients)); pa_idxset_free(c->clients, NULL); pa_assert(pa_idxset_isempty(c->cards)); pa_idxset_free(c->cards, NULL); pa_assert(pa_idxset_isempty(c->sinks)); pa_idxset_free(c->sinks, NULL); pa_assert(pa_idxset_isempty(c->sources)); pa_idxset_free(c->sources, NULL); pa_assert(pa_idxset_isempty(c->source_outputs)); pa_idxset_free(c->source_outputs, NULL); pa_assert(pa_idxset_isempty(c->sink_inputs)); pa_idxset_free(c->sink_inputs, NULL); pa_assert(pa_hashmap_isempty(c->namereg)); pa_hashmap_free(c->namereg); pa_assert(pa_hashmap_isempty(c->shared)); pa_hashmap_free(c->shared); pa_assert(pa_hashmap_isempty(c->modules_pending_unload)); pa_hashmap_free(c->modules_pending_unload); pa_subscription_free_all(c); if (c->exit_event) c->mainloop->time_free(c->exit_event); pa_assert(!c->default_source); pa_assert(!c->default_sink); pa_silence_cache_done(&c->silence_cache); if (c->rw_mempool) pa_mempool_free(c->rw_mempool); pa_mempool_free(c->mempool); for (j = 0; j < PA_CORE_HOOK_MAX; j++) pa_hook_done(&c->hooks[j]); for (j = 0; j < PA_ACCESS_HOOK_MAX; j++) pa_hook_done(&c->access[j]); pa_xfree(c); }