示例#1
0
static void append_port_list(pa_strbuf *s, pa_hashmap *ports)
{
    pa_device_port *p;
    void *state;

    if (!ports)
        return;

    pa_strbuf_puts(s, "\tports:\n");
    PA_HASHMAP_FOREACH(p, ports, state)
        pa_strbuf_printf(s, "\t\t%s: %s (priority %u, available: %s)\n",
            p->name, p->description, p->priority, port_available_to_string(p->available));
}
static void inotify_cb(
        pa_mainloop_api*a,
        pa_io_event* e,
        int fd,
        pa_io_event_flags_t events,
        void *userdata) {

    struct {
        struct inotify_event e;
        char name[NAME_MAX];
    } buf;
    struct userdata *u = userdata;
    static int type = 0;
    bool deleted = false;
    struct device *d;
    void *state;

    for (;;) {
        ssize_t r;
        struct inotify_event *event;

        pa_zero(buf);
        if ((r = pa_read(fd, &buf, sizeof(buf), &type)) <= 0) {

            if (r < 0 && errno == EAGAIN)
                break;

            pa_log("read() from inotify failed: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
            goto fail;
        }

        event = &buf.e;
        while (r > 0) {
            size_t len;

            if ((size_t) r < sizeof(struct inotify_event)) {
                pa_log("read() too short.");
                goto fail;
            }

            len = sizeof(struct inotify_event) + event->len;

            if ((size_t) r < len) {
                pa_log("Payload missing.");
                goto fail;
            }

            /* From udev we get the guarantee that the control
             * device's ACL is changed last. To avoid races when ACLs
             * are changed we hence watch only the control device */
            if (((event->mask & IN_ATTRIB) && pa_startswith(event->name, "controlC")))
                PA_HASHMAP_FOREACH(d, u->devices, state)
                    if (control_node_belongs_to_device(d, event->name))
                        d->need_verify = true;

            /* ALSA doesn't really give us any guarantee on the closing
             * order, so let's simply hope */
            if (((event->mask & IN_CLOSE_WRITE) && pa_startswith(event->name, "pcmC")))
                PA_HASHMAP_FOREACH(d, u->devices, state)
                    if (pcm_node_belongs_to_device(d, event->name))
                        d->need_verify = true;

            /* /dev/snd/ might have been removed */
            if ((event->mask & (IN_DELETE_SELF|IN_MOVE_SELF)))
                deleted = true;

            event = (struct inotify_event*) ((uint8_t*) event + len);
            r -= len;
        }
    }

    PA_HASHMAP_FOREACH(d, u->devices, state)
        if (d->need_verify) {
            d->need_verify = false;
            verify_access(u, d);
        }

    if (!deleted)
        return;

fail:
    if (u->inotify_io) {
        a->io_free(u->inotify_io);
        u->inotify_io = NULL;
    }

    if (u->inotify_fd >= 0) {
        pa_close(u->inotify_fd);
        u->inotify_fd = -1;
    }
}
示例#3
0
char *pa_card_list_to_string(pa_core *c) {
    pa_strbuf *s;
    pa_card *card;
    uint32_t idx = PA_IDXSET_INVALID;
    pa_assert(c);

    s = pa_strbuf_new();

    pa_strbuf_printf(s, "%u card(s) available.\n", pa_idxset_size(c->cards));

    for (card = pa_idxset_first(c->cards, &idx); card; card = pa_idxset_next(c->cards, &idx)) {
        char *t;
        pa_sink *sink;
        pa_source *source;
        uint32_t sidx;

        pa_strbuf_printf(
                s,
                "    index: %u\n"
                "\tname: <%s>\n"
                "\tdriver: <%s>\n",
                card->index,
                card->name,
                card->driver);

        if (card->module)
            pa_strbuf_printf(s, "\towner module: %u\n", card->module->index);

        t = pa_proplist_to_string_sep(card->proplist, "\n\t\t");
        pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t);
        pa_xfree(t);

        if (card->profiles) {
            pa_card_profile *p;
            void *state;

            pa_strbuf_puts(s, "\tprofiles:\n");
            PA_HASHMAP_FOREACH(p, card->profiles, state)
                pa_strbuf_printf(s, "\t\t%s: %s (priority %u)\n", p->name, p->description, p->priority);
        }

        if (card->active_profile)
            pa_strbuf_printf(
                    s,
                    "\tactive profile: <%s>\n",
                    card->active_profile->name);

        if (!pa_idxset_isempty(card->sinks)) {
            pa_strbuf_puts(s, "\tsinks:\n");
            for (sink = pa_idxset_first(card->sinks, &sidx); sink; sink = pa_idxset_next(card->sinks, &sidx))
                pa_strbuf_printf(s, "\t\t%s/#%u: %s\n", sink->name, sink->index, pa_strna(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)));
        }

        if (!pa_idxset_isempty(card->sources)) {
            pa_strbuf_puts(s, "\tsources:\n");
            for (source = pa_idxset_first(card->sources, &sidx); source; source = pa_idxset_next(card->sources, &sidx))
                pa_strbuf_printf(s, "\t\t%s/#%u: %s\n", source->name, source->index, pa_strna(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)));
        }

        append_port_list(s, card->ports);
    }

    return pa_strbuf_tostring_free(s);
}