More of a programming nerd than is strictly healthy. See also {nevyn.nu, thirdcog.eu, twitter}

Projects

Overooped

Media keys hook in Mac OS X

There is no nice (or is it even official?) way of detecting and handling the media keys on the user’s keyboard. One can intercept events with type NSSystemDefined and subtype 8 in -[NSApplication sendEvents:], but this has major problem: any other applications that listen to the media keys will receive these events too. This means for example that if only Spotify is running and you want to pause your music, iTunes will start when you press play/pause. If you have VLC running in the background, it will also start playing.

Apple has solved this problem internally by having their media key using applications cooperate and resign media key controls to the application that was in the foreground most recently. However, there is no way for third party applications to join this cooperation.

I have implemented a workaround that does this using a CGEventTap in the Cocoa class SPMediaKeyTap. The advantage of using an event tap instead of just intercepting the events in -[NSApplication sendEvent:] is that you have the power to throw the event away. This way, we can decide to “own” the media keys and be the only app that listens to them.

This class is smart enough to resign the media key event tap whenever another application that we know will want to use the media keys becomes active, and keeps track of which media key using app was recently started.

If everyone uses this class, and everyone add each other’s bundle ID to that list of whitelisted bundle ID’s, we’ll get nice behavior from all apps. An even better solution would be if Apple provided a way of acquiring the media keys.

Reblogged from Oh Hey There

thedevilswater:

(Source: fscottfitzgerald)

Maybe half of Spotify’s dev team is completely addicted to Minecraft. We spent maybe six hours last night making this on our own multiplayer server. It doesn’t come through very well in a still picture, but that thing there is *huge*. (For perspective, this is from during the construction process (or rather the first; we redid the whole thing after that due to mistakes))

Maybe half of Spotify’s dev team is completely addicted to Minecraft. We spent maybe six hours last night making this on our own multiplayer server. It doesn’t come through very well in a still picture, but that thing there is *huge*. (For perspective, this is from during the construction process (or rather the first; we redid the whole thing after that due to mistakes))

List of capabilities web apps need but can’t currently have

I despise using web apps. The only ones I’ve found that are even at least useful are made by Google, and Google’s web apps are as aesthetically pleasing and user friendly as a Windows 98 shareware app. But even if they were made with the same care and attention to detail as Mac apps by Cultured Code or Omni Group, they’d still have a long way to go before being as useful and productive as a native desktop app, because they’d be missing some essential features the browser can’t give them. This is my list of these features, as I think of them.

There is one things a web app can’t *ever* have without doing tons and tons of work, and that is behaving like a native app. Google has fake context menus in their apps for example, but they don’t contain the options normally available when context-clicking text in Mac OS; for example, right clicking a word in Wave won’t let me look it up in the dictionary, speak it, nor do spelling corrections on it. Moving down a list using arrow keys is a very standard feature in list views in native apps; in Gmail this is an advanced feature you have to turn on, and you have to use letter keys to do the navigation (j, k for down, up).

I originally made this list in Wave over a year ago; moving it here since Wave is dying. The list is made a little bit antique by the introduction of the iPad; three of the items might now fall under the category of “things a native app might not need”.

The big wins you get with web apps are all in deployment. Deploy-once, instant upgrades, cross-platform. You can argue that sacrificing usability for easier deployment is worth it, but I’d rather do it the other way around.

Michael Casteel is my new hero! Got mom a 13” MBP a while ago to replace a Performa, but she missed Klondike and none of the other osx card games I had found were as good. Turns out Casteel ported his original Klondike to OS X! It’s originally a game for the Plus, I hadn’t even considered that he still worked on it.

Reblogged from Andrey Subbotin

Andrey Subbotin: iPhone 4 @2x assets made easy

We were updating our app’s graphics for the gorgeous screen of iPhone 4 the other day and it was a pain to update all the 163 PNG files we had and not to miss a thing.

