The 11 Cases of Jane Tennison

It is 25 years now that London-based police detective Jane Tennison first appeared on the TV screen in April 1991. The British TV series Prime Suspect was a huge hit then and the following years until its final episode in 2006. I remember watching most episodes at one time, with a magnificient performance of Helen Mirren in the lead role.

The original inventor of the series fictional Jane Tennison character, British writer Lynda La Plante, has thankfully decided two years ago to breathe new life into Jane Tennison, with new cases that build a prequel to the original episodes. Contrary to the rule of thumb that no good companion novels come after great TV series, both the TV series and the novels are superb and you should consider to both read and watch.

It is slightly complicated, though, to keep track of the episodes and cases, also there are some caveats. So, primarily for my own benefit, I’m going to shed some light on what-is-what.

Prime Suspect

This is the 1991+ original plot featuring Jane Tennison as hardboiled detective with London’s Metropolitan Police Service in the then present time, fighting not only crime, but also her male colleagues and sometimes herself, too.

The TV Series

The 1991-2006 UK TV Series starring Helen Mirren was produced by Granada and screened by ITV. It is not to be confused with the short-lived 2011 US adaptation starring Maria Bello. Wikipedia is a bit confusing, listing seven series with 15 episodes, but in fact we talk about nine cases in seven series that Jane Tennison had to solve. Most cases were split to several episodes for TV screening and one series contained three cases, while normally there has been only one case per series:

  • Prime Suspect (1991): How it all started, Jane Tennison against male colleagues and the evil killer George Marlow.
  • Prime Suspect II (aka A Face in the Crowd, 1992): Racial discrimination and an unsolved murder case.
  • Prime Suspect III (aka Silent Victims, 1993): Jane Tennison hands in her notice, only for short of course, and solves a case around prostitution, child abuse and a mole in Old Bill.
  • The Lost Child (1995): A dead child and a promotion for Jane Tennison.
  • Inner Circles (1995): Murder of a country club manager leads to Jane Tennison uncovering a political scandal.
  • The Scent of Darkness (1995): Villain George Marlow, or at least his modus operandi, is back.
  • Errors of Judgement (1996): Jane Tennison investigates in Manchester.
  • The Last Witness (2003): Jane Tennison is involved in the aftermath of the Bosnian war.
  • The Final Act (2006): A last big case and Jane Tennison is off to retirement.

All episodes and cases are available in a very reasonably priced DVD collection (with a combined runtime of almost 24 hours!) and older episodes may be available on some streaming services. Also, don’t forget to watch the hilarious 1997 cross-over Prime Cracker, a 13 minutes episode starring Helen Mirren and Robbie Coltrane.

The Novels

Novels exist only for the first three cases, all written by Lynda La Plante and first published in parallel to the first three TV series in the early nineties (Prime Suspect, 1991; Prime Suspect 2: A Face in the Crowd, 1992; Prime Suspect 3: Silent Victims, 1993).

The scripts for the other six TV series’ cases were written by different authors and never made it to novels, probably due to copyright issues as it seems that Lynda La Plante might own the rights to the fictional character of Jane Tennison, but not to the Prime Suspect TV format. As she wasn’t commissioned to write the TV series’ scripts after the first three cases anymore, a legal stalemate would have been the consequence.

If you want to read the first three cases today, the cheapest way is to purchase the paperback or ebook editions that were re-published in late 2014 with all three cases in one volume. You can also purchase paperback and ebook editions of each of the first three cases separately but that will cost you considerably more.


This is the 2015+ succession plot featuring the young Jane Tennison, having just joined London’s Metropolitan Police Service in the early seventies. As usual, Tennison runs into trouble with her male colleagues.

The TV Series

There is no TV series yet, but ITV has announced that they have commissioned a 6 x 60 minute series following the plot of the 2015 Tennison novel with actress Stefanie Martini as young Jane Tennison, which is great news. Rumors say that the series is to be aired on ITV later this year.

The Novels

As of now, we have two Tennison novels:

The Strange Case of the OS X System Preferences Window Width

The OS X System Preferences app is something like a wrapper app. In itself, it doesn’t do more than to present all installed system preference panes and these panes then allow you to configure your OS X installation. In addition to system-provided preference panes that come with OS X, additional preference panes can be installed by the user, or by applications.

