Raspberry Pi+Minibian: Adjusting the Locale and Time Zone

I really have enjoyed playing with the Raspberry Pi, but many of my projects don't require a GUI (for example OpenVPN and web servers). For projects like these, I usually install Minibian which is a great, small version of Raspbian with all the GUI goodness removed. It is a perfect starting point for my headless projects, except that out of the box, it comes setup with locale and timezones configured for Great Britian. This causes some strange characters to come up when typing on the keyboard, and the clock doesn't reflect my local time zone.

Fortunately, these issues are easy to address, and I will show you the steps I take to configure my system for my locale and time zone (us-EN & America/Los_Angeles). Just use your locale and time zone in the steps below to configure your system as desired.

  1. Install Minibian on your SD card following the provided instructions. Insert the card into your Raspberry Pi, power it up, and log in. (The default username/password is root/raspberry). You may also want to change the name of your system from the default "raspberrypi" by editing the /etc/hostname file.
  2. Change the keyboard locale. Run the following command:
    dpkg-reconfigure keyboard-configuration
    • Set your "Keyboard model" to "Generic 105-key (Intl) PC".
    • Set the "Country of origin for the keyboard" and "Keyboard layout" both to "English (US).
    • Next for the "Key to function as AltGr" choose "The default for the keyboard layout".
    • For "Compose key" I chose "No compose key".
    • Finally, choose "No" for "Use Control+Alt+Backspace to terminate the X server".
    Once the command completes, reboot your Raspberry Pi to pickup the new keyboard layout.
  3. Now change the system local. Run the command
    dpkg-reconfigure locales
    and de-select "en_GB.UTF-8 UTF-8" and select "en_US.UTF-8 UTF-8", then set the default locale to "en_US.UTF-8" on the next screen.
  4. Edit the /etc/default/locale file and change/add the following lines:
    then log out and back in again to pick up the new locale.
  5. Finally, run
    dpkg-reconfigure tzdata
    and select "America", then "Los_Angeles" to set the local time zone for your system.
  6. Now that your system understands you a little better, it's probably a good time to update your system using
    apt-get update
    apt-get upgrade
    then reboot your system again.

Optional Tweaks

If you'd like to make your system a little more secure, you can enable sudo and disable the root login with the following steps:
  1. Install sudo:
    apt-get install sudo
  2. Create your new user. For example, to add the user "bob" run the command
    adduser bob
    and follow the prompts.
  3. Add your new user to the sudoer's list. Run visudo then add the following line (changing the username to the user you just added) after the root ALL=(ALL:ALL) ALL line:
    bob ALL=(ALL:ALL) ALL
  4. Now disable the root user with the command
    passwd -l root
    (note that is a lower-case L, not a one)
  5. Now log out of your root session and log in as your new user.
Finally, it's a good idea to change the SSH server keys because the ones that come with the image file make it easy to impersonate your system (since everybody has access to those keys):
sudo rm /etc/ssh/ssh_host_*
sudo dpkg-reconfigure openssh-server

Now you should have a headless Raspberry Pi system that you can use for various server projects that is customized for your locale and timezone! If you have any questions or comments on this procedure, please feel free to leave a comment.

Read More......


Driving WS2812/NeoPixels RGB LEDS over CAT5 Ethernet Cable

I was recently working on a project using Adafruit NeoPixels (WS2812) RGB LED strips where a single controller was supposed to drive five strings of 30 pixels that were physically located several feet apart. I knew right away that there was going to be a couple of problems trying to drive the strings over more than 20 feet of cable. First off there is the voltage drop issue - these strings can draw several amps, and could easily drop around 1 volt or more, depending on the cabling and connectors. The other issue is the integrity of the data signal being sent to the string. The pixels are very timing sensitive, and noise or ringing caused by a long wire run could easily introduce errors, or even result in a completely non-functioning string. This last issue was made even worse by my choice of controller, the Teensy 3.0 which is a 3.3V part, while the pixels require a 5V input. (By the way, the Teensy 3.0/3.1 + the OctoWS2811 library is an awesome choice for driving dozen to hundreds of RGB pixels!)