So, I’ve come up with a simple Ruby script that checks that for each @1x image you have a properly sized @2x image.

Man, such a life saver. sudo gem install ios-png-check is the path to bliss.

One-line closures in ObjC without blocks; or, NSInvocation fun

Objective-C is wonderfully dynamic. One of my favorite wonders is the invocation grabber. I never paid them much attention at first, only using them when I explicitly needed an NSInvocation for some API. Then, I started working at Spotify and found a certain header file; suddenly, I saw the light.

If you know what that an invocation grabber is, you can just skip down to the code. For the rest, I’ll elaborate.
Shortcut: Just gimme the juicy bits, I’m impatient!

NSInvocations

An NSInvocation is a standard Foundation class that wraps four pieces of information all related to calling a method:

Or, in the form you are used to see these parts in code:

[target partOfSelector:argument1 secondPartOfSelector:argument2]

Normally, these are kind of tricky to construct, particularly the method signature. However, Objective-C’s message forwarding mechanism practically gives them to us for free!

Message forwarding?

(Short clarification detour: In Objective-C, you almost never call methods directly; instead, you send messages to objects, and the receiver almost always responds to the message by calling the method corresponding to that message on itself. This is why the terms ‘method calling’ and ‘messaging’ are often used interchangeably in ObjC, but they are not the same thing.)

When you call a method on an instance whose class does not define that method, you don’t get a compiler error as in C++. When you then run your code, the runtime assumes that you’re trying to do message forwarding. Message forwarding means that the receiver of the message will not itself handle the message, but is only a proxy for some other object. One common example is Distributed Object, where you’re sending messages (calling methods) on objects in other applications, or even other applications on other computers.

Writing an invocation grabber

This is where the invocation grabber comes in. We can create a class that does nothing but listen for message forwarding requests, and when it receives one, asks the target what it would respond to such a request. Given this answer, an NSInvocation can be created which matches the invocation of the message we sent to it.

Consider the following example:

We define a MyClass, create an instance of it, then create an invocationGrabber with that new MyClass as its target, and then try to call -[MyClass areTheNewViewersGoneYet:] on the grabber. Finally, we fetch the result of the invocation grabbing.

Note that line 9 does not call areTheNewViewersGoneYet: on your new MyClass. Instead, the grabber intercepts that call and gives us an NSInvocation that would have called that line just as we wrote it, but some time in the future instead of now. This is like a one-line closure, as the code, state and variables you send to the grabber are saved until later, just waiting to be executed.

Our invocation grabber does not implement a method with the selector areTheNewViewersGoneYet:. Given just the invocation grabber and that selector, the runtime would have no idea how to call it. Does it return a bool, in which case it will need to reserve four bytes for the return value? Or maybe a CGRect, in which case 16 bytes are needed.

So to figure this (and related things) out, the runtime will begin by asking for the method signature for the selector being sent with the message with -[NSObject methodSignatureForSelector:(SEL)]. Our SPInvocationGrabber itself has no idea, so we implement that method to ask the target:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)inSelector {
	return [_target methodSignatureForSelector:inSelector];
}

With the signature in hand, the runtime will now give you an NSInvocation and ask you to take care of invocation with -[NSObject forwardInvocation:]. In our case, we’ll just stash away the invocation for later use. In the example above, we created a yellowDuck and sent it as an argument to areTheNewViewersGoneYet:, and if we delay our execution of the NSInvocation, that duck might be released with the nearest NSAutoreleasePool. Thus, in forwardInvocation, we ask the NSInvocation to retain all its arguments. Don’t worry, when we release the NSInvocation, it will release those arguments too.

- (void)forwardInvocation:(NSInvocation *)anInvocation {
	[anInvocation retainArguments];
	anInvocation.target = _target;
	self.invocation = anInvocation;
}

That’s basically all there is to it! Some memory management and accessor methods, and we have our own invocation grabber.

So what’s all the fuss about?

