Sunday, 15 January 2012

Recycling Smoke Alarms

We all know that we should have smoke alarms fitted in our homes. Those alarms can be damaged and will need replacing every ten years or so anyway. So what do you do with the old ones? Chuck them in the bin? Well, the fact that they are the subject of a best practice guide on the National Household Hazardous Waste Forum suggests that this is probably not the right solution. And indeed, looking at the back of mine, I can see why:

The back of my smoke alarm showing that it is a ionization alarm that contains a small amount of radioactive Americium 241

Ionization smoke alarms contain a small amount of radioactive material, Americium 241. Looking back at the best practice guide above, there are apparently three ways to deal with it:

  1. By a person authorised under section 13 of the Radioactive Substances Act 1993,
  2. By returning it to the manufacturer,
  3. By chucking it in the bin as long as you don't chuck in other radioactive waste and you only throw away one smoke alarm per bin bag.

Option 3 doesn't sound like recycling, while I don't know anybody who can help me with option 1. So that leaves option 2. As I've got the manufacturer's details on the back of the alarm, and their address is confirmed on their web site, that smoke alarm is going to find itself put into a jiffy bag, back to where it came from.

Note that there is another type of smoke alarms: photoelectric ones. They do not contain any dangerous material so are probably safer to dispose of. However, they are geared to detect different types of fires so for maximum protection you should have a combination of both photoelectric and ionization alarms.

For more questions on recycling stuff, have a look at the Recycle This web site.

Update

As very sensibly pointed out by Earth Notes, there may be an even easier way to deal with them: under the WEEE Directive, you can probably just give the old one to the retailer when you buy a new one.

Friday, 13 January 2012

Yodel redefines the word Safe while John Lewis redefines Eco-Friendly

Last week-end I visited the John Lewis web site and bought a couple of Buiani folding chairs. I was advised that they would be delivered within 7 days via a standard delivery service, as opposed to the specialist delivery service you get when you buy larger items and who are very good.

So when I came back home on Wednesday night, I found a very large (more on that later) cardboard box outside my front door and in the letter box was this delivery notice:

Yodel delivery notice

Yodel delivery notice

You will note how they checked the a safe place box. They actually left the parcel outside my front door. Luckily I live in a relatively safe place so theft is unlikely. On the other hand, leaving an unprotected cardboard box outside, in London, in January, with something inside that may suffer from getting wet strikes me as a tad optimistic. Or did check the weather forecast before leaving the box outside?

Another thing that I found rather puzzling was the size of the box. It would have made sense had it contained normal chairs. But folding ones: surely they'd be shipped folded? All was revealed when I opened the box:

The big box

The big box

