Begin main content

Apple Operating Systems

I felt like pulling out my emulator collection this evening, so then I thought I'd see how many Apple OS's I could jam onto my iMac 27" screen at once. The answer is quite a lot, but fewer than I'd hoped—I may have to re-do the challenge including my second monitor.

Anyway, for your enjoyment, here it is. Click to expand:

The emulated systems are, left to right, top to bottom:

  1. Macintosh System 1.1 (showing the early Control Panel)
  2. Macintosh System 2.0.1 (running MacPaint)
  3. Macintosh System 3.3.0 (running the Scrapbook Desk Accessory)
  4. Macintosh System 6.0.0 (showing the newer Control Panel)
  5. Macintosh System 8.5 (running CyberDog)
  6. Apple 1 with a simple Hello World program entered into the WOZ Monitor
  7. Dos 3.3 (running Beagle Bros Apple Mechanic)
  8. UCSD Pascal OS
  9. Prodos 1.1
  10. Apple /// SOS
  11. The Lisa Office System (running LisaCalc)
  12. Newton OS (running on an eMate 300)
  13. NextStep 3.3 (running Mail.app - not strictly an Apple OS I guess)

10:58 PM, 18 Oct 2011 by Mark Aufflick Permalink | Short Link | Comments (0)

Speaking at Mobile Camp OZ on March 1st

I may be entering the lion's den judging by the majority of Mono/.Net talks, but nevertheless I am giving an iOS zero to hero in 55 minutes talk at Mobile Camp OZ in historic (ie. remote and cold ;) Bathurst. It's a free two day conference, so why don't you come along? http://www.mobilecampoz.com/. You could win one of these ride-on Eski's, now that would be awsm!

On the topic of conferences, not sure why I didn't mention this earlier - Swipe Conference! Australia's first iOS and Mac developers conference organised by Jake MacMullin, Sean Woodhouse and yours truly.

04:09 PM, 28 Apr 2011 by Mark Aufflick Permalink | Short Link | Comments (0)

Apple Push Notifications Talk—Screen/Audio recording now available

Thanks again to the guys at the Apple University Consortium for inviting me to speak at /dev/world 2010. The screen/audio recordings are now available. I have linked to them (and the rest of the /dev/world presentations) on my APNS talks page:

http://mark.aufflick.com/talks/apns

11:00 AM, 03 Mar 2011 by Mark Aufflick Permalink | Short Link | Comments (0)

Easily create random secret strings

alias randsecret='dd if=/dev/urandom count=2048 2>/dev/null | md5'

Will give you a random md5 string every time.

03:36 PM, 04 Jan 2011 by Mark Aufflick Permalink | Short Link | Comments (0)

Extracting detailed Time Slip data from Billings

Similar to a previous post about Extracting invoice data from Billings I hit another limitation with Billings exporting ability today. Each "Slip" in Billings can have multiple time records - I might do 5 minutes on a task now, 10 minutes after lunch and a further 25 tomorrow. There is no way, I can see, to export this data—but armed with our knowledge of Billing's sqlite3 schema we can get it for ourselves.

echo "select TimeSlip.name, datetime(TimeEntry.startDateTime, 'unixepoch', 'localtime'), datetime(TimeEntry.endDateTime, 'unixepoch', 'localtime') from TimeSlip, TimeEntry where projectID = 1400 and TimeEntry.timeSlipID = TimeSlip._rowID;" | sqlite3 -separator ' ' "$HOME/Library/Application Support/Billings/Database/billings.bid"

