Accepting request 55588 from multimedia:libs

Accepted submit request 55588 from user tiwai

OBS-URL: https://build.opensuse.org/request/show/55588
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/alsa-utils?expand=0&rev=49
This commit is contained in:
Marcus Rückert 2010-12-10 19:31:08 +00:00 committed by Git OBS Bridge
commit 600a8923b7
6 changed files with 673 additions and 0 deletions

View File

@ -0,0 +1,53 @@
From a97bcd19dcea98be86f15c6af0b5e0a8d234d190 Mon Sep 17 00:00:00 2001
From: Colin Guthrie <cguthrie@mandriva.org>
Date: Thu, 25 Nov 2010 21:40:25 +0000
Subject: [PATCH 40/43] alsactl: Add a --with-udev-rules-dir configure option.
After the previous patch to install udev rules it is impossible to do a
non-root, custom-prefix make install. This is generally not a problem
when building official packages but it can be a pain for developers
and debuggers etc.
This is essentially the same patch as was already made in PulseAudio
in commit e8a5746f2fcae59bfd18d39b621509b3ef130453.
Signed-off-by: Colin Guthrie <gmane@colin.guthr.ie>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
alsactl/Makefile.am | 2 --
configure.in | 6 ++++++
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/alsactl/Makefile.am b/alsactl/Makefile.am
index 721b619..5cfc415 100644
--- a/alsactl/Makefile.am
+++ b/alsactl/Makefile.am
@@ -11,8 +11,6 @@ alsactl_SOURCES=alsactl.c state.c utils.c init_parse.c
alsactl_CFLAGS=$(AM_CFLAGS) -DSYS_ASOUNDRC=\"$(ASOUND_STATE_DIR)/asound.state\"
noinst_HEADERS=alsactl.h list.h init_sysdeps.c init_utils_string.c init_utils_run.c init_sysfs.c
-udevrulesdir=/lib/udev/rules.d
-
dist_udevrules_DATA = \
90-alsa-restore.rules
diff --git a/configure.in b/configure.in
index 77778da..2d6c80c 100644
--- a/configure.in
+++ b/configure.in
@@ -112,6 +112,12 @@ if test x"$alsaconf" = xtrue; then
fi
AM_CONDITIONAL(USE_XMLTO, test x"$xmlto" = xyes)
+AC_ARG_WITH(
+ [udev-rules-dir],
+ AS_HELP_STRING([--with-udev-rules-dir],[Directory where to install udev rules to (defaults to /lib/udev/rules.d)]),
+ [udevrulesdir=$withval], [udevrulesdir="/lib/udev/rules.d"])
+AC_SUBST(udevrulesdir)
+
dnl Checks for header files.
AC_HEADER_STDC
if test x$alsamixer = xtrue; then
--
1.7.3.1

View File

@ -0,0 +1,28 @@
From e57f619c82e2fec20c20c30f56d3fa4db22a8353 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 6 Dec 2010 14:04:39 +0100
Subject: [PATCH 41/43] alsamixer: remove obsolete e-mail
Remove the no-longer-valid e-mail address also from the man page.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
---
alsamixer/alsamixer.1 | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/alsamixer/alsamixer.1 b/alsamixer/alsamixer.1
index ba05aca..cd88404 100644
--- a/alsamixer/alsamixer.1
+++ b/alsamixer/alsamixer.1
@@ -171,7 +171,7 @@ fault. Plain old \fBxterm\fP seems to be fine.
.SH AUTHOR
.B alsamixer
-has been written by Tim Janik <timj@gtk.org> and
+has been written by Tim Janik and
been further improved by Jaroslav Kysela <perex@perex.cz>
and Clemens Ladisch <clemens@ladisch.de>.
--
1.7.3.1

View File

