Quantcast

Hardware volume key support on XFCE

XFCE4 from Debian unstable (“sid”) does not seem to bind the hardware volume-up, volume-down, and mute keyboard buttons on my ThinkPad to any actions.  It’s convenient to be able to control the sound card with these dedicated buttons – no twiddling around with the mouse to reach for a volume slider when NWA hits your playlist and the boss walks over.  I suppose this is just a rough edge with the current XFCE integration; Gnome seems to handle this pretty well out of the box, but then again, Gnome is a bloated pig compared to XFCE. So here’s one way to make the buttons work in XFCE.

First, you’ll need to make sure some prerequisite packages are installed: the package that provides the “amixer” binary, and some variant of awk. Open an XFCE terminal window by clicking on the XFCE “mouse” logo in the XFCE panel, then clicking “Terminal”. Become root by running the following and entering your root password:


su -

Then install the appropriate packages — here’s how to do it in Debian:


apt-get install alsa-utils mawk

Once the packages are installed, drop root privileges:


exit

Then let’s pick a place for our scripts to live. This example will assume that they will go into a ‘bin’ directory underneath your home directory; so, let’s make sure that exists:


mkdir ~/bin

Now, on to the scripts. Copy and paste the following script as “~/bin/alsa-toggle-mute”. Probably the easiest way to do this with a stock Debian system is to start the ‘nano’ editor with:


nano ~/bin/alsa-toggle-mute

highlighting the script below, and then using your middle mouse button to paste the script into the nano terminal window, then using “Ctrl-x y ENTER” to save the file:


#!/bin/sh
#
# alsa-toggle-mute
#
##########################################################
#
# AMIXER: path to your 'amixer' binary
AMIXER=/usr/bin/amixer
#
# CONTROL: sound card control to adjust: run 'amixer' to find this
CONTROL="Master,0"
#
# LEVELKEY: pattern on 'amixer' output lines to search for that provides
# the current control level
LEVELKEY=Mono:
#
##########################################################
#
$AMIXER sset $CONTROL \
`$AMIXER sget $CONTROL |
awk "(/$LEVELKEY/) { if (\\$NF == \\"[on]\\") { print \\"mute\\" } else { print \\"unmute\\" } }"` > /dev/null

Make the script executable:


chmod 700 ~/bin/alsa-toggle-mute

Then attach it to the hardware mute button with the XFCE keyboard settings manager GUI. Click on the XFCE “mouse” logo that should be on the edge of your XFCE panel; click “Settings” from the pop-up menu; then click “Keyboard”. Click on the “Application Shortcuts” tab. Then click “Add”. XFCE will ask for a path to the command; enter the full path to your alsa-toggle-mute script, e.g., “/home/username/bin/alsa-toggle-mute” — of course, you will have to substitute your username in that command. XFCE will then pop up a box waiting for the “Command Shortcut” — at this point, press your hardware mute button.

That should be it! Your mute button should now work.

Now let’s add support for the volume-up button. Save this script to “~/bin/alsa-volume-up”:


#!/bin/sh
#
# alsa-volume-up
#
##########################################################
#
# OFFSET: amount to increment/decrement the control level: e.g., -1
# decrements the volume, 1 increments the volume; values with
# a greater absolute magnitude will decrement or increment the
# control level more quickly. Use "$1" if you wish to pass
# the offset in from command line parameters
OFFSET=1
#
# AMIXER: path to your 'amixer' binary
AMIXER=/usr/bin/amixer
#
# CONTROL: sound control to adjust: run 'amixer' to find this
CONTROL="Master,0"
#
# LEVELKEY: pattern on 'amixer' output lines to search for that provides
# the current control level
LEVELKEY=Mono:
#
# LEVELFIELD: awk field number of the current control level
LEVELFIELD=3
#
##########################################################
#
$AMIXER sset $CONTROL \
`$AMIXER sget $CONTROL | \
awk "(/$LEVELKEY/) { print \\$$LEVELFIELD + $OFFSET }"` > /dev/null

Make it executable:


chmod 700 ~/bin/alsa-volume-up

