Python interface to Linux's input_event and uinput

A little while back I bought an ASRock 330HT as a media PC. Aside from the fan being a little noisier than I hoped, the remote control had no Linux driver so I bought a Hama MCE remote control after reading that it works well under Linux. Unfortunately, while it works fine under Linux, it's got hardcoded key values and not every key is unique. As an example the "i" info button is actually a prolonged right click, a couple of the keys send *exactly* the same keycodes as others (Play and Pause), and there are a bunch of buttons which generate Control-Shift-foo and Alt-bar and so on. I guess under Windows Media Center these all serve a specific purpose. Under Linux and its media center programs (such as XBMC) they don't (and XBMC's input layer is a bit restrictive).

I had my toys, but things weren't working exactly as I wanted. What's a guy to do? I got hacking, of course.

The Linux Input Subsystem is pretty clean nowadays and detecting the correct device and reading a few bytes from /dev/input/eventXX isn't all that hard. Within a couple of hours I was reading the bytes from the remote and pretty printing them as I received them. Unfortunately, this lead to the realisation (as shown above) that the remote's a little screwy and that a few hacks would be necessary to make things work as I wanted. But I was having fun and I was learning something.

The next step was deciding how to use these key events. XBMC has an interface to LIRC and another chap had written a python script making the HAMA MCE remote produce LIRC events. I tried it, fixed some bugs, and it worked.. but it was unsatisfying.. the MCE remote also has a mouse cursor (there are two input devices generated - a mouse and a keyboard - but the mouse device also sends a few key events that I care about as well as the all-important info button).. I started to explore the uinput device which lets you create a fake input device and write to it. Figuring out how to initialise it was a little tricky but I found some similar code and worked it out.. after that it's just writing input events to the device.

My initial idea of just reading all input, munging a few things, and passing the remaining events directly through proved somewhat problematic. If you leave a stranded Control or Alt key pressed down then you have a serious problem and in my tests I had to kill my X session a few times. A better way is to read all the input and have a virtual keyboard that handles the MOD keys, does the processing of normal keystrokes, does the translations, and then converts the translated events back into input events for uinput, ensuring there're no dangling modkeys.

The final step was to create a versatile translated step. I decided that I wanted a configuration file, instead of coding the translations all in python.

Here's some snippets from my config file:

# simple 1-1 translation
KEY_HOMEPAGE-down = send KEY_ESC-down
KEY_HOMEPAGE-up = send KEY_ESC-up
# the info button/right click magic
BTN_RIGHT-down = set rightclick time.time()
BTN_RIGHT-up = if (time.time()-rightclick) > 0.3; send KEY_I; else; send BTN_RIGHT
# compound key sequence example
Alt-KEY_F4-down = wait
Alt-KEY_F4-down KEY_F4-up = send KEY_ESC; clear

The wait action means to add the current key event to the match criteria for the next keystroke. clear then clear's the list.

Code will be online soon at http://github.com/rmt/pyinputevent/

— by Robert Thomson, created 3rd Feb, 2010, last modified 4th Feb, 2010 | Tags: Tech

 Python's SimpleHTTPServer and unnecessarily fragmented HTTP sessions..

A couple of months ago I discovered the joys of an Internet Explorer bug revolving around HTTP.. If a HTTP redirect is returned from a server but the Location: header is not in the same TCP packet, Internet Explorer would have some serious issues. This seems to affect MSIE6, MSIE7, & MSIE8. This suggests some poor separation of the network layers in Windows & IE, but it also highlighted the strangeness of SimpleHTTPServer's implementation, which is used by paste's default server.

Every time it sends a header, it flushes the buffer.. the end result is that you often get one TCP packet for each header, and then the data afterwards.. obviously this isn't the most efficient use of the network. Headers and data should be buffered before sending.

The solution was to switch to using FLUP & FastCGI for both the testing and production environments. We're using Nginx, and this combination proved very robust. Wireshark certainly showed much nicer results.

— by Robert Thomson, created 19th Dec, 2009, last modified 19th Dec, 2009 | Tags: Tech

 Hardware Splurge!

I decided to splurge and purchase this baby: The AsRock ION 330 HT for all my media center needs.

People seem to have got it working fine with Linux, except for the remote control... but I'll look into that.

Now, all I need is a TV (or monitor), and a keyboard+mouse for it. Time to head to Saturn and start evaluating TV sets.

Update: It arrived today, and I didn't have a keyboard nor screen for it... I've now bought a decent Samsung monitor and a cheap microsoft wireless keyboard+mouse. The TV can come in a little while - too big a purchase to buy under pressure.

— by Robert Thomson, created 21st Nov, 2009, last modified 25th Nov, 2009 | Tags: Tech

 Got Sofa?

WE DO! 8-)

