29 February 2008

I multitouched your mom

I'm going to find Apple, and I'm going to shoot them in the face. No, seriously. Not because I hate their OS, I've grown to accept that. This is because of what they've done to multitouch. Multitouch is just about the greatest thing ever, and sadly before Apple got involved nobody had heard of it. If you don't know what multitouch is, I'll use the now-canonical example of the iPhone, although ironically the iPhone uses almost none of multitouch's capabilities. If you're in the map view of the iPhone, and you put two fingers on the display and "pinch" them together, the map will zoom in. Oooo. Basically, multitouch is the ability for a touchscreen to recognize multiple fingers and react to their movements.

I first discovered multitouch years and years ago, probably close to a decade now. It was a small company called Fingerworks, and they manufactured the iGesture Pad:


It's a big multitouch pad that accepts any combination of 5 fingers, either spread apart or together. You can move in different directions, rotate your hand in different ways, spread or collapse your fingers, basically tons and tons of different gestures, and each one can do a different thing. Look at that sexy, sexy device. You want one, don't you? Well, you can't have one. Because Fingerworks is out of business. I live in fear of the day my iGesture Pad breaks, because I'll have considerable trouble replacing it. If you clicked that link I had to them earlier, you know that "FingerWorks has ceased operations as a business". Why? That's what we (I believe the accepted term is "fingerfans") all asked. Just one day, probably 5 years ago now, they were gone. Finally, rumors started circulating that Apple had bought them out.

At first, I thought this might be good news. As I mentioned earlier, nobody had really heard of multitouch except its small group of fans, although demonstrations by people like Jeff Han led to it being rediscovered all over again by a much larger audience who think the technology was invented two years ago. Nonetheless, Fingerworks was struggling as a business, and I figured with Apple marketing their products and improving them, multitouch was going to explode. Oh, silly me. For ages, nothing happened. And we fingerfans were confused. Then the iPhone came out, and its Fingerworks roots were obvious. Sure, now it's a display instead of a simple pad, but it's the same technology, only way suckier. Worse, Apple keeps filing for patents for stuff like, for example, the pinch gesture for zooming. Instead of innovating, they've spent years doing nothing but making sure nobody else can innovate either.

What probably annoys me most is most people don't even realize Apple is doing this. People think Apple invented the technology, or damn close. Quotes like "the iPhone is arguably the first mainstream gadget to successfully implement a set of concrete touch gestures and link them to specific functions" from that Wired article drive me crazy. Apple didn't come up with this at all; they basically stole it from Fingerworks, crushed the company, and then did nothing with the technology but let it sit there. If they don't want to do anything with it, that's fine, but they're blocking everyone else from doing anything either. Multitouch should be huge by now, but instead it's remained stuck for the last 5 years, and Apple is at least partly to blame. The Fingerworks people (who work -- "work" -- at Apple now) probably hate themselves.

As an aside, I tried to look up the wikipedia article on Fingerworks, which used to exist. Now it just links to the article on Apple. Not cool.

28 February 2008

Rails and Macs

"when you're using Rails and OS X, you're using the platform of choice for douchebags."
-- http://www.codinghorror.com/blog/archives/001065.html

Oh, how very true :)

Renice goes to my head

I find myself using renice more and more. If you don't know, it lets you change the scheduling priority of a process that's currently running, anywhere from -20 (highest) to 20 (lowest). Processes all start at 0. So if firefox is starting to take the entire processor (as it has been known to do), i renice it to 10 or so. And then I laugh as my computer speeds up and firefox cries. I've tried taking the opposite approach and changing it to -10 to see if it stops lagging. But it doesn't, it just makes the rest of my computer lag too. So no more chances, firefox. Maybe if a process pleased me I might bump it up, but I doubt it, I'm too busy punishing firefox. Renice is far too much power, I don't think I can handle it.

27 February 2008

Printing PDFs

When I posted my screenshot script I thought of a similar script, which also implements functionality I didn't like. The standard CUPS PDF printer prints to a fixed directory (~/PDF in my case) instead of prompting where you'd like to save it. This annoyed me, so I looked around and discovered the PDF driver's configuration file (/etc/cups/cups-pdf.conf if you use Ubuntu like me) has a directive named PostProcessing. If you set PostProcessing to a script's path, it will run the script after printing the PDF, passing it the printed PDF's filename and the name of the user that printed it. I have mine point to a script I wrote that offers similar functionality as the screenshot script, showing a gnome alert with options to open the PDF or move it somewhere else. Again, I don't write my scripts to be used on other machines, so certain things (like the Adobe Reader icon on line 10) probably won't work for you:

#!/bin/bash
pdf=$1
username=$2
action=${3:-"default"}

export DISPLAY=:0.0

case $action in
default)
notify-more -u low -t 10000 -i /opt/Adobe/Reader8/Resource/Icons/32x32/adobe.pdf.png -n "Open" -x "gnome-open \"$pdf\"" -n "Move" -x "$0 \"$pdf\" \"$username\" move" "PDF Printed" "PDF printed to $pdf" -n "Clipboard" -x "echo -n $pdf | xsel -i -b";;

move)
dest=`zenity --file-selection --title "Save PDF" --save --confirm-overwrite`

if [ "$dest" ]; then
mv "$pdf" "$dest"
if [ -e "$dest" ]; then
notify-more -u low -t 5000 -i /usr/share/icons/gnome/32x32/actions/gtk-paste.png "PDF Saved" "PDF saved to $dest" -n "Open" -x "gnome-open \"$dest\"" -n "Clipboard" -x "echo -n $dest | xsel -i -b"
else
notify-more -u high -t 5000 -i /usr/share/icons/gnome/32x32/emblems/stock_mail-priority-high.png "Save Failed" "Unable to move PDF. The original is stored at $pdf"
fi
fi;;
esac

Screenshots

I've just discovered the most fun command ever:

vncviewer 127.0.0.1


I let my computer recursively explode for a minute before I closed it. I tried to get a screenshot, but I couldn't get my computer to do much until I closed vnc. Speaking of screenshots, however, I figured I'd post my screenshot script. I tried a bunch of different screenshot programs and pretty much hated all of them, so I ended up writing a script that uses ImageMagick's import tool. It depends on two other programs that I use fairly often and really like.

  • Zenity is like a really good version of the standard dialog command. It can show all the same types of dialogs, like calendars and progress bars and whatnot, but they're the standard GTK dialogs so they look good. Most of the time the only dialog type I use is file-selection, which is what the screenshot script uses; I tend to use libnotify to display other types of alerts instead of zenity's info dialogs

  • Notify-more is a python script that uses PyNotify, the python interface to gnome's standard libnotify. Libnotify comes with a command-line tool to access it (notify-send), and notify-more intentionally mirrors it's syntax so you can use them fairly interchangably, but notify-more provides several other features, like the pie display to show when the notification will timeout and buttons that launch commands.


Here's the screenshot script itself. I don't generally write my scripts to be used elsewhere, so it might not be particularly cross-platform. I have PrntScrn bound to launch screenshot root, and Alt+PrntScrn to screenshot window:

#!/bin/bash
action=${1:-"default"}

case $action in
root|window)
echo -n Touching temporary file...
filename=`mktemp /tmp/screenshotXXXX`;
echo done

if [ $action == root ]; then
echo -n Capturing root X window...
import -frame -window root png:$filename
echo done
printText="Captured root window into $filename"
else
echo -n Determining window ID...
windowID=`xdpyinfo | awk '/focus/ {print $3}' | sed s/,//`
echo $windowID

echo -n Capturing window...
import -frame -window $windowID png:$filename
echo done
printText="Captured window $windowID into $filename"
fi

notify-more -u low -t 5000 -i /usr/share/icons/gnome/32x32/devices/video-display.png "Screenshot" "$printText" -n "Open" -x "eog \"$filename\"" -n "Save" -x "$0 save \"$filename\"" -n "GIMP" -x "gimp \"$filename\"";;

save)
filename=$2

if [ "$filename" ]; then
echo -n Getting destination...
newfile=`zenity --file-selection --title "Save Screenshot" --save --confirm-overwrite`
echo done

if [ "$newfile" ]; then
echo -n Moving screenshot to $newfile...
mv "$filename" "$newfile"
echo done

notify-more -u low -t 5000 -i /usr/share/icons/gnome/32x32/devices/video-display.png "Screenshot" "Screenshot saved to $newfile" -n "Open" -x "eog \"$newfile\"" -n "GIMP" -x "gimp \"$newfile\""
fi
fi;;
esac

Daemons wear the pants in our relationship

When I try to use AFS over the internet, I occasionally lose the connection. No problem, I think, I'll just reload it:

% /etc/init.d/openafs-client reload
Stopping AFS services:afsd: Shutting down all afs processes and afs state
afsd: AFS still mounted; Not shutting down


Well, damn. Pretty sure nothing is using it, but hope is not lost, there's a force-reload command too. As in, to force it to reload.

% /etc/init.d/openafs-client force-reload
Stopping AFS services:afsd: Shutting down all afs processes and afs state
afsd: AFS still mounted; Not shutting down