You will note the green stickers on the left side of the chairs with the FSC logo advising me that those chairs are made from wood from well-managed forests. Brilliant! Unfortunately the amount of Air Pad packaging filling in the box probably offsets all eco-friendly credentials imparted by the FSC logo. On the plus side, it probably means that I now have enough air pads to send presents to my two nieces until they reach adult age (uncles are meant to spoil nieces and nephews, that's part of the job description).

Friday, 30 December 2011

Non-Exchangeable, Non-Refundable

I travelled on Eurostar today and learnt something about non-exchangeable, non-refundable tickets in the process so thought I'd share in case it can be useful to someone else. Eurostar sells several types of tickets in several classes (Standard, Standard Premier and Business Premier). The higher the class and the more flexible the ticket, the greater the price. So the cheapest tickets are non-exchangeable, non-refundable standard class tickets. Once bought, such tickets cannot be exchanged against another on a different train, cannot be refunded in case you don't want to travel anymore but they can most certainly be upgraded to the next travel class up, as I did today. Of course, it requires you paying an upgrade price, which may not be cheap. The fact that you can upgrade any ticket makes sense because:

  • An upgrade doesn't fall under the non-refundable rule because you're not asking for a refund, and in fact you're paying extra for the upgrade;
  • It doesn't fall under the non-exchangeable rule either because you're not asking for an exchange as you still want to travel on the same train at the same date: you just want to upgrade your existing ticket.

So if you ask general information staff in the station and are told that you cannot upgrade your ticket, don't take their word for it, go to the sales counter. The only reason why you would not be able to upgrade (and pay Eurostar more money) is if the travel class you want to upgrade to is already fully booked on your train.

Saturday, 28 May 2011

Crash of the Day

Received today from a colleague:

Please note that if somebody opens Build log excel in Microsoft excel 2007 and updates it while a filter put on any column, the file crashes.

So please avoid updating the build log in Microsoft excel 2007.

So we're talking about a fairy simple file created in Excel 2003 that crashes Excel 2007 if you try to update it while a filter is set on any column... Sigh...

Thursday, 21 April 2011

MS Works to MS Word: LibreOffice to the Rescue

I am at my mum's for Easter and one of the first things she asked me to look at had to do with her computer. She had this document that she wrote using Microsoft Works aeons ago that she wanted to open again. Of course, she's now using Microsoft Word and Word has no idea how to open Works files, even though both products are produced from the same software company.

What to do? The answer is very simple but rather counter-intuitive for people not used to open source software: LibreOffice. From the point of view of someone who lives in a world where closed source is the norm, how can a free office wannabe solve a problem that the mighty MS Office can't solve? Simple: as highlighted by Michael Meeks at FOSDEM earlier this year, LibreOffice wants to have the largest possible list of supported file formats so that they can support their users in reading their old documents stored in long forgotten format and hopefully migrate them to modern and preferably open document formats. As a result, LibreOffice supports MS Works and MS Word out of the box.

So back to my mum's document, retrieving the content was then very easy: copy the document to a USB key, open it on my laptop using LibreOffice, save it again and copy the new document back to her PC. In this case, it meant saving it back as an MS Word document. In an ideal world, I would have saved it as ODF and installed LibreOffice on her computer but I'll leave that for another day.

So if you have any old document lying around that you can't open anymore, try LibreOffice first, you'll be surprised how many weird and wonderful formats it supports. If it still doesn't work, consider contributing a filter to the project or at least reporting the issue and providing sample files so that the developers can build such a filter.

Tuesday, 1 February 2011

Outlook Error

In the meaningless error category, let me present today's effort by Microsoft Outlook:

Task 'Microsoft Exchange Server' reported error (0x8004010F): 'The operation failed. An object could not be found.'

Sunday, 30 January 2011

D-Bus Experiments in Vala

Most modern Linux desktop distributions now include D-Bus. It enables different applications in the same user session to communicate with each other or with system services. So I thought I'd experiment with D-Bus using Vala and starting with the published example.

Example 1: Ping Loop

I started with a simple ping client and server based on the example above, the main difference being that I added a loop in the client. The server code takes a message and an integer, prints out the message and the received integer, then adds one to the integer before returning the result:

[DBus (name = "org.example.Demo")]
public class DemoServer : Object {

    public int ping (string msg, int i) {
        stdout.printf ("%s [%d]\n", msg, i);
        return i+1;
    }
}

void on_bus_aquired (DBusConnection conn) {
    try {
        conn.register_object ("/org/example/demo",
            new DemoServer ());
    } catch (IOError e) {
        stderr.printf ("Could not register service\n");
    }
}

void main () {
    Bus.own_name (
        BusType.SESSION, "org.example.Demo",
        BusNameOwnerFlags.NONE,
        on_bus_aquired,
        () => {},
        () => stderr.printf ("Could not aquire name\n"));

    new MainLoop ().run ();
}

server.vala

And the client simply queries the server in a loop every second and prints out the input and output values:

[DBus (name = "org.example.Demo")]
interface DemoClient : Object {
    public abstract int ping (string msg, int i)
        throws IOError;
}

void main () {
    int i = 1;
    int j;
    while(true) {
        try {
            DemoClient client = Bus.get_proxy_sync (
                BusType.SESSION, "org.example.Demo",
                "/org/example/demo");

            j = client.ping ("ping", i);
            stdout.printf ("%d => %d\n", i, j);
            i = j;

        } catch (IOError e) {
            stderr.printf ("%s\n", e.message);
        }
        Thread.usleep(1000000);
    }
}

client.vala

Compiling both programs requires the gio-2.0 package:

$ valac --pkg gio-2.0 server.vala
$ valac --pkg gio-2.0 client.vala

Start the server followed by the client in two separate terminal windows and you should see them exchange data.

Example 2: Graceful Termination

The problem with the code above is that if the server process terminates while the client is still running, an exception occurs and the client doesn't recover. It would be nice if we could get the client to terminate gracefully when the server stops. The Vala GDBus library provides the ability to detect when a service comes up or is brought down using watches. When you setup a watch, you need a callback method for the watch to call. That callback method needs to be called on a different thread than the main client thread. This is handled by the MainLoop class but it means that the core client loop needs to be run in its own thread, which complicates the client code a bit. In the code below, the client code has been encapsulated into a Demo class and the client loop thread is controlled using a simple boolean attribute.

[DBus (name = "org.example.Demo")]
interface DemoClient : Object {
    public abstract int ping (string msg, int i)
        throws IOError;
}

public class Demo : Object {
    private bool server_up = true;
    
    private DemoClient client;
    
    private uint watch;
    
    private MainLoop main_loop;
    
    public Demo() {
        try {
            watch = Bus.watch_name(
                BusType.SESSION,
                "org.example.Demo",
                BusNameWatcherFlags.AUTO_START,
                () => {},
                on_name_vanished
            );
            client = Bus.get_proxy_sync (
                BusType.SESSION,
                "org.example.Demo",
                "/org/example/demo");
            server_up = true;
        } catch (IOError e) {
            stderr.printf ("%s\n", e.message);
            server_up = false;
        }
    }
    
    public void start() {
        main_loop = new MainLoop();
        Thread.create(() => {
            run();
            return null;
        }, false);
        main_loop.run();
    }
    
    public void run() {
        int i = 1;
        int j;
        while(server_up) {
            try {
                j = client.ping ("ping", i);
                stdout.printf ("%d => %d\n", i, j);
                i = j;
            } catch (IOError e) {
                stderr.printf ("%s\n", e.message);
            }
            if (server_up)
                Thread.usleep(1000000);
        }
        main_loop.quit();
    }
    
    void on_name_vanished(DBusConnection conn, string name) {
        stdout.printf ("%s vanished, closing down.\n", name);
        server_up = false;
    }
}

void main () {
    Demo demo = new Demo();
    demo.start();
}

client.vala

The server code is unchanged.

With this version, once the server and client are started, stopping the server through CTRL-C will notify the client which will then stop gracefully. You can even have multiple clients, they will all stop in the same way. The advantage of doing this is that the client has a chance to clean up any resource it holds before stopping.

Example 3: Peers and Service Migration

All of the above is great and we can now design client programs that share a common service. But when dealing with software that is started by the user, the client/server model is not always the best option: you need to ensure that the server is started before any client is and that it is only stopped after the last client has stopped. And what happens is the server fails? What would be really nice is if we could have peers: no difference between client and server, just a single executable that can be run multiple times, the first process to start acts as a server for the other ones and when it stops responsibility for the service is taken over by one of the other processes if any are still running. The last process to terminate closes the service. D-Bus makes it easy to implement for the following reasons:

  • Only one process can own a service;
  • All service calls go via D-Bus so a client process will not notice if the server process actually changes, as long as the service is still available;
  • The client and server processes can be the same process or different processes, it makes no difference to the client.

Therefore, the implementation of the peer program is simple:

  • Start the server, followed by the client and ignore any failure in starting the server: if another process has already started, the service will be available to the client;
  • When the peer is notified of the loss of service, try to start the server but ignore any failure: if another process was notified first, it will have started the server and there will be no interruption in service for the client thread.

We only need a single Vala file to implement the peer:

[DBus (name = "org.example.Demo")]
interface DemoClient : Object {
    public abstract int ping (string msg, int i)
        throws IOError;
}

[DBus (name = "org.example.Demo")]
public class DemoServer : Object {

    public int ping (string msg, int i) {
        stdout.printf ("%s [%d]\n", msg, i);
        return i+1;
    }
}

public class Demo : Object {
    private DemoClient client;
    
    private uint watch;
    
    public Demo() {
        // nothing to initialise
    }
    
    public void start() {
        start_server();
        start_client();
        new MainLoop().run();
    }
    
    public void start_client() {
        try {
            watch = Bus.watch_name(
                BusType.SESSION,
                "org.example.Demo",
                BusNameWatcherFlags.AUTO_START,
                on_name_appeared,
                on_name_vanished
            );
            client = Bus.get_proxy_sync (
                BusType.SESSION,
                "org.example.Demo",
                "/org/example/demo");
            Thread.create(() => {
                run_client();
                return null;
            }, false);
        } catch (IOError e) {
            stderr.printf ("Could not create proxy\n");
        }
    }
    
    public void run_client() {
        int i = 1;
        int j;
        while(true) {
            try {
                j = client.ping ("ping", i);
                stdout.printf ("%d => %d\n", i, j);
                i = j;
            } catch (IOError e) {
                stderr.printf ("Could not send message\n");
            }
            Thread.usleep(1000000);
        }
    }
    
    public void start_server() {
        Bus.own_name (
            BusType.SESSION,
            "org.example.Demo",
            BusNameOwnerFlags.NONE,
            on_bus_aquired,
            () => stderr.printf ("Name aquired\n"),
            () => stderr.printf ("Could not aquire name\n"));
    }
    
    void on_name_appeared(DBusConnection conn, string name) {
        stdout.printf ("%s appeared.\n", name);
    }
    
    void on_name_vanished(DBusConnection conn, string name) {
        stdout.printf (
            "%s vanished, attempting to start server.\n",
            name);
        start_server();
    }

    void on_bus_aquired (DBusConnection conn) {
        try {
            conn.register_object (
                "/org/example/demo",
                new DemoServer ());
        } catch (IOError e) {
            stderr.printf ("Could not register service\n");
        }
    }
}

void main () {
    Demo demo = new Demo();
    demo.start();
}

peer.vala

Start several peers in different terminal windows, at least 3 or 4. You will notice that the first process starts a server thread that all client threads connect to. When the process that provides the service terminates, the next process in the chain takes over the responsibility for the service. And finally, when the last process terminates, the service is closed.

Note that if you want to check D-Bus activity while running the programs in this introduction, you can either install the D-Feet tool or run dbus-monitor from the command line.

The Devil's in the Details

A good piece of software should make boring, repetitive and error prone tasks easy. One of them that photographers face regularly is resizing a batch of images. The typical situation is the day after a party when everybody wants a copy of the photos you took, either by email or on a CD. Quite often, people don't want the full size but they'd quite like copies of all the photos. I found myself in such a situation on New Year's Day: 150-odd photos that needed resizing and burning to a CD. Luckily, I had my trusty Ubuntu laptop running Shotwell. Shotwell does exactly the right thing when you want to export photos: it allows you to resize them all to a size that you specify, as shown in the dialog below:

Shotwell's export dialog

Shotwell's export dialog

My laptop took a few minutes to resize all 150 photos when I exported them. Next to me was a friend who uses a proprietary operating system that shall remain nameless and who commented: Wow, that's cool! When I do that, I have to resize each photo manually and it takes ages! Sometimes the best features are the simple ones.

Monday, 6 December 2010

Web accessibility – Code of practice

BSi have just released a new British Standard, BS 8878:2010 Web accessibility – Code of practice. First things first, this is not another set of web accessibility guidelines. This document is meant to complement existing guidelines such as WCAG and provide a framework for companies to implement accessible web products. It recognises that accessibility goes well beyond HTML tags and requires the right processes to be in place in the organisation, from planning for accessibility to delivering and testing it. To quote from the standard itself:

This British Standard sets a standard for the quality of the process of creating accessible web products, rather than a standard for the quality of accessibility of web products resulting from it.

I've only had time to quickly browse through it and I'll do a more thorough write-up when I can. First impressions are very good and it's no surprise considering that AbilityNet, who are one of the most knowledgeable organisations on the subject, made significant contributions to it. The document is clearly and concisely written, there's no jargon unless absolutely necessary and it includes an awful lot of useful information, such as how to build a business case for accessibility, what processes to put in place to deliver it, how to make justifiable decisions on accessibility, write an accessibility policy, etc. It is also very pragmatic and concentrates on the ultimate goal, delivering accessibility efficiently, rather than on specific processes and guidelines.

So if you're about to start a new web project, grab a copy of BS 8878 and ensure that what you deliver is accessible to all: there is no excuse!

Sunday, 7 November 2010

Reading Paradise... or DRM Hell?

New Toy

Yesterday, I bought myself a Sony PRS-650 Reader Touch Edition as a belated birthday present. I could have bought the new Kindle, as there are lots of adverts for it in the tube, it's cheaper and it has Wi-Fi. I went for the Sony PRS reader instead because I don't really need Wi-Fi and it has a touch screen, which means that it's not encumbered by a keyboard and is therefore a lot smaller for the same screen size (6" display). The Sony device does really fit in a pocket as it's about the size of a very thin paperback. If you want even smaller, you can get the Pocket edition, a.k.a. PRS-350.

So the first thing I did was go to Waterstone's as I know they stock the PRS-650. Unfortunately, between two shops I visited, they had 5 demo devices, only one of which seemed to work and no staff in sight to help. So I ended up going to the Sony Centre in Tottenham Court Road, where I was served by very helpful staff who were happy to answer any question and demo the device. What's more, if you buy the device from Sony direct, you can also have it in a very nice red colour that is much less boring than the black and grey offered by Waterstone's.

Back home, I installed calibre from the Ubuntu repositories and, lo and behold, my new toy was immediately recognised and supported out of the box! On a side note, the connection is a standard Micro-B USB connector, which means that the cable to connect it to the computer and charge it is the same as with my Nokia N900.

But getting the device to work is only the start, you then need to load it with books. The PRS-650 supports a variety of file formats and whatever it doesn't support, calibre should be able to convert to EPUB. So you basically need to find books to download. Here's a quick list of what I tried.

The Good

  • The first thing to do when you get your Sony reader is to register it on My Sony, you will then be able to download 100 free classic books in Sony's own format, including titles like Don Quixote, Gulliver's Travels, The Importance of Being Earnest or David Copperfield.
  • If you want more classics, Project Gutenberg is the place to go to: thousands of books in a variety of languages for which the copyright has expired.
  • If you are into science fiction, Baen Publishing offer most of their titles as non-DRM e-books that you can then load into calibre. They even offer some of them for free through their free library.
  • For technical books, both The Pragmatic Bookshelf and O'Reilly offer their titles in a variety of formats without DRM.

The Bad

  • Waterstone's, WHSmith, Penguin, rbooks (Random House) and kobo will only sell you DRM-encumbered books that require Adobe Digital Editions, which of course doesn't exist for Linux. Apparently it works well under WINE but Adobe won't offer the Windows download if you connect to their web site using Ubuntu. It also means that you are forced to use a particular piece of software, which may or may not be practical. Add to this that, apart from kobo, the other web sites are not very forthcoming with that information so you may end up buying an e-book that you can't download and only discover that after you've actually paid for it!
  • Amazon, quite predictably, will only sell you books for the Kindle but won't let you download the file, you have to use either a Kindle device or the Kindle software, which only works on Mac OS-X or Windows and won't work with the Sony reader anyway.

The Ugly

  • Foyles and Books, etc. have a web site that seems to be able to show me e-books or fiction books but not fiction e-books so I was unable to find what I wanted and eventually gave up.
  • Blackwell's seem to have a very limited list of titles available as e-books so I gave up and also failed to find out any information on the e-book formats they offer and whether they were DRM-encumbered.

It looks like the publishing industry is following blindly in the footsteps of the music industry, leaving very few options for Linux users to buy e-books legally. And as usual it's not a question of hardware support, it's all about restricting what customers can do with the media they purchase. Surely, there must be a better solution than this mess?

Update 1

I originally thought that The Book Depository didn't offer e-books but in fact they do and, like a number of others, only sell DRM-encumbered books, require you to use Adobe Digital Editions and don't tell you until you've actually bought the book. So that's one more candidate for the bad list above.

Update 2

I mistakenly said above that The Book Depository didn't warn you about the requirement for Adobe Digital Editions. In fact they do, just not in a place where I was expecting it so I didn't notice it. As a result they won't refund you if you mistakenly buy an e-book that you can't download.

WHSmith also mention that you need Adobe Digital Editions. However, they do that at the very bottom of the book's page below adverts for other e-books and customer reviews, so not quite as prominently as you would expect. They won't refund you either if you make a mistake.

rBooks will refund you if you ask them politely.

Update 3

Waterstone's will refund you too if you ask politely.