Ejemplo n.º 1
0
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;
}
/* Runs in PA mainloop context */
static void get_service_data(struct service *s, pa_object *device) {
    pa_assert(s);

    if (pa_sink_isinstance(device)) {
        pa_sink *sink = PA_SINK(device);

        s->is_sink = true;
        s->service_type = SERVICE_TYPE_SINK;
        s->ss = sink->sample_spec;
        s->cm = sink->channel_map;
        s->name = pa_xstrdup(sink->name);
        s->proplist = pa_proplist_copy(sink->proplist);
        s->subtype = sink->flags & PA_SINK_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL;

    } else if (pa_source_isinstance(device)) {
        pa_source *source = PA_SOURCE(device);

        s->is_sink = false;
        s->service_type = SERVICE_TYPE_SOURCE;
        s->ss = source->sample_spec;
        s->cm = source->channel_map;
        s->name = pa_xstrdup(source->name);
        s->proplist = pa_proplist_copy(source->proplist);
        s->subtype = source->monitor_of ? SUBTYPE_MONITOR : (source->flags & PA_SOURCE_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL);

    } else
        pa_assert_not_reached();
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
static void get_service_data(struct service *s, pa_sample_spec *ret_ss, pa_channel_map *ret_map, const char **ret_name, pa_proplist **ret_proplist, enum service_subtype *ret_subtype) {
    pa_assert(s);
    pa_assert(ret_ss);
    pa_assert(ret_proplist);
    pa_assert(ret_subtype);

    if (pa_sink_isinstance(s->device)) {
        pa_sink *sink = PA_SINK(s->device);

        *ret_ss = sink->sample_spec;
        *ret_map = sink->channel_map;
        *ret_name = sink->name;
        *ret_proplist = sink->proplist;
        *ret_subtype = sink->flags & PA_SINK_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL;

    } else if (pa_source_isinstance(s->device)) {
        pa_source *source = PA_SOURCE(s->device);

        *ret_ss = source->sample_spec;
        *ret_map = source->channel_map;
        *ret_name = source->name;
        *ret_proplist = source->proplist;
        *ret_subtype = source->monitor_of ? SUBTYPE_MONITOR : (source->flags & PA_SOURCE_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL);

    } else
        pa_assert_not_reached();
}
Ejemplo n.º 5
0
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 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;
}
Ejemplo n.º 7
0
static int process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u;

    if (pa_sink_isinstance(o)) {
        u = PA_SINK(o)->userdata;

        switch (code) {

            case PA_SINK_MESSAGE_GET_LATENCY: {
                pa_usec_t r = 0;
                if (u->hwo)
                    r = sink_get_latency(u);
                *((pa_usec_t*) data) = r;
                return 0;
            }

        }

        return pa_sink_process_msg(o, code, data, offset, chunk);
    }

    if (pa_source_isinstance(o)) {
        u = PA_SOURCE(o)->userdata;

        switch (code) {

            case PA_SOURCE_MESSAGE_GET_LATENCY: {
                pa_usec_t r = 0;
                if (u->hwi)
                    r = source_get_latency(u);
                *((pa_usec_t*) data) = r;
                return 0;
            }

        }

        return pa_source_process_msg(o, code, data, offset, chunk);
    }

    return -1;
}
static int publish_service(struct service *s) {
    int r = -1;
    AvahiStringList *txt = NULL;
    const char *name = NULL, *t;
    pa_proplist *proplist = NULL;
    pa_sample_spec ss;
    pa_channel_map map;
    char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
    enum service_subtype subtype;

    const char * const subtype_text[] = {
        [SUBTYPE_HARDWARE] = "hardware",
        [SUBTYPE_VIRTUAL] = "virtual",
        [SUBTYPE_MONITOR] = "monitor"
    };

    pa_assert(s);

    if (!s->userdata->client || avahi_client_get_state(s->userdata->client) != AVAHI_CLIENT_S_RUNNING)
        return 0;

    if (!s->entry_group) {
        if (!(s->entry_group = avahi_entry_group_new(s->userdata->client, service_entry_group_callback, s))) {
            pa_log("avahi_entry_group_new(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
            goto finish;
        }
    } else
        avahi_entry_group_reset(s->entry_group);

    txt = txt_record_server_data(s->userdata->core, txt);

    get_service_data(s, &ss, &map, &name, &proplist, &subtype);
    txt = avahi_string_list_add_pair(txt, "device", name);
    txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate);
    txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels);
    txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format));
    txt = avahi_string_list_add_pair(txt, "channel_map", pa_channel_map_snprint(cm, sizeof(cm), &map));
    txt = avahi_string_list_add_pair(txt, "subtype", subtype_text[subtype]);

    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_DESCRIPTION)))
        txt = avahi_string_list_add_pair(txt, "description", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_ICON_NAME)))
        txt = avahi_string_list_add_pair(txt, "icon-name", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_VENDOR_NAME)))
        txt = avahi_string_list_add_pair(txt, "vendor-name", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_PRODUCT_NAME)))
        txt = avahi_string_list_add_pair(txt, "product-name", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_CLASS)))
        txt = avahi_string_list_add_pair(txt, "class", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_FORM_FACTOR)))
        txt = avahi_string_list_add_pair(txt, "form-factor", t);

    if (avahi_entry_group_add_service_strlst(
                s->entry_group,
                AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                0,
                s->service_name,
                pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE,
                NULL,
                NULL,
                compute_port(s->userdata),
                txt) < 0) {

        pa_log("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
        goto finish;
    }

    if (avahi_entry_group_add_service_subtype(
                s->entry_group,
                AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                0,
                s->service_name,
                pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE,
                NULL,
                pa_sink_isinstance(s->device) ? (subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SINK_HARDWARE : SERVICE_SUBTYPE_SINK_VIRTUAL) :
                (subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SOURCE_HARDWARE : (subtype == SUBTYPE_VIRTUAL ? SERVICE_SUBTYPE_SOURCE_VIRTUAL : SERVICE_SUBTYPE_SOURCE_MONITOR))) < 0) {

        pa_log("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
        goto finish;
    }

    if (pa_source_isinstance(s->device) && subtype != SUBTYPE_MONITOR) {
        if (avahi_entry_group_add_service_subtype(
                    s->entry_group,
                    AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                    0,
                    s->service_name,
                    SERVICE_TYPE_SOURCE,
                    NULL,
                    SERVICE_SUBTYPE_SOURCE_NON_MONITOR) < 0) {

            pa_log("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
            goto finish;
        }
    }

    if (avahi_entry_group_commit(s->entry_group) < 0) {
        pa_log("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
        goto finish;
    }

    r = 0;
    pa_log_debug("Successfully created entry group for %s.", s->service_name);

finish:

    /* Remove this service */
    if (r < 0)
        service_free(s);

    avahi_string_list_free(txt);

    return r;
}