While it seems that many people have successfully driven NeoPixel/WS2812 strings directly from the Teensy using a small resister to reduce ringing, I was pretty sure that wouldn't work over any appreciable distance. It also appears that the newer WS2812B pixels won't work at all with just a 3.3V signal. It didn't take me too long to come up with the solution for the data issue - RS-422/485 drivers and receivers! Since the pixel data is really just serial data, I figured using RS-485 balanced transmission lines to send the data would work perfectly. The data signal is well within the bandwidth these chips are capable of, and as a bonus, the SN75174 Quad Differential Line Driver IC inputs will easily accept the 3.3V outputs from the controller! On the receiving end, I went with SN75176 Differential Bus Transciever chips because I had several of those on hand in my parts bin. I just needed the receiver part of the chip, and it was quite easy to disable the transmitter portion.

Next up was the power-drop issue. Right about the same time I was dealing with this I discovered these LM2596 DC-DC Buck Converters on Amazon - they were perfect! Their low cost, small size, high efficiency and wide input voltage range made them a snap to integrate into my project. (Just make sure you check/adjust the output voltage on these before you use them!). Now I could feed 12V into my long cables feeding the remote strings, and use these power supplies on the receiving side to drop it down to the needed 5V. Since I was only driving about 30 pixels on each line, the 3A output was more than enough to drive each string.

With all the pieces in place, it was time to test out my ideas. First, I wanted to test out driving the data signal using the differential converts, so I wired up a transmitter and receiver on each end of 100 feet of CAT5 cable, connected up my controller to the transmitter and 5 meters (150 pixels) on the receiving end. For now, I just connected up a beefy 5V/10A power supply at the receiving end to power the string. After connecting everything up, it worked like a charm! Every pixel was responding as though it was sitting right next to the controller.

Next up, I cut the string up into 5 lengths of 30 pixels each, and wired them up as shown below, using the differential transmitters/receivers and the DC/DC converters (again making sure they were adjusted to provide 5V output!), powering everything with a large 12V power supply. Everything worked as expected, the pixels were changing colors as commanded, with no color shift or dimming caused by voltage drops.

Notice that I am calling out the color codes for the CAT5 wiring - it is important that at least the data wires are on twisted pair of conductors (blue/blue-white in this case). I also like to have the power wires paired as well, with all the +V connections on the solid wires and the -V connections on the white-striped wires, which helps with noise immunity on the power lines. In my project, I used 4 position connectors and just tied all the +V wires together on one terminal and all the -V wires on another (with the data on the remaining two terminals). Using all the extra wires in the cable for power helps reduce the resistance, and thus the power drop on the cables.

In the end, my project worked well, with the strips connected via 15 - 25 foot lengths of CAT5 cable all connecting back to my central controller. If you have a project where you need to have several remote RGB pixel strips all controlled from a single controller, hopefully by using this approach you can make your pixels work just like they were connected directly to the controller. As usual, your feedback is always appreciated, and if you have any questions please feel free to leave a comment.

Read More......


Making kvm/qemu/libvirt Play Nice with PulseAudio on a Headless Ubuntu 12.04 Server

I've been running over a dozen virtual machines on my headless server for almost two years now, and for all that time I've always missed being able to hear the audio from those machines. I would occasionally try to figure out how to make audio work over VNC, but never could find a solution on the Internet. Finally last week I decided to at least get part-way there by getting the audio to play on the server's speaker port. The first step was pretty easy – installing PulseAudio on the server:

sudo apt-get install pulseaudio

Now from what I could gather on the Internet, it seems like I needed to run PulseAudio in system mode, despite all the warnings that it should probably not be run that way. I figured that since I don't usually have any logged in users on the system, it would just be better to have it running all the time. In order to do that, I edited the /etc/default/pulseaudio file, and changed the following settings to:


Then I added my user and the libvirt-qemu user to the pulse-access group:

sudo adduser myuser pulse-access
sudo adduser libvirt-qemu pulse-access

You'll need to log out and back in again for the new group to be picked up on your shell. Finally, I started the PulseAudio service:

sudo service pulseaudio start

Now a quick test to make sure the sound subsystem was working:

paplay test-sound.wav

In my case, I could barely hear the sound playing, so I did a pactl list sinks to figure out which sink was being used, then issued
pactl set-sink-volume 1 100%
pactl set-sink-mute 1 0
to set the volume level of sink 1 to the maximum and unmute it. Now I could hear the sound just fine!

