Living the Life -- Dave Battonhttp://www.mere-mortal-software.com/blog/Dave Batton's musings on Macintosh software development.en-usFri, 06 Jun 2008 20:19:31 -0400Fri, 06 Jun 2008 20:19:31 -0400http://www.mere-mortal-software.com/blog/blog.rssReleased!<p><a href="http://www.mere-mortal-software.com/inspireme/"><img src="blogimages/2008/06/06/inspiremeicon.png" class="blogimgright" align="right" width="104" height="92"></a>It’s hard to believe, but It’s been well over three years since I took Aaron Hillegass’s <a href="http://www.bignerdranch.com/classes/cocoa.shtml">Cocoa Bootcamp</a>. You’d think I’d have more to show for it. Of course, I haven’t been doing just Cocoa programing since then. I’ve still been doing a lot of 4D development to pay the bills. But I have picked up a few Cocoa programming gigs too, which have been a lot of fun.<br /> <br /> Although the Bootcamp was a great head start, I learn new computer languages best by just trying to get something tangible accomplished. So right after the class I decided I’d write a very simple little Mac application that I could eventually give away or sell inexpensively.<br /> <br /> In the past, I’ve always enjoyed those programs that would display an interesting quotation as the computer started up. But nowadays, you just don’t restart your computer often enough to enjoy these types of programs. So I decided as my first project I’d write a simple database for storing text phrases that could also display these phrases in an overlay window throughout the day.<br /> <br /> Of course, I had too many ideas to keep it that simple. Besides the overlay window, I added a transparent panel, and a window that stays on the desktop, behind all other windows. I even designed it to display quotes using <a href="http://growl.info/">Growl</a>, if it was available.<br /> <br /> Then I realized not many people would use it unless it was really easy to load up with a bunch of quotes. So I added a services menu item to grab text from the frontmost application. But that still wasn’t going to be enough. Being a big iTunes Store fan, I decided to integrate a website into the application where users could download quotes. For free.<br /> <br /> Finally, that project is now ready to show off. Today, I’m proud to announce the release of <a href="http://www.mere-mortal-software.com/inspireme/">Inspire Me</a> 1.0.<br /> <br /> And yes, I decided I had put enough work into this to charge a small amount for it. It’s introductory priced at $12.95.</p>Fri, 6 June 2008 06:00:00 GMTThe Registration User Interfacehttp://www.mere-mortal-software.com/blog/details.php?d=2008-06-06<p>Now that I know <a href="/details.php?d=2008-05-07">what I want my registration numbers</a> to look like, I want to design the application’s user interface for the registration process.<br /> <br /> Like most shareware applications, I want to offer a full working version of the program when it’s first downloaded. This will give users a chance to play with all of the features to determine if they want to purchase the program. Of course, if the program remains fully functional then there’s little incentive for them to purchase it, so after some number of days I want the program to either stop working, or run with some reduced functionality.<br /> <br /> <br><br><span class="subtitle">The Demo Window</span><br /> <br /> When my application launches, I want to inform the user that there’s a trial period involved, and warn them about how many days remain in the trial. From this screen they should be able to go to the purchase page on my website, enter a registration code if they’ve purchased a license, or just dismiss the dialog and use the program.<br /> <br /> So I whipped up this dialog in Interface Builder:<br /> <div align="center"><img src="blogimages/2008/05/17/DemoWindow.jpg" width="542" height="353"></div><br /> <br /> Since I want this to be a generic solution that I can easily use in multiple projects, everything here is generic and will be set at runtime to application specific values. For example, the icon will be replaced with the application’s icon, the CFBundleName and CFBundleVersion text fields will actually display the application’s name and version number from the application’s info.plist file. And the “xx” in the text will be replaced with the number of trial days allowed and remaining.<br /> <br /> <br><br><span class="subtitle">The Hidden File</span><br /> <br /> To keep track of the number of trial days remaining, I’ll need to store the trial start date somewhere. I could do this quite easily in the user’s preferences file. But if the user wants to restart the trial period, the first thing they’re probably going to do is to look in the application’s preferences file to see if that’s where the trial start date is stored. If it is, they could edit the date or just toss out the preferences.<br /> <br /> To make resetting the start date just slightly more difficult, I’ve decided to store it in a separate hidden plist file on the system. I can hide it either by actually making the file invisible, or by just giving it a deceptive file name that will blend in with other system file names. Or I can do both. Now the user has to find this hidden file to restart the trial period.<br /> <br /> I could get really fancy and store the start date in both the user’s preferences file and a hidden file, or in multiple hidden files on the system, then compare the two to make sure they match. Most users wouldn’t be able to figure out that they need to delete both files simultaneously to restart the demo. But <a href="/details.php?d=2008-03-10">as I stated earlier</a>, I’m really just trying to keep the honest people honest. So I’m going for simplicity instead.<br /> <br /> <br><br><span class="subtitle">The Registration Dialog</span><br /> <br /> Back to the dialog, if the Register button is clicked I’ll need another dialog where the user’s name and registration code can be entered:<br /> <div align="center"><img src="blogimages/2008/05/17/RegWindow.jpg" width="431" height="271"></div><br /> <br /> When this information is entered, I’ll run it through my validation routine to make sure the registration code is valid for the user name. If it is, then I need to store the user name and registration code so I can automatically verify it again the next time the program is launched. Once again, I could store these values in the user preferences file. Browsing through the preference files on my system, it’s obvious that many applications do this. But since I’ve already created another file for the trial start date, I might as well use that same hidden file. This will allow the user to throw out the preferences file without unregistering the program, and prevent other users on the machine from snagging a copy of the registration information if they happen to notice it in the application’s preferences file.<br /> <br /> <br><br><span class="subtitle">The Software License Window</span><br /> <br /> There’s one last thing I wan to handle while I’m here. I want to display the application’s software license the first time the program is launched.<br /> <div align="center"><a href="blogimages/2008/05/17/LicenseWindow.jpg" rel="lightbox[1]" title="The Software License Window"><img src="blogimages/2008/05/17/LicenseWindow_.jpg" width="500" height="340"></a></div><br /> <br /> The user will need to click the Accept button to use the software. If they instead click Decline, the program will just quit. But if they click Accept, I want to store a Boolean value so I know I don’t need to display the license agreement the next time the program launches. Again, the hidden file is a good place to do this.<br /> <br /> </p>Sat, 17 May 2008 06:00:00 GMTGenerating Unique Registration Numbershttp://www.mere-mortal-software.com/blog/details.php?d=2008-05-17<p><img src="blogimages/2008/05/07/registrationwindow.jpg" class="blogimgright" align="right" width="191" height="120">So before I can write any user registration routines, I need to figure out a way to generate a unique registration number for each user.<br /> <br /> Kenneth Ballenegger recently <a href="http://www.seoxys.com/registration-schemes-serial-numers/trackback/">blogged</a> about various ways to generate registration numbers. My technique is similar. This isn’t rocket science.<br /> <br /> My goal is to generate a number that the user can read off of a piece of paper and type into a dialog box. If you’ve ever typed in a registration number, you may have noticed that one of the biggest problems is telling the difference between the uppercase letter i and the lowercase letter L. Or between O and 0.<br /> <br /> I want the registration number tied to the user’s name. And I want to be able to use the same Objective-C classes for multiple products, so I’ll need to include a unique product specifier into the number so the user can’t purchase one product and use his registration number with a different product. I’ll keep this string a secret, and it will be the <a href="http://en.wikipedia.org/wiki/Salt_%28cryptography%29">salt</a> described in Kenneth’s post.<br /> <br /> Finally, although it’s not a feature I need now, I wan want be able to enable additional functionality through the registration number. For example, I might want to let the program know it’s a 5-user license, or that the user has paid for the Full Screen Mode option.<sup><a href="#fn1">[1]</a></sup><br /> <br /> So I decided that an easy solution is to convert a combination of a secret product-specific identifier, the user’s name, and any extra licensing info into a string. Then I’ll get the <a href="http://en.wikipedia.org/wiki/Md5">MD5</a> hash representation of the string. An MD5 is expressed as a 32-character string of hexadecimal numbers. I want shorter registration numbers, so I’ll truncate the MD5 to just 16 characters, and toss in some dashes for readability. Then I’ll append the license info at the end of the registration number so it’s available at runtime. Shazam! A registration number that meets my needs.<br /> <br /> An MD5 value works very well for a registration number since it consists only of numbers and the letters A through F (hexadecimal values). Unlike registration numbers that use the letters A-Z, hexadecimal values do not include the letters I, L, or O, so there’s a smaller chance of confusing these letters with the numbers 1 and 0.<br /> <br /> Here’s the plan...<br /> <br /> <span class="subtitle">The Secret Key</span><br /> <br /> First, we need a secret key to make the registration numbers for this application differ from other applications. Select the secret key as you would a password: something that can’t easily be guessed. We’ll assume that anyone wanting to crack the application has read this blog entry, so if they could guess the secret key they would just need to follow these instructions to generate their own registration numbers.<br /> <br /> It’s a good idea to make the secret key obscure, as you would a password, so that it isn’t easily spotted by just opening up the executable code in a text editor. “MySecretKey01” is easer to spot than “K-%99w4y” when you’re viewing raw binary code.<br /> <br /> Of course, a talented cracker can look watch your program at runtime in a debugger and get the secret key. But if they have that level of ability, there are lots of other ways they can circumvent the registration scheme anyway, so we’re <a href="http://www.mere-mortal-software.com/blog/details.php?d=2008-03-10">not going to worry</a> about them.<br /> <br /> If we release a new version that requires an upgrade fee, we can just change the secret key, requiring users to get a new registration number.<br /> <br /> <span class="subtitle">Input Values</span><br /> <br /> The input string from which we’ll generate the MD5 is a combination of these strings: <br /> <div id="codetxt">secret key<br><br /> user name<br><br /> license information</div><br /> <br /> These values are combined into a single string separated by two colons (“::”). There’s no special reason for the colons, other than it’s a little bit easier to read in the debugger. Then the entire string is converted to a <a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8</a> format to ensure that an identical registration number will be generated regardless of the platform. This will be important if we’re generating registration numbers from a web server running on Windows or Unix.<br /> <br /> The license information can be any string you want to make available to the program at runtime. However, it should be relatively short, since it will be appended to the registration number. If you have more than two or three characters of license info, you might want to use just 12 characters from the MD5 instead to shorten the overall length of the registration number.<br /> <br /> Finally, these strings will be concatenated and used to generate an MD5 value.<br /> <br /> <span class="subtitle">Formatting</span><br /> <br /> Rather than using the entire 32 character MD5 value, we’ll use just the first 16 characters. We don’t really need the security of using all 32 characters — 16 characters will be more than adequate for a registration number. Dashes are also added after every four characters to make the number easier to read.<br /> <br /> <span class="subtitle">Verification</span><br /> <br /> It’s not possible to take an MD5 value (especially a partial one) and convert it back to the original string used to create it. So instead, the application uses the same process as the registration generator to create a registration number, and this number is compared to the one entered into the registration dialog by the end user. If the registration numbers match, we know the registration number is valid and we store it and the user name in a hidden file.<br /> <br /> Each time the program is launched, the registration number is retrieved from the hidden file and this process is repeated to verify that the saved registration number is still valid.<br /> <br /> <span class="subtitle">An Example</span><br /> <br /> To clarify this process, we’ll use an example. Let’s say we have selected “K-%99w4y@” as our secret key, and that we want to generate a registration number for a customer named John Doe. Additionally, we want to indicate that the user has purchased a 5-user license, so we want to incorporate “5-user” into the registration number. In practice, it might be better to add just “5” to the registration number, but “5-user” works better for this example. We could use any string, as long as we understand its significance.<br /> <br /> First, we’ll concatenate the strings into one string we can pass to an MD-5 routine. We’ll separate each of the input strings with two colons (“::”). This is done just to make the string slightly easier to read during development. We combine the strings in this order:<br /> <div id="codetxt">secret key::user name::license information</div><br /> <br /> So our input string for this example looks like this:<br /> <div id="codetxt">K-%99w4y@::John Doe::5-user</div><br /> <br /> Even if no license information is added, the two-colon separator would still be included after the user name for consistency: <br /> <div id="codetxt">K-%99w4y@::John Doe::</div><br /> <br /> Note that any of the input values may already include the “::” character sequence. That’s not a problem, since we’re never going to try to parse this data into its separate elements. The colons are just added for human readability while debugging.<br /> <br /> Just to avoid problems, none of the input values should contain a carriage return or a line break.<br /> <br /> Next, before generating an MD5 value from this string, the string is converted to an ISO 8859-1 representation. Since none of our text includes any high-ASCII characters, it still looks the same after this conversion: <br /> <div id="codetxt">K-%99w4y@::John Doe::5-user</div><br /> <br /> And finally, the input string is converted to an MD5 value, and we convert that into a human-readable string. The MD5 string for our example looks like this:<br /> <div id="codetxt">e580dcdd0b5e5939a093bf13c28ff453</div><br /> <br /> Now we take the first 16 characters and toss in a few dashes. We also convert the letters to uppercase:<br /> <div id="codetxt">E580-DCDD-0B5E-5939</div><br /> <br /> Since we can’t reverse this to get the original information used to create it, we need to append the license information. Remember the user has a field to type his name into, so we have that. But having a license info field too would be confusing. So we’ll tack it onto the registration number, separated by a slash, so we can procedurally get at it at runtime. Now the user gets a registration number that looks like this:<br /> <div id="codetxt"> E580-DCDD-0B5E-5939/5-user</div><br /> <br /> This is actually nice, because it makes it clear for both the end user and developer that this is a 5-user license. We can get this value at runtime to enable additional functionality or allow additional users (if we’re actually bothering to check the network for other instances of the application). Or we can just display it in the About box.<br /> <br /> The user can’t change the "5" into another number when entering the registration number, because that would generate a different MD5 value internally, and the test to ensure that it’s a valid registration number would fail.<br /> <br /> If no license info is needed, we’ll just give the user the registration number without anything after it:<br /> <div id="codetxt">E580-DCDD-0B5E-5939</div><br /> <br /> <span class="subtitle">Implementation</span><br /> <br /> Don’t worry, I’m not a tease. I’ll post a demo project soon so you can see how I’ve implemented this.<br /> <br /> <br /> <br><br /> <i>Footnotes:</i><br /> <small><a name="fn1">1.</a> Yes, I just made that up. I don’t have any products with a full screen mode, and I don’t think I’d ever charge extra for that if I did.</small><br /> <br></p>Wed, 7 May 2008 06:00:00 GMTMy Product Registration Solutionhttp://www.mere-mortal-software.com/blog/details.php?d=2008-05-07<p>As I mentioned in my <a href="http://www.mere-mortal-software.com/blog/details.php?d=2008-02-15">previous post</a>, I’ve decided to roll my own product registration routines. I’m comfortable with this decision because my ultimate goal is to give Mac users that pay for software a reason to send me money. It’s not to prevent software pirates from using my product. I don’t think that’s a realistic goal.<br /> <br /> <blockquote><cite>Don’t worry much about piracy. If you spend more than a couple days a year worrying about it, you’re fooling yourself. </cite> - <a href="http://wilshipley.com/blog/2005/06/piracy.html">Wil Shipley</a><br /> </blockquote><br /> <br /> Whatever I do is going to be <a href="http://en.wikipedia.org/wiki/Software_cracking">crackable</a>. I know I’m not a good enough Cocoa programmer to make something unbreakable. I’m not even good enough to make it terribly difficult for them. It might take somebody ten minutes, or it might take them a day. That really doesn’t really matter to me. My goal is not to make myself feel better by trying to waste some hacker’s time. The end result would be the same anyway. If somebody wants to use my software without paying for it, they’ll find a way. I just want to put up a small fence with a “Keep Out” sign to keep the honest people honest.<br /> <br /> <blockquote><cite>There is no perfect way of protecting your application, and no matter what you do, those that want to crack your application will... </cite> - <a href="http://lipidity.com/apple/shareware-licensing-techniques/">Ankur Kothari</a></blockquote><br /> <br /> On the other hand, I do have a realistic, achievable goal (although it’s not specific to product registration). That is to write code that’s easy to maintain and reuse.<br /> <br /> Based on this goal, I’ve decided to write my registration code in Objective-C. I realize that I can make my code more obscure by writing it in C, or calling it as a macro. I can also make things more difficult for a hacker by using <a href="http://unsanity.org/archives/000101.php">misleading method names</a>. But these things make it more difficult for me to maintain.<br /> <br /> On the other hand, some things seem to make sense. For example, I do base the registration code on the customer’s name. And the date of the first launch goes into a hidden file, so deleting the preferences doesn’t reset the trial period. I might even take some time to <a href="http://www.cocoadev.com/index.pl?CocoaInsecurity">strip the symbols</a> from the final executable.<br /> <br /> I suppose I could also make it more difficult to hack by not describing in detail what I’m doing in my blog. Oh, well.<br /> <br /> In my next entry I’ll describe the algorithm I’ve created for generating registration numbers. After that, I’ll create an example project that shows the registration routines in action.<br /> <br /> Perhaps, if my new product is popular enough to be widely cracked, I’ll change my mind about how little effort I’m putting into protecting the product registration routines. I’m hoping my software will become popular enough for it to be an issue.<br /> <br /> <blockquote><cite>If your software doesn’t get cracked, then that’s probably something to worry about. It means you either spent way too much time making it uncrackable—or it wasn’t interesting enough to crack. </cite> - <a href="http://inessential.com/2004/10/27.php">Brent Simmons</a></blockquote></p>Mon, 10 March 2008 06:00:00 GMTStill Thinking About Product Registrationhttp://www.mere-mortal-software.com/blog/details.php?d=2008-03-10<p>I <a href="http://www.mere-mortal-software.com/blog/details.php?d=2007-03-31">mentioned previously</a> that I was trying to decide how to handle registration for my new shareware application.<br /> <br /> Option one was to go with either <a href="http://www.esellerate.net/">eSellerate</a> or <a href="http://www.kagi.com/">Kagi</a>.<br /> <br /> I did download the eSellerate Embedded Web Store to give it a try. Unfortunately, after a few hours of research, I gave up. The documentation is comprehensive on how to use their web site, but not how to install their framework in a Cocoa application. Instead, they offer a sample application for you to reverse engineer. I’m sure that I could have figured it out, but if they don’t even bother to document step one, then I’m not going to assume things get better once I get deeper into their product.<br /> <br /> And I’ll admit, I’m really not that excited about getting locked into a proprietary system. Especially one that starts at 10% of my gross profit. Before I downloaded eSellerate’s product I decided I liked it better than the Kagi options. Now that I’ve given up on eSellerate, I don’t see the value in spending much time with my second choice.<br /> <br /> Option two was the <a href="http://www.aquaticmac.com/">AquaticPrime</a> framework. This looked like a much better option to me. I get full control of the interface, and they don’t want 10%. In fact, they don’t want anything. Really attractive.<br /> <br /> Unfortunately, I think distributing license <em>files</em> is much more complex and error-prone than is necessary for an inexpensive shareware application. I’d much rather just display a dialog asking the user to enter their name and an activation code.<br /> <br /> So I’ve decided to go with option three: I’ll be rolling my own product registration routines. I’ve done it before for my <a href="http://www.4d.com/">4D</a> projects, so I’ve already got the technique worked out. I’ve also already got the back-end (in-house database and PHP/MySQL web site) set up to support it. Now I just need to implement the Cocoa version.</p>Fri, 15 February 2008 06:00:00 GMTThe Leopard Dilemmahttp://www.mere-mortal-software.com/blog/details.php?d=2008-02-15<p><img src="blogimages/2007/01/27/leoparddisc.jpg" class="blogimgright" align="right" width="91" height="91">I finally installed the <a href="http://www.macgeekblog.com/blog/archive/2007/06/12/wwdc-07-leopard-developer-preview.html">Leopard Developer Preview</a> I picked up at WWDC. It’s on an external drive—I didn’t replace my primary Tiger OS. I’m not that much of a thrill-seeker.<br /> <br /> The Cocoa product I’m working on isn’t going to be ready for a couple of months yet, so I’ve decided I’ll make it a Leopard-only product and use all of the cool new Leopard technologies.<br /> <br /> I’ve heard some rumors that Leopard isn’t solid yet. I don’t expect it to be, since it is a beta release. My problem is that I’m still pretty new to Cocoa, and I run into problems all the time that I eventually track down to my own programming mistakes. Working on Tiger, I know that if something doesn’t work, I screwed up. But if I upgrade my development environment to Leopard, I won’t know if a problem is due to my error, or a bug in Leopard.<br /> <br /> Granted, almost all of the problems will continue to be with my code. But I won’t know this for sure until I get the problem fixed. If I can’t get it fixed, I still won’t know if the problem is with my code or Leopard. How many hours should I spend trying to track down a bug that might not be mine?<br /> <br /> So for now, I’m continuing to do my product development in Tiger. I think I’ll make the switch and start developing with Leopard in October.</p>Tue, 14 August 2007 06:00:00 GMTiPhone Envyhttp://www.mere-mortal-software.com/blog/details.php?d=2007-08-14<p><a href="http://www.apple.com/iphone/"><img src="blogimages/2007/08/13/iPhone.jpg" class="blogimgright" align="right" width="52" height="89"></a>There were lots of <a href="http://www.apple.com/iphone/">iPhones</a> at <a href="http://c4.rentzsch.com/1/">C4</a> this past weekend. I’d guess that 70% of the developers attending the conference brought an iPhone. Not me.<br /> <br /> I want one. A lot. But I don’t use a cell phone that much, and the idea of having to pay $60/month for service, in addition to the $600 to get the phone, really puts me off. Once you add taxes, that’s around $1,400 for the first year. Not cheap. I can buy a lot of other cool toys with that money.<br /> <br /> I do have a cell phone now, but it’s unlocked, so I purchased a prepaid card for it. This way I’m paying closer to $25/month (including taxes). So to be fair, the real first-year cost of an iPhone to me would be about $1,100. Still not chump-change.<br /> <br /> However, I can’t claim to have the best resolve when it comes to spending money on cool toys. I’m sure that if I were to go to an Apple Store and play with an iPhone, I’d leave with one. So I haven’t been to an Apple Store since the iPhone was released. And although I was surrounded by iPhones at C4, I never asked anyone if I could try theirs. That would be too risky.<br /> <br /> I’d love to write an application for the iPhone. You can hack something now, though I wouldn’t want to try to market an iPhone hack. But as soon as Apple delivers an iPhone SDK, I’m sure I’ll get an iPhone.</p>Mon, 13 August 2007 06:00:00 GMTC4 - Day 3http://www.mere-mortal-software.com/blog/details.php?d=2007-08-13<p>Today was the last day of the C4 conference. After an 11 AM breakfast, Cable Sasser of <a href="http://www.panic.com/">Panic</a> talked about everything from the early days of the company to the design of <a href="http://www.panic.com/coda/">Coda</a>, their latest <a href="http://developer.apple.com/wwdc/ada/index.html">award winning</a> software release.<br /> <br /> This was certainly my favorite session of the conference. Technical info is all well and good, but I really love hearing about what happens behind the scenes at sucessful Mac companies. For example, I learned that Panic was launched by Cabel and Steven Frank. <a href="http://www.panic.com/transmit/">Transmit</a> wasn't their first product, it was just the first one to see the light of day. In fact, it sounds like they've abandoned as many products as they've shipped. The company now has nine people.<br /> <br /> Cabel showed how he used Photoshop to design Coda. Basically every aspect of the application was created first in Photoshop, in complete detail. Panic has already made Coda completely resolution independent. And Cabel even showed us a Photoshop technique to help us create our own resolution independant images.<br /> <br /> Next came the <a href="http://rentzsch.com/c4/ironCoderLive">Iron Coder Live</a> demonstrations. The theme this year was the iPhone, and there were lots of cool hacks. It was great to see that it is possible to write code for the iPhone, even if Apple isn't providing the tools.<br /> <br /> My favorite, and the winner, was the “Squidge” entry by Ken and Glen Aspeslagh. I was able to chat in-depth with Ken and Glen, the founders of Ecamm Network, earlier during the conference. They make <a href="http://www.ecamm.com/mac/dockstar/">DockStar</a>, one of my favorite Mac utilities. Anyway, they created a way to use the iPhone as a video chat device. They even have a hardware accessory that allows you to re-aim the camera on the back so the user can see and be seen while chatting. Very cool. Check out their <a href="http://macdaddyworld.com/?p=38">web site</a> for details.<br /> <br /> The conference was over. I thanked Wolf for the great opportunity, and told him the conference was well worth the money, and that I'd be back next year. Then I hailed a taxi, jumped on the train, boarded the plane, and hopped on the bus for home.<br /> </p>Sun, 12 August 2007 06:00:00 GMTC4 - Day 2http://www.mere-mortal-software.com/blog/details.php?d=2007-08-12<p>Today was day two of the <a href="http://c4.rentzsch.com/1/">C4</a> conference. I really like the format of this conference. Unlike most conferences I go to with multiple tracks, we’ve got just one track here, so I don’t always wonder if I’m missing something in the next room.<br /> <br /> The first presentation was by Daniel Jalkut of <a href="http://www.red-sweater.com/">Red Sweater Software</a>. He spoke about software acquisition, having just recently acquired both MarsEdit and Black Ink. Daniel’s a really interesting and down-to-earth guy. I’ve followed his story through his blog, chatted with him online, and had a chance to meet him in person for the first time at <a href="http://developer.apple.com/wwdc/">WWDC</a> last June. So it was thrilled to hear him speak today.<br /> <br /> For the second session, <a href="http://technosmores.blogspot.com/">Shawn Morel</a> of <a href="http://www.vmware.com/">VMWare</a> talked about virtualization on the Mac. Vinay Venkatesh was supposed to do this presentation, but apparently he was afraid of getting <a href="http://www.drunkenblog.com/drunkenblog-archives/000767.html">punched in the face</a> by <a href="http://iron.wootest.net/2005/06/drunkenbatman/">Drunkenbatman</a>.<br /> <br /> I met Shawn last night and chatted with him briefly. He’s a very good speaker, but the topic was a little too technical to me. Way over my head. It was about the history of virtualization on mainframes, ISA requirements, operating system traps, blah, blah, blah... Good time for a bathroom break.<br /> <br /> During lunch I sat at a table with, among others, <a href="http://iconfactory.com/home/staff#craig">Craig Hockenberry</a> of <a href="http://www.iconfactory.com/">IconFactory</a> and Cabel Sasser, one of the founders of <a href="http://www.panic.com/">Panic</a>. What an incredible opportunity to talk directly with some of the current movers and shakers of the Mac community. <br /> <br /> After lunch, Allen Odgaard, author of <a href="http://macromates.com/">TextMate</a>, discussed his product’s design model. The ability for other developers to extend its capabilities wasn’t just a product feature, it was an integral part of the product’s marketing plan.<br /> <br /> There was a little extra time before the next session so Wolf brought up Bobby Andersen to show off his icon creation techniques with <a href="http://www.maxon.net/pages/products/cinema4d/cinema4d_e.html">CINEMA 4D</a>. I was lucky enough to be sitting at the table with the two of them during breakfast this morning with the two of them when they came up with this last-minute plan. Bobby, a fellow Denverite, has done icons for <a href="http://www.sandvox.com/">Sandvox</a>, <a href="http://www.codepoetry.net/products/notae">Notae</a>, <a href="http://www.last.fm/">Last.FM</a>, <a href="http://www.memoryminer.com/">MemoryMinor</a>, and many more popular Mac applications. You can see his work at <a href="http://pixelimplosion.com/">The Pixel Implosion</a>.<br /> <br /> Bob Ippolito from <a href="http://mochimedia.com/">Mochi Media</a> was next with a demo of the <a href="http://www.erlang.org/">Erlang</a> language. He used it to write a very fast web server. Good stuff for some people I’m sure, but not terribly interesting to me.<br /> <br /> However, the next session was right up my alley. Tidbits publisher <a href="http://www.tidbits.com/adam/">Adam Engst</a> talked about working with the press to get exposure for a software product. He covered everything from getting mentioned in an article, to getting a full review, to getting interviewed on the evening news. This is the kind of information that I came for.<br /> <br /> Tim Burks discussed his work on <a href="http://www.rubyobjc.com/">RubyObjC</a>, and then his new project, Nu. It’s a version of <a href="http://en.wikipedia.org/wiki/Lisp">Lisp</a> “written on, with, and for Objective-C.” Okay, cool. Nice demos. But it’s not for me, thanks.<br /> <br /> The last session of the evening was a discussion panel of all of the C4 presenters, moderated by <a href="http://iron.wootest.net/2005/06/drunkenbatman/">Drunkenbatman</a>. He started with a long-winded rant about the questionable sales techniques of <a href="http://www.pzizz.com/">Pzizz</a>, followed by some reasonable responses from the presenters and some interesting input from some of the attendees in the audience. This included a short discussion about the validity of <a href="http://en.wikipedia.org/wiki/Neuro-linguistic_programming">neuro-linguistic programming</a> and the ability of a developer to give <a href="http://en.wikipedia.org/wiki/Wil_shipley">Wil Shipley</a> a hand-job.<br /> <br /> After asking the panelists another question, Drunkenbatman tried to provoke a response with the statement “Black people don’t use Macs.” It sounded like an inappropriate statement to most of us in the audience (and on the panel I think). It certainly won’t be remembered as one of the high points of this conference.<br /> <br /> For dinner we headed to <a href="http://www.associatedcontent.com/article/227074/ginos_east_chicago_style_pizza_legendary.html">Gino’s East</a> for pizza and beer (a staple for most developer’s I assume). I took the opportunity to grab a free seat near Dan Moren of <a href="http://www.macuser.com/">MacUser.com</a> and <a href="http://daringfireball.net/">Daring Fireball</a>’s John Gruber. I just sat quietly and listened to them discuss the state of Mac journalism. What an incredibly cool opportunity for a Mac geek like me.<br /> <br /> Finally, back at the pool-side party at the hotel, I chatted with Sanford Selznik, author of <a href="http://www.selznick.com/products/passwordwallet/">PasswordWallet</a>. Dispite the fact that I publish a competing product, he was quick to offer to help me out when I told him I was a little frustrated with trying to figure out how to integrate the <a href="http://www.esellerate.net/">eSellerate</a> engine into my new product. Next, I had a great conversation about being self-employed and still having a life Mac with Roustem Karimov, one of the authors of <a href="http://1passwd.com/">1Passwd</a>.<br /> <br /> I’ve had an opportunity to meet with so many authors of the products I use (or at least really respect) this weekend. This conference has been an incredible experience so far. There’s still one day to go, but I’ve already got my money’s worth.<br /> </p>Sat, 11 August 2007 06:00:00 GMTC4 - Day 1http://www.mere-mortal-software.com/blog/details.php?d=2007-08-11<p><a href="http://c4.rentzsch.com/1/"><img src="blogimages/2007/05/25/C4.png" class="blogimgright" align="right" width="128" height="98"></a>Today I caught a bus, took a plane, then a train, then grabbed a taxi to get to the <a href="http://c4.rentzsch.com/1/">C4 conference</a> in Chicago, Illinois. This conference, hosted by Jonathan “Wolf” Rentzsch of <a href="http://redshed.net">Red Shed Software</a>, is for independent developers like myself that are interesteded in trying to make a living by writing and selling Macintosh software.<br /> <br /> After picking up my badge, a C4 t-shirt, and a very cool set of C4 <a href="http://www.flickr.com/photos/ldandersen/1078554263/">dog tags</a> personalized with my name and company name, I joined about 150 like-minded Mac developers for dinner at the City Centre Hotel. After dinner Wolf spoke about the meaning of “indie” as it applies to developers. It doesn’t have to be just a single developer -- it can be a company of hundreds of people. But it does have to involve a group of developers without the big-company mindset. <br /> <br /> Next, <a href="http://www.wilshipley.com/blog/">Wil Shipley</a>, formerly of <a href="http://www.omnigroup.com/">The Omni Group</a>, and now the creator of <a href="http://www.delicious-monster.com/">Delicious Library</a>, spoke about “hype.” I love listening to Wil speak. He’s easily the one of the best presenters in the Mac software community. He doesn’t pull any punches as he describes his dealings with Apple, big retailers, and his own customers. I had to go pee halfway through his presentation, but stayed in my seat because I wasn’t willing to chance missing any of his sarcastic humor. In addition to being fun, his presentation is full of valuable content based on his experience making loads of money selling Macintosh software.<br /> <br /> Afterwards we headed for the hotel’s rooftop pool for drinks and conversations about Mac software development. Then a large group of us continued the party at a nearby pub.<br /> <br /> I’m very much looking forward to tomorrow’s presentations. Fortunately breakfast is being served at 10 AM. Perfect for a group of programmers.<br /> </p>Fri, 10 August 2007 06:00:00 GMT