diff options
Diffstat (limited to 'src/modules/alsa/alsa-mixer.c')
-rw-r--r-- | src/modules/alsa/alsa-mixer.c | 108 |
1 files changed, 59 insertions, 49 deletions
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index 3eef5f9c..51a6cd64 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -1084,10 +1084,14 @@ int pa_alsa_path_set_mute(pa_alsa_path *p, snd_mixer_t *m, pa_bool_t muted) { return 0; } -static int element_mute_volume(pa_alsa_element *e, snd_mixer_t *m) { - snd_mixer_elem_t *me; - snd_mixer_selem_id_t *sid; - int r; +/* Depending on whether e->volume_use is _OFF, _ZERO or _CONSTANT, this + * function sets all channels of the volume element to e->min_volume, 0 dB or + * e->constant_volume. */ +static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) { + snd_mixer_elem_t *me = NULL; + snd_mixer_selem_id_t *sid = NULL; + int r = 0; + long volume = -1; pa_assert(m); pa_assert(e); @@ -1098,49 +1102,44 @@ static int element_mute_volume(pa_alsa_element *e, snd_mixer_t *m) { return -1; } - if (e->direction == PA_ALSA_DIRECTION_OUTPUT) - r = snd_mixer_selem_set_playback_volume_all(me, e->min_volume); - else - r = snd_mixer_selem_set_capture_volume_all(me, e->min_volume); - - if (r < 0) - pa_log_warn("Failed to set volume to muted of %s: %s", e->alsa_name, pa_alsa_strerror(errno)); + switch (e->volume_use) { + case PA_ALSA_VOLUME_OFF: + volume = e->min_volume; + break; - return r; -} + case PA_ALSA_VOLUME_ZERO: + if (e->db_fix) { + long dB = 0; -/* The volume to 0dB */ -static int element_zero_volume(pa_alsa_element *e, snd_mixer_t *m) { - snd_mixer_elem_t *me; - snd_mixer_selem_id_t *sid; - int r; + volume = decibel_fix_get_step(e->db_fix, &dB, +1); + } + break; - pa_assert(m); - pa_assert(e); + case PA_ALSA_VOLUME_CONSTANT: + volume = e->constant_volume; + break; - 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; + default: + pa_assert_not_reached(); } - if (e->direction == PA_ALSA_DIRECTION_OUTPUT) - if (e->db_fix) { - long value = 0; + if (volume >= 0) { + if (e->direction == PA_ALSA_DIRECTION_OUTPUT) + r = snd_mixer_selem_set_playback_volume_all(me, volume); + else + r = snd_mixer_selem_set_capture_volume_all(me, volume); + } else { + pa_assert(e->volume_use == PA_ALSA_VOLUME_ZERO); + pa_assert(!e->db_fix); - r = snd_mixer_selem_set_playback_volume_all(me, decibel_fix_get_step(e->db_fix, &value, +1)); - } else + if (e->direction == PA_ALSA_DIRECTION_OUTPUT) r = snd_mixer_selem_set_playback_dB_all(me, 0, +1); - else - if (e->db_fix) { - long value = 0; - - r = snd_mixer_selem_set_capture_volume_all(me, decibel_fix_get_step(e->db_fix, &value, +1)); - } else + else r = snd_mixer_selem_set_capture_dB_all(me, 0, +1); + } if (r < 0) - pa_log_warn("Failed to set volume to 0dB of %s: %s", e->alsa_name, pa_alsa_strerror(errno)); + pa_log_warn("Failed to set volume of %s: %s", e->alsa_name, pa_alsa_strerror(errno)); return r; } @@ -1178,11 +1177,9 @@ int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m) { switch (e->volume_use) { case PA_ALSA_VOLUME_OFF: - r = element_mute_volume(e, m); - break; - case PA_ALSA_VOLUME_ZERO: - r = element_zero_volume(e, m); + case PA_ALSA_VOLUME_CONSTANT: + r = element_set_constant_volume(e, m); break; case PA_ALSA_VOLUME_MERGE: @@ -1368,6 +1365,12 @@ static int element_probe(pa_alsa_element *e, snd_mixer_t *m) { pa_log_warn("Your kernel driver is broken: it reports a volume range from %li to %li which makes no sense.", e->min_volume, e->max_volume); e->volume_use = PA_ALSA_VOLUME_IGNORE; + } else if (e->volume_use == PA_ALSA_VOLUME_CONSTANT && + (e->min_volume > e->constant_volume || e->max_volume < e->constant_volume)) { + pa_log_warn("Constant volume %li configured for element %s, but the available range is from %li to %li.", + e->constant_volume, e->alsa_name, e->min_volume, e->max_volume); + e->volume_use = PA_ALSA_VOLUME_IGNORE; + } else { pa_bool_t is_mono; pa_channel_position_t p; @@ -1685,8 +1688,15 @@ static int element_parse_volume( else if (pa_streq(rvalue, "zero")) e->volume_use = PA_ALSA_VOLUME_ZERO; else { - pa_log("[%s:%u] Volume invalid of '%s'", filename, line, section); - return -1; + uint32_t constant; + + if (pa_atou(rvalue, &constant) >= 0) { + e->volume_use = PA_ALSA_VOLUME_CONSTANT; + e->constant_volume = constant; + } else { + pa_log("[%s:%u] Volume invalid of '%s'", filename, line, section); + return -1; + } } return 0; @@ -2637,7 +2647,7 @@ pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t d pa_bool_t duplicate = FALSE; char **kn, *fn; - for (kn = pn; kn != in; kn++) + for (kn = pn; kn < in; kn++) if (pa_streq(*kn, *in)) { duplicate = TRUE; break; @@ -3669,14 +3679,14 @@ void pa_alsa_decibel_fix_dump(pa_alsa_decibel_fix *db_fix) { if (db_fix->db_values) { pa_strbuf *buf; - long i; - long max_i = db_fix->max_step - db_fix->min_step; + unsigned long i, nsteps; - buf = pa_strbuf_new(); - pa_strbuf_printf(buf, "[%li]:%0.2f", db_fix->min_step, db_fix->db_values[0] / 100.0); + pa_assert(db_fix->min_step <= db_fix->max_step); + nsteps = db_fix->max_step - db_fix->min_step + 1; - for (i = 1; i <= max_i; ++i) - pa_strbuf_printf(buf, " [%li]:%0.2f", i + db_fix->min_step, db_fix->db_values[i] / 100.0); + buf = pa_strbuf_new(); + for (i = 0; i < nsteps; ++i) + pa_strbuf_printf(buf, "[%li]:%0.2f ", i + db_fix->min_step, db_fix->db_values[i] / 100.0); db_values = pa_strbuf_tostring_free(buf); } |