@ -0,0 +1,40 @@
From 70a01748d594ef57a1962e4cb012927faf6d852f Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 6 Dec 2010 14:05:10 +0100
Subject: [PATCH 42/43] alsamixer: increase step size for big control value ranges
For controls with a big range, stepping through all values can become
tedious and make it impossible to adjust the volume easily. Therefore,
ensure that all steps are big enough so that the full range has at most
one hundred steps.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
---
alsamixer/mixer_widget.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/alsamixer/mixer_widget.c b/alsamixer/mixer_widget.c
index c8ca156..adb4568 100644
--- a/alsamixer/mixer_widget.c
+++ b/alsamixer/mixer_widget.c
@@ -318,7 +318,7 @@ static void change_volume_to_percent(struct control *control, int value, unsigne
set_func(control->elem, control->volume_channels[1], min + (max - min) * value / 100);
}
-static void change_volume_relative(struct control *control, int delta, unsigned int channels)
+static void change_volume_relative(struct control *control, long delta, unsigned int channels)
{
int (*get_range_func)(snd_mixer_elem_t *, long *, long *);
int (*get_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long *);
@@ -352,6 +352,8 @@ static void change_volume_relative(struct control *control, int delta, unsigned
if (err < 0)
return;
}
+ if (max - min > 100)
+ delta = (delta * (max - min) + (delta > 0 ? 99 : -99)) / 100;
if (channels & LEFT) {
value = left + delta;
if (value < min)
--
1.7.3.1

View File

@ -0,0 +1,538 @@
From 34bb514b5fd1d6f91ba9a7b3a70b0ea0c6014250 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 6 Dec 2010 14:07:48 +0100
Subject: [PATCH 43/43] alsamixer: use cubic scale for volume bars
Instead of mapping the raw volume values linearly to the screen, use
a mapping where the bar height is proportional to the audible volume,
i.e., where the amplitude is the cube of the bar height.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
---
alsamixer/Makefile.am | 1 +
alsamixer/mixer_display.c | 53 ++++---------
alsamixer/mixer_widget.c | 120 +++++++++++-------------------
alsamixer/volume_mapping.c | 180 ++++++++++++++++++++++++++++++++++++++++++++
alsamixer/volume_mapping.h | 19 +++++
5 files changed, 260 insertions(+), 113 deletions(-)
create mode 100644 alsamixer/volume_mapping.c
create mode 100644 alsamixer/volume_mapping.h
diff --git a/alsamixer/Makefile.am b/alsamixer/Makefile.am
index 1de47c6..8a82323 100644
--- a/alsamixer/Makefile.am
+++ b/alsamixer/Makefile.am
@@ -15,6 +15,7 @@ alsamixer_SOURCES = card_select.c card_select.h \
proc_files.c proc_files.h \
textbox.c textbox.h \
utils.c utils.h \
+ volume_mapping.c volume_mapping.h \
widget.c widget.h
man_MANS = alsamixer.1
EXTRA_DIST = alsamixer.1
diff --git a/alsamixer/mixer_display.c b/alsamixer/mixer_display.c
index 20d6d6a..51a1546 100644
--- a/alsamixer/mixer_display.c
+++ b/alsamixer/mixer_display.c
@@ -17,10 +17,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define _C99_SOURCE /* lrint() */
#include "aconfig.h"
#include <stdlib.h>
#include <string.h>
#include <strings.h>
+#include <math.h>
#include CURSESINC
#include <alsa/asoundlib.h>
#include "gettext_curses.h"
@@ -28,6 +30,7 @@
#include "mem.h"
#include "colors.h"
#include "widget.h"
+#include "volume_mapping.h"
#include "mixer_widget.h"
#include "mixer_controls.h"
#include "mixer_display.h"
@@ -390,24 +393,14 @@ static void display_string_centered_in_control(int y, int col, const char *s, in
display_string_in_field(y, x, s, width, ALIGN_CENTER);
}
-static long clamp(long value, long min, long max)
-{
- if (value < min)
- return min;
- if (value > max)
- return max;
- return value;
-}
-
static void display_control(unsigned int control_index)
{
struct control *control;
int col;
int i, c;
int left, frame_left;
- int bar_height, value;
- long volumes[2];
- long min, max;
+ int bar_height;
+ double volumes[2];
int switches[2];
unsigned int index;
const char *s;
@@ -452,35 +445,22 @@ static void display_control(unsigned int control_index)
waddch(mixer_widget.window, ACS_LRCORNER);
}
if (control->flags & (TYPE_PVOLUME | TYPE_CVOLUME)) {
- int (*get_vol_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long *);
+ double (*get_vol_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t);
if (control->flags & TYPE_PVOLUME)
- get_vol_func = snd_mixer_selem_get_playback_volume;
+ get_vol_func = get_normalized_playback_volume;
else
- get_vol_func = snd_mixer_selem_get_capture_volume;
- err = get_vol_func(control->elem, control->volume_channels[0], &volumes[0]);
- if (err >= 0 && (control->flags & HAS_VOLUME_1))
- err = get_vol_func(control->elem, control->volume_channels[1], &volumes[1]);
+ get_vol_func = get_normalized_capture_volume;
+ volumes[0] = get_vol_func(control->elem, control->volume_channels[0]);
+ if (control->flags & HAS_VOLUME_1)
+ volumes[1] = get_vol_func(control->elem, control->volume_channels[1]);
else
volumes[1] = volumes[0];
- if (err < 0)
- return;
- if (control->flags & TYPE_PVOLUME)
- err = snd_mixer_selem_get_playback_volume_range(control->elem, &min, &max);
- else
- err = snd_mixer_selem_get_capture_volume_range(control->elem, &min, &max);
- if (err < 0)
- return;
- if (min >= max)
- max = min + 1;
- volumes[0] = clamp(volumes[0], min, max);
- volumes[1] = clamp(volumes[1], min, max);
if (control->flags & IS_ACTIVE)
wattrset(mixer_widget.window, 0);
for (c = 0; c < 2; c++) {
- bar_height = ((volumes[c] - min) * volume_height +
- max - min - 1) / (max - min);
+ bar_height = lrint(volumes[c] * volume_height);
for (i = 0; i < volume_height; ++i) {
chtype ch;
if (i + 1 > bar_height)
@@ -505,19 +485,18 @@ static void display_control(unsigned int control_index)
}
if (control->flags & IS_ACTIVE)
wattrset(mixer_widget.window, attr_mixer_active);
- value = ((volumes[0] - min) * 100 + (max - min) / 2) / (max - min);
if (!(control->flags & HAS_VOLUME_1)) {
- sprintf(buf, "%d", value);
+ sprintf(buf, "%d", lrint(volumes[0] * 100));
display_string_in_field(values_y, frame_left - 2, buf, 8, ALIGN_CENTER);
} else {
- mvwprintw(mixer_widget.window, values_y, frame_left - 2, "%3d", value);
+ mvwprintw(mixer_widget.window, values_y, frame_left - 2,
+ "%3d", lrint(volumes[0] * 100));
if (control->flags & IS_ACTIVE)
wattrset(mixer_widget.window, attr_ctl_frame);
waddstr(mixer_widget.window, "<>");
if (control->flags & IS_ACTIVE)
wattrset(mixer_widget.window, attr_mixer_active);
- value = ((volumes[1] - min) * 100 + (max - min) / 2) / (max - min);
- wprintw(mixer_widget.window, "%-3d", value);
+ wprintw(mixer_widget.window, "%-3d", lrint(volumes[1] * 100));
}
}
diff --git a/alsamixer/mixer_widget.c b/alsamixer/mixer_widget.c
index adb4568..fb352d3 100644
--- a/alsamixer/mixer_widget.c
+++ b/alsamixer/mixer_widget.c
@@ -33,6 +33,7 @@
#include "textbox.h"
#include "proc_files.h"
#include "card_select.h"
+#include "volume_mapping.h"
#include "mixer_controls.h"
#include "mixer_display.h"
#include "mixer_widget.h"
@@ -295,82 +296,57 @@ static void change_enum_relative(struct control *control, int delta)
static void change_volume_to_percent(struct control *control, int value, unsigned int channels)
{
- int (*get_range_func)(snd_mixer_elem_t *, long *, long *);
- int (*set_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long);
- long min, max;
- int err;
+ int (*set_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, double, int);
if (!(control->flags & HAS_VOLUME_1))
channels = LEFT;
- if (control->flags & TYPE_PVOLUME) {
- get_range_func = snd_mixer_selem_get_playback_volume_range;
- set_func = snd_mixer_selem_set_playback_volume;
- } else {
- get_range_func = snd_mixer_selem_get_capture_volume_range;
- set_func = snd_mixer_selem_set_capture_volume;
- }
- err = get_range_func(control->elem, &min, &max);
- if (err < 0)
- return;
+ if (control->flags & TYPE_PVOLUME)
+ set_func = set_normalized_playback_volume;
+ else
+ set_func = set_normalized_capture_volume;
if (channels & LEFT)
- set_func(control->elem, control->volume_channels[0], min + (max - min) * value / 100);
+ set_func(control->elem, control->volume_channels[0], value / 100.0, 0);
if (channels & RIGHT)
- set_func(control->elem, control->volume_channels[1], min + (max - min) * value / 100);
+ set_func(control->elem, control->volume_channels[1], value / 100.0, 0);
}
-static void change_volume_relative(struct control *control, long delta, unsigned int channels)
+static double clamp_volume(double v)
{
- int (*get_range_func)(snd_mixer_elem_t *, long *, long *);
- int (*get_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long *);
- int (*set_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long);
- long min, max;
- long left, right;
- long value;
- int err;
+ if (v < 0)
+ return 0;
+ if (v > 1)
+ return 1;
+ return v;
+}
+
+static void change_volume_relative(struct control *control, int delta, unsigned int channels)
+{
+ double (*get_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t);
+ int (*set_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, double, int);
+ double left, right;
+ int dir;
if (!(control->flags & HAS_VOLUME_1))
channels = LEFT;
if (control->flags & TYPE_PVOLUME) {
- get_range_func = snd_mixer_selem_get_playback_volume_range;
- get_func = snd_mixer_selem_get_playback_volume;
- set_func = snd_mixer_selem_set_playback_volume;
+ get_func = get_normalized_playback_volume;
+ set_func = set_normalized_playback_volume;
} else {
- get_range_func = snd_mixer_selem_get_capture_volume_range;
- get_func = snd_mixer_selem_get_capture_volume;
- set_func = snd_mixer_selem_set_capture_volume;
+ get_func = get_normalized_capture_volume;
+ set_func = set_normalized_capture_volume;
}
- err = get_range_func(control->elem, &min, &max);
- if (err < 0)
- return;
- if (channels & LEFT) {
- err = get_func(control->elem, control->volume_channels[0], &left);
- if (err < 0)
- return;
- }
- if (channels & RIGHT) {
- err = get_func(control->elem, control->volume_channels[1], &right);
- if (err < 0)
- return;
- }
- if (max - min > 100)
- delta = (delta * (max - min) + (delta > 0 ? 99 : -99)) / 100;
+ if (channels & LEFT)
+ left = get_func(control->elem, control->volume_channels[0]);
+ if (channels & RIGHT)
+ right = get_func(control->elem, control->volume_channels[1]);
+ dir = delta > 0 ? 1 : -1;
if (channels & LEFT) {
- value = left + delta;
- if (value < min)
- value = min;
- else if (value > max)
- value = max;
- if (value != left)
- set_func(control->elem, control->volume_channels[0], value);
+ left = clamp_volume(left + delta / 100.0);
+ set_func(control->elem, control->volume_channels[0], left, dir);
}
if (channels & RIGHT) {
- value = right + delta;
- if (value < min)
- value = min;
- else if (value > max)
- value = max;
- if (value != right)
- set_func(control->elem, control->volume_channels[1], value);
+ right = clamp_volume(right + delta / 100.0);
+ set_func(control->elem, control->volume_channels[1], right, dir);
}
}
@@ -460,34 +436,26 @@ static void toggle_capture(unsigned int channels)
static void balance_volumes(void)
{
struct control *control;
- long left, right;
+ double left, right;
int err;
control = get_focus_control(TYPE_PVOLUME | TYPE_CVOLUME);
if (!control || !(control->flags & HAS_VOLUME_1))
return;
if (control->flags & TYPE_PVOLUME) {
- err = snd_mixer_selem_get_playback_volume(control->elem, control->volume_channels[0], &left);
- if (err < 0)
- return;
- err = snd_mixer_selem_get_playback_volume(control->elem, control->volume_channels[1], &right);
- if (err < 0)
- return;
+ left = get_normalized_playback_volume(control->elem, control->volume_channels[0]);
+ right = get_normalized_playback_volume(control->elem, control->volume_channels[1]);
} else {
- err = snd_mixer_selem_get_capture_volume(control->elem, control->volume_channels[0], &left);
- if (err < 0)
- return;
- err = snd_mixer_selem_get_capture_volume(control->elem, control->volume_channels[1], &right);
- if (err < 0)
- return;
+ left = get_normalized_capture_volume(control->elem, control->volume_channels[0]);
+ right = get_normalized_capture_volume(control->elem, control->volume_channels[1]);
}
left = (left + right) / 2;
if (control->flags & TYPE_PVOLUME) {
- snd_mixer_selem_set_playback_volume(control->elem, control->volume_channels[0], left);
- snd_mixer_selem_set_playback_volume(control->elem, control->volume_channels[1], left);
+ set_normalized_playback_volume(control->elem, control->volume_channels[0], left, 0);
+ set_normalized_playback_volume(control->elem, control->volume_channels[1], left, 0);
} else {
- snd_mixer_selem_set_capture_volume(control->elem, control->volume_channels[0], left);
- snd_mixer_selem_set_capture_volume(control->elem, control->volume_channels[1], left);
+ set_normalized_capture_volume(control->elem, control->volume_channels[0], left, 0);
+ set_normalized_capture_volume(control->elem, control->volume_channels[1], left, 0);
}
display_controls();
}
diff --git a/alsamixer/volume_mapping.c b/alsamixer/volume_mapping.c
new file mode 100644
index 0000000..9cacad8
--- /dev/null
+++ b/alsamixer/volume_mapping.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2010 Clemens Ladisch <clemens@ladisch.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * The functions in this file map the value ranges of ALSA mixer controls onto
+ * the interval 0..1.
+ *
+ * The mapping is designed so that the position in the interval is proportional
+ * to the volume as a human ear would perceive it (i.e., the position is the
+ * cubic root of the linear sample multiplication factor). For controls with
+ * a small range (24 dB or less), the mapping is linear in the dB values so
+ * that each step has the same size visually. Only for controls without dB
+ * information, a linear mapping of the hardware volume register values is used
+ * (this is the same algorithm as used in the old alsamixer).
+ *
+ * When setting the volume, 'dir' is the rounding direction:
+ * -1/0/1 = down/nearest/up.
+ */
+
+#define _ISOC99_SOURCE /* lrint() */
+#define _GNU_SOURCE /* exp10() */
+#include "aconfig.h"
+#include <math.h>
+#include <stdbool.h>
+#include "volume_mapping.h"
+
+#define MAX_LINEAR_DB_SCALE 24
+
+static inline bool use_linear_dB_scale(long dBmin, long dBmax)
+{
+ return dBmax - dBmin <= MAX_LINEAR_DB_SCALE * 100;
+}
+
+static long lrint_dir(double x, int dir)
+{
+ if (dir > 0)
+ return lrint(ceil(x));
+ else if (dir < 0)
+ return lrint(floor(x));
+ else
+ return lrint(x);
+}
+
+enum ctl_dir { PLAYBACK, CAPTURE };
+
+static int (* const get_dB_range[2])(snd_mixer_elem_t *, long *, long *) = {
+ snd_mixer_selem_get_playback_dB_range,
+ snd_mixer_selem_get_capture_dB_range,
+};
+static int (* const get_raw_range[2])(snd_mixer_elem_t *, long *, long *) = {
+ snd_mixer_selem_get_playback_volume_range,
+ snd_mixer_selem_get_capture_volume_range,
+};
+static int (* const get_dB[2])(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long *) = {
+ snd_mixer_selem_get_playback_dB,
+ snd_mixer_selem_get_capture_dB,
+};
+static int (* const get_raw[2])(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long *) = {
+ snd_mixer_selem_get_playback_volume,
+ snd_mixer_selem_get_capture_volume,
+};
+static int (* const set_dB[2])(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long, int) = {
+ snd_mixer_selem_set_playback_dB,
+ snd_mixer_selem_set_capture_dB,
+};
+static int (* const set_raw[2])(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long) = {
+ snd_mixer_selem_set_playback_volume,
+ snd_mixer_selem_set_capture_volume,
+};
+
+static double get_normalized_volume(snd_mixer_elem_t *elem,
+ snd_mixer_selem_channel_id_t channel,
+ enum ctl_dir ctl_dir)
+{
+ long min, max, value;
+ double normalized, 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 || min == max)
+ return 0;
+
+ err = get_raw[ctl_dir](elem, channel, &value);
+ if (err < 0)
+ return 0;
+
+ return (value - min) / (double)(max - min);
+ }
+
+ err = get_dB[ctl_dir](elem, channel, &value);
+ if (err < 0)
+ return 0;
+
+ if (use_linear_dB_scale(min, max))
+ return (value - min) / (double)(max - min);
+
+ normalized = exp10((value - max) / 6000.0);
+ if (min != SND_CTL_TLV_DB_GAIN_MUTE) {
+ min_norm = exp10((min - max) / 6000.0);
+ normalized = (normalized - min_norm) / (1 - min_norm);
+ }
+
+ return normalized;
+}
+
+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);
+}
+
+double get_normalized_playback_volume(snd_mixer_elem_t *elem,
+ snd_mixer_selem_channel_id_t channel)
+{
+ return get_normalized_volume(elem, channel, PLAYBACK);
+}
+
+double get_normalized_capture_volume(snd_mixer_elem_t *elem,
+ snd_mixer_selem_channel_id_t channel)
+{
+ return get_normalized_volume(elem, channel, CAPTURE);
+}
+
+int set_normalized_playback_volume(snd_mixer_elem_t *elem,
+ snd_mixer_selem_channel_id_t channel,
+ double volume,
+ int dir)
+{
+ return set_normalized_volume(elem, channel, volume, dir, PLAYBACK);
+}
+
+int set_normalized_capture_volume(snd_mixer_elem_t *elem,
+ snd_mixer_selem_channel_id_t channel,
+ double volume,
+ int dir)
+{
+ return set_normalized_volume(elem, channel, volume, dir, CAPTURE);
+}
diff --git a/alsamixer/volume_mapping.h b/alsamixer/volume_mapping.h
new file mode 100644
index 0000000..d4251d6
--- /dev/null
+++ b/alsamixer/volume_mapping.h
@@ -0,0 +1,19 @@
+#ifndef VOLUME_MAPPING_H_INCLUDED
+#define VOLUME_MAPPING_H_INCLUDED
+
+#include <alsa/asoundlib.h>
+
+double get_normalized_playback_volume(snd_mixer_elem_t *elem,
+ snd_mixer_selem_channel_id_t channel);
+double get_normalized_capture_volume(snd_mixer_elem_t *elem,
+ snd_mixer_selem_channel_id_t channel);
+int set_normalized_playback_volume(snd_mixer_elem_t *elem,
+ snd_mixer_selem_channel_id_t channel,
+ double volume,
+ int dir);
+int set_normalized_capture_volume(snd_mixer_elem_t *elem,
+ snd_mixer_selem_channel_id_t channel,
+ double volume,
+ int dir);
+
+#endif
--
1.7.3.1