Attach it to the hardware volume up button by following the same instructions as for the mute script (above), but in place of “/home/username/bin/alsa-toggle-mute”, use “/home/username/bin/alsa-volume-up”. And rather than pressing the hardware mute button, press the hardware volume up button.

Then let’s handle the hardware volume down button. This time we will take a shortcut. Rather than copying and pasting another script, we’ll just copy and edit the volume-up script that you’ve already saved:


cp ~/bin/alsa-volume-up ~/bin/alsa-volume-down

Then edit the ~/bin/alsa-volume-down script in nano to change the line that reads “OFFSET=1″ to “OFFSET=-1″:


nano ~/bin/alsa-volume-down

.. edit the script, then use “CTRL-x y ENTER” to save.

Then, as before, attach the script to the hardware volume down button by following the same instructions as for the mute script (above), but in place of “/home/username/bin/alsa-toggle-mute”, use “/home/username/bin/alsa-volume-down”. And rather than pressing the hardware mute button, press the hardware volume down button.

Star Wars re-remastered to high quality 1977 version!

So I wanted to sit down in my updated home theatre and watch one of my favorite films, “Star Wars”. Problem is, I have two versions on DVD, and neither are ideal. The 2004 DVD version has remastered audio and video, but also added scenes and changes I really don’t like. The 1977 DVD version is a poor quality transfer and encoding.

So I combined the 1977 and 2004 DVDs into the highest quality 1977 version of the film! I show all my scripts and techniques here, too, so you can make the same version from your two DVDs, too!
http://www.archive.org/details/reremaster

star wars comparison of two films

star wars comparison of two films

Twinkle SIP phone, Fedora 11, PulseAudio

Linux distributions have recently been shipping PulseAudio, a daemon meant to handle mixing, resampling, and control of audio streams. Maybe they will get it working right someday, but as of now, it is frustratingly not ready for mainstream usage. Many applications do not work with it, or work poorly with it, requiring stupid hacks and workarounds.

One such application is Twinkle, a SIP phone for Linux.  Previously on Fedora 9, Twinkle worked okay.  It connected to ALSA directly, so I just needed to set up ALSA to handle software mixing.

However,  in Fedora 11, PulseAudio has been designated as the One True Intermediary between ALSA and the rest of userspace.  In the case of Twinkle, this resulted in no audio emissions from the computer.   Calls could be placed, and would appear to proceed normally, but nothing emerged from the speaker.   Running ‘pavucontrol’ during a call showed that PulseAudio’s ALSA emulation plugin had been started, but the VU meter associated with the Twinkle application was completely dead.

After struggling with a bunch of useless workarounds (padsp, pasuspender, asound.conf, killall pulseaudio DIE DIE DIE, etc); several other softphones, none of which worked, for completely distinct reasons;  and exploring half-heartedly what it would take to hack PulseAudio support into Twinkle, suddenly I accidentally got it “working.”

If, during the first call placed after Twinkle is launched, you send a DTMF digit (e.g., pressing one of the number keys), audio will unwedge for that call, and all subsequent calls.

I hope this saves someone some time and frustration.  It’s embarrassing how much time it took to figure this out!

Fixing MTRRs on Linux

Some x86 computers have a buggy BIOS that can cause poor Linux graphics performance.  The problem is caused by the BIOS’s boot-time configuration of the Memory Type Range Registers (MTRR).  On modern systems, the graphics aperture should be configured as write-combining memory.  But buggy BIOSes will configure it as plain “uncacheable” memory.  The performance cost of the bug can be large: as an example, a ThinkPad T61 with Intel x3100 GMA  and T9300 CPU initially rendered ~120 fps in glxgears; this increased to ~580 fps with a fixed configuration.

You can determine whether your system has the bug by examining your X server log (likely in /var/log/Xorg.0.log) and looking for a line similar to:

(WW) intel(0): Failed to set up write-combining range (0xe0000000,0x10000000)

The Fix

The good news is that the MTRR can be fixed from the Linux command line via ‘cat’ and ‘echo’ and the /proc/mtrr file.  The bad news is that figuring out the right configuration is difficult and often involves some trial and error.  The process often involves converting cached memory to uncached memory, so it is best done in single-user mode, without X running.  The machine should be doing nothing else, otherwise the system is likely to slow to the the point of unusability.