Let’s start out with some code.

That’s the header. It has a few categories on NSObject, which is where it’s at. (A category on NSObject means that we are adding methods on almost all other classes; these three methods can be called on any instance of a class inheriting from NSObject.)

-[NSObject grab] gives you an invocation grabber for the receiver, so that instead of [[[SPInvocationGrabber alloc] initWithObject:foo] autorelease] we can just say [foo grab]. It doesn’t sound like much, but it goes a long way toward taking the hassle out of doing magic.

-[NSObject invokeAfter:] will give you a proxy object that, instead of performing the method you call on it right away, instead invokes it later. Again, doesn’t sound like much, but man, -[NSObject performSelector:withObject:afterDelay:] is a mouthful, and it doesn’t work with non-object arguments or calls that take more than two arguments. Suddenly delayed execution is simple.

-[NSObject nextRunloop] is the same as invokeAfter: with a zero second delay. This is the common idiom for having something executed the next runloop (or at least as soon as possible after the current runloop).

I’ll show you what it can do with some examples:

A: Yeah yeah, we could have set an animation delegate, and animation did finish selector, and from there called removeFromSuperview. That’s at least six lines of code. Now we did it with one: [[flash invokeAfter:duration+0.1] removeFromSuperview].

B: Some things work better if you call them very soon instead of right away. Sometimes it’s an animation that needs to have started before we can begin modifying it. Other times it’s a timing issue and creating a delegate or notification is a lot of hassle for something that will just work one runloop from now.

C: Hey, who thought animations could be so simple? Don’t worry if the view controller that owns that table goes away before the animation finished: the invocation grabber retains both the table view and the arguments, so for 450 milliseconds, those objects *will* remain.

There’s more magic, but I’ll go through that after the implementation:

First, stack trace saving. You have no idea how useful this is. If you do the old -[NSObject performSelector:withObject:afterDelay:] trick, you’ll note that sometimes you crash. You’ll also note that below the method you just delayed execution of, you have no useful backtrace. Fret not, for execinfo.h is here to save your day! When an SPInvocationGrabber is created, the names of the symbols on the stack are saved away with -[saveBacktrace]. Then, if you use the grabber’s invoke instead of -[NSInvocation invoke], the invocation will be wrapped in a try-catch, and in the event of an exception, the old backtrace will be printed, showing you the culprit that scheduled this broken future invocation.

As for those convenient categories on NSObject, they are ridiculously simple. All -[invokeAfter:] does is to create a grabber, schedule it for execution later with an NSTimer (before it has grabbed anything, even!), and then returns it, ready to grab something for later execution.

I’ve tried to create -[NSObject invokeOnMainThread] and -[NSObject invokeOnBackgroundThread], but those are trickier, because you can’t just schedule the invocation and then return the grabber, as -[NSObject performSelectorOnMainThread:withObject:waitUntilDone:] would perform -[invoke] immediately, giving us no time to do the invocation grabbing, as with -[invokeAfter:]. It’s easy to do on your own though, even without a convenience method:

  id grabber = [foo grab];
  [grabber doSomethingFancyThatMustBeDoneOnMainThread:object someArg:wohoo];
  [grabber performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:NO];

Enjoy, and do post your own invocation tricks in the comments and reblogs.

Update 20100828: As you can see from the gist, I’ve updated it with background and main thread invocation (example usage below); thanks to Adam Crume in the comments for the idea and half of the code.

Reblogged from The Daily What

thedailywhat:

Nerdy Animation of the Day:Sidewalk Mario Bros” — A graffiti-style animated Super Mario Bros. speedrun “played” alongside a concrete crash barrier.

[tinycartridge.]

Reblog 4 awesomeness! How did they even do that?!

Reblogged from rentzsch.tumblr.com

rentzsch.tumblr.com: Magic Feet

The experiment:

Step on a nail. Make sure it punctures your shoe and penetrates your foot.

