Caius Theory

Now with even more cowbell…

+[NSObject load] in MacRuby

If you've not heard of it, MacRuby is an implementation of Ruby 1.9 directly on top of Mac OS X core technologies such as the Objective-C runtime and garbage collector, the LLVM compiler infrastructure and the Foundation and ICU frameworks. Basically means you write in Ruby using Objective-C frameworks, and vice versa. It's pretty damn cool to be honest!

What is +[NSObject load]?

From the documentation:

Invoked whenever a class or category is added to the Objective-C runtime; implement this method to perform class-specific behavior upon loading.

This means when your class is loaded, and implements the load method, you get a load message sent to your class. Which means you can start doing stuff as soon as your class is loaded by the runtime.

The main place I've seen it used (and used it myself) is in SIMBL plugins. A SIMBL plugin is an NSBundle that contains code which is loaded (injected) into a running application shortly after said application is launched. It lets you extend (or "fix") cocoa applications with additional features. So you have this bundle of code, that gets loaded into a running application some point after it starts, and you want to run some code as the bundle is loaded - usually to kick off doing whatever you want to do in the plugin. This is where load becomes useful.

Here's a quick implementation that just logs to the console:

    @implementation MainController
    
    + (void) load
    {
        NSlog(@"MainController#load called");
    }

Now where does MacRuby come into this?

Well I came across a need to do the same in ruby, have some code triggered when the class is loaded into the runtime. Tried implementing Class.load but to no avail. Then remembered MacRuby is just ruby! And I can call any code from within my ruby class definition.

For continuity I still call it Class.load, but then call it as soon as I've defined it in the class. Eg:

class MainController
  def self.load
    NSLog "MainController#load called"
  end

  self.load
end

Of course, I'm not sure when the Objective-C method is called, it's probably after the entire class has been defined rather than as soon as load has been loaded into the runtime. So you might want to move the self.load call to just before the closing end.

iPad? iPerfect (…for me)

Google Groups is a pile of fail and hasn't posted my message in reply to a thread on Geekup so I'm blogging it instead.

On 27 Jan 2010, at 19:53, Steve Richardson wrote:
Thoughts?

I've been searching for a device to fit between my Macbook Pro and iPhone. I work all day on the MBP, and moving it to then watch video in another room or read twitter/news/mail whilst watching telly, etc is a pain.

The iPhone is a great little device on the move, but for trying to multitask at home it's a bit.. tedious. Even jailbroken and running multiple apps at once it's still limiting.

I'd been looking around at netbooks, but what put me off actually getting one was my previous experience with one. I know I'd want it to run OS X to keep in sync (easily) with my other Apple devices, but hackintoshing one was a bit too much hassle, plus the fact ones to hackintosh cost more than I really wanted to pay for something that wasn't quite what I thought I needed.

And then.. the iPad. I've been sort of keeping up with the rumours (mainly through Daring Fireball) and whilst I didn't get excited about it too much ahead of announcement1, having seen the official video of it it's pretty much guaranteed that I'm going to get one.

Yes, it's limited (App Store, closed device), but.. I don't care. Take the iPhone, it's good enough for doing things on it, even if someone else is in charge of the ecosystem and has a big finger saying yes or no. I (willingly) use iTunes, Mobile Me, all the things that are so wonderfully integrated in the world of Apple, so another device that consumes my media using channels I already know and use is just a massive win for me.

All I'm hoping now is that $499 doesn't equal £499. Hopefully it'll be £399, still a good £80 above direct exchange rate, but low enough that it's a no-brainer for me to get one.

…And I think this is the first Apple product that I've seen announced and actually known from the start why I'm going to get one, instead of just a knee-jerk "SHINY!!!! WANT!!!" reaction. Uh oh, does that make me an adult?

