Planet Openbox!

May 17, 2012

Ring of Fire: 2012 annular eclipse

[Solar annular eclipse of January 15, 2010 in Jinan, Republic of China, by A013231 on Wikimedia Commons.] This Sunday, May 20th, the western half of the US will be treated to an annular solar eclipse.

Annular means that the moon is a bit farther away than usual, so it won't completely cover the sun even if you travel to the eclipse centerline. Why? Well, the moon's orbit around the earth isn't perfectly circular, so sometimes it's farther away, sometimes nearer. Remember all the hype two weeks ago about the "supermoon", where it was unusually close at full moon? The other side of that is that during this eclipse, at new moon, the moon is unusually far away, and therefore a little smaller, not quite big enough to cover the sun.

Since the sun will never be totally covered, make sure you have a safe solar filter for this one -- don't look with your naked eyes! You want a solar filter anyway, if you have any kind of telescope or even binoculars, because of next month's once-in-a-lifetime Venus transit (I'll write about that separately). But if you don't have a solar filter and absolutely can't get one in time, read on -- I'll have some suggestions later even for people without any sort of optical aid.

But first, the path of the eclipse. Here in the bay area, we're just a bit south of the southern limit of the annular path, which passes just south of the town of Redway, through Covelo, just south of Willows, then just misses Yuba City and Auburn. If you want to be closer to the centerline, go camping at Lassen National Park or Lake Shasta, or head to Reno or Tahoe If you're inclined to travel, NASA has a great interactive 2012 eclipse map you can use to check out possible locations.

Even back in the bay area, we still get a darn good dinner show. The partial eclipse starts at 5:17 pm PDT, with maximum eclipse at 6:33. The sun will be 18 degrees above the horizon at that point, and 89% eclipsed. Compare that with 97% for a site right on the centerline -- remember, since this is an annular eclipse, no place sees 100% coverage. The partial eclipse ends at 7:40 -- still well before sunset, which isn't until 8:11.

Photographers, if you want a shot of an annular eclipse as the sun sets, you'll need to head east, to Albuquerque, NM or Lubbock, TX. A little before sunset, the centerline also crosses near a lot of great vacation spots like Bryce, Zion and Canyon de Chelly.

[eclipse viewed through leaves] I mentioned that even without a solar filter, there are ways of watching the eclipse. The simplest is with a pinhole. You don't need to use an actual pin -- the size and shape of the hole isn't critical, as you can see in this image of the sun through the leaves of a tree during a 2005 eclipse in Malta. If you don't have a leafy tree handy, you can even lace your fingers together and look at the shadow of your hands. This eclipse will be very low in the sky, continuing through sunset, so you may need to project its shadow onto a wall rather than the ground.

If you have some time to prepare, take a piece of cardboard and punch a few holes through it. Try different sizes -- an actual pinhole, a BBQ skewer, a 3-hole punch, maybe even bigger holes up to the size of a penny. You might also try using aluminum foil -- you can get very clean circular holes that way, which might give a crisper image. Here's a good page on eclipse pinhole projection. What works best? I don't remember! It's been a very long time since the last eclipse here! Do the experiment! I know I will be.

[Solar projection with a Dobsonian] If you do have a telescope or binoculars but couldn't get a solar filter in time, don't despair. Instead of looking through the eyepiece, you can project the sun's image onto a white screen or even the ground or a wall. Use a cheap, low-power eyepiece -- any eyepiece you use for solar projection will get very hot, and you don't want to risk ruining a fancy one.

Point the telescope at the sun -- it's easy to tell when it's lined up by watching the shadow of the telescope -- and rotate the eyepiece so that it's aimed at your screen, which can be as simple as a sheet of paper. Be careful where that eyepiece is aimed -- make sure no one can walk through the path or put their hand in the way, and if you have a finderscope, make sure it's covered. This solar projection method works with binoculars too, but you'll want to mount them on a tripod so you don't have to hold them the whole time.

Of course, another great way to watch the eclipse is with your local astronomy club. I expect every club in the bay area -- and there are a lot of them -- will have telescopes out to share the eclipse with the public. So check with your local club -- San Jose Astronomical Association, Peninsula Astronomical Society, San Francisco Sidewalk Astronomers, San Francisco Amateur Astronomers, or any of the others on the AANC's list of Amateur Astronomy Clubs in Northern California or the SF Chronicle's list of astronomy clubs.

This eclipse should be pretty cool -- and a great chance to test out your solar equipment before next month's Venus transit.

When I went to put the event on my wall calendar last month, I discovered the calendar already had an entry for May 20: it's the start of Bear Awareness Week. So if you head up to Lassen or Shasta to watch the eclipse, be sure to be aware of the bears! (Also, maybe I should get a calendar that's a little more in tune with the sky.)

The Plight of Pinocchio: JavaScript's quest to become a real language

Brandon Keepers at JSDay:

JavaScript is no longer a toy language. Many of our applications can’t function without it. If we are going to use JavaScript to do real things, we need to treat it like a real language, adopting the same practices we use with real languages.

I’ll admit that I still write a lot of JavaScript in toy-like style. Brandon’s presentation is both motivating and informative for anyone wanting to improve their use of JavaScript.

Permalink

May 16, 2012

A cara da inveja



A cara da inveja

Setting up Vim for Clojure development notes

Started the process of getting jiggy with Clojure at work and didn’t like the idea of using Eclipse for my day to day work… so I started looking at how to make vim and clojure get along and came across a great post! Here are the distilled notes plus minor tweaks to get anyone out there trying to do the same thing going:

  1. Download VimClojure (http://www.vim.org/scripts/script.php?script_id=2501)
  2. Download VimSlime (https://github.com/jpalardy/vim-slime)
  3. Extract these files into your ~/.vim folder
  4. Add the following lines to ~/.vimrc:
    • ” Settings for VimClojure
    • let vimclojure#HighlightBuiltins = 1
    • let vimclojure#ParenRainbow = 1
    • ” Send entire file to repl
    • nmap <C-m> ggVG<C-c><C-c>
  5. Start a repl session inside screen:
    • screen -S clojure
    • lein repl
  6. Open a clojure file with vim and highlight the method you want to evaluate
  7. Press ctrl + c twice
    • For session name prompt, enter ‘clojure’ which is the name of the screen session
    • For window name prompt, accept the default number displayed
  8. The selected code should be evaluated in the screen session
  9. Press ctrl + c, v to get prompt again

Vim and Clojure sitting on a tree

NOTES:

  • I chose to start a repl using lein but you can use whatever you’re familar with to get a repl started
  • I have lein inside a directory in my Dropbox as well as all of my vim files and plugins. I then created soft links to them in my $HOME directory which makes this whole thing very easy to access from different systems as long as Dropbox is installed :)

May 15, 2012

Hello world!

Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!

mutt-kz: A new mutt fork

I stumbled upon a relatively new fork of mutt recently called mutt-kz.

It is a project which was created with the purpose of modernizing mutt by heavily integrating notmuch, a fast mail indexer, into the client. This integration provides mutt-kz with the ability to have full-text searching, tagging, virtual folders, and more.

After compiling it and configuring the virtual folders and tags to my liking, I have to say that I am quite pleased with mutt-kz. It's now my defacto replacement for mutt on my machines.

If you are interested, you can download the source code or learn more about it by heading over to the Wiki and Mailing list.

Tags:

Nova foto :)



Nova foto :)

Onde vai parar a criatividade humana?!



Onde vai parar a criatividade humana?!

Você sabia?

Sabe o Guile, do Street Fighter? Ele tem um cabelo engraçado, né? E o golpe que ele solta com as mãos, o tal Sonic Boom (também chamado erroneamente de Alec Full), é meio esquizito, né? Nunca parou pra pensar nessas coisas e que relação podem ter? Pois é, eu pensei.

Guile e o seu Sonic Boom
Guile e o seu Sonic Boom 

 O tal Sonic Boom, segundo o Wikipedia, é isto aqui:

A sonic boom is the sound associated with the shock waves created by an object traveling through the air faster than the speed of sound. Sonic booms generate enormous amounts of sound energy, sounding much like an explosion. The crack of a supersonic bulletpassing overhead is an example of a sonic boom in miniature.  

Ou seja: é o barulho que um objeto emite ao ultrapassar a velocidade do som!

- Ahh! Que legal!! E o cabelo dele? O que tem a ver com isso?


Nossa!!!

É disso aí que vem o formato do cabelo do coitado. 

Pra quem gosta de coisas exatas, uma imagem do Wikipedia:

 

Legal, né? :) 

May 14, 2012

May 2012 Screenshot #2

Another screenshot for the month. This one of course featuring my Openbox install.

Information:
Wallpaper: eCO
VIM color scheme: xoria256
Terminal colors: My config file.
Compositing / Effects: Cairo Composite Manager
Browser: uzbl

May 13, 2012

May 2012 Screenshot

Information:
Plasma Theme: A combination of Amakage and nowardev 2
Icons: elementary USU
Plasma Widget: Current Song
Wallpaper: curtns
Conky: My config file.

What podcasts does everyone recommend listening too?