(You probably want to make sure you’re up-to-date on your tetanus shot first.)

Do it again. Yes, with the blood. Doesn’t matter if you wait a week or a couple of years in-between runs.

Now the fun starts.

On the third run, you’ll catch yourself.

You’ll develop what roofers call “magic feet” — you’ll learn to recognize the sensation of a nail driving through the sole of your shoe.

I have magic feet.

And I just took a screenshot of my unsaved work as an app crashed.

That’s probably the closest software analog to magic feet.

Sometimes, an app starts to beachball mysteriously. Most often it’s Safari. It’s a special kind of beachball. You can feel that it will lead to a crash. Cmd-shift-3, open TextEdit, start typing whatever you were typing in Safari into TextEdit manually copying the text, watch Safari crash, reopen, open windows from last session, paste from TextEdit. The only thing that saved your work was an ungodly slow cache miss because your harddrive sucks.

I should just get MarsEdit. And a harddrive with a speed switch.

Howto: Restore Springboard icon positions after iTunes botches them

You’re syncing from another computer. You’re restoring from a backup. iTunes has a bad day. Whatever reason, iTunes decided to resync all your apps, and replace them in your springboard in alphabetical order. I don’t know about you, but I don’t find that particularly helpful. I don’t know *how* many times I’ve meticulously sorted at least the three first Springboard pages with my most often used apps (which doesn’t sound like much, but *damn* does that UI suck!).

Expert instructions
Get your ~/Library/Preferences/com.apple.springboard.plist from your old device or a backup, and replace the plist on your new device or new install. Nothing of much importance is in that file, so it should be fine to just replace. If you’re worried, just open the two files in Property List Editor and copy the array over; it’s just an array of array of application identifiers under the keypath iconState.iconLists. Respring/`killall SpringBoard` when done.

Noobie instructions
Scenario: You have a recent backup of your phone/pod/pad in Time Machine. You have your device with the botched icon ordering. You want to fix things.

  1. Make a backup of your device. This way, we will know relatively certainly which backup belongs to this particular device.
  2. In Finder, navigate to your home folder > Library > Application Support > MobileSync > Backups
  3. Sort by Modified, newest at the top. The topmost one (something like “74e39ee0ac6b69af6f57e213cf5c6b95e5fd787f”, perhaps longer and with dashes) will be your device’s backup. Move this one to your desktop.
  4. Enter Time Machine for this folder. Restore the folder you moved away before to yesterday’s version or something
  5. Download the iPhone Backup Extractor app
  6. Open that app, click the button, choose the name of your device with the most recent date, and confirm
  7. At the bottom, there is an “iPhone OS Files” entry. Extract this to your desktop.
  8. Now, your device need to be jailbroken. If it isn’t already, get Spirit JB, run it, and jailbreak your device (it’ll only take seconds)
  9. If you just jailbroke your device, or if you don’t have SSH enabled, go into Cydia on your device, wait for it to restart, and then install OpenSSH. You must change your default password, or bad things will invariably happen.
  10. Get Transmit or another good SFTP client.
  11. Make sure you’re on the same wifi as your device.
  12. In your SFTP client, connect to (name of your device, with spaces replaced with dashes).local. My device is called Canvas, so I connected to Canvas.local. The connection method should be SFTP, the username should be ‘mobile’, and the password is your mobile password, as changed above or previously. By default it is ‘alpine’, but you REALLY SHOULD NOT USE THIS PASSWORD, as it means anyone can connect to your phone, and e g read and send SMSes.
  13. You’ll end up in your mobile user’s home folder. Navigate to Library > Preferences.
  14. From your desktop, get the file iPhone OS Files > Library > Preferences > com.apple.springboard.plist, and upload and replace the one on your device.
  15. Respring or reboot the device. Icon positions should be restored.

I haven’t tested the noobie instructions; just mail me at joachimb@gmail.com if they don’t work and we’ll figure it out.