Comment 13 for bug 1497666

Revision history for this message
Raymond (superquad-vortex2) wrote : Re: No right channel sound on Creative Xtreme Audio (CA0106) in Ubuntu 14.04-15.10

http://cgit.freedesktop.org/pulseaudio/pulseaudio/tree/src/modules/alsa/alsa-mixer.c

seem pulseaudio only control left channel when it only use the virtual master playback volume control

in function element_set_volume, it check the element has left and right channel

static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v, bool deferred_volume, bool write_to_hw) {

    snd_mixer_selem_id_t *sid;
    pa_cvolume rv;
    snd_mixer_elem_t *me;
    snd_mixer_selem_channel_id_t c;
    pa_channel_position_mask_t mask = 0;
    unsigned k;

    pa_assert(m);
    pa_assert(e);
    pa_assert(cm);
    pa_assert(v);
    pa_assert(pa_cvolume_compatible_with_channel_map(v, cm));

    SELEM_INIT(sid, e->alsa_name);
    if (!(me = snd_mixer_find_selem(m, sid))) {
        pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
        return -1;
    }

    pa_cvolume_mute(&rv, cm->channels);

    for (c = 0; c <= SND_MIXER_SCHN_LAST; c++) {
        int r;
        pa_volume_t f = PA_VOLUME_MUTED;
        bool found = false;

        for (k = 0; k < cm->channels; k++)
            if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k])) {
                found = true;
                if (v->values[k] > f)
                    f = v->values[k];
            }

        if (!found) {
            /* Hmm, so this channel does not exist in the volume
             * struct, so let's bind it to the overall max of the
             * volume. */
            f = pa_cvolume_max(v);
        }

        if (e->has_dB) {
            long value = to_alsa_dB(f);
            int rounding;

            if (e->volume_limit >= 0 && value > (e->max_dB * 100))
                value = e->max_dB * 100;

            if (e->direction == PA_ALSA_DIRECTION_OUTPUT) {
                /* If we call set_playback_volume() without checking first
                 * if the channel is available, ALSA behaves very
                 * strangely and doesn't fail the call */
                if (snd_mixer_selem_has_playback_channel(me, c)) {