Friday, January 28, 2011

Zeemote controller on Android

This blog post is about Bluez IME for Android.

I have recently purchased a Zeemote JS 1 controller from Amazon. I wanted to use it with my HTC Desire phone, which is running Android 2.2.

Unfortunately the Zeemote came with no drivers, probably because it was priced at £3 and was shipped in a bubble wrap envelope :). This was a bit weird, because the Zeemote website claims that Android 1.6 to 2.0+.

Looking at the Android market, I could find two drivers. One was called something like Zeemote JS1, and did not work on the HTC Desire (it appears to have been removed). The other is called GamePro, and did work, but costs $10, which is more than twice the price of the controller itself. Besides, the whole purchase seems a bit dodgy with only a forum for a webpage. I also believe that this is not allowed due to Android Market publisher agreements 3.3.

So I set out figuring out how to implement a working Zeemote driver. First block in the road is that Android prevents emulated hardware keypresses for security reasons. This can be handled by creating a custom Input Method Editor (IME), which can then send key press events.

Next block was that I got no manual of any kind, so I could only pair with the device. Fortunately, there was a post here that explained how to connect to the Zeemote with Android Bluetooth, and it works for HTC Desire.

Upon connection, the device starts dumping some data, probably describing the device and its capabilities. After this, there is no communication until you activate the device. By looking at the transmitted data, I was able to guess the format. Doing this took about 3 hours, plus 2 hours for implementing the IME, so a total of 5 hours for getting a working Zeemote driver.

I then figured that others would probably have the same issues as I did, so I spent a few more hours, creating a settings interface.

I have also purchased a Bluetooth keyboard, which I am hoping to get working under the same framework, but no luck so far. The code is flexible enough to allow other devices to be supported.

Then I realized that if you search Android Market for Zeemote, most of the results are games claiming to support Zeemote. This seems to indicate that a lot of people have been through the same ordeal as me, and likely have to update their app to support whatever changes there are.

I then spent a few more hours isolating the core of the application as a service. The cool thing about this is that other apps can freely activate the service, and register for events. In effect, any app can support Zeemote just by invoking the service (provided that it is installed), and all updates can be done within the driver itself.

I have packaged the app up and published it on Android Market for free, just search for Bluez IME.

As always, I have released the source under LGPL. If you are interested in the source code, visit the android-bluez-ime site. You can also download the package from there but I recommend using Market if possible, as that will ensure that you are automatically updated.

On the android-bluez-ime site, you can also see the source code for a test application that uses the Bluez IME service. Note that the test application does not require Bluetooth permissions, as that is handled by the driver.

If you have questions or comments related to Bluez IME, please create an issue on the website.

Friday, January 14, 2011

How to not match a string with regular expressions

Regular expressions are a robust method for matching strings, and finding patterns in text. But it takes some time to learn, for instance, consider extracting all strings in quotations from this text:
a "sample" text "fragment".

The initial attempt is something like this:

But since regular expressions use greedy matching, it will match:
"sample" text "fragment"

The fix for this would be to change any character (.) to match any character except " ([^"]):

And this solution works, but what if the delimiter is a string and not just a single character? For example:
a <!--sample--> text <!--fragment-->.

You cannot use any character except, you need a any character except one that is followed by, and this is called negative lookahead.

To match any character except one that is followed by --> you can use the following expression:

Applying this on the sample text matches all text except the e and t in sample and fragment respectively. If we want the entire inner text matched, we need to add the excluded character:

This will match the entire text, so now we can apply the delimiters:

Derek Slager has an online regular expression tester.

Monday, January 10, 2011

TortoiseSVN for Linux

I'm usually working cross-platform, and there are a few killer-apps that I am missing on Linux. One of the most annoying things were the absence of a TortoiseSVN like application.

If you have never heard of TortoiseSVN, it is an application that integrates into the windows explorer and shows overlays that indicate the SVN state of files. Compared to other SVN applications, this gives a really great overview of the current state. It is very fast to identify which files and folders that contains changes.

It also contains a number of context menus, so you can easily view the changes, revert them and so on.

On Linux I have used the commandline SVN tools, but it gives no overview. For instance, you cannot easily see which files that are not added to SVN. And just executing "svn add" will possibly add a number of files you do not want, and you have to revert it and so on.

There are some standalone apps, such as PySVN Workbench and RapidSVN which I have found quite a few bugs in. But even if those bugs were fixed, it is not integrated with the shell, and will always miss some option, eg. thumbnail view, permissions, copy actions, etc., and will never feel like an integrated part of the system.

But last week I discovered RabbitVCS (previously named NautiliusSVN). It does pretty much the same as TortoiseSVN, and places emblems on files and folders in Nautilus. There are some RabbitVCS screenshots here.

I have not used it extensively yet, so I am not sure how stable it is, but it looks REALLY promising. The RabbitVCS about page is a but outdated and states that only SVN and Nautilus are supported.

Unlike TortoiseSVN, there is a actually support for multiple VCS in the application, and I can confirm that it works just as well with Git, making it a replacement for TortoiseGit as well.

Looking at the code it seems that thunar is supported as well.

Monday, January 3, 2011

Java Grievances part 3

The previous Java posts were about the library, this post is about Java classes missing properties. This means that you have to write code like this in Java:
float adjustX = 0.5;
for(int i = 0; i < some_object.getRectangle().getPoints().size(); i++)
some_object.getRectangle().getPoints().get(i).getX() +
Where properties can make the same code much more readable:
float adjustX = 0.5;
for(int i = 0; i < some_object.Rectangle.Points.Size; i++)
some_object.Rectangle.Points[i].X += adjustX;

This can actually be implemented without changing the Java bytecode, simply by adopting a standard syntax, eg.:
public property X {
float getX() { return m_x; }
void setX(float value) { m_x = value; }

The compiler is then free to emit code without the property part. This will make this feature just as useless as generics currently are, unless the compiler also assumes that the common getX/setX function pairs can be used as a property. This means that all those old libraries will suddenly appear to have properties when they have not.

Such a syntactic sugar model doesn't break anything, not even reflection, as the methods are there just as they should be.

This is in fact how they are implemented in C#/VB and others, and allows interoperability with languages that have no property features. Unfortunately some people confuse properties with instance variables, which they are not. Properties are NOT a way to get out of proper class encapsulation. Properties are also more expensive than variables as they can validate the input/output, cause events etc. so you would still need both.