Skip to main content

Cocoa

Announcing the support forums!

forum icon

At last, I'm happy to announce the Code Sorcery Workshop support forums! These forums will gradually become the official support channel for our Mac products Meerkat and Pukka, as well as a place to discuss what's on your mind with regard to our website, potential future products, our services, or happenings in the Mac & Drupal communities.

The forums have been open for a week or two in unannounced form, but have quite expectedly not garnered much activity, so consider this the official "word". Feel free to go to it!

Feature Run-Down

We are using Drupal for the forum solution, which is what is used for the rest of the website as well. I'd like to take a moment to go over some of the features that this provides. In the near future, I also hope to make another post about the more technical details, such as which modules were used, what kind of custom solutions were implemented, and what administrative features are provided on the backend.

Main Page

The main page gives an at-a-glance view of the latest topics, much like any forum software. Posts are organized into containers, such as Mac OS X Products, and below that, forums addressing a particular product or group of topics, such as Pukka. When new topics are posted under a forum, they bubble up to the top.


Forums main page (click to enlarge)

Your Account

To participate in the forums, you must register for an account. With this account, you can maintain a unique identity across all of the posts. You can include as much or as little information as you like, currently including real name, photo or avatar, physical location, and website. This information is only available to other forum users -- only your username is available publicly.


Account page (click to enlarge)

