Saturday, December 31, 2011

Ogg Vorbis on HP Touchpad

I was gifted one of those going-out-of-production HP Touchpad's. It's no iPad, but webos is actually pretty nice! I like many things about it, one of which is that it will play my ogg vorbis music collection.

But when I copied the music over... a bunch of albums showed up grouped together in the unknown albums bin. After some Google searching, I discovered this is a bug. While you can try and apply that patch, I found it easier to just fix my music collection. cd to your music directory and run this (I love bash):

find . -name '*.ogg' | { while read fn; do echo $fn; vorbiscomment -l "$fn" | awk -F = '{ print sprintf("%s=%s",toupper($1),$2); }' | vorbiscomment -w "$fn"; done; }

Friday, September 2, 2011

Hauppauge PVR-150 IR Blaster and Comcast DTA - it doesn't work

At least not under Linux with LIRC. After several failed attempts following Mark's instructions and using various other lircd configs I found via Google, I've concluded that my PVR-150 IR blaster just don't work with my Comcast DTA. I keep a MythTV box in the States so that I can record and download American TV and it was working great until Comcast switched to all digital. My Silicondust HD Homerun only gets the unencrypted content and so in order to get the encrypted content, I need to use a Comcast DTA (or some other STB) with an IR blaster (yes, there are several other options, but this appears to be the easiest). However, the PVR-150 IR Blaster doesn't support the XMP remote protocol that the DTA's remote uses. From forum posts I read, it sounds like the hardware could support it, but that the Linux driver/firmware can't do it now and I don't have the expertise or time to fix it. So it looks like I need to fork over some cash to buy another IR blaster like the MCE remote or the USB UIRT.

Tuesday, August 23, 2011

microphone doesn't do stereo on asus 1001p

The mic on my asus eee 1001p doesn't work correctly under Linux (apparently also on a number of models of the eee). In pulseaudio, it shows up as a stereo mic but the two channels cancel each other out so if you want it to work, you have to adjust one of the channels down to 0 (I use the pulseaudio volume control for this, pavucontrol). However, it's annoying that this doesn't just work. I've looked for solutions since I bought the device and I finally found one this week.

