Code is hard to remember.

This is where I put interesting bits of source so I can find them again. Maybe they will be useful to you. Don’t expect consistency, documentation, bike messengers, or aspiring actors.

Bind Pithos’s play/pause to a key or script

dbus-send --print-reply --dest=net.kevinmehall.Pithos /net/kevinmehall/Pithos net.kevinmehall.Pithos.PlayPause


Reduce PDF size using ghostscript

Courtesy of Jenny:

Note: don’t use if you have transparency in your figures.

gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/printer -dNOPAUSE -dQUIET -dBATCH -sOutputFile=output.pdf input.pdf


Compress AviSynth / VirtualDub Output

Sometimes I output from VirtualDub in an uncompressed format.

Works with pdfpc:

F="file.avi"; avconv -i $F -acodec pcm_s16le -ac 2 -b 100000k -ab 100000 ${F/.avi/}-c.avi

Better audio compression:

F="file.avi"; avconv -i $F -acodec libmp3lame -ac 2 -b 100000k -ab 100000 ${F/.avi/}-c.avi

If Unknown encoder ‘libmp3lame’:

sudo apt-get install libavcodec-extra-53


Using the ArudPilot (APM 2.5) as a Sensor and I/O Board wth another onboard PC communicating over USB

I recently wrote a firmware package for the ardupilot / APM 2.5 for use as a sensor and I/O board. This strips out most of its logic and pumps sensor data up the USB as fast as I could make it go while simultaneously reading USB commands for publishing to servo motors.

It also will mux between input servo commands and the USB commands based on an input channel’s value.

Post here:

Code here (in the ArduRead folder):


How to Fix a Sticky Kinesis Advantage Keyboard

I opened a soda near my keyboard and it blew up all over the right side. Now you might be thinking “no big deal,” but I have had some RSI issues so I use a $300 Kinesis Advantage, which, if you have RSI problems, is simply amazing. It, along with Workrave, has almost completely solved my problems.

So, my keys were sticking. Bad day. I popped the keys off with their included tool, and wiped them down, but that only cleared up the issues for about 10 minutes. You can send yours in for a few weeks and like $50-80 and they’ll fix it, but I decided to give it a shot.

Step 1) Take it apart. Relatively simple. A few screws on the back and you’re set.


Step 2) Take out the side that you’re having issues with. A few more screws and one ribbon cable and it will come off

Kinesis right side top

Kinesis right side

Step 3) Get a syringe, fill it with water, and very carefully press the Cherry switch down and put a few drops of water inside. As soon as the water is in, flip the board over and shake while holding the switch down. Then use compressed air to blow out the water, all the while holding a napkin under the switch to absorb anything that comes out.

Repair kinesis

Step 4) Dry it with a heater or leave it for a while. I dried mine, put it back together, and almost all the keys worked. I turned out I hadn’t pushed the ribbon cable all the way in, so make sure you do that. Typing on it now as good as new!

Update: I’ve had to repeat this process a number of times now as keys that weren’t stuck have become stuck. I recommend cleaning most of the keys in the affected area all at once so you don’t have to keep opening up the keyboard.

Update 2: I’ve had to repeat this process about five times on the keys to get them unstuck (drying, then washing, then drying, etc.) Each time everything seems to be a little bit better. I’m crossing my fingers that I’m in the clear now.

Update 3: Seems to be working well now.

Update 4: Continued to have problems after a while. Next I took the right circuit board out (as pictured above) and put it in a warm bowl of water for a few minutes. I worked each key (with the keycaps off) and then dried it out. So far this has been the best solution yet, and the keyboard has survived its trip.

Update 5: After Update 4, the keyboard has been working without any issues for over a year.


Slow WiFi on Ubuntu with a Thinkpad

A post I’m trying out now:


Convert GoPro Hero 2/3/4 MP4 to AVI for AviSynth

avconv -i GOPR0047.MP4 -acodec mp2 -b 100000k -ab 224000 GOPR0047.avi

if not found:

sudo apt-get install libavcodec-extra-53

in parallel:

find ./ -maxdepth 1 -name "*.MP4" -type f |  xargs -I@@ -P 8 -n 1 bash -c "filename=@@; avconv -i \$filename -acodec mp2 -b 100000k -ab 224000 \${filename/.MP4/}.avi"

For 120 fps video:

avconv -i GOPR0058.MP4 -acodec mp2 -vcodec ffv1 -b 100000k -ab 224000 GOPR0058.avi

in parallel:

