Ejemplo n.º 1
0
static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
    struct userdata *u =  userdata;
    pa_sink_input *si = NULL;
    pa_source_output *so = NULL;
    struct rule *r;
    char *name;

    pa_assert(c);
    pa_assert(u);

    if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
        t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) &&
        t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
        t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE))
        return;

    if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
        if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx)))
            return;

        if (!si->client || !(name = client_name(si->client)))
            return;
    } else {
        pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT);

        if (!(so = pa_idxset_get_by_index(c->source_outputs, idx)))
            return;

        if (!so->client || !(name = client_name(so->client)))
            return;
    }

    if ((r = pa_hashmap_get(u->hashmap, name))) {
        pa_xfree(name);

        if (si) {

            if (!r->volume_is_set || !pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) {
                pa_log_info("Saving volume for <%s>", r->name);
                r->volume = *pa_sink_input_get_volume(si);
                r->volume_is_set = TRUE;
                u->modified = TRUE;
            }

            if (!r->sink || strcmp(si->sink->name, r->sink) != 0) {
                pa_log_info("Saving sink for <%s>", r->name);
                pa_xfree(r->sink);
                r->sink = pa_xstrdup(si->sink->name);
                u->modified = TRUE;
            }
        } else {
            pa_assert(so);

            if (!r->source || strcmp(so->source->name, r->source) != 0) {
                pa_log_info("Saving source for <%s>", r->name);
                pa_xfree(r->source);
                r->source = pa_xstrdup(so->source->name);
                u->modified = TRUE;
            }
        }

    } else {
        pa_log_info("Creating new entry for <%s>", name);

        r = pa_xnew(struct rule, 1);
        r->name = name;

        if (si) {
            r->volume = *pa_sink_input_get_volume(si);
            r->volume_is_set = TRUE;
            r->sink = pa_xstrdup(si->sink->name);
            r->source = NULL;
        } else {
            pa_assert(so);
            r->volume_is_set = FALSE;
            r->sink = NULL;
            r->source = pa_xstrdup(so->source->name);
        }

        pa_hashmap_put(u->hashmap, r->name, r);
        u->modified = TRUE;
    }

    if (u->modified && !u->save_time_event) {
        struct timeval tv;
        pa_gettimeofday(&tv);
        tv.tv_sec += SAVE_INTERVAL;
        u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u);
    }
}
Ejemplo n.º 2
0
char *pa_sink_input_list_to_string(pa_core *c) {
    pa_strbuf *s;
    pa_sink_input *i;
    uint32_t idx = PA_IDXSET_INVALID;
    static const char* const state_table[] = {
        [PA_SINK_INPUT_RUNNING] = "RUNNING",
        [PA_SINK_INPUT_DRAINED] = "DRAINED",
        [PA_SINK_INPUT_CORKED] = "CORKED",
        [PA_SINK_INPUT_UNLINKED] = "UNLINKED"
    };

    pa_assert(c);
    s = pa_strbuf_new();

    pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_size(c->sink_inputs));

    for (i = pa_idxset_first(c->sink_inputs, &idx); i; i = pa_idxset_next(c->sink_inputs, &idx)) {
        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];

        pa_assert(i->sink);

        pa_strbuf_printf(
            s,
            "    index: %u\n"
            "\tname: <%s>\n"
            "\tdriver: <%s>\n"
            "\tflags: %s%s%s%s%s%s%s\n"
            "\tstate: %s\n"
            "\tsink: <%u> '%s'\n"
            "\tvolume: <%s>\n"
            "\tmute: <%i>\n"
            "\tlatency: <%0.0f usec>\n"
            "\tsample spec: <%s>\n"
            "\tchannel map: <%s>\n"
            "\tresample method: %s\n",
            i->index,
            i->name,
            i->driver,
            i->flags & PA_SINK_INPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "",
            i->flags & PA_SINK_INPUT_DONT_MOVE ? "DONT_MOVE " : "",
            i->flags & PA_SINK_INPUT_NO_REMAP ? "NO_REMAP " : "",
            i->flags & PA_SINK_INPUT_NO_REMIX ? "NO_REMIX " : "",
            i->flags & PA_SINK_INPUT_FIX_FORMAT ? "FIX_FORMAT " : "",
            i->flags & PA_SINK_INPUT_FIX_RATE ? "FIX_RATE " : "",
            i->flags & PA_SINK_INPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "",
            state_table[pa_sink_input_get_state(i)],
            i->sink->index, i->sink->name,
            pa_cvolume_snprint(cv, sizeof(cv), pa_sink_input_get_volume(i)),
            !!pa_sink_input_get_mute(i),
            (double) pa_sink_input_get_latency(i),
            pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec),
            pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
            pa_resample_method_to_string(pa_sink_input_get_resample_method(i)));

        if (i->module)
            pa_strbuf_printf(s, "\tmodule: <%u>\n", i->module->index);
        if (i->client)
            pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", i->client->index, i->client->name);
    }

    return pa_strbuf_tostring_free(s);
}
Ejemplo n.º 3
0
char *pa_sink_input_list_to_string(pa_core *c) {
    pa_strbuf *s;
    pa_sink_input *i;
    uint32_t idx = PA_IDXSET_INVALID;
    static const char* const state_table[] = {
        [PA_SINK_INPUT_INIT] = "INIT",
        [PA_SINK_INPUT_RUNNING] = "RUNNING",
        [PA_SINK_INPUT_DRAINED] = "DRAINED",
        [PA_SINK_INPUT_CORKED] = "CORKED",
        [PA_SINK_INPUT_UNLINKED] = "UNLINKED"
    };

    pa_assert(c);
    s = pa_strbuf_new();

    pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_size(c->sink_inputs));

    for (i = pa_idxset_first(c->sink_inputs, &idx); i; i = pa_idxset_next(c->sink_inputs, &idx)) {
        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t, clt[28];
        pa_usec_t cl;
        const char *cmn;
        pa_cvolume v;
        char *volume_str = NULL;

        cmn = pa_channel_map_to_pretty_name(&i->channel_map);

        if ((cl = pa_sink_input_get_requested_latency(i)) == (pa_usec_t) -1)
            pa_snprintf(clt, sizeof(clt), "n/a");
        else
            pa_snprintf(clt, sizeof(clt), "%0.2f ms", (double) cl / PA_USEC_PER_MSEC);

        pa_assert(i->sink);

        if (pa_sink_input_is_volume_readable(i)) {
            pa_sink_input_get_volume(i, &v, TRUE);
            volume_str = pa_sprintf_malloc("%s\n\t        %s\n\t        balance %0.2f",
                                           pa_cvolume_snprint(cv, sizeof(cv), &v),
                                           pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &v),
                                           pa_cvolume_get_balance(&v, &i->channel_map));
        } else
            volume_str = pa_xstrdup("n/a");

        pa_strbuf_printf(
            s,
            "    index: %u\n"
            "\tdriver: <%s>\n"
            "\tflags: %s%s%s%s%s%s%s%s%s%s%s\n"
            "\tstate: %s\n"
            "\tsink: %u <%s>\n"
            "\tvolume: %s\n"
            "\tmuted: %s\n"
            "\tcurrent latency: %0.2f ms\n"
            "\trequested latency: %s\n"
            "\tsample spec: %s\n"
            "\tchannel map: %s%s%s\n"
            "\tresample method: %s\n",
            i->index,
            i->driver,
            i->flags & PA_SINK_INPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "",
            i->flags & PA_SINK_INPUT_DONT_MOVE ? "DONT_MOVE " : "",
            i->flags & PA_SINK_INPUT_START_CORKED ? "START_CORKED " : "",
            i->flags & PA_SINK_INPUT_NO_REMAP ? "NO_REMAP " : "",
            i->flags & PA_SINK_INPUT_NO_REMIX ? "NO_REMIX " : "",
            i->flags & PA_SINK_INPUT_FIX_FORMAT ? "FIX_FORMAT " : "",
            i->flags & PA_SINK_INPUT_FIX_RATE ? "FIX_RATE " : "",
            i->flags & PA_SINK_INPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "",
            i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND ? "DONT_INHIBIT_AUTO_SUSPEND " : "",
            i->flags & PA_SINK_INPUT_NO_CREATE_ON_SUSPEND ? "NO_CREATE_SUSPEND " : "",
            i->flags & PA_SINK_INPUT_KILL_ON_SUSPEND ? "KILL_ON_SUSPEND " : "",
            state_table[pa_sink_input_get_state(i)],
            i->sink->index, i->sink->name,
            volume_str,
            pa_yes_no(pa_sink_input_get_mute(i)),
            (double) pa_sink_input_get_latency(i, NULL) / PA_USEC_PER_MSEC,
            clt,
            pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec),
            pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
            cmn ? "\n\t             " : "",
            cmn ? cmn : "",
            pa_resample_method_to_string(pa_sink_input_get_resample_method(i)));

        pa_xfree(volume_str);

        if (i->module)
            pa_strbuf_printf(s, "\tmodule: %u\n", i->module->index);
        if (i->client)
            pa_strbuf_printf(s, "\tclient: %u <%s>\n", i->client->index, pa_strnull(pa_proplist_gets(i->client->proplist, PA_PROP_APPLICATION_NAME)));

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

    return pa_strbuf_tostring_free(s);
}