Xcode comes with a template for such custom preference panes and there is a Preference Pane Programming Guide. Custom preference panes aren’t full-scale applications but rather a user interface to adjust some settings, wrapped in a bundle, so they can’t be distributed via the Mac App Store as such, but could only be an accessory to an application. It might be for this reason that custom preference panes don’t seem to be too popular nowadays.

When I prepared a preference-pane-only app recently, I stumbled upon one inconsistency in Apple’s Preference Pane Programming Guide. The guide states in its section “The Preference Application”, as does the Xcode template, that the

System Preferences window has a fixed width (668 pixels)[.]

and fancies to also give another value in its section “Creating a Preference Pane Bundle”:

For System Preferences, the window should not be more than 595 pixels wide.

Both values didn’t match with what I saw on my computer, so I investigated the issue. Apparently, the System Preferences window on my computer running OS X El Capitan was considerably wider than 668 (or even 595) pixels. Some research later it turned out that the width of the System Preferences window depends on the system language: The window will be 668 pixels wide when English is the primary language, but will have a different width for other languages. For example, with German set as primary language, as it is on my computer, the window is 762 pixels wide:


Setting the language to Russian, it is 780 pixels wide, setting it to Italian, it is 750 pixels wide etc. I checked previous OS X versions and found that this flexible-width approach is around since OS X Yosemite, but is still not mentioned in any Apple documentation. While Apple’s preference panes that come with OS X dynamically adjust their width to the actual width of the System Preferences window, this is not true for any custom preference pane, that will instead be displayed centered with more or less wide blank margins. For example, the popular Growl app comes with a custom preference pane that on my computer with German system language displays like this:


This doesn’t look too professional so I thought of making my preference pane dynamically resize itself, as do the system-provided preference panes. As the Preference Pane Programming Guide still assumes that preference panes have a fixed width (while it isn’t too sure about which width this is, see above), it naturally doesn’t mention any way how to achieve this. Also, the NSPreferencePane class that is to be used to implement a custom preference pane doesn’t offer any way to retrieve the actual width of the system preferences window.