find ./ -maxdepth 1 -name "*.MP4" -type f |  xargs -I@@ -P 8 -n 1 bash -c "filename=@@; avconv -i \$filename -acodec mp2 -vcodec ffv1 -b 100000k -ab 224000 \${filename/.MP4/}.avi"

The old way (causes audio issues on 1080p / 60fps video):

avconv -i GOPR0051.MP4 -acodec libmp3lame -ac 2 -ar 44800 -b 100000k -ab 100000 GOPR0051.avi


Installing AviSynth and VirtualDub in Linux under wine

Follow the instructions here: [local mirror]

Don’t forget this step: put avs2yuv.exe in the folder: ~/.wine/drive_c/windows/system32/

Then install vcrun6sp6 using winetricks.

After you’re done, you might consider installing support for MP4 / GoPro files.


Gumstix notes

Update: Use this URL if your wget won’t resolve https connections:

The environment that has worked very well for me is to compile on-board (not cross-compiling) for anything small (see tip #2 below for how to get a compiler easily). That usually just works, is fast enough, and simplifies things a lot. When I need to compile something big, I’ve used distcc to get my desktop to help (over wifi). Below is an email from another guy in our lab who wrote down how to get that to work.

There’s a few other big tricks I’ve used.

1) If you’re using wifi, I wrote an article about getting that to work here:

2) Add more repositories to the package manager. The default one barely has anything in it, but the main angstrom repo has a lot of stuff (much more like using apt-get) Again, this will only work with a network connection, but I think you can get a board that will give you that.

Page about it:

Here’s the relevant part:

By default, opkg uses the Gumstix repositories defined in the configurations files found under /etc/opkg/. This repository, however, does not contain all the packages you can build using OpenEmbedded. For example, we can add the armv7a base·Angstrom Distribution repository to our list of repositories.

$ opkg list | wc -l
$ echo 'src/gz angstrom-base
base' > /etc/opkg/angstrom-base.conf
$ opkg update
$ opkg list | wc -l


I highly recommend doing that. It made my life much simpler by allowing me to just install things like a compiler, etc.

distcc email

distcc worked like a charm once I finally figured out where the cross compiler was, and that the compilers needed to have the same name on the two systems. State estimator built, and runs as far as complaining about not getting a bot-param :-)

to get to the cross compiler setup environment according to:

the cross compiler would then be in:


To get distcc to work, I followed the distcc part of these instructions:

The only other critical step was to create a symbolic link from the cross-compiler location to


Then to have Make to use distcc on the gumstix you need to do is set three environment variables:

export CC="distcc arm-angstrom-linux-gnueabi-gcc"
export CXX="distcc arm-angstrom-linux-gnueabi-g++"
export DISTCC_HOSTS="ip-of-desktop"


whaw — Tiling Windowing on Linux

Whaw comes from John Meacham. It’s awesome (pardon the pun) for use with tiling windows. I added a few extra command line options so you can move the “hot pixel” around on the screen.

I highly recommend that you spend 30 seconds and read the description of how to use it.

Link to my version: whaw-0.1.2.andy.tar.gz

To install you might need:

sudo apt-get install libxmu-dev


Using encfs


encfs ~/crypt ~/visible


encfs ~/crypt ~/visible


fusermount -u ~/visible


Ban email first thing in the morning

I noticed that when I check my email first thing in the morning, I spend the day putting out small fires instead of doing good work. I wrote a quick script that bans my email after about 7 hours of idle activity and then restores it sometime between the first 45-75 minutes of activity.

  1. Install xprintidle: sudo apt-get install xprintidle
  2. Paste this script somewhere on your system and make it executable.
  3. Add it to root’s crontab (sudo crontab -e):
    53 * * * * /home/abarry/scripts/banEmailCronjob

# this should be run as a cron job (as root)
# sudo crontab -e
#   53 * * * * /home/abarry/scripts/banEmailCronjob
# the idea is that within an hour of the user returning, the job
# will run and email will be restored, but just as you sit down,
# email will be banned.
# DEPENDS on xprintidle which is in apt.

set -x # tells bash to print everything it's about to run




# first get the idle time

IDLE=`DISPLAY=:0.0 xprintidle`
echo "Idle amount: " $IDLE
echo "Sleeping for a while..."

sleep 1727 # sleep for a while so email will never be active right as you sit down

# get the IPs of gmail
ADDRESSES=`dig +short A`
FIRSTIP=`dig +short A | head -n 1`