The next hurdle was to get the sound from the virtual machines to play through PulseAudio. It turns out there are quite a few obstacles to achieving that goal. First off, libvirt automatically disables audio if you are using a VNC client! It turns out to be fairly simple to fix that though, simply edit /etc/libvirt/qemu.conf and change the following setting to:

vnc_allow_host_audio = 1

After restarting the libvirt daemon using sudo service libvirt-bin restart I could see in the syslog file that libvirt/kvm was trying to use the PulseAudio subsytem, but apparmor was blocking access to several key files/directories. I never did find a working answer by Googling, but I worked out the following settings for the /etc/apparmor.d/abstractions/libvirt-qemu file. I changed /{dev,run}/shm r, to /{dev,run}/shm rw, then added /{dev,run}/shm/pulse* rw, right after that line. Finally I added /var/lib/libvirt/.pulse-cookie rwk, (note the trailing commas on those lines!) then told apparmor to reload the configuration:

sudo invoke-rc.d apparmor reload

I fired off a Windows XP x32 guest, and was able to hear sound, but it was very distorted and choppy. The solution to that was to change the sound hardware in the virtual machine's configuration file from <sound model='ac97'> to <sound model='es1370'>. After that, I was getting perfect sound from my virtual machine!

Now for a few caveats – it seems that changing any of the PulseAudio configuration or restarting the service while the virtual machine is running can cause problems like the sound no longer working, all the way to the virtual machine's OS hanging up trying to play sounds. So once you started your virtual machine, leave things alone! I have also been working on trying to forward the sound over the network to my workstation, but so far I am having mixed results with that. Hopefully I'll have another post soon describing how to make that work.

And here is the usual warning that goes with tweaking your system like this: These instructions worked for me, but your mileage may vary. Also, I won't be responsible if any of this causes your machine to stop working or catch on fire – but this stuff should be pretty straight-forward and not cause any serious issues that can't be reversed. Hopefully my adventure will help you to enjoy hearing from your virtual machines. If you have any questions or corrections, please feel free to post them in the comments.

Read More......


Time-Lapse Video Capture From Network Cameras (Linux)

I have several network cameras watching the outside of my home, monitored by ZoneMinder. I have it set up so that when there is motion detected, it will record for several seconds and send me an email with stills of the incident. While this is nice and gives me a little peace-of-mind, I've always thought about having it record continuously. While it is easy enough to do in ZoneMinder, I didn't really want to use up that much storage recording video and then have to scroll through it to find anything interesting.

The other day I saw a blog post where someone was using a Raspberry Pi and a webcam to do some time-lapse photography, and that sparked an idea that seemed easy enough to do in an afternoon – I could come up with a Python script to grab images from the network cameras at fixed intervals, and write them to a video file in order to generate a time-lapse video!

The first step was to figure out how to build a video file a frame at a time using Python. I had played with the motion-jpeg (mjpeg) format in the past, which pretty much consists of jpeg images streamed one after the other in a file (sometimes with a boundary record between them). I discovered that I could simply capture and append jpeg images to a file and get a video file that could be read by a few video players and converters. Best of all, I could use a simple avconv (formerly ffmpeg) command to convert the mjpeg files to mp4, which is smaller and viewable by almost any player.

Next, I wanted to be able to time-stamp each image so that I could tell when the video was created. For this I stumbled across the Python Imaging Library (PIL) which supports several image formats, including jpeg. Using it, I was able to select a font and write a time-stamp on each image as it was captured before adding it to the mjpeg video file. If it isn't already installed on your system, you can install it using

sudo apt-get install python-imaging
for Debian-based systems or by using the appropriate package manager for your distro.

With all the pieces in place, I developed a little Python script that periodically grabs images from several network cameras and builds a separate mjpeg file for each of them:


# Number of seconds between frames:

# Name of truetype font file to use for timestamps (should be a monospace font!)
FONT_FILENAME = "UbuntuMono-B.ttf"

# Format of timestamp on each frame
TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S"

# Command to batch convert mjpeg to mp4 files:
#  for f in *.mjpeg; do echo $f ; avconv -r 30000/1001 -i "$f" "${f%mjpeg}mp4" 2>/dev/null ; done

import urllib
import sys, time, datetime
import StringIO
import Image, ImageDraw, ImageFont