Tonight we received two lovely leather sofas and a matching armchair.. and a dining room table..

Sophia's aunt & uncle bought some new sofas, and they asked if we wanted theirs.. Naturally, we replied with an emphatic "Yes!" We initially wanted to buy a Sofa-Bed, but we couldn't find one that we liked (for less than €800).. We looked in quite a few places.. so we started to look for normal Sofas that someone could sleep on. Yesterday, I suggested that we start considering second hand sofas, and today we get a phone call. :-)

So, we now have a complete set of loungeroom furniture, for just the cost of delivery. (And the cost of repairs to some plaster & paint, but that's a lot less than it would've cost to get the furniture, and now I can learn how to repair plaster damage! .. Yes, I'm an eternal optimist. :-)

— by Robert Thomson, created 6th Nov, 2009, last modified 6th Nov, 2009 | Tags: World

 2 weeks in the apartment now..

It's been almost two weeks since we moved into the apartment.. It's looking okay, but we still have unpacked boxes and bags full of clothes. We still need to buy some cupboards (and surface area) for the kitchen, a sofa, and a wardrobe for me.. some nicer ceiling lights would be good too. Once we have the sofa, we should be ready for visitors. :-)

— by Robert Thomson, created 3rd Nov, 2009, last modified 3rd Nov, 2009 | Tags: World

 We now have an apartment. :-)

I finally have keys to put on my keyring again.. We just have to choose a moving company now.. hopefully in under 2 weeks we'll be in.

— by Robert Thomson, created 14th Oct, 2009, last modified 14th Oct, 2009 | Tags: World

 Django: Forcing a Multiple Choice Widget into a delimited CharField

This works, but is there a better way, like only modifying a Widget or a Field?

class TextCheckboxSelectMultiple(widgets.CheckboxSelectMultiple):
    """
    Set checked values based on a comma separated list instead of a python list
    """
    def render(self, name, value, **kwargs):
        if isinstance(value, basestring):
            value = value.split(",")
        return super(TextCheckboxSelectMultiple, self).render(name, value, **kwargs)

class TextMultiField(forms.MultipleChoiceField):
    """
    Work in conjunction with TextCheckboxSelectMultiple to store a
    comma separated list of multiple choice values in a CharField/TextField
    """
    widget = TextCheckboxSelectMultiple
    def clean(self, value):
        val = super(TextMultiField, self).clean(value)
        return ",".join(val)
— by Rob, created 15th Sep, 2009, last modified 15th Sep, 2009 | Tags: Tech

 We're in Berlin!

