static pa_hook_result_t source_output_fixate_hook_cb(pa_core *c, pa_source_output_new_data *data, struct userdata *u) { struct device_info *d; pa_assert(c); pa_assert(data); pa_assert(u); if (data->source->monitor_of) d = pa_hashmap_get(u->device_infos, data->source->monitor_of); else d = pa_hashmap_get(u->device_infos, data->source); if (d) { resume(d); if (d->source) { if (pa_source_check_suspend(d->source) <= 0) restart(d); } else { /* The source output is connected to a monitor source. */ pa_assert(d->sink); if (pa_sink_check_suspend(d->sink) <= 0) restart(d); } } return PA_HOOK_OK; }
/* Self-locked */ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_id, size_t offset, size_t size) { pa_memblock *b = NULL; pa_memimport_segment *seg; pa_assert(i); pa_mutex_lock(i->mutex); if ((b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(block_id)))) { pa_memblock_ref(b); goto finish; } if (pa_hashmap_size(i->blocks) >= PA_MEMIMPORT_SLOTS_MAX) goto finish; if (!(seg = pa_hashmap_get(i->segments, PA_UINT32_TO_PTR(shm_id)))) if (!(seg = segment_attach(i, shm_id))) goto finish; if (offset+size > seg->memory.size) goto finish; if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks)))) b = pa_xnew(pa_memblock, 1); PA_REFCNT_INIT(b); b->pool = i->pool; b->type = PA_MEMBLOCK_IMPORTED; b->read_only = true; b->is_silence = false; pa_atomic_ptr_store(&b->data, (uint8_t*) seg->memory.ptr + offset); b->length = size; pa_atomic_store(&b->n_acquired, 0); pa_atomic_store(&b->please_signal, 0); b->per_type.imported.id = block_id; b->per_type.imported.segment = seg; pa_hashmap_put(i->blocks, PA_UINT32_TO_PTR(block_id), b); seg->n_blocks++; stat_add(b); finish: pa_mutex_unlock(i->mutex); return b; }
static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, struct userdata *u) { struct device_info *d; pa_assert(c); pa_object_assert_ref(o); pa_assert(u); if (!(d = pa_hashmap_get(u->device_infos, o))) return PA_HOOK_OK; if (pa_sink_isinstance(o)) { pa_sink *s = PA_SINK(o); pa_sink_state_t state = pa_sink_get_state(s); if (pa_sink_check_suspend(s) <= 0) if (PA_SINK_IS_OPENED(state)) restart(d); } else if (pa_source_isinstance(o)) { pa_source *s = PA_SOURCE(o); pa_source_state_t state = pa_source_get_state(s); if (pa_source_check_suspend(s) <= 0) if (PA_SOURCE_IS_OPENED(state)) restart(d); } return PA_HOOK_OK; }
static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) { pa_context *c = userdata; pa_stream *s; pa_assert(p); pa_assert(chunk); pa_assert(chunk->length > 0); pa_assert(c); pa_assert(PA_REFCNT_VALUE(c) >= 1); pa_context_ref(c); if ((s = pa_hashmap_get(c->record_streams, PA_UINT32_TO_PTR(channel)))) { if (chunk->memblock) { pa_memblockq_seek(s->record_memblockq, offset, seek, TRUE); pa_memblockq_push_align(s->record_memblockq, chunk); } else pa_memblockq_seek(s->record_memblockq, offset+chunk->length, seek, TRUE); if (s->read_callback) { size_t l; if ((l = pa_memblockq_get_length(s->record_memblockq)) > 0) s->read_callback(s, l, s->read_userdata); } } pa_context_unref(c); }
static struct service *get_service(struct userdata *u, pa_object *device) { struct service *s; char *hn, *un; const char *n; pa_assert(u); pa_object_assert_ref(device); if ((s = pa_hashmap_get(u->services, device))) return s; s = pa_xnew0(struct service, 1); s->userdata = u; s->device = device; if (pa_sink_isinstance(device)) { if (!(n = pa_proplist_gets(PA_SINK(device)->proplist, PA_PROP_DEVICE_DESCRIPTION))) n = PA_SINK(device)->name; } else { if (!(n = pa_proplist_gets(PA_SOURCE(device)->proplist, PA_PROP_DEVICE_DESCRIPTION))) n = PA_SOURCE(device)->name; } hn = pa_get_host_name_malloc(); un = pa_get_user_name_malloc(); s->service_name = pa_truncate_utf8(pa_sprintf_malloc("%s@%s: %s", un, hn, n), kDNSServiceMaxDomainName-1); pa_xfree(un); pa_xfree(hn); pa_hashmap_put(u->services, s->device, s); return s; }
static pa_autoload_entry* entry_new(pa_core *c, const char *name) { pa_autoload_entry *e = NULL; pa_core_assert_ref(c); pa_assert(name); if (c->autoload_hashmap && (e = pa_hashmap_get(c->autoload_hashmap, name))) return NULL; e = pa_xnew(pa_autoload_entry, 1); e->core = c; e->name = pa_xstrdup(name); e->module = e->argument = NULL; e->in_action = 0; if (!c->autoload_hashmap) c->autoload_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); pa_assert(c->autoload_hashmap); pa_hashmap_put(c->autoload_hashmap, e->name, e); if (!c->autoload_idxset) c->autoload_idxset = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); pa_idxset_put(c->autoload_idxset, e, &e->index); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_NEW, e->index); return e; }
static pa_hook_result_t source_output_fixate_hook_cb(pa_core *c, pa_source_output_new_data *data, struct userdata *u) { struct device_info *d; pa_assert(c); pa_assert(data); pa_assert(u); if (data->source->monitor_of) d = pa_hashmap_get(u->device_infos, data->source->monitor_of); else d = pa_hashmap_get(u->device_infos, data->source); if (d) resume(d); return PA_HOOK_OK; }
static pa_hook_result_t source_output_state_changed_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) { pa_assert(c); pa_source_output_assert_ref(s); pa_assert(u); if (pa_source_output_get_state(s) == PA_SOURCE_OUTPUT_RUNNING) { struct device_info *d; if (s->source->monitor_of) d = pa_hashmap_get(u->device_infos, s->source->monitor_of); else d = pa_hashmap_get(u->device_infos, s->source); if (d) resume(d); } return PA_HOOK_OK; }
const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type_t type) { pa_autoload_entry *e; pa_core_assert_ref(c); pa_assert(name); if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type) return NULL; return e; }
static pa_hook_result_t source_output_move_start_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) { struct device_info *d = NULL; pa_assert(c); pa_source_output_assert_ref(s); pa_assert(u); if (s->source->monitor_of) { if (pa_sink_check_suspend(s->source->monitor_of) <= 1) d = pa_hashmap_get(u->device_infos, s->source->monitor_of); } else { if (pa_source_check_suspend(s->source) <= 1) d = pa_hashmap_get(u->device_infos, s->source); } if (d) restart(d); return PA_HOOK_OK; }
static void card_changed(struct userdata *u, struct udev_device *dev) { struct device *d; const char *path; const char *t; char *n; pa_assert(u); pa_assert(dev); /* Maybe /dev/snd is now available? */ setup_inotify(u); path = udev_device_get_devpath(dev); if ((d = pa_hashmap_get(u->devices, path))) { verify_access(u, d); return; } d = pa_xnew0(struct device, 1); d->path = pa_xstrdup(path); d->module = PA_INVALID_INDEX; PA_INIT_RATELIMIT(d->ratelimit, 10*PA_USEC_PER_SEC, 5); if (!(t = udev_device_get_property_value(dev, "PULSE_NAME"))) if (!(t = udev_device_get_property_value(dev, "ID_ID"))) if (!(t = udev_device_get_property_value(dev, "ID_PATH"))) t = path_get_card_id(path); n = pa_namereg_make_valid_name(t); d->card_name = pa_sprintf_malloc("alsa_card.%s", n); d->args = pa_sprintf_malloc("device_id=\"%s\" " "name=\"%s\" " "card_name=\"%s\" " "namereg_fail=false " "tsched=%s " "fixed_latency_range=%s " "ignore_dB=%s " "deferred_volume=%s " "use_ucm=1 " "card_properties=\"module-udev-detect.discovered=1\"", path_get_card_id(path), n, d->card_name, pa_yes_no(u->use_tsched), pa_yes_no(u->fixed_latency_range), pa_yes_no(u->ignore_dB), pa_yes_no(u->deferred_volume)); pa_xfree(n); pa_hashmap_put(u->devices, d->path, d); verify_access(u, d); }
static pa_hook_result_t device_unlink_cb(pa_core *c, pa_object *o, struct userdata *u) { struct service *s; pa_assert(c); pa_object_assert_ref(o); if ((s = pa_hashmap_get(u->services, o))) service_free(s); return PA_HOOK_OK; }
int pa_headerlist_puts(pa_headerlist *p, const char *key, const char *value) { struct header *hdr; bool add = false; pa_assert(p); pa_assert(key); if (!(hdr = pa_hashmap_get(MAKE_HASHMAP(p), key))) { hdr = pa_xnew(struct header, 1); hdr->key = pa_xstrdup(key); add = true; } else
void* pa_property_get(pa_core *c, const char *name) { pa_property *p; pa_assert(c); pa_assert(name); pa_assert(c->properties); if (!(p = pa_hashmap_get(c->properties, name))) return NULL; return p->data; }
void* pa_shared_get(pa_core *c, const char *name) { pa_shared *p; pa_assert(c); pa_assert(name); pa_assert(c->shared); if (!(p = pa_hashmap_get(c->shared, name))) return NULL; return p->data; }
static void browser_cb( AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata) { struct userdata *u = userdata; struct tunnel *t; pa_assert(u); if (flags & AVAHI_LOOKUP_RESULT_LOCAL) return; t = tunnel_new(interface, protocol, name, type, domain); if (event == AVAHI_BROWSER_NEW) { if (!pa_hashmap_get(u->tunnels, t)) if (!(avahi_service_resolver_new(u->client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolver_cb, u))) pa_log("avahi_service_resolver_new() failed: %s", avahi_strerror(avahi_client_errno(u->client))); /* We ignore the returned resolver object here, since the we don't * need to attach any special data to it, and we can still destroy * it from the callback */ } else if (event == AVAHI_BROWSER_REMOVE) { struct tunnel *t2; if ((t2 = pa_hashmap_get(u->tunnels, t))) { pa_module_unload_request_by_index(u->core, t2->module_index, TRUE); pa_hashmap_remove(u->tunnels, t2); tunnel_free(t2); } } tunnel_free(t); }
static pa_hook_result_t sink_input_move_start_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) { struct device_info *d; pa_assert(c); pa_sink_input_assert_ref(s); pa_assert(u); if (pa_sink_check_suspend(s->sink) <= 1) if ((d = pa_hashmap_get(u->device_infos, s->sink))) restart(d); return PA_HOOK_OK; }
int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type_t type) { pa_autoload_entry *e; pa_assert(c); pa_assert(name); pa_assert(type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE); if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type) return -1; entry_remove_and_free(e); return 0; }
void pa_device_port_set_available(pa_device_port *p, pa_port_available_t status) { uint32_t state; pa_card *card; /* pa_source *source; pa_sink *sink; */ pa_core *core; pa_assert(p); if (p->available == status) return; /* pa_assert(status != PA_PORT_AVAILABLE_UNKNOWN); */ p->available = status; pa_log_debug("Setting port %s to status %s", p->name, status == PA_PORT_AVAILABLE_YES ? "yes" : status == PA_PORT_AVAILABLE_NO ? "no" : "unknown"); /* Post subscriptions to the card which owns us */ pa_assert_se(core = p->core); PA_IDXSET_FOREACH(card, core->cards, state) if (p == pa_hashmap_get(card->ports, p->name)) pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, card->index); #if 0 /* This stuff is temporarily commented out while figuring out whether to actually do this */ if (p->is_output) PA_IDXSET_FOREACH(sink, core->sinks, state) if (p == pa_hashmap_get(sink->ports, p->name)) pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, sink->index); if (p->is_input) PA_IDXSET_FOREACH(source, core->sources, state) if (p == pa_hashmap_get(source->ports, p->name)) pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, source->index); #endif pa_hook_fire(&core->hooks[PA_CORE_HOOK_PORT_AVAILABLE_CHANGED], p); }
int pa_shared_set(pa_core *c, const char *name, void *data) { pa_shared *p; pa_assert(c); pa_assert(name); pa_assert(data); pa_assert(c->shared); if (pa_hashmap_get(c->shared, name)) return -1; p = shared_new(name, data); pa_hashmap_put(c->shared, p->name, p); return 0; }
int pa_property_set(pa_core *c, const char *name, void *data) { pa_property *p; pa_assert(c); pa_assert(name); pa_assert(data); pa_assert(c->properties); if (pa_hashmap_get(c->properties, name)) return -1; p = property_new(name, data); pa_hashmap_put(c->properties, p->name, p); return 0; }
static pa_hook_result_t sink_input_state_changed_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) { struct device_info *d; pa_sink_input_state_t state; pa_assert(c); pa_sink_input_assert_ref(s); pa_assert(u); state = pa_sink_input_get_state(s); if (state == PA_SINK_INPUT_RUNNING || state == PA_SINK_INPUT_DRAINED) if ((d = pa_hashmap_get(u->device_infos, s->sink))) resume(d); return PA_HOOK_OK; }
/** Will accept only valid UTF-8 */ int pa_proplist_sets(pa_proplist *p, const char *key, const char *value) { struct property *prop; bool add = false; pa_assert(p); pa_assert(key); pa_assert(value); if (!pa_proplist_key_valid(key) || !pa_utf8_valid(value)) return -1; if (!(prop = pa_hashmap_get(MAKE_HASHMAP(p), key))) { prop = pa_xnew(struct property, 1); prop->key = pa_xstrdup(key); add = true; } else
/** Will accept only valid UTF-8 */ int pa_proplist_sets(pa_proplist *p, const char *key, const char *value) { struct property *prop; pa_bool_t add = FALSE; pa_assert(p); pa_assert(key); pa_assert(value); if (!property_name_valid(key) || !pa_utf8_valid(value)) return -1; if (!(prop = pa_hashmap_get(MAKE_HASHMAP(p), key))) { prop = pa_xnew(struct property, 1); prop->key = pa_xstrdup(key); add = TRUE; } else
static pa_hook_result_t sink_input_fixate_hook_cb(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { struct device_info *d; pa_assert(c); pa_assert(data); pa_assert(u); /* We need to resume the audio device here even for * PA_SINK_INPUT_START_CORKED, since we need the device parameters * to be fully available while the stream is set up. */ if ((d = pa_hashmap_get(u->device_infos, data->sink))) resume(d); return PA_HOOK_OK; }
static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *data, struct userdata *u) { struct rule *r; char *name; pa_assert(data); if (!data->client || !(name = client_name(data->client))) return PA_HOOK_OK; if ((r = pa_hashmap_get(u->hashmap, name))) { if (!data->source && r->source) { if ((data->source = pa_namereg_get(c, r->source, PA_NAMEREG_SOURCE, 1))) pa_log_info("Restoring source for <%s>", r->name); } } return PA_HOOK_OK; }
static int port_device_is_typeof(struct pa_classify_device_def *defs, const char *name, const char *type, struct pa_classify_device_data **data) { struct pa_classify_device_def *d; for (d = defs; d->type; d++) { if (pa_streq(type, d->type)) { if (d->data.ports && pa_hashmap_get(d->data.ports, name)) { if (data != NULL) *data = &d->data; return TRUE; } } } return FALSE; }
int pa_memimport_process_revoke(pa_memimport *i, uint32_t id) { pa_memblock *b; int ret = 0; pa_assert(i); pa_mutex_lock(i->mutex); if (!(b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(id)))) { ret = -1; goto finish; } memblock_replace_import(b); finish: pa_mutex_unlock(i->mutex); return ret; }
static pa_hook_result_t sink_input_fixate_hook_cb(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { struct device_info *d; pa_assert(c); pa_assert(data); pa_assert(u); /* We need to resume the audio device here even for * PA_SINK_INPUT_START_CORKED, since we need the device parameters * to be fully available while the stream is set up. In that case, * make sure we close the sink again after the timeout interval. */ if ((d = pa_hashmap_get(u->device_infos, data->sink))) { resume(d); if (pa_sink_check_suspend(d->sink) <= 0) restart(d); } return PA_HOOK_OK; }
void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type_t type) { pa_autoload_entry *e; pa_module *m; pa_assert(c); pa_assert(name); if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || (e->type != type)) return; if (e->in_action) return; e->in_action = 1; if (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE) { if ((m = pa_module_load(c, e->module, e->argument))) m->auto_unload = 1; } e->in_action = 0; }