class Camera:
    def __init__(self, name, url, filename):
        self.name = name
        self.url = url
        self.filename = filename
    def CaptureImage(self):
        camera = urllib.urlopen(self.url)
        image_buffer = StringIO.StringIO()
        image = Image.open(image_buffer)
        return image
    def TimestampImage(self, image):
        draw_buffer = ImageDraw.Draw(image)
        font = ImageFont.truetype(FONT_FILENAME, 16)
        timestamp = datetime.datetime.now()
        stamptext = "{0} - {1}".format(timestamp.strftime(TIMESTAMP_FORMAT), self.name)
        draw_buffer.text((5, 5), stamptext, font=font)

    def SaveImage(self, image):
        with open(self.filename, "a+b") as video_file:
            image.save(video_file, "JPEG")

    def Update(self):
        image = self.CaptureImage()
        print("Captured image from {0} camera to {1}".format(self.name, self.filename))

if __name__ == "__main__":
    cameras = []
    cameras.append(Camera("porch", "http://username:password@", "cam1.mjpeg"))
    cameras.append(Camera("driveway", "http://username:password@", "cam2.mjpeg"))
    cameras.append(Camera("backyard", "http://username:password@", "cam3.mjpeg"))
    cameras.append(Camera("sideyard", "", "cam4.mjpeg"))
    cameras.append(Camera("stairway", "", "cam5.mjpeg"))
    print("Capturing images from {0} cameras every {1} seconds...".format(len(cameras), LAPSE_TIME))
        while (True):
            for camera in cameras:
    except KeyboardInterrupt:
        print("\nExit requested, terminating normally")

Notice the URLs supplied in the Camera constructors. These are specific to each brand of camera, but you can usually find the format with a little Googling. In my program above, the first three cameras are Panasonic BL-C101A network cameras, the last two are a D-Link DCS-930L and a TrendNet TV-IP551W which both have very similar software and URLs.

The font file referenced above needs to be located in the same directory as the Python script, and for best results should be a mono-space font. I just grabbed the Ubuntu Monospace Bold TrueType font file for use here, but you could use anything you like.

You will probably want to launch this as a background task so that it can run for extended periods of time. I have it running on the same server that runs my ZoneMinder setup, so it can run 24-7 collecting time-lapse video. I also wrote a quick little script file that iterates the mjpeg files it finds and converts them to mp4 for easier viewing and archiving:


echo "Removing old files..."
rm -fv *.mp4

echo "Converting files to mp4..."
for f in *.mjpeg ; do
    echo "  Converting $f to $t"
    avconv -r 30000/1001 -i "$f" -q 5 "$t" 2>/dev/null

echo "Done!"

I had a lot of fun learning a few new tricks while working on this, and hopefully you can use it as a starting point for your own time-lapse adventure. If you find this post useful, or have questions about how it works, please leave a comment below.

Read More......


Low-Voltage Controlled AC Power Strip

NOTE:  This hack involves working with dangerous voltage levels, which can result in property damage, injury, or death!  Proceed at your own risk.  If you are not comfortable working with power circuits and wiring, you may want to consider using something like the PowerSwitch Tail II from Adafruit instead.

As part of a larger project I'm working on, I needed a way to control five AC powered devices from a small microcontroller.  At work, we use Opto 22 G4 Solid State Relays in our industrial control systems.  They are small and convenient to work with, but I was looking for something more compact.  Searching around the web, I noticed that many hobbyist were working with Sharp S108T02 Solid State Relays, but doing a little research at Digikey I decided to use the similar Sharp S201S06V instead.

S201S06V Solid State Relay Diagram

Next, I needed to find a way to provide outlets to plug the controlled devices into.  I thought about using a project box and mounting three standard dual outlet wall sockets on it, then using a standard outlet cover on those.  That would work, but it would still be on the large side.  I then considered using a standard six outlet power strip.  I headed down to my local Home Depot to see what options I had there, and returned with a nice, metal cased power strip.  I removed the four screws holding the bottom on and checked to see if my relays would fit:

Ready for surgery

It looked like everything would fit!  As a bonus, mounting the relays flat against the bottom would allow the metal to act like a heat sink.  I measured to get them evenly spaced, drilled the mounting holes, and attached the relays using a bit of thermal compound for good heat transfer.  (I thought I would be able to attach the wires after the relays were mounted, but it turned out to be easier to do with them unmounted, so next time I would wait on the thermal compound).

Power and control bus wiring