The correct solution is a kernel patch which appears to be on its way to kernel land. But while I'm waiting, I found a suitable workaround using the hda-verb utility. Here's the magic incantation below. Update the /dev/snd/* path to whatever is right for your system and then take the "value" output of the 2nd command and do a bit-wise or of 0x80 (in my case, 0x1800 became 0x1880) and use that as the last argument to the last command below.


# ./hda-verb /dev/snd/hwC0D0 0x20 SET_COEF_INDEX 0x07
nid = 0x20, verb = 0x500, param = 0x7
value = 0x0
# ./hda-verb /dev/snd/hwC0D0 0x20 GET_PROC_COEF 0
nid = 0x20, verb = 0xc00, param = 0x0
value = 0x1800
# ./hda-verb /dev/snd/hwC0D0 0x20 SET_COEF_INDEX 0x07
nid = 0x20, verb = 0x500, param = 0x7
value = 0x0
# ./hda-verb /dev/snd/hwC0D0 0x20 SET_PROC_COEF 0x1880

Wednesday, August 3, 2011

x86_64 versus x86 on ASUS eee

Use x86, hands down. I installed Fedora x86_64 on my ASUS eee 1001p with 1G of RAM and that was a mistake. In hindsight, it makes complete sense: 64-bit addressing makes programs take up lots more space in memory (because the pointers and stored memory addresses are twice as large) which makes systems with not much RAM not work as well. When I reverted back to an x86 Fedora, WOW! Things went much faster. There was oodles more memory available for applications.

Lesson Learned: Don't use x86_64 unless you absolutely need access to more than 4G of memory. And on my ASUS 1001p laptop, that'll never happen (system can only handle 2G I think) so it just doesn't make sense.

Friday, December 31, 2010

volume keys in lxde

gmixer is just not working for me correctly under the Fedora LXDE spins on my Asus EEE laptop. So I hacked together a solution using some suggestions I found across the 'net.

add to the "keyboard" section in ~/.config/openbox/lxde-rc.xml

<keybind key="XF86AudioLowerVolume">
<action name="Execute">
<command>/home/user/bin/vol.sh down</command>
</action>
</keybind>
<keybind key="XF86AudioRaiseVolume">
<action name="Execute">
<command>/home/user/bin/vol.sh up</command>
</action>
</keybind>
<keybind key="XF86AudioMute">
<action name="Execute">
<command>/home/user/bin/vol.sh mute</command>
</action>
</keybind>


/home/user/bin/vol.sh

#!/bin/bash

function dispvolpercentage() {
zenity --progress --text="Volume" --percentage="$1" --no-cancel --timeout=1
}

function getvolume() {
amixer get Master | grep -o -E "[0-9]+%" | head -1 | cut -d '%' -f 1
}

case "$1" in
up)
VAL="`getvolume`"
VAL=$(($VAL+5))
amixer set Master ${VAL}%
dispvolpercentage $VAL
;;
down)
VAL="`getvolume`"
VAL=$(($VAL-5))
amixer set Master ${VAL}%
dispvolpercentage $VAL
;;
mute)
amixer set Master toggle
;;
esac


References
* http://wiki.lxde.org/en/LXDE:Questions#How_do_I_make_my_keyboard_volume_buttons_work.3F
* https://bbs.archlinux.org/viewtopic.php?id=69589&p=1 - I wrote my script based on this one but just using zenity (doesn't look very nice, but works)

Saturday, December 4, 2010

openwrt crashes due to OOM killer

I have an openvpn tunnel running between two OpenWRT-powered routers. One of them is running Kamikaze 7.09 and crashes all the time when transferring lots of data at once. It was getting really annoying (for me and them) having to call the site and have it manually rebooted. I finally discovered that it appears to be dying because it runs out of memory and the OOM killer terminates all the important processes. It'd be nice if the OOM killer would just reboot the thing, but the kernel in Kamikaze 7.09 for this router doesn't support that (I think newer ones do). So I wrote the following watchdog script and installed it in root's crontab to run every 4 minutes. So far, the router hasn't crashed permanently. When memory gets low, it just reboots! Hopefully no more calls to this site...


#!/bin/sh

F="`free | grep Mem | cut -c 37-45`"
if [[ $F -lt 500 ]]; then
logger "Memory Low ($F) - rebooting..."
sleep 5
/sbin/reboot
fi

Thursday, December 2, 2010

I'm a victim of this NetworkManager bug where if it can't reach the dhcp server after some longer amount of time, it gives up. I have a server that is difficult for me to reboot that has gone down because NetworkManager just gives up if something happens to the DHCP server. So, I wrote this watchdog script and put it in my crontab to run every 5 minutes.


#!/bin/bash

if pidof dhclient > /dev/null; then
logger "dhclient is alive"
else
logger "dhclient is dead, restart NetworkManager"
/etc/init.d/NetworkManager restart
fi

Sunday, November 7, 2010

Writing a File Atomically from Python

I wanted to be able to write to a file, but there was a possibility that others could be reading from it while I was writing to it. So I came up with this code below (which I release as public domain) which should guarantee that the file gets written without anyone being able to read it until it is completely written to disk.

import os, os.path
import errno

def write(filename, data, mode=0600):
""" guarantees that noone can read filename with only partial data """
fd = None
seq = 1
dn = os.path.dirname(filename)
bn = os.path.basename(filename)
while fd == None:
try:
fn = os.path.join(dn,".%s.%d"%(bn,seq))
fd = os.open(fn, os.O_CREAT | os.O_EXCL | os.O_WRONLY, mode)
except OSError, e:
if e.errno == errno.EEXIST:
seq += 1
continue
else:
raise

# write data to temporary file
fo = os.fdopen(fd, "w")
fo.write(str(data))
fo.close
#os.close(fd)

# move file into place now that it is written
os.rename(fn, filename)

Outputting HTML5 via XML/XSLT

One of my web applications uses XSLT to transform some XML data into output. For a long time, I was convinced XHTML was the future. But now I've seen the light and HTML5 is the way to go. I want my app to be able to take advantage of all the HTML5 goodness while still retaining the content/view separation that using XML and XSLT has allowed me.

Content With Style had a good blog post highlighting this problem, but it seems that the doctype has since changed. The current HTML5 spec outlines the current accepted doctype including the doctype that XSLT-generated documents can use.

So here's the xsl:output string I needed to use:

<xsl:output method="html"
doctype-system="about:legacy-compat"
indent="yes"/>

Wednesday, September 22, 2010

Palm not syncing

My Palm wasn't connecting correctly to my Linux netbook. I was getting some weird errors in the logs:

usb 2-1: new full speed USB device using uhci_hcd and address 2
usb 2-1: device descriptor read/64, error -71
usb 2-1: device descriptor read/64, error -71
usb 2-1: new full speed USB device using uhci_hcd and address 3
usb 2-1: device descriptor read/64, error -71
usb 2-1: device descriptor read/64, error -71
usb 2-1: new full speed USB device using uhci_hcd and address 4
usb 2-1: device not accepting address 4, error -71
usb 2-1: new full speed USB device using uhci_hcd and address 5
usb 2-1: device not accepting address 5, error -71
hub 2-0:1.0: unable to enumerate USB device on port 1


After hunting and hunting (and not saving the page that gave me the answer), I discovered this is related to a bug on the Palm. The page I found suggested a reset. So I did, and it synced up right after that.

Saturday, September 11, 2010

Screen Locking Shortcut in LXDE

I liked having a keyboard shortcut, ctrl-alt-l, to lock the screen under Gnome. But in LXDE, it was a bit trickier to setup. There isn't a fancy GUI for setting these options (that I know of), one has to edit Openbox's configuration file: ~/.config/openbox/lxde-rc.xml

Find the "<keyboard>" section and add the following:

<keybind key="C-A-l">
<action name="Execute">
<command>xscreensaver-command -lock</command>
</action>
</keybind>

Tuesday, September 7, 2010

Suspend on Lid Close with LXDE

LXDE has been great on my Asus EEE 1001P. It's fast and usable. I've had some issues with it, but the most frustrating problem is that Fedora 12 with LXDE doesn't suspend by default when you close the lid. I did some googling and discovered this is known and the easy to fix it is to install the gnome-power-manager. But that kind of defeats the point of LXDE, right? I'm trying to avoid installing and using gnome heaviness to stay lean and mean and fast.

So, after lots of googling around, I finally came up with the optimum configuration which uses what I hope are lighter-weight services.

First, I had to install acpid to respond to lid close/open events (my code is based on this post):
yum install acpid


I hunted through the LXDE source code and discovered that lxde-logout uses a dbus call to HAL to trigger the suspend. I found a great blog post describing how to do this from a script. I implemented that by doing creating the following files:

/etc/acpi/events/lid (update: don't put a dot in the filename for Fedora 14+, it seems a new version of acpid ignores all files with dots in their names)

event=button/lid
action=/etc/acpi/actions/lid.sh


/etc/acpi/actions/lid.sh

#!/bin/bash

# maybe this sleep isn't needed, but just to make sure the lid close event doesn't trigger immediate wake-up
sleep 2

# make sure the lid is closed
grep -q open /proc/acpi/button/lid/LID/state && exit 0

# suspend
dbus-send --system --dest=org.freedesktop.Hal --type=method_call --print-reply /org/freedesktop/Hal/devices/computer org.freedesktop.Hal.Device.SystemPowerManagement.Suspend int32:0

Sunday, August 29, 2010

Germany Bike Maps - For Free!

I've known about the OpenStreetMap project for some time, but I've never taken advantage of it before. But as I was hunting around for a Linux mapping program (and found "qlandkarte gt"), I stumbled across OpenStreetMap-based maps that you could use off-line. And among those were detailed bike trail maps of Germany. But loading them on to my GPS proved a bit complicated because I don't have a Windows box around!

First, I found the maps here: http://openmtbmap.org/download/

Then I had to download 7zip in order to unpack the map files (which are bundled in a Windows executable). qlandkarte was immediately able to use these map files locally. And they looked very detailed and accurate! But how to get them on to my Garmin Etrex Vista C (an older handheld model)?

Unfortunately, Garmin only provides map loading software for Windows and Mac. There appears to be an open-source project to do this, but it didn't look well supported or easy. Since I have a Mac, I downloaded Basecamp (i found many recommendations to skip Garmin's RoadTrip project and use the more stable Basecamp).

Next, you have to convert the Windows maps into Mac maps (why oh why does Garmin have separate formats for different programs?). Garmin provides a converter program that runs under windows (http://www8.garmin.com/support/download_details.jsp?id=3897), but fortunately, there is an open-source project called Gmapibuilder that does the same thing.

Next, I ran the Garmin Map Manager on my Mac (came bundled with Basecamp) to load the maps into Basecamp. Then, I used Garmin's Map Installer applications (also bundled with Basecamp) to select my GPS unit and load a subset of the map on to it. I was happy to discover that I was able to pick a subset because my eTrex Vista C only has 24MB of memory and no expansion slots. So I was able to reduce the map to just the area that I wanted. And voila! I was done!

I got some good help in this process from openmtbmap.org, but since it seemed missing a couple steps, I thought I'd document it all here.

Tuesday, April 6, 2010

chown in Python

The built-in chown in Python (in the os module) only uses uid/gid instead of username/groupname. So here's a couple of (simple) versions that can take usernames and groupnames. I can't remember where I borrowed some of this code from, but it was heavily inspired by code samples I found while google searching:


def chown(path,user,group):
uid = pwd.getpwnam(user)[2]
gid = grp.getgrnam(group)[2]
os.chown(path,uid,gid)

def chown_recursive(path,user,group):
if path is None or path in ['/','/root','/usr','/tmp','/bin','/sbin']:
raise Error("path isn't right...")
uid = pwd.getpwnam(user)[2]
gid = grp.getgrnam(group)[2]
os.chown(root, uid, gid)
for root, dirs, files in os.walk(path):
for name in dirs:
os.chown(os.path.join(root,name), uid, gid)
for name in files:
os.chown(os.path.join(root,name), uid, gid)

Wednesday, March 17, 2010

Repairing Corrupt MySQL Tables

Drat... My MythTV's MySQL database got corrupt somehow. I noticed some strange problems with the guide data over the past couple weeks and today, the guide data ran out. When I ran "mythfilldatabase" on the command-line, I noticed a weird error from MySQL suggesting the tables were corrupt.

A couple of google searches later, I found a great reference guide (http://www.thegeekstuff.com/2008/09/how-to-repair-corrupted-mysql-tables-using-myisamchk/) that discusses how to use myisamchk to find corrupt tables and then repair them. Worked like a champ.


cd /var/lib/mysql/mythconverg
myisamchk *.MYI
# in my case, only one table was corrupt
myisamchk -r CORRUPTTABLE.MYI

Monday, May 18, 2009

Reducing an LVM Volume Group that's missing disks

I put in a new hard drive and used "pvmove" to move all the physical extents (all the data) from the old drives to the new one. But then, I removed the drives without running vgreduce! Oops... Fortunately, vgreduce has a "--removemissing" flag that can remove all the missing physical volumes from a volume group and restore consistency. This is exactly what I needed since I was sure that there was no data left on those other volumes.

Tuesday, September 30, 2008

Jump-Starting a new Honda Odyssey

Yes, I'm the proud owner of a fairly new Honda Odyssey. And I did the stupid thing of leaving the lights on over part of the weekend. And when my wife went out to start the car, lo and behold, the battery was dead. Now on a car with so many electric features (there is only one key hole on the outside of the car, they expect you to use the automatic door locks for the rest of the doors), having a dead battery leaves you in a world of trouble!

It took some time to find a place that sells jumper cables. Fortunately, the local Obi (like Home Depot) has an automotive section. So I go out well before the sun rises this morning to jump start the car. And as soon as I attach the jumper cables from the good battery, the honda odyssey goes into "Help! I'm being stolen!" mode with horn a blaring. I'm sure my neighbors loved that!

Well, after almost 2 hours of frustration, I finally discovered that ADAC (the equivalent of AAA in Germany) will do a courtesy jump-start for AAA card holders overseas. And they were pretty prompt! The tech (who didn't speak hardly any English, but we were able to communicate) knew exactly how to disable the panic mode: put the key in the outside of the driver's door and lock and unlock the car. I guess my putting the key in the ignition wasn't good enough for the car, it needed to be in the outside door. I'm told that using the lock/unlock on the keyless entry would have had the same effect. But I'm disappointed that my car will always panic when I try and jump-start it from a dead battery. I guess I just can't jump start it in the dead of night without disturbing the neighbors for a few moments while I get that key into the door...