Archive for the 'Mac OS X' Category

Simple starter Cocoa app ideas

Wednesday, December 11th, 2013

Inspired partly by tonight’s Hour of Code, here are some index-card-sized outlines of some simple app projects you can make as someone new to Cocoa.

Text editor/word processor

  • Document-based Mac app
  • In document window: NSTextView
  • Use NSAttributedString to read/write document data
  • Document types:
    • public.plain-text
    • public.rtf
    • com.apple.rtfd
    • com.microsoft.word.doc
  • Extra credit:
    • Add a ruler (NSRulerView)

Picture viewer

  • Document-based Mac app
  • In document window: IKImageView
  • Use CGImageSource to read image (picture) & its properties
  • Document types:
    • public.png
    • public.jpeg
  • Extra credit:
    • Floating inspector panel showing the properties in an NSTableView
    • Color-correction panel (IKImageEditPanel)
    • Support folders (public.folder): display images from folder in IKImageBrowserView

PDF viewer

  • Document-based Mac app
  • In document window: PDFView
  • Use PDFDocument to read from .pdf file
  • Document types:
    • com.adobe.pdf
  • Extra credit:
    • Toolbar with zoom in/out buttons, zoom % field, page number field

Conferences 2011

Monday, September 12th, 2011

It’s that time again! Just like last year, there are a bunch of different conferences going on; unlike last year, I’m not going to even attempt to list all of them.

The two that I have a reason to mention are:

  • Voices That Matter. This time it’s in Boston, November 12 and 13. Their early bird pricing is still on through September; I’ll let their site tell you more. As I do whenever I mention it here, I have a coupon code for it, which is BSTBLOG. As usual, due to time and expense constraints, I won’t be attending this one.
  • MacTech Conference. I’m presenting again—same topic as last year, how to recognize, find, and fix bugs in Cocoa applications, but this time it’s the Xcode 4 edition. The early bird period has ended, but you can get the same $500 off by signing up through this referral link. The time and place is November 2, 3, and 4 in Universal City, California.

Last year at the MacTech Conference, I brought with me some of my useful Cocoa links business card. I’ll be doing that again this year, so if you attend the MacTech Conference, feel free to ask me for one.

I hope to see you at the MacTech Conference!

Apple documentation search that works

Sunday, March 6th, 2011

You’ve probably tried searching Apple’s developer documentation like this:

The filter field on the ADC documentation library navigation page.

Edit: That’s the filter field, which is not what this post is about. The filter sucks. This isn’t just an easy way to use the filter field; it’s an entirely different solution. Read on.

You’ve probably been searching it like this:

Google.

(And yes, I know about site:developer.apple.com. That often isn’t much better than without it. Again, read on.)

There is a better way.

Better than that: A best way.

Setup

First, you must use Google Chrome or OmniWeb.

Go to your list of custom searches. In Chrome, open the Preferences and click on Manage:

Screenshot with arrow pointing to the Manage button.

In OmniWeb, open the Preferences and click on Shortcuts:

Screenshot of OmniWeb's Shortcuts pane.

Then add one or both of these searches:

For the Mac

Chrome OmniWeb
Name ADC Mac OS X Library
Keyword adcmac adcmac@
URL http://developer.apple.com/library/mac/search/?q=%s http://developer.apple.com/library/mac/search/?q=%@

For iOS

Chrome OmniWeb
Name ADC iOS Library
Keyword adcios adcios@
URL http://developer.apple.com/library/ios/search/?q=%s http://developer.apple.com/library/ios/search/?q=%@

Result

Notice how the results page gives you both guides and references at once, even giving specific-chapter links when relevant. You even get relevant technotes and Q&As. No wild goose chases, no PDF mines, no third-party old backup copies, no having to scroll past six hits of mailing-list threads and Stack Overflow questions. You get the docs, the right docs, and nothing but the docs.

For this specific purpose, you now have something better than Google.

Manpage Monday: memset_pattern(3)

Monday, September 6th, 2010