In addition, you get a box in the right sidebar with easy access to My forum posts (posts created by you) and My forum votes (posts you've voted on).


User box

Search

Just like the blog archives and all of the pages on the site, forum topics are searchable. And these searches are able to be bookmarked, so you can easily check back frequently for updates related to a topic you are interested in.

Topic Voting

Aside from easy access to any forum topics that you may have created yourself, you can also vote on anyone else's topics using a zero- to five-star rating system. Perhaps the best use for this feature is that you can use this to flag topics that you are interested in periodically checking back on. Another use might be a tip that you really want others to see or a feature request that you'd like to weigh in on.

The popular topics get aggregated to a special page called top forum topics where they can be easily tracked. I'm hoping that this can be a useful way to chart the future direction of our applications, as well as to more easily resolve important issues affecting many customers.


Topic voting

Feeds, Feeds, Feeds

One of the strongest features of the forums is easy and plentiful RSS feeds. Currently, you can access feeds for:

  • All forum topic activity: codesorcery.net/forums/feed
  • Container activity: For example, all posts about Pukka. Just add /feed to the end of any container URL.
  • Topic activity: If you make a post, you subscribe to all comments on the post by clicking the link on the topic page or adding /feed to the URL.

Forum feeds (click to enlarge)

Conclusion

In conclusion, I'm happy to launch the forums and I hope that they will be of benefit to users of our products, Mac, iPhone, and Drupal enthusiasts, and folks interested in our services, for starters. Please, if you have any suggestions or feedback, consider using the General Discussion forum topic.

Enjoy the forums!

Getting around... table

I recently had the pleasure of participating in the excellent Mac Developer Roundtable podcast, where the featured topic was open source software. I've been involved in open source software myself for about ten years, so it was great to, first, be asked onto the show, but also, to share my experiences and knowledge -- not to mention, to "meet" and discuss software with some great fellow Mac developers!

This podcast was particularly satisfying because it brought together the two main halves of my business -- Cocoa and Mac development, where I tend to use open source software, and Drupal and web development, where I tend to contribute open source software.

So, have a listen to the show and if you'd like to check out my main open source efforts, I have an info page with more details.

Hooking into Portland CocoaHeads

I had the opportunity to attend the October meeting of the Portland CocoaHeads club last night and had a great time! I especially liked the location, CubeSpace, and look forward to spending some more time there soon.

My friend Jon Wight of Toxic Software was able to be on this side of the country, too, to demo his, and others', recent work on the Obama iPhone application. Great job, guys! It's a really impressive piece of software, all the more so because it was a volunteer effort and was created in a mere three weeks!

I also did brief demo towards the end of the meeting of my dockless mode hack, just to share it and to get some eyes on the problems I've seen with it.

Lastly, just a note for the curious. When I introduced myself last night, a couple folks mentioned that they had heard of my blog or products, but had no idea I was based in Portland. Well, it's a recent thing, and I haven't tended to talk about travel or personal life much on this blog, but I'm now located just outside of Portland. This year has been a wild ride wherein my wife and I have attempted to live in a number of places, taking advantage of my mobile work ability and our shared wanderlust. Thus far, we've lived in DC, which we sadly left in March after three years, and then in Spain, Cape Cod, and now, the West Coast. I think we'll be staying here for some time, though, especially given a great Cocoa group like CocoaHeads and the vibrant tech (and not to mention, beer) scene in Portland.

Offline Subversion: Building a Trac of your own

trac_svn.png

I have recently, like many other folks, become a fan of my friends Daniel Jalkut and Manton Reece's new Mac developer podcast, Core Intuition (especially the whimsical theme music). In their latest episode, Traveling Luddites, among other things, they discuss distributed version control systems such as Git, Mercurial, and Bazaar.

I'm kind of in the same boat in that I've spent little or no time trying these systems out compared to what I've been using, Subversion, and am a little hesitant to invest a lot of time into migrating and learning a new system. Don't get me wrong -- I'm a hacker and I love to try new technology. However, I don't really have any problems with Subversion and in fact, some time ago I came up with a really sweet setup for offline development, offsite backup, and integrated project management using Trac that I've been meaning to blog about, and this episode was just the catalyst I needed.

Following the directions here, you will get:

  • Offline access to your versioning, ticketing, and documentation systems.
  • Support for multiple projects (though one project is just fine, too).
  • A multi-user setup, if you need it.
  • Integration of your code repository with web-based ticketing, GUI changesets and diffing, activity timelines, and project roadmap planning.
  • Complete, incremental offline backup whenever you like (and have a connection).
  • Very little intrusion into your Mac OS X environment.
  • Complete flexibility in getting your data out at any time.

Just have a look around the Trac demo to get a feel for this system. It was a tremendous thrill during the development of Meerkat to see the roadmap progress meter get ever closer to the 1.0 milestone as I closed tickets and definitely helped me organize the project much better than before I adopted Trac.

And this isn't rocket science -- if you're already technical enough to be using version control, I'm pretty sure you can handle this and have a great setup in a short amount of time. I've found that the parts that trip most people up are Trac installation and Apache configuration. Relax, I've got you covered.

A quick historical note

I've been using Subversion in both user and administrator capacities since 2001 and before that, like Daniel and Manton, I too had a painful coexistence with CVS (and still do sometimes with projects like Drupal). I was introduced to SVN by a former co-worker, Garrett Rooney, back in the days when he was one of the few people who knew about and worked on SVN. Since then, he literally wrote the book (Practical Subversion) on SVN and through the years, I've come to really love the project and have introduced my fair share of folks to it as well.

While, as I said, I'm generally open minded about new technology and systems, when it comes to version control I'm in the camp right now of "if it ain't broke, don't fix it". I'm using Trac on some other client projects, including one with a team of over 30 people all over the world, and I use SVN for the development of both Pukka (over two years of commits) and Meerkat (about a year of commits) as well. It works well for me, I don't have hassles, and since SVN has been integrated with Trac, Apple's Xcode, and the Apache web server that ships on OS X, it's going to take free pony rides or something comparable before I seriously look elsewhere for my version control needs. Of course, YMMV.

What you'll need

In order to replicate this setup, you'll need:

  • A Mac running Leopard and administrator access to it.
  • Familiarity with SVN, but you don't need an existing repository.
  • Some Terminal experience.
  • About an hour to spare (or less, and not counting some background compilation time in which you can do other things).

If you already have MacPorts installed, you'll save even more time and you won't even need to manually download anything else.

Ready? Let's do it.

Install MacPorts and Trac

I'll admit it, Trac can be a little intimidating to setup because of dependencies. But if you get MacPorts, this can all be reduced to a fraction of the time and very little hassle.

  1. Install MacPorts if you don't have it already. The latest installer package for Leopard is here.
  2. Make sure that /opt/local/bin is in your path so that the commands provided with MacPorts are available to you easily in the Terminal.
  3. Open up Terminal and start the Trac installation process by typing sudo port install trac.
  4. Let it roll while you grab a $BEVERAGE or move on to the next steps. When it finishes, you should be able to access a command called trac-admin in Terminal. Depending on what ports you already have installed, you may need to answer some basic questions during the install process, so keep an eye on the window. Brian Cooke's Growl When Done is a good solution here.

Setup Subversion

You'll need to setup a parent directory for your Subversion repository or repositories. I like /usr/local/svnroot, so if you are using someplace else, you'll need to alter the directions below as appropriate. Keep in mind that stuff under /usr/local gets backed up by Time Machine by default, even if you exclude "System Files and Applications". This is separate from the backup mechanism that I'll talk about in just a little bit.

  1. Make a top level Subversion folder using sudo mkdir /usr/local/svnroot and change into it.
  2. Either move an existing repository into a subfolder of this folder, or create a new repository folder using sudo svnadmin create MyProject in Terminal.
  3. Make the whole setup owned by Apache, which on Leopard can be accomplished with sudo chown -R _www:_www . in the Terminal.

Setup Trac

Again, I prefer a similar convention here and put stuff under /usr/local/tracroot. Adjust as necessary.

  1. Make a top level Trac folder using sudo mkdir /usr/local/tracroot and change into it.
  2. Create a new Trac project using sudo trac-admin MyProject initenv.
  3. Edit the MyProject/conf/trac.ini file to configure it. You'll likely just need to change the following items:
    • max_size if you want to upload larger files to the wiki
    • downloadable_paths if you have a non-standard repository structure
    • link to something like http://localhost/trac/MyProject
    • descr, footer, name, and url if you wish
    • repository_dir if you didn't specify it during the initialization step
  4. Give your account full project permissions using sudo trac-admin MyProject permission add <username> TRAC_ADMIN in Terminal (replacing <username> with your own username).
  5. Make it owned by Apache using sudo chown -R _www:_www . like you did with SVN.

Configure Apache

This is perhaps the trickiest part, but I've done the work for you. I did some poking around and figured out a good way to get this working with the Apache that is built into Leopard. Although I haven't tested the other parts of this guide for Tiger compatibility, Apache is pretty much the part that requires Leopard, since it ships with Apache 2 and has some of the modules necessary for SVN integration built in. If you have your own Apache 2 going with MacPorts or something else, perhaps this will still work for you.

First, you'll want to create a password file for authenticating your Trac and SVN users, even if it's just you.

sudo htpasswd -c /etc/apache2/other/htpasswd <username>

Be sure to replace <username> with your own username. This command will create a new password file at the chosen path and add your first user. If you have other users, repeat the command above with their usernames but leave off the -c option since the file already exists and you don't want to clobber the previous commands.

Next, you want to create a configuration file for SVN to make your repository available over the (local) web and to password protect it. Create a file at /etc/apache2/other/svn.conf that looks like this:

LoadModule dav_svn_module libexec/apache2/mod_dav_svn.so
LoadModule authz_svn_module libexec/apache2/mod_authz_svn.so
<Location "/svn">
    DAV svn
    SVNParentPath /usr/local/svnroot
    AuthType Basic
    AuthName "Subversion Repository"
    AuthUserFile /etc/apache2/other/htpasswd
    Require valid-user
</Location>

After this, make another file at /etc/apache2/other/trac.conf that looks like this:

ScriptAlias /trac /opt/local/share/trac/cgi-bin/trac.cgi
<Location "/trac">
    SetEnv TRAC_ENV_PARENT_DIR "/usr/local/tracroot"
    AllowOverride None
    Order allow,deny
    Allow from all
    AuthType Basic
    AuthName "Trac"
    AuthUserFile /etc/apache2/other/htpasswd
    Require valid-user
</Location>

Remember in both of these instances to change the paths as necessary if you put your SVN or Trac environments someplace other than the paths I mentioned above.

Once these files are set, go to Terminal and issue the command sudo apachectl graceful to let the configurations take effect. Once you do, you should be able to reach your Subversion repository at http://localhost/svn/MyProject and a list of your Trac projects at http://localhost/trac. Both will be password protected using the account(s) you created above.

Backing it up

You're almost there! The last bit is some scripting that lets you back both of these systems up to a remote server using rsync over SSH.

  1. Edit a new text file at /usr/local/bin/ts (or $HOME/bin/ts, if that's how you roll) and fill it with the following:

    #!/bin/sh
    echo "Backing up Subversion repositories..."
    /usr/bin/rsync -e ssh -avz --delete /usr/local/svnroot/ <username>@<hostname>:svn/Repository.sync
    echo "Backing up Trac databases..."
    /usr/bin/rsync -e ssh -avz --delete /usr/local/tracroot/ <username>@<hostname>:trac/Trac.sync

    Be sure to replace the <username> and <hostname> values with whatever username and hostname your SSH account has.

  2. In Terminal, use chmod 755 /usr/local/bin/ts to make the script executable.

Now, whenever you want to incrementally backup your SVN and Trac databases, just type ts (think: "trac sync") at the shell. Everything that has changed since the last time you performed this command will get copied up to the remote server, keeping a handy backup of both your SVN repositories and your Trac installations should you need to move to another server. And even without the Apache configuration, the SVN repository will be useful as a standalone. Just keep in mind that it is for backup purposes and there is not any two-way syncing going on. That is, your local copy is the authoritative copy and is the one that you should use from day to day, and ideally over HTTP and not using local filesystem access to /usr/local/svnroot directly.

Conclusion

This system has been really useful for me during the development of Meerkat and through the continued development of Pukka, since I've been able to easily track feature requests, bugs, wiki-based notes for future reference, and have it all tied together with Subversion commits. In addition, I've been able to take advantage of offline time while at airports or otherwise on-the-go to actually get code committed, issues resolved, ideas jotted down, and processes documented.

I hope that this guide has been useful to you. Of course, feel free to leave a comment if you have any questions or clarifications or find any typos and I'll try to correct them.

Happy Trac-ing!

Fun with Cocoa: Snarf

Posted in

A friend of mine asked me today if I knew of a quick and easy way to preview an ICNS file as it would look on an application in Mac OS X's dock. I didn't, aside from opening an existing app's bundle and overwriting its icon or something like that.

Late tonight I decided that I could probably whip up a tiny app to accomplish this sort of thing in far less than an hour, and I did! So I give you: Snarf (requires Tiger or Leopard). Snarf allows you to drag an ICNS file either onto its main window or onto its dock icon and will instantly update to use the dragged file as its new icon.

There's not much more to say than that, so enjoy!

Feature requests versus the "right way" to do it

One of the challenges of developing Mac software, particularly for an audience that is generally more technical than the average user, is that your users compare your application to others that are out there on the basis of how they utilize the rich set of technologies available on Mac OS X. And I'm not just talking competitors here, but any Mac application. This can be both a blessing and a curse, as it can inform you of and inspire you to add great new features, but can also cast a seemingly bad light on your own product if you are unable or unwilling to implement certain functionality. Users often don't care why you might not want to or can't implement features which are, in your own estimation, not the "right" way of doing something -- at least not right now. Other apps are doing it, why can't you?

I'm hoping to provide some insight into my thought process on making these judgement calls and talk about a specific issue that I've been working on in this department. I'll get a bit technical, but I'll try to explain along the way for the non-programmers in the room. And I'll mention a couple of other apps by name that handle the same issue in different ways. I don't mean to call out or embarrass anyone, and all the apps that I mention are ones that I use (and love) on a daily basis, but I want to show what other developers are doing. Lastly, I have an overriding goal here to be a somewhat exhaustive resource for this particular issue for other programmers to find, too.

What's up, dock?

A big feature request that's been hanging around for some time for Pukka is the ability to run without a dock icon. For a utility with a small footprint like Pukka, this makes a lot of sense for a number of reasons:

  • As of Pukka 1.6, a status bar menu provides omnipresence for all of the app's "background features" -- looking up bookmarks and visiting your links online.
  • Pukka is not visible when you are not using its "foreground features" -- posting bookmarks -- anyway. Some users would like to not have to think about it by seeing it in the dock and task switcher.
  • Pukka has long supported a "quit after posting" feature which quits the app entirely after a post is made. Since you can call Pukka via your RSS reader or the browser bookmarklet and since it's lightweight and starts quickly, Pukka can come and go only when you need it. People who like an uncluttered dock really appreciate this, though some people would rather have Pukka running all of the time, but still not in the dock. After all, lingering invisibly in the background is faster than starting up on demand.
  • "All the other apps are doing it!" :-) Apps that I use that have a user-configurable dockless mode include Twitterrific, MenuCalendarClock, Knox, BluePhoneElite, SSHKeychain, and iShowU. There are many more that do as well.

I should make a distinction here between applications like Lighthouse, Macaroni, and Growl (which I also use) which always run dockless, since these apps have alternate interfaces -- typically robust status bar menus or preference panes -- that allow use of the application. I'm talking about applications that let you choose on a whim whether you'd like to run without a dock icon or not -- defaulting, of course, like normal applications, to running with a dock icon.

Users who are used to dockless apps know the downsides -- no application switching, the app doesn't show up in the Force Quit menu, and sometimes there are window focus issues -- and are willing to accept them as limitations in Mac OS X. But there are some issues on the developer side that make this feature more difficult than one might think at first pass.

How do you work this thing?

The only real way* to make an application run dockless is to change a setting in a file inside of its application bundle -- though a variation on this exists, as I'll describe in a little bit.

* I do know about TransformProcessType, a Carbon call, which can go from dockless mode to having a dock icon, but this has to happen too early in the launch process to read a user's preference setting, plus it's only a one-way transition.

A Mac application is actually a folder named <application name>.app containing a number of files and folders, one of which is called Info.plist. This property list file contains entries such as the application's name, version, copyright info, and other info used by the system to query what the application is all about.

If you add an entry to an application's Info.plist called LSUIElement and set its value to a string containing the number one, relaunching the application will make it go dockless. There are even applications like Dockless and Dock Dodger that will do this for you for a given application. Most of the applications that I mention above use this method to go dockless.

However, I've long preferred not to do this for a couple reasons:

  • It's bad form for an application to modify itself -- though I realize it's not the end of the world.
  • If the user is not an admin or if the application is located someplace like a network-mounted share, the user will not be able to -- and shouldn't be able to -- modify the app bundle that is shared by other users or even other computers.
  • Lastly -- and this is the big one -- Apple introduced code signing in Leopard and, according to the documentation, it's only a matter of time before this method of altering the Info.plist will render the application unusable.

With code signing and Info.plist modification on the fly, the writing is on the wall:

A seal, which is a collection of checksums or hashes of the various parts of the program, such as the identifier, the Info.plist, the main executable, the resource files, and so on. The seal can be used to detect alterations to the code and to the program identifier. #

Various components of the application bundle (such as the Info.plist file, if there is one) are also signed. #

Your code must be immutable once signed. After signing, do not attempt to change executable code (including symbol tables), the Info.plist, or your program’s resource files. Do all that before signing. If you make modifications after signing, the signature may be invalid. #

And according to Apple, you should be signing code now. Not doing so can interfere with the keychain user experience, Parental Controls, firewall, and other integrated systems in Leopard that rely on code signing.

So, where does that leave us?

When I talked to Marko Karppinen, whose company makes the excellent Knox security application, at last summer's C4 in Chicago, he let me in on how he accomplished a user-specified dockless setting in that application.

If you look at the application bundle, it contains another copy of the application within a subfolder of the app bundle itself -- sort of a Russian Doll. But if you look closer, you'll see that all of the components of this "inside" application are actually symbolic links to the parent application's version, except for the Info.plist file. And -- you guessed it -- the internal Info.plist has the LSUIElement set. For the curious, here is a shell script that I came up with to be used as an Xcode build phase to accomplish this.

I'm actually using this method successfully with Meerkat, my next application (which is currently in private beta) and it's working ok for now. On launch, the application checks to see if if the user's preference setting matches the setting of the version being launched and if not, it launches the other one. Pretty sweet, right?

It is, except for one thing in Pukka's case -- Apple Event targeting. Besides being launched normally, Pukka can be launched by a number of external forces, including:

  • AppleScripts that interact with Pukka
  • Posted information from RSS readers like NetNewsWire using its author's External Weblog Editor Interface
  • Pukka's bookmarklet, which actually uses a custom pukka:// protocol to pass information
  • Opening http:// and https:// URLs with Pukka like you would with an alternate web browser
  • Opening a supported file, such as a .webloc on the desktop, a Pukka license file, or one of the Spotlight files that Pukka generates for easy access to your bookmarks via system searching

On launch, not only do I have to figure out if the right version is running, but if not, I have to pass whatever information actually launched the application to a new process. I've actually managed to accomplish this for everything but AppleScript, but it's still non-ideal. It comes down to the fact that it's just generally bad practice to have more than one copy of the same application on the same hard drive because Mac OS X's Launch Services can get confused as to which one it should be targeting.

On top of that, since Pukka uses Sparkle for auto-updating, some issues needed to be resolved in order to update the outer, docked application and not the internal, dockless one, even if the internal one is the one running the update. Overwhelmed yet?

Now what?

So right now, I'm at a loss as to how to proceed. Apple doesn't provide a tried-and-true way to let the user toggle an application's dock mode and although many applications implement this, it seems to me that no way is fool-proof nor future-proof. The last thing I'd want is to release the feature but have to revoke it later from paying customers because it's untenable.

Cocoa developers, anything obvious that I'm missing? Have you tackled these challenges? Are you thinking about adding the same feature to your application?

Ironcoded!

Last week, I finally got a chance to participate in an Ironcoder contest and I took second place! I've never been able to find the time during the previous, weekend-long contests, but since Ironcoder VII was nine days long, I managed to squeeze some time in during the week and put together an entry. Read on for some more info.

First off, a caveat: Ironcoder is a programming contest, by programmers and for programmers, so don't expect anything particularly useful to come out of it (nor my entry). Entrants are writing to show off programming chops under pressure.

The contest theme was "Retro" and the preferred programming toolset was Core Animation. I diverged a tad (which is allowed) and instead used Quartz Composer, a visual programming language which was introduced on Tiger, created my animations there, and wrapped it in Cocoa to do the normal things that applications do.

I described my entry, called "Pop Rock", in the README file thusly:

Pop Rock takes the Ironcoder theme of Retro and the API of Core Animation and combines them as a retro rock concert app launcher. As each app is launched, it is a featured performer on stage, playing a guitar riff in front of the rest of your running apps. The more apps you are running at the time, the more popular the launched app and the better the crowd reaction.

The idea for Pop Rock just kind of popped into my head after about a day or two of latent thinking and once I started, I couldn't stop (as my wife can attest). The pressure was fun! Also, I mentioned it in the project notes, but again I just want to give a shout out to fellow Mac indie Mike Zornek of Clickable Bliss for his MegaManEffect, which I adore and which gave me the idea for an app launcher style of project.

I originally had the idea to use iusethis to fetch app popularity ratings, but this proved to be too slow to be useful at app launch time, so I fell back to a basic count of the number of other applications running, which was much quicker.

Since the app was built on Quartz Composer and not on Core Animation, it runs on Tiger too. I've compiled a version for both Tiger and Leopard (though I haven't had a chance to test it on Tiger yet).


Pop Rock screenshot thumbnail

Pop Rock (click for larger screenshot)

Download (7.42MB) | Source Code


You can read a bit more about the contest results over at Ars Technica or on the Ironcoder blog. Congratulations as well to Geoff Pado of Elgebar Studios for his winning entry, Etcher, a really great Etch A Sketch tribute!

Syndicate content