Package: hotkeys Version: 0.5.7.4-0.1 Severity: normal Tags: patch I've implemnted support in hotkeys for using the alsa mixer. A patch is attached. It's fairly complete, though I hardcoded -lasound in the Makefiile, as I don't enjoy messing around with autoconf.
I chose to only enable alsa if the ALSAcontrol config file option, which probably needs to be tuned for each system anyway, is filled in. Without that it will continue doing the old-style OSS mixing, which doesn't seem to affect the alsa volume at all. Since the patch allows ALSAcontrol to be set to a list of controls, which are all controlled at once, it fixes bug #305716. A useful tip for laptops with separate speaker and headphone volumes: Have hotkeys control them both, and use alsamixer to mute the headphones. Then when you toggle the muting, the headphones will unmute, and the speaker will mute, so you can switch between them like that. -- System Information: Debian Release: lenny/sid APT prefers unstable APT policy: (500, 'unstable'), (500, 'testing'), (1, 'experimental') Architecture: i386 (i686) Kernel: Linux 2.6.21-2-686 (SMP w/1 CPU core) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Versions of packages hotkeys depends on: ii libasound2 1.0.14a-2 ALSA library ii libatk1.0-0 1.18.0-2 The ATK accessibility toolkit ii libc6 2.6-2 GNU C Library: Shared libraries ii libcairo2 1.4.10-1 The Cairo 2D vector graphics libra ii libdb4.5 4.5.20-5 Berkeley v4.5 Database Libraries [ ii libfontconfig1 2.4.2-1.2 generic font configuration library ii libglib2.0-0 2.12.13-1 The GLib library of C routines ii libgtk2.0-0 2.10.13-1 The GTK+ graphical user interface ii libpango1.0-0 1.16.4-3 Layout and rendering of internatio ii libx11-6 2:1.0.3-7 X11 client-side library ii libxcursor1 1:1.1.8-2 X cursor management library ii libxext6 1:1.0.3-2 X11 miscellaneous extension librar ii libxfixes3 1:4.0.3-2 X11 miscellaneous 'fixes' extensio ii libxi6 2:1.1.1-1 X11 Input extension library ii libxinerama1 1:1.0.2-1 X11 Xinerama extension library ii libxml2 2.6.29.dfsg-1 GNOME XML library ii libxmu6 1:1.0.3-1 X11 miscellaneous utility library ii libxosd2 2.2.14-1.3 X On-Screen Display library - runt ii libxrandr2 2:1.2.1-1 X11 RandR extension library ii libxrender1 1:0.9.2-1 X Rendering Extension client libra hotkeys recommends no packages. -- no debconf information -- see shy jo
diff --new-file -ur old/hotkeys-0.5.7.4/TODO hotkeys-0.5.7.4/TODO --- old/hotkeys-0.5.7.4/TODO 2002-11-28 09:30:14.000000000 -0500 +++ hotkeys-0.5.7.4/TODO 2007-07-27 23:55:36.000000000 -0400 @@ -12,8 +12,6 @@ - Support of devfs -- Support of ALSA (hardware mute) - - Multiple functionalities per key - Support true sleeping, suspend and power down (or logging out from WM). diff --new-file -ur old/hotkeys-0.5.7.4/src/Makefile.am hotkeys-0.5.7.4/src/Makefile.am --- old/hotkeys-0.5.7.4/src/Makefile.am 2002-12-08 09:16:20.000000000 -0500 +++ hotkeys-0.5.7.4/src/Makefile.am 2007-07-27 12:51:23.000000000 -0400 @@ -1,13 +1,13 @@ bin_PROGRAMS = hotkeys hotkeys_SOURCES = hotkeys.c kbddef.c conf.c fixVMware.c apmlib.c xmalloc.c \ - splash.c \ + splash.c amixer.c \ XF86keysym.h apm.h common.h conf.h hotkeys.h kbddef.h \ - xmalloc.h splash.h + xmalloc.h splash.h amixer.h sysconf_DATA = hotkeys.conf man_MANS = hotkeys.1 CFLAGS = @CFLAGS@ @X_CFLAGS@ @XML_CFLAGS@ @LIBXOSD_CFLAGS@ @GTK_CFLAGS@ -I.. # -DDEBUG -LIBS = @LIBS@ @X_LIBS@ @XML_LIBS@ @LIBXOSD_LIBS@ @GTK_LIBS@ +LIBS = @LIBS@ @X_LIBS@ @XML_LIBS@ @LIBXOSD_LIBS@ @GTK_LIBS@ -lasound DEFS = @DEFS@ -DSHAREDIR=\"@datadir@/@[EMAIL PROTECTED]" \ -DCONFDIR=\"@[EMAIL PROTECTED]" -DCONFIG_NAME=\"@[EMAIL PROTECTED]" diff --new-file -ur old/hotkeys-0.5.7.4/src/Makefile.in hotkeys-0.5.7.4/src/Makefile.in --- old/hotkeys-0.5.7.4/src/Makefile.in 2002-12-08 09:34:44.000000000 -0500 +++ hotkeys-0.5.7.4/src/Makefile.in 2007-07-27 12:51:25.000000000 -0400 @@ -96,13 +96,13 @@ l = @l@ bin_PROGRAMS = hotkeys -hotkeys_SOURCES = hotkeys.c kbddef.c conf.c fixVMware.c apmlib.c xmalloc.c splash.c XF86keysym.h apm.h common.h conf.h hotkeys.h kbddef.h xmalloc.h splash.h +hotkeys_SOURCES = hotkeys.c kbddef.c conf.c fixVMware.c apmlib.c xmalloc.c splash.c amixer.c XF86keysym.h apm.h common.h conf.h hotkeys.h kbddef.h xmalloc.h splash.h amixer.h sysconf_DATA = hotkeys.conf man_MANS = hotkeys.1 CFLAGS = @CFLAGS@ @X_CFLAGS@ @XML_CFLAGS@ @LIBXOSD_CFLAGS@ @GTK_CFLAGS@ -I.. # -DDEBUG -LIBS = @LIBS@ @X_LIBS@ @XML_LIBS@ @LIBXOSD_LIBS@ @GTK_LIBS@ +LIBS = @LIBS@ @X_LIBS@ @XML_LIBS@ @LIBXOSD_LIBS@ @GTK_LIBS@ -lasound DEFS = @DEFS@ -DSHAREDIR=\"@datadir@/@[EMAIL PROTECTED]" -DCONFDIR=\"@[EMAIL PROTECTED]" -DCONFIG_NAME=\"@[EMAIL PROTECTED]" @@ -121,7 +121,7 @@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ hotkeys_OBJECTS = hotkeys.o kbddef.o conf.o fixVMware.o apmlib.o \ -xmalloc.o splash.o +xmalloc.o splash.o amixer.o hotkeys_LDADD = $(LDADD) hotkeys_DEPENDENCIES = hotkeys_LDFLAGS = diff --new-file -ur old/hotkeys-0.5.7.4/src/amixer.c hotkeys-0.5.7.4/src/amixer.c --- old/hotkeys-0.5.7.4/src/amixer.c 1969-12-31 19:00:00.000000000 -0500 +++ hotkeys-0.5.7.4/src/amixer.c 2007-07-28 15:04:25.000000000 -0400 @@ -0,0 +1,293 @@ +/* + * ALSA command line mixer utility + * Copyright (c) 1999-2000 by Jaroslav Kysela <[EMAIL PROTECTED]> + * Modified for hotkeys by Joey Hess <[EMAIL PROTECTED]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <stdarg.h> +#include <ctype.h> +#include <math.h> +#include <errno.h> +#include <assert.h> +#include <alsa/asoundlib.h> +#include <sys/poll.h> + +#include "hotkeys.h" +#include "xmalloc.h" + +char *card; +char **controls; +int numcontrols=0; +snd_mixer_t *handle = NULL; + +static int parse_simple_id(const char *str, snd_mixer_selem_id_t *sid) { + int c, size; + char buf[128]; + char *ptr = buf; + + while (*str == ' ' || *str == '\t') + str++; + if (!(*str)) + return -EINVAL; + size = 1; /* for '\0' */ + if (*str != '"' && *str != '\'') { + while (*str && *str != ',') { + if (size < (int)sizeof(buf)) { + *ptr++ = *str; + size++; + } + str++; + } + } else { + c = *str++; + while (*str && *str != c) { + if (size < (int)sizeof(buf)) { + *ptr++ = *str; + size++; + } + str++; + } + if (*str == c) + str++; + } + if (*str == '\0') { + snd_mixer_selem_id_set_index(sid, 0); + *ptr = 0; + goto _set; + } + if (*str != ',') + return -EINVAL; + *ptr = 0; /* terminate the string */ + str++; + if (!isdigit(*str)) + return -EINVAL; + snd_mixer_selem_id_set_index(sid, atoi(str)); + _set: + snd_mixer_selem_id_set_name(sid, buf); + return 0; +} + +snd_mixer_elem_t *getelem(char *control) { + snd_mixer_elem_t *elem; + snd_mixer_selem_id_t *sid; + snd_mixer_selem_id_alloca(&sid); + + if (control == NULL) + return NULL; + + if (parse_simple_id(control, sid)) { + uError("Bad ALSA control '%s'", control); + return NULL; + } + elem = snd_mixer_find_selem(handle, sid); + if (!elem) { + uError("Unable to find ALSA control '%s',%i", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid)); + return NULL; + } + + return elem; +} + +int gethandle(void) { + int err=0; + + if (handle) { + snd_mixer_close(handle); + handle=NULL; + } + + if ((err = snd_mixer_open(&handle, 0)) < 0) { + uError("Mixer %s open error: %s", card, snd_strerror(err)); + return err; + } + if ((err = snd_mixer_attach(handle, card)) < 0) { + uError("Mixer attach %s error: %s", card, snd_strerror(err)); + snd_mixer_close(handle); + handle = NULL; + return err; + } + if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) { + uError("Mixer register error: %s", snd_strerror(err)); + snd_mixer_close(handle); + handle = NULL; + return err; + } + err = snd_mixer_load(handle); + if (err < 0) { + uError("Mixer %s load error: %s", card, snd_strerror(err)); + snd_mixer_close(handle); + handle = NULL; + return err; + } + + return 0; +} + +int configALSA(char *alsacard, char *alsacontrols) { + int i = 0; + char *c = alsacontrols; + + if (alsacard == NULL || alsacontrols == NULL) { + return 1; + } + + card=alsacard; + + /* Split controls into array and parse. */ + do { + c = strchr( c+1, '|' ); + numcontrols++; + } while ( c != NULL ); + controls = XMALLOC( char *, numcontrols ); + /* dup needed since strtok modifies the string */ + c = (char*) xstrdup( alsacontrols ); + controls[0] = strtok( c, "|" ); + while ( i < numcontrols ) { + i++; + controls[i] = strtok( NULL, "|" ); + } + + return 0; /* success */ +} + +#define check_range(val, min, max) \ + ((val < min) ? (min) : (val > max) ? (max) : (val)) + +/* Fuction to convert from volume to percentage. val = volume */ + +static int convert_prange(int val, int min, int max) { + int range = max - min; + int tmp; + + if (range == 0) + return 0; + val -= min; + tmp = rint((double)val/(double)range * 100); + return tmp; +} + +#define convert_prange1(val, min, max) \ + ceil((val) * ((max) - (min)) * 0.01 + (min)) + +static int set_volume_simple(snd_mixer_elem_t *elem, + snd_mixer_selem_channel_id_t chn, + int percent) { + long val, pmin, pmax; + int invalid = 0, err = 0; + + if (! snd_mixer_selem_has_playback_volume(elem)) + invalid = 1; + + if (! invalid && + snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax) < 0) + invalid = 1; + + if (! invalid) + val = (long)convert_prange1(percent, pmin, pmax); + + if (! invalid) { + val = check_range(val, pmin, pmax); + err = snd_mixer_selem_set_playback_volume(elem, chn, val); + } + return err ? err : (invalid ? -ENOENT : 0); +} + +/* Pass percent to change mixer, or zero to toggle mute. Returns new + * mixer volume if changed, or mute status if mute changed, or negative + * on error. (Returned values are for the first control only.) */ +int amixer(int percent) { + snd_mixer_selem_channel_id_t chn; + unsigned int channels = ~0U; + long pvol; + long pmin = 0, pmax = 0; + int i; + int err=0, ret = -1; + + /* Need to reopen the handle every time to detect changes to the + * mixer state. This is probably not the best way.. */ + if (gethandle() != 0) { + err=-1; + } + + if (! numcontrols) { + uError("internal error: no controls"); + err=-1; + } + + int firstcontrol = 1; + for (i = 0; i < numcontrols; i++ ) { + snd_mixer_elem_t *elem = getelem(controls[i]); + + if (elem == NULL) + continue; + + int firstchn = 1; + for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) { + int ival; + if (!(channels & (1 << chn))) + continue; + if (snd_mixer_selem_has_playback_channel(elem, chn)) { + if (percent == 0) { + if (snd_mixer_selem_has_playback_switch(elem) && + (firstchn || !snd_mixer_selem_has_playback_switch_joined(elem))) { + snd_mixer_selem_get_playback_switch(elem, chn, &ival); + snd_mixer_selem_set_playback_switch(elem, chn, (ival ? 1 : 0) ^ 1); + if (firstcontrol) { + ret = ival; + firstcontrol=0; + } + } + } + else { + int current_percent; + + snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax); + snd_mixer_selem_get_playback_volume(elem, chn, &pvol); + current_percent = convert_prange(pvol, pmin, pmax); + + current_percent += percent; + if (current_percent > 100) + current_percent = 100; + /* 1 not 0 to avoid muting */ + else if (current_percent < 1) + current_percent = 1; + + if (set_volume_simple(elem, chn, current_percent) > 0) { + uError("volume set failed"); + err=-1; + } + + if (firstcontrol) { + ret = current_percent; + firstcontrol=0; + } + } + } + firstchn = 0; + } + } + + if (err != 0) + return err; + else + return ret; +} diff --new-file -ur old/hotkeys-0.5.7.4/src/amixer.h hotkeys-0.5.7.4/src/amixer.h --- old/hotkeys-0.5.7.4/src/amixer.h 1969-12-31 19:00:00.000000000 -0500 +++ hotkeys-0.5.7.4/src/amixer.h 2007-07-27 12:53:56.000000000 -0400 @@ -0,0 +1,2 @@ +int amixer(int percent); +int configALSA(char *alsacard, char *alsacontrols); diff --new-file -ur old/hotkeys-0.5.7.4/src/conf.c hotkeys-0.5.7.4/src/conf.c --- old/hotkeys-0.5.7.4/src/conf.c 2007-07-20 09:53:06.000000000 -0400 +++ hotkeys-0.5.7.4/src/conf.c 2007-07-27 12:02:13.000000000 -0400 @@ -41,6 +41,11 @@ /* CDROM device */ "CDROM", "/dev/cdrom", + /* ALSA card */ + "ALSAcard", "default", + /* List of ALSA control names, separated by "|" */ + //"ALSAcontrols" "Master", + /* general actions */ "PrevTrack", "xmms --rew", "Play", "xmms --play-pause", diff --new-file -ur old/hotkeys-0.5.7.4/src/hotkeys.1 hotkeys-0.5.7.4/src/hotkeys.1 --- old/hotkeys-0.5.7.4/src/hotkeys.1 2004-12-24 10:45:02.000000000 -0500 +++ hotkeys-0.5.7.4/src/hotkeys.1 2007-07-28 00:00:58.000000000 -0400 @@ -141,6 +141,11 @@ # CDROM device CDROM /dev/cdrom + # ALSA card + ALSAcard default + # List of ALSA control names, separated by "|" + ALSAcontrols Master + # audio actions PrevTrack xmms --rew Play xmms --play @@ -180,6 +185,11 @@ .SH "NOTES" Do not disable the XKEYBOARD extension. For XFree86 3.x, make sure \fBXkbDisable\fR is not set. +.P +The ALSA control names have to be set to enable using ALSA. Otherwise, it +defaults to using OSS volume control. The ALSA control names are the same +as those used by the amixer(1) program, use "amixer scontrols" to list. +All listed controls will be adjusted at the same time by hotkeys. .SH "TODO" Please consult the TODO file. .SH "BUGS" diff --new-file -ur old/hotkeys-0.5.7.4/src/hotkeys.c hotkeys-0.5.7.4/src/hotkeys.c --- old/hotkeys-0.5.7.4/src/hotkeys.c 2005-02-19 13:29:23.000000000 -0500 +++ hotkeys-0.5.7.4/src/hotkeys.c 2007-07-27 23:49:30.000000000 -0400 @@ -75,6 +75,7 @@ #include "hotkeys.h" #include "conf.h" +#include "amixer.h" #include <X11/Xmu/Error.h> @@ -97,6 +98,7 @@ int loglevel = 0; Bool background = True; Bool noSplash = False; +Bool haveALSA = False; FILE * errorFile = NULL; @@ -340,7 +342,6 @@ close (fd); } - static void setLoglevel(int level) { @@ -624,6 +625,19 @@ last_time.tv_usec = this_time.tv_usec; } + if (haveALSA) { + master_vol = amixer(adj); + if (master_vol < 0) + return master_vol; +#ifdef HAVE_LIBXOSD + if (osd) { + xosd_display(osd, 0, XOSD_string, "Volume"); + xosd_display(osd, 1, XOSD_percentage, master_vol); + } +#endif + return ret; + } + /* open the mixer device */ if ( (mixer_fd = open( MIXER_DEV, O_RDWR|O_NONBLOCK )) == -1 ) { @@ -745,6 +759,18 @@ short ret = 0; /* return value */ + if (haveALSA) + ret = amixer(0); + if (ret >= 0 && osd) { + if (ret) { + xosd_display(osd, 0, XOSD_string, "Mute"); + } + else { + xosd_display(osd, 0, XOSD_string, "Unmute"); + } + } + return ret; + /* open the mixer device */ if ( (mixer_fd = open( MIXER_DEV, O_RDWR|O_NONBLOCK )) == -1 ) { @@ -1506,6 +1532,9 @@ if ( !parseArgs(argc,argv) ) bailout(); + if ( configALSA(strdup(getConfig("ALSAcard")), strdup(getConfig("ALSAcontrols"))) == 0) + haveALSA = True; + #if HAVE_GTK if ( !noSplash ) { diff --new-file -ur old/hotkeys-0.5.7.4/src/hotkeys.conf hotkeys-0.5.7.4/src/hotkeys.conf --- old/hotkeys-0.5.7.4/src/hotkeys.conf 2002-11-21 13:03:35.000000000 -0500 +++ hotkeys-0.5.7.4/src/hotkeys.conf 2007-07-27 12:01:08.000000000 -0400 @@ -10,6 +10,11 @@ # Kbd=acerwl # CDROM=/dev/cdrom +### ALSA card +# ALSAcard=default +### List of ALSA control names, separated by "|" +# ALSAcontrols=Master + # PrevTrack=xmms --rew # Play=xmms --play-pause # Stop=xmms --stop
signature.asc
Description: Digital signature