Vista: A Massively Multiplayer Beta Test
2007-02-28
The Register, the epitome of acerbic British commenting, looks at Vista in an article titled Vista First Look: Bugs and Confusion. I'm just glad that my employer (a large US corporation) has told us that they won't be rolling out Vista for at least another 18 months.
|
Random Wok: Who Wants To Test It?
2007-02-27
Aperture Plugin: Preventing Illegal Path Characters
2007-02-27

Since the prefix and postscript strings will be going into a path, I also want to prevent the user from entering characters such as / and : that could cause unintended actions. There is no delegate method I can add to a text field to do this. Instead, a different class is used: a text formatter.
A text formatter can be attached to a text cell. Once attached, it can intervene in the formatting of the text to modify what the user sees. A phone number formatter would automatically add brackets and spaces as a number were entered, for instance. A formatter can also change the color and style of the text, and add and remove characters.
Since none of the supplied formatters do what I want, I will have to write my own. And to do that I have to create a new formatter class as a subclass of NSFormatter, the abstract base class that all formatters descend from.
The new formatter will be called BTValidPathElementFormatter and will prevent forward slash and colon characters from appearing, and optionally disallow leading periods and hyphens. Leading periods in file names make the file invisible in the Finder and that would almost certainly be unintended. Leading hyphens are not valid in a file name.
To create my new class in XCode I use File > New File and select Objective C class. Then I give it a name and make sure it is added to my project:

Then in the header file, I add the prototypes for the necessary methods, and add my own methods and ivars for handling the leading periods and hyphens:

The -isPartialStringValid: method allows me to figure out what was just added to the string, and then act accordingly to adjust the string and the current selection.
I need -init and -dealloc methods for my class. I use the -init method to initialize the superclass and up the default state of my ivars:

And I have to provide methods for changing the period and hyphen options:

These three methods are filled in with what is basically template code:

And finally here are the guts of the class: the code that disallows the characters. The first part sets up a character set that will be used to compare against the string in the text field. Then two easy cases are dealt with quickly:

The code uses NSRange structures to keep track of the current selection. Next, periods and hyphens and disallowed:

I'm not certain if the unichar cast is needed, but I did notice that the type returned by characterAtIndex: is of type unichar, so put it in to be on the safe side. Finally I look for the illegal characters in the text that was inserted. I can figure out what was added by comparing the previous and current selections:

And that is it for the new class. I have to make some changes in Random_Wok so that the new formatter is attached to the fields and set up correctly. I add this code to -willBeActivated:

It creates an instance of the formatter for each of the two fields that need formatting. Additionally the prefix formatter is set to reject hyphens and periods. Finally the formatters are attached to the NSCells associated with the NSTextFields using -setFormatter.
A delegate method to NSControl -control:didFailToValidatePartialString:errorDescription is called whenever the formatter returns NO. Since Random_Wok is already a delegate of the three text fields, this will be called. By coding it to beep, I can give the user audible feedback that the key press is not permitted:

And the code works. The prefix field will not accept leading periods or colons and both the prefix and postfix fields reject forward slashes and colons.
The other parts of this series can be found via the Cocoa page.
Dock Dividers
2007-02-26

That white thing is a dock divider: a small graphic created by Adam Betts that can be used to section off your dock items. They are little Applescripts that just quit. That way if you accidently launch one it will do nothing. They come in horizontal and vertical flavors.
Aperture: Is There Any Way To Stop Aperture Importing The Same Image More Than Once?
2007-02-25
I have found your Aperture articles to be very useful, thanks for taking the time to post them. Quick question for you about your advanced importing article. When you did the following: 'In this case I have elected to copy the master files into a folder called Dogs' Is there any way to tell Aperture to ignore duplicate images and only import/copy the new ones to the 'Dogs' folder? This was a handy feature that Canon's CameraWindow provided and I got into the habit of using it (I don't always delete all the images from my photo card after an import).
Aperture does not ignore duplicates when they are imported, as you and many others have discovered. Certainly this is a feature of iView and many other image cataloging applications. Why not Aperture as well?
It's simply that Aperture is not an image cataloging application: it's an image library application. It includes cataloging features, (including a catalog) as all libraries do, but there is more to it that that. The difference is that a catalog tells you where something is while a library stores it for you as well. It gets confusing when referenced image masters are involved. The addition of referenced masters makes Aperture look just like a cataloging application in some ways. But really referenced masters are a part of the library just as much as managed masters are. It is only their storage that is different.
Having said that, I do agree that having an "ignore already imported images" button on the import pane would be very useful. I just don't see how it could be reliably implemented. How does Aperture know that the image has already been imported? If it gets it wrong, you will lose images and be much madder than a few duplicates could ever make you.
Aperture does not ignore duplicates when they are imported, as you and many others have discovered. Certainly this is a feature of iView and many other image cataloging applications. Why not Aperture as well?
It's simply that Aperture is not an image cataloging application: it's an image library application. It includes cataloging features, (including a catalog) as all libraries do, but there is more to it that that. The difference is that a catalog tells you where something is while a library stores it for you as well. It gets confusing when referenced image masters are involved. The addition of referenced masters makes Aperture look just like a cataloging application in some ways. But really referenced masters are a part of the library just as much as managed masters are. It is only their storage that is different.
Having said that, I do agree that having an "ignore already imported images" button on the import pane would be very useful. I just don't see how it could be reliably implemented. How does Aperture know that the image has already been imported? If it gets it wrong, you will lose images and be much madder than a few duplicates could ever make you.
Aperture Plugin: Continuous Example File Name Updates
2007-02-24