I started by soldering the common buses for the AC power and DC control lines, covering all the exposed wiring with heat shrink as I went.  Once I had the common wiring done, I added the individual AC output wiring using different colors for each – I picked colors that matched the low-voltage cable's colors.  For the low-voltage cable I just used the cable from an old PS/2 mouse that had a 6 pin DIN connector, which gave me 5 lines for control signals and 1 for ground.  The mouse cable works nicely here because it is long and flexible.  Before you start wiring the DC cable,  drill a hole in the upper part of the case near the power cable, big enough for an appropriate strain-relief.  Then run the cable through that hole, before you begin soldering it!  I also made sure to write down the sequence of wire colors on the DC cable that corresponded to the pin numbers on the DIN connector, so that I could attach the AC control wire colors in the same sequence.

Added power control wiring

After getting all the AC and DC wiring attached to the solid state relays, I mounted everything to the bottom plate of the power strip, and routed the wires, with the inputs coming from the side where the power cable comes in, and the outputs at the opposite end.  As you can see, I also added some cable tie points to make sure the wires did not get pulled out or shorted.

Solid state relays wired and mounted

Next, I removed the black “hot” bus from all but the outlet closest to the power cord, and broke the jumpers on the hot side between the top and bottom outlet of each outlet pair that connected them together.  I am leaving the outlet closest to the power cord always hot, so I have some place to plug in the project's controller.  I can still turn the entire thing on and off using the existing power switch.  Now that that the remaining five outlet's hot sides are disconnected, it's time to start wiring them up.

Since these outlets use “slide in” connections intended for lower gauge solid core wire, and I am using smaller gauge stranded wire, I soldered the ends of the stranded wire to form a stiff end that would easily slide into the outlet connections.  You can sort of see the soldered end of the red wire in the next photo.

Connecting the power wiring

Now I attach each of the AC control wires to the corresponding outlet, making sure to keep them in the same order as the relay (and DIN connector) wiring.  I cut each wire to the proper length, so that I wouldn't have a lot of extra wire to try and tuck inside.  Here it is all wired up:

Ready to close

And now all assembled and ready to go with its new “tail”:

Ready for work

Now I should note that the solid state relay inputs are simply LEDs, and require a current limiting resistor in series or you will destroy the devices.  In this design, those resistors are located on the controller board, but you could easily include them inside the power strip by soldering them inline with the DC control wires.  If you are going to use this with multiple projects, I would suggest including the resistors in the power strip to help protect the relays from damage.

This hack worked out very nicely, and it's been working for several months without any issues.  Once again, since this project involves dangerous voltages, you should exercise extreme caution when building and using this hack.  I am not responsible if you decide to duplicate this project and you electrocute yourself, set your house on fire, or encounter some other mishap.  You have been warned.


Several of the commenters over at Hack a Day noted that I didn't mention the solid state relays I'm using are only rated for 3 amps (and you would likely need a heat sink for that).  Although that is fine for my project, you probably shouldn't try to control your air conditioner using these devices!  You could do a similar hack using a larger power strip with more internal room and beefier solid state relays, and along the way provide either fusing or circuit breaker protection for the individual outlets.

Read More......


Let There Be Music

I needed to be able to play MP3 files as part of a larger project I'm working on.  I did a quick search on the Internet for embeddable MP3 player chips and circuits, but everything seemed a bit too expensive or too much work.  It was around then I saw Hack a Day's post pointing me to Gadget Gangster's Instructables article Adding MP3 to your project for $3.00.  Being the cheapskate that I am, $3 sounds great to me!

A quick trip to eBay and I had two of these “mini-clip” players on the way.  I figured I should get an extra just in case I damage one while fooling around.   Before I began hacking the player, I tested it out to make sure it was operational and get an idea of how it behaves.  One of the things I discovered is that the USB interface is pretty flaky (at least when connected to a Linux system), so it was much easier and faster to transfer files onto it by writing directly to the MicroSD card using a card reader.

Player liberated from its case

I cracked one open and took a look to see what it would take to hook into it.  One of the things I wanted to do is to be able to move this from prototype to finished product, or between projects.  The Instructables article showed discrete wires soldered to the board, which I could have brought out to some kind of connector.  After a bit of thought, I realized I could use a small 10 pin IDC connector and ribbon cable to allow me to plug it into a nice wire-wrappable header.  And with the extra pins, I could also supply power, and even pick off the audio!

After some minor surgery