View File

@ -1,3 +1,9 @@
-------------------------------------------------------------------
Thu Dec 9 14:03:18 CET 2010 - tiwai@suse.de
- Use cubic scale for alsamixer volume bars for better usability
- Misc fixes from upstream
-------------------------------------------------------------------
Tue Nov 30 08:42:50 CET 2010 - tiwai@suse.de

View File

@ -77,6 +77,10 @@ Patch36: 0036-update-German-translations.patch
Patch37: 0037-alsactl-systemd-and-udev-hookup.patch
Patch38: 0038-alsactl-Move-asound.state-location-to-var-lib-alsa.patch
Patch39: 0039-configure.in-Fix-variable-name.patch
Patch40: 0040-alsactl-Add-a-with-udev-rules-dir-configure-option.patch
Patch41: 0041-alsamixer-remove-obsolete-e-mail.patch
Patch42: 0042-alsamixer-increase-step-size-for-big-control-value-r.patch
Patch43: 0043-alsamixer-use-cubic-scale-for-volume-bars.patch
Patch99: alsa-utils-gettext-version-removal.diff
Patch100: alsa-utils-po-pre-patch.diff
Url: http://www.alsa-project.org/
@ -140,6 +144,10 @@ sed -i -e's/EXTRA_DIST= config.rpath /EXTRA_DIST=/' Makefile.am
%patch37 -p1
%patch38 -p1
%patch39 -p1
%patch40 -p1
%patch41 -p1
%patch42 -p1
%patch43 -p1
%if %suse_version < 1020
%patch99 -p1
%endif