Wednesday, 21 July 2010

Windows 7 Jump List not appearing on Start Menu

I searched for hours and hours before finding this StackOverflow answer, which got me on the right path. If your app has a Jump List and it's appearing fine when right-clicking on the app's icon in the task bar, but it doesn't appear in a pop-out menu on the Start Menu, it's possible that this is because your start menu entry is a shortcut and you need to set that shortcut's AppUserModelID. If you don't do this, Windows doesn't realise that the shortcut has anything to do with your app.

If you're using Inno Setup as an installer, you just need to add an AppUserModelID: tag to the entry under [Icons] that creates your Start Menu icon.

Hopefully posting here will make the answer more easily Google-able for others.

Wednesday, 5 November 2008

World Time display in PHP and Javascript

We have a world clock on the wall in the office, displaying the times in 24 different world cities. Unfortunately, it's a (comparitively) cheap model that doesn't know about daylight saving time. (This may be a blessing - it certainly wouldn't know about rule changes for DST.) As a result, it ends up being an hour out of sync with the actual time in various cities. Whilst it's nice to know that the time in Anchorage might be 12:34, I figured it'd be more helpful to know what the time actually is.

Checking up on the displayed times manually seemed like a job only mildly more enjoyable than reading the thing's one-page user manual (which seems to have been translated from Chinese into English via Sanskrit by translators with only a passing knowledge of Chinese, English, Sanskrit or the concept of timekeeping). The quickest way would probably have been entering "time now <city>" into Google for each of the 24 cities. Instead, I've made a world clock script which shows me the current time in all 24 cities.

The script uses PHP to output (hopefully) correct timezone data. It uses JavaScript for all of the actual calculation. I'd have preferred using pure JavaScript, but JS doesn't give you data about timezone offsets other than for your own timezone. The script contains a list of cities, with name, latitude, longitude and timezone and places them automatically on the map, so it's easily customisable for anyone who has a similar need. The source and the world map it uses are linked below.

PHP/Javascript world clock script source
World map

Wednesday, 13 August 2008

JUnit 4.4: Why I don't like assertThat

A colleague pointed at the release notes for JUnit 4.4. He was really happy about the new assertThat. I've tried and tried, but I can't share his enthusiasm.

Here are their four examples from the release notes:
assertThat(x, is(3));
assertThat(x, is(not(4)));
assertThat(responseString, either(containsString("color")).or(containsString("colour")));
assertThat(myList, hasItem("3"));
And here is how I'd write that at the moment:
assertTrue("Unexpected value for x, was expecting 3", x==3);
assertTrue("x should not be 4",
x!=4);
assertTrue(
"responseString should contain color/colour", responseString.matches(".*colo(u)?r.*"));
assertTrue(
"Item 3 not present in myList", myList.contains("3"));

The release notes and my colleague both say that assertThat is shiny because it automatically outputs readable error messages. But I already write readable error messages. (Doesn't everybody? Who in their right mind decided that "AssertionError" with no extra text would help them later when the test failed?) Leaving aside the generic examples from the release notes, a typical message from one of my assertions would be more like "Order 1234: Buy Order's side was Sell instead of Buy". I'd argue that my error messages are more readable and more helpful.

Writing my own messages has the glorious side effect that the error message is documenting what I think the assertion is asserting. I'm effectively adding a comment to each assertion which can be checked by the poor soul who has to look through this stuff in 5 years' time when the test suddenly breaks.

The main reason I'm not a fan of assertThat, though, is that I've devoted a deal of brain space to boolean expressions in C-like languages and a deal more to Java's class libraries. Having done that, I instinctively dislike the idea of having to expend mental effort on internally translating someChar, is('b') into someChar=='b'. Even if it does give me vaguely readable error messages.

Monday, 11 August 2008

Siemens S685IP DECT IP Phone, S68H Handset

The short version, to save you reading the rest: the S685IP seems to work quite well. The S68H is.. less impressive.

The long version: I've had an S685IP (which comes with an S68H handset) and two additional S68H handsets for a week now. I'd realised that my fixed-line phone/DSL provider (Vodafone Germany, which on a technical level is run by Arcor) was actually using SIP for everything. The box that they provided me with is an integrated DSL modem, firewall and WLAN router - and also has analog and ISDN ports. It converts calls made over these ports into SIP calls. Since everything's using SIP anyway and since they make no secret of the address of their SIP gateway, a SIP phone seems like the best way forward.

I plugged in the S685IP and the handset that came with it for the first time and without me touching anything, the S68H was soon showing the weather for a selection of world cities. Which was nice. Configuring the S685IP to use Arcor's SIP gateway took a couple of tries, but was simple enough. I've included the settings below in case anyone wants to save those couple of tries.

After getting the SIP settings right, actual phone calls worked nicely. One of the reasons that I'd got the system, though, was its ability to display information on-screen as a screensaver. I saw it paging neatly through its weather in world cities and went off to visit gigaset.net, where you can configure what you'd like it to display. Puzzlingly, though, the amount that you can configure would be accurately described as "a tiny little bit". Gigaset.net offers you the option of: Weather for world cities, Weather for a (single) city of your choice, a horoscope (we shall speak no more of this), biorhythms (Really, Siemens needs to turn down the dosage on their employees' drugs. Or increase it.) and a custom RSS feed. OK, I thought, all is not lost, I'll give it a custom RSS feed. I can then arrange for the RSS feed I give it to display whatever information I want.

Turns out, the Custom RSS Feed option shows the text of the first item in the RSS feed. Or rather, it shows whatever of that text fits into the first 6 lines of the phone's display. Now, the phone's only got an 8-line display anyway, so I was never planning to read Proust on it. But if you've only got an 8-line display, using all of those 8 lines seems pretty important. And the other thing: whilst the gigaset.net weather display will happily scroll between different world cities every 90 seconds, with the custom RSS feed, you're stuck with the first item for at least half an hour at a time (because while the phone is asking gigaset.net for new info every 90 seconds, gigaset.net is only hitting the RSS page every 30 minutes). This... was not what I was looking for.

Lesser and/or saner people might at this point have given up, accepted the gigaset.net weather or returned the phone. Insaner people might have decided that what they were looking for in a phone was a biorhythm display. To each his own. I decided that I was going to make it work the way I wanted it to work. It turns out, this is possible. If you have a DNS server and a web server under your control. If you don't... have you ever considered having a horoscope displayed on your phone? Sorry.

So, assuming you do, arrange for your S685IP to point at your DNS server. Arrange for your DNS server to be authoritative for "info.gigaset.net" and make that name point at the address of your web server. Add a virtual host of that name to your webserver. Create a directory called "info". Get my request.do script and put it in the info directory. Arrange for ruby to be available and for your webserver to use it to execute the script. Or rewrite it in the language of your choice, it's not complicated stuff. You just need to output (a very limited dialect of) XHTML-MP.

My script pulls up the weather for today and tomorrow for the nearest large town from our local radio station and pulls up the top headline from a couple of news sites. Monday mornings and Friday evenings, when I have to drop my girlfriend off at and pick her up from the train station, it checks whether her train will be on time (and deactivates the other pages, to avoid having to wait until that page comes around). Being able to control which pages will appear on which weekdays and at what times makes things much more useful. Having the handset show a new page every 90 seconds vs. every half an hour is a no-brainer. Adding more stuff is easy. And I get to use all 8 lines of the display. I don't get to use colour or any more complicated XHTML-MP. It seems the handset doesn't support this. Lose a point, S68H.

Now for the other bits: another reason for getting this system was Bluetooth support. It turns out, it might as well not have Bluetooth support. For telephone book transfers, it doesn't work reliably with either my Sony Ericsson P1i or my girlfriend's Blackberry. Lose a point, S68H. If you do want to use it, my recommendation would be to first transfer your books to a Bluetooth-enabled laptop, then use gTool or the Siemens QuickSync stuff to copy them to the phone. Not good and not the way things should be, but it does work. I haven't tried the Bluetooth headset support.

Ringtones. I'm as willing as anyone else to quietly seethe or snigger at someone with a ridiculous ringtone. However. The majority of the S68H's standard ringtones will make you want to insert a pencil in your ear and keep on inserting rather than be subjected to that every time the phone rings. Roughly three of them are sufficiently non-irritating to be of use. Even those three are pretty poor. So, I found myself wanting to install a new ringtone. Turns out, you can copy screensaver pictures to it (with QuickSync or gTool) but you can't touch the ringtones. Lose another point, S68H. I'm left using one of the three non-painful ringtones.

Ringtones: the vengeful return. We have three numbers assigned to the one phone line. With my old Gigaset handset, you could assign different ringtones to ring when different numbers were called. This was really useful, since it was immediately obvious when the phone rang whether the call was for me or my girlfriend. Neither of us had to stand around making small talk with the other's friends and relations (not that we don't love them all dearly, you understand). The S68H can't do this. Lose another point, S68H.

Overall: I suspect the problem here is that someone at Siemens decided that they were going to cut the price of the handset by using less flash and a slower CPU than it should really have. I suspect that at least in part, the Bluetooth issues are related to slowness.
Display of stuff is also slow. Some of the features give me the impression that they've been squeezed in for lack of flash. Though it could also be lack of development time. Worse, it seems reasonably likely that Siemens could have found out about all of these issues just by putting the phone in the hands of a few average users for a couple of hours and seeing what turned up. Maybe they did. Maybe those users didn't want Bluetooth support and really liked Biorhythms.

Either way, because the S685IP has an easy mechanism for updating firmware but the S68H doesn't (it can also be used as a plain DECT handset without all this new-fangled IP malarkey), I suspect that S68H owners are stuck with the problems they have.

Still, I do have my train times displayed on all 8 lines.

Arcor settings for the S685IP
Assuming phone number 012345689, in area code 01234
Authentication Name: 0123456789

Authentication Password: password_from_arcor
Username: 0123456789
Display name: Whatever
Domain: 01234.sip.arcor.de
Proxy server address: 01234.sip.arcor.de
Proxy server port: 5060
Registrar server: 01234.sip.arcor.de
Registrar server port: 5060
Everything else standard

Sunday, 10 August 2008

This blog will not kill puppies

...but that's about the only thing I promise for it. My main aim here is to put the various little projects that I work on or look at somewhere where they'll be available to a wider audience. This will save me time, since I won't continually have to find somewhere else to publish them. Hopefully, it will also help somebody one day.

Neither great wisdom nor penetrating insights are to be expected. What is to be expected is my first proper article, tomorrow, about the Siemens S685IP phone and the associated S68H handset. Thrilling stuff.