Podcasts are an excellent way to pass the time and it has been awhile since I updated my list to include 'new' shows.
What are some podcasts that you recommend listening too?

The podcasts I currently listen too:

  • 2600: Off the Hook (RSS)
  • 2600: Off the Wall (RSS)
  • Buzz Out Loud (RSS)
  • Common Sense with Dan Carlin (RSS)
  • Dan Carlin's Hardcore History (RSS)
  • No Agenda (RSS)
  • The 404 (RSS)
  • The Skeptics' Guide to the Universe (RSS)
  • The Skeptics' Guide 5X5 (RSS)
  • this WEEK in TECH (RSS)

Tags:

May 12, 2012

Downloading Adobe-protected books to a Nook using Linux

University of Chicago Press has a Carl Zimmer book, A Planet of Viruses, as their free monthly e-book.

I know Zimmer is a good writer. but the ebook, despite being free, is encumbered with Adobe's version of DRM, which unlocks via a Windows or Mac program. I use Linux, and wanted to read the book on a Nook. Was I out of luck?

Happily, the instruction page they sent when I signed up for the book helpfully included a section for Linux users. Hooray, U. Chicago! It said Adobe Digital Editions will run under Wine, the Windows emulator. I'd been meaning to try that anyway, and a Carl Zimmer book seemed like the perfect excuse.

And overall, it worked pretty well, with only a few snags. Here are the steps I had to follow:

Authorizing a book using Adobe Digital Editions in Linux on Wine

Install wine (on Ubuntu, I used apt-get install wine).

Download the Adobe Digital Editions setup.exe

Run: wine setup.exe (this should install ADE inside your .wine directory)

Copy the file, e.g. URLLink.acsm, into .wine/drive_c/My\ Documents/ Don't bother trying to open it with ADE -- the program won't open anything except PDF and epub. Curiously, the only ways to open the file from ADE are to drag the file onto the ADE window or to pass it as a commandline argument:
wine start .wine/drive_c/My\ Documents/URLLink.acsm

Now ADE should download your book and display it. You can read it there, if you want. But you won't want to -- it's not a good reading interface.

Authorizing a device with Adobe Digital Editions under Wine