From the manpage:

     void
     memset_pattern4(void *b, const void *pattern4, size_t len);

     void
     memset_pattern8(void *b, const void *pattern8, size_t len);

     void
     memset_pattern16(void *b, const void *pattern16, size_t len);

These are analogous to memset(), except that they fill memory with a replicated pattern either 4, 8, or 16 bytes long.

Handy if you want to scribble 0xdeadbeef (or any other value of your choice) over something.

As noted in the manpage, these functions require Mac OS X 10.5 or later. I don’t know about iOS.

Capture Cursor

Saturday, March 13th, 2010

Most people don’t know how to get the cursor that’s currently on the screen—a useful ability, especially if you’re writing screenshot or screen-recording software. I’ve written an app that demonstrates the technique, or at least tries to.

It’s a bit flaky. The API it uses, IOFramebuffer, doesn’t tell me how many frames there are or what format they’re in, so the app assumes ARGB in native byte-order and doesn’t worry about frames. This gives wrong results more of the time than I like.

I’ve filed a request for a higher-level API, which would make the task much easier and the app much shorter.

I’ve posted a build in the repository’s downloads area, in case you’d like to see it in action. If you want to build it yourself, you’ll need to download SGHotKeysLib and put the source where the Capture Cursor Xcode project expects it to be.

UPDATE 2010-08-28: I’ve pushed a change, [9cbec7dd5169], that deletes the IOFramebuffer-based category method and uses Snow Leopard’s new, far more reliable [NSCursor currentSystemCursor] instead. I suggest you do the same.

An introduction to Cocoa and Cocoa Touch

Wednesday, February 3rd, 2010

If you know someone who’s recently taken up programming the Mac or the iPhone (or both), please give them one (or both) of these links:

As a frequent answerer of questions on Stack Overflow, I see certain patterns—not just frequently-asked questions, but also frequently-unasked questions: Things that are biting the questioner that they don’t know about.

Sometimes they’re thinking about things the wrong way (e.g., using property list objects where they should have a model). Sometimes there is a route to a solution (“my app is slow” “run Instruments”), but they don’t know about that route. Often, they’ll use wrong terms that are right on another platform (like “member variable”), like a speaker using their native language’s pronunciation rules when speaking a foreign one.

To help people over these speed bumps, I’ve composed an introduction for new Cocoa and Cocoa Touch programmers. (Both of the above links redirect to it.)

If any part of it doesn’t help them (i.e., is unclear or wrong), I’d appreciate it if you’d let me know, either here or by email.

finder, a command-line tool

Sunday, January 24th, 2010

Today’s Ship-It Saturday is a command-line interface to the Finder.

The two most useful commands are:

  • finder reveal file, which will select the file in a Finder window, and
  • finder update (or updated) file, which will tell the Finder that the file has been updated.

The latter command probably is not too useful anymore, but the command-line tool should work on no less than 10.4, and could probably be recompiled for even older versions of Mac OS X, so you may still have a use for it.

Lazy Finder

Tuesday, January 19th, 2010

This is an expansion of a reply I wrote to a tweet by Daniel Jalkut. He wrote:

Imagine if the iPhone home screen showed a matrix of “generic” icons before filling in real ones. Mac Finder is a disgrace.

He’s referring to behavior introduced in Snow Leopard: When you visit a folder for the first time in a session, the Finder shows every symbolic link and alias with the kUnknownFSObject icon ( this one ), every application with the generic application icon, every file with the generic document icon, and every folder with the generic folder icon, before displaying the item’s real icon and then its Quick Look thumbnail.

Compare the environment of SpringBoard (on a non-jailbroken device) to that of Finder:

iPhone Mac OS X

Every item is of one kind: Application.

Items are of any of three kinds: File, folder, and bundle. The Finder must handle each kind differently.

Everything is on one iPhone’s worth of flash memory.

Files may be distributed over any number of volumes, local and remote; however, the general case is all files on one hard disk, which is the startup disk.

Because the iPhone doesn’t allow background processes, it’s the only app running, with only a few built-in, light-on-file-system-access exceptions (the heaviest of which is probably Mail).

