<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SteveStreeting.com &#187; OS X</title>
	<atom:link href="http://www.stevestreeting.com/tag/os-x/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.stevestreeting.com</link>
	<description>Man bites Ogre</description>
	<lastBuildDate>Sat, 24 Dec 2011 13:08:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.4</generator>
		<item>
		<title>Escalating privileges on Mac OS X securely, and without using deprecated methods</title>
		<link>http://www.stevestreeting.com/2011/11/25/escalating-privileges-on-mac-os-x-securely-and-without-using-deprecated-methods/</link>
		<comments>http://www.stevestreeting.com/2011/11/25/escalating-privileges-on-mac-os-x-securely-and-without-using-deprecated-methods/#comments</comments>
		<pubDate>Fri, 25 Nov 2011 17:04:09 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[AuthorizationExecuteWithPrivileges]]></category>
		<category><![CDATA[SMJobBless]]></category>

		<guid isPermaLink="false">http://www.stevestreeting.com/?p=3059</guid>
		<description><![CDATA[This week I implemented a much-requested feature in SourceTree for the upcoming 1.3 release (beta 1 went out on Monday, this will make it into beta 2) &#8211; a command-line tool so you can quickly pull up SourceTree for the repository you&#8217;re in from a terminal. Writing the command-line tool was trivial, but when I [...]]]></description>
			<content:encoded><![CDATA[<p>This week I implemented a much-requested feature in <a href="http://www.sourcetreeapp.com" target="_blank">SourceTree</a> for the upcoming 1.3 release (<a href="http://www.sourcetreeapp.com/2011/11/21/sourcetree-1-3-public-beta/" target="_blank">beta 1</a> went out on Monday, this will make it into beta 2) &#8211; a command-line tool so you can quickly pull up SourceTree for the repository you&#8217;re in from a terminal. Writing the command-line tool was trivial, but when I came to implement the menu item which would install it in /usr/local/bin, which inherently needs privilege escalation, it turned out to be a lot more complicated than I expected.</p>
<p>How so? Surely lots of people have done this sort of thing before? Well, that&#8217;s true, they have &#8211; but the problem is that just about all of the existing examples of this use the <a href="http://developer.apple.com/library/mac/#documentation/Security/Reference/authorization_ref/Reference/reference.html" target="_blank">Authorization Services</a> API call <a href="http://developer.apple.com/library/mac/#documentation/Security/Reference/authorization_ref/DeprecationAppendix/AppendixADeprecatedAPI.html#//apple_ref/doc/uid/TP30000826-AppendixA" target="_blank">AuthorizationExecuteWithPrivileges</a> &#8211; and this method is <strong>deprecated</strong> in OS X 10.7 (Lion). Now, of course that doesn&#8217;t stop you using it (yet), provided you&#8217;re willing to turn off the warning that building against the 10.7 SDK gives you, but any programmer worth his salt should take deprecation as a hint that they should be looking for another way.</p>
<p>There are basically 3 ways to escalate privileges on OS X, and only one of them is now recommended:</p>
<ol>
<li>Use a helper tool which has its setuid bit set so that it runs as root. Risky if that tool gets compromised, and the setuid bit can be lost, needing reinstatement by another privileged task.</li>
<li>Execute a command as root via <a href="http://developer.apple.com/library/mac/#documentation/Security/Reference/authorization_ref/DeprecationAppendix/AppendixADeprecatedAPI.html#//apple_ref/doc/uid/TP30000826-AppendixA" target="_blank">AuthorizationExecuteWithPrivileges</a>. As mentioned above, this is now deprecated, and again if a hacker compromises either the app or the tool being launched, bad things can happen.</li>
<li>Ask Launch Services to install a privileged helper tool via <a href="http://developer.apple.com/library/mac/#samplecode/SMJobBless/Listings/ReadMe_txt.html" target="_blank">SMJobBless</a>. This helper is subsequently run by launchd as root when invoked via a Unix socket, and can perform privileged tasks. Importantly, code signing is verified at both ends by Launch Services at install time to prevent tampering with either binary.</li>
</ol>
<p>Clearly option 3 was the way to go &#8211; the only &#8216;downside&#8217; about it is that is does require that you have the ability to sign your application and helper tool. I already have valid code signing certificates because I deploy on the App Store, so this isn&#8217;t an issue (even though this functionality won&#8217;t actually be in the App Store version of SourceTree because Apple disallow installer behaviour there, I still sign with the same certs). In fact, the fact that I know my app and helper tool can&#8217;t be interfered with without the code signatures becoming invalid is very reassuring. Given that it only costs $99 per year to be on the Mac Developer Programme which allows you to get certificates (even if you don&#8217;t deploy on the App Store), it&#8217;s something serious developers should consider strongly.</p>
<p>SMJobBless is ideally suited to installing daemons, but it&#8217;s perfectly acceptable to install tools which run simple one-off tasks too. When setting up the plist for the helper, you specify that it is &#8216;OnDemand&#8217;, with no &#8216;KeepAlive&#8217; which means it&#8217;s not started by Launch Services at startup, only when a Unix socket is opened, and shuts down very quickly if there&#8217;s no activity. Unfortunately the <a href="http://developer.apple.com/library/mac/#samplecode/SMJobBless/Listings/ReadMe_txt.html" target="_blank">SMJobBless example</a> doesn&#8217;t do anything except to show you how to install a tool, it doesn&#8217;t tell you how to implement that tool to do anything useful, or how to call it from your main application.</p>
<p>To see how to do that, you need to refer to <a href="http://developer.apple.com/library/mac/#samplecode/BetterAuthorizationSample/Introduction/Intro.html" target="_blank">BetterAuthorizationSample </a>, which includes a re-usable library for this. Ironically though, this example uses AuthorizationExecuteWithPrivileges to install its helper (this example pre-dated its deprecation in favour of SMJobBless). So you have to remove all the code associated with installation; you won&#8217;t need it anyway since SMJobBless does that function better. You keep the rest which gives you a framework for implementing and calling the helper. So here&#8217;s what I did:</p>
<ol>
<li>Implement the installation of a privileged helper, based directly on the SMJobBless example. I needed to change the bundle IDs and the certificate CN&#8217;s to match my setup of course.</li>
<li>Extend the plist files from SMJobBless to register the helper with a socket. This was basically a case of copying the settings from the BetterAuthorizationSample plists, which already does this.</li>
<li>Bring in BetterAuthorizationSampleLib.c/.h to assist with implementation of the helper, and the code for calling it in the app, but remove everything in the &#8216;Installation&#8217; section. This eliminates all the references to AuthorizationExecuteWithPrivileges &#8211; we&#8217;re doing the install with SMJobBless so don&#8217;t need that.</li>
<li>Follow the BetterAuthorizationSample for the implementation of the helper, and the bit in the application where you call the helper to perform privileged operations.</li>
</ol>
<p>So in my case, the following happens when you click &#8216;Install Command Line Tool&#8217; in SourceTree:</p>
<ol>
<li>A privileged helper is installed in Launch Services using SMJobBless. OS X checks the code signatures on both ends to ensure that the helper and the application asking to install it are valid (must be signed with my cert, and that cert must be issued by Apple).</li>
<li>A connection is opened to the privileged helper over a socket which causes launchd to start it up</li>
<li>I ask the helper via the BetterAuthorizationSampleLib to install the command-line tool in /usr/local/bin. As an additional check, the helper validates via &#8216;codesign -v  -R=&#8221;conditions&#8221;&#8216; that this tool is code signed with my cert (again, must be issued by Apple) &#8211; this is to prevent anyone else sniffing out this socket and trying to use it to install other things. If that passes, it installs the command.</li>
</ol>
<p>This is quite a long-winded process compared to just calling a &#8216;cp&#8217; command via AuthorizationExecuteWithPrivileges, but it&#8217;s also a lot more secure, since a malicious person can&#8217;t alter any of the moving parts without invalidating the code signatures. You&#8217;re also insulated from future changes when inevitably AuthorizationExecuteWithPrivileges is removed entirely.</p>
<p>I apologise for the lack of a pre-packaged example here &#8211; I haven&#8217;t had time to extract one from my own implementation yet. However, as described above if you start with the <a href="http://developer.apple.com/library/mac/#samplecode/SMJobBless/Listings/ReadMe_txt.html" target="_blank">SMJobBless</a> sample and add-in the <a href="http://developer.apple.com/library/mac/#samplecode/BetterAuthorizationSample/Introduction/Intro.html" target="_blank">BetterAuthorizationSample</a>, removing from the latter everything associated with installation, you&#8217;re basically there. If I get chance later I&#8217;ll post a shrink-wrapped example.</p>
<p>I hope that helps someone &#8211; I found there to be little information on this subject that was up-to-date, and lots of older information that was misleading so maybe this will save someone some time. Ideally, I hope Apple will combine the SMJobBless and BetterAuthorizationSample some time to produce a 10.7-compliant official example.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevestreeting.com/2011/11/25/escalating-privileges-on-mac-os-x-securely-and-without-using-deprecated-methods/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SSSelectableToolbar</title>
		<link>http://www.stevestreeting.com/2011/06/20/ssselectabletoolbar/</link>
		<comments>http://www.stevestreeting.com/2011/06/20/ssselectabletoolbar/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 13:32:07 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[bwtoolkit]]></category>
		<category><![CDATA[preference pane]]></category>
		<category><![CDATA[ssselectabletoolbar]]></category>

		<guid isPermaLink="false">http://www.stevestreeting.com/?p=3002</guid>
		<description><![CDATA[A common requirement in any Cocoa application is a preference pane style window where each toolbar item switches to a different view in the main window, resizing as necessary. I&#8217;ve used BWToolkit to do this in the past, which provides BWSelectableToolbar. However, there are a few issues with using BWToolkit: If you want to deploy [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-3003" title="SelectableToolbarDemo001" src="http://www.stevestreeting.com/wp-content/uploads/2011/06/SelectableToolbarDemo001.png" alt="" width="239" height="254" align="right" />A common requirement in any Cocoa application is a preference pane style window where each toolbar item switches to a different view in the main window, resizing as necessary. I&#8217;ve used <a href="http://brandonwalkin.com/bwtoolkit/" target="_blank">BWToolkit</a> to do this in the past, which provides BWSelectableToolbar. However, there are a few issues with using BWToolkit:</p>
<ol>
<li>If you want to deploy on the Mac App Store, You have to customise it to remove all uses of private methods, since those are banned on the App Store.</li>
<li>It sometimes crashes Interface Builder &#8211; usually not fatally but it can get awkward</li>
<li>Sometimes it gets the window height slightly too tall when switching panes &#8211; I&#8217;ve patched it to try to cope with this but it still happens sometimes</li>
<li>It relies on using IB plugins. XCode 4 does not support IB plugins anymore &#8211; although you can still build the code, you can&#8217;t edit the nibs anymore</li>
</ol>
<p>I&#8217;ve just been coping with 1, 2 &amp; 3 so far, but 4 was the killer which made me come up with my own alternative: <a href="https://bitbucket.org/sinbad/ssselectabletoolbar" target="_blank">SSSelectableToolbar</a>.</p>
<p>With SSSelectableToolbar, you can still do the preference pane setup entirely within Interface Builder, but it doesn&#8217;t require any plugins. There are a couple of extra steps required because of this, but they&#8217;re not onerous and still better than setting it all up in code.</p>
<p>The license is permissive MIT, usage is in the README, and there&#8217;s an example demo to show how it works. I hope it&#8217;s useful to someone else too.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevestreeting.com/2011/06/20/ssselectabletoolbar/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SourceTree, your Mac Git &amp; Mercurial GUI, is 40% off this week</title>
		<link>http://www.stevestreeting.com/2011/05/19/sourcetree-your-mac-git-mercurial-gui-is-40-off-this-week/</link>
		<comments>http://www.stevestreeting.com/2011/05/19/sourcetree-your-mac-git-mercurial-gui-is-40-off-this-week/#comments</comments>
		<pubDate>Thu, 19 May 2011 17:13:40 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[1.2]]></category>
		<category><![CDATA[releases]]></category>
		<category><![CDATA[sourcetree]]></category>

		<guid isPermaLink="false">http://www.stevestreeting.com/?p=2982</guid>
		<description><![CDATA[Since I&#8217;m trying to spread this news as far and wide as I can, I might as well say it here too Since the approval light just went green on the Mac App Store, I&#8217;m happy to announce the launch of SourceTree 1.2! In celebration, I&#8217;m having a crazy-bonkers 40% off sale just for one week, so [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-2846" title="SourceTree icon" src="http://www.stevestreeting.com/wp-content/uploads/2010/10/icon.png" alt="" width="154" height="154" /></p>
<p>Since I&#8217;m trying to spread this news as far and wide as I can, I might as well say it here too <img src='http://www.stevestreeting.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Since the approval light just went green on the Mac App Store, I&#8217;m happy to announce the launch of <a href="http://www.sourcetreeapp.com" target="_blank">SourceTree</a> 1.2! In celebration, I&#8217;m having a crazy-bonkers <strong>40% off sale</strong> just for one week, so get it while it&#8217;s hot!</p>
<p>There&#8217;s <em>loads</em> of things that are new or improved in this release, but here are the headlines:</p>
<ul>
<li><strong>Support for GitHub, Bitbucket and Kiln APIs</strong>, so you can see your hosted projects inside SourceTree, clone from them, link them as remotes, and even create new projects if you want.</li>
<li><strong>Streamlined and polished user interface</strong> &#8211; I specifically dedicated a lot of extra time in this release on making SourceTree easier on the eyes, and to streamline the layout and workflows better.</li>
<li><strong>Performance -</strong> I thought SourceTree was already pretty fast, but I managed to find quite a few more places to trim the fat, and also parallelised more activities to make things feel more responsive. Everything feels snappier, and complex repositories benefit especially.</li>
<li><strong>New Sidebar </strong>- I had previously resisted the need to emulate iTunes here, but once I had implemented it, I had to admit that I was wrong, and in fact this worked great. Provides lots of shortcuts to navigating and operating on branches, tags and remotes.</li>
<li><strong>Stashing and Shelving </strong>- oft requested, now delivered <img src='http://www.stevestreeting.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
<li><strong>Customise Git and Mercurial</strong> &#8211; you can now use your system Git / Mercurial instead of SourceTree&#8217;s standard versions (which have been updated), and enable additional Mercurial extensions (at your own risk).</li>
<li><strong>French and Japanese translations</strong> &#8211; local versions for our friends in far away (and not so far away) places, likely to be more to come in future. Big thanks to tuan_kuranes and mzch for their help with these two!</li>
<li><strong>And the rest</strong> &#8211; just lots of little refinements too numerous to list. Examples: copying text from the diff panel, &#8216;git commit &#8211;amend&#8217; support, close branches in Mercurial, switch tracking branches in Git</li>
</ul>
<p>It&#8217;s quite a big update &#8211; one user remarked to me that they&#8217;d normally expect developers to charge an upgrade fee for something like this, but like all other SourceTree updates this is free to existing customers. I have no plans for any paid upgrades for some time yet, I just want to keep making SourceTree better, and hope that more people come onboard. Maybe it&#8217;s my open source background, but I like to keep iterating and continually improving things, based on what I want to do (I&#8217;m a daily SourceTree user myself), and on what people tell me they&#8217;d like to see. SourceTree 1.2 certainly won&#8217;t be the last update by far <img src='http://www.stevestreeting.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>When I look back 6 months at SourceTree 1.0, it&#8217;s incredible how much better it is as a product now, both visually and functionally. I&#8217;ve learned a ton of things while I&#8217;ve been developing it, and I continue to learn more all the time, and I can&#8217;t think of anything I&#8217;d rather be doing right now. Also, my wife Marie re-designed many of the icons for 1.2 (and I think you&#8217;ll agree they&#8217;re a lot nicer) &#8211; that was fun to do as a joint project, even if I am a picky &#8216;customer&#8217; <img src='http://www.stevestreeting.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>I hope you enjoy the new release!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevestreeting.com/2011/05/19/sourcetree-your-mac-git-mercurial-gui-is-40-off-this-week/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Mac user base by country: my figures so far</title>
		<link>http://www.stevestreeting.com/2011/04/07/mac-user-base-by-country-my-figures-so-far/</link>
		<comments>http://www.stevestreeting.com/2011/04/07/mac-user-base-by-country-my-figures-so-far/#comments</comments>
		<pubDate>Thu, 07 Apr 2011 12:09:29 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[sales]]></category>
		<category><![CDATA[sourcetree]]></category>

		<guid isPermaLink="false">http://www.stevestreeting.com/?p=2935</guid>
		<description><![CDATA[As many of you probably know, almost a year ago now I decided to take the plunge and move my primary development activities to the Mac. I taught myself Objective-C, got properly to grips with Cocoa at last, and started a new Mac OS X-specific project which would eventually become SourceTree, learning a ton along [...]]]></description>
			<content:encoded><![CDATA[<p>As many of you probably know, <a href="http://www.stevestreeting.com/2010/05/16/takinga-bite-of-the-apple/">almost a year ago now</a> I decided to take the plunge and move my primary development activities to the Mac. I taught myself Objective-C, got properly to grips with Cocoa at last, and started a new Mac OS X-specific project which would eventually become <a href="http://www.sourcetreeapp.com" target="_blank">SourceTree</a>, learning a ton along the way (a process which is by no means complete!).</p>
<p>Happily, things have turned out very well &#8211; SourceTree continues to sell, reassuring me that there&#8217;s enough interest out there for me to keep expanding and improving it (I&#8217;m looking forward to getting the next major release in people&#8217;s hands soon), and I&#8217;ve also been getting some Mac/<a href="http://www.ogre3d.org" target="_blank">Ogre</a>-based contract work which I&#8217;ve enjoyed a great deal. In short, my Macbook Pro and I are now pretty inseparable, Windows 7 is powered off 99% of the time, and I saved hundreds of pounds by not upgrading to Visual Studio 2010 <img src='http://www.stevestreeting.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Out of interest, I thought I&#8217;d share some of my <a href="http://www.sourcetreeapp.com" target="_blank">SourceTree</a> sales information, in terms of the country distribution. Mac use is typically associated primarily with the USA, and while that&#8217;s certainly reflected in my absolute numbers, there&#8217;s some quite interesting figures revealed when you take into account population size. SourceTree is aimed at developers of course, so all numbers reflect this audience alone (and of course those that chose to buy it) but in practice I suspect that the proportions of developers to non-developers is fairly uniform in most developed countries.</p>
<p>So, firstly the absolute distribution:</p>
<p><img class="alignnone size-full wp-image-2938" title="SourceTree_Country_Absolute" src="http://www.stevestreeting.com/wp-content/uploads/2011/04/SourceTree_Country_Absolute.png" alt="" width="611" height="400" /></p>
<p>No surprises there, the USA is the single largest source, followed by Germany and the UK (who are constantly scrapping over second place!). To me though, Switzerland stuck out as the most interesting, because it&#8217;s up there in 4th place yet has a relatively small population (under 8m). So I wondered &#8211; what would the chart look like if I scaled it by the population size? Here&#8217;s the result:</p>
<p><img class="alignnone size-full wp-image-2941" title="SourceTree_Country_PerCapita2" src="http://www.stevestreeting.com/wp-content/uploads/2011/04/SourceTree_Country_PerCapita2.png" alt="" width="611" height="400" /></p>
<p>And there you go &#8211; as expected Switzerland jumps right to the top, and to my surprise Luxembourg and Denmark are up there too, beating the UK which I expected to come in second. Quite a lot of European countries are punching above their weight in per-capita Mac development, if SourceTree sales are any indication. In fact, on a per-capita basis, the USA is only just sneaking into the top 10, despite it being by far my best overall customer in sheer sales volume.</p>
<p>I&#8217;m aware that scaling by population isn&#8217;t all that scientific, since it is sensitive to the proportion of non-developers (and even non-computer users), but as I say, I think in developed countries at least, the comparisons are reasonably valid.</p>
<p>So the perception that Mac development is more popular in the USA than elsewhere may be inaccurate, based on my numbers at least (which of course are not massive in the grand scheme of things, but still a statistically relevant sample I think). Sure, simply because of the sheer population size of the USA it&#8217;s bound to dominate anyone&#8217;s sales numbers, but if you asked the question &#8216;of 1000 randomly selected developers in a country, what percentage are using a Mac?&#8217;, the result may not be skewed in the way you might expect. It was surprising to me, anyway.</p>
<p>I wonder if anyone else who has been doing this for longer has had similar results?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevestreeting.com/2011/04/07/mac-user-base-by-country-my-figures-so-far/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Introducing: SourceTree</title>
		<link>http://www.stevestreeting.com/2010/10/26/introducing-sourcetree/</link>
		<comments>http://www.stevestreeting.com/2010/10/26/introducing-sourcetree/#comments</comments>
		<pubDate>Tue, 26 Oct 2010 16:24:20 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[DVCS]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Mercurial]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[sourcetree]]></category>
		<category><![CDATA[vcs]]></category>
		<category><![CDATA[version control]]></category>

		<guid isPermaLink="false">http://www.stevestreeting.com/?p=2845</guid>
		<description><![CDATA[I&#8217;m pleased to announce that I&#8217;m finally ready to make my first fully-fledged commercial Mac OS X application available to the world! SourceTree is a user-friendly Mac OS X front-end for Mercurial and Git, the two most popular distributed version control systems used today. The goal was to create a single tool which could deal [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.sourcetreeapp.com" target="_blank"><img class="alignright size-thumbnail wp-image-2846" title="icon" src="http://www.stevestreeting.com/wp-content/uploads/2010/10/icon-150x150.png" alt="" width="150" height="150" align="right" /></a>I&#8217;m pleased to announce that I&#8217;m finally ready to make my first fully-fledged commercial Mac OS X application available to the world!</p>
<p><strong><a href="http://www.sourcetreeapp.com" target="_blank">SourceTree</a></strong> is a user-friendly Mac OS X front-end for <a href="http://mercurial.selenic.com/" target="_blank">Mercurial</a> and <a href="http://git-scm.com/" target="_blank">Git</a>, the two most popular distributed version control systems used today. The goal was to create a single tool which could deal with both systems efficiently, and to give a developer quick and intuitive access to the things (s)he needs to just get on with building software.</p>
<p>I thought I&#8217;d answer a few background questions on this that I get asked on occasion:</p>
<p><strong>Why Mercurial AND Git?</strong></p>
<p>Other apps tend to concentrate on just one version control system, so why am I supporting two? Well, as a developer I&#8217;m regularly coming across projects from both sides of the fence, and in practice I find I need to use both fairly regularly. I personally chose Mercurial for my own projects (and discussed why <a href="http://www.stevestreeting.com/2009/11/06/dvcs-score-card/">here</a>), but I still use Git when dealing with other projects, and spend a fair amount of time hopping between the two. It struck me that even though they have their differences, they are both based on the same <a href="http://en.wikipedia.org/wiki/Distributed_Version_Control_System" target="_blank">distributed principles</a>, so having to use two separate tools was just unnecessary. I wanted a single tool which provided a common interface where that made sense, while still exposing the things they do differently where that was useful too. <a href="http://www.sourcetreeapp.com" target="_blank">SourceTree 1.0</a> is my first attempt at that.</p>
<p><strong>Why only Mac OS X?</strong></p>
<p>There were actually multiple reasons for this choice:</p>
<ol>
<li>I wanted to learn Objective-C and Cocoa on a real project</li>
<li>I know from experience that designing for multiple platforms can be a distraction, with more time spent on compatibility issues, and less on functionality &#8211; and that&#8217;s before you even consider the compromises  you have to make, particularly on UI conventions which are far from uniform across platforms. I&#8217;ve been a multi-platform developer for more than 10 years, and for a change I just wanted to focus on the end user results and nothing else. I&#8217;m aware that schedules slip very easily when you overcomplicate, and I&#8217;m already supporting multiple DVCS systems (something I consider to be an important feature point), so I deliberately chose to keep this element simple.</li>
<li>Mac OS X has become my own platform of choice for most things now. The combination of stability, user-friendliness, Unix underpinnings and well designed hardware match my current needs perfectly. I&#8217;m done with the &#8216;some assembly required&#8217; PCs that I loved tinkering with over the past 15 years</li>
</ol>
<p><strong>What about Subversion?</strong></p>
<p>A few people have asked me if I plan to add Subversion support too. I actually did intend to originally, until I realised how much time it was going to take to just do a decent job on Mercurial and Git. Within the time constraints, I focussed on the subject areas that I felt I could contribute most to &#8211; there are already quite a few Subversion tools out there for Mac OS X, but Mercurial and Git are much less well served, so that&#8217;s where I focussed my efforts.</p>
<p>I still have Subversion support tentatively on my work plan, but it&#8217;s not top of the list. I think it&#8217;s better to do your most important features well before diversifying. Plus, there are problems with Subversion &#8211; it&#8217;s very, very slow compared to Mercurial and Git, so to match the performance in SourceTree of things like the interactive searches and dynamic refreshing / log population I&#8217;d probably have to do a ton of extra caching just so the user wasn&#8217;t sat tapping their fingers.</p>
<p><strong>Edit:</strong> I made my decision on this: I don&#8217;t plan to support local Subversion, but to support operating with Subversion servers with Mercurial and Git locally via hgsvn and git-svn.</p>
<p><strong>Why didn&#8217;t you make it open source?</strong></p>
<p>Sorry folks, while I love contributing to open source (I&#8217;ve done a bit on SourceTree too, sending a patch back to BWToolkit), making it work as a business is very hard indeed. I half-killed myself trying to combine being an open source project leader and doing other commercial activities at the same time, so now I&#8217;m trying a more traditional approach. One thing I learned in the last few years is that there are some sectors &amp; application types where being an open source maintainer is very compatible with also running a business based on that project, and there are others where you can really only do one or the other simultaneously without flaming out. Sucks, but there it is <img src='http://www.stevestreeting.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>What&#8217;s Next?</strong></p>
<p>I have a <a href="http://www.sourcetreeapp.com/roadmap/" target="_blank">public, official roadmap</a> for SourceTree and encourage users to suggest things they think should be on there, via the <a href="http://www.sourcetreeapp.com/support/" target="_blank">support system</a>. I learned from running an open source project for 10 years that being open about your plans can be a big benefit &#8211; users like to know where things are likely to be going, and often have better ideas than the developer on what could do with a bit more spit and polish. They can also tell you what&#8217;s important to them, which is crucial for prioritising &#8211; as developers we tend to get carried away with things we want to work on, but in the end, it&#8217;s scratching the customer&#8217;s itch that matters most.</p>
<p>And while I&#8217;m really quite proud of SourceTree 1.0, there are plenty of features I&#8217;d like to continue to add, and definitely more room for some totally unnecessary beautification which I didn&#8217;t have time for in the first release. Hey, this <em>is</em> OS X <img src='http://www.stevestreeting.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>SourceTree is available now on a 21-day trial license. <a href="http://www.sourcetreeapp.com" target="_blank">Go get it already</a> <img src='http://www.stevestreeting.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevestreeting.com/2010/10/26/introducing-sourcetree/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Cocoa tip: using custom outline view cells designed in IB</title>
		<link>http://www.stevestreeting.com/2010/08/08/cocoa-tip-using-custom-table-outline-cells-designed-in-ib/</link>
		<comments>http://www.stevestreeting.com/2010/08/08/cocoa-tip-using-custom-table-outline-cells-designed-in-ib/#comments</comments>
		<pubDate>Sun, 08 Aug 2010 11:13:44 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[custom]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[nscell]]></category>
		<category><![CDATA[nsoutlineview]]></category>
		<category><![CDATA[nsview]]></category>
		<category><![CDATA[OS X]]></category>

		<guid isPermaLink="false">http://www.stevestreeting.com/?p=2800</guid>
		<description><![CDATA[I only started learning Objective-C and Cocoa in mid-May, and for the first time I think I actually have a tip to contribute to the wider community. It&#8217;s about using custom cells in NSOutlineView, but those which you want to design inside Interface Builder rather than drawing manually. If you&#8217;re an iOS developer, you&#8217;ll be [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.stevestreeting.com/wp-content/uploads/2010/08/outlineview_custom.png"><img class="alignright size-medium wp-image-2807" title="outlineview_custom" src="http://www.stevestreeting.com/wp-content/uploads/2010/08/outlineview_custom-267x300.png" alt="" width="267" height="300" /></a>I only started learning Objective-C and Cocoa in mid-May, and for the first time I think I actually have a tip to contribute to the wider community. It&#8217;s about using custom cells in NSOutlineView, but those which you want to design inside Interface Builder rather than drawing manually.</p>
<p>If you&#8217;re an iOS developer, you&#8217;ll be wondering why this deserves a blog post &#8211; it&#8217;s easy to do in Cocoa Touch! Well, yes it is easy on iOS, because Apple have specifically allowed you to design table view cells in Interface Builder. When targetting Mac OS X though, it&#8217;s actually pretty awkward, and here&#8217;s why: in Cocoa Touch, the class which draws the cells in a table is UITableViewCell, which is a subclass of UIView &#8211; meaning you can drag one onto the canvas in Interface Builder and lay stuff out right there. In Cocoa, in contrast, the cell is simply represented by <a href="http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ApplicationKit/Classes/NSCell_Class/Reference/NSCell.html" target="_blank">NSCell</a>, which is <strong>not</strong> an NSView subclass. This means Interface Builder will not let you play with them, you draw them by implementing <a href="http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ApplicationKit/Classes/NSCell_Class/Reference/NSCell.html#//apple_ref/doc/uid/20000074-BBCCFICJ" target="_blank">drawWithFrame:inView:</a> instead. I think Apple realised the problem with this design in time for Cocoa Touch but obviously felt they couldn&#8217;t break the existing Cocoa interfaces. There are also many differences between the instantiation of NSCell versus UITableViewCell &#8211; there&#8217;s only one NSCell for all rows in a table / outline view, compared to a type-indexed pool in Cocoa Touch.</p>
<p>The problem boiled down to this: if the contents of your table / outline cell is non-trivial, or if you just don&#8217;t want to write a bunch of layout code, it&#8217;s a PITA to implement a custom look in NSOutlineView, such as the one in the picture, especially if you want custom controls embedded in it. For my current Cocoa app, I really wanted to design my cells (and I have 2 different styles for group levels and detail levels) in Interface Builder to save me hassle, including using Cocoa Bindings to hook up some dynamic fields within. Many internet searches later, and mostly the answer I found was that <a href="http://stackoverflow.com/questions/202471/is-it-possible-to-design-nscell-subclasses-in-interface-builder" target="_blank">it couldn&#8217;t be done</a>. Luckily, I&#8217;m too stubborn to take no for an answer, and eventually I figured out a way to do it. Details are after the jump, with an example project to show it in action.</p>
<p><span id="more-2800"></span></p>
<p><a href="http://bitbucket.org/sinbad/cocoacustomoutlineviewcells" target="_blank">Code Example on BitBucket</a></p>
<p><strong>Note: </strong>The project is written with garbage collection <em>required</em>, that&#8217;s because my original project uses that approach (I&#8217;m happy to require ObjC 2.0 / Leopard and don&#8217;t have a need for low-level memory control in this project) and I didn&#8217;t have time to retrofit old-style retain/release patterns to it. If you still use manual memory management in Mac OS X you&#8217;ll need to alter the code.</p>
<p>The answer to this problem involved several pieces:</p>
<ol>
<li>We need a tree model to hold our data. I&#8217;ve included a pretty standard node implementation in the example (ModelTreeNodeBase), and then subclassed it for the specific example (MyTreeNode)</li>
<li>Since we can&#8217;t design NSCell in Interface Builder, we need to design an NSView instead &#8211; in this case I designed one for the group level, and one for the detail level, but you could do more or less if you wanted. For convenience, I put both in one nib (CustomCells.xib).</li>
<li>We need to attach our NSViews as subviews of the outline view, in the appropriate place, at the right time, in order to display them. I do that in our custom NSCell subclass, CustomCell</li>
<li>Since there is only one instance of NSCell for all data rows of an outline view, we can&#8217;t use that to hold row-specific information, such as binding values to fields. So, I use a controller called CustomCellController which provides the linkage between the cell view and the model node (appropriate MVC practice). I use Cocoa Bindings to pull in data from this controller&#8217;s node per row, see the CustomCells.xib setup.</li>
<li>Again because there&#8217;s only one NSCell instance, we need to associate the specific controller instance for the correct row with the NSCell just before drawing. I do this in the NSOutlineView delegate method outlineView:willDisplayCell: , which you&#8217;ll find in the CustomOutlineViewAppDelegate in this case.</li>
<li>The association between the model node and the controller is kept in a simple NSDictionary, just to keep the coupling loose. Note that I use the model node itself as a key (which is why we&#8217;ve implemented the hash and isEqual methods in the model), in my app this is useful anyway because to identify a node uniquely regardless of content values is required.</li>
<li>Because we&#8217;re manually attaching our subviews on display, we also need to remove them at the right time. I do this on outlineViewItemDidCollapse: (and in the real app, I also do it when deleting rows and on drag/drop)</li>
<li>Outline views allow you to click or press enter to edit the main title text, and I support this here too. I have to do a bit of work though, firstly to make the edit box appear in the right place (see CustomCell&#8217;s editWithFrame: and selectWithFrame: methods) based on where we&#8217;ve placed the text in our custom view, and also to place the &#8216;hit box&#8217; in the right place &#8211; in my case I&#8217;ve allowed the hit box to extend over the entire cell, barring the other controls which take precedence if the mouse hits them. See CustomCell hitTestForEvent: for that code.</li>
<li>I also do a little bit of presentation nicety by changing the colour of the text when the row is selected. You get this for free with NSOutlineView normally, but since we&#8217;re using custom views, you don&#8217;t automatically get inverse video on text, so we have to do that ourselves.</li>
<li>To make the cells resize correctly, you use Interface Builder&#8217;s sizing options as per usual. However, it&#8217;s very important that the size values in the NSOutlineView&#8217;s table column, the size of the scroll view containing it, and the initial size of the custom NSViews for the cells are set to the same values in the various nibs. If you get this wrong, resizing won&#8217;t work correctly. As you can see from the example, if you set it up right you can get all the usual content resizing options for free while designing your cells in Interface Builder.</li>
</ol>
<p>Basically, that&#8217;s it &#8211; hopefully you can see the details from the code with those pointers. You&#8217;ll notice that although I used Cocoa Bindings to link the cell values to the model, I used the NSOutlineViewDataSource protocol for the main outline view structure, instead of binding it via a tree controller. The only reason for that was that the example from my project does it this way, because you need to use a custom datasource to handle drag/drop and the pasteboard, so it was simpler this way. There&#8217;s no reason why this wouldn&#8217;t work with a tree controller providing the data too, since all the key moving parts are in the delegate, custom cell and controllers.</p>
<p>Forgive me for any errors or bad practice here, I&#8217;m still relatively new to ObjC / Cocoa. But still, I hadn&#8217;t seen this done anywhere before so I wanted to share the technique I used, because when I was trying to do it I really wished someone had posted an example like this before. This code works well for me, but suggestions, patches &amp; forks on BitBucket are of course welcome if you see something I&#8217;ve done wrong or sub-optimally.</p>
<p>I hope this is useful to someone!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevestreeting.com/2010/08/08/cocoa-tip-using-custom-table-outline-cells-designed-in-ib/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>OS X Localisation: incremental genstrings and UTF-8 files</title>
		<link>http://www.stevestreeting.com/2010/05/18/os-x-localisation-incremental-genstrings-and-utf-8-files/</link>
		<comments>http://www.stevestreeting.com/2010/05/18/os-x-localisation-incremental-genstrings-and-utf-8-files/#comments</comments>
		<pubDate>Tue, 18 May 2010 15:18:41 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[genstrings]]></category>
		<category><![CDATA[Localization]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://www.stevestreeting.com/?p=2734</guid>
		<description><![CDATA[I came across a couple of interesting issues when I came to do the first pass of writing the text for the user-visible strings I&#8217;d been setting up for a Cocoa app I&#8217;m writing (painfully slowly as I learn the nuances of the environment), and I thought I&#8217;d share them. Full details are after the [...]]]></description>
			<content:encoded><![CDATA[<p>I came across a couple of interesting issues when I came to do the first pass of writing the text for the user-visible strings I&#8217;d been setting up for a Cocoa app I&#8217;m writing (painfully slowly as I learn the nuances of the environment), and I thought I&#8217;d share them. Full details are after the jump, since I&#8217;ve embedded a large script in the post.</p>
<p>The basic principle for text localisation on OS X is that, like most systems, you externalise your user-visible strings in string tables and reference them by keyed aliases in code &#8211; in this case using NSLocalizedString. Apple provide a tool called &#8216;genstrings&#8217; which extracts all these into a template strings file called Localizable.strings which you can then populate per language &#8211; localised files are kept in folders called en.lproj, fr.lproj etc and helpfully they&#8217;re picked up by default like this.  So far, so good.</p>
<p><span id="more-2734"></span><br />
There are a couple of practical issues though. Firstly, genstrings always overwrites its output file, which means that using it incrementally to add new strings when you&#8217;ve already populated the previous set &#8211; which is bound to be the normal case for most developers &#8211; isn&#8217;t possible out of the box. Luckily I found a <a href="http://blog.joaomoreno.com/incremental-localization-on-xcode-based-projects/" target="_blank">nice little Python script</a> which solves this problem for you by merging the results in to your existing files. I&#8217;ve added a custom target with a Run Script step to my XCode project which uses a modified version of this script (see below) to update my strings files whenever I need to.</p>
<p>The second problem is that genstrings creates UTF-16 encoded files, and there&#8217;s no way to alter this. The problem with UTF-16 is that both Mercurial and Git don&#8217;t like them very much; both system&#8217;s text/binary detection will classify them as binary, meaning you lose the ability to diff and merge these files in any useful way. It&#8217;s not a deal-breaker, but it&#8217;s inconvenient. Couple that with the fact that OS X will quite happily use UTF-8 encoded .strings files directly at run-time (although iPhone will not), and it seemed something that I should resolve. For the convenience of development, I modified the Python script (as shown below) to convert the result of genstrings to UTF-8 via iconv, meaning they always get picked up as text in source control. If you&#8217;re deploying on iPhone, it&#8217;s trivial to write a small build script calling iconv again to convert back to UTF-16 for deployment.</p>
<pre class="brush: python;">
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Localize.py - Incremental localization on XCode projects
# João Moreno 2009
# http://joaomoreno.com/

# Modified by Steve Streeting 2010 http://www.stevestreeting.com
# Changes
# - Use .strings files encoded as UTF-8
#   This is useful because Mercurial and Git treat UTF-16 as binary and can't
#   diff/merge them. For use on iPhone you can run an iconv script during build to
#   convert back to UTF-16 (Mac OS X will happily use UTF-8 .strings files).
# - Clean up .old and .new files once we're done

from sys import argv
from codecs import open
from re import compile
from copy import copy
import os

re_translation = compile(r'^&quot;(.+)&quot; = &quot;(.+)&quot;;$')
re_comment_single = compile(r'^/\*.*\*/$')
re_comment_start = compile(r'^/\*.*$')
re_comment_end = compile(r'^.*\*/$')

class LocalizedString():
    def __init__(self, comments, translation):
        self.comments, self.translation = comments, translation
        self.key, self.value = re_translation.match(self.translation).groups()

    def __unicode__(self):
        return u'%s%s\n' % (u''.join(self.comments), self.translation)

class LocalizedFile():
    def __init__(self, fname=None, auto_read=False):
        self.fname = fname
        self.strings = []
        self.strings_d = {}

        if auto_read:
            self.read_from_file(fname)

    def read_from_file(self, fname=None):
        fname = self.fname if fname == None else fname
        try:
            f = open(fname, encoding='utf_8', mode='r')
        except:
            print 'File %s does not exist.' % fname
            exit(-1)

        line = f.readline()
        while line:
            comments = [line]

            if not re_comment_single.match(line):
                while line and not re_comment_end.match(line):
                    line = f.readline()
                    comments.append(line)

            line = f.readline()
            if line and re_translation.match(line):
                translation = line
            else:
                raise Exception('invalid file')

            line = f.readline()
            while line and line == u'\n':
                line = f.readline()

            string = LocalizedString(comments, translation)
            self.strings.append(string)
            self.strings_d[string.key] = string

        f.close()

    def save_to_file(self, fname=None):
        fname = self.fname if fname == None else fname
        try:
            f = open(fname, encoding='utf_8', mode='w')
        except:
            print 'Couldn\'t open file %s.' % fname
            exit(-1)

        for string in self.strings:
            f.write(string.__unicode__())

        f.close()

    def merge_with(self, new):
        merged = LocalizedFile()

        for string in new.strings:
            if self.strings_d.has_key(string.key):
                new_string = copy(self.strings_d[string.key])
                new_string.comments = string.comments
                string = new_string

            merged.strings.append(string)
            merged.strings_d[string.key] = string

        return merged

def merge(merged_fname, old_fname, new_fname):
    try:
        old = LocalizedFile(old_fname, auto_read=True)
        new = LocalizedFile(new_fname, auto_read=True)
        merged = old.merge_with(new)
        merged.save_to_file(merged_fname)
    except:
        print 'Error: input files have invalid format.'

STRINGS_FILE = 'Localizable.strings'

def localize(path):
    languages = [name for name in os.listdir(path) if name.endswith('.lproj') and os.path.isdir(name)]

    for language in languages:
        original = merged = language + os.path.sep + STRINGS_FILE
        old = original + '.old'
        new = original + '.new'

        if os.path.isfile(original):
            os.rename(original, old)
            os.system('genstrings -q -o &quot;%s&quot; `find . -name &quot;*.m&quot;`' % language)
            os.system('iconv -f UTF-16 -t UTF-8 &quot;%s&quot; &gt; &quot;%s&quot;' % (original, new))
            merge(merged, old, new)
        else:
            os.system('genstrings -q -o &quot;%s&quot; `find . -name &quot;*.m&quot;`' % language)
            os.rename(original, old)
            os.system('iconv -f UTF-16 -t UTF-8 &quot;%s&quot; &gt; &quot;%s&quot;' % (old, original))

        if os.path.isfile(old):
        	os.remove(old)
        if os.path.isfile(new):
        	os.remove(new)

if __name__ == '__main__':
    localize(os.getcwd())
</pre>
<p>Hopefully this is useful to someone else! I&#8217;m still very much learning on the Mac development side, so if there&#8217;s something I haven&#8217;t considered, please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevestreeting.com/2010/05/18/os-x-localisation-incremental-genstrings-and-utf-8-files/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Taking a bite of the Apple</title>
		<link>http://www.stevestreeting.com/2010/05/16/takinga-bite-of-the-apple/</link>
		<comments>http://www.stevestreeting.com/2010/05/16/takinga-bite-of-the-apple/#comments</comments>
		<pubDate>Sun, 16 May 2010 14:24:47 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[personal]]></category>

		<guid isPermaLink="false">http://www.stevestreeting.com/?p=2727</guid>
		<description><![CDATA[Giving up the leadership of OGRE was a sad moment for me, but in hindsight it has also been rather liberating. For 10 years I&#8217;d spent most of my energy on OGRE or on projects that were related to OGRE. There was an implicit understanding both from the community and from myself that everything I [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-813" title="apple_logo" src="http://www.stevestreeting.com/wp-content/uploads/2007/07/apple_logo.jpg" alt="" width="100" height="103" align="right" />Giving up the leadership of <a href="http://www.ogre3d.org" target="_blank">OGRE</a> was a sad moment for me, but in hindsight it has also been rather liberating. For 10 years I&#8217;d spent most of my energy on OGRE or on projects that were related to OGRE. There was an implicit understanding both from the community and from myself that everything I embarked on would in some way tie into OGRE &#8211; and indeed my business has always been based on a constant balancing act between how I can make a living while also promoting and advancing OGRE. I&#8217;d tended to major on the latter rather than the former most of the time as it happens, because I had an emotional attachment to the project and a feeling of responsibility and custodianship that I took very seriously. So when I finally admitted to myself that my back couldn&#8217;t take the ongoing demands of being an open source leader as well as making a living, the big question was: what next?</p>
<p>Over the years I&#8217;ve learned a couple of things about choosing what projects to work on &#8211; follow your gut, and work on things you&#8217;d do even if there was no money in it. Yes, you need to do a business case and convince yourself that there&#8217;s a viable market for what you have in mind, but all that&#8217;s irrelevant if you don&#8217;t feel strongly about what you&#8217;re doing, because it&#8217;s passion and enthusiasm that will get you through the difficult times. So I sat down and gave some thought to what really excited me these days, what I liked using and what technical directions piqued my interest. I still find 3D and games fascinating, but they&#8217;re far from my only interests.</p>
<p>So, I realised that one area that I&#8217;ve been dying to get my teeth into properly for ages but had never found the time before, was coding specifically for <a href="http://www.apple.com/macosx/" target="_blank">Mac OS X</a>. In 3 years I&#8217;ve gone from a total newcomer to the platform, to a staunch advocate of it. However until now I&#8217;d never really had time to play with developing on it, beyond porting cross-platform C++ code and providing / using intermediate libraries. One thing I learned in those 3 years as a user was how much better applications designed for OS X felt to use compared to those that were just ported via a common UI layer (like wxWidgets / Qt), and I&#8217;m convinced now that while cross-platform infrastructural code is great, user experiences are <em>far</em> better when designed with the specific platform in mind &#8211; increasingly that means OS and physical device now of course. Sure, cross-platform UIs save the developer time, but the result is often a watered-down experience &#8211; early on I liked OS X applications that felt like Windows, or ran the same on both platforms &#8211; now I  do not. Such carbon-copying applications were helpful while I was unfamiliar with the platform, but now it&#8217;s just glaring to me how basic their compatibility with the OS typically is, and how the UI styles clash with the expected standards.</p>
<p>So, I decided I wanted to learn how to target OS X specifically, and had a couple of ideas for projects I could do with it, which meant learning <a href="http://en.wikipedia.org/wiki/Objective-C" target="_blank">Objective-C</a>. At first, I <em>hated</em> it and tried to escape via more familiar technologies like Objective-C++ and <a href="http://pyobjc.sourceforge.net/" target="_blank">PyObjC</a>. Ultimately I found shortcomings and limitations of those routes and returned to Objective-C, and the more I used it, the more my animosity toward it diminished. In the end I realised the problem was that I needed to adapt to the environment, rather than try to adapt <em>it</em> to my previously learned styles and behaviours. Sure, missing elements like namespaces might still nag me, but on balance the blend of static and dynamic language elements works very well for the intended use. And besides, I really didn&#8217;t want to be &#8216;that guy&#8217; &#8211; the programmer that having decided one language / tech is &#8216;the best&#8217;, then tries to apply it everywhere, regardless of suitability; I like to think I&#8217;m a bit more flexible &amp; multicultural than that.</p>
<p>I&#8217;ve also learned that <a href="http://developer.apple.com/technologies/mac/cocoa.html" target="_blank">Cocoa</a> is a very, very smart system. Mad as a bison if you&#8217;re used to other systems beforehand, but persevere with it and resist the urge to hide it under some vanilla layer that you&#8217;re already familiar with, and you discover it&#8217;s really very powerful. Not to mention the Core Animation and Core Graphics frameworks are a lot of fun.</p>
<p>It&#8217;s funny, I&#8217;ve spent so many years concerning myself with providing compatibility across multiple OS&#8217;s, multiple GPUs, multiple render APIs, and multiple drivers, it&#8217;s a genuine joy to actually forget all that for a while, and concentrate on an end goal with a finite number of permutations for a change &#8211; and not to shy away from using platform-specific features.</p>
<p>While I&#8217;m still very much an advocate of open systems, I look at things slightly differently now &#8211; that data &amp; protocols should be open, and that we should all re-use &amp; collaborate on common, preferably open source infrastructure (like OGRE), but that the &#8216;last mile&#8217; to the user is the <em>least</em> suitable for generalisation, because the more specific you can make that interface to what the user expects on their OS &amp; device, the better that experience will be. And at the end of the day to the user, that experience <em>is</em> the application, and thus all that really matters &#8211; and I feel that Apple gets that, in a way that very few others do.</p>
<p>So, I&#8217;m having a great time learning to be an Apple developer so far, I&#8217;m going to see where this takes me for a while. My gut says it feels right, and I&#8217;ve learned to listen to my gut <img src='http://www.stevestreeting.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  I love the platform, it&#8217;s a total change of pace and technology, it&#8217;s something I&#8217;ve had an interest in for a while, and the Mac has quite a thriving community of quality independent app developers that I can try to join &#8211; what&#8217;s not to like?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevestreeting.com/2010/05/16/takinga-bite-of-the-apple/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>VMWare Fusion 3 impressions</title>
		<link>http://www.stevestreeting.com/2009/10/31/vmware-fusion-3-impressions/</link>
		<comments>http://www.stevestreeting.com/2009/10/31/vmware-fusion-3-impressions/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 14:54:17 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[OS X]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[3D]]></category>
		<category><![CDATA[fusion]]></category>
		<category><![CDATA[virtualisation]]></category>
		<category><![CDATA[vmware]]></category>

		<guid isPermaLink="false">http://www.stevestreeting.com/?p=2327</guid>
		<description><![CDATA[As soon as Macs started running on Intel, they became infinitely more attractive just because suddenly you had the option of using Windows on them too if you needed to. Because let&#8217;s face it, as lovely to use as OS X is, and as much as its popularity has grown, the majority of the world [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-2332" title="vmware_fusion3" src="http://www.stevestreeting.com/wp-content/uploads/2009/10/vmware_fusion3.jpg" alt="vmware_fusion3" width="150" height="166" />As soon as Macs started running on Intel, they became infinitely more attractive just because suddenly you had the option of using Windows on them too if you needed to. Because let&#8217;s face it, as lovely to use as OS X is, and as much as its popularity has grown, the majority of the world still runs Windows. <a href="http://www.apple.com/support/bootcamp/" target="_blank">Boot Camp</a> is a great little tool provided by Apple which makes setting up a dual-boot into Windows generally a breeze, barring a few small niggles such as the slightly ropey support for the extended functions of the track pad (two-finger right-clicking and scrolling is very flaky).</p>
<p>I have Vista installed as a secondary boot on my 2007 MacBook Pro, something I&#8217;ve come to regret as it&#8217;s regularly far more hassle than XP would have been. In practice, I&#8217;ve found that I hardly use it, with weeks passing without me bothering to boot up Vista (which makes it worse, because when I do boot it up its intrusive and wholly unstoppable update process starts kicking in in the background, making me grind my teeth at the CPU / RAM loss). Nevertheless, it&#8217;s useful at times.</p>
<p>I&#8217;ve dallied with virtualisation occasionally, from Parallels to VMWare to VirtualBox, but have been generally disappointed &#8211; my day-to-day work and most of my recreation involves 3D acceleration in one form or another, and virtualisation has historically been pretty bad at supporting it, making it an impractical option. <a href="http://www.vmware.com/products/fusion/" target="_blank">VMWare Fusion 3</a>, however, claims support for Shader Model 3, which is good enough for the vast majority of the work that I do (Dx10+ is still a tiny, tiny niche that is still rarely in demand), so I thought I&#8217;d give it a shot.</p>
<p>One of the nice things about Fusion 3 is that it lets you boot your existing Boot Camp partitions in a VM, which meant I could test it quickly. Parallels supported this too but I found it didn&#8217;t work that well in practice when I tried it. Fusion 3&#8242;s support is excellent &#8211; just a few minutes of adaptation and the requisite install of VMWare Tools on the Windows partition and it was up and running. The main problem I initially encountered is that the default 1GB memory allocation is, of course, absolutely no use for running the sweating hunk of lard that is Vista. This is the OS that is capable of getting up to 1.2GB on my machine after first boot with only Explorer open, if you&#8217;re unlucky enough that it feels it needs to run update processes in the background. I only (only??) have 2GB on my laptop so I had limits, but a quick tweak of the VM to 1.6GB (and also letting it use multiple CPUs) made it run OK and still let me jump back to OS X, albeit a bit slower than usual (but show me a post-millennium Windows OS that can stay usable on 400MB!).</p>
<p>For general non-specialist use, Fusion 3 is as awesome as other virtualisation tools. Either in a window, full screen, or in &#8216;Unity&#8217; mode, where Windows apps look like first-party OS X windows in your task list (a bizarre feeling to have Explorer and Visual Studio show up in Exposé), it works great. They even fix the track pad issues, it works much better than in Boot Camp natively. I&#8217;d definitely want to upgrade the RAM on my machine if I did this regularly, but it&#8217;s certainly solid. But, for me, it&#8217;s all about the 3D, so let&#8217;s get to that.</p>
<p>I ran through a few GPU tests, after having to wait an hour or so for Vista to go through its background update processes so that it stopped sucking CPU and RAM, distorting my performance sampling (grr), and sure enough all the OGRE demos ran ok. They did, however, run pretty slowly; simple fixed-function demos that usually run at 2000fps on this machine ran at about 300fps, and moderately complex SM2 demos usually pegged at 250fps here ran at about 40fps. Highly complex SM3 demos (e.g. <a href="http://www.torusknot.com/ogrespeedtree.html" target="_blank">OgreSpeedTree</a>) were unfortunately almost unusable. So, you can expect a pretty steep performance penalty of at least a factor of 6 times running virtualised 3D in my experience. Clearly, at this performance degradation, this would be no good for me as a sole Windows option on this machine. <strong>But</strong>, it still is valuable, since it&#8217;s using the Boot Camp partition, I can use this to quickly test things for compile &amp; run-time behaviour, albeit at unrealistic performance levels, and reboot &#8216;properly&#8217; into Windows for the times where I want to performance test or demo something.</p>
<p>That is, I would be able to if it wasn&#8217;t for Windows Activation. As we all know, this is Microsoft&#8217;s anti-piracy strategy and involves requiring you to re-activate your copy of Windows within 3 days if a &#8216;significant&#8217; hardware change is detected. Since a VM basically emulates all of the core system processes, inevitably Windows sees that as a &#8216;significant&#8217; change and requires you to reactivate. You can do this online, but only 5 times, after which you have to phone someone every time you want to do it. If I used my Boot Camp partition in both modes, as is useful to me, I&#8217;d have to reactivate way too often.</p>
<p>There are some threads and articles about this issue on the VMWare site; they claim that provided you <a href="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&amp;cmd=displayKC&amp;externalId=1003426" target="_blank">follow this article</a>, then the Windows activation monster will be sated and leave you alone when switching between Boot Camp and Fusion 3. <span style="text-decoration: line-through;">No such luck for me, I&#8217;ve rebooted many times between Boot Camp and VMWare and have had the VMWare Tools installed since the first boot, and all I continuously get is an activated product when I use Boot Camp, and a &#8217;2 days to activation expiry&#8217; message in VMWare. I&#8217;m not the only one: <a href="http://communities.vmware.com/thread/228138;jsessionid=93159ED0AD42D0BACA7E13588397C768?start=15&amp;tstart=0" target="_blank">people are reporting this issue in the forums</a>, including with Windows 7.</span></p>
<p><span style="text-decoration: line-through;">If they can&#8217;t get the activation issue fixed, so that I can choose to use Boot Camp and VMWare interchangeably, this effectively kills the product stone dead for me, as with every other virtualisation product before it. Which is a shame, because apart from this,  it works great. It&#8217;s Windows fault of course, rather than VMWare&#8217;s, but regardless the effect is the same. This is a perfect example of bad, customer-unfriendly DRM &#8211; it&#8217;s especially galling to have MS accuse me of stealing when in fact I&#8217;ve paid through the nose for many, many copies of Windows before, and am set to do so again with their expensive Windows 7 (Pro+) pricing &#8211; where they still seem to stick to this ridiculous principle. Another option would be to free up a spare Windows license from my collection and have separate Boot Camp and VMWare partitions, but I&#8217;d really prefer not to burn the time &amp; disk space on maintaining two installs.</span></p>
<p><span style="text-decoration: line-through;">Fix the activation issue and I&#8217;ll be buying a copy of this plus a 4GB RAM upgrade immediately. Until then, it&#8217;s another nice product that&#8217;s scuppered by one small, but nevertheless major issue.</span></p>
<p><strong>Edit:</strong> Ok, I&#8217;ve resolved this issue. Actually the <a href="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&amp;cmd=displayKC&amp;externalId=1003426" target="_blank">original KB article</a> on the VMWare site was correct, I just didn&#8217;t follow it correctly. In my defence, the key to success is in the small print at the bottom of the article rather than the ordered steps: you have to make sure that you&#8217;ve booted once into Boot Camp <em>with the VMWare Tools installed</em>, then afterwards to start the VM under OS X and reactivate Windows. Having done this, both my hosted VM and Boot Camp configuration show up as &#8216;activated&#8217;, which is precisely what I need.</p>
<p>So, now to buy a copy of this puppy and get 2 new sticks of RAM to shove in the laptop. <img src='http://www.stevestreeting.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevestreeting.com/2009/10/31/vmware-fusion-3-impressions/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Accented characters on OS X</title>
		<link>http://www.stevestreeting.com/2009/09/24/accented-characters-on-os-x/</link>
		<comments>http://www.stevestreeting.com/2009/09/24/accented-characters-on-os-x/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 20:24:04 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[OS X]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[accents]]></category>
		<category><![CDATA[international]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[umlaut]]></category>

		<guid isPermaLink="false">http://www.stevestreeting.com/?p=2252</guid>
		<description><![CDATA[I can&#8217;t believe this is the first time I&#8217;ve needed this on OS X, but it came about from needing to write a document for a European customer and suddenly realising I didn&#8217;t know how to make an umlaut on my Macbook Pro&#8217;s British keyboard. On Windows I might fire up the Character Map, but [...]]]></description>
			<content:encoded><![CDATA[<p>I can&#8217;t believe this is the first time I&#8217;ve needed this on OS X, but it came about from needing to write a document for a European customer and suddenly realising I didn&#8217;t know how to make an umlaut on my Macbook Pro&#8217;s British keyboard. On Windows I might fire up the Character Map, but I didn&#8217;t know how to do it on OS X. Here&#8217;s what I discovered:</p>
<ol>
<li>OS X friendly apps like Mail, Safari, iCal and even Firefox have a &#8216;Special Characters&#8217; entry on the Edit menu which brings up an equivalent of Character Map.</li>
<li>For less OS X friendly apps (like Open Office), you can add a menu bar item to do the same everywhere under System Preferences, Language &amp; Text, Input Sources &#8211; check the Keyboard and Character Viewer option and make sure the Show Input On Menu Bar is enabled. Then you just click the new icon on the menu bar every time you need the character browser.</li>
<li>The most common ones have keyboard shortcuts which modify the next character you type afterward &#8211; Option-e puts an acute accent on the next character you type, Option-` is a grave accent, Option-u is an umlaut, Option-i a circumflex, Option-n that weird Spanish squiggle <img src='http://www.stevestreeting.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  While experimenting I found the ® and © symbols too (Option-r and Option-g respectively, Option-c is the cedilla)</li>
</ol>
<p>So there you go &#8211; useful stuff if you&#8217;re on a British (or presumably US) keyboard and need to deal with non-English names from time to time. If you already knew this, great &#8211; this is just for people in my position who have to use these characters rarely and haven&#8217;t encountered it on a Mac yet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevestreeting.com/2009/09/24/accented-characters-on-os-x/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