# dig seems unreliable
IPV6ADRESSES=`dig +short AAAA`
IPV6ADRESSES="$IPV6ADRESSES 2607:f8b0:4009:802::1015 2607:f8b0:4009:802::1016"


if [ $IDLE -gt "25200000" ]
    echo "Idle is greater than threshold, banning email..."
    # ban email here

    # check to see if it is already banned
    HOSTS=`iptables -L -v -n | grep "$FIRSTIP"`
    echo "$HOSTS"
    if [ -z "$HOSTS" ]
        # not already banned, so ban it

        # ban gmail's IPs
        # find these IPs using $ dig
        echo "banning via iptables"

        # loop through the IPs and ban them
        for thisip in ${ADDRESSES}; do
            iptables -A INPUT -s $thisip -j DROP

        # loop through IPv6 aadresses
        echo "banning via ip6tables"
        for thisip in ${IPV6ADRESSES}; do
            ip6tables -A INPUT -s $thisip -j DROP

        echo "banned!"

    echo "Idle is less than threshold, so removing ban on email..."
    # remove ban here

    echo "removing iptables ban"
    # unban IPs
    #for thisip in ${ADDRESSES}; do
    #    iptables -D INPUT -s $thisip -j DROP
    iptables -F

    echo "removing IPv6 ban"
    #for thisip in ${IPV6ADRESSES}; do
    #    echo "ip6tables -D INPUT -s $thisip -j DROP"
    #    ip6tables -D INPUT -s $thisip -j DROP
    ip6tables -F



VirtualDub audio compression

Best done with ffmpeg instead of virtual dub / avisynth:

ffmpeg -i knife-edge-narration.avi -sameq -acodec libmp3lame -ac 1 knife-edge-narration2.avi


The Complete Guide to Embedded Videos in Beamer under Linux

Edit: A better solution is to use pdfpc. See my new guide.

It is now possible to embed videos in Beamer presentations under Linux. It’s stable and works well.

The strategy is to use acroread and a flash player to play .flv files. Credit to this post for a lot of this work. Here’s how to do it:

The short version:
1. Get acroread version 9.4.1 [local mirror]
2. Download the example.
3. Convert your video to flv (mess with the resolution to get smooth playback).

ffmpeg -i movie.avi -sameq -s 960x540 movie.flv


Now the explanation:

I. Get the right version of acroread.

1. Uninstall acroread using apt-get (which isn’t likely to be the right version)

sudo apt-get remove acroread

2. Download version 9.4.1 of acroread from Adobe (note that the i486 version will still work on 64-bit systems) [FTP page] [local mirror]
3. Mark the package executable:

cd your-download-directory
chmod +xx AdbeRdr9.4.1-1_i486linux_enu.bin

4. Install acroread:


I installed to /opt/acroread, so I run it like so:


II. Get Beamer files and flash player

Read the rest of this entry »


flash encoding using ffmpeg

ffmpeg -i movie.avi -sameq movie.flv

If you have issues with the sound and just want to remove it:

ffmpeg -i movie.avi -an -sameq movie.flv


S107G Helicopter Control via Arduino

I have worked with two types of S107G helicopters. One is a 2-channel (A and B) and the other is a 3-channel (A, B, and C) version. Their protocols differ significantly. The more common 2-channel (32-bit) version’s protocol is well documented elsewhere, so here I will only document the 3-channel (30-bit) version.

(First posted at rcgroups.)

S107G at FIAP Workshop


The protocol for this is 30 bits long.

  • To send a bit you flash the IR lights 16 times for a 0 and 32 times for a 1.
  • Each flash is off for 8-9 microseconds and on for 8-9 microseconds.
  • Between bits you wait for 300 microsecond
  • Between 30-bit packets you delay an amount depending on the channel you are using.
  • Channel A: 136500 us
  • Channel B: 105200 us
  • Channel C: 168700 us

The order of the bits is as follows:


C – channel
P – pitch
T – throttle
Y – yaw
X – checksum
R – trim

There are a few other things to note:

1) It has a checksum. The 21-24th bits are a bitwise XOR of 4-bit words with the two zeros appended to the end of the bitstring. Thus you can compute the checksum for the first packet:

1000 0000 1000 1100 0000 1111 1111 11
1000 ^ 0000 ^ 1000 ^ 1100 ^ 0000 ^ 1111 ^ 1100 = 1111

and for the second packet:

1000 0000 0011 1001 0000 0001 1111 11
1000 ^ 0000 ^ 0011 ^ 1001 ^ 0000 ^ 1111 ^ 1100 = 0001