AFS just told me to go to hell, and there's pretty much nothing I can do about it. I never need to unmount it if I try to stop the daemon while still connected, but I'll listen to the error message and try unmounting it's folder instead:

% umount /afs
umount: /afs: device is busy


Just for giggles, let's force that too:

% umount -f /afs
umount2: Device or resource busy


Yeah, totally didn't see that coming. What is the point of having force options if they never work? Somebody finally told me about umount -l, which detaches the filesystem but doesn't actually clean up references to it, which is generally considered a bad idea but actually works, unlike all the approved mechanisms

Water ripple as demands_attention indicator

I came across an interesting effect for Pidgin (or anything else, really). It requires Compiz; specifically, it requires the Water Effect plugin. I'm also pretty sure it requires GNOME. It turns out compiz has a fantastic dbus interface, you can pretty much get, set or trigger anything using it (more info). You can use any language with dbus bindings, but I prefer shell scripting when I can, so I use the included dbus-send program. To trigger the water effect, the command is:

dbus-send --type=method_call --dest=org.freedesktop.compiz /org/freedesktop/compiz/water/allscreens/point org.freedesktop.compiz.activate string:'root' int32:`xwininfo -root | grep id: | awk '{ print $4 }'`


The backtick expression pulls the root window's ID, which all the compiz activation commands require. That command shows a water ripple in the middle of the screen. My goal was to make the Pidgin icon ripple when I got a new message, which I'd noticed in a youtube video once and liked. I found code that uses xwininfo to figure out the location of a gnome panel icon, and combined it with the dbus call to make the ripple effect around a panel icon:

#!/bin/bash
#WINFO=`xwininfo -root -tree | egrep ' (1[2-9]|2[0-4])x(1[2-9]|2[0-4])\+0\+0' | grep "$1" | cut -d ')' -f 2-`
#This WINFO is faster to calculate, but depends on the icon being in the top panel
WINFO=`xwininfo -root -tree -name "Top Expanded Edge Panel"| grep "$1" | cut -d ')' -f 2-`
WIW=`echo $WINFO | cut -d 'x' -f 1`
WIH=`echo $WINFO | cut -d 'x' -f 2 | cut -d '+' -f 1`
WIX=`echo $WINFO | cut -d '+' -f 4`
WIY=`echo $WINFO | cut -d '+' -f 5`
let WAX=WIX+WIW/2
let WAY=WIY+WIH/2

dbus-send --type=method_call --dest=org.freedesktop.compiz /org/freedesktop/compiz/water/allscreens/point org.freedesktop.compiz.activate string:'root' int32:`xwininfo -root | grep id: | awk '{ print $4 }'` string:'amplitude' double:.1 string:'x' int32:$WAX string:'y' int32:$WAY


All that's left is to call the script when a message comes in. The accepted way I found was to change Pidgin's sound settings, but I'd prefer to leave them the way they are. Instead, I wrote a Pidgin plugin (in Perl, because C makes me sad) that waits for the received-im-msg signal and calls the shell script:

use Purple;

%PLUGIN_INFO = (
perl_api_version => 2,
name => "Icon Ripple",
version => "2.0.0",
summary => "Shows water ripples around the Pidgin icon",
description => "Shows water ripples (powered by the Compiz Water Effect plugin) around the Pidgin icon when a message is received",
author => "Michael Mrozek <sysop073\@gmail.com>",
url => "http://pidgin.im",
load => "plugin_load"
);

sub plugin_init {return %PLUGIN_INFO;}

sub plugin_load {
my $plugin = shift;
Purple::Signal::connect(Purple::Conversations::get_handle(), "received-im-msg", $plugin, \&signal_msgin, "");
}

sub signal_msgin { #(account, sender, message, conv, flags)
system("/home/mrozekma/scripts/waterping","Pidgin");
}


This has a side-effect that some may not like of showing the ripple on every received message, not just ones when the window is demanding attention. There's probably a way to change this in the plugin, but I prefer it that way so I haven't explored it.

EDIT: I forgot that I took a screenshot of the ripple effect before I wrote this article, and never included it. It's not very good, but you can see the effect at least:

Hello

Apparently I had a blogger account forever ago, but never posted any entries, so sniper506th told me I should. I renamed it "Things that amuse or depress me", which is only slightly better than the former "Mike's blog thingy", but not nearly as clever as "From My Brain To Your Computer". I miss my precious vJournal, but Blogger is by Google, so it's almost as good: . I suspect this will just be a crosspost of all the things I put in my away messages, but if I get unlazy I might put other stuff in here too. It'll probably be mostly quotes that amuse me, CS/Linux stuff, and how I hate Republicans/Theists/Southerners if I run out of the first two.