Any number of applications may be running, and they may be accessing files on the same volume you’re browsing.

Accessing any file in flash memory is as quick as accessing any other file (random access).

Disks are not so predictable: Accessing one file and then another can incur milliseconds of seek time. Doing this repeatedly for dozens or hundreds of files (possibly in multiple Finder windows at different scroll positions) may cause the disk to thrash. You can hope that the OS can put the requests into a favorable order, but you can’t rely on it, and there’s only so much it can do.

Flash memory is always active.

Most users aren’t using flash memory. Hard disks may be spun down to conserve power. If this is the case, the disk will need to be spun up, which can take seconds.

All files (that is, all applications) are local.

Some volumes may be on remote machines, across a local network or the internet; depending on throughput and latency, every access to such a volume can take tenths of a second.

All applications are in one place, making caching of icons or their filenames easy.

Applications aren’t the only user-visible bundles, and any bundle can be anywhere.

Compare also how SpringBoard and Finder obtain icons*:

iPhone Mac OS X

Assuming that the icons themselves aren’t cached:

  1. Look up the application’s icon filename in the bundle’s Info.plist (or a cache of icon filenames).

  2. Load the icon from the indicated file.

(All of this may happen inside NSWorkspace and/or Icon Services.)

  1. If the item is a symbolic link or alias, find the original file. If it still exists, start over with it from this step. If it does not exist, jump to step 7.

  2. Get the item’s custom-icon bit.
  3. If the custom icon bit is set, open the resource fork (or, for folders and bundles, the resource fork of the “Icon\r”** file) and search for icon resources of ID -16455. (This step probably happens in Icon Services.)

    If this step succeeds, we have the icon.

  4. If the item is a bundle, look up the application’s icon filename in the bundle’s Info.plist.

  5. Load the icon from the indicated file.

    If this step succeeds, we have the icon.

  6. Identify the item’s HFS file type (if available) or its filename extension. For bundles, the file type may be in Info.plist. For bundles and packages, the file type and creator may be in a PkgInfo file inside the item, which would be yet another file open+read.

  7. Look up the icon for the file types (probably using Icon Services). For anything but a document of an installed application, this will be a generic icon (such as the generic application icon). If the icon does come from an installed application, it will need to be read from a file inside that application bundle.

SpringBoard hasn’t much to do, it’s in a straightforward environment, and the task and environment provide a couple of obvious caching strategies. The iPhone doesn’t have as much processing power, but what it has is enough—it can just get and display the icon without being lazy about it.

In fact, SpringBoard probably doesn’t even need to be asynchronous about it; all it needs to do is keep three pages of icons (current, next, and previous) in short-term memory. When the user flips one page, drop the farthest page out of the short-term memory cache and load the next one into it.

Meanwhile, on the Mac, getting an icon is not straightforward, and the environment can throw a monkey wrench into the works at any point. Every icon can take dozens, hundreds, or thousands of milliseconds to display, and more icons mean more opportunities for a stall. The solution is to load and show the icons asynchronously and in parallel—but then, what to show in the meantime?

Thus, for the Finder, lazy loading makes sense. The Finder can show you what it has (filenames and other basic metadata) immediately. You can work with those files, scroll to other files, or move through the folder hierarchy without having to wait for icons. And while you do that, the Finder has all the time it needs to asynchronously fetch the icons and, if it’s still appropriate, display them.

It’s a feature, not a bug.

* I’m speculating, since I don’t have the source code to either. These steps are how I would implement each one if I were imitating the current stock behavior.
** “\r” here means, as it does in C, the carriage-return character (U+000D).

The myth of Carbon’s 64-bit unavailability

Monday, January 18th, 2010

There’s a recurring myth going around, which goes something like this:

In fact, using Carbon locks you out of 64 bit.

No, it doesn’t.

The truth is that some APIs that are part of the Carbon sub-frameworks are not available in 64-bit. Merely linking against Carbon does not mean your app suddenly stops working in the 64-bit world.