We've been in Berlin for a little over a week now. We've mostly recovered from the sunburn we got in Taormina (it's all too easy to get sunburnt when you have clouds and a pool), and I'm almost recovered from the stresses of Etna. It was a fantastic experience though.

Right now, I'm trying to juggle work (finishing off projects from before the holiday) and apartment hunting. Oh yeah, Sophia got accepted into FU Berlin, the University she wanted to change to, so she's now in the progress of switching and she has to give notice on her apartment in Passau, and we have to arrange transport for her goods. I think it will be an expensive affair, this moving business. But I'm looking forward to having a Zuhause again. In every place that I've stayed since 2004, I've treated it as temporary lodgings, so I didn't really settle down.

I'm also deciding whether I want to find a proper job here and go mainstream, or continue contracting.. Or maybe both.. I think it will come down to a combination of money and life satisfaction in the end. I can afford to wait for the right opportunity, though.

— by Robert Thomson, created 11th Sep, 2009, last modified 11th Sep, 2009 | Tags: World

 Second Travel Report

2. September

Catania's a nice city - a real city - not too much visible tourism. Still things to do and see, if you are willing to brave the heat. The hostel was quite good - simply a modified apartment run by an italian couple, but it was a good price, had working aircon, and for a reasonable fee we could make use of the kitchen for cooking.

We went to the Volcano, Etna, yesterday. Absolutely amazing. We went right to the top, and looked into the big crater. We had perfect weather and volcanic conditions. We could see a long way down, because the gases weren't too thick. Smelt awful though. The whole volcano was like a black desert. In some places, you'd sink 30cm or more into the "sand" when walking.

28. August

Syracuse good. Taormina touristy. We're in Catania since yesterday.

18. August

Bit of a gap in my writings, but here goes. Palermo was great, but we spent too long there, and/or didn't take advantage of the nearby opportunities there.

We found a nice cheap outdoor restaurant where we treated our taste buds to many sicilian specialties. We ate there almost daily, and said an almost teary goodbye to our regular waiter, Vincenzo, the day before we left.

The shopping opportunities are quite good there. There are some nice beaches just outside of Palermo, which we failed to visit.

Trapani was pleasant. We changed from our out of the way hostel to a hotel at the last minute, and from then on Trapani was great. We went to the small island of Levanzo first, lost the trail trying to find the main grotto there, so backtracked and found our way to a smaller grotto, where we swam and took in some sun before heading to one of the very few local restaurants/bars, where we ate pizza before catching the ferry back.

The second day in Trapani we visited the hilltop city of Erice, and the ruins of the temple there, before returning to the city, catching the afternoon sun and watching the sunset with our plastic cups full of red wine, and finally a walk through the city in the evening.

Because Saturday, August 15. was a public holiday, we opted to take a train back to Palermo, and then down to Agrigento instead of taking the one and only bus in the evening.

Agrigento failed initially to make a good impression, largely to do with the public holiday and sunday, and the initially malfunctioning fan in the room (we had it replaced at 11pm when we couldn't sleep and I went to find the hostelkeeper with murderous thoughts, but he had a spare, lucky for him) Our local take away pizza store did make excellent pizza, though, so we enjoyed that the first night on a nearby bench overlooking the all-but deserted street and some trashcans. Luckily we were in good company. On Sunday we visited the Valley of the Temples, which was indeed impressive. Amazingly well preserved. A little warm, though, as most of this holiday has been so far. We went to the beach afterwards, but didn't want to swim or set foot on the sand until later in the day, so we walked for a bit, eventually settling for a little beachside cafe with umbrellas. They have chip-patties in Sicily. Oh how I've missed them.

The second day we wanted to visit "le scale dei turchi" (the turkish steps), and assumed it woud be an easy trip. After chilling in the morning, we caught a bus to Realmonte, then we walked for 1 hour in the midday-sun to the stairs, because the next bus was still 1.5 hours away and we were told it would take 30 minutes. There were no cafe's in-between to buy more water, but it was mostly downhill. We made it, drank lots of water, took some photos on the steps, waded in the ocean, and then decided we didn't have time to stay longer if we had to walk back too, so went on our way. 10 minutes out we asked a man on a motorbike if he knew the number for a taxi service. He told us there was no service because it's such a small town, but he called a friend of his with a car and negotiated a fee. 25 minutes later we were enjoying a beer at the caffé next to the bus stop, with 40 minutes to spare until the last bus back to Agrigento. The bus came late, and our taxi driver stopped on his motorbike to see if everything was ok, but we made it back ok. So - Agrigento is good for public transport to the temples, and ok to its beaches, but you want a car for anything else. A motorbike would be ok too, but don't expect to be able to hire one there.

Right now we're on a train to Catania, and we'll catch another train later to Syracuse. The hotel looks ok, but we'll see!

At the Hotel. It looks great! The aircon's on and we'll shower before taking off to explore the old city at night. I love places like this. New plan - if the hostels aren't significantly less than hotels, just stay at a hotel!

7. August

First day in Palermo was a success. It was a bit of a walk from the port to the hostel - different port than we thought. But we walked it anyway, getting directions from friendly natives.

— by Robert Thomson, created 2nd Sep, 2009, last modified 11th Sep, 2009 | Tags: World

 Travel Report

6. August, 5.30am

The ferry from Sorrento to Naples was faaaast - on a hydrofoil - it only took 30 minutes, which was nice. But we ended up with 5 hours in Naples. It was better this time - different part of the city. We enjoyed a spicy pizza for lunch, visited an Internet cafe, and then a couple of cafe's before embarking the ship.

Dinner was funny. We pre-booked the cheapest dinner on the website along with our tickets (choices were none, a cheap pizza menu, or one of two expensive menu's), but we must have been the only people to have done that because nobody knew what to do. It involved a lot of running around and asking questions and a special exception for us. Tutto casino, tutto normale. Next time we'll know that we don't need to pre-order.

I slept well for a while tonight, but Sophia not so well. We'll get ready now, and we'll go to watch the ship come into port in a few. Must do washing soon. But otherwise we'll just spend the day in Palermo.

4. August

We went to the island of Capri today. Wow - stunning - I only wish I had enough money to afford more than one cup of coffee per day there though! The boat trip was quite nice, but I prefer larger boats against potential sea sickness. We walked up to Capri city from Marina Picola, where we arrived, and spent some time getting our bearings. We then found a cafe out of the main tourist zone (hoping it would be affordable - alas not - €3 for an espresso, when we got the bill) and a supermarket (normal prices, mostly). We wandered up a hill hoping to hit Salto di Tiberio, where Tiberius apparently threw his (usually very young) ex's off the cliff. We didn't find it, but we did find the Belvedere, which was breathtaking. The blue waters near the island make for great photos (forthcoming). Afterwards we spent a while at the beach near the port. Rocks instead of sand, but great, and a very picturesque backdrop. We saw a few grottos from the boat, but we didn't go into any (and the blue grotto was closed to boats because of choppy waters, but a few people swam in, some sustaining a few scratches). A great day. Tomorrow, we have to go to Naples (by ferry hopefully), then from there to Palermo.

3. August

Third day involved a trip to Amalfi. 2hr bus trip, although it's only 30km away, it was a little hellish with the inadequate aircon. Hot air blowing on our heads - yet better than no aircon. And those mountainous corners! Italians beep before going around a blind corner, and don't slow down very much at all. Can't imagine the number of accidents there are, even for Italian trained drivers. Amalfi itself is small and pretty. The history is more interesting than the tourist city it has become. But we found a small normal priced pizzeria to enjoy a lunchtime snack. We're catching a boat back to Sorrento in a few minutes. Should be faster and more comfortable thana return bus trip. And we'll see the coastline better.

End of the day. Ok - forget the bus. If you go, pay extra for a ferry bothways. Preferably one or both ways slow. It takes about 2 hours on a slow ferry, but the coastline is magnificent. We had deck chairs undercover but in the open facing the coast. Amazing. We even dozed off for a while. I think we'll opt for a ferry to Naples port instead of catching the train on Wednesday too. That way we'll also skip the dreck of the city and have no hassles finding the port there.

2. August

Travel from Perugia to Naples was nightmarish. We arrived too late for our next connection.. But it too was late.. So we ran to catch it, but had no water. We waited for 30 minutes in an overcrowded entrance while the sign always said 5 minutes until departure. Italian trains leave much to be desired. Berlusconi is no Mussolini. From Naples to Sorrento was no problem, just on a very slow local train. We failed to find the bus stop taking us to our hostel though. So we caught a taxi for €20.

We stayed in Sorrento the first day, and we quite like it. Beautiful coastline, and obviously benifiting from the tourist industry. But the local supermarket we found was better and cheaper than the small one in Perugia's center. Can't wait for Germany again. We did a lot of walking, bought a travel chess/backgammon set, and found a small shop selling cheap beer by a park before returning to our campsite and cooking dinner - a great first day of the holiday.

Our second day was less thrilling, however. Too hot, and we went to see Herculaneum, then Naples. Too hot for Herculaneum, but very interesting. Naples is north africa, though, and I'm not referring to the street vendors. Beautiful old buildings, but the poverty shines through. Cheap clothes shopping on Corso Umberto 1 though.

— by Robert Thomson, created 6th Aug, 2009, last modified 11th Sep, 2009 | Tags: World