This will output the detailed timing data for all slips that are un-invoiced for the given projectID (look that up in the Project table - it's _rowid).

07:08 PM, 22 Nov 2010 by Mark Aufflick Permalink | Short Link | Comments (0)

Making a fat static library for iOS device and simulator

Some third party iOS library providers (I'm looking at you Omniture) provide separate static library archives for simulator (i386) and device (armv6 and or armv7).

That's a pain since you either change them manually or set the linking flags on different Xcode targets to use the appropriate library (whereas normally with libraries and frameworks you just drag it into your project and you're done).

Instead, you can build your own fat (multi-architecture) library from the provided archives and Xcode will link against the appropriate architecture segment (flagrantly ignoring Erik's dire predictions about testability and your personality ;)

We achieve this using the lipo tool, eg:

lipo -output libOmnitureAppMeasurement-fat.a -create -arch armv6 libOmnitureAppMeasurement-iPhoneDevice.a -arch l386 libOmnitureAppMeasurement-iPhoneSimulator_4_0_GM.a

Update:

The latest Omniture libraries, available via the Omiture SiteCatalyst admin console, now contains armv6 and armv7 architectures. Oddly, that means that they provide two archives—one regular i386 archive (with no fat header) for the simulator and one fat archive for the device with armv6 and armv7 segments. Since the device archive headers now specify the archives already, we don't need to tell lipo anything other than the archive file name.

lipo -output libOmnitureAppMeasurement-fat.a -create libOmnitureAppMeasurement-iPhoneDevice.a -arch i386 libOmnitureAppMeasurement-iPhoneSimulator.a

03:43 PM, 19 Nov 2010 by Mark Aufflick Permalink | Short Link | Comments (2)

Extracting invoice data from Billings

I use the excellent Billings 2 from MarketCircle for tracking my time and issuing invoices. There are some things it doesn't do well though, and one is exporting or interacting with external systems*

I knew from the also excellent Workload widget for Billings that all the billings data is in an sqlite3 database at the following path:

$HOME/Library/Application Support/Billings/Database/billings.bid

So getting my Q3 invoice data is as simple as:

echo "select date(invoiceDate, 'unixepoch', 'localtime'), '', invoiceNumber, company, totalCached from Invoice, Client where Client._rowid = Invoice.clientID and invoiceDate > strftime('%s', '2010-07-01') and invoiceDate < strftime('%s', '2010-10-01');" | sqlite3 -separator ' ' "$HOME/Library/Application Support/Billings/Database/billings.bid"

This gives me what I need to paste into my BAS spreadsheet (I've set the separator to the tab character). The tax fields in the Invoice table don't seem to be used, but I can easily calculate the flat 10% GST afterwards so I didn't bother investigating the Tax tables.

* I do note that their FAQ for Billings Pro says about any forthcoming API: "We do have the ability to run FScript scripts (or FScript wrapped within AppleScript), but we have not documented the potential calls and methods." which is pretty interesting, but I'm a little nervous about doing that with my billing system until they document which methods are safe!

02:02 PM, 22 Oct 2010 by Mark Aufflick Permalink | Short Link | Comments (0)

Aquamacs copying styled text

Some time ago I switched from X11 GNU emacs to Aquamacs - the Aqua Mac native port of GNU emacs. The latest version of Aquamacs has a neat Edit menu item "Copy as HTML" which basically makes a convenient way to use the htmlize.el package to put a colourised version, in HTML format, of the current selection on the Mac clipboard.

That's great for posting into, for example, a blog post—but what about into other Cocoa apps? For that you still only need html, but it has to have the correct UTI on the clipboard to be recognised. The Aquamacs/GNU Emacs copy internals for the Mac nearly work flawlessly, and the following slightly hacky function will put a "Copy as Styled Text" into your edit menu:


(defun copy-as-styled-text (beg end)
  "Copies the region as HTML styled text into the clipboard."
  (interactive "r")
  (when (or (not transient-mark-mode) mark-active)
    (let ((x-select-enable-clipboard t)
      (buf (aquamacs-convert-to-html-buffer beg end)))
      ;; the copy as html is more reliable if we've copied plain text first
      ;; (which seems to clear the clipboard of all types)
      (with-current-buffer buf
    (copy-region-as-kill (point-min) (point-max)))
      (with-current-buffer buf
        (ns-store-cut-buffer-internal 'PRIMARY (buffer-string) 'html))
      (kill-buffer buf))))

(define-key-after menu-bar-edit-menu [copy-styled]
  '("Copy as Styled Text" . copy-as-styled-text) 'copy-html)

07:33 PM, 24 Sep 2010 by Mark Aufflick Permalink | Short Link | Comments (0)

Speaking at /dev/world 2010

/dev/world is a conference run by the Australasian Apple University Consortium (AUC). The AUC has been around since the Mac was launched in 1984 to promote and foster development of Apple platforms.

This year the AUC conference is in Melbourne on September 28th-29th and I will be one of the speakers. Here's my bit in the program:

Push Notifications - Device, Protocol and Server
Speaker: Mark Aufflick
Target Audience: Intermediate

Apple Push Notifications are an integral part of many applications, from games like "Words With Friends" to VOIP call notification, but for the non-expert developer they can be a source of mystery. Apple's "Local and Push Notification Programming Guide" provides details of the binary protocol, SSL certificates and other details which are hardly beginner material. Additionally the guide makes little mention of correct UTF encoding and other small details which create more difficulty for those unfamiliar with data encodings etc. And finally a persistent server is required which can handle the protocols. This talk will take attendees through: an understanding of the service overall; the protocol and its limitations; responding to notifications in the iOS application; approaches to implementing a server in Perl, Python or Ruby.

Bio:
Mark Aufflick has been involved in the Apple industry since his first job in 1995 and finally put his Computer Science degree to use becoming a freelance developer in 2000. Since then he has developed back end, web and gui applications for various Unix platforms, MacOS and iOS - for both corporate giants and small businesses. Mark has presented on programming topics in fora such as Sydney University's Web Engineering Group and CocoaHeads. These days Mark is an iOS and Mac developer with his company Pumptheory as well as the convenor of Sydney CocoaHeads.

I'm really looking forward to meeting the other presenters and delegates! If you're attending, let me know on twitter - I'm @markaufflick.

02:36 PM, 06 Sep 2010 by Mark Aufflick Permalink | Short Link | Comments (0)

Quickly add PDFs to iTunes/iBooks

Being able to transfer PDFs to iBooks on your iPad and iPhone is really handy. But sometimes it's a pain to either make or track down an actual PDF file. Here's how to do it painlessly.

For any non-PDF document, you can print to PDF and open it in iTunes. But you can collapse that with this neat tip from MacWorld.

If you want to quickly add a document or a web page to your 'Books' collection in iTunes, all you need to do is to create an alias of iTunes and drag it to ~/Library/PDF Services. Now, when you're browsing the web or viewing documents and you decide that you want to read them later on a portable Apple device just hit Print, click the PDF button on the bottom left corner of the window and choose iTunes. iTunes will launch and receive the PDF. Next, sync your device and you're ready to go. Source

But what about when you've got a PDF already open in Preview (say you clicked a PDF download link)? Sure you could save to desktop, drag into iTunes, delete it. Or find 18e3764.pdf in your download folder etc. But if you're any kind of Mac commandline nerd, you will already have DTerm installed (if you don't - do yourself a favour and go check it out).

So you have a PDF open in Preview (or any other PDF app) - just hit your DTerm shortcut key combo (mine is Command-Shift-Enter), then type open -a iTunes then hit Command-Shift-V. (this pastes the path of the current window's file into the DTerm commandline) and hit Enter.

Now your PDF is in iTunes, already highlighted ready for you to change the title if needed.

12:30 PM, 19 Aug 2010 by Mark Aufflick Permalink | Short Link | Comments (0)

Filtering Growl notifications

Now that I work full time on my Mac I have Skype, Notify and any number of other apps telling me stuff via Growl. One of the great things about having everything centralised through a single notification mechanism is that you can easily choose what notifications you want to see.

Growl already has a great way to choose notifications by turning Apps on or off and notification types as registered by the Apps. But it doesn't have any way to filter based on the content of the notification—e.g. if I want to see when some Skype users log on but not others.

So since Growl is open source I took matters into my own hands. I don't have a UI yet, and haven't forked the repository, but for now here's a quick patch.

The UI is you use Apple's Plist editor to add an array with key "GrowlIgnorePredicates" to com.Growl.GrowlHelperApp.plist in your Library/Preferences directory :) Here are the keys, see NSPredicate docs for predicate string syntax. If you have no idea what I just said you'll have to wait for the UI I'm afraid!

  • ApplicationName
  • NotificationTitle
  • NotificationDescription
And here is the patch:

diff -r 9f9a8561261a Core/Source/GrowlApplicationController.m
--- a/Core/Source/GrowlApplicationController.m	Sun Aug 01 10:35:51 2010 -0400
+++ b/Core/Source/GrowlApplicationController.m	Wed Aug 04 13:18:37 2010 +1000
@@ -592,6 +592,21 @@
 		[pool release];
 		return GrowlNotificationResultDisabled;
 	}
+    
+    GrowlPreferencesController *preferences = [GrowlPreferencesController sharedController];
+    
+    // Mark Aufflick hack - needs UI    
+    NSArray *ignorePredicates = [preferences objectForKey:GrowlIgnorePredicates];
+
+    if ([ignorePredicates isKindOfClass:[NSArray class]]) {
+        for (NSString *predString in ignorePredicates) {
+            NSPredicate *p = [NSPredicate predicateWithFormat:predString];
+            if ([p evaluateWithObject:dict]) {
+                NSLog(@"ignoring notification due to predicate: %@", p);
+                return GrowlNotificationResultDisabled;
+            }
+        }
+    }
 
 	NSMutableDictionary *aDict = [dict mutableCopy];
 
@@ -642,8 +657,6 @@
 		value = [NSNumber numberWithInt:priority];
 	[aDict setObject:value forKey:GROWL_NOTIFICATION_PRIORITY];
 
-	GrowlPreferencesController *preferences = [GrowlPreferencesController sharedController];
-
 	// Retrieve and set the sticky bit of the notification
 	int sticky = [notification sticky];
 	if (sticky >= 0)
diff -r 9f9a8561261a Core/Source/GrowlPreferencesController.h
--- a/Core/Source/GrowlPreferencesController.h	Sun Aug 01 10:35:51 2010 -0400
+++ b/Core/Source/GrowlPreferencesController.h	Wed Aug 04 13:18:37 2010 +1000
@@ -39,6 +39,7 @@
 #define LastKnownVersionKey			XSTR("LastKnownVersion")
 #define GrowlStickyWhenAwayKey		XSTR("StickyWhenAway")
 #define GrowlStickyIdleThresholdKey	XSTR("IdleThreshold")
+#define GrowlIgnorePredicates       XSTR("GrowlIgnorePredicates")
 
 CFTypeRef GrowlPreferencesController_objectForKey(CFTypeRef key);
 CFIndex   GrowlPreferencesController_integerForKey(CFTypeRef key);

01:47 PM, 04 Aug 2010 by Mark Aufflick Permalink | Short Link | Comments (0)

Using Haml with Catalyst

Thanks to Viacheslav Tykhanovskyi's Text::Haml, we can now enjoy the good clean fun of Haml markup in Perl. Much Perl web templating is done with Template::Toolkit, and using Haml within TT is also now possible thanks to Template::Plugin::Haml by Caleb Cushing. The trouble is, you need to wrap every template in some boilerplate:

[%- USE Haml ; FILTER haml -%]
...
[%- END -%]

So I hacked up a quick solution to using .haml templates directly in Catalyst. First, create a MyApp::View::Haml class:

package Hello::View::Haml;

use strict;
use warnings;

use base 'Catalyst::View::TT';

use Template::Plugin::Haml;

__PACKAGE__->config(
    TEMPLATE_EXTENSION => '.haml',
    render_die => 1,
);

sub render {
    my ($self, $c, $template, $args) = @_;

    $c->log->debug(qq{Rendering Haml/TT template "$template"}) if $c && $c->debug;

    # args may be passed in or be in the stash
    $args = { %{ $c->stash} }
        if ref $args ne 'HASH';

    # let the master haml template know which template to render
    $args->{haml_template} = $template;

    # do the normal TT render
    return $self->SUPER::render($c, 'haml_master.tt', $args);
}

1;

Then you need a haml_master.tt template:

[%- USE Haml ; PROCESS $haml_template | haml -%]

And finally set your config to use the Haml view by default:

default_view => 'Haml'

Et voila - .haml template rendering albeit with only TT style variable interpolation. Getting haml interpolation working might need some change to how the stash is passed to the Text::Haml module.

A controller method might look like this:

sub foo :Global {
    my ($self, $c) = @_;

    $c->stash(foo => 'bar');
    $c->stash(template => 'foo.haml');
}

And foo.haml:

!!! HTML
%body
  %p This is haml inside TT rendering your variables: [% foo %]

Becomes rendered as:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<body>
<p>This is haml inside TT rendering your variables: bar</p>
</body>

06:35 PM, 29 Jul 2010 by Mark Aufflick Permalink | Short Link | Comments (0)

Code Bubbles - the most important IDE innovation since SmallTalk?

Wow. An IDE concept (with prototype and promise of a beta implementation that you can sign up for) that for the first time makes me want to program in Java. People who know me will know how huge that is.

I loved the SmallTalk IDE's concept of method-level programming ever since I was first exposed to it. Code-folding just isn't the same, you are still conceptually dealing with files on a file system - methods and their interactions aren't presented as first class entities in "modern" editors or IDEs and thus struggle for that place in the minds of most developers.

Code Bubbles, by Andrew Bragdon at Brown University resumes this paradigm from SmallTalk and takes the UI to the logical next level, all with a polish that just invites you to hunt through the code to sqaush any bugs!

Any professional developer, Java or otherwise, needs to check it out.

/via Lambda the Ultimate

06:29 PM, 13 Mar 2010 by Mark Aufflick Permalink | Short Link | Comments (0)

IBM 305 RAMAC

I wouldn't want to be debugging that 'wired format control'!

via Royal Pingdom.

03:41 PM, 19 Feb 2010 by Mark Aufflick Permalink | Short Link | Comments (0)

iPad gets back to the priorities of the first Macintosh

The first Mac I ever used was a Mac 128, when my Dad brought one home as part of the ground breaking Apple Test Drive promotion. It booted into the Finder quickly even though it used a floppy. It only ran one program at once, so programs (mostly) started and exited quickly and didn't interact. It had a fixed screen size so everyone's experience was the same. There were desk accessories that gave access to limited functionality while applications were running.

Sounds a lot like the iPad (except bigger and black and white - and of course no 3G ;).

Seriously, it's Steve Job's core vision all over again. Steve Jobs didn't want the Apple ][ to have any expandability, it was Steve Wozniak who convinced him (correctly) that computers were still very much a hobbyist device and need expandability. The original Mac wasn't supposed to have upgradeable ram - it was the engineers (Burrell Smith I think) who secretly made the circuit board easily upgradeable.

Only now, the hardware and connectivity reality has caught up with Jobs' reality: hardware is cheap, expendable and compact - and Apple makes the best. Once again another insanely great device is going to change the place computers have in our lives.

11:08 AM, 28 Jan 2010 by Mark Aufflick Permalink | Short Link | Comments (1)

Debugging release/autorelease issues in Cocoa

So your code crashes with an EXC_BAD_ACCESS in objc_msgSend and there is *none* of your own code in the stack trace. Bummer. Since all we know from objc_msgSend is that it's trying to call a method on an object. Since we got EXC_BAD_ACCESS you can bet your bottom dollar that it's attempting to call a method on a freed pointer, so there's no obvious way of finding out what the object was. We can, though, easily find the method. Read Greg Parker's excellent post So you crashed in objc_msgSend(). For the iPhone simulator on my Mac I need to do this at the gdb prompt to decode the eax register:

(gdb) x/s $ecx
0x980530c4:	 "release"
you can see that the selector in the second argument is "release". Now we're getting somewhere, we know an already freed object is trying to be released. Since there is none of our code in the stack trace it's a fair bet that it's happening when the autorelease pool is releasing.

There are a few tricks in your toolbox for tracking down over-released objects. There's the NSZombieEnabled, NSAutoreleaseFreedObjectCheckEnabled and other environment variables which will give you better logging rather than just crashing.

I've found this is not always reliable (logs from the above builtin debug options showed that the over-release was on an NSCFDate object, when in fact it was an NSNumber). Sometimes you also just want to trace through exactly what is happening with your retain/release/autorelease cycles. That's what we're about to achieve here.

Ok, so you have a unit test that replicates this problem right? I use the excellent GHUnit by Gabriel Handford. If not you'll have to play around a bit to narrow down your problem code. In my case, I wanted to confirm that a particular unit test was failing during the autorelease pool release. Best way is to wrap the offending code in a new autorelease pool. Then it will be freed inside your code, which you will see in the stack trace, and confirm you have found the reason. My unit test now looks like:

(Note that the code examples, embedded in github gists, are not showing up in my RSS feed. I'll fix that later, but for now please read the original post)

Now when I fail with EXC_BAD_ACCESS my stack trace looks like this:

Where line 91 of CJTestCJCard.m is the [pool release] call above. So something is being added to the autorelease pool, and is *also* being fully released, or maybe it's being added to the pool more times than it is being retained. There doesn't seem to be a way to interrogate the contents of the autorelease pool (which is a shame) but we log some really useful info by overriding a few methods, like NSObject's release and autorelease methods, so we can see when things are being added to the pool and when things are being released. This is some funky stuff, but since we're only doing it in our unit test class, not code we're going to release you can sleep soundly at night. Here's how I effected logging in release and autorelease.

Add this to the top of your unit test class, before your current @implementation:

Now in your unit test class @implementation, you can use the setupClass method to effect the method implementation switcharoo:

Now your log will be filled with log lines like:

This can help when tracking down tricky releasing bugs. Note that not all classes seem to comply. For instance I see plenty of log lines for NSCFString, but never any release lines. I assume that NSCFString release implementation is a bit different since it's a toll free bridged object - getting that to log is an exercise left for the reader!

If you're interested in the functions I used above to interact with the runtime, check out the Introduction to The Objective-C Programming Language and Objective-C Runtime Reference. Note that the code above works fine in the iPhone simulator. It should be fine on 64 bit Mac apps, but you may need to diddle the method structs manually in 32 bit Mac apps since they use the legacy Objective-C runtime (which you can read about in the Objective-C 1 Runtime Reference).

Also note it won't work on the iPhone itself, so to save constantly commenting out code, you can wrap the offending code in #if TARGET_IPHONE_SIMULATOR #endif pairs.

12:38 PM, 14 Jan 2010 by Mark Aufflick Permalink | Short Link | Comments (2)

Book Review: iPhone SDK 3 Visual Quickstart Guide


CocoaHeads Sydney member Duncan Campbell has just published a book with PeachPit press titled "iPhone SDK 3 Visual Quickstart Guide".

Like all of Peachpit's "Visual Quickstart Guides", the book is mostly broken into two columns - text and images. At first I thought it would suck! As soon as I got into it though, I quite liked the thin column. It has readability like a newspaper, although it did make following inline code a little tedious.

The book covered all the basics you need for making a great app, and made some tricky tasks simple - like custom cells and multi-touch.

It avoids a common approach of many intro books where they continually build into an ever evolving single app. Instead, each example is short and entirely standalone. I have to say it was refreshing - it avoided wasting time in frivolities and allowed the author to introduce concepts at the time he chose, rather than the time it was needed to continue building the app.

I also appreciated the time spent on one of the most important rools - the Xcode interface. Even I learned a handy Xcode shortcut!

The choice to use code for UI layout instead of interface builder makes the writing easier to follow, no enless 'click here, control click and drag here...' and also avoids those madenning bugs where you've missed a step but can't easily compare the compound result. Similarly, the continual tweaks to IB won't invalidate the examples.

I also appreciated how each example was standalone - building and running an interesting looking example didn't rely on carefully building examples stretching back through previous chapters.

Two extra chapters can be downloaded as PDFs from the Peachpit press website once you have the book covering the Address Book api and the Media apis. The latter is very useful - covering saved images, using the camera and playing audio and video.

While this is a book for people starting out with iPhone programming, it's not for people who have never programmed before. If you have programmed before but don't know at least the bare basics of one of C, C++, Objective-C then I would suggest completing an introduction to Objective-C first. Apple has one and there are lots of great books.

One of the positives above is that the use of code to create UI controls is repeatable, easy to error check and shows how it all works. Once you start building apps, though, you'll use Interface Builder a lot. You'll need to brush up on that after completing this book. Again, Apple has one and there are lots of great books! Aaron Hillegass's Cocoa Programming for Mac OS X will cover both Objective-C and Interface Builder really well - and you'll learn how to write MacOS X apps to boot!

So in summary, it's a great book. I enjoyed it and you hopefully will too! Available at Amazon and all good bookstores :)

07:33 PM, 25 Oct 2009 by Mark Aufflick Permalink | Short Link | Comments (2)

Problem compiling Erlang 13B02 on MacOS

I was getting the following error compiling erlang 13B02 on MacOS Leopard:

Thanks to the Google translation of a page in Japanese on javaeye.com (link) I figured out I had to rebuild wxWidgets (even though version 2.8 already seems installed in Leopard). Here's the nub of it:

  • Download wxWidgets 2.8.x, untar to a directory of your choice
  • cd into the un-tarred directory and make a build dir (eg. mkdir MYBUILD)
  • cd into that new directory and build a static install into a destination of your choice (I put it in /opt/wxWidgets28):
    ../configure --with-opengl --enable-unicode --enable-graphics_ctx --enable-gnomeprint --disable-shared --prefix=/opt/wxWidgets28
    make
    sudo make install
    cd contrib/src/stc
    make
    sudo make install
  • Now you can build OTP/Erlang properly, but make sure the new wx-config is first in your path, eg:
    PATH=/opt/wxWidgets28/bin:$PATH ./configure ....

06:53 PM, 30 Sep 2009 by Mark Aufflick Permalink | Short Link | Comments (2)

Higher Order Perl now available as a *free* PDF

I've reviewed "Higher Order Perl" by Mark Jason Dominus before - it's a great book for people who know Perl and want to master topics such as parsing or memoisation or who want to incorporate more functional approaches such as currying into their code.

It's worth buying, but now you can also get a free PDF thanks to the generosity of the author, Mark Jason Dominus:

http://hop.perl.plover.com/book/

02:37 PM, 17 Sep 2009 by Mark Aufflick Permalink | Short Link | Comments (0)

Safari 4.0.2

Unfortunately the recent Safari 4.0.2 update doesn't seem to have fixed the cpu usage runaway with Google Apps email. Basically after some time (say 10 minutes) of having Google Apps email open, Safari 4 goes to 20% cpu usage and stays there.

It's a bug in either Google's Javascript or in Safari because the cpu utilisation is minimal in the first 10 minutes, and drops back to zero again as soon as you close the tab with Google Apps email.

I was *really* hoping that the "Nitro stabilisation" improvements would resolve that.

08:22 AM, 13 Jul 2009 by Mark Aufflick Permalink | Short Link | Comments (0)

ruby 1.9 issue on Mac (MacPorts) : [BUG] unknown type 0x22 (oxc given)

From reading internet threads about the error, [BUG] unknown type 0x22 (oxc given), it seems to occur when C code compiled against ruby 1.8 is loaded into ruby 1.9.

At least using the MacPorts ruby 1.9 install there is a very odd issue related to this. You get a crash, under some circumstances, when a gem loads into ruby 1.9 and the MacOS linker decides it's a good idea to link against the standard OS installed version 1.8 libruby.

What's especially odd is that the stack trace doesn't show it, but i did track it down by running lsof in a while /bin/true loop as I caused the crash:

...
ruby1.9 41978 aufflick txt REG 14,2 3148976 67264 /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/libruby.1.dylib
...
ruby1.9 41978 aufflick txt REG 14,2 1906476 3915360 /opt/local/lib/libruby1.9.1.9.1.dylib
...

Now to find a way around it!

Update: I may have found the culprit. The ruby core .dylib files (the Mac equivalent of .so files) are correctly linked to the ruby1.9 library, but the thin library (installed via gem1.9) is not:

bash-3.2$ otool -L /opt/local/lib/ruby1.9/gems/1.9.1/gems/thin-1.2.1/lib/thin_parser.bundle
/opt/local/lib/ruby1.9/gems/1.9.1/gems/thin-1.2.1/lib/thin_parser.bundle:
/usr/local/lib/libruby.dylib (compatibility version 1.8.0, current version 1.8.6)
...

Now I can manually tweak this with install_name_tool, but the gem build process must be broken somehow...

Update 2: That wasn't the problem. I fixed the linking path in the thin_parser.bundle:

sudo install_name_tool -change /usr/local/lib/libruby.dylib /opt/local/lib/libruby1.9.dylib /opt/local/lib/ruby1.9/gems/1.9.1/gems/thin-1.2.1/lib/thin_parser.bundle

but it still crashes...

Update 3: It's something to do with the MacPorts build. I did a compile from source of runby 1.9.1 into a new prefix and ruby/rack/thin work fine. Sweet!

05:19 PM, 10 May 2009 by Mark Aufflick Permalink | Short Link | Comments (0)

Functional map_each method for Ruby Hash

I prefer to use functional style programming wherever possible. In many popular dynamic languages such as Perl, Python or Ruby there is quite good support for functional programming with arrays such as Perl and Ruby's map and Python's even better list comprehensions.

With hashes (or dictionaries or whatever you call them) you're usually stuck to sequential programming. Since in Ruby hashes are objects we can inject a nice map_each method into the Hash class which will process each key value pair and the resultant list will have one result for each pair.

class Hash
  def map_each
    ret = []
    self.each do |key, val|
      ret.push yield(key, val)
    end
    ret
  end
end

02:53 PM, 09 May 2009 by Mark Aufflick Permalink | Short Link | Comments (0)

Opportunistically streaming html output with Ruby lambdas

In my last post (Ruby, HTML, s-expressions, lambdas?) I said I would show how we can modify the html generation to allow streaming.

Of course I was making it out to be a lot more complicated in my head than it really is - all the hard work is done already by the lambdas enforcing correct execution order. All we need to do is add a few judicious STDOUT.flush calls before anything that might take some time (ie. evaluating the tag content which could include a database lookup etc.)

I've done that in the new htm.rb below, but first, here's some demo code with some delays:

engines = [["http://google.com/", "Google"],
           ["http://yahoo.com/", "Yahoo!"],
           ["http://webcrawler.com/", "Showing my age"]]

Htm.htm(:ul, engines.map \
        { |e| Htm.htm(:li,
                      [:a, :href, e[0], [:b, lambda { sleep 3; Htm.str(e[1])}]])}).call

Notice also how we can use a lambda anywhere we can put content. Instead of a sleep, perhaps it's an external ImageMagick command. Or perhaps instead of the map iterator our loop is iterating over results being streamed from a slow database query.

Our output will look the same, but I've indicated with !!! where the output pauses for 3 seconds:

<ul><li><a href="http://google.com/"><b> !!! Google</b></a></li><li><a href="http://yahoo.com/"><b> !!! Yahoo!</b></a></li><li><a href="http://webcrawler.com/"><b> !!! Showing my age</b></a></li></ul>

You can see that the http stream will receive all the output it possibly can while waiting for the expensive operation, and the tags are still automagically closed. Job done!

Here's the up to date htm.rb:

require 'cgi'

module Htm
  def Htm.str(content)
    lambda { print CGI.escapeHTML(content.to_s) }
  end

  def Htm._build_tag(tag, args)

    # open the tag
    print '<' + tag.to_s

    tok = args.shift

    # find any tag attribute key/value pairs
    while tok.kind_of? Symbol
      print ' ' + tok.to_s + '="' +
        CGI.escapeHTML(args.shift.to_s) + '"'
      tok = args.shift
    end

    if tok.nil?
      # self-close tag if no content
      print ' />'
    else
      # finish open tag
      print '>'

      # output tag content
      Htm._eval_content(
                        tok.kind_of?(Symbol) ? Htm.htm(tok, args) : tok )

      # close tag
      print '</' + tag.to_s + '>'
    end
  end

  def Htm._eval_content(content)
    while content.kind_of? Proc
      STDOUT.flush
      content = content.call
    end

    if content.kind_of? Array
      Htm._eval_content(Htm.htm( *content ))
    elsif ! content.nil?
      print content
    end
  end

  def Htm.htm( *args )
    lambda do

      tok = args.shift

      while ! tok.nil?
        if tok.kind_of? Symbol
          Htm._build_tag(tok, args)
        else
          Htm._eval_content(tok)
        end
        tok = args.shift
      end
    end
  end
end

10:02 AM, 09 May 2009 by Mark Aufflick Permalink | Short Link | Comments (0)

Ruby, HTML, s-expressions, lambdas? Oh my!

I've been noodling around with various lisps lately, and one of the sources of lisp's elegance is the lack of separation between data and code. A practical example of that is the cl-who library which creates html from an s-expression representation, ensuring all tags are correctly closed. For example:

(with-html-output (*http-stream*)
  (loop for (link . title) in '(("http://zappa.com/" . "Frank Zappa")
                                ("http://marcusmiller.com/" . "Marcus Miller")
                                ("http://www.milesdavis.com/" . "Miles Davis"))
        do (htm (:a :href link
                  (:b (str title)))
                :br)))

There are a number of ways to replicate this style in other languages. You can do it by building up a big string, but I want to print to a stream like the example above. Using lambdas we can make a pretty good approximation in Ruby. Here's some Ruby code using a simple module I whipped up (see below) to achieve the same output as the cl-who lisp code above:

engines = [["http://google.com/", "Google"],
           ["http://yahoo.com/", "Yahoo!"],
           ["http://webcrawler.com/", "Showing my age"]]

Htm.htm(engines.map { |e| Htm.htm(:a, :href, e[0], [:b, Htm.str(e[1])],
                                :br, nil)}).call

Lets say we realise that the br tags are nasty and want to put the list of links into a list:

Htm.htm(:ul, engines.map \
        { |e| Htm.htm(:li,
                      [:a, :href, e[0], [:b, Htm.str(e[1])]])}).call

It's not quite as elegant as the lisp equivalent because we are mixing lambdas and arrays - both as nesting constructs. Here is the final output (indented for clarity - the Htm module below does no indenting):

<ul>
  <li><a href="http://google.com/"><b>Google</b></a></li>
  <li><a href="http://yahoo.com/"><b>Yahoo!</b></a></li>
  <li><a href="http://webcrawler.com/"><b>Showing my age</b></a></li>
</ul>

Now even though we are controlling the order of execution such that the various parts will be printed to the stream in the right order, we still can't print until we have closed our outermost tag (usually html). To be able to stream output while also auto-closing the tags we're going to need to use continuations - I'll cook up an example of that for a later blog. There's also other neat ways we can have self-closing tags that will allow streaming - I'll post about that later also.

Here is the Htm module in full:

require 'cgi'

module Htm
  def Htm.str(content)
    lambda { print CGI.escapeHTML(content.to_s) }
  end

  def Htm._build_tag(tag, args)

    # open the tag
    print '<' + tag.to_s

    tok = args.shift

    # find any tag attribute key/value pairs
    while tok.kind_of? Symbol
      print ' ' + tok.to_s + '="' +
        CGI.escapeHTML(args.shift.to_s) + '"'
      tok = args.shift
    end

    if tok.nil?
      # self-close tag if no content
      print ' />'
    else
      # finish open tag
      print '>'

      # output tag content
      Htm._eval_content(
                        tok.kind_of?(Symbol) ? Htm.htm(tok, args) : tok )

      # close tag
      print '</' + tag.to_s + '>'
    end
  end

  def Htm._eval_content(content)
    while content.kind_of? Proc
      content = content.call
    end

    if content.kind_of? Array
      Htm._eval_content(Htm.htm( *content ))
    elsif ! content.nil?
      print content
    end
  end

  def Htm.htm( *args )
    lambda do

      tok = args.shift

      while ! tok.nil?
        if tok.kind_of? Symbol
          Htm._build_tag(tok, args)
        else
          Htm._eval_content(tok)
        end
        tok = args.shift
      end
    end
  end
end

09:13 PM, 06 May 2009 by Mark Aufflick Permalink | Short Link | Comments (0)

Adding Apple Remote Support to your Cocoa App

Here is the presentation I gave at last month's CocoaHeads:

Or you can download the pdf from the CocoaHeads AU Google group: apple_remote.pdf.

10:24 AM, 05 May 2009 by Mark Aufflick Permalink | Short Link | Comments (0)

CocoaHeads Sydney - May 7th 2009

CocoaHeads Sydney is steaming along with our fourth monthly meeting on the trot this Thursday.

Last month at CocoaHeads Sydney I gave a lightning talk showing how to add Apple IR support to your Cocoa app. I have uploaded the slides to the files section of the google group. In the presentation I also showed how I used the LaTeX beamer class to make pdf slides, and I used the open source SplitShow application to give the presentation (using my Apple IR support of course!) You can get SplitShow from the google code project but you'll have to build from the trunk to get the IR support which has not yet been included in a release.

We also had Ben Hill show us the impressive prototype of an OpenGL iPhone game he put together using cocos2d.

This month our very own Jude Sutton will be giving us a presentation on the Authorisation Services and related APIs.

This month's details:

When: Thursday May 7th, 6:30pm
Where: UTS Broadway CB10.07.114. ie. Building 10, Level 7, Room 114
Calendar:

All details are published monthly on the CocoaHeads AU google group.

Hope to see you there!

10:12 PM, 03 May 2009 by Mark Aufflick Permalink | Short Link | Comments (0)

Native MacOS Umbrello in KDE4

One of the consistently popular pages on this website is my blog entry about building Umbrello on MacOS. Umbrello is the KDE UML modelling program. UML modelling programs are mostly surprisingly rubbish, so Umbrello being not rubbish is one of the better ones and it's open source to boot.

It has, though, been tough to build on MacOS even just under X11 (as witnessed by the long list of comments on my earlier blog with various configure recipies). KDE4 promises to resolve that with the native MacOS Qt support allowing Mac native applications.

The Mac KDE project has beta downloads of the (nearly) full KDE environment for Mac. All the bits you need are at http://mac.kde.org/ but note they are hosted on an ftp server that allows you to only download one file at a time, so let one finish before you start the next. No compilation or commandline trickery needed - just installing normal MacOS packages.

After installing the various bits you will find a KDE4 folder in your Applications folder. Here's Umbrello running on my Mac:

There are a few oddities - I could maximise the window, but not drag the window size to anything other than the original or the maximum, but otherwise it seems quite solid.

10:38 PM, 17 Feb 2009 by Mark Aufflick Permalink | Short Link | Comments (2)

OMG - Lego Turing Machine

If this isn't the coolest thing you've ever seen in 2009 I'll eat my hat:

03:05 PM, 30 Jan 2009 by Mark Aufflick Permalink | Short Link | Comments (0)

heads up 'tunes featured on iLoveMacApps.com

James Powell has featured heads up 'tunes on his iLoveMacApps.com and also has some neat feature suggestions.

I'm not sure where the slowdown he is seeing is coming from so I'll quiz him on that, but clicking the song and hiding the dock icon are good ideas.

He has a pretty eclectic playlist :)

10:51 AM, 20 Jan 2009 by Mark Aufflick Permalink | Short Link | Comments (0)

Bringing Cubase LE into the 20th century

Cubase, like Photoshop and many other seemingly professional software packages, refuse to acknowledge that software developers (who you might consider important users) often choose to install their Macs with case-sensitive file systems. Mac OS X has had case sensitive file system options since 10.0 in 2001 included UFS.

Anyhoo, to make Cubase LE work after the installer botches it's attempts, run the following in your terminal:

CUBASE="/Applications/Cubase LE 4.app"

cd "$CUBASE/Contents"
sudo mv components Components
# documentation stays lowercase
# documentation files seem missing - can get them from steinberg website anyway
# fonts must stay lowercase
sudo mkdir -p Help
sudo mv help/* Help
sudo rmdir help
sudo mv presets Presets
sudo mv scripts Scripts
sudo mv Scripts/patchnames Scripts/Patchnames
sudo mv Scripts/trackmixer Scripts/Trackmixer
sudo mv Templates templates/unknown.cpr
# templates dir stays lowercase
sudo mv vstplugins VSTPlugIns


# in case future updates have different casing:
sudo ln -s Components components
sudo ln -s documentation Documentation
sudo ln -s fonts Fonts
sudo ln -s Help help
sudo ln -s Presets presets
sudo ln -s Scripts scripts
sudo ln -s templates Templates
sudo ln -s VSTPlugIns vstplugins

Or I zipped this up in a command file you can double click if you prefer: fix_cubase_case_sensitive.command.zip.

06:39 PM, 03 Dec 2008 by Mark Aufflick Permalink | Short Link | Comments (1)

By popular demand, heads up 'tunes 0.4

There's a raft of new features, none cooler than the popup you get if you hover over an album cover when the window is too small to show any text. Pictured left.

Happy Matt?

The big change is that it's now designed to stay running all the time. When you pause or stop iTunes, the hut window will tastefully fade away. When iTunes fires up again, it will come back. There are a number of new options in the prefs window to support that such as adding to your login items.

Available now :)

11:07 PM, 01 Dec 2008 by Mark Aufflick Permalink | Short Link | Comments (1)

heads up 'tunes Version 0.3

This release adds a new preference to stick the hud display to all spaces, as per Mr Barnes request.

I also changed the framework used by the prefs window, so let me know if there are any issues or raise a bug: http://mark.aufflick.com/software/heads-up-tunes/bugs

11:43 PM, 20 Nov 2008 by Mark Aufflick Permalink | Short Link | Comments (2)

heads up 'tunes Version 0.2

The much awaited version 0.2 of my iTunes thingamy is now released! Version 0.1 installations should find the update automatically or go to the home page to download it yourself.

You can now resize the window yourself, so it can be skinny or wide:

You can turn off the shadow if you wish, and it now remembers it's window position between runs. And that's about it :)

No comments about my music selection please!

06:59 PM, 17 Nov 2008 by Mark Aufflick Permalink | Short Link | Comments (0)

heads up preview for iTunes

heads up 'tunes version 0.1When I'm listening to music I like to know what tracks are queued up. Call me a control freak.

One doesn't normally have enough screen space to leave iTunes visible though, so I figured what I wanted was a heads up style panel, floating above all other applications, showing the current and upcoming songs. Something like the image on the right:

Surprisingly, no such app existed. There are many heads up controllers (which I don't need since I control tracks and level from my Apple bluetooth keyboard media function keys), or artwork viewers that display the current track only. There was no alternative but to suspend my study plan for an evening and write my own.

The result is heads up 'tunes. It's lightweight, nothing fancy (although I will add animation to it one day). You can download the current version at the software home page:

http://mark.aufflick.com/software/heads-up-tunes/

Here's the blurb from the about box:

This is a preliminary version of heads up 'tunes.

Pretty much all this program does is display the current and next two iTunes™ tracks in a "heads up" style window. It works fine with genius and party shuffle as well as manual and smart playlists. Results will be disappointing when using regular shuffle mode since it is not possible to determine what track will come next.

Please visit http://mark.aufflick.com/software/heads-up-tunes for future releases.

Please email any bug reports to mark@aufflick.com.

© Copyright 2008 Mark Aufflick. This software is free for you to use. No warranty is provided with this software except that which cannot be excluded by such disclaimers. This is free pre-release software - use at your own risk :) iTunes™ is a Trade Mark of Apple.

Oh, and it also sets its dock icon to the current track artwork. It's a Universal binary and has been tested on PPC (by me) and Intel (by Matt B and DB). Enjoy!

04:01 PM, 25 Oct 2008 by Mark Aufflick Permalink | Short Link | Comments (6)

XML

Blog Categories

software (39)
..cocoa (21)
  ..heads up 'tunes (5)
..ruby (6)
..lisp (3)
..perl (4)
..openacs (1)
mac (20)
embedded (2)
..microprocessor (2)
  ..avr (1)
electronics (3)
design (1)
photography (25)
..black and white (6)
..A day in Sydney (18)
..The Daily Shoot (6)
food (2)
Book Review (2)

Notifications

Icon of Envelope Request notifications

Syndication Feed

XML

Recent Comments

  1. Unregistered Visitor: An other Script
  2. Unregistered Visitor: A message in there?
  3. Unregistered Visitor: using Amazon S3
  4. Unregistered Visitor: Thank you ! Thank you ! Thank you !
  5. Unregistered Visitor: Umbrello on leopard
  6. Unregistered Visitor: Script gor generate for library
  7. Unregistered Visitor: Similar but different
  8. Unregistered Visitor: Thanks for fixing my problem!
  9. Unregistered Visitor: Pop up once the category is been defined
  10. Unregistered Visitor: smal amendment