static pa_hook_result_t device_new_hook_cb(pa_core *c, pa_object *o, struct userdata *u) { struct device_info *d; pa_source *source; pa_sink *sink; pa_assert(c); pa_object_assert_ref(o); pa_assert(u); source = pa_source_isinstance(o) ? PA_SOURCE(o) : NULL; sink = pa_sink_isinstance(o) ? PA_SINK(o) : NULL; /* Never suspend monitors */ if (source && source->monitor_of) return PA_HOOK_OK; pa_assert(source || sink); d = pa_xnew(struct device_info, 1); d->userdata = u; d->source = source ? pa_source_ref(source) : NULL; d->sink = sink ? pa_sink_ref(sink) : NULL; d->time_event = pa_core_rttime_new(c, PA_USEC_INVALID, timeout_cb, d); pa_hashmap_put(u->device_infos, o, d); if ((d->sink && pa_sink_check_suspend(d->sink) <= 0) || (d->source && pa_source_check_suspend(d->source) <= 0)) restart(d); return PA_HOOK_OK; }
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 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_hook_result_t device_unlink_hook_cb(pa_core *c, pa_object *o, struct userdata *u) { pa_assert(c); pa_object_assert_ref(o); pa_assert(u); pa_hashmap_remove_and_free(u->device_infos, o); return PA_HOOK_OK; }
static pa_hook_result_t device_new_or_changed_cb(pa_core *c, pa_object *o, struct userdata *u) { pa_assert(c); pa_object_assert_ref(o); if (!shall_ignore(o)) publish_service(get_service(u, o)); return PA_HOOK_OK; }
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; }
static bool shall_ignore(pa_object *o) { pa_object_assert_ref(o); if (pa_sink_isinstance(o)) return !!(PA_SINK(o)->flags & PA_SINK_NETWORK); if (pa_source_isinstance(o)) return PA_SOURCE(o)->monitor_of || (PA_SOURCE(o)->flags & PA_SOURCE_NETWORK); pa_assert_not_reached(); }
static pa_hook_result_t sink_state_changed_cb(pa_core *c, pa_object *o, struct pa_policy_activity_variable *var) { pa_sink *sink; pa_assert(c); pa_object_assert_ref(o); pa_assert(var); if (pa_sink_isinstance(o)) { sink = PA_SINK(o); perform_activity_action(sink, var, var->default_state); } return PA_HOOK_OK; }
static pa_hook_result_t device_new_hook_cb(pa_core *c, pa_object *o, struct userdata *u) { struct device_info *d; pa_source *source; pa_sink *sink; const char *timeout_str; int32_t timeout; bool timeout_valid; pa_assert(c); pa_object_assert_ref(o); pa_assert(u); source = pa_source_isinstance(o) ? PA_SOURCE(o) : NULL; sink = pa_sink_isinstance(o) ? PA_SINK(o) : NULL; /* Never suspend monitors */ if (source && source->monitor_of) return PA_HOOK_OK; pa_assert(source || sink); timeout_str = pa_proplist_gets(sink ? sink->proplist : source->proplist, "module-suspend-on-idle.timeout"); if (timeout_str && pa_atoi(timeout_str, &timeout) >= 0) timeout_valid = true; else timeout_valid = false; if (timeout_valid && timeout < 0) return PA_HOOK_OK; d = pa_xnew(struct device_info, 1); d->userdata = u; d->source = source ? pa_source_ref(source) : NULL; d->sink = sink ? pa_sink_ref(sink) : NULL; d->time_event = pa_core_rttime_new(c, PA_USEC_INVALID, timeout_cb, d); if (timeout_valid) d->timeout = timeout * PA_USEC_PER_SEC; else d->timeout = d->userdata->timeout; pa_hashmap_put(u->device_infos, o, d); if ((d->sink && pa_sink_check_suspend(d->sink) <= 0) || (d->source && pa_source_check_suspend(d->source) <= 0)) restart(d); return PA_HOOK_OK; }