Read the rest of this entry »


Run script on resume from suspend

Put your script into


with a number at the beginning and mark it executable. Here’s an example that sets my Thinkpad mouse sensitivity and enables two-fingered scrolling on my touchpad.

$ cat /etc/pm/sleep.d/99-trackpoint-and-twofinger
case "$1" in
	echo -n 220 > /sys/devices/platform/i8042/serio1/serio2/sensitivity 2> /dev/null
	echo -n 95 > /sys/devices/platform/i8042/serio1/serio2/speed 2> /dev/null
	xinput set-int-prop 'SynPS/2 Synaptics TouchPad' "Synaptics Two-Finger Pressure" 32 4
xinput set-int-prop 'SynPS/2 Synaptics TouchPad' "Synaptics Two-Finger Width" 32 7
xinput set-int-prop 'SynPS/2 Synaptics TouchPad' "Synaptics Two-Finger Scrolling" 8 1 1
xinput set-int-prop 'SynPS/2 Synaptics TouchPad' "Synaptics Jumpy Cursor Threshold" 32 250
exit $?

Note that if you want to have the script run at boot as well you probably want to add your code to



VirtualDub settings and conversion for .MTS video

Video: MTS off a Canon Vixia HG21.
Setup: Linux, working in wine.

Conversion to avi for VirtualDub/AviSynth:

avconv -i 00394.MTS -vcodec libxvid -b 100000k -deinterlace -acodec mp2 -ab 224000 output.avi

Or in parallel:

find ./ -maxdepth 1 -name "*.MTS" -type f | xargs -I@@ -P 8 -n 1 bash -c "filename=@@; avconv -i \$filename -vcodec libxvid -b 100000k -deinterlace -acodec mp2 -ab 224000 \${filename/.MTS/}.avi"

Jenny says, “I had to add the -ac 2 flag for audio”

For .mp4 video:

avconv -i 00394.MTS -vcodec libxvid -b 100000k -deinterlace -acodec mp2 -ab 224000 output.mp4

Or in parallel:

find ./ -maxdepth 1 -name "*.MTS" -type f | xargs -I@@ -P 8 -n 1 bash -c "filename=@@; avconv -i \$filename -vcodec libxvid -b 100000k -deinterlace -acodec mp2 -ab 224000 \${filename/.MTS/}.mp4"

Set up VirtualDub:

  • Options > Preferences > AVI > Check Directly decode uncompressed YCbCr (YUV) sources
  • Select Video > Compression…
    • Select ffdshow Video Codec
    • Select Configure and then set the bitrate to 10000
  • Select Video > Fast recompress


Speed up MATLAB figures with OpenGL

You can substantially increase your MATLAB figure performance by using OpenGL rendering. Put this in your startup.m file:

set(0, 'DefaultFigureRenderer', 'OpenGL');

You can check if MATLAB has detected your hardware by using:

>> opengl info

Other relevant figure properties are:

>> set(gcf,'Renderer','OpenGL')
>> set(gcf,'RendererMode','manual')

Warning: this breaks saving EPS files as vectorized figures.


Gumstix wifi (wlan1: link not ready)

I just spent a long time trying to diagnose an issue with a Gumstix Overo Fire and brining up WiFi (802.11b/g) on boot. I did all the standard things (when using a desktop image, you must uninstall NetworkManager and then set up your configuration in /etc/network/interfaces. I could get a connection sometimes, but it was very unclear why it would or would not connect. So unclear that I couldn’t write a script that would bring the WiFi up on boot.

I kept getting this issue:

ADDRCONF(NETDEV_UP): wlan1: link is not ready

occasionally followed by the better:

ADDRCONF(NETDEV_CHANGE): wlan1: link becomes ready

Also, something odd was going on that I don’t understand because when the interface would configure on boot, it would rename to wlan1:

[... boot messages ...]
libertas_sdio: Libertas SDIO driver
libertas_sdio: Copyright Pierre Ossman
Remounting root file system...
libertas: 00:19:88:21:59:1c, fw 9.70.7p0, cap 0x00000303
libertas_sdio mmc1:0001:1: wlan0: Features changed: 0x00004800 -> 0x00004000
libertas: wlan0: Marvell WLAN 802.11 adapter
udev: renamed network interface wlan0 to wlan1
Caching udev devnodes

Finally, I found a solution: use an image from 2010. I’m using the omap3-console-image-overo-201009091145 build found here and mirrored locally here.