Carbon itself is just an umbrella framework. It doesn’t have any APIs that it provides immediately; everything comes from either another framework or one of its sub-frameworks.

Examples of the first category include Core Foundation, Core Services (home of Launch Services), and Application Services (home of Core Graphics). Even these are not immune to the myth, as demonstrated by the comment I linked to above: It’s on an answer suggesting a Core Foundation function. The answerer referred to it as a “Carbon function” (true in a sense), and the commenter pounced.

Many things that were once explicitly considered part of Carbon, such as the File Manager and Resource Manager, are now part of Core Services. Note that they haven’t even been consigned to the Legacy Library!

In the other category, even some APIs that remain strongly identified with Carbon, by being in a direct sub-framework of Carbon, are still at least partially around. One of these is the Carbon Event Manager, which even has the word Carbon in its name. Try registering a hot-key with it in a 64-bit-only app—it’ll work. (That one is in the Legacy Library. I should probably file a bug on that.)

What is deprecated and not available in 64-bit, as you can see in the Carbon Event Manager Reference, is anything that you would need to build your application on Carbon. That’s what’s deprecated: the concept of a Carbon application. Only Cocoa apps remain.

But some parts of “Carbon” are useful for things other than building a Carbon application. You can use them from a Cocoa application, or from a command-line tool.

Those APIs are still around. They are not deprecated, they are still useful, and they are still available in 64-bit. Use them freely.

(Oh, and before anybody mentions it: No, those NSEvent class methods introduced in Snow Leopard are not direct replacements for Carbon Event Manager hot-keys. You’d have to sift through the events yourself, whereas Carbon Event Manager filters them for you and only calls your function when your key is pressed. The correct analogue would be CGEventTap.)

Application Locator

Friday, January 8th, 2010

This is a little one, inspired by a Growl discussion list thread. Enter the bundle identifier or name of an application, and Application Locator will reveal it in the Finder.

RAM disks on Snow Leopard

Friday, October 23rd, 2009

Make RAM Disk still works, which is not surprising, considering it’s based on a few built-in commands.

What’s changed is that the disk images system is now 64-bit, so if you have a 64-bit-capable Mac, you can create a single RAM disk bigger than 2 GiB—you no longer need to make multiple RAM disks and RAID them.

How not to use UTIs

Tuesday, September 22nd, 2009

John C. Welch has written an article telling you to use UTIs to replace creator codes.

It is wrong.

Daring Fireball, rosscarter.com, and (the most sober of the bunch), TidBITS have all gotten on the “Apple has abandoned creator codes, now we’re screwed, damn you Apple” bandwagon. They’re all right about one thing: Apple has dumped creator codes in Snow.

So before you panic, there’s a replacement mechanism, the UTI, or Universal Type Identifier.

No. Uniform Type Identifiers are a replacement for type codes (and MIME media types, and filename extensions), not for creator codes. There is no replacement for creator codes.

Uniform Type Identifiers are just that: They identify types of data. Using them for anything else is misusing them.

Ideally, Coda should assign an application-specific UTI for CSS files it creates.

No, it should not.

As it turns out, Coda is a UTI-aware application, and according to Coda’s info.plist file, that identifier is com.panic.coda.css.

And that identifier is wrong, because CSS is not Panic’s format.

I use CSSEdit. Currently, it doesn’t declare a UTI, but if they should follow Coda’s example, they should make one up of their own, such as com.macrabbit.cssedit.css. Now we have one type with two names. Which is right?

Suppose I write an application that accepts CSS data. Which UTI do I look for: com.panic.coda.css or com.macrabbit.cssedit.css? Should I look for both of them? What if I find both? What if a third developer releases a CSS editor? Now I have to keep up with the entire population of Mac CSS editors just to accept all the many names for one type.

The right type identifier would be something like org.w3.css or org.w3.cascading-style-sheets, following the rule that the type should be named after whoever controls it. The W3C controls CSS, so its UTI should be named after them. Some other formats, such as PNG, aren’t controlled by anybody, so they go in public.