There is a problem with the current interface: the user has to type in the prefix and postfix strings and then tab away from the field to end the editing. Until that happens, the example file name does not get updated. What I want is for the text fields to update the example file name continuously with each key press.
To do this I have to set up my Random_Wok object as the delegate to the text fields. If my Random_Wok class provides a -controlTextDidChange: method, then as a delegate, the NSTextField instances will call it for each change of the text.
I set up Random_Wok as the delegate in -willBeActivated: for each of the text fields:

And provide a way to distinguish between the fields by giving them tags:

I give them numbers 0, 1, and 2. Then I code the delegate to update the appropriate string and remake and display the example string on each call:

And that works. Typing, deleting, pasting, any change to the text fields is reflected in an immediate change in the example filename.
The other parts of this series can be found via the Cocoa page.
Aperture vs Lightroom
2007-02-23
Now that Lightroom 1.0 has been released, the reviews and comparisons are starting to come in. Ars Technica has a review called In Search of The Perfect Workflow and O'Reilly has two writers doing real-life comparisons, working with the tools over an extended period of time to find out what they think.
If Adobe sends me a free copy, I'll give Lightroom a try and write some artciles. The 30 day trial is much too short to get into an application of that size to any depth.
If Adobe sends me a free copy, I'll give Lightroom a try and write some artciles. The 30 day trial is much too short to get into an application of that size to any depth.
Aperture: How Do I Apply Keywords To All Of The Images In A Stack?
2007-02-22
Sorry to bother you again with a quick question. I've imported all my old images, and groped the similar shots into stacks, and closed the stacks to reduce the number of images shown. Now I'm going through and applying keywords, but the keywords I select are only being applied to the pick of the stack, not the whole stack. Any idea how to apply the keyword to the whole stack? I've tried the "primary only" toggle and that doesn't seem to be it.
Yes, metadata should really be a stack attribute, not an image attribute, but there is nothing we can do about that. The real answer is to set up your workflow so that you stack last. Apple seems to think that doing it first is the way to go but my experience is the opposite -- there are just too many gotchas. Do absolutely everything you normally do to your photos and then stack them. Or better still, stack only the good ones. There is usually no point wasting time on the one and two star images taken at the same time: they are still accessible simply by displaying thumbnails in time order.
To quickly access stacks (and only stacks) to apply metadata, do this:
1. Open all the stacks with option ' (apostrophe)
2. Go to the top with Home
3. Select one image in the first stack and press command E. That extends the selection, selecting all of the images in the stack
4. Drag keywords from the keyword HUD and they will apply to all of the images in that stack
5. Hit option Page Down. That takes you to the next stack and selects all of its contents.
6. Repeat steps 4 and 5 as many times as you need
7. Close all the stacks with option ; (semi colon)
Yes, metadata should really be a stack attribute, not an image attribute, but there is nothing we can do about that. The real answer is to set up your workflow so that you stack last. Apple seems to think that doing it first is the way to go but my experience is the opposite -- there are just too many gotchas. Do absolutely everything you normally do to your photos and then stack them. Or better still, stack only the good ones. There is usually no point wasting time on the one and two star images taken at the same time: they are still accessible simply by displaying thumbnails in time order.
To quickly access stacks (and only stacks) to apply metadata, do this:
1. Open all the stacks with option ' (apostrophe)
2. Go to the top with Home
3. Select one image in the first stack and press command E. That extends the selection, selecting all of the images in the stack
4. Drag keywords from the keyword HUD and they will apply to all of the images in that stack
5. Hit option Page Down. That takes you to the next stack and selects all of its contents.
6. Repeat steps 4 and 5 as many times as you need
7. Close all the stacks with option ; (semi colon)
The Ultimate Test Of Bill Gates' Sense Of Humor
2007-02-21
Now we know that Bill Gates and Steve Jobs will make a "historic joint appearance" at the fifth annual "D: All Things Digital" conference on May 30th, there is an opportunity for Bill Gates to pass or fail the ultimate test of his sense of humor.
It starts with Steve Jobs standing up and saying "Hi, I'm a Mac".
It starts with Steve Jobs standing up and saying "Hi, I'm a Mac".
Aperture Plugin: Using Bindings To Populate The Length Pop-Up
2007-02-20

To populate the length pop-up I'm going to use bindings. Bindings allow changes in one object to automatically control another object. In this case I want the contents of the length pop-up to reflect the values I store in an array in my Random_Wok instance. Each time I change the array contents, the pop-up contents change. The advantage to this is that I don't have to write the code that populates the pop-up.
To make this work I need a third object: an array controller instance in my nib. An array controller is a pre-written, general-purpose controller that knows how to communicate with objects that expose bindings. It's like hiring a manager to run a department. Since it knows about arrays it can take a lot of work off my hands by dealing with the individual array elements for me. The array controller will mediate between changes in my data model and updates to the view.
To get an array controller instance into my nib I drag one from the controller palette to the nib file:

And I give it a name by double-clicking it: Length Popup Controller. To make the controller do anything useful I have to hook it up to a data model (an array) and a view (the pop-up). The controller then mediates between these for me.
The first thing I have to do is tell the controller what kind of object is in the array it is dealing with. "Good morning new manager, your staff consists of interns". In this case it is an array of NSMutableStrings that I will be modifying according to which string lengths I want the user to be able to choose:

Then I have to tell the array controller which array it will be dealing with. "Your interns are in that cube farm over there". To do this I bind the array controllers content array to the array of length strings in my Random_Wok object. That's an ivar called _lengthStrings:

I bind to File's Owner because that is a stand-in for my Random_Wok class. What this step does is to make the controller able to observe changes to the _lengthStrings array. The observation is incomplete at this stage -- the manager knows which cube farm to keep an eye on, but none of the interns yet know to tell the manager that anything has happened.
Next I have to tell the pop-up button that its contents will be supplied by an array controller. To do that I select the pop-up button and bind it to the array controller. The pop-up button has a binding called content that is designed for doing just this:

The controller key (arrangedObjects) is what the pop-up will observe to get its content. "Catering department, watch the manager's list of foods on his white board. Any time he changes it update the menu".
The last thing I must do is to add code to Random_Wok so that the object tells the NSArrayController that something has changed (remember that the interns in their cubes don't automatically tell the manager that their choice of foods has been updated). I code manual observer notification for this by using -willChangeValueForKey: and -didChangeValueForKey:

I need this manual method of notifying the controller that something has happened because my Random_Wok class is not Key Value Observing compliant. As a class it lacks the methods that the KVO mechanism requires to have change notifications automatically sent to observers. The array controller is KVO compliant, to the pop-up can automatically get notifications that the content array has changed.
Now the interns are saying to the manager "We will have a new list of foods in a minute -- OK, it's been updated". And the manager knows to update his whiteboard, the caterers see the new list of foods because they are watching the whiteboard, and the menu gets changed. And all along the interns don't know or care why they are creating food lists, and the caterers don't know or care where the food lists are coming from.
I try out the code and it works:

The final code for actually creating the array was more complicated than the little test I initially wrote:

This includes some extra logic to select the current length, or if not possible, use the highest length available. In this way as the user clicks around the available controls the pop-up does not keep resetting to the minimum length setting.
The other parts of this series can be found via the Cocoa page.
I, Cringely: Appeerances Can be Deceiving
2007-02-20
On I, Cringely Robert Cringely esposes his theory that the Apple TV box is (going to be) part of a centrally-controlled P2P network. This could actually happen, I think. But there is more.
The idea is that instead of creating a VOD (video on demand) system that suffers from all the delays of downloading after you have decided to watch, a problem shared by every delivery system out there, including DVDs by mail from Netflix, the box which is always plugged in and turned on will be downloading movies for you 24 hours a day. Only when there is a sufficiently large chunk available on your Apple TV will the system offer it to you for watching. The rest of the movie will come from other Apple TV boxes all over the world, seeded by Apple and/or Google servers.
This means that Apple can achieve very rapid distribution of movies without setting up millions of servers. This reduces costs of course, but also makes Apple the fastest network mass distribution system there is. That in itself makes for some interesting possibilities. Why stop at movies? Shorter content, often at lower resolution is much easier to handle and can include a much wider selection. Like weather, local news, and traffic conditions. And widgets of course. There is no reason that the Apple TV cannot display widgets exactly the same as the iPhone and the Mac can.
The other thing it does is to allow Apple to offer instant gratification and with it receive instant income. Think about it. Your Apple TV says "Last week you watched Lord Of The Rings part one on DVD. I have part two ready for you to watch right now. Just pay me to watch it". Why go to Blockbuster or wait for Netflix? VOAW: Video On A Whim.
The article also asks this question:
Bob misses the obvious. They are not designed to all stack together, so much as to each stack with another piece that Apple has not yet released. What is that piece? My pet theory is that it is a home server. That will allow people to maintain very large collections of movies for P2P distribution and so earn credits toward their own movie downloads. That's right. Apple will give you credit for providing P2P content to other people. The more you have and the bigger bandwidth you have, the more you can earn. A big, easy to use home server is also perfect for home video collections, photos (many people have tens of thousands of 10M photos these days), and backing up to.
Another theory I have is that it will be a WiMAX box: fixed, high speed, wireless networking -- real broadband in fact -- that will not be controlled by either the cable or the phone companies. This will introduce real competition into the marketplace and rates of payment will fall like crazy as rates of data transfer climb like crazy. This is why you won't care about the bandwidth cost or the amount of data your Apple TV is sending and receiving.
The idea is that instead of creating a VOD (video on demand) system that suffers from all the delays of downloading after you have decided to watch, a problem shared by every delivery system out there, including DVDs by mail from Netflix, the box which is always plugged in and turned on will be downloading movies for you 24 hours a day. Only when there is a sufficiently large chunk available on your Apple TV will the system offer it to you for watching. The rest of the movie will come from other Apple TV boxes all over the world, seeded by Apple and/or Google servers.
This means that Apple can achieve very rapid distribution of movies without setting up millions of servers. This reduces costs of course, but also makes Apple the fastest network mass distribution system there is. That in itself makes for some interesting possibilities. Why stop at movies? Shorter content, often at lower resolution is much easier to handle and can include a much wider selection. Like weather, local news, and traffic conditions. And widgets of course. There is no reason that the Apple TV cannot display widgets exactly the same as the iPhone and the Mac can.
The other thing it does is to allow Apple to offer instant gratification and with it receive instant income. Think about it. Your Apple TV says "Last week you watched Lord Of The Rings part one on DVD. I have part two ready for you to watch right now. Just pay me to watch it". Why go to Blockbuster or wait for Netflix? VOAW: Video On A Whim.
The article also asks this question:
I'll tell you my theory about the Apple TV in a moment, but first I want to riff a bit on the other components in the new ministack -- the Mac Mini and the new AirPort Extreme Base Station. All three components have the same form factor, very similar cases, and they stack beautifully one atop the other. But why? Under what circumstance would you even want to stack all three together? It makes no sense to me.
Bob misses the obvious. They are not designed to all stack together, so much as to each stack with another piece that Apple has not yet released. What is that piece? My pet theory is that it is a home server. That will allow people to maintain very large collections of movies for P2P distribution and so earn credits toward their own movie downloads. That's right. Apple will give you credit for providing P2P content to other people. The more you have and the bigger bandwidth you have, the more you can earn. A big, easy to use home server is also perfect for home video collections, photos (many people have tens of thousands of 10M photos these days), and backing up to.
Another theory I have is that it will be a WiMAX box: fixed, high speed, wireless networking -- real broadband in fact -- that will not be controlled by either the cable or the phone companies. This will introduce real competition into the marketplace and rates of payment will fall like crazy as rates of data transfer climb like crazy. This is why you won't care about the bandwidth cost or the amount of data your Apple TV is sending and receiving.
Aperture: Working With An External Editor
2007-02-19
Very occasionally I need to use an external editor with Aperture. It's rare because I don't do much tweaking of my images, try to remove distortion, composite anything, or create anything artistic with other tools. I actually don't have many other image tools: Photoshop Elements 3 is it. It's PowerPC only, but runs at a quite acceptable speed for my use on this dual Intel iMac.
To use an external editor with Aperture, I must first visit the preferences and choose an application:

The file format choice is between PSD and TIFF. The DPI setting really doesn't matter except in the way it is interpreted by the external editor. It's a number that gives the image an absolute scale and does not affect the number of pixels at all. The image passed to the external editor is always 16 bit. As well as the obvious choices, non-conventional image editors can also be used.
Here is an example of using an external editor. I want to mess with the colors in this picture of a Corvette:

So I control-click the image to open it in Photoshop Elements:

As Photoshop opens, Aperture creates a new master in a stack for me and adds a target-shaped badge so that I know it was created in an external editor:

It's in a stack out of convenience. I can drag it out if I want. The new image is a complete copy with all the same metadata as the original. I adjust my image in Photoshop to get the effect I want:

I don't have all the options in the menus of Photoshop Elements enabled because not all of the filters and effects work with 16 bit images. When I save the image (using Save, not Save As), Aperture sees the file change and updates the thumbnail and the copy in the library:

If I make more adjustments and save again the image is updated again:

I can also convert the image to 8 bit in Photoshop, use some other filters, and save and it will be updated:

Internally Aperture created a new master it the library with the same name as the original, but added (1). This new master is always created in the library, even if the original is referenced:

One thing to watch is that while using Save As in Photoshop will work, it will not update the image in Aperture. The new image has to be imported into Aperture by hand. Apple also has a handy FAQ that describes how to avoid issues with external editors.
To use an external editor with Aperture, I must first visit the preferences and choose an application:

The file format choice is between PSD and TIFF. The DPI setting really doesn't matter except in the way it is interpreted by the external editor. It's a number that gives the image an absolute scale and does not affect the number of pixels at all. The image passed to the external editor is always 16 bit. As well as the obvious choices, non-conventional image editors can also be used.
Here is an example of using an external editor. I want to mess with the colors in this picture of a Corvette:

So I control-click the image to open it in Photoshop Elements:

As Photoshop opens, Aperture creates a new master in a stack for me and adds a target-shaped badge so that I know it was created in an external editor:

It's in a stack out of convenience. I can drag it out if I want. The new image is a complete copy with all the same metadata as the original. I adjust my image in Photoshop to get the effect I want:

I don't have all the options in the menus of Photoshop Elements enabled because not all of the filters and effects work with 16 bit images. When I save the image (using Save, not Save As), Aperture sees the file change and updates the thumbnail and the copy in the library:

If I make more adjustments and save again the image is updated again:

I can also convert the image to 8 bit in Photoshop, use some other filters, and save and it will be updated:

Internally Aperture created a new master it the library with the same name as the original, but added (1). This new master is always created in the library, even if the original is referenced:

One thing to watch is that while using Save As in Photoshop will work, it will not update the image in Aperture. The new image has to be imported into Aperture by hand. Apple also has a handy FAQ that describes how to avoid issues with external editors.
Aperture Plugin: A Better Way To Randomize
2007-02-18

Reading the documentation for the Aperture export plugin SDK carefully I think I have found a better way of generating random names. What I really want is a random name per image, not per image name. If the name of the image is changed, the image should still get the same pseudo-random export name. If there is some sort of identifier that is tied to the image, not changing with the name, then I should use that.
And it does exist. By using -propertiesWithoutThumbnailForImageAtIndex: I can get a dictionary of properties for each image. Among the properties available is one keyed with kExportKeyUniqueID. This is a 22 character pseudo-random identifier stored in the library file for each image master and version. Here are some examples: Nku72ZxXT1CkGAF1JoQWRQ, mQ6wSngJQH29z0+o0yldKg, Jo1HuM/bRcu3u81dVYhdqw.
I looked at several thousand UUIDs by using SQLite Database Browser to export a table from one of my Aperture libraries. Then by analyzing the character frequencies I could see roughly how random the strings are and what characters are used. I found 0-9, A-Z, a-z, + and /. That is 64 in all, so I get 6 bits from each character, or 132 bits in all. That's four more than 128, which may explain why several of the characters have abnormally high frequencies (Q especially).
I can take the UUID, feed it and the salt into a hash function to get a 64 bit number, and then generate a string to satisfy the user's needs by repeated division of the resulting long long and conversion of the remainders into characters.
So the diagram now becomes:

The other parts of this series can be found via the Cocoa page.
Daring Fireball
2007-02-17

John Gruber's blog Daring Fireball comments on the world of Apple, Cocoa, technology, media, design, and many other connected topics. Today he outdoes himself with an unraveling of Macrovision's CEO Fred Amoroso's response to Steve Jobs's Thoughts On Music.

He has also recently taken apart Paul Thurrott, Rob Enderle, Palm's CEO, and others equally as clueless or overpaid.
How Canon Makes Lenses
2007-02-17
Aperture: Fun With Final Cut Pro Filters
2007-02-16
Aperture Plugin: Initialization Puzzle
2007-02-15

A puzzle I faced when dealing with the interface was was how to handle initialization. What can be done when?
I found that -initWithAPIManager: is called once to instantiate the plug-in and that is matched with a single call to -dealloc, as expected. But that call occurs very early in the set-up and the nib file has not even been loaded. No nib file means no outlets, so although ivars can be set up, the interface cannot. So here I just set up default values for ivars.
-settingsView loads the nib and initializes it. Once that is done, the objects in the nib are instantiated. This method is called next. But it has no balancing method to undo anything I may have set up, so I add nothing to this method.
Next, -willBeActivated is called once and paired with -willBeDeactivated which is also called once. The documentation says that these are called each time the application is made active, but this appears not to be the case. Now that the outlets are ready, this is where I set up delegates and will initialize the state of the interface elements based on the ivar values. Anything I do that needs undoing will be undone in -willBeDeactivated.
The other parts of this series can be found via the Cocoa page.
The Squares Marked A and B Are The Same Shade Of Gray
2007-02-14

Surely not. The A square is darker, much darker! Most people would put money on it. But they'd lose. Open it in Photoshop and inspect the pixel values. Or on the Mac open up the DigitalColor Meter application and take a peek .
Edward H Adelson explains it all in great depth in his paper Lightness Perception and Lightness Illusions. There are some great interactive illusions on the web site as well.
Aperture Plugin: Making The Interface Work
2007-02-13

Now I need to add code to the Random_Wok class so that the interface does something. The alphaSet action is connected to the Lower/Upper/Both alpha case selection radio buttons. When the user changes the selection I get the selectedTag of the NSMatrix that holds the buttons and then update the example filename string:

The tags are set up to be 0, 1, and 2 for the three buttons via the Attributes pane of the Inspector:

And I have a typedefed enum called BTStringAlpha that encodes the values that the buttons can take.
The code for the length selection changing is a little different and took me a while to figure out. To get a number from the pop-up containing a list of number strings I need to get the integer value of the string that is the title of the selected item in the pop-up menu:

Changes to the postfix string just store the string and update the example string:

For that code to work, there must be an accessor _setPostfixString that stores the new string and releases any existing string:

If the Salt checkbox is selected I want to have the Generate button and the salt string available to the user. If not I want them grayed out. Here is the code that does that:

I use tags again for the four possible values of the string format pop-up. This time I have to update the state of the alpha buttons as well:

If Numeric is selected then the alpha buttons get grayed out, since they do not apply:

And for the purposes of debugging all of that, my example string display just shows the values that have been obtained from the interface:

This gives a display that looks like this:

Here the <1> comes from the selection of Hex, <14> is the length, and <2> shows Both.
The other parts of this series can be found via the Cocoa page.
Pictures of Smoke and How To Take Them
2007-02-12

Sensitive Light is the creation of Graham Jeffery. One of his subjects is smoke. How does he do it? Photocritic.org talks to him and finds out.
Aperture: How Do I Delete A Version Without Deleting The Master?
2007-02-11
Congrats on your blog! There definitely is a lack of consciousness on Apple's side with regard to the ease of use of manuals which should - in our opinion - reflect the ease of use of their hard- and software (which is not the case). Thanks for every effort to change that! I spent a lot of time trying to understand the project/album/folder business. It may become a little easier with your help. The next thing (which I suppose is linked with the above subject) I will have to get my teeth in is "How do I delete a version and keep the master"? Until now I have not found a way to delete just this one file and be sure I have not done harm to something else.
A warning dialog is always presented when a master is about to be deleted. When no masters will be deleted, the delete proceeds without the warning and the operation can be undone with command Z.

When you select an image and delete it with Delete Version, that version will always be deleted. The master is only deleted if the last version is deleted, so if you see the dialog, that's the last version. File > Delete Master Image and All Versions always trashes the master and all the versions, and gives the same warning dialog.
Some confusion arises with images in albums. Remember that albums are just a different way of looking at the same images that are in projects. They are not themselves separate versions. Any change to an image in an album (including deleting) will affect the image in the project and all other representations of that image in other albums in exactly the same way. On the other hand, removing an image from an album will make it disappear without deleting it.
Note that the images you see are always versions, since you cannot see or manipulate the master directly. Each time a photo is added to Aperture, it stores the master and creates a version from it that contains no adjustments or modifications. There is nothing special about that particular version. The consequence of this is that if new versions are created either by duplicating existing versions or directly from the master, then none of them is the "master" version. You can delete versions in any order and only when the last version is deleted will the master be deleted.
A warning dialog is always presented when a master is about to be deleted. When no masters will be deleted, the delete proceeds without the warning and the operation can be undone with command Z.

When you select an image and delete it with Delete Version, that version will always be deleted. The master is only deleted if the last version is deleted, so if you see the dialog, that's the last version. File > Delete Master Image and All Versions always trashes the master and all the versions, and gives the same warning dialog.
Some confusion arises with images in albums. Remember that albums are just a different way of looking at the same images that are in projects. They are not themselves separate versions. Any change to an image in an album (including deleting) will affect the image in the project and all other representations of that image in other albums in exactly the same way. On the other hand, removing an image from an album will make it disappear without deleting it.
Note that the images you see are always versions, since you cannot see or manipulate the master directly. Each time a photo is added to Aperture, it stores the master and creates a version from it that contains no adjustments or modifications. There is nothing special about that particular version. The consequence of this is that if new versions are created either by duplicating existing versions or directly from the master, then none of them is the "master" version. You can delete versions in any order and only when the last version is deleted will the master be deleted.
Hair Care or Digital Audio?
2007-02-10

You be the decider. Ridiculous Fish challenges the reader to match the logo with the product type. Not as easy as it sounds. Ridiculous Fish also hosts Hex Fiend, a fiendishly good hex editor.
Aperture Plugin: Hooking Up The Interface
2007-02-09

Hooking up the interface to an application is confusing for beginners. I've done it enough times to think that I know how it is done, but not enough times to be sure about it. So here goes.
For the Random Wok plugin, here is the nib file that contains the user interface:

The first area of confusion is File's Owner. What the heck is that? It's a stand-in for an instance of my Random_Wok object instance. It's called File's Owner because it is an instance of the Random_Wok class that "owns" the nib file (the "file" part).
The first thing I have to do is to tell Interface Builder that File's Owner is an instance of Random_Wok. I click on File's Owner, open the Inspector (shift command I), go to the Custom Class pane, and select Random_Wok from the long list of possibilities:

It would be so nice if Interface Builder would change the name of File's owner to Random_Wok after I had done this, but alas it does not. I have heard that many changes are coming to IB, so hopefully this is one of the improvements.
The next task is to tell IB what outlets and actions File's Owner (Random_Wok) has. More confusion because File's owner is an instance in the nib file and the outlets and actions are part of the class description. So with With File's owner selected, I click the Classes button:

and in the Inspector bring up the Attributes pane:

Those outlets represent pointers from the Random_Wok object instance to the interface elements in the nib file. That's how my plug-in will control the user interface. The SDK has already created these three for me, but has not connected them to the nib file (how would it know how?).
To make the outlet connections from File's owner to the views I control drag from File's Owner to the prefix NSTextField and click connect and then repeat for the postfix NSTextField, and to the Settings View NSView. This makes the prefix text field the first view for tabbing, and the postfix text field the last view for tabbing.

Actions are methods in the Random_Wok object that are sent messages when the user interacts with the interface. Clicking on the actions button shows that there are no actions for the File's Owner (Random_Wok) class yet:

To create the actions for the Random_Wok class I click on the Add button and fill in the names for my actions:

Then hook all of them up in turn by control-dragging from each of the controls to the File's owner instance and clicking Connect:

These actions coincide with the pars of the user interface that can send messages to my code: pop-up buttons, text fields, etc. Each action I create has to be added to the Random_Wok class files as a method and declared as in this example:

Having dealt with the actions I now need more outlets. The three that are provided for me are not enough: I have to be able to control many more aspects of the interface. So one at a time I add these to Random_Wok class, selecting the correct class for each one as I go:

Once that is done, I click back on the File's Owner instance, and use the Connections pane of the Inspector to connect up each interface element with File's owner, this time control clicking on File's Owner, dragging to the interface element, and clicking connect:

Finally I add each of these as outlet declarations to Random_Wok.h by adding this code:

Now when I compile and run I get this window instead of the generic controls:

I clearly need to adjust this a bit and clean up some problems, but now it is hooked up, I will be able to start writing the code that makes it come alive.
The other parts of this series can be found via the Cocoa page.
Aperture: Merging Libraries
2007-02-08
I'm an advocate for putting everything into one library. That lets me find what I want without trying to figure out how I classified the images I put in. But what if I have several libraries right now and want to merge them into one big library? Aperture has no built-in way to do this.
Merging Aperture libraries can be done almost perfectly just by exporting and importing by project. It requires some extra space: about the same amount as the smallest library you want to merge. That's because to merge, you'll have to export each project from the small library and then import it into the large library. Once all the imports are done, the small library can be deleted. Going from small to large minimizes the amount of extra storage needed.
I say to do it this way (process all the projects first, then delete) rather than deleting projects as you go, because deleting a project deletes its masters. And any other project that has not yet been copied that uses images in an album from a deleted project will have those missing once the libraries are merged.
Merging using prroject export and import will preserve all the versions, edits, metadata, import groups, previews, albums, and almost everything else. Anything in the small library that is not inside a project, however, will not be copied across -- smart albums stored at the top level for instance. So move everything into one project or another before the copy.
To export a project, select it in the projects pane, and select File > Export > Project... That will bring up a dialog to select a destination:

The Consolidate images checkbox will take any referenced masters and make a copy of them in the exported project. The projects in the library are not changed by this. The checkbox appears even if there are no referenced masters in the project, which is a little confusing.
An exported project looks like this in the Finder:

And it can be imported simply by dragging onto the projects pane:

There is one thing extra that will come across with the import: image duplicates. If one project has an album with images from another project, then when the first project is exported, copies of the masters for those album images from the second project will be included in the export. So when the projects are both imported into the destination library, there will be two copies of some of the masters. That will cause duplicates to show up in some smart albums, and may cause confusion if the images are subsequently adjusted and the album versions remain unchanged. Fixing this requires a lot of manual work.

Keywords will come across correctly, since the keyword database is automatically merged. If you are sure that the keywords in both libraries are organized the same way and correct, then I recommend importing the projects with the keyword HUD unlocked. This will allow the keywords to merge. Bring up the keyword HUD with shift H and click the lock icon to lock or unlock:

If the keyword HUD is locked for the import, the new keywords will end up in an Imported Keyword section at the end of the keyword list and they will have to be rearranged by hand.
Hopefully Apple will add the ability to merge libraries to Aperture in the future.
Merging Aperture libraries can be done almost perfectly just by exporting and importing by project. It requires some extra space: about the same amount as the smallest library you want to merge. That's because to merge, you'll have to export each project from the small library and then import it into the large library. Once all the imports are done, the small library can be deleted. Going from small to large minimizes the amount of extra storage needed.
I say to do it this way (process all the projects first, then delete) rather than deleting projects as you go, because deleting a project deletes its masters. And any other project that has not yet been copied that uses images in an album from a deleted project will have those missing once the libraries are merged.
Merging using prroject export and import will preserve all the versions, edits, metadata, import groups, previews, albums, and almost everything else. Anything in the small library that is not inside a project, however, will not be copied across -- smart albums stored at the top level for instance. So move everything into one project or another before the copy.
To export a project, select it in the projects pane, and select File > Export > Project... That will bring up a dialog to select a destination:

The Consolidate images checkbox will take any referenced masters and make a copy of them in the exported project. The projects in the library are not changed by this. The checkbox appears even if there are no referenced masters in the project, which is a little confusing.
An exported project looks like this in the Finder:

And it can be imported simply by dragging onto the projects pane:

There is one thing extra that will come across with the import: image duplicates. If one project has an album with images from another project, then when the first project is exported, copies of the masters for those album images from the second project will be included in the export. So when the projects are both imported into the destination library, there will be two copies of some of the masters. That will cause duplicates to show up in some smart albums, and may cause confusion if the images are subsequently adjusted and the album versions remain unchanged. Fixing this requires a lot of manual work.

Keywords will come across correctly, since the keyword database is automatically merged. If you are sure that the keywords in both libraries are organized the same way and correct, then I recommend importing the projects with the keyword HUD unlocked. This will allow the keywords to merge. Bring up the keyword HUD with shift H and click the lock icon to lock or unlock:

If the keyword HUD is locked for the import, the new keywords will end up in an Imported Keyword section at the end of the keyword list and they will have to be rearranged by hand.
Hopefully Apple will add the ability to merge libraries to Aperture in the future.
Envy and Blame Are The New Marketing Tools
2007-02-07
It's amazing how badly and in how many ways Microsoft is able to send disastrously damaging messages to its users these days.
Roger Ehrenberg writes for Seeking Alpha, describing in detail the thud of envy that has accompanied Microsoft's recent marketing and product efforts. And then there is whatswrongwithu.com that blames the citizens of most of the developed Asian world for Microsoft's failure to successfully market the XBox360 in that region. Alpha geeks are having a bad time with Vista as well. If you can't impress them, then where are the early adopters going to turn for advice?
Roger Ehrenberg writes for Seeking Alpha, describing in detail the thud of envy that has accompanied Microsoft's recent marketing and product efforts. And then there is whatswrongwithu.com that blames the citizens of most of the developed Asian world for Microsoft's failure to successfully market the XBox360 in that region. Alpha geeks are having a bad time with Vista as well. If you can't impress them, then where are the early adopters going to turn for advice?
Aperture Plugin: Designing The Interface
2007-02-07

The user interface for the plugin is a single window. It's a combination of elements put there by Aperture and elements put there by the plugin. So far I have not defined an interface or hooked it up, so there has been nothing to see when the plugin is used except the Aperture elements.
In XCode the resources folder holds the user interface files:

And it is the nib file that describes the interface and contains instances of the objects it uses. Double-clicking on the nib file opens Interface Builder and shows the current Settings View:

I can remove that message, resize the window and add whatever I need to that view to implement the user controls. After some dragging and dropping, and more dragging, and more dragging, I came up with this:

It's not 100% there, but is good enough to get me to the next stage. The string format pop-up is populated with the four ways of creating the random string, but the length pop-up that follows is not. That will need to be filled dynamically by code depending on which choice of format is made.
It took me a little while to figure out how to add new items to a pop-up menu. Either drag a new one (called "Item") from the menu palette, or much more easily, just option drag an existing one.
Some of the interface elements will be disabled when they are not in use. For instance there is no letter case option if Numeric is chosen, so that will go gray. And if Salt is not selected then the Generate button and the text field will be gray and disabled.
The Example file name at the bottom will change dynamically as the user selects and types so they can see an example of the format. It will include the prefix and postfix strings in their proper positions and the random string in the middle.
I added the None strings in the text fields as placeholders in Interface Builder via the Attributes pane of the Inspector. They will appear whenever nothing is present in the field.

The next step is to join the user interface elements to the code and make them do something useful.
The other parts of this series can be found via the Cocoa page.
GeForce 7300 GT Firmware Update
2007-02-06
Apple has made a firmware update available for the GeForce 7300 GT graphics card. This ships in some of the MacPros, so may be of interest to anyone running Aperture.
Kevin Smith Protests Dogma
2007-02-06

Kevin Smith, Director of Dogma, wanted to know a little more about the rumored demonstration by 1500 people outside a theatre showing his movie. Here he tells the story of how he and a friend went along to join the crowd.
Aperture Plugin: Random Thoughts
2007-02-06

"The generation of random numbers is too important to be left to chance" -Robert R. Coveyou
At some point in this project I will have to implement the random file names. But how to generate them? I want to give the user the ability to repeatedly create the same random names for the same images if the export is run over and over. And I want the user to be able to add more images and have the original set keep the same names. This means that I will need to use a hashing technique that transforms each image name into a random name rather than simply using a random string generator. Since complete randomness is also desired (if chosen by the user) I will need "salt" that is added to the hash that is fixed for each export but changeable between exports.
Another feature I want is to be able to control the format of the random name: its length, what characters it can contain, what it must start and end with. So I am now getting close to the point of needing to design and implement a user interface. Here is a quick diagram that shows how I think it will work. Red boxes are user input. Green boxes are code:

For testing purposes I can make a really simple hasher: one that does nothing but convert all of its settings to a readable string. That will let me examine the output file names to test the user interface. Once that is all working I can implement the hash routine for real.
I can offer a variety of random string formats. Depending on the format I will be able to generate a string of a certain length. There is an upper limit on the number of random characters I can generate for a given number of random input bits. Assuming that I have 64 bits of randomness to work with, a purely numeric random string can have up to 19 characters, an alphanumeric string with both cases only 10. I plan to offer numeric, hex, alpha, and alphanumeric, all with either uppercase, lowercase, or both cases as an option.
So far I have found two likely ways of generating the hash. One is a C routine called lookup3 that would need adapting for Objective C. That will get me up to 64 bits. The other is to use the built-in openSSL library that comes with Cocoa that will give me 128 bits.
The other parts of this series can be found via the Cocoa page.
Dells Cost Too Much
2007-02-05
Salon has an article by Andrew Leonard that explains Dell's failure in China (oh yes, they bombed there).
As Simon Ye and Annie Chung at Gartner Research called it four days later, Dell -- the low cost leader in most of the world -- was run out of the market by companies willing and able to produce computers at a much lower price.
There can only be one lowest-cost provider. And if that is your whole company's market advantage, then you better not be beaten on price. Next, the Chinese will duplicate the rest of Dell's business in the rest of the world and eventually most of the computer industry will go the way of the car industry.
If I were Apple I'd be licensing Mac OS X -- but only to the Chinese.
As Simon Ye and Annie Chung at Gartner Research called it four days later, Dell -- the low cost leader in most of the world -- was run out of the market by companies willing and able to produce computers at a much lower price.
There can only be one lowest-cost provider. And if that is your whole company's market advantage, then you better not be beaten on price. Next, the Chinese will duplicate the rest of Dell's business in the rest of the world and eventually most of the computer industry will go the way of the car industry.
If I were Apple I'd be licensing Mac OS X -- but only to the Chinese.
A Basement Full Of Macs
2007-02-05

Soyburger has a basement full of Macs and has posted photos on Flickr. There must be a hundred or so. All kinds, back to the original Apples, Mac, and the Lisa. Plus software, Newtons, PowerBooks, packaging, monitors, hard drives, iPods,..... There are many I don't think I have ever seen before.
Aperture Plugin: Saving The Image Files
2007-02-04

Since my code just logs file names so far, the next thing I am going to do is change it so that it actually saves the data to disk. Initially I am going to save the files without using any randomization. Later I will implement the random naming.
The full path name to use comprises the name that I was given by -exportManagerWillbeginExportToPath: (and saved in _exportBasePath) with the file name given in the path variable in -exportManagerShouldWriteImageData:relativeToPath:forImageAtIndex:

And this works. I'm using the file names given to me by Aperture which means either the master file name or the version name depending on the user's selection on the dialog.
After some experimentation I discovered that Aperture always gives the plug-in a filename that can be written successfully. If a file already exists with the name of the image to be written, Aperture appends (1) or (2), etc. to the end of the name and gives that to the plug-in. So instead of trying to handle all the cases that Aperture is already handling for me regarding the naming, the strategy for generating random names should be to let Aperture do all the file writing with its own names and then rename the files myself when it is done. This actually makes randomizing the names easier because I will be in possession of all the information about all the files at the same time and won't have to maintain any state between naming image files.
To rename all the files at once I will have to make a copy of all the paths as I am given them. Once the exports are all done, I will generate a list of random names, and then use NSFilemanager -movePath:toPath:handler: to do the rename.
To store the names I create an NSMutableArray called _origFileNames and initialize it in the initWithAPIManager: method. Then in -exportManagerShouldWiteImageData: I add each file name to the array:
And in -exportManagerDidFinishExport I iterate through the stored filenames and do the rename:

For now I am just using a sequence of numbers 0001, 0002, etc. And I am being careful to keep the same file extension. My code is a little sloppy here with memory usage (what if this code is run with a huge number of files?) and I am not checking a lot of possible error conditions, such as existing files with the same numbered names. I will have to tackle problems like that when I write my final randomizing code.
The other parts of this series can be found via the Cocoa page.
Site Focus: Aperture Plugged In
2007-02-03

Aperture Plugged In is a new site dedicated to Aperture plugins. It lists all the Aperture plugins known to man, plus links, forums, resources, and news. Hopefully the site will grow and be a good source of information for struggling plugin authors.
WWDC 2006 IT State Of The Union
2007-02-03
For developers, another WWDC 2006 presentation is available via iTunes: IT State Of The Union.
Fix Your Demand Chain
2007-02-02
Owen Thomas writing for Business 2.0 hits several nails on the head in an article about Dell's business performance these past few years:
Dell needs to figure out a new selling proposition, since its price advantage has disappeared and its customer-service message lacks credibility. That's why Michael Dell's new job is so tough. It's not clear why anyone would buy a Dell today.
The other factor in the equation is that Dell only controls half of their product. Microsoft controls the other half, arguably the most important half. So they can't control most of the product, and the rest is made from commodity parts. It's no wonder that the biggest player is feeling the biggest pain.
Dell needs to figure out a new selling proposition, since its price advantage has disappeared and its customer-service message lacks credibility. That's why Michael Dell's new job is so tough. It's not clear why anyone would buy a Dell today.
The other factor in the equation is that Dell only controls half of their product. Microsoft controls the other half, arguably the most important half. So they can't control most of the product, and the rest is made from commodity parts. It's no wonder that the biggest player is feeling the biggest pain.
Aperture Plugin: What Happens When I Run It??
2007-02-02

So I compiled the plugin, copied it from the Random Wok/build/Release folder to the ~/Library/Application Support/Aperture/Plug-Ins/Export folder, and fired up Aperture (with a small test library!). The plug-in appears in the Export menu along with another plug-in:

But when I select some images and run the plug-in:

That's me. I'm the vendor for this plugin, so I better fix it. After some poking around and some help from another plugin author, it turned out that the info.plist contained these lines:
and should have contained these instead:
The difference is the underscore in the name. That's a bug in the template code: most but not all uses of the plug-in name have their spaces changed to underscores.
So I fix that (and tell Apple) and run again, this time getting this dialog:

The help button works, taking me to my help page. And I can select a version preset and whether versions or masters are exported. Canceling works. Clicking Export brings up a folder dialog and lets me select a destination. Clicking Export on that dialog makes Aperture process for a little while, and then it is done. The progress bar is not functional yet, and my only output is in the console log file:

So far so good. Next I need to make the code actually save the files.
The other parts of this series can be found via the Cocoa page.
The Bagelturf site welcomes Donations of any size