First, I removed the power wires and also carefully removed the surface mount audio connector.  Somewhere in my lab I have the parts to build the IDC/ribbon cable assembly, but I found a pre-made one in my parts bin so I just cut it in half and started peeling back a few of the wires.

IDC cable ready for action
 I started by connecting to the power pads (mostly because they were big and easy to get to).  This also conveniently allowed me to set the amount of overhang from the connector to the board.  I then cut and stripped the remaining three wires for that side and landed them onto the pads where the audio connector used to be.  Next, I flipped over the board and cut each of the wires to length and soldered them to the center of each button pad.

Wires landed on board

Now with all the wires hooked up, it's time to test it out and see if I fried anything.  I wired up a 2x10 header on my main project (more about that in a future post) and wrote some quick code to “push” the buttons.

At home in the new project

I'm using a PIC18F4550 in this project, and using my favorite language – assembly. I love the challenge of hand-tuning code to make it as small and fast as possible, and that's not so easy with the PIC18F's!  Anyway, I wanted to drive the switch outputs open collector style, so for the switch outputs I initialize the ports by setting the switch TRIS bits and clearing the LAT output bits.  Then when I want to “press” a switch, I clear the the corresponding TRIS bit which drives the output low, and set a tick countdown timer.  When that timer expires about 200ms later, I set all the TRIS bits again to “float” the outputs and release all the switches.

After checking to make sure the software was doing as I expected, I connected the MP3 player to the main project, powered it up, and out came music!  I then tested each of the switch functions, and the player responded as expected, pausing, playing, skipping forward and back, etc.  To my surprise, everything worked as expected.  The player has been working without any hiccups for several months, despite powering it with 5v instead of it's expected 3.7v battery, and shorting the switch inputs to ground instead of the other contact (although I expect that is the way it is wired anyway).

I would like to thank Gadget Gangster for sharing his cool tip to re-purpose cheap MP3 players for use in embedded projects, and Hack a Day for bringing it to my attention.

Read More......


Hacking WebRunner to work with Firefox 6.0

I have come to depend on Salsita Software's WebRunner extension for Firefox that let's me create “applications” out of web sites. It comes in especially handy when I want to be logged in with multiple identities on the same web site, as well has keeping an always open window on my Zoneminder cameras.

When Firefox 6.0 was pushed out in Ubuntu, I was quite dismayed to find that when it checked add-ons and extensions for compatibility, WebRunner was not compatible, and furthermore, an updated version was not available. I waited for around two weeks for Salsita to update their software, but so far there's been nothing. So I dug around in the .xpi file and came up with this hack to make the current version work with Firefox 6. These instructions are for Ubuntu/Linux (since that is all I have running now), but the changes should be very similar for Windows as well.

First download (but don't install/run) the latest .xpi file from here. Then open the file with an archive manager (.xpi files are really just jar/zip files) and edit the file install.rdf, changing the value of /RDF/Description/version from 5.0 to 5.1, and the value of /RDF/targetApplication/maxVersion from 5.* to 6.*. Next, edit the file stub/application.ini, changing the value for MaxVersion from 5.0.* to 6.0.*. You may want to rename the .xpi file at this point to make it easier to keep track of it.

Now update to Firefox 6.0 (if you haven't done so already) and remove the old WebRunner 5.0 extension, in Tools|Add-ons on the Extensions tab. Close that dialog, and go to File|Open File... in Firefox and select your modified .xpi file. It should install without complaint, indicating it is version 5.1 (hopefully Salsita will version their next release higher than this).

At this point, you can either re-create your web application shortcuts, or hack the existing ones to work with the updated extension. To fix the current shortcuts and applications, modify the command for the shortcuts to point to firefox-6.0 instead of firefox-5.0. Then for each application in your ~/.webapps directory, edit the appname@webrunner/stub/application.ini file and change MaxVersion from 5.0.* to 6.0.* and change GRE_HOME to /usr/lib/firefox-6.0. Now try to launch your web application shortcuts and you should be good-to-go!

As with most hacks, I make no guarantees that this won't in some way hose your Firefox installation or your entire computer, so attempt this at your own risk! On the other hand, if you are like me and depend on the excellent WebRunner extension, this hack is a quick way to get it back in Firefox 6. Make sure to leave comments if you have tried this under Windows and get it to work.

Read More......
Template design by Amanda @ Blogger Buster