Now how do you get it into your ebook reader? ADE running under Wine doesn't recognize devices such as ebook readers. so nothing will be copied automatically. But you can copy it manually.

  • Plug in your ebook reader.
  • Mount the device wherever you like -- /media/nook, /nook or whatever.
  • With ADE not running (quit it if it's running), map a drive letter to the mount point:
    • Run winecfg
    • Click the Drives tab
    • Click Add...
    • Choose a drive letter (I chose D:)
    • Under Path: type in the mount point, like /nook
    • Click Show Advanced
    • Set the Type: to Floppy disk
    • Click OK to save it
  • Now the drive is mapped. Re-run ADE:
    wine .wine/drive_c/Program\ Files/Adobe/Adobe\ Digital\ Editions/digitaleditions.exe
    ADE should now see the device and ask you if you want to authorize it.
  • In ADE, drag the chosen book onto the left sidebar entry for the device.
  • umount the reader ... and now your new book should show up in the library.

In theory, the drive letter should stay mapped, so you should be able to use it for opening future books. Just remember to mount your device to the same location before running ADE under wine.

urukrama

I have never used Windows Vista or Windows 7, but from what I’ve learned from others it seems to have one really neat feature: Aero snap. If you drag a window to a screen edge that window will fill half of the available screen space. Tiling two windows is extremely easy with this. You can comfortably view two documents at the same time without losing much screen estate.

Now that I am using Pekwm again, I tried to replicate this behaviour with this window manager. One of Pekwm’s neatest features is its use of screen edges: you can assign mouse actions to the edges of the screen.

Could we use those screen edges to get a window to take up half of the screen space? One of the mouse actions you can use with the screen edges is “EnterMoving”, a mouse event that is only used for the screen edges. As the documentation states, this action “defines how to act when a dragged window enters a ScreenEdge”. The default action assigned to this action is “WarpToWorkspace”; if you drag a window to the left screen edge, the window will be moved to the workspace on the left.

I rarely use this feature, so I lose little by assigning a different action to this mouse binding. I initially tried to use Pekwm’s own window management actions to resize a window that I dragged to a screen edge, but that did not seem to work. But luckily there is wmctrl, a little tool that can manipulate windows managed by standard compliant window managers (like pekwm), from the command line.

Wmctrl is in the repositories of most distributions. If you use Debian or Ubuntu (or one of its derivatives), you can install it with the following command:

sudo aptitude install wmctrl

Once you have wmctrl installed, you have to reconfigure Pekwm’s mouse behaviour, by editing the ~/.pekwm/mouse file which governs all mouse actions. In the ScreenEdge section you’ll find the settings for each of the four screen edges. Look for the line that begins EnterMoving = “Any Any” in each of those section. This is what we will modify (or create if it doesn’t have that behaviour mapped yet for a screen edge).

The wmctrl commands we will use are specific to a particular screen size. The settings I give below are for my desktop screen, which has a 2048×1152 resolution, and for my laptop screen, which has a 1028×768 resolution. If you have a screen of a different size, you’ll have to modify this (I’ll explain how later).

For a 2048×1152 resolution

In the Down section, I have the following:

EnterMoving = "Any Any" { Actions = "Exec wmctrl -r :ACTIVE: -e 0,0,627,2048,550 &" }

In the Up section, I have the following:

EnterMoving = "Any Any" { Actions = "Exec wmctrl -r :ACTIVE: -e 0,0,0,2048,542 &" }

In the Left section:

EnterMoving = "Any Any" { Actions = "Exec wmctrl -r :ACTIVE: -e 0,0,0,1024,1152 &" }

And in the Right section, I have the following:

EnterMoving = "Any Any" { Actions = "Exec wmctrl -r :ACTIVE: -e 0,1025,0,1024,1152 &" }

For a 1028×768 resolution

In the Down section, I have the following:

EnterMoving = "Any Any" { Actions = "Exec wmctrl -r :ACTIVE: -e 0,0,412,1028,324 &" }

In the Up section, I have the following:

EnterMoving = "Any Any" { Actions = "Exec wmctrl -r :ACTIVE: -e 0,0,0,1028,384 &" }

In the Left section:

EnterMoving = "Any Any" { Actions = "Exec wmctrl -r :ACTIVE: -e 0,0,0,513,768 &" }

And in the Right section, I have the following:

EnterMoving = "Any Any" { Actions = "Exec wmctrl -r :ACTIVE: -e 0,513,0,513,768 &" }

These settings work as follows: If I drag a window to the right or left screen edge, it takes up the right or left half of the screen. If I drag it to the top or bottom edge, the window will tile vertically and take up the top or bottom half of the screen. These last settings are a little more troublesome, as you need to take the window decorations into consideration. The above settings are based on the Infinity Pekwm theme. If I were to use a different theme, that has smaller or bigger window decorations, I’ll have to adjust these settings by a few pixels so that the windows will not overlap. Since I very rarely use the vertical tiling (where the biggest changes would have to be made to account for the theme’s window decorations), I am not really bothered by this.

If you have to adjust these settings for your own screen size, it probably helps to know the syntax of the wmctrl command I use above. Let’s use the command for the Left screen edge as an example:

wmctrl -r :ACTIVE: -e 0,0,0,1024,1152

-r :ACTIVE: tells wmctrl to do something with the active window, which would be the window you are dragging into the screen edge. -e, then, tells wmctrl that you want to move and resize the window, according to the values given in the rest of the command, using the following syntax as explained in wmctrl man’s page: g,x,y,w,h.

  • g stands for the gravity. I’m not entirely sure what this does (you can read up on it on the EWMH standards documentation, if you like), but if you use the value 0 for this, it works.

  • x and y determine where the window will be positioned. For the left screen edge this is 0,0, as we want the window in the top left corner. For the right screen edge, this should be 0,half-of-your-horizontal-resolution as you want the window to be positioned at the top of the screen (the 0 value for x), but only beginning from a pixel after the middle of the screen (if you would start from the middle of the screen, it would overlap by a pixel the left window). In my case this is 1025 (half of 2048 + 1). For a 1024×768 screen resolution, this would be 513 (half of 1024 + 1). For the top and bottom edges you would set 0,0 for your top edge (as you want the window to placed in the top right corner), and 0,half-of-your-vertical-resolution for the bottom edge, as you want it to be placed in the middle of your screen.
  • The final two values (w and h) tell wmctrl how to resize the window: how wide and high it should be. For the left and right screen edges, you would want it to fill half of the screen horizontally, and to fill the entire screen vertically, so you would set the first value to half of your screen size (in my case 1024), and the second value to the size of your screen width (in my case 1152). For the top and bottom screen edges, you would reverse these values: the first would be the entire width of your screen (in my case 2048) and half of your vertical screen size, minus the size of your window decorations, as I mentioned before. You could, of course, also adjust the positioning of these windows, by adjusting the previous values.
  • Make sure that you did not delete the & sign at the end of the action in your configuration file. Once you have configured this for your screen, save your ~/.pekwm/mouse and reconfigure Pekwm. If you drag a window to one of the screen edges now, it should “snap” as it would in Aero (or, since I’ve never used Aero, as I think it would snap in Aero).

    The standard Openbox does not make use of the screen edges, so you can’t accomplish this with Openbox, but you could assign these commands to keybindings and do so manually. But in Openbox, you would probably want to use Openbox’ own actions, instead of wmctrl. Have a look at this post for ideas on how to set this up.


    May 11, 2012

    aphilippe: AHOIUAHAIUAHIOAUHOAUIHAOIUAH Twentieth Century Fox...



    aphilippe:

    AHOIUAHAIUAHIOAUHOAUIHAOIUAH

    Twentieth Century Fox con flauta (by TheKakolo2)

    May 10, 2012

    I live!

    Hello World,
    It has been quite a long time since I last posted on this site and I figured that I might as well attempt to revive it again.
    I've been pretty busy over the past few months with variety of things (Minecraft being one of the main culprits) and I didn't mean to take this long to post something, but time flies rather quickly it seems.

    My plan is to at least initially try to create a few posts a month and then try to build from there.

    elegance

    What follows is not a new guide. I wrote this a long time ago, for the Ubuntu forums, but was recently informed that the “Howto” section of the Ubuntu forums is being deprecated, in favour of the Ubuntu Wiki. I decided to save it here, for easier reference. I’ve updated the guide to make it relevant for Debian as well as the current Pekwm version.

    Contents

    1. Introduction
    2. Installing Pekwm
    3. Creating a Session entry for Pekwm
    4. Pekwm basics
    5. Configuring Pekwm
    6. Pekwm themes
    7. Conclusion

    1. Introduction

    Pekwm is a fast, functional, and flexible window manager, originally based on aewm++. It supports tabbed windows (like Fluxbox), key chains, pixmap themes, xinerama support and much more. If you like Fluxbox or Openbox chances are you’ll like Pekwm too, as it resembles both in looks and functionality. Pekwm is still actively developped.

    Here is what Pekwm can look like:


    (The first screenshot uses the Groove Pekwm and Gtk theme; the second uses the Fearless Pekwm theme and a modified Royalty gtk theme; the third uses the Elegance Pekwm theme.)

    Pekwm has excellent documentation, which you can find here. Everything you need to know to use Pekwm can be found there, and though it can be daunting at times I strongly recommend reading it. This guide is not meant to repeat or replace the official documentation, but rather to help users new to Pekwm getting started.

    2. Installing Pekwm

    The latest version of Pewkm (0.1.14) is both in the repositories of Debian Wheezy and Sid, as well as those of Ubuntu Quantal. Installing Pekwm 0.1.14 on Debian Wheezy and Sid, or Ubuntu Quantal (or distributions based on these) is, in other words, very easy. Just install the package through Synaptic, or through a terminal (sudo aptitude install pekwm).

    2.2 Building Pekwm from source

    Older versions of Debian or Ubuntu have older versions of Pekwm in their repositories. If you use one of those, or if you prefer to build from source, you can get Pekwm installed in just a few steps. Here is how to do it.

    • Preparation
      Since you will have to build from source, you will need the basic building tools installed. If you have never build a package from source before, you’ll have to install build-essential. I also recommend installing checkinstall, as it makes it much easier to remove the package you’ve installed later on. Checkinstall will first create a .deb package and install that. This means that it will show up in Synaptic and can be removed with Apt or Aptitude.

    You can install these two packages with the following command:

    sudo aptitude install build-essential checkinstall

    Next install the needed dependencies for Pekwm:

    sudo apt-get build-dep pekwm

  • Download the source code from the Pekwm site.
    Use your favourite web browser to surf to the Pekwm site and click on the download link for Pekwm 0.1.14 to download the latest stable version, or download it with the following command:
  • wget https://www.pekwm.org/projects/pekwm/files/pekwm-0.1.14.tar.bz2

  • Unpack the archive
    Once the source code archive has been downloaded, it is time to unpack it. Use a file browser to navigate to the directory where you saved the file and unpack the archive to the directory of your choice. Alternatively, you can use the command line as follows:
  • cd /path/to/the/directory/where/the/archive/is/saved
    tar xjvf pekwm-0.1.14.tar.bz2

  • Configure the package to make it ready to compile
    Now you have to compile the package. Open a terminal and navigate with the cd (‘change directory’) command to the directory where the unpacked archive is:
  • cd pekwm-0.1.14

    Then run the configure script to prepare the source for installation with the following command:

    ./configure

    You can add several options to this. Using this command, the package will be installed in /usr/local/. If you’d like the package to be installed in another directory, for example /usr/, use the following command:

    ./configure --prefix='/usr'

    There are more options (see here), but unless you really know what you are doing, you need not be concerned with them.

    The configure script will look for dependencies and basic system settings. Just let it all run. You don’t need to worry about what it tells you, unless you encounter an error and the process is aborted: only the first error message is then of importance as it will help you figure out what went wrong. If all goes well, you should see something like this:

    * pekwm version 0.1.14 configured successfully.
    *
    * PREFIX: /usr/local
    * FEATURES:  XShape Xrandr Xft image-xpm image-png menus harbour
    * CXXFLAGS: -g -O2  -I/usr/include -I/usr/include/freetype2
    * LIBS:   -L/usr/X11R6/lib -lX11 -lXext -lXrandr -lXft -lX11 -lfreetype -lz -lfontconfig -lXrender -lX11 -lXpm -lpng

    If you changed the destination directory, as explained above, the ‘PREFIX’ line will give the directory you specified. You can ignore the rest.

  • Build the package
    Once all this is done, you have to build the package. At the command prompt type the following command:
  • make

    A lot of information will appear. If no errors show up, none of it is really important and can safely be ignored. Note that this may take a while.

  • Install Pekwm
    If all this went smoothly and no errors were encountered, you can finally install the package with the following command:
  • sudo checkinstall

    (If you prefer not to use checkinstall, type ‘sudo make install’ instead.)

    Checkinstall will then build a .deb package and install that. If you’d rather build the .deb now, but install the package later using that deb, enter the following command instead to install:

    sudo checkinstall -D

    Checkinstall will ask for confirmations three times in the beginning of the process, so keep an eye on it. The defaults are fine, so you can just press enter when it asks for something.

    If all goes well, Pekwm is now installed. If you encounter any error messages in this process, post them in here, and perhaps someone can help.

    3. Creating a Session entry for Pekwm

    If you have installed the Pekwm package from the repositories, you can skip this step.

    If you compiled Pekwm from source and if you use a display and session manager, such as GDM, KDM or Slim, you will not have an entry for Pekwm in the Sessions menu of your login screen. But don’t worry, this is easily created. Open a terminal and enter the following command (you can replace nano by any other text editor, such as mousepad, leafpad, vim or gedit):

    sudo nano /usr/share/xsessions/Pekwm.desktop

    An empty file will open. Add the following to this:

    [Desktop Entry] 
    Encoding=UTF-8 
    Name=PekWM
    Comment=Start PekWM
    Exec=/usr/local/bin/pekwm
    Icon= 
    Type=Application

    (If you have installed Pekwm to /usr/ (as mentioned above), change the Exec line to ‘Exec=/usr/bin/pekwm’)

    Save and close the file and make the file executable with the following command:

    sudo chmod +x /usr/share/xsessions/Pekwm.desktop

    When you restart your computer, you will be able to choose Pekwm in the sessions menu (which is accessed with F10 > Sessions if you use GDM or KDM, or whatever other display manager your distro uses).

    If you don’t use a session manager, edit your ~/.xinitrc file (create one if you don’t have one already), so that it looks something like this:

    #!/bin/sh
    xsetroot -solid black &
    
    exec /usr/local/bin/pekwm
    

    If you have installed Pekwm to /usr/ (as mentioned above), change the exec line to ‘exec /usr/bin/pekwm’. When you start X with the command startx you will start a new Pekwm session.

    4. Pekwm basics

    When you first log into Pekwm, you won’t see much apart from a blank screen. This is normal. Pekwm doesn’t come with a panel, or a desktop manager. Pekwm is fairly straightforward. It is a window manager, and does not do much more than managing windows. Here are a few basics of Pekwm:

    Windows

    • Pekwm supports tabbed windows. You can group windows together by middle-clicking the titlebar of one window and dragging it to another window title. To group the next launched window with the current one, press the windows key + T to tag the current window. Until untagged with the same command, all new windows will be opened as tabs within that window.

  • Apart from maximizing, windows can also ‘fill’ in Pekwm: they will grow (either vertically, horizontally or both) until they reach another window border or an edge of the screen.
  • Every window can be stripped of their titlebar or their borders or both.
  • Menus

    • Pekwm comes with several menus. You have the root menu, which is editable and generally contains entries to launch your applications. There is a active window menu (the GoTo menu), which contains a list of all active windows on all workspaces. The GoToClient menu list all active windows with their tabs. The Icon menu lists the iconified windows.

  • Right click on the desktop, and you’ll have your root menu. Middle click and you have the active window menu. You can also click on the screen edges to call up these menus, which means you don’t have to iconify all windows to use the menu.
  • To see the Icon menu, press Windows key+Shift+I, to use the GoToClient menu, press Windows key+C
  • Other

    • Pekwm does not come with any panels, pagers, system trays. It does have a ‘harbour’, where you can load dockapps, and which is similar to (though less developed than) the slit of Fluxbox or the dock of Openbox. The order in which the dockapps are loaded can be specified in the autoproperties file (see below).

  • Pekwm has a command dialog, which can be launched by pressing the Windows key + D. It can be used to execute commands to launch applications, but also to performs Pekwm actions. For a list of actions, see here.
  • 5. Configuring Pekwm

    All of Pekwm’s configuration happens in the ~/.pekwm directory. In there you will find 7 files: config, menu, keys, mouse, autoproperties, start, and vars.

    There are no graphical tools to change the settings in these files (apart from a text editor ;-) ). Any changes you make to these files will not be applied until you reconfigure (in the root menu) or restart Pekwm.

    In case you accidentally delete these files, the defaults can be found at /usr/local/etc/pekwm

    Config
    This is the general configuration file. Here you can control the basic behaviour of Pekwm. It controls the workspace settings, the menu and harbour behaviour, window edge resistance, and more. The settings are very well explained in the official Pekwm documentation.

    Menu
    As you could have guessed, this is the file that controls your menu. You can edit this file to add, edit or remove entries or submenus to your root menu and (towards the end of the file) your window menu (the menu that pops up when you right click a window header). Any custom menu you’d like to setup will have to be added to this file.

    When you first run Pekwm you will already have a rather full default menu, with possibly plenty of applications you don’t have installed. It might be a useful basis to create your own menu. You could also run Menumaker to set up menus of all your installed applications. Run it with the following command:

    mmaker --no-desktop pekwm

    (Note that this will not overwrite your existing menu file. If you want it to overwrite, add the -f flag to the above command.

    The syntax for the menu file is fairly straightforward. A simple entry has the following structure:

    Entry = "NAME" { Actions = "Exec COMMAND &" }

    A submenu has the following syntax:

    Submenu = "NAME" {
    		Entry = "NAME" { Actions = "Exec COMMAND &" }
    		Entry = "NAME" { Actions = "Exec COMMAND &" }
    }

    (Make sure these brackets are always closed, or you will have errors and your menu will not display)

    To add a separator line to the menu, use the following:

    Separator {}

    Pekwm also supports dynamic menus. These are basically menu entries or submenus that display the output of a script that is run every time the entry or submenu is accessed.

    You can find some dynamic menus online. Check the exact syntax the menu requires, as they can vary. There are not that many dynamic menu scripts around, unfortunately. You can find and example of a dynamic menu, used to display the time and date, here.

    Keys
    This file controls all the keyboard bindings and keychains used in Pekwm. You can add keyboard bindings to launch programs or to perform actions in Pekwm, such as show a menu, move a window, switch desktops, etc. For a full list of Pekwm’s actions, see the documentation.

    The syntax structure of this file resembles that of the menu file and should be fairly self-evident. Mod1 is the Alt key, Mod4 the Windows key.

    You can have more than one action assigned to one key combination. To do so, just separate the actions by a semicolon. Here is an example:

    KeyPress = "Ctrl Mod1 R" { Actions = "Exec osdctl -s 'Reconfiguring'; Reload" }

    When you press Ctrl+Alt+R Pekwm will display on the screen the text ‘Reconfiguring’ (osdctl -s ‘Reconfiguring’) and reconfigure (Reload). (Note that this requires osdsh to be installed)

    Mouse
    This file controls all the mouse actions used in Pekwm. For a full list of Pekwm’s actions, see the documentation.

    Pekwm is set up by default to focus windows when the mouse moves over them (as opposed to the ‘click to focus’ style). If you’d like to change this, look for the following lines in the file and do what they say (there are quite a few of the first, but only one occurrence of the second):

    # Remove the following line if you want to use click to focus.
    # Uncomment the following line if windows should raise when clicked.

    For some ideas of what you can do with the Mouse and Keys file, have a look here.

    Autoproperties
    If you’d like certain applications to open on certain workspaces, have a certain title, skip the (window) menus, or be automatically tabbed together, you can specify all that here. The syntax is a little confusing at first, but it is well documented in the documentation and the default autoproperties file contains plenty of examples.

    For example, to have Opera start maximized and without titlebar, you would use the following setting:

    Property = "^opera,^Opera" {
     	ApplyOn = "Start New"
     	Border = "True"; Titlebar = "False"
    	MaximizedHorizontal = "True"; MaximizedVertical = "True"
    }

    Start
    This file is used to start applications when Pekwm is started. If you’d like to display a wallpaper or launch a panel whenever Pekwm is started, you can add entries for these things here. Note, though, that these applications are run every time Pekwm is started — including when you run ‘Restart’ in the root menu. The commands are executed only after Pekwm is started.

    To add an application, use the following structure:

    nameofapplication &

    The & at the end is crucial, or anything after it won’t be run. To give you an idea of what this file could look like, here is an example:

    # Auto-mounting drives 
    gnome-volume-manager & 
    # To set the background image
    hsetroot -tile "/home/urukrama/Images/Desktops/Abandoned.jpg" &
    fbpanel &
    conky &
    # To have visual feedback when changing the volume
    osdsh & 
    (sleep 1 && osdctl -m 1) &

    Before you can use this file, you will have to make it executable with the following command:

    chmod +x ~/.pekwm/start

    Vars
    Finally, the vars file contains variables that are applied throughout Pekwm. The default entry should be clear enough:

    $TERM="xterm -fn fixed +sb -bg white -fg black"

    Whenever the variable $TERM is used in any of Pekwm’s configuration files, the command xterm -fn fixed +sb -bg white -fg black will be run.

    6. Themes

    Unlike some other window managers, Pekwm themes govern all visual aspects: window headers and borders, menus, the harbour, fonts, as well as the position and functions of window buttons (like close, iconify, etc.).

    Themes are installed in ~/.pekwm/themes or /usr/local/share/pewkm/themes (/usr/share/pekwm/themes if you have changed the default installation directory). To install a theme, unpack the theme archive, and copy the folder that contains the ‘theme’ file and possibly image files to the above mentioned folders. The name of the theme folder is the name that will appear in the menu. You can change the theme also manually by editing the Pekwm config file (in the first section ‘Files’).

    You can download pekwm themes from Box-look. The theme settings have changed in more recent versions of Pekwm, so themes written for older versions are most likely unusable. You’ll be able to tell straight away whether a theme is broken or not. :-)

    7. Conclusion

    Since Pekwm is just a window manager, it doesn’t control the desktop, provide ways of changing Gtk settings such as themes, icons or fonts, manage the (un)mounting of devices, etc. Solutions to these are the same in Pekwm as in Fluxbox, Openbox or Icewm. If you need help with these, have a look at my Openbox guide, which discusses these at length.

    Like Fluxbox and Openbox, Pekwm is small and light, but highly configurable. Explore its many potentials and find a setup that works for you.

    For additional support of Pekwm read the documentation, join the mailing list, or enter #pekwm at irc.freenode.net.


    May 09, 2012

    Heroku's new $50 per month production database

    With a $150 per month reduction in the minimum dedicated database price, Heroku suddenly becomes viable for many more of our apps.

    Permalink

    The Darker Side of Software Development

    Jim Whimpey read my last post and shared exactly how he feels when consumed with a software problem:

    After hours without progress you go to bed thinking about it. Thinking about it makes you angry and frustrated but you can’t stop thinking about it. You spend so long at the computer you lose all perspective and follow paths that take you further from the solution. With each minute you spend banging your head against the problem you think less clearly and the possibility of solving the problem decreases. It is frustrating.

    This is exactly what happened with me. I think there’s only so many times you can work like this before you burn out. It’s important to learn from those moments and develop a sense for when they begin to arise, so you know when it’s time to step back and short-circuit the cycle.

    Permalink

    May 08, 2012

    Mução fora do ar - Carniça e as polícias



    Mução fora do ar - Carniça e as polícias

    test

    ok then  1 2 3

    May 07, 2012

    Money, Stress and The Cloud

    Or: How to Save Your Relationship with Rails Streaming Responses on Heroku

    This is as much a personal story as one about software development. It’s about dealing with problems in a production app, handling credit card payments on Heroku, working with customers, implementing custom HTTP streaming responses in Rails 3.0, all while living a happy life alongside.

    I failed at the last part, which has actually made this article somewhat painful to write. Although the events occurred in November and December 2011, it’s taken this long to share, not only because it’s a long story, but also because I was happy to have this stuff behind me. However, I believe it is illustrative on both a technical and personal level, and contains some useful lessons, so here you go!

    The Problem

    I’m at a mountain resort, palm trees shading the warm tropical sun, with a cold bottle of San Miguel Light in my hand. My wife and I have just arrived in the Philippines, where we’ll be spending the next eight months. I’m hanging out for a week during her volunteering orientation, before we head out to our new home town.

    Towards the end of that week, a rather disturbing email came to me: a double payment in an e-commerce app that we maintain. It’s the first time we’ve been told about something like this happening. I fixed it for the customer right away and let them know. Handling the money properly is pretty much the most important thing for this kind of app, so I interrogated the database and, surprisingly, found several more instances of the problem, taking a few different forms. Some payments were even missing data. This was not good.

    My first step was to step through the codebase again and look for opportunities to make the payment process more robust. I made a few changes and deployed them. For a little while, things seemed better, but it wasn’t too much longer before we heard about some further occurances of the problem. After some more debugging, I isolated the problem: some transactions with our credit card gateway (SecurePay) were very slow.

    The credit card transactions were taking longer than 30 seconds, which is the default timeout period for web requests on Heroku. This resulted in the user seeing their request timeout – but the actual payment might or might not still complete in the background, detached from the user’s browser request. In the meantime, the user might just pay again or leave altogether, creating these inconsistencies in the data.

    By this time, we’ve moved from Manila to our new home city, Bacolod. But we haven’t actually moved moved yet. We’re staying in a pension house. It’s basic, but comfortable, and in a good location to start exploring the city. But I have this big technical problem that’s inconveniencing people. So I spend the first couple of days half-thinking about what needs to be done, and the first couple of nights perched on the bed (the only seating in our room) working on code to get a solution ready.

    This first attempt at a solution was pushing the payment into a background job, then having the frontend check on the progress of the job before showing the “payment complete” message and order receipt. Pretty straightforward. I’d done this kind of thing plenty of times before. So I put my head down and got to work building a solution using delayed_job, which we already had in place for background jobs. After a couple of nights, I had things ready to test. I tried it and everything worked except the payment. What had happened? The credit card number wasn’t being passed on to the payment gateway. Then it struck me: the credit card number! Naturally, I had ensured my payment model never persisted the full credit card number. We didn’t want to store credit card numbers. This was a problem for delayed_job, because it relied on the persistence of all a record’s information in order for the asynchronous method to work properly. If only I had remembered this first!

    This led to a big discussion with my co-workers and Twitter network about ways to make this work. I really didn’t want to persist the credit card number in any way, but could it be done acceptibly, somehow? Perhaps persisting it only momentarily? Maybe we could move to Resque for the background jobs and use an in-memory-only Redis instance for the job persistence? I wasn’t happy with any of these options. I really didn’t want to have to worry about storing credit card numbers. (In my desparation, I briefly looked into what PCI compliance might involve, but that quickly steeled my resolve to avoid it completely.) Back to the drawing board.

    My wife has just started her first couple of days at her new workplace. There’s a lot of meeting people and other formalities. I join her for these. I’m still thinking about fixing this problem, but there’s not much time to translate the thought into action. Soon after, we’re taken around the town looking at places to rent. We pick a place and now it’s time to start a final move.

    With the delayed_job option no longer possible, I thought about other simple ways to fix the problem. I found this <timeoutValue> option in the SecurePay API docs! Perhaps we could just set that to 30 and all would be good! Turns out it wasn’t so. After some largely unconstructive back and forth with SecurePay’s developer support team, I realised that the timeout value was only intended for batches of transactions, not the individual transactions that we were using.

    Meanwhile, I’d written a script that took a day’s transaction data from SecurePay, compared it to the payment records in our app, and reported on any inconsistencies. I ran it each night with bated breath. Many nights, things were OK, and I would feel a massive relief. But my heart was in my mouth everytime I pasted the code into the Heroku console and hit the return key. And at the times when it did reveal problems, I knew I had to then look into things, rectify them, and sheepishly pass on the news to our customer, so they could make things right for their users. Fortunately, our customer was actually very gracious about this. They knew that new software undergoes teething issues, and they were grateful we were staying on top of things for them.

    As an aside, one thing that was very helpful for ensuring we didn’t lose any critical payment information was Papertrail, a cloud-based application logging service. I threw a whole bunch of specially marked logger.info messages around the payment events in the app, which would safely store all the request parameters in on Papertrail (after removing the full credit card details), where I could easily find them and review them with a saved search. I highly recommend it. In this case, it ensured we could always recover from any instances of the problem.

    But this was just a measure to help us cope while the problem still existed. We still needed a solution. It was clear that the only way forward was to accept that the credit card transactions could take more than 30 seconds, and then find a way to handle it gracefully.

    I had an inkling that an asynchronous web server or app framework might help. I didn’t know much about this stuff, so I started madly researching them. Goliath. Rainbows. Cramp. EventMachine and its family of libraries. They’re a whole a different world, and I didn’t really know where to start. I didn’t want to shift the whole app to different underlying tech. Maybe I could extract the payments into an asynchronous mini-app? But that would still have the same response timeout problems, just shifted around a little. Perhaps this approach wasn’t going to help at all.

    It’s the weekend now, and we’re in our new place with a minimal set of furniture. Just some bamboo chairs. No bed or table yet. We’ll do some shopping later in the day for the rest of our essentials, but it’s the morning now and I need to keep pushing with this work. I’m perched on the edge of the bamboo chair, my laptop tethered to a delicately placed iPhone, tenuously receiving a 3G signal. The connection was fine when I tested it outside the house, but not so within its concrete walls. We don’t have air conditioning yet. It’s 35 degrees inside and the air is still. I’m sweating and the laptop is hot and I have tab upon tab of slowly-loaded web pages open about a topic I’m not sure will help me and I’m worried about just how on earth I will be able to work in this environment and I’m not getting anywhere and I’m more irritable and tightly wound than I can remember. This is not how things should be.

    The Solutions

    After some research, an async web server didn’t seem to offer a straightforward answer to my problems. A simpler approach was to leverage a feature of the Heroku Cedar platform: its handling of HTTP streaming responses. If Heroku detects that you’re streaming a response, then its timeout window is extended by 55 seconds every time a byte of data is sent down the line.

    Streaming responses are a flagship feature of Rails 3.1, but they are primarily for passing on the start of your page layout while it assembles the rest of the page’s content for rendering. This means the browser can start downloading the site’s JS and CSS assets sooner. This is useful for overall performance, but it wasn’t what I needed. My app was also only on Rails 3.0, and didn’t want to upgrade to a new Rails at the same time as fixing this problem.

    Fortunately, some support for manually handling streaming exists in Rails 3.0, via assigning an object to the controller’s response_body. All it needs to do is response to each and accept a block, which it can call with the data to be streamed:

    class StreamResponse
      def each(&block)
        # Send some data to the client
        block.call("This is some data")
        
        # And send a bit more. It's a stream, after all
        block.call("This is some more data")
      end
    end
    
    class OrdersController < ApplicationController
      def create
        # Do your normal controller things here
    
        # Then stream the response
        self.response_body = StreamResponse.new
      end
    end
    

    This object is sent the each message once as the controller action runs. Inside this method, whatever you output is streamed immediately to the client browser. Here, finally, I could create some custom streaming logic and support these slow payments.

    What I did was split the response into four phases:

    • Immediately stream the content for a loading screen
    • Run the slow payment action in a separate Ruby thread
    • Regularly check the thread’s progress, and while it is still running, stream a bite-sized chunk of data to keep the connection alive
    • When the thread completes, stream a final success or failure message

    Here’s how the controller looks:

    class OrdersController < ApplicationController
      respond_to :html
        
      def create
        @order = Order.new(params[:order])
    
        if !@order.valid?
          # Don't bother streaming and talking to the payment gateway if we know there are already things missing or invalid
          render 'show' and return
        end
    
        stream_response = ThreadedOrderPurchaseResponse.new
        stream_response.start_content     = render_to_string('purchasing')
        stream_response.keepalive_content = ' '.html_safe
        stream_response.success_content   = render_to_string('purchasing_complete', :layout => false, :locals => {:success => true})
        stream_response.failure_content   = render_to_string('purchasing_complete', :layout => false, :locals => {:success => false})
    
        stream_response.slow_process = lambda do
          if @order.save
            if @order.purchaser_email.present?
              Resque.enqueue(DeliverOrderMailerOrderCompletedJob, order.id)
            end
    
            Thread.current['success'] = true
          else
            Thread.current['success'] = false
          end
        end
    
        self.response_body = stream_response
      end
    end
    

    The logic for handling the threaded payment in the background is in the ThreadedOrderPurchaseResponse class, which is based in part on the template_streaming gem for Rails 2.3. For this particular case, I added a simple Ruby thread:

    class ThreadedOrderPurchaseResponse
      attr_accessor :bytes_to_threshold,
                    :slow_process,
                    :start_content,
                    :keepalive_content,
                    :success_content,
                    :failure_content,
    
      def initialize
        @bytes_to_threshold = 2048
      end
    
      def each(&block)
        @response_stream = block
    
        push(@start_content)
        
        if @payment_thread.blank?
          @payment_thread = create_payment_thread
        end
    
        # OK, let's sort this out. We're going to let the transaction run for up to 180 seconds.
        # And we only have 190 before unicorn kills us anyway.
        # Everytime we send a bit of data in a streamed response, they give us 55 seconds.
        # So we only only need to check on the thread 3 times.
    
        90.times do |i|
          if @payment_thread.status.nil?
            # An exception occured in the thread
            push(failure_response)
            @payment_thread.join
            return
          elsif @payment_thread['complete']
            if @payment_thread['success']
              push(@success_content)
            else
              push(@failure_content)
            end
            @payment_thread.join
            return
          else
            push(@keepalive_content)
          end
    
          sleep 2
        end
    
        # We only get here if the thread hasn't completed within 180 seconds.
        @payment_thread.join
        push(@failure_content)
      end
    
      def push(data)
        if @bytes_to_threshold > 0
          @response_stream.call(data + padding(@bytes_to_threshold - data.length))
          @bytes_to_threshold = 0
        else
          @response_stream.call(data)
        end
      end
    
      private
    
      def create_payment_thread
        Thread.new do
          @slow_process.call
          Thread.current['complete'] = true
        end
      end
    
      def padding(length)
        return '' if length <= 0
        content_length = [length - 7, 0].max
        "<!--#{'+'*content_length}-->".html_safe
      end
    end
    

    Some things to note here. Firstly, with a streaming response, browsers won’t start rendering your content until you’ve returned a certain number of bytes. So the first time we send data back, we pad it with an HTML comment string to ensure we pass this threshold. 2048 bytes for the threshold is enough for all the browsers to render the initial content.

    We also use two thread-local variables (complete and success booleans) to record the status of the operation we’re running inside the thread. Since these can be inspected from outside the thread, the supervising loop in the each method can know when the operation has completed and return the appropriate data to the client browser.

    Because we’re using threads here, it’s important to set config.threadsafe! in config/application.rb to ensure things run properly (though I keep it mostly turned off in development mode because having to restart the app for every change is quite slow).

    Finally, here’s how the views look. First, we have a partial HTML page for the loading screen:

    <% page_title 'Purchase in progress' -%>
    
    <div class="public-page">
      <div class="content">
        <div class="wrapper">
          <div class="purchasing">
            <div class="purchasing-inner">
              <div id="purchasing-progress">
                <div><!-- Needed to ensure streaming DOM forms how we want it -->
                <div id="spinner"></div>
                <h2>Your payment is in progress</h2>
                <p>We&rsquo;re talking to the bank to confirm your payment. This can take up to a minute or two so hang tight!</p>
                <script src="/javascripts/vendor/spin.min.js"></script>
                <script>
                  (function() {
                    var opts = {
                      lines: 16,
                      length: 12,
                      width: 4,
                      radius: 19,
                      color: '#000',
                      speed: 1.2,
                      trail: 60,
                      shadow: false
                    };
                    var spinner = new Spinner(opts).spin(document.getElementById('spinner'));
                  })();
                </script>
              </div>
              <!-- just inside .purchasing-progress -->
    

    Even though this is not a complete HTML document, browsers still render it as expected, showing the user a nice spinner and loading message. Then, then the operation (hopefully) succeeds, we send the following along the response stream:

                  <div id="purchasing-complete">
                    <% if success -%>
                      <h2>Payment successful</h2>
                      <p>Thanks! Your payment was successful and your order is complete. <a href="/order">View your purchase receipt</a>.</p>
                    <% else -%>
                      <h2>Payment error</h2>
                      <p>Sorry, something went wrong and we couldn&rsquo;t complete your purchase. <a href="/order?errors=true">Please review your details and try your purchase again</a>.</p>
                    <% end -%>
                    <script>
                      (function() {
                        document.getElementById('purchasing-progress').style.display = 'none';
                        var t = setTimeout(function() {
                          document.getElementById('purchasing-complete').style.visibility = 'visible';
                        }, 500);
                      })();
                    </script>
                  </div>
                  <script type="text/javascript">
                    (function() {
                      window.location.href = '/order<%= "#{'?errors=true' unless success}" %>';
                    })();
                  </script>
                  <meta http-equiv="refresh" content="1; url=<%= "#{request.protocol}#{request.server_name}/order#{'?errors=true' unless success}" %>">
                </div><!-- .purchasing-inner -->
              </div>
            </div>
          </div>
        </div><!-- .public-page -->
      </body>
    </html>
    

    When the purchase is complete, we want to send the user back to an /order page, where they see either their purchase receipt, or a form for fixing any errors if the purchase failed. We use a number of methods to ensure this happens. Firstly, for the browser with no support for JavaScript, we show a descriptive paragraph with a simple link back to /order. Additionally, we throw a meta refresh tag in there that should send them along to the right place. Next, for browsers supporting JavaScript, we hide the existing loading message and send the user to /order by setting window.location. Lastly, we append ?errors=true to the URL if the purchase failed. This is necessary because the redirect results in a new GET request, and it doesn’t have the existing object around to inspect for its state.

    I’m reasearching and building all of this, and I know it will no longer be something I can cram into a couple of big days alone. So I finally fall back into a regular, more sustainable work pattern, from our thankfully now furnished and air-conditioned home. I wake up, make breakfast, start working at 8am, and work solidly through to around 6pm, when I once again check for any erroneous payments that might have occurred during the day. But outside my working hours, I just want the next work day to hurry along so I can get closer to finishing this refactor. Especially know that I’ve found a workable approach, I really want this off my plate. I want to reclaim my life.

    Fortunately, a forced respite comes in the form of an impromptu beach holiday in Sipalay, a 5-hour bus trip to the south of our island. There’s a weekend followed by a Philippine public holiday and also our wedding anniversary, so we get a nice break. The laptop only leaves my bag once, for a movie-viewing session. This is much-needed time away for both of us.

    The Release

    Finally, I thought I was ready to go. I’d built a working solution for gracefully handling payment processing of any duration. I’d also expanded the state machine around orders to include an additional “paying” state that is entered immediately before the transaction with the payment gateway, and left immediately after. This gave me some extra granularity in finding and catching any orders that don’t complete the transaction as expected.

    At this point, it was time to do some thorough testing on the staging app on Heroku. I pushed up the code, eagerly looking for confirmation that the end of this problem was in sight. It didn’t come. My streaming responses, well, didn’t stream. Not in the slightest.

    I was baffled and frustrated. Before embarking on this line of development, I’d already written an isolated testing app and verified that the streaming responses worked on Heroku. Now that I’d taken the time to integrate this technique into the app at large, and verified it all locally, all I had was the browser waiting until the request was complete before rendering all the content at once.

    To further investigate, I introduced an isolated streaming test controller into my app. Something I could harmlessly access and test at /streams/new within the full app. First, I kept most of the logic that I was using for the purchases. Deployed and tested. Didn’t work. Then I started stripping a little out. Deployed and tested. Didn’t work. Finally, I made it as basic as possible. It was effectively the same as my test within the separate isolated app. Surely this would yield the behaviour I wanted. Deployed and tested. Still didn’t work!

    Something strange was happening, and it must have been something outside of the app’s codebase. I compared the environment of my test app with the staging app. The staging app had a few Heroku add-ons enabled, so I started disabling them. It turned out that the NewRelic add-on was preventing the streaming responses from working. I dove deeply into its configuration to see if there was a way to keep it around. Perhaps something to make it thread-friendly? Nothing was immediately obvious, and removing it allowed streaming to work again. So I removed it (though later I worked out out to keep it around, and I’m glad to have it back).

    By this stage, I was wary of how changes in the Heroku environment could affect the streaming. To ensure everything would work in production, I copied the remaining environmental difference into the staging app: HTTPS support. This broke everything all over again. So again, it was time for more frustration at trying to work around the problem, especially since there didn’t seem to be many options available. I was using hostname-based SSL, the only suitable option for our app, which uses a wildcard SSL certificate for secure connections across multiple subdomains. Luckily, my good colleague Hugh made me aware of Heroku’s SSL Endpoint beta add-on, which works seamlessly with Cedar’s streaming support and fixed the remaining problem with the app in staging. This improved SSL support has just now been released by Heroku.

    So there it was. With the app environment problems smoothed out, the streaming refactor applied to both the public and admin areas, and a nice design put in place for both, everything was ready to go. On the 19th of December, we made the changes live. Everything went smoothly, and after six weeks, I could finally breathe a sigh of relief.

    The Lessons

    In those six weeks (which truly felt like a lot longer), not only did I have to solve one of the most difficult technical problems I’d encountered, but I also moved six thousand kilometers away, started living in a new culture amid a new language, found and set up a house, and did what I could to support my wife in doing all these same things as well as getting started in her new volunteering role. In trying to do all of these at once, I did all of them somewhat badly. And in placing priority on a quick fix to the technical issues, I did especially poorly at everything that happened away from the computer screen, including being the happy husband and travel partner that I wanted to be.

    I won’t do this again. What would I do differently if I had the same things happen? First, I would relax. I’d spend more time thinking over the problems while away from the text editor and the Google searches. This would actually allow some room for insight and incision into the problem. There would be less flaying about. I’d be calmer and happier and would think more clearly. I’d also spend more time talking things over with my creative and resourceful teammates. In this case, the problem occurred immediately after moving overseas. While I’d previously spent quite some time successfully working remotely, the extra distance left me feeling unreasonably isolated, and I didn’t rely on my friends and colleagues as much as I should have.

    What I wouldn’t have changed was how I communicated with the customer. I was quick to admit a problem, assured them that addressing it was important to me, and then kept them in the loop through the entire debugging and development process. I’d also still have devised interim measures (like the script to check for erroneous payments) to stay on top of any instances of the problem, ensuring my customer could manage their business as well as possible under the circumstances. Even if my final fix took a little longer to come, keeping the customer informed and equipped in this way would have kept them happy.

    And happiness, after all, is what’s important. A happy developer will do better work and end the day satisfied. And then be happy in anything else outside of work. And all of this strengthens their ability to contribute positively to the world.

    Despite the unhappiness I endured dealing with this problem, I’m happy that I’ve fixed it, moved on from it, and learnt some valuable lessons:

    • It’s important to recognise when a problem requires a serious fix. Building a serious fix requires a real plan, not an ad-hoc one.
    • Creating a real plan requires time, especially away from the computer screen.
    • Architecting serious changes is best done in collaboration with your teammates, even you’re the holder of most of the domain knowledge.
    • Customers can remain satisfied and sympathetic even during times of app instability, as long as they know you’re serious about fixing the problems and are kept involved throughout the process.
    • You need to take care of yourself. You’re not a machine, and you can’t solve problems when you’re feeling like shit.

    I hope you find these helpful too.

    May 06, 2012

    Playing an MP3 file from an Android app

    I've mostly been enormously happy with my upgrade from my old Archos 5 to the Samsung Galaxy Player 5.0. The Galaxy does everything I always wanted the Archos to do, all those things the Archos should have done but couldn't because of its buggy and unsupported Android 1.6.

    That is, I've been happy with everything except one thing: my birdsong app no longer worked.

    I have a little HTML app based on my "tweet" python script which lets you choose from a list of birdsong MP3 files. (The actual MP3 files are ripped from the excellent 4-CD Stokes Field Guide to Western Bird Songs set.) The HTML app matches bird names as you type in characters. (If you're curious, an earlier test version is at tweet.html.)

    On the Archos, I ran that under my WebClient Android app (I had to modify the HTML to add a keyboard, since in Android 1.6 the soft keyboard doesn't work in WebView text fields). I chose a bird, and WebView passed off the MP3 file to the Archos' built-in audio player. Worked great.

    On the Samsung Galaxy, no such luck. Apparently Samsung's built-in media player can only play files it has indexed itself. If you try to use it to play an arbitrary file, say, "Song_Sparrow.mp3", it will say: unknown file type. No matter that the file ends in .mp3 ... and no matter that I've called intent.setDataAndType(Uri.parse(url), "audio/mpeg"); ... and no matter that the file is sitting on the SD cad and has in fact been indexed already by the media player. You didn't navigate to it via the media player's UI, so it refuses to play it.

    I haven't been able to come up with an answer to how to make Samsung's media player more flexible, and I was just starting a search for alternate Android MP3 player apps, when I ran across Play mp3 in SD Card, using Android's MediaPlayer and Error creating MediaPlayer with Uri or file in assets which gave me the solution. Instead of using an intent and letting WebView call up a music application, you can use an Android MediaPlayer to play your file directly.

    Here's what the code looks like, inside setWebViewClient() which is itself inside onCreate():

                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    if (url.endsWith(".mp3")) {
                        MediaPlayer mediaPlayer = new MediaPlayer();
                        try {
                            mediaPlayer.setDataSource(getApplicationContext(), Uri.parse(url));
                            mediaPlayer.prepare();
                            mediaPlayer.start();
                        }
                        catch (IllegalArgumentException e) { showMessage("Illegal argument exception on " + url); }
                        catch (IllegalStateException e) { showMessage("Illegal State exception on " + url); }
                        catch (IOException e) { showMessage("I/O exception on " + url); }
                    }
                }
    

    showMessage() is my little wrapper that pops up an error message dialog. Of course, you can handle other types, not just files ending in .mp3.

    And now I can take the Galaxy out on a birdwalk and use it to help me identify bird songs.

    Scam Failure via Norfolk Homes

    My wife and I recently attempted to have a company in Ann Arbor called Norfolk Homes build us a new house. It didn’t work out. Read on to hear my short story of dealing with a corrupt business.

    We put down $1000 to hold the lot. We had been going about choosing what features etc we wanted in the house. At one point, Lisa Markwardt, the Norfolk rep we’d been working with, let us know that the $1000 only held the lot for about a week and that we had to sign a purchase agreement to properly secure the lot since there was “another buyer interested in the same lot.” They wanted us to sign an agreement for the base cost of the home.

    I was very annoyed and felt this was probably a nasty tactic at the time, but we gave them the benefit of the doubt. When we signed it and gave another $9000 check, I was careful to make it very clear that we intended on formulating our addendum and amend the agreement before the nine business days that we had to withdraw from the contract had elapsed.

    I pressed Lisa nearly each of the nine days to get us the information we needed to provide our final list of upgrades. The timeline went as follows:

    • Tuesday, May 1st: We give her the list of wants
    • Wednesday: She responds, “I have reviewed your list and all seems to be good. I will prepare your documents and send them over.” That night, with nothing apparently happening, I let her know by email, voicemail, and text that I needed the list that night, or we’d be backing out.
    • Thursday: I send a formal withdrawal letter to the corporate office via FedEx Overnight, USPS Certified Mail, Fax, and email, and to Lisa via email.
    • Friday, May 4th: The ninth business day we had to withdraw.

    I haven’t heard a single thing from any of them since her last devoid-of-usefulness email.

    Since things went the way that they did, I have very strong suspicions that this is a standard business practice, and it makes me a little sick to think of the poor folks who could be taken advantage of by them.

    Once those nine days had elapsed, we would have been legally bound to purchase the base home. They could have simply refused to do the upgrades we discussed. And if they did them, we would have zero opportunity to negotiate — we’d be forced to accept what they give us or continue with the base home.

    Absolutely shameless.

    Update, Sunday, May 6: Lisa lives! She just fired this email, and I can’t believe they’re even still trying. (Btw, I like how she calls them “cancelation requests.”)

    Hi Adam and Julie,
    We received the last of your cancelation requests late on Friday afternoon. If you do wish to continue in a more timely manner as mentioned in your email, please let me know and I will hand your file over to our other sales agent Gretchen who has been in Tennessee but will be returning on Monday. That way we will be sure to get you the attention you deserve.
    Thanks and I hope you are enjoying your weekend.

    Lisa Markwardt
    Norfolk Homes
    Michigan Division Sales
    734 389 9976
    lmarkwardt@Norfolk-Homes.com

    Update: Norfolk president, Kevin Martin, did call me a few days after things exploded and tried to salvage the deal, explaining that this was not how the company does business and that “corrective action” would be taken on his end. So it’s possible Lisa Markwardt is mostly at fault for this episode. I’m still not convinced Norfolk would have been too upset if my nine days elapsed without action, though.

    May 03, 2012

    Extremely strange seatbelt warning sticker

    I bought a Miata yesterday! My new baby. It's a 2000, in a lovely color Mazda calls "twilight blue mica". (You can see Miata pictures here, if you're so inclined.)

    I'd forgotten how much nicer sports cars are to drive. I retired my last X1/9 more than a year ago, and have been driving mushy street vehicles since then. The Miata surprises me every time I get into it with its immediacy -- throttle, brake, steering, everything happens now.

    It does have some used-car glitches that I need to sort out (some of them maybe even severe), but in general it's a great car: in stock trim it handles a lot like the street-prepared X1/9, even on crappy Kumho tires. Of course, that could be new owner infatuation talking. Ask me again in a few months. :-)

    [extremely strange seatbelt warning] But really what I wanted to write about was the extremely strange warning sticker that came plastered to the driver's side window. I didn't really look at the sticker until the second day after I drove the car home, and then did a double-take. It says:

    While use of all seat belts reduce the chance of ejection, failure to install and use shoulder harnesses with lap belts can result in serious or fatal injuries in some crashes. Lap-only belts increase the chance of head and neck injury by allowing the upper torso to move unrestrained in a crash and increase the chance of spinal column and abdominal injuries by concentrating excessive force on the lower torso. Because children carry a disproportionate amount of body weight above the waist, they are more likely to sustain those injuries. Shoulder harnesses may be available that can be retrofitted in this vehicle. For more information call the Auto Safety Hotline at 1-800-424-9393.

    If you look at the photo I took of the sticker, note the shoulder belt anchor at the right edge of the frame. It's a normal stock shoulder belt, just like you'll find in any car -- this is a 2000 model, for crying out loud, not a 1970.

    A web search on the error message led me to Section 27314.5 of the California Vehicle Code, which states that

    27314.5. (a) (1) Subject to paragraph (3), no dealer shall sell or offer for sale any used passenger vehicle of a model year of 1972 to 1990, inclusive, unless there is affixed to the window of the left front door or, if there is no window, to another suitable location so that it may be seen and read by a person standing outside the vehicle at that location, a notice, printed in 14-point type, which reads as follows:
    ... followed by the text on my sticker. It goes on:
    (2) The notice shall remain affixed to the vehicle pursuant to paragraph (1) at all times that the vehicle is for sale.

    So the dealer must have put this sticker on. But why? Reading on:

    (3) The notice is not required to be affixed to any vehicle equipped with both a lap belt and a shoulder harness for the driver and one passenger in the front seat of the vehicle and for at least two passengers in the rear seat of the vehicle.

    The dealer must not have read as far as paragraph (3).

    I also found that, despite the fact that the DMV's website still links to the page I linked above, that statute was in the process of being repealed by CA Assembly Bill 2679. Except that if you click on "Read latest draft", apparently they changed their minds again in the latest version of AB 2679 and are now going to keep the warning in.

    Maybe instead of leaving it unchanged or striking it, they should change it to make it clearer that it only applies to cars without shoulder harnesses installed ... if there are any such cars. Haven't shoulder harnesses been mandatory in US cars since the early 1970s? Wikipedia says they've been mandatory in the front seat since 1968 ... but the citation they give for that goes to a page that no longer exists, so that may be off by a few years.

    In any case, anyone buying a car so old it doesn't have a shoulder harness and only "may" be able to have one retrofitted to it probably understands there may be some safety issues in a 40-year-old car, and doesn't need a warning sticker.

    May 02, 2012

    "Now my adopted state has chosen to turn its back on its tradition of welcoming immigrants, and of..."

    ““Now my adopted state has chosen to turn its back on its tradition of welcoming immigrants, and of tolerance and freedom to all its citizens, with a proposed amendment to the NC State Constitution no less, that hangs a great banner across the entrances to the state saying to a whole bunch of American citizens: You are not welcome here.””

    - Bob Young

    May 01, 2012

    Updated Themes etc

    I've updated some themes to be more up-to-date and whatnot.

    I've also started working on a newer version of the theme I use, including a much updated gtk3 theme.

    It looks like this:

    http://david.chalkskeletons.com/files/pics/ecru3.png

    Themes are here:

    https://github.com/mulberry/Ecru3

    https://github.com/mulberry/Openbox-Ambiance-theme

    https://github.com/mulberry/Elementary-Openbox-Theme

    They are self explanatory.

    The Ambiance theme really needs openbox from git to work properly but it will work fine (but lack different coloured buttons) on older versions.

    Any questions might be better directed at twitter @david_barr

    English: My Red Hat took me and the kids to the NC Museum of Art...



    English: My Red Hat took me and the kids to the NC Museum of Art this last Sunday! It was perfect too as we got to see a lot of the exhibits and still managed to find time to eat at Lilly’s. Did you know that the entrance is free and the museum is sponsored by the State of North Carolina for our viewing and learning pleasure? Take that NYC and your extremely expensive entrance fees! :P

    Português: Meu Red Hat me levou com minhas filhas até o NC Museum of Art este último domingo! Foi um dia mais que perfeito já que conseguimos ver um monte das exibições e ainda achamos um tempinho para comer na pizzaria Lilly’s. Você sabia que a entrada é completamente free e que o museo é patrocinado pelo Estado da Carolina do Norte para o nosso deleite? Toma NYC e seus preços de entrada exorbitantes! :P

    April 27, 2012

    Venus is at its brightest -- why? And how to calculate it

    Venus has been a beautiful sight in the evening sky for months, but at the end of April it's reaching a brightness peak, magnitude -4.7.

    By then, if you look at it in a telescope or even good binoculars, you'll see it has waned to a crescent. That's a bit non-obvious: when the moon is a crescent, it's a lot fainter than a full moon. So why is Venus brightest in its crescent phase?

    It has to do with their orbits. The moon is always about the same distance away, about 385,000 km or 239,000 miles (I've owned cars with more miles than that!), though it varies a little, from 362,600 km at perigee to 405,400 km at apogee.

    When we look at the full moon, not only are we seeing the whole Earth-facing surface illuminated, but the central part of that light is reflecting straight up off the moon's surface. When we look at a crescent moon, we're seeing light that's near the moon's sunrise or sunset point -- dimmer and more spread out than the concentrated light of noon -- and in addition we're seeing less of it.

    Venus, in contrast, varies its distance from us immensely. We can't see Venus when it's "full", because it's on the other side of the sun from us and lost in the sun's glow. It'll next be there a year from now, in April of 2013. But if we could see it when it's full, Venus would be a distant 1.7 AU from us. An AU is an Astronomical Unit, the average distance of the earth from the sun or about 89 million miles, so Venus when it's full is about 170 million miles away. Its disk is a tiny 9.9 arcseconds (an arcsecond is 1/3600 of a degree) -- about the size of Mars this month.

    In contrast, when we look at the crescent Venus around the end of this month, although we're only seeing about 28% of its surface illuminated, and that only with glancing twilight rays, it's much closer to us -- less than half an AU, or about 45 million miles -- and its disk extends a huge 37 arcseconds, bigger than Jupiter this month.

    Of course, eventually, as Venus pulls between us and the sun, its crescent gets so slim that even its huge size can't compensate. So its peak brightness happens when those two curves cross, when the disk is somewhere around 27% illuminated, as happens at the end of this month and the beginning of May.

    Exactly when? Good question. The RASC Handbook says Venus' "greatest illuminated extent" is on April 30, but PyEphem and XEphem say Venus is actually brighter from May 3-8 ... and when it emerges from the sun's glare and moves into the morning sky in June, it'll be slightly brighter still, peaking at magnitude -4.8 in the first week of July.)

    Tracking Venus with PyEphem

    When I started my Shallow Sky column this month, I saw the notice of Venus's maximum brightness and greatest illuminated extent in the RASC Handbook. But I wanted more details -- how much did its distance and size really change, when would the brightness peak again as it emerged from the sun's glare, when would it next be "full"?

    PyEphem made it easy to calculate all this. Just create an ephem.Venus() object, calculate its values for any date of interest, then print out parameters like phase, mag, earth_distance and size. In just a few minutes of programming, I had a nice table of Venus data.

    import ephem
    
    venus = ephem.Venus()
    
    print '%10s   %6s %6s %6s %6s' % ('date', '%', 'mag', 'dist', 'size')
    def print_venus(when) :
        venus.compute(when)
        fmt = '%02d-%02d-%02d   %6.2f %6.2f %6.2f %6.2f'
        trip = when.triple()
        print fmt % (trip[0], trip[1], trip[2],
                     venus.phase, venus.mag, venus.earth_distance, venus.size)
    
    # Loop from the beginning of 2012 through the middle of 2013:
    d = ephem.date('2012')
    end_date = ephem.date('2013/6/1')
    while d  end_date :
        print_venus(d)
        # Add a week:
        d = ephem.date(d + ephem.hour * 24)
    

    I've found PyEphem very handy for calculations like this -- and it's great to be able to double-check listings in other publications.

    April 24, 2012

    Firefox stopped accepting remote commands

    When I upgraded to Firefox 11 a month or so ago, I got a surprise: I couldn't invoke firefox from other applications any more. Clicking on a link in an app such as xchat just gave me the Firefox Profile Manager dialog, instead of opening the link in the browser I was already running.

    I couldn't find anything written about it, so I've been putting up with it, copying each link then switching to the desktop where Firefox is running and middleclick-pasting it into the browser. But this morning, I did a new round of searching, and finally found the answer, in bug 716110. and its duplicate, 716361.

    Quoting from bug 716110::

    [The developers] changed the -no-remote flag's behavior in a
    surprising, backward incompatible way. Before, it just meant "start a
    new instance." Now, it also means "don't listen for remote commands."
    
    Apparently the change went in for Firefox 9, because of bug 650078.

    Indeed, that was the problem. I have multiple Firefox profiles, so I use -no-remote -P profilename when I start Firefox, so each profile doesn't conflict with one that might already be running.

    But with Firefox 9 or later, you can't do that. Instead, run your first, primary profile without -no-remote; then if you start up other profiles later, run them with -no-remote so they don't conflict with the first one. That works okay for my typical usage, fortunately: I have a main Firefox window I run all day, and only start up other profiles for short periods.

    But since not everyone uses this model, fortunately, some upcoming Firefox version will fix the problem by adding a new runtime flag, -new-instance, to do what -no-remote used to do: start up a window for a new profile, rather than talking to the running Firefox. Here's the new --help text:

    -no-remote Do not accept or send remote commands; implies -new-instance.\n
    -new-instance Open new instance, not a new window in running instance.\n
    The web Command Line Options page doesn't seem to have been updated yet, but perhaps it will when the Firefox with the fix is released.

    Of course, it would have been much simpler if Firefox just honored the -P flag and used whatever profile it was given, as suggested by a commenter in bug 650078. But bsmedberg replies that the complexity of the code makes that difficult.

    The new arguments look more sensible than the old -no-remote, though it's frustrating that it was so hard to find information about changes like this. All three bugs are filled with comments from people who, like me, lost a lot of time trying to figure out what broke and how to launch URLs remotely after the change. Thanks to Ryan for clarifying the issue and filing the bug to fix the problem, and to Jed, who added the new flag with his first Mozilla patch. Hooray for open source!

    Blog entries aggregated on this page are owned by, and represent the opinion of the author.
    Hosted by Tim Riley
    lovingly cared for by David Barr