I then came up with a solution which takes advantage of the fact that the code of the custom preference pane will be executed by the System Preferences app and will therefore also have its process identifier. We can now use this process identifier to read out the width of its window from the obscure Quartz Window Services CGWindowListCopyWindowInfo function. This is what below snippet does:

    float result = 668.0; // default in case something goes wrong
    NSMutableArray *windows = (NSMutableArray *)CFBridgingRelease(CGWindowListCopyWindowInfo
      (kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID));
    int myProcessIdentifier = [[NSProcessInfo processInfo] processIdentifier];
    BOOL foundWidth = NO;
    for (NSDictionary *window in windows) {
        int windowProcessIdentifier = [[window objectForKey:@"kCGWindowOwnerPID"] intValue];
        if ((myProcessIdentifier == windowProcessIdentifier) && (!foundWidth)) {
            foundWidth = YES;
            NSDictionary *bounds = [window objectForKey:@"kCGWindowBounds"];
            result = [[bounds valueForKey:@"Width"] floatValue];
    return result;

In the mainViewDidLoad method of the custom preference pane code we can use the retrieved width value to resize the width of our preference pane’s main view:

    NSSize size = self.mainView.frame.size;
    size.width = [self preferenceWindowWidth];
    [[self mainView] setFrameSize:size];

I’ve filed a bug report with Apple to at least update the Preference Pane Programming Guide.

Adobe Flash Player OS X Update Script

Perhaps the Adobe Flash Player will not be around anymore in a few years. Until then, some of us are still using it, people like me. I don’t fancy the update mechanisms it offers, though, neither automatic updates nor the annoying pop-up thing.

There has been some Bash code around since a long time on how to update the Adobe Flash Player from the OS X command line. I have taken some of it and adapted it to current OS X El Capitan. When called, it will check if an update is available and, if it is, install it.

EURO 2016: Laws of the Game

Until today, I didn’t know about the International Football Association Board, which is the non-governmental organisation that is responsible for maintaining the official global football rules (the “Laws of the Game”). I also didn’t know that this organisation has exactly five members – of course the FIFA, but also the [English] Football Association, the Scottish Football Association, the Football Association of Wales and the [Northern] Irish Football Association.

You should read the Laws of the Game. They’re not only very informative, but at times also funny. Would you have known about this clause from Law 17 (“The Corner Kick”):

A goal may be scored directly form a corner kick, but only against the opposing team

They wouldn’t have created such a rule if this didn’t happen at some time in the past, though I honestly can’t imagine how it should be possible to kick an own goal from a corner kick.


This blog is now being served via https-only. If you’re still not using https: It’s really easy to switch and you don’t need to buy a certificate anymore. Using Let’s Encrypt, this is what I typed on my server (aside from a few additional “yes” and <Enter>):

git clone
cd certbot
./certbot-auto –apache

That’s all. Blog up and running. Do it!

The Panini Formulas

The Panini sticker book for the upcoming UEFA Euro 2016 football tournament features 680 stickers this time. We can calculate how many sticker we need to buy to fill the album by using the amazing (due to its relationship to music and architecture) harmonic series formula:

Latex formula

Buying 4829 stickers, it will give me 4149 stickers to swap, assuming that stickers are evenly distributed. If we take into account that stickers are not sold separately but in packs of 5 stickers, the result is slightly different.

Having bought my first 160 stickers today, I have 3.3% of these already, caught in the coupon collector’s problem. We can calculate the probable duplicates I will have from these 160 stickers by:

Latex formula

and I ended up with 17 duplicates, which is nearby.

Today’s Neural Networks Are The Machine Code

In a great new piece in Wired, Jason Tanz announces the end of coding. That might be a bit tendentious but it shows that machine learning that comes with neural networks has the effect of computers programming themselves, with us humans reduced to providing some training data sets:

If in the old view programmers were like gods, authoring the laws that govern computer systems, now they’re like parents or dog trainers.

A neural network takes lots of input data and create its own internal wirings, matching input data to the desired output. It is self-learning, so to say. The neurons of a neural network effectively learn by adjusting their own relative weights (expressed by a number value) as well as by adjusting the weight of the relationships between different neurons (also expressed by number values). As all of the generated stuff is just lots and lots of numbers, we might not be able to say for sure how neural networks work and how they will react on specific input data:

The code that runs the universe may defy human analysis. Right now Google, for example, is facing an antitrust investigation in Europe that accuses the company of exerting undue influence over its search results. Such a charge will be difficult to prove when even the company’s own engineers can’t say exactly how its search algorithms work in the first place.

While this is surely true, it is perhaps too early to be pessimistic.

Continue reading “Today’s Neural Networks Are The Machine Code”

Automation and Artificial Intelligence

Steven Cherry has written an essay about automation and artificial intelligence for the New Scientist. I took two insights from it:

Malone’s third law: “Every technology breakthrough takes twice as long as we expected and half as long as we are prepared for.

So, let’s give real automation with artificial intelligence a few decades, from today.

In fact, all jobs are at risk, even the software programmer’s.

I agree that automation will target all employment sectors, but I would argue that the degree of risk will be divided very unevenly between different professions.

WhatsApp Must Speak German Because

Legal journalism is no easy thing, especially if it is about foreign law or court judgments. All too easy, all those details making the difference, or just the legal context, don’t make it to a published article.

David Meyer’s coverage for Fortune of a recent German regional court of appeal decision in a legal case that WhatsApp is fighting against a local German consumer protection association:

WhatsApp Must Speak German to Germans

Yes, but. This is by no way a suprising decision. It is long established in German legal practice that foreign companies that actively target German consumers are subject to German law, including legal provisions regulating Internet commerce. It is easy to actively target German consumers, with e.g. a German language website (like being sufficient. If you want to avoid German regulation, don’t target German customers specifically.

The appellate court said that while many Germans can understand everyday English, few speak the English legalese in which terms of service are written. Therefore, it said, it was unreasonable to expect them to do so, and WhatsApp’s terms of service and privacy policy are essentially ineffective.

Yes, but. In its decision, the court stressed that it probably wouldn’t agree to any terms of service not being in German language: “Alltagsenglisch mag verbreitet sein, für [..] überhaupt kommerzielles Englisch [..] gilt das aber nicht.”, meaning that while everyday English might be found commonly in Germany, this isn’t true for any commercially relevant situation. This is also a common line of German courts. So, if you want to do business in Germany, you need to follow German law.

If the ruling is finalized

WhatsApp has a chance to lodge a kind of final appeal to the German Federal Court of Justice (Bundesgerichtshof). However, as the recent appeal decision in this case is in line with the common sense of courts in Germany on the applicability of German law, I doubt very much that such a final appeal would have any chance to go through.