Archive

Six Days of Cocoa: Day Two

Day Two: code-name iChibi

My whole family is very much into all things japanese (including, of course, manga and anime). The other day, they found a little “sound-playing ghost” called Flele (I have no idea what the name means).

As far as I can tell, Flele is a small application that you drop one or more MP3s on, and it starts to “sing” when you click on the character’s hair. I have no idea how it actually works, since it requires Windows and the Japanese language pack. But my daughter and I quickly hashed out that what we could do would be a globally-floating iTunes controller, who would respond to click and animate when music was playing (we’ll figure out the “singing” part later).

iChibi

My daughter drew lots of PNGs this weekend (using Painter, of course), and we assembled them in sequences to make animations. The iChibi can blink, and lights turn on/off on its headphones whenever music is playing.

iChibi can be dragged anywhere on screen, and will float on top of all windows.

Clicking on its left ear starts playing in iTunes, on the right ear stops playing. The left headphone goes to the previous track, the right headphone to the next track.

Clicking on the zipper gives a Settings panel, where you can control the its size, opacity and which playlist the songs are coming from.

If you are interested in following the development of iChibi, follow @ichibiapp on Twitter.

ImageSoup

Since iChibi uses lots of images for animations, and I didn’t want to keep multiple copies of the same image in memory (for example, if an image is re-used in multiple animation loops), I figured I should make a small class to hold all the images, loading them as necessary. I named this class ImageSoup, referring to the Newton’s filesystem of course…

ImageSoup is very simple, and does not need to be its own class (after all, it’s a dictionary). But it is nice to be able to abstract that implementation detail out of your code, as well as the image-loading code. What if your source image was an Acorn image or a Painter RIFF? You could hide the image-loading code in ImageSoup, and your calling code need not be aware of this.

To use ImageSoup, just create an ImageSoup* instance and always ask it to load your images (using the full path to the image):

What is it?

Around the time of c4[2] I was futzing around with making a proper UI for my Twitter Avatar Acorn script.

I also wanted to learn about Core Data and Image Kit.

So I wrote AvatarManager, which uses Core Data to store images in png, tiff or jpg format and displays them in an ImageKit view. People suggested that it should not be limited to Twitter (which is my main Social Network app), so I made a pop-up menu populated by scripts that are run as an NSTask by the app. The scripts provide the interface to the image-upload interface of your on-line service.

Things change

Unfortunately, the Twitter “API” got modified and my script broke, so I lost interest. I was using Ruby’s ‘mechanize’ module to essentially script my way in the web page, which is an interesting way of doing it.

It’s still a good project!

I think the app is a good starting point: it’s simple, robust and extensible. The source code is easy to understand, and it shows how to use the Keychain (to store your passwords) and NSTasks.

You can help!

Grab a copy of the code and hack away! Patches welcome. Especially if you have new and updated upload scripts.

hg clone http://bitbucket.org/philippec/avatarmanager

Requirements

You can debug your QuickLook plugin easily with the help of qlmanage. But sometimes, you don’t want to dump your plugin in /Library/QuickLook/ every time you build because you run as a regular (non-admin) user.

QuickLook has a search path feature. You can set the search order, and in my case I use my two build folders (Debug and Release) before the main /Library/QuickLook/ folder. It is a global, per-user property (hence the -g), and as far as I know, the array can contain as many values as you want

All done? Great. I wanted some extras in “Browse Images”, for example a slideshow and a filter. There is a guide to build a slideshow application, but it makes you write a separate application. We already have “Browse Images”, surely we can re-use it?

The first method is the same as before, while the second one returns not a MyImageObject (what is stored in mImages), but the path of that object. To get this path, simply add an accessor to MyImageObject:

- (NSString*) path
{
return mPath;
}

(Also add the prototype to the interface, lest you get a warning…)

Tying it together in Interface Builder

Now that our controller conforms to the IKSlideshowDataSource protocol, we need a way to start the slide show. To this end, create an IBAction in the controller’s interface, and implement it like this:

Create a button in Interface Builder, and Control-drag it to your controller to connect it to the startSlideShow: action (IB 3 should have automatically picked up the change in your header file and offer you the new action).

Build and run. You should be able to browse pictures like before, and pressing on the “Slideshow” button should start a full-screen slideshow, complete with index sheet.