Ammo Navigation Weblog Company Support Store Rogue Amoeba
Rogue Amoeba
Sat, 29 Sep 2007



The new Apple keyboards now have "media keys" for Previous, Next and Play/Pause. As of yet there doesn't appear to be any public API for developers to use these keys in your own application. But this post to the CocoaDev mailing list from Peter Maurer reveals a way.

Firing up Xcode, we start by subclassing NSApplication and listening in on -sendEvent. We can see applications are actually passed events for these new keys. The event has a type of NSSystemDefined, and a subtype of 8.

Here is a code snippet showing how to trap them:

- (void)sendEvent: (NSEvent*)event
{
if( [event type] == NSSystemDefined && [event subtype] == 8 )
{
int keyCode = (([event data1] & 0xFFFF0000) >> 16);
int keyFlags = ([event data1] & 0x0000FFFF);
int keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA;
int keyRepeat = (keyFlags & 0x1);

[self mediaKeyEvent: keyCode state: keyState repeat: keyRepeat];
}

[super sendEvent: event];
}

I'm not completely sure on the "keyState" code, it appears the value alternates between 0xA and 0xB depending on if the key is up or down. There may be other values I don't know about though.

Moving on, once we got the event, the code for handling would be something like as follows:

- (void)mediaKeyEvent: (int)key state: (BOOL)state repeat: (BOOL)repeat
{
switch( key )
{
case NX_KEYTYPE_PLAY:
if( state == 0 )
; //Play pressed and released
break;

case NX_KEYTYPE_FAST:
if( state == 0 )
; //Next pressed and released
break;

case NX_KEYTYPE_REWIND:
if( state == 0 )
; //Previous pressed and released
break;
}
}

The key codes constants come from the header IOKit/hidsystem/ev_keymap.h. One other thing to note is that these keys act as "global hot keys", every application receives events for them, not merely just the foreground application. This whole public domain sample code is available in a file here.

And while we are on the topic of coding: Don't use strnstr.

Posted by Quentin | Permalink | View/Post Comments (6)

Comments


Peter Maurer
Tue Oct 2 13:42:44 2007

Now that someone else is playing around with these keys, I'm curious if you have anything to say about this problem I've been trying to solve for about two months:

http://www.cocoabuilder.com/archive/message/cocoa/2007/8/10/187519

Peter Hosey
Tue Oct 2 13:50:35 2007

Peter Maurer: What about a CGEventTap? You may be able to eat the event that way. If so, that's probably what QTP is doing, in order that the event does not reach iTunes.

This also presents a broader (and more on-topic) question: Are CGEventTaps also able to catch the media-key events?

Tom Lazar
Tue Oct 2 14:54:21 2007

Perhaps off-topic but I stumbled upon this entry and now I'm wondering if perhaps this is a good place to ask how one would go about to map the new keyboard's second alt-key to enter, i.e. the key that macbooks and powerbooks have in its place (and which I have become so accustomed to).

However, so far none of my attempts have been fruitful (mainly trying out shareware keymapping applications and then finding that they cannot distinguish between the left and the right alt-key)

is there hope for me?

Peter Maurer
Tue Oct 2 15:48:57 2007

Peter Hosey: Thanks for the pointer! You just made me realize that when I had thought about using an event tap, I had simply assumed that media key events would have to be tapped as key down/up events (*), which is just silly when you think about how NSApplication treats them as system-defined.

So I gave it a try, and sure enough it works: You can tap media key events by doing something along the lines of:

CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, options, CGEventMaskBit(NX_SYSDEFINED), tapSystemDefinedEvent, NULL);

(I haven't tested yet whether this solves my iTunes issue completely, but it's definitely a huge step forward. So thanks again.)

--

(*) Tapping key events requires either Universal Access being enabled or your application running as root. Both requirements were unacceptable for me.

Quentin (Rogue Amoeba Staff)
Tue Oct 2 17:04:41 2007

I briefly considered the "iTunes" problem, but couldn't think of anything off the top of my head. For my personal use it also wasn't a problem.

I'm going to venture that iTunes/QuickTimePlayer use a different dispatch mechanism for these events, and what we get via NSApplication is just bonus behavior from the system.

Frederik Fix
Tue Oct 2 19:30:10 2007

Do you know if one can use this method to interface with the Apple remote?


This post is archived, and commenting has been closed.
Copyright © 2008 Rogue Amoeba Software, LLC. All rights reserved.