You might point out public.html and public.xml, as both of those are also controlled by the W3C. Obviously, I disagree that these should be in public.*. But it’s too late to change them now, so we have to put up with them.

Better examples include com.adobe.pdf and com.microsoft.word.doc. In each of these cases, some third party controls the format, so they get the format’s UTI named for them. Notice that Preview does not invent a com.apple.preview.pdf UTI, and TextEdit does not invent a com.apple.textedit.word.doc UTI; they use the UTIs named for the creators and maintainers of those types.

So now we see a problem. All the text-ish files have the same type identifier: com.apple.traditional-mac-plain-text.

Because they are all the same type. And that type is named after Apple because Apple controls that format (in this case, a text encoding).

The Photoshop PNG file is typed as public.png.

There’s no such thing as a “Photoshop PNG” file. PNG is an open format controlled by no-one (or, arguably, the W3C, in which case the type should have been named for them). What you have is a PNG file that you created in Photoshop. That latter detail is irrelevant to its type, which is why HFS had the creator code separate from the type code in the first place.

If there is such a thing as a “Photoshop PNG” file (that is, if Adobe incompatibly extends the PNG format in some way), then they should assign that format its own name (say, com.adobe.png), because it’s a different format.

If you take away the creator code, you’re screwed, because all you have are the extensions.

Exactly why John Gruber, Ross Carter, and Matt Neuberg don’t like the change.

Coda CSS file props:

displayed name:"test.css", 
creator type:"TStu", 
type identifier:"com.apple.traditional-mac-plain-text",

I’m surprised you didn’t notice this. Why isn’t this file’s type identifier com.panic.coda.css?

… why aren’t any of these applications doing the right things? Pages ’09 does. It sets the type for .pages files to “com.apple.iwork.pages.pages”.

Because it’s Apple’s own format specifically for Pages. Again, see also com.microsoft.word.doc.

Unsurprisingly, it doesn’t even have a creator code.

Yeah. Cocoa makes it difficult to apply a creator code to a file and doesn’t do it automatically, so expect most Cocoa apps to not do it.

Even thought the default for the .html extension is BBEdit, the UTI overrode that. When I changed the handler for public.html to BBEdit, then the file opened in BBEdit. That’s exactly the behavior I’d expect, and it matches what you got with Creator Codes.

It matches what you got when you assigned the default handler of a file type, as well. That’s what you did the newer equivalent of.

There never was a way to set which application opened files that had a given creator code. That was what the creator code was for: Determining which application would opened the file.

Yes, Apple did abruptly kill off Creator Codes, however, they’ve been warning about that for some time now.

Sort of. They’ve been warning that they’d kill off the combination of file type codes and creator codes. UTIs are the replacement for file type codes; as I said above, there is none for creator codes.

Now, I know that ‘simple’ is a big fat lie when it comes to application development, however, at some point during the 10.5 lifecycle, all these applications should have been updated to not only support UTIs, but to use them. Instead, they all relied overmuch on FIle Types/Creator Codes …

Actually, it was more common to use filename extensions. See what I said above about the difficulty of assigning file types and creator codes from a Cocoa app. I think that was actually quite rare, simply because filename extensions were so much easier.

… and now that those are gone, well, the OS does what it can with the information it has available.

No, it doesn’t. The creator code information is still available, and the OS ignores it. The OS now only uses type information to determine how to open a given file, except for files that the user has assigned a specific application to.

Oh, and what about when you change a file association in the Finder? Well, unsurprisingly, the Finder cheats. It adds a resource fork to the file with the path to the desired application coded within. … [M]aybe the Finder could start doing the right thing too?

Agreed. I say it should set the file’s creator code.

Incidentally, I tested in Tiger, Leopard, and Snow Leopard, and Finder did this resource trick in all three versions. If the Info window ever did set the file’s creator code, it hasn’t done that for many years.

