Ejemplo n.º 1
0
static void sink_set_volume_cb(pa_sink *s) {
    struct userdata *u = s->userdata;
    pa_cvolume hw;
    pa_volume_t v;
    char t[PA_CVOLUME_SNPRINT_VERBOSE_MAX];

    pa_assert(u);

    /* If we're muted we don't need to do anything */
    if (s->muted)
        return;

    /* Calculate the max volume of all channels.
       We'll use this as our (single) volume on the APEX device and emulate
       any variation in channel volumes in software */
    v = pa_cvolume_max(&s->real_volume);

    /* Create a pa_cvolume version of our single value */
    pa_cvolume_set(&hw, s->sample_spec.channels, v);

    /* Perform any software manipulation of the volume needed */
    pa_sw_cvolume_divide(&s->soft_volume, &s->real_volume, &hw);

    pa_log_debug("Requested volume: %s", pa_cvolume_snprint_verbose(t, sizeof(t), &s->real_volume, &s->channel_map, false));
    pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint_verbose(t, sizeof(t), &hw, &s->channel_map, false));
    pa_log_debug("Calculated software volume: %s",
                 pa_cvolume_snprint_verbose(t, sizeof(t), &s->soft_volume, &s->channel_map, true));

    /* Any necessary software volume manipulation is done so set
       our hw volume (or v as a single value) on the device */
    pa_raop_client_set_volume(u->raop, v);
}
static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *core, pa_sink_input_new_data *data, struct userdata *u) {
    const char *hpos, *vpos, *role, *id;
    double f;
    char t[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
    pa_cvolume v;

    pa_assert(data);

    if (!(role = pa_proplist_gets(data->proplist, PA_PROP_MEDIA_ROLE)))
        return PA_HOOK_OK;

    if (!pa_streq(role, "event"))
        return PA_HOOK_OK;

    if ((id = pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID))) {

        /* The test sounds should never be positioned in space, since
         * they might be triggered themselves to configure the speakers
         * in space, which we don't want to mess up. */

        if (pa_startswith(id, "audio-channel-"))
            return PA_HOOK_OK;

        if (pa_streq(id, "audio-volume-change"))
            return PA_HOOK_OK;

        if (pa_streq(id, "audio-test-signal"))
            return PA_HOOK_OK;
    }

    if (!(hpos = pa_proplist_gets(data->proplist, PA_PROP_EVENT_MOUSE_HPOS)))
        hpos = pa_proplist_gets(data->proplist, PA_PROP_WINDOW_HPOS);

    if (!(vpos = pa_proplist_gets(data->proplist, PA_PROP_EVENT_MOUSE_VPOS)))
        vpos = pa_proplist_gets(data->proplist, PA_PROP_WINDOW_VPOS);

    if (!hpos && !vpos)
        return PA_HOOK_OK;

    pa_cvolume_reset(&v, data->sink->sample_spec.channels);

    if (hpos) {
        if (parse_pos(hpos, &f) < 0)
            return PA_HOOK_OK;

        if (pa_channel_map_can_balance(&data->sink->channel_map)) {
            pa_log_debug("Positioning event sound '%s' horizontally at %0.2f.", pa_strnull(pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID)), f);
            pa_cvolume_set_balance(&v, &data->sink->channel_map, f*2.0-1.0);
        }
    }

    if (vpos) {
        if (parse_pos(vpos, &f) < 0)
            return PA_HOOK_OK;

        if (pa_channel_map_can_fade(&data->sink->channel_map)) {
            pa_log_debug("Positioning event sound '%s' vertically at %0.2f.", pa_strnull(pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID)), f);
            pa_cvolume_set_fade(&v, &data->sink->channel_map, f*2.0-1.0);
        }
    }

    pa_log_debug("Final volume factor %s.",
                 pa_cvolume_snprint_verbose(t,
                                            sizeof(t),
                                            &v,
                                            &data->sink->channel_map,
                                            data->sink->flags & PA_SINK_DECIBEL_VOLUME));
    pa_sink_input_new_data_add_volume_factor_sink(data, u->name, &v);

    return PA_HOOK_OK;
}