1 I miss getting really excited about apple announcements :(

Update

It just got even better. Was lamenting to a friend on IM that it'd be so much nicer once you can directly suck photos off a camera/SD card into it. Turns out there's an adapter for that. See "iPad Camera Connection Kit" at the bottom of http://www.apple.com/ipad/specs/ for details.

Read Later in a keystroke

I use a wonderful service for saving text to be read later, instapaper.com. It's gotten more wonderful as time has gone on and other applications/service's have gained the ability to save links/articles/webpages there for me to pick up later.

For instance, I'm out and about checking twitter on my iPhone using tweetie and someone tweets a link. Rather than wait for it to load and having to read it then and there I can just hit "Read Later" and it's saved in my instapaper account for me to read as and when I choose to. Recently the legendary mac feed reader NetNewsWire gained this ability too.

There's a few ways to send a feed item to instapaper from within NNW. Firstly you can right-click and click "Send to Instapaper".

Send to Instapaper from contextual menu
View Original on Flickr

Secondly there's a menu item for it in the News menu, which also provides my chosen way of instapapering an item—the keyboard shortcut! ⌃P (control-P).

Send to Instapaper from News menu
View Original on Flickr

So, in NNW I'm happily sending stuff to instapaper with the handy ⌃P shortcut, but that doesn't exist in the third place I mark things to read later–Safari! Up until now I've been using the standard "Read Later" bookmarklet that instapaper.com provides, and it's got a spot on my Bookmarks Bar so I can easily click it.

That doesn't really help with the fact I'm hitting ⌃P in NNW, and it doesn't work in Safari. Quite often I noticed myself hitting the key combination in Safari and wondering for a split second why it wasn't sending the item to instapaper. Then the solution hit me!

In OS X you can setup (and/or override) menu items with custom key combinations! Why hadn't I remembered this before. Because the "Read Later" bookmark(let) is nested under the Bookmarks menu, it is a menu item! A quick trip into the Keyboards Prefpane in System Preferences and a new binding later and voilâ, "Read Later" in Safari is bound to ⌃P and I can use it in both Safari and NNW.

Filling in the form to bind the keyboard shortcut
View Original on Flickr

My Menubar Items

This is a something that occasionally makes the rounds again, I've not seen it for a while and I've added some new items since I last remember documenting it. Thus, @macarne asking what the app was that gives me stats prompted me to document my current menubar items.

annotated-menubar by ©aius, on Flickr

View original

  1. SMCFanControl - Lets me adjust the minimum speed of my fans.
  2. Tweetie/mac
  3. iScrobbler - Scrobbles tunes iTunes plays
  4. LittleSnapper (Or more accurately the menubar icon is NanoSnapper, LittleSnapper is the full app.) Mainly used for screen grabs.
  5. SlimBatteryMonitor - Takes up less horizontal space than Apple's menu item.
  6. Expresscard menu item - Lets me power off my Expresscard/34 SSD
  7. MenuMeters - An old friend I've been using for as long as I can remember running OS X. Set to show (left to right)
    1. Ram - Used and Free totals.
    2. Network - Graph + values.
    3. CPU - Graph per core. Probably the most useful out of the three.
  8. Bluetooth
  9. Time Machine
  10. Modem - To dial on my Huawei E220 3G stick.
  11. Airport
  12. Sound
  13. Day/Time
  14. Fast User Switching - Not sure why I keep this in the menubar, only have one user and I lock my screen with a password protected screensaver.
  15. Viscosity - VPN software. Pretty useful.
  16. Spotlight! - Occasionally this vanishes when spotlight decides to be a dick and eat ram/cpu reindexing my disk every few hours. Touch wood it hasn't done it since 10.6.1.

Filter through command

This is another old post that I'm republishing. Originally published 27th April 2007.

My text editor TextMate has a nice feature called "Filter through command" whereby you can filter the current document through a command.

Anyway, I've never used it before, but today I had a text file with 30 or so url's in, each on a new line, so I thought I'd test it out. I selected it to input the document & to not replace the output. I then entered the following command, which is a ruby command to take each line that isn't blank, and run the shell command open $url.

ruby -e 'a = ARGF.read.scan(/\S+/); a.each { |x| `open #{x}` }'

What this does is take ARGF (the document) and read it in line by line, but only the non-whitespace characters (so newlines, space, etc are ignored.) And it assigns it to an array called a. What I then do is for each item of a, we run it past the shell command open, which on OS X if you pass it a URL it just opens that URL in the default browser.

My browser is Safari, and its set to open new links in a new tab in the foremost window. So I ran the command, and hey presto, within a few seconds I had all the URL's loading in seperate tabs in Safari's foremost window!

The power of Unix (OS X) & TextMate (amongst other tools) just never ceases to amaze me.

Update

I just realised if you change the regex to scan for http://.* then it'll select all website URLs.

ruby -e 'a = ARGF.read.scan(/^http://.*$/); a.each { |url| `open #{url}` }'

Mac Tips you may not know

Here are some mac tips I know and consider "basic" mac knowledge, but no-one else seems to know.

(Alternative title Peter Cooper suggested, "A miscellany of input device co-ordinations to modulate the response of Apple's task preview and switching subsystem")

Capitalise "ringer" on the iPhone Volume Bezel

Backstory: Got myself a first generation iPhone second hand and unlocked it to work on my existing T-Mobile (Official iPhone network in the UK is O2.) Noticed after a week or so of owning it that when you change the volume on the phone, the bezel that comes up says "ringer" across the top. But when you have headphones plugged in, it says "Headphones". (Note the capitalisation difference.)

Now I'm not usually bothered by stuff like this (honest!) but as soon as I'd noticed the "bug", I couldn't help but think of it everytime I changed the volume, whether I was looking at the screen or not. Seeing as I'm running a jailbroken phone, and therefore have SSH access to it, I figured the string would be defined in a .strings file somewhere in the /System folder. And I'd be able to change it!

Fast-forward a few months and I install the iPhone OS 3.0 update (jailbroken of course), and finally decide to turn the phone's SSH server on and go looking for the setting. To do so I figured I'd just need grep installed on the phone - I could copy the file itself to my mac and edit it there.

So I connect to the phone, have a poke around the filesystem and then start a search to find the correct file:

# On the iPhone
$ cd /System/Library/
$ grep -r "ringer" *
Binary file CoreServices/SpringBoard.app/English.lproj/SpringBoard.strings matches
Binary file CoreServices/SpringBoard.app/M68AP.plist matches
Binary file CoreServices/SpringBoard.app/SpringBoard matches
Binary file Frameworks/CFNetwork.framework/CFNetwork matches
Binary file Frameworks/CFNetwork.framework/da.lproj/Localizable.strings matches
Binary file Frameworks/CFNetwork.framework/no.lproj/Localizable.strings matches
Binary file Frameworks/Foundation.framework/da.lproj/URL.strings matches

At which point I stopped the grep search (^C) because I know the home screen of the iPhone is the SpringBoard.app, so I figured it would be in the file SpringBoard.app/English.lproj/SpringBoard.strings. Making sure to have SSH enabled on your mac, a simple scp CoreServices/SpringBoard.app/English.lproj/SpringBoard.strings user@your_mac.local: later and the file is sat in my home folder on my mac.

Switching to the mac, now I try and open the file with TextMate, only to realise its in binary format. I need it in the nice XML format to edit it, so a quick google later and I've found a hint on MacOSXHints telling me how to convert from binary to xml plist format.

# On the mac
$ plutil -convert xml1 SpringBoard.strings

Then opening the file in TextMate was a bit more successful! I can actually understand what its defining now. Search through the file for "ringer" and I found the following lines:

<key>RINGER_VOLUME</key>
<string>ringer</string>

Change the "ringer" to "Ringer" between the <string> and my editing work is complete! Yes, it really is that easy to edit an interface string that is defined in a .string. Now I just need to convert the file back to binary, and copy it back to the phone. Converting back to binary file is one line, just change the xml1 in the previous command to binary1.

# On the mac
$ plutil -convert binary1 SpringBoard.strings

And then scp it back to the phone, make a backup of the existing file, and overwrite the existing file with the new one I've edited:

# On the iPhone
$ cd ~
$ scp user@mac_name.local:SpringBoard.strings .
$ cd /System/Library/CoreServices/SpringBoard.app/English.lproj/
$ mv SpringBoard.strings SpringBoard.strings.bak
$ cp ~/SpringBoard.strings SpringBoard.strings

And then restart the phone, either in the usual manner or just run reboot on the phone via SSH. Lo and behold once its rebooted and I changed the volume, it read "Ringer"!

Screenshot of Volume bezel

Safari 4 Hidden Preferences

Updated 2009-06-09: This post is for the Safari 4 beta and will not work with the new Safari 4 released yesterday at the WWDC keynote. I've had a look through that release and can't see any way to revert the address bar, etc sorry.


Having a quick poke through the new Safari binary yields the following strings:

$ strings /Applications/Safari.app/Contents/MacOS/Safari | grep DebugSafari4
DebugSafari4TabBarIsOnTop
DebugSafari4IncludeToolbarRedesign
DebugSafari4IncludeFancyURLCompletionList
DebugSafari4IncludeGoogleSuggest
DebugSafari4LoadProgressStyle
DebugSafari4IncludeFlowViewInBookmarksView
DebugSafari4TopSitesZoomToPageAnimationDimsSnapshot
DebugSafari4IncludeTopSites

NB: Run these commands in Terminal.app and then you need to restart Safari for them to take effect.

DebugSafari4TabBarIsOnTop

This moves the tab bar back where you expect it to be:

$ defaults write com.apple.Safari DebugSafari4TabBarIsOnTop -bool NO

DebugSafari4IncludeToolbarRedesign and DebugSafari4LoadProgressStyle

When both set to NO it restores the blue loading bar behind the URL. Also puts a page loading spinner in the tab itself, which looks odd with the new tabs.

$ defaults write com.apple.Safari DebugSafari4IncludeToolbarRedesign -bool NO
$ defaults write com.apple.Safari DebugSafari4LoadProgressStyle -bool NO

DebugSafari4IncludeFancyURLCompletionList

Switches off the new URL autocomplete menu and goes back to the original one.

$ defaults write com.apple.Safari DebugSafari4IncludeFancyURLCompletionList -bool NO

DebugSafari4IncludeGoogleSuggest

Turns off the new Google suggest menu.

$ defaults write com.apple.Safari DebugSafari4IncludeGoogleSuggest -bool NO

DebugSafari4IncludeFlowViewInBookmarksView

Removes CoverFlow from the Bookmarks view entirely. (Credit to Erik)

$ defaults write com.apple.Safari DebugSafari4IncludeFlowViewInBookmarksView -bool NO

DebugSafari4TopSitesZoomToPageAnimationDimsSnapshot

Disables the dimming when you click on a Top Site and it scales the screenshot up to fill the screen.

$ defaults write com.apple.Safari DebugSafari4TopSitesZoomToPageAnimationDimsSnapshot -bool NO

DebugSafari4IncludeTopSites

Disables Top Sites feature completely.

$ defaults write com.apple.Safari DebugSafari4IncludeTopSites -bool NO

Undoing changes

Just run the defaults command with the delete flag for the appropriate key you wish to delete.

$ defaults delete com.apple.Safari <key>

NB: Don't include the -bool NO at the end, it just requires the key (eg: "DebugSafari4IncludeGoogleSuggest")

Update 2009-02-26

Jools points out in the comments how to reset the recent searches in the google search box.

Update 2009-05-26

Lowell's kindly created a Mac OS X application to edit these settings without using Terminal. http://github.com/cocoastep/tweaky

Update 2010-11-18

Patric has kindly translated this post into Belorussian and posted it on his site.

Fix Mail.app crashing after 10.5.6 upgrade

When you upgrade to Mac OS 10.5.6, Mail.app might start crashing a few seconds after starting due to the GPG Bundle.

The solution is to grab the updated version of the GPG bundleGPGMail_d55_Leopard.dmg

Installing Ubuntu on an iMac G3

I decided to install ubuntu onto my iMac G3450Mhz G3, 768mb ram, 20GB Hard Drive to play around with. Only problem was it would boot so far, then just stop at a black screen. In googling the fix, the blog post that contains the fix is slightly outdated and 100% 404.

Here is the fix, updated for Ubuntu 6.10 Desktop PPC:

  1. When the screen goes black, drop to the console

     Control - Option - F2
    

    (if you need to log in use the name ubuntu to log in.)

     $ sudo nano /etc/X11/xorg.conf
    
  2. Change the frequencies in monitor section as follows:

     Section “Monitor”
         Identifier “Generic Monitor”
         Option “DPMS”
         HorizSync 60-60
         VertRefresh 43-117
     EndSection
    
  3. After the changes then type control-o, return (to accept the filename), then control-x (save and exit nano)
  4. Restart X by running the following:

     sudo killall gdm && sudo /etc/init.d/gdm start