If the only way to have a unique UTI associated to a file is for that file to use a completely unique file extension, then WHAT THE FUCK GOOD ARE UTIS? Fucking seriously, why the FUCK bother? BBEdit creates TEXT FILES. Does Apple seriously expect that Bare Bones, to properly use UTIs, is going to now create a .bbedittext extension, a .bbedithtml extension, a .bbeditohmyfuckinggodwhatthefuckisgoingon extension, then make you EXPORT to ‘standard’ extensions, just so you can know a file created in BBEdit will open in it?

And now you know why smashing type information and creator/opener information into a single value is a bad thing.

If this is what Apple is pushing, then everyone who signed off on non-settable UTIs is a fucking idiot…

There is no reason why the average user should be able to change the type of a file. If they created an HTML file, it’s an HTML file, and there’s no reason for a user to be able to set it to anything different unless they really know what they’re doing. (I’ve done it, and I’m assuming you have, too. We’re exceptions.)

What you want to do is to change which application opens the HTML file, and that is completely separate from the fact that the file contains HTML.

TimeMachineGrowler 1.0.1

Saturday, September 5th, 2009

The new version of TimeMachineGrowler includes compatibility with Snow Leopard and a few fixes. Plus, I’ve created a Google group for it, so you can get news of any further updates there.

TimeMachineGrowler 1.0

Thursday, August 27th, 2009

Just in time for tomorrow’s release of Snow Leopard, TimeMachineGrowler is an app that will tell you how long Time Machine takes to create a back-up by posting Growl notifications when the back-up starts and finishes.

One of the promised “refinements” in Snow Leopard is faster back-ups, so you may find it interesting to compare how long a back-up takes on your machine running Leopard to how long it takes on Snow Leopard (assuming, of course, that you haven’t already abandoned Leopard for the Snow Leopard GM).

Copy UNIX path to Finder selection

Thursday, August 13th, 2009

UPDATE 2009-08-14: Or just use CopyPath, which looks like a much better implementation of exactly the same thing. Thanks to David Keegan, its author, for suggesting it in the comments.

The original post content follows.


This is a script application, which apparently you can drag into your Finder toolbar. (If it doesn’t let you, you didn’t drop it in the right spot. Finder is finicky about this. Keep trying.)

Once you’ve added it to your toolbar, you can just click on it to run it. The script will copy the UNIX path of whatever you have selected in Finder to the clipboard.

Inspired by a conversation with Alan Boyd.

Manpage Monday: PlistBuddy(8)

Monday, April 13th, 2009

PlistBuddy(8) is a command-line tool for editing property-list files, with a deeper reach than plutil defaults:

Entries consist of property key names delimited by colons. Array items are specified by a zero-based integer index. Examples:

  :CFBundleShortVersionString
  :CFBundleDocumentTypes:2:CFBundleTypeExtensions

Jonathan “Wolf” Rentzsch, in his del.icio.us bookmark for the manpage, says that PlistBuddy is “always at /usr/libexec/PlistBuddy on modern systems”.

Manpage Monday: copyfile(3)

Monday, March 30th, 2009

copyfile(3) is an API for copying and moving files within the file-system:

DESCRIPTION

These functions are used to copy a file’s data and/or metadata. (Metadata consists of permissions, extended attributes, access control lists, and so forth.)

The copyfile() function can copy the named from file to the named to file; the fcopyfile() function does the same, but using the file descriptors of already-opened files.

The copyfile() and fcopyfile() functions can also have their behavior modified by the following flags:

COPYFILE_CHECK

Return a bitmask (corresponding to the flags argument) indicating which contents would be copied; no data are actually copied. (E.g., if flags was set to COPYFILE_CHECK|COPYFILE_METADATA, and the from file had extended attributes but no ACLs, the return value would be COPYFILE_XATTR.)

COPYFILE_PACK

Serialize the from file. The to file is an AppleDouble-format file.

COPYFILE_UNPACK

Unserialize the from file. The from file is an AppleDouble-format file; the to file will have the extended attributes, ACLs, resource fork, and FinderInfo data from the to file, regardless of the flags argument passed in.

