예제 #1
0
static int set_normalized_volume(snd_mixer_elem_t *elem,
				 snd_mixer_selem_channel_id_t channel,
				 double volume,
				 int dir,
				 enum ctl_dir ctl_dir)
{
	long min, max, value;
	double min_norm;
	int err;

	err = get_dB_range[ctl_dir](elem, &min, &max);
	if (err < 0 || min >= max) {
		err = get_raw_range[ctl_dir](elem, &min, &max);
		if (err < 0)
			return err;

		value = lrint_dir(volume * (max - min), dir) + min;
		return set_raw[ctl_dir](elem, channel, value);
	}

	if (use_linear_dB_scale(min, max)) {
		value = lrint_dir(volume * (max - min), dir) + min;
		return set_dB[ctl_dir](elem, channel, value, dir);
	}

	if (min != SND_CTL_TLV_DB_GAIN_MUTE) {
		min_norm = exp10((min - max) / 6000.0);
		volume = volume * (1 - min_norm) + min_norm;
	}
	value = lrint_dir(6000.0 * log10(volume), dir) + max;
	return set_dB[ctl_dir](elem, channel, value, dir);
}
예제 #2
0
파일: alsa.c 프로젝트: aarizkuren/pnmixer
/**
 * Adjusts the current volume and sends a notification (if enabled).
 *
 * @param vol new volume value
 * @param dir select direction (-1 = accurate or first bellow, 0 = accurate,
 * 1 = accurate or first above)
 * @param notify whether to send notification
 * @return 0 on success otherwise negative error code
 */
int
setvol(int vol, int dir, gboolean notify)
{
    long min = 0, max = 0, value;
    int cur_perc = getvol();
    double dvol = 0.01 * vol;

    int err = snd_mixer_selem_get_playback_dB_range(elem, &min, &max);
    if (err < 0 || min >= max || !normalize_vol()) {
        err = snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
        value = lrint_dir(dvol * (max - min), dir) + min;
        snd_mixer_selem_set_playback_volume_all(elem, value);
        if (enable_noti && notify && cur_perc != getvol())
            do_notify_volume(getvol(), FALSE);
        // intentionally set twice
        return snd_mixer_selem_set_playback_volume_all(elem, value);
    }

    if (use_linear_dB_scale(min, max)) {
        value = lrint_dir(dvol * (max - min), dir) + min;
        return snd_mixer_selem_set_playback_dB_all(elem, value, dir);
    }

    if (min != SND_CTL_TLV_DB_GAIN_MUTE) {
        double min_norm = exp10((min - max) / 6000.0);
        dvol = dvol * (1 - min_norm) + min_norm;
    }

    value = lrint_dir(6000.0 * log10(dvol), dir) + max;
    snd_mixer_selem_set_playback_dB_all(elem, value, dir);
    if (enable_noti && notify && cur_perc != getvol())
        do_notify_volume(getvol(), FALSE);
    // intentionally set twice
    return snd_mixer_selem_set_playback_dB_all(elem, value, dir);
}