Try the Easier Fix First

Someone may have already fixed the problem for your machine.  If they’ve posted it to the Internet, try their script first.  One sample is below, along with a  few links for other machines.  These may not work, since BIOS MTRR configurations can vary depending on the amount of memory in the system,  devices present, and BIOS revision.

Then Try Figuring It Out

Needed are Linux expertise, an understanding of hexadecimal arithmetic, and an understanding of the basics of how computers map memory. General steps:

  1. Use the error message from the Xorg log file (probably /var/log/Xorg.0.log) to determine the start address and size of the graphics aperture.  Example:
    (WW) intel(0): Failed to set up write-combining range (0xe0000000,0x10000000)
  2. Reorganize the MTRR settings (via /proc/mtrr) to mark the video chip’s memory as write-combining.  This generally involves:
    1. removing any MTRRs that overlap with the graphics region,
    2. adding a MTRR for the write-combining area, and
    3. breaking the removed MTRR into MTRRs that do not overlap the graphics aperture area.
  3. Create a script to replicate the MTRR settings (sample below) and run it during boot, e.g., from /etc/rc.local.

The details are beyond the scope of this post, but here are some resources that may help.

MTRR Fix For A Sample Configuration

Here are the details of an MTRR fix for a Lenovo ThinkPad T61 (8897CTO) laptop with 4GB RAM and a 64-bit kernel.  Here’s the default BIOS MTRR configuration (cat /proc/mtrr):

reg00: base=0xc0000000 (3076MB), size=1024MB: uncachable, count=1
reg01: base=0x13c000000 (5056MB), size=  64MB: uncachable, count=1
reg02: base=0x00000000 (   0MB), size=4096MB: write-back, count=1
reg03: base=0x100000000 (4096MB), size=1024MB: write-back, count=1
reg04: base=0xbf700000 (3063MB), size=   1MB: uncachable, count=1
reg05: base=0xbf800000 (3064MB), size=   8MB: uncachable, count=1

The problem is that the graphics card memory (which according to the Xorg log is at 0xe0000000) lies within the reg00 uncacheable region, but should be marked as “write-combining.”  After running this script:

#!/bin/sh
echo "disable=5" > /proc/mtrr
echo "disable=4" > /proc/mtrr
echo "disable=3" > /proc/mtrr
echo "disable=2" > /proc/mtrr
echo "base=0x0 size=0x80000000 type=write-back" > /proc/mtrr
echo "base=0x80000000 size=0x40000000 type=write-back" > /proc/mtrr
echo "base=0xe0000000 size=0x10000000 type=write-combining" > /proc/mtrr
echo "base=0x100000000 size=0x40000000 type=write-back" > /proc/mtrr
echo "base=0xbf700000 size=0x100000 type=uncachable" > /proc/mtrr
echo "base=0xbf800000 size=0x800000 type=uncachable" > /proc/mtrr
echo "disable=0" > /proc/mtrr
echo "base=0xc0000000 size=0x20000000 type=uncachable" > /proc/mtrr

… the MTRR configuration changes to:

reg00: base=0xc0000000 (3072MB), size= 512MB: uncachable, count=1
reg01: base=0x13c000000 (5056MB), size=  64MB: uncachable, count=1
reg02: base=0x00000000 (   0MB), size=2048MB: write-back, count=1
reg03: base=0x80000000 (2048MB), size=1024MB: write-back, count=1
reg04: base=0xe0000000 (3584MB), size= 256MB: write-combining, count=2
reg05: base=0x100000000 (4096MB), size=1024MB: write-back, count=1
reg06: base=0xbf700000 (3063MB), size=   1MB: uncachable, count=1
reg07: base=0xbf800000 (3064MB), size=   8MB: uncachable, count=1

and glxgears frame rates are much higher.

More Information

Here are some samples that others have provided for other configurations:

A technical discussion of write-combining: http://download.intel.com/design/PentiumII/applnots/24442201.pdf

Linux /proc/mtrr documentation: http://www.mjmwired.net/kernel/Documentation/mtrr.txt