File Manager also has APIs for copying files, in both asynchronous and synchronous flavors. Those APIs don’t provide as much control over management of metadata, but they do offer asynchronous operation, whereas the copyfile(3) APIs appear to be synchronous.

And, of course, I should mention NSWorkspace operations, which you use with the performFileOperation:source:destination:files:tag:
method
. Unlike the other two, this API has been around since 10.0. On the other hand, like copyfile(3), it’s synchronous only.

Manpage Monday: CC_SHA(3cc)

Monday, February 16th, 2009

The Common Crypto library in Mac OS X 10.4 and later provides simple APIs for five SHA algorithms:

CC_SHA1() computes the SHA-1 message digest of the len bytes at data and places it in md (which must have space for CC_SHA1_DIGEST_LENGTH == 20 bytes of output). It returns the md pointer.

CC_SHA1_Init() initializes a CC_SHA1_CTX structure.

CC_SHA1_Update() can be called repeatedly with chunks of the message to be hashed (len bytes at data).

CC_SHA1_Final() places the message digest in md, which must have space for CC_SHA1_DIGEST_LENGTH == 20 bytes of output, and erases the CC_SHA1_CTX.

The successor versions of SHA-1, SHA-2, are also implemented for hash bit lengths of 224, 256, 384, and 512. The functions to call to invoke the larger hash-size versions of the algorithms include the hash size as part of the function names: …

RETURN VALUES

All routines return 1 except for the one-shot routines ( CC_SHA1(), etc.), which return the pointer passed in via the md parameter.

Manpage Monday: notify(3)

Monday, December 8th, 2008

notify(3) is a simple API that allows processes to poke other processes, and to be poked.

The API is similar to NSDistributedNotificationCenter, except that it’s not object-oriented, it’s not based on Foundation or CF, and it doesn’t allow you to attach a property list to the notification.

You register in one of four ways:

notify_register_check
Sign up under a name, and get a registration token.
notify_register_signal
Have the system send your process a signal when another process posts a notification with a particular name. Also get a registration token.
notify_register_mach_port
Have the system send your process a message on a Mach port when another process posts a notification with a particular name. Also get a registration token.
notify_register_file_descriptor
Get a registration token, and have the system write that token to a file descriptor when another process posts a notification with a particular name.

Each of the last two functions will create the Mach port or file descriptor for you, unless you tell it to use one you already have. You do that by passing NOTIFY_REUSE.

All four functions give you a registration token (the first one does nothing else), which is simply a signed 32-bit integer. You can then use notify_check to poll that token to see whether any processes have posted a notification to it since the last time you checked. (I don’t know how the other notification methods affect this—e.g., whether notify_check will ever return true if you got the token from notify_register_signal.)

You free the token using notify_cancel. This also closes any Mach ports or file descriptors you have associated with it. There is no way to disassociate them from the token or to cancel the token without closing the associated resources.

On the sending side, the API provides one function: notify_post. It takes one argument, which is the notification name; this is the same name that any receiving processes passed to their chosen notify_register_whatever function.

Leopard adds a new feature: you can associate a shared 64-bit number with a name using notify_set_state, and retrieve that number using notify_get_state. I suggest that you only use notify_set_state in a single process, as I can imagine race conditions occurring if two processes try to set state under the same name. If you need bidirectional communication, use two notification names (or a different means of communication, such as sockets or Mach ports).

Apple introduced the rest of the notify(3) API in Panther.

Manpage Monday: afconvert(1)

Monday, November 24th, 2008

afconvert is a command-line utility that uses Core Audio to convert audio files from one format to another.

The manpage is actually pretty sparse (like the rest of the Core Audio documentation); you’re better off reading the command-line help:

% afconvert -h

A simple example is to convert an AIFF file to AAC in an MPEG-4 file:

% afconvert -f 'm4af' -d 'aac ' -b 98304 Recording.aiff

The resulting file is 96 kbps (98,304 bps) and is named “Recording.m4a”.

UPDATE 2008-11-26: Corrected permalink and title to include the section number.