1. Mr. David Hepworth , of the lovely Word Magazine (I subscribe !), a usually reliable, and always interesting cultural commentator just blogged a piece about the reactions to the untimely passing of ex-Apple CEO  Steve Jobs . I think his assessment of Mr Jobs' cultural impact is wrong. I was going to present my reaction in place on his blog, although it did seem to grow a little too long for the commentary section, and I subsequently found out that his blogger site seems to be set up disallow comments from people who aren't logged in to a Google account, which I object to, somewhat dogmatically. So I decided to post my piece here, and link back to his , which is more in keeping with my own views about how the Web ought to run.


    I don't disagree fundamentally with the tone of the piece. I do share his unease over the now seemingly mandatory broadcast grief marathons that accompany any death in the public eye, and I find an unpleasant hint of infantile narcissim in the fetish relationship between the user and product celebrated with the mass parades of public Apple evangelists and their iDevices, which might be a cousin to the sentiments he expresses about toys and proportional responses.


    This attempt to sum up Mr. Jobs as a super-skilled marketer I think underestimates the scale, and perhaps also the nature of Mr. Jobs' contributions, some of which are subtle, many of which may look obvious, but usually only by hindsight. Even if his role was solely as a provoker, and curator of works; and I doubt it was, the truth is rarely that neat - he seems to have his fingerprints near the genesis of a string of transformational products, which do seem to fulfill the cliche of yes, changing the world.


    Start at the beginning: His role in realising the portable microcomputer as a packaged appliance, something like a food processor, that people could be taught to directly integrate into their homes and offices. The Apple II barnstormed this market. I am not so sure as most other commentators that this idea was an obvious, archetypal product simply waiting to happen. Putting computers in your house, I think, is a fundamentally odd idea, albeit one that we have now fully naturalised. In 1976 it must have been almost schizophrenic.


    Refining this idea into the Macintosh and Lisa, a specifically pioneering further insight was that a then unusual  square pixel bitmapped display would better lend itself to curve plotting. This gave us the WYSIWYG relationship between the graphical computer and the laser printer , computer typography and thereby re-shaped the primary means of production for print and graphics.


    The post-Apple "wilderness years" are particularly interesting. At NeXT they pioneered software controlled automated computer assembly and production, I've heard it said maybe a decade ahead of everyone else. I think they made a lot of mistakes, but I also think these lessons learned were invaluable later on. More significantly, the NeXT system software placed an elegant emphasis on "object-oriented programming", carefully enveloping the tedious nuts and bolts of interfacing with electrical computer hardware with well chosen software 'components'; tidy abstractions that lead to a system that was significantly easier to port to new hardware configurations, and simultaneously could be more-easily programmed at a higher level, without resorting to so much specialist understanding of specific hardware.


    The significance of the work at NeXT will not be fully realised until later in his career, but as an intriguing footnote, it is on a NeXT workstation that a British scientist called Tim Berners-Lee develops some applications and protocols he calls the "World Wide Web". Mr Berners-Lee is on the record noting that the unique NeXT development tools allowed him to easily connect abstract layers to form useful application prototypes in the space of a couple of months.


    Steve's other business during those years was Pixar . You don't have to study the history of cinema over the last two decades too hard to detect just how fundamentally Pixar shaped mainstream family movie making.


    Then he returns to Apple and begins that now over-documented turnaround from prodigal son and failing company, to pin-up CEO and spectacular media and financial success. It's worth pointing out that the portablility of the NeXT system software allows them to insinuate it into Macintosh entirely. Next the iPod, and then we get iTunes, and the 'iTunes Store'.  And then the same elegant software evolves to pocket phones, where the relative ease of programming buoys up the freshly invented 'App market'. And a finely edged production control builds an on-demand production, supply and retail operation that is the envy of the rest of the industry.


    I'm not a professional writer as Mr. Hepworth is. I hope I don't read like I'm elegising him mawkishly like some Princess Di or Jade Goody for the "Facebook generation", or lionising him in super-human terms as though he's some over-egged digital Da Vinci, or Newton. I never met him. I'm not laying flowers anywhere. I'm sure that a huge part of his success was through fortunate timing, and developing good taste and keeping good company, but this is surely true of many whom history accounts amongst the Great, perhaps even of most. What a C.V. though!


    These things are not a competition you can score, and yet I don't think most Word Magazine readers would rush to disagree with the suggestion that Steve's musical idols like Dylan or the Beatles "changed the world". I'm comfortable suggesting that to a subsequent generation, with it's own new media of choice, Steven P. Jobs influenced and changed the world to an arguably similar degree.

    posted by cms on
    tagged as
  2. I've been having persistent niggles with my home router / 802.11x base station / DSL modem. It's a D-Link DSL-2740B , itself bought as a replacement for my ISP-provided machine, an O2 wireless III (a re-badged Thomson SpeedTouch) which proved itself a low performer at both wireless and routing, and particularly dismal at doing both simultaneously.

    I picked up the D-link cheaply, in a clearance bin in John Lewis. In most respects it has been a splendid replacement for the O2. WiFi is fast, routing is consistent, ADSL sync is better. However, it does have one stupid bug. It can't do DHCP reliably. After a certain period, it starts sending out broken leases to clients; either issuing them with IP addresses that are already in use, or more commonly issuing a working address, but nullifying the nameserver settings. A reboot will restore sanity, but involves an irksome couple of minutes of network outage. Afterwards it is only a matter of time before the problem re-emerges, noticeably quicker if there's an increased rate of new leases issued, such as a group of visitors armed with smartphones popping in.

    I'm consistently amazed at how flawed home router appliances are. How anyone 'normal' is supposed to cope with these things, I have no idea. I've updated the firmware to the last available revision, fiddled with the limited options in the admin interface, to little avail. Web searches turn up a few people commenting on the same problem, but no solutions offered. This leaves me with three straightforward, yet unappealing options.

    1. Buy another router. Either another toy one, which seems likely to smuggle in some fresh nugget of buried failure, or buy something more professional, and hence eye-wateringly expensive
    2. Set up static configuration for every client. Seems a stupid solution in 2010 for a primarily wireless network
    3. Disable DHCP on the router, and add another, more reliable DHCP server to the network


    Option 3 initially seems least aggravating. In the past, my strategy for service infrastructure has always been using home servers, with some form of UNIX. These days though, I'm trying to minimise the number of computer-type devices I have to keep running 24/7. I no longer find any joy in being a home UNIX administrator, and it's nice to correspondingly reduce power consumption, fan noise, and cabling. So the idea of setting up a computer just to act as a DHCP controller is slightly repellant.



    The only machine tethered to the network is a modest, first-generation, G4 mac mini . It's chief use in the past was as a basic freeview PVR, using Elgato eyeTV , but the London flat's TV reception is too poor for this, so it mostly acts as an AFP -capable network interface to my firewire Drobo . It's a very old, low power machine, but would certainly be capable of acting as a DHCP server.

    It wasn't immediately obvious how best to do this. Obviously I could install any of the common free UNIX DHCP software, using MacPorts , or homebrew , or fink , or even just hand rolling something from tarballs, but all of these come with overheads, adding dependencies, requiring build tools, and subsequent package management, and all the little bits of service glue needed to make it run neatly as a daemon. Experience has shown me that integrating third-party UNIX services into a vanilla Macintosh can get fiddly, fast.

    There's no obvious DHCP server component on desktop OS X, but there's a latent capacity somewhere, demonstrated by 'Internet sharing', which lets you easily set up a Macintosh with a network connection as a basic router. After a little bit of poking around with this, and some internet searching, I discovered that this facility is part of the bootpd service. It's documented, and after a little trial-and-error, I figured out a way to run a DHCP server facility only, using just the built-in Apple utilities.

    Here's an overview of my network configuration
    • The D-link router provides NAT routed internet via O2 ( actually Be ) ADSL 2+ with a static IP.


    • The private subnet is 192.168.1.0/24


    • The router's internal address is set as 192.168.1.1


    • The mac mini is connected to the router via wired ethernet with an address of 192.168.1.4, and runs headlessly.


    • Everything else connects to the D-Link router wirelessly, using a mix of 802.11n and 802.11g




    Here's how to set up bootpd to act as a DHCP server for this network.



    First, configure the mac mini to have a static IP. Using screen-sharing from another Mac ( Cmd-K, vnc://192.168.1.4 ) to configure the network interface in system preferences.








    Next, configure your computer to also have a static address on the same subnet. If you get something wrong, and need to troubleshoot settings, you'll still need to be able to connect between the router, the mini and your workstation. I picked 192.168.1.111, as being well outside the range of anything I'd expect to be routinely allocated.

    Now you need to produce your bootpd config file ( /etc/bootpd.plist ). Unfortunately this means an XML property list. Every time I feel smug about how the Macintosh is re-invigorating UNIX with the old, crufty bad bits removed, I ought to remind myself about the maniacally stupid idea that is XML plists. Instead I thank my stars that I have a capable text editor. It's not that fearsome a property set, and is well explained in the man page , so you could build one by hand. An alternative approach, the one I used, would be to set up internet sharing temporarily on the mini for an interface you're not using; I chose firewire. Take a copy of the /etc/bootpd.plist file this will create, e.g. / etc/bootpd.plist.template , and then disable internet sharing again, which will remove the /etc/bootpd.plist file if it still exists. Now rename your template back to /etc/bootpd.plist and edit it.

    The options are all well documented, and it turns out that you need hardly any of them to get up and running.

    The key options are


    • dhcp_enabled: an array of network interface device names to answer dhcp requests on - I just have en0, which is the built-in ethernet
    • Subnets: an array of property dictionaries, that represent networks we're interested in serving. We only want a single dictionary for 192.168.1.0/24.
      • net_address: , is the network address - 192.168.1.0,
      • net_mask: the netmask for our subnet range - '255.255.255.0',
      • dhcp_router: default gateway address - 192.168.1.1
      • net_range: an array of strings representing the bounds of a pool of addresses to allocate from - 192.168.1.12 to 192.168.1.254
      • allocate: a boolean that is set to indicate that we're interested in issuing addresses for this subnet
    <ul>

    Most of the other defaults are sensible. I've kept all the other values that were generated for my template. Here's what I have in my file.


    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
    <key>Subnets</key>
    <array>
    <dict>
    <key>_creator</key>
    <string>cms</string>
    <key>allocate</key>
    <true/>
    <key>dhcpdomainname_server</key>
    <string>208.67.222.222,208.67.220.220</string>
    <key>dhcp_router</key>
    <string>192.168.1.1</string>
    <key>lease_max</key>
    <integer>3600</integer>
    <key>lease_min</key>
    <integer>3600</integer>
    <key>name</key>
    <string>192.168.1</string>
    <key>net_address</key>
    <string>192.168.1.0</string>
    <key>net_mask</key>
    <string>255.255.255.0</string>
    <key>net_range</key>
    <array>
    <string>192.168.1.12</string>
    <string>192.168.1.254</string>
    </array>
    </dict>
    </array>
    <key>bootp_enabled</key>
    <false/>
    <key>detectotherdhcp_server</key>
    <integer>0</integer>
    <key>dhcp_enabled</key>
    <array>
    <string>en0</string>
    </array>
    <key>replythresholdseconds</key>
    <integer>4</integer>
    </dict>
    </plist>


    Next, create two empty files that bootpd expects to use. ' /etc/bootptab ', for any static address maps, and /var/db/dhcpd_leases , which will be a persistent database for issued leases. Now connect to the router, and disable it's DHCP server.

    The bootpd binary lives at /usr/libexec/bootpd . If you run it from a terminal with a -d flag, it will stay in the foreground and emit debugging info to stdout. You'll need root privileges for it to run, I just used sudo /usr/libexec/bootpd . Now request a dhcp address from a different network client. I used an iPad. It's a good idea to make a note of the network MAC address. If everything is working, you should see some output acknowledging the request, and then some more as a lease is issued. The client should then configure it's network interface with all the settings from your Subnet definition above. If it doesn't, and the output isn't helpful enough, there's also a further -v switch for more verbose logging.

    Initially I had trouble getting any leases issued although all requests were logged fine. It turned out I'd misconfigured the netmask when I set up the static address for the mini. If the network details don't match the defined subnet exactly, then bootpd will just fall back to default behaviour for the subnet, which is to just observe. Once I fixed that, things started working as they should. By default, a line is written to logs in /var/system.log for every request recieved, and one for every lease issued.

    The remaining task is to configure the service to run as a daemon from launchd. Luckily, there is a launchd profile for bootpd present, /System/Library/LaunchDaemons/bootps.plist .

    You can install this persistently into launchd like so

    sudo launchctl load -w /System/Library/LaunchDaemons/bootps.plist

    Running sudo launchctl list should then show a com.apple.bootpd service enabled. If for some reason you need to disable it once again, you can uninstall the service using

    sudo launchctl unload -w /System/Library/LaunchDaemons/bootps.plist



    posted by cms on
    tagged as
  3. The other day at work , prompted by a shoutbox conversation with one of our users , I did a little bit of exploring some of the artist catalogue data. The idea was to find band names that were repeating words, such as ' Talk Talk ' and ' The The '. Coincidentally, I had a freshly installed database server with just this sort of information on it, and needed a good excuse to stress test it a little. PostgreSQL's regular expression support is brilliant , and it was a very trivial exercise to quickly knock up a query that returned promising data. In the process of refining it, I got a chance to play around with the Hadoop cluster. I wrote the whole thing up over on the company blog, if you'd like further details. Fame fame fatal fame, it can play hideous tricks on the brain, as the song goes .

    posted by cms on
    tagged as
  4. Yesterday at work , I had to clean after up a particularly freaky Slony-I replication fault. I still haven't managed to understand quite what went wrong there. So this morning, I arrived at work in full diagnostic mode, jokingly grumbling about 'howfuckedismydatabase.com'. Laurie was particulary amused by this curmudgeonly joke, and we bantered about it. I pitched a few ideas about how such a joke site might operate, and we left it there and moved on.

    Except Laurie didn't. Despite my attempts to dissuade him, he registered the domain, and started knocking together some pages based on the earlier jokes. I chipped in a couple more suggestions, and suggested some error messages, and within twenty minutes or so he had an operational site . Then we shared it with a couple of like-minded people, and left it be. A few of the other people at work passed it around, and a couple of people submitted it to reddit.

    Within an hour or so things had started to really snowball. One of the reddit submissions gathered hundreds of upvotes, and for a period of time we were the number one story on hacker news . Laurie added a twitter button and a comment form to the site, and retweets and emails started accumulating fast. By mid-afternoon the site was approaching 200 hits a second, which it handled with aplomb, because he had coded it efficiently, and
    configured the server sensibly.

    It felt great to watch so many people comment positively about some of my dumb jokes, pretty much in real time. It gave me a really direct experience of something I'd always innately understood about the internet, but had not yet witnessed close to home; the ability to quickly reach an appropriate audience for almost any content, regardless of how specialised. Our little shared joke quickly reached out to thousands of people, who found something within it they also related to. This really amazes me.

    It also showed me something about my own character. While I was perfectly happy to joke about the idea, it needed somebody like Laurie, with the skill and enthusiasm to pick up on it and make it into something tangible and exciting. I'd instinctively shied away from broadcasting it further than my desk, and my initial reaction was that developing it any further would be a waste of time and money. I was very wrong about that, it turned out to be an interesting experience, and enormous fun. I think this means I should endeavour to be a little less cynical.

    posted by cms on
    tagged as
  5. I ran into some problems while I was trying to install python bindings for the Growl notification framework on my MacBook Pro. My Mac is running the current release of Snow Leopard ( 10.6.4 ) and I'm using a python.org installed binary package of python, under /usr/local/python. Building using distutils and the supplied setup.py failed, seemingly because the compiler was unable to find quite routine include files, such as stdarg.h and float.h .

    /Developer/SDKs/MacOSX10.4u.sdk/usr/include/stdarg.h:4:25: error: stdarg.h: No such file or directory


    This error message both confused and perturbed me, because stdarg is a fairly fundamental component of a working C library, and I am pretty certain that my compiler isn't that fundamentally broken.

    Picking apart the build output from the generated Makefile, I see that it is setting the -isysroot gcc flag, to /Developer/SDKs/MacOSX10.4u.sdk/ . I presume this is because the python installation is built to use the OS X 10.4 compatability SDK. This is why it's pulling in /Developer/SDKs/MacOSX10.4u.sdk/usr/include/stdarg.h . That header is a stub, and included the following stanza



    /* GCC uses its own copy of this header */
    #if defined(GNUC)
    #include_next


    #include_next is a gcc extension to cpp, and instructs the preprocessor to start searching for the include file again starting with the next directory on the include path after this one. Standard libraries like stdarg and float can be quite compiler specific, and as the comment indicates, GCC is expected to have it's own copy of this header file, which would be put away somewhere under /usr/lib/gcc .

    At this point, a nagging memory of building cocoa apps with XCode resurfaced, suggesting that the 10.4 SDK isn't compatible with gcc-4.2 ( the system default gcc under snow leopard ). GCC 4.0 is supplied though, for use with building against legacy SDKs. On this whim, I tried exporting CC=/usr/bin/gcc-4.0 and rebuilding, and everything worked as it should.

    From inspection, it seems like the snow supplied leopard python is built to use 10.6 SDKs and gcc-4.2 and may well be a more sensible python to use. Further googling ducking , turned up this bug report .

    posted by cms on
    tagged as
  6. There's a handy little command line tool nestled away inside Apple's system WiFi framework.

    Apple80211.framework/Resources/airport

    It doesn't come with a man page, but --help will print a usage guide.


    posted by cms on
    tagged as
  7. Leopard introduced a number of system level changes to font handling. There's a system daemon, fontd that handles runtime font registration. Some of the new features that are implemented include on-demand font activation, on a per-application basis and system font-protection, which guards against removal or disabling certain fundamental system fonts.

    There's a couple of situations where you might need to interface with the font registry database. Sometimes the system font caches can become garbled, and require a manual flush - before leopard these could be easily found under /Library/Caches/com.apple.ATS - now they're squirreled away under /var and managed by fontd. Font protection might stop you from legitimately manipulating certain font files; in a prepress environment you might need to replace one of the magic System protected fonts with a custom version.

    There's a command line utility provided, called ' atsutil ' which offers a user interface to these features. It has a fine man page .

    To purge the font caches, which will fix persistant text rendering problems, you use the command atsutil databases -removeUser

    To display the list of System protected fonts use the command atsutil fontprotection -files .

    To globally disable the font protection feature, use the command atsutil fontprotection -off . Re-enable it with the -on switch.

    Don't remove system protected fonts , unless you are replacing them with a workable substitute.

    posted by cms on
    tagged as
    1. Obtain S60 smartphone. I'm quite fond of my Nokia E51

      2. Install Python for series 60 on your phone.

      3. On a nearby OS X Leopard notebook, setup a new bluetooth serial port, type RS232. ( System preferences -> Bluetooth -> Advanced ). Call it something like 'Bluetooth-console'. Ensure the Mac is paired with the phone.

      4. In a terminal, run ' screen /dev/tty.Bluetooth-console '

      5. Set your Mac's bluetooth to 'discoverable'

      6. Launch the Python application you've just installed on your phone. Select Options -> Bluetooth Console -> Other. Choose your Mac, and then select the Bluetooth-console serial port as the device.

      7. Meanwhile, back on the Mac: a python shell will start in your screen session after a small delay.

      8. In the python session, " import audio "

      9. In the python session, " audio.say('I never realised my phone had a built-in speech synthesizer') "

      10. Fall over in astonishment.
    posted by cms on
    tagged as
  8. I often travel with a laptop. I almost invariably travel with a charged mobile phone. I enjoy using the fancy multi-touch trackpad in my MacBook Pro, but an odd thing happens sometimes when I've put my phone down nearby on the desk; I reach automatically to try and use the phone as a computer mouse. One of those amusing peculiarities of muscle-memory and reflex that can surprise, when you're engaged by something, within the computer, verging upon a liminal state.

    It's a slightly amusing quirk, but when I think further about it, I find plenty of reasons why it perhaps ought to work.

    External mice are more useful than trackpads, although not enough use to me to justify carting one around. My phone is palm-sized, about the ideal weight, is already paired with my laptop over bluetooth, has clickable buttons all over one face, and an optical camera on the reverse. In short, it already has most of the technology needed to be a wireless optical mouse.

    Most but not all. I'm a bit dubious about whether it could be done in software alone. I doubt that the lens will focus well enough to motion tracking without a special surface, and it's completely lacking the light source, but it is almost tempting enough to try. It might be feasible with some sort of very recognisable surface, perhaps a monchrome checkerboard grid, which would be very easy to render and print.

    posted by cms on
    tagged as
  9. So much for my new year resolution to write more often.

    Just before I went away for Christmas, my trusty white MacBook had developed a bit of a problem with it's keyboard. Initially this manifested as the function keys intermittently losing the ability to switch between special Mac control keys, such as brightness, eject media and what-not and normal user-programmable f -keys. Initially I thought this may be a problem with the fn key that is the toggle, but eventually the keys f1 - f9 stopped working entirely. This was irritating, but didn't really render the machine unuseable. Most of the time I use it with an external keyboard, and luckily all the defunct keys functions were duplicated in software.

    The next key to go was the right Shift key. Although, of course there's a left Shift key, for a touch-typist, this was a little harder to ignore. Although I find much to admire about Apple's current laptop keyboard design, unfortunately user-repairability isn't one of its many blessings. There's no simple way to get into the top casing on a polycarbonate MacBook, it's an expensive specialist job for a service centre.

    Sensibly I'd followed my own advice when I purchased this laptop, and bought it from the always-wonderful John Lewis with their standard two-year full warranty on electrical goods. I was coming up very close to the two-year anniversary, which fell within the first week of January, itself another lucky stroke, as it meant that I'd be able to take it with me on my trip to North America , where hopefully it would hold up well enough to let me edit photos, communicate, and act as an additional entertainment for any idle moments. It managed the job fine, and as soon as I was back in the U.K. I packed it off to John Lewis for maintenance, which is something that they arranged with their usual attention to customer service. More thumbs up for John Lewis.

    Which left me Mac-less, save for my rather under-spec G4 mini, which can barely read mail and a web-page at the same time, under Leopard. And so no blogging.

    The two year mark was also my planned point for a new machine upgrade. Buying a machine for work, I was able to take advantage of the Apple Developer Program hardware discount. Sadly this means abandoning John Lewis to purchase direct, but now we've got a real Apple Store in Bristol , I think AppleCare is probably a good deal.

    I figured I'd be needing a machine with better graphics hardware, to better make advantage of the already signposted future directions in OS X technology. The new 'unibody' Macbooks didn't really suit, as I've probably got as many firewire devices as USB. Also, my recent work had been feeling the strains of my Macbook's 13" screen and modest integrated graphics chipset. And so I'm typing this update from my new 2.8GHz, 15.4" MacBook Pro .

    It's mostly a great upgrade. On the positive side, it's pretty and slim, and I'm remembering just how right the 15" widescreen form is for me. The screen is brighter than anything I've ever seen, and makes other LCD displays, including my expensive monitor look washed out and dull by comparison. The new glass front is dramatically easier to clean than any laptop screen I've owned. The extra-large button-free trackpad is brilliant, and even the gimmicky sounding gestures have proven to be almost practical enough for regular use. The unibody shell seems rigid and light, and bringing across the now-standard Apple keyboard hardware makes a brilliant switch from the old silver PowerBook G4 style, which I frankly hated. It's super-fast, of course; the new CPU, memory bandwidth, and fast hard drive all combining to ensure that as yet, I've not seen any performance stalls when many simultaneous processes grow busy.

    It's not perfect of course. Some of the positives are also negatives. The glass fronted screen is considerably more reflective than the previous gloss models, and while in practice I find that I mostly mind this far less than I'd have thought, it's undeniably worse than my gloss MacBook.

    Then there are more straightforwardly negative negatives. Like many people, I've found trouble with the Apple mini DisplayPort to DVI connector - the integrated NVidea 9400 graphics adaptor can't drive my 23" TFT without sparkly artefacts, I have to run it through the additional 9600 GT GPU to get a useful picture. It's too pretty, in as much as it makes me fret about the wear and tear that will inevitably mar its looks over time; surely computers should be tools not jewellery? It's slightly heavier than a MacBook, and the battery life is probably less, it's too hard to say, the calibration as yet seems to be a bit iffy with estimates. I miss the inbuilt LED charge gauges on the battery which allowed one to check the power without having to connect the battery up, so handy when travelling with two or more. I also miss the ports on the left hand side, and find the supplied ports a bit stingy; surely they could have squeezed a couple more USB slots and a firewire 400 in somewhere? I'm not sure I need a wired ethernet anymore.

    Not only that, but shortly after I'd ordered it, Apple saw fit to announce an update to the polycarbonate MacBook line, giving it a memory bus and GPU boost to inject some of the performance I was lacking, and keeping the essential firewire port in place. And then they announced iLife '09 would ship a mere handful of days after my new machine was dispatched. I think I'll still enjoy all the other Pro upgrades though, and they did offer recent purchasers like me the chance to upgrade the iLife suite for just a nominal cost.

    Overall I'm happy, and I'm sure all the wrinkles will be ironed out, as I adjust to life with it. It ought to keep me in the manner to which I'm accustomed for the next couple of years, at least. What was that they said about never buying the first iteration of a new Apple product line? Oh.

    posted by cms on
    tagged as
  10. Ever wondered what your most used shell commands are? Here's a very silly way I knocked up to find out mine.

    history|perl -anle'$C ++;END &#39|head -10

    Some people would have you believe that perl is difficult to read.

    posted by cms on
    tagged as
  11. If you have a Django 1.0 deployment configured to use sqlite3, and are struggling to understand sporadic eruptions of what are clearly exceptions thrown by closing a database cursor with uncommitted work; either manage.py commands on the shell, or page requests to the application generate stack traces centered around messages like ' Unable to close due to unfinalised statements ' then it might be a file permissions problem.

    In my case, neither my developer shell account, nor the user id of the running apache httpd processes had write permissions to the directory with the sqlite3 database file. Not immediately apparent from the wording used in the error messages.

    posted by cms on
    tagged as
  12. I have some Objective C classes that I've built for use in a project. They are model and utility classes, and have no direct UI responsibility. To aid in automated testing and debugging, I've built them as a project that creates a static library. The project has a test target that runs suites of automated unit tests, and a library target that builds a C-style static library archive binary. The install configuration of this target copies the library to $HOME/lib/ , and the class headers to $HOME/include/$LIBNAME.

    This way when I use these classes in another project, I can just #import the headers in the sources, add the static library to the project frameworks list, add the include and lib directories to the compiler and linker search paths in the XCode target inspector, and build as normal. Build times are reduced, base classes are frozen in a stable, well tested implementation, code re-use is easier, everybody wins.

    Recently I broke this happy pattern, a little perplexingly, with what I thought was a fairly innocuous piece of refactoring. I noticed that one of my classes was rather a simple set container, and its implementation really little more than a thin wrapper around NSMutableArray , with only a trivial specialisation of behaviour. As it was only used within a parent class structure, with no interface outside the library innards, it seemed a bit of overkill to have it implemented as a sizeable class. The special behaviour really boiled down to maybe two additional methods on top of the normal array interface.

    I first refactored it to be a subclass of NSMutableArray, but that actually introduced more complexity. NSMutableArray is implemented as a class cluster , with an abstract API around a private hidden shadow class. In order to subclass it, you are expected to provide your own implementations of a subset of its interface. In my case, this would have made for more code than the class I was trying to replace.

    Of course, Objective-C allows you to define categories on any existing classes. Categories allow you to formally define and implement additional methods onto an existing class definition at compile time. I could re-implement my class as a tiny category on NSMutableArray, removing lots of my code, and reducing the size of my library footprint and perhaps add some value by introducing NSMutableArray's extensive interface.

    Surprisingly, it wasn't plain sailing. Coding up the category, and tweaking the library to use NSMutableArray in place of the now-redundant class was straightforward. Once the updated code passed the original test suite, it was deployed as a library. The first time I built a project using it, it crashed on startup, with an unhandled exception. I cleaned all targets and rebuilt. Same problem. I checked the library headers to confirm that the new data structures were properly defined on include. No problems there, but still a hard crash on initialisation.

    The system logs had an entry for the crash; selector not recognized attached to symbols that were recognisably the new array methods from my category. Running 'nm' against the library file showed the symbols present, and correctly defined as a category on NSMutableArray. I was stumped. After a bit of googling, I came up with the correct solution.

    It turns out that in order to link against a static library that contains Objective C categories, you need to pass the linker a special flag, '-ObjC'. Adjusting the build settings of my project to include this flag in the 'Other linker flags' entry of the target inspector fixed it so that the symbols are correctly resolved at runtime. Here is the official word, Technical Q&A QA1490.



    posted by cms on
    tagged as
  13. Apple released iTunes version 8 this week , which introduced some excellent new features , such as Genius playlists, but broke the fancy perl script that I wrote to rotate my music library on my iPod touch.

    While revisiting this, I took the opportunity to re-implement it, aiming to fix a few of it's faults, most specifically the terrible performance. I decided to use Python this time around, chiefly because of the existence of appscript , an apple event bridge with a nice syntax. Python's object and sequence semantics are a slightly better fit with AppleScript's data models, and appscript should be a more optimal solution than Mac::Glue for sending lots of messages iteratively.

    I've also improved the actual command recipe, using 'duplicate' rather than 'add' to build the playlist seems more efficient. Also the overhead of having to periodically build glue modules with the ' gluemac ' tool is removed. Sadly appscript isn't shipped with OS X, but installing it ( at least on Leopard ), is as simple as ' sudo easy_install appscript '.

    The concept behind the tool is the same : use a nominated playlist to synchronise the albums with the iPod, and pick a random set of albums from buckets organised by album rating. Currently it's set to shuffle in 10 '2 star' albums, 20 'three star' albums, and 30 'four star' albums, selected from a 'just music' smart playlist that filters the master library, removing all spoken word, and podcasts and other miscellany from the pool.

    Here's the source . I'm far less experienced at python than I am perl, so I wouldn't claim it was a particularly idiomatic solution. It does run many times more quickly than the perl / Mac::Glue solution, taking a minute or so, rather than the best part of an hour. I would put all the performance gains down to the AppleEvents bridge , appscript interface, and using more efficient apple event set operations, rather than iterating over individual data.





    posted by cms on
    tagged as
  14. Some advice for when you're debugging code using the whizz-bang, illustrated debugger in XCode 3, and suddenly find that none of your breakpoints are triggered. XCode forgets all your breakpoints! Even plain breaks at line numbers disappear when you hit "Go". You may have some, or even all, of the following symptoms.


    • The little blue indicators in source view just turn yellow (for 'pending') when the debugger loads your executable, and never go blue again.


    • The tickbox for 'Use' in the debugger breakpoint list view, turns to a dash for half-checked.



    • Attempts to set symbolic breakpoints which used to match multiple symbols don't match any symbols.



    • "break info" in the gdb console doesn't list anything.


    If you're anything like me, you might be muttering loudly by this point, and perhaps banging things. Cleaning the entire project, and rebuilding all the dependencies doesn't seem to help. Nonetheless there may yet be hope! In my case, setting the debugging option 'Load symbols lazily' to off, magically fixed things again. This setting is found in the IDE preference pane - XCode -> Preferences -> Debugging .

    posted by cms on
    tagged as
  15. It seems like the iPhone 3G has been another smash hit. Certainly here in the UK, with pretty universal 3G signal coverage, there's lots of interest, and the handsets are selling out as quickly as they come into stock. Several people I know who waited out the first generation immediately signed up for the 3G edition.

    Responses to the new platform seem mostly positive, although there's already some mild grumbling seeping through across the web. There's more software glitches, unsurprising; given the rush of new third-party applications there's countless potential software combinations interacting in unpredictable ways. The new units eschew the metal casing of the original iPhone, for a return to possibly scratch-prone iPod plastic. 3G mode depletes the battery rapidly, just as Apple said it would, when they justified their initial transport choice of GPRS/EDGE. The camera is unimproved over the first generation (although I have always been rather impressed with the iPhone camera. For a phone, with no flash it takes great photos, a textbook-worthy example of why it's nothing to do with the megapixel count)

    So maybe it's not the holy grail of portable devices. It's certainly not for me. I don't like the idea of being locked to a single phone company. I don't want a smartphone that can't be used as a 3G modem - I've grown too used to being able to connect a variety of devices up to the net, using USB / bluetooth or even infra-red links. It's a little big for my idea of a phone.

    As a portable, internet connected, media player cum tablet, it can't be beaten. The mobile browser is immeasurably better than any others I've used. The iPod, photo, and movie playing is slick, and the iPod + iTunes combination still the best available digital music library implementation. The straightforward syncing of contacts and calender information beggars belief (at least for Mac users, such as myself ). Thrown in a few simple PIM applications, ebooks and games from the Application store, and you're looking at a compelling platform.

    Of course, you can get the majority of this behaviour in the iPod touch. Smaller and lighter than it's phone siblings. Metal back. iPhone-trouncing storage capacity (up to 32GB). Runs the same operating system and applications, same beautiful interface. No contract. The downside being that you can only use it as an internet device over WiFi, which means you need to be tethered to a hotspot. Except it doesn't mean this at all.

    There's a simple recipe to open up the iPod touch's internet capabilities to something much closer to the iPhone.


    1. Arrange a 3G phone+data connection with the phone provider of your choice. I use T-mobile , I'm very happy with the service.


    2. Choose a phone handset, with a high speed modem capability. Make sure you get a model with WiFi . I have a Nokia E51 . It's lovely. Depending on your phone contract terms, you may get this as a freebie.



    3. Configure your phone to act as a WiFi hotspot, using something like WalkingHotspot


    4. Join your iPod touch with your phone's WiFi network. Enjoy 3.5G connectivity on the go!



    Of course it's not a drop-in replacement. You don't get an in-device camera or GPS, although you may have these in your phone. You do get to spread the battery load between two devices, one with the big screen and multimedia capabilities, another with the data transmission hardware. Although WiFi use will run down your iPod battery faster, you might still find that this combination outperforms an iPhone 3G.

    posted by cms on
    tagged as
  16. Every time I install a fresh debian derived linux, I subsequently find out that I'm missing the man pages for the C library. Usually many months later, it's not like I program in C for kicks. I then waste twenty minutes fruitlessly grepping around in apt using patterns like 'glibc'. The package name is actually 'manpages-dev' . Perhaps posting it here will fix this in my memory.

    posted by cms on
    tagged as
  17. Sometimes you run programs in xterm windows that try and do you a favour, by setting the xterm title property. Potentially useful enough, but aggravatingly some of them don't restore the previous title when they exit. If you're using some scheme of your own to set meaningful window titles, this is annoying.

    Here's a shell one liner that you can use to grab the current title in an xterm. You could use this to write a wrapper script that gracefully launches any such rude application, and restores the rightful title property when it's done

    /usr/X11R6/bin/xprop -id $WINDOWID | perl -nle 'print $1 if /^WM_NAME.+= \"(.*)\"$/'

    posted by cms on
    tagged as
  18. Ever wanted to combine multiple individual PDF files into a single PDF document? Say you were scanning a paper document, a page at a time, and wanted to collate the digital pages back into a single document. Or collect together a number of similar PDFs you'd generated
    via 'Print to PDF', perhaps to send via email.

    You can do this incredibly simply in Leopard, without resorting to any additional software. PDF is such a fundamental component of Mac OS X, you can script operations like this using a very simple Automator workflow.

    Just build the following sequence of actions.

    1. Files & Folders: - Get Selected Finder Items
    2. PDFs: - Combine PDF Pages
    3. Files & Folders: - Open Finder Items

    Select all the individual pages in a Finder window, and then run the workflow. After a short wait, while the actions are run, a multi-page PDF will open in Preview. Choose 'Save As', to create a new file. Notice the optional Quartz Filter operations you can apply to the new document when you save.

    posted by cms on
    tagged as