<?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"
	>

<channel>
	<title>The Incrementalist</title>
	<atom:link href="http://retrovirus.com/incr/feed/" rel="self" type="application/rss+xml" />
	<link>http://retrovirus.com/incr</link>
	<description></description>
	<pubDate>Tue, 03 Jul 2007 04:46:10 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.1</generator>
	<language>en</language>
			<item>
		<title>Super See Original bookmarklet for Google Reader on iPhone</title>
		<link>http://retrovirus.com/incr/2007/07/super-see-original/</link>
		<comments>http://retrovirus.com/incr/2007/07/super-see-original/#comments</comments>
		<pubDate>Tue, 03 Jul 2007 04:46:10 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
		
		<category><![CDATA[iphone]]></category>

		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://retrovirus.com/incr/2007/07/super-see-original/</guid>
		<description><![CDATA[Right now, if you visit Google Reader on the iPhone, you get redirected to the mobile XHTML version of Reader.  This works fine for browsing through feed items, but when you click &#8220;See original&#8221; to go to source page for an entry, you get the stripped-down Google Web Transcoder mobile version.  We know [...]]]></description>
			<content:encoded><![CDATA[<p>Right now, if you visit <a href="http://reader.google.com">Google Reader</a> on the iPhone, you get redirected to the mobile XHTML version of Reader.  This works fine for browsing through feed items, but when you click &#8220;See original&#8221; to go to source page for an entry, you get the stripped-down <a href="http://googleblog.blogspot.com/2006/11/viewing-web-through-mobile-lens.html">Google Web Transcoder</a> mobile version.  We know that the iPhone is capable of more than this; what I really wanted to see in this situation was the full-blown original page in a new &#8220;tab&#8221;.</p>

<p>Fortunately, the iPhone&#8217;s Safari supports bookmarklets, so I whipped up a little bookmarklet that makes it easy to see the <i>real</i> original page in Reader.  Here&#8217;s how to use it:</p>

<ol><li>On your desktop computer, drag the following link onto Safari&#8217;s bookmarks toolbar: 
<b><a href="javascript:var%20links=document.getElementsByTagName('a');for(var%20i=0;i<links.length;++i){if(links[i].accessKey==1){/n\?u=(.*)/.test(links[i].href);window.open(unescape(RegExp.$1));break;}}">Super See Original</a></b></li>
<li>Sync your iPhone</li>
<li>Once that&#8217;s done, go to Google Reader on your iPhone, and navigate to a blog entry.</li>
<li>Hit the bookmark icon at the bottom, then choose <b>Bookmarks Bar</b> > <b>Super See Original</b></li>
<li>The original page for your blog entry should open in a new &#8220;tab&#8221;!</li>
</ol>

<p>I have no doubt that the Reader team will eventually make a more iPhone-optimized version of Reader, but until then, hopefully some of you will find this useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://retrovirus.com/incr/2007/07/super-see-original/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Dabble DB: Still sadly short of structured Shangri-La</title>
		<link>http://retrovirus.com/incr/2007/03/dabble-db-shortcomings/</link>
		<comments>http://retrovirus.com/incr/2007/03/dabble-db-shortcomings/#comments</comments>
		<pubDate>Sat, 17 Mar 2007 05:41:20 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
		
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://retrovirus.com/incr/2007/03/dabble-db-shortcomings/</guid>
		<description><![CDATA[My latest side project is Headway, a resource for public transit hackers and the agencies who&#8230; often aren&#8217;t sure what to make of them.  For whatever reason, the combination of sharp urban-dwelling creative folk and useful-but-confusing public transit systems has yielded many handy sites dedicated to making it easier to get around.

As I was [...]]]></description>
			<content:encoded><![CDATA[<p>My latest side project is <a href="http://headwayblog.com">Headway</a>, a resource for public transit hackers and the agencies who&#8230; often aren&#8217;t sure what to make of them.  For whatever reason, the combination of sharp urban-dwelling creative folk and useful-but-confusing public transit systems has yielded <a href="http://headwayblog.com/wiki/index.php?title=Category:Third-Party_Sites">many handy sites</a> dedicated to making it easier to get around.</p>

<p>As I was setting up the blog, found that I really wanted some kind of <a href="http://www.oreillynet.com/pub/a/javascript/2002/01/01/cory.html">outboard brain</a> that could help me keep all the people and sites straight, and hopefully provide a useful reference for others.  For expediency&#8217;s sake, I just used the handy &#8220;one-click&#8221; install of MediaWiki that <a href="http://www.dreamhost.com/r.cgi?54326">DreamHost</a> provides and started typing away.  A few weekends later, <a href="http://headwayblog.com/wiki/">the Headway Wiki</a> was starting to become something useful&#8212;but I was definitely chafing against MediaWiki&#8217;s limitations.  I found that I generally wanted to represent the same kinds of things about <a href="http://headwayblog.com/wiki/index.php?title=BART_Map/Schedule">each entry</a>:</p>

<ul>
<li>the name of the site</li>
<li>the web address</li>
<li>who runs it</li>
<li>when it was launched (often with some degree of fuzziness, because even the site&#8217;s creator doesn&#8217;t really remember)</li>
<li>which agencies it serves</li>
</ul>

<p>&#8230;and a few other miscellaneous things.  Unfortunately, MediaWiki is really oriented towards prose&#8212;and in fact, I found myself using repetitive prose (with a smattering of bulleted lists) to express these things.  Even worse, when I wanted to connect a entry about a third-party transit site to an entry on the agency that it was helping out, I had to manually maintain the link on both ends of the connection.  That is, I couldn&#8217;t just tell the system that <a href="http://headwayblog.com/wiki/index.php?title=Boston_Subway_Station_Map">Boston Subway Station Map</a> had information about the MBTA, and have it automatically display that in the <a href="http://headwayblog.com/wiki/index.php?title=MBTA">MBTA</a> entry&#8212;I had to go and edit the MBTA page by hand.</p>

<p>I did make use of MediaWiki&#8217;s (apparently) single structural feature: categories.  Categories are basically simple tags that you can add to articles, so that the software can automatically generate <a href="http://headwayblog.com/wiki/index.php?title=Category:Agencies">an index</a> of articles that all share a particular tag.  Still, in the end it was far more work than I wanted to do.</p>

<p>There really should be a better way to put together a structured data collection like this, something in between limited expressiveness of MediaWiki and the programming involved in putting together a custom database-backed website using Ruby on Rails or what have you.  I&#8217;m pretty sure that it&#8217;s possible, because I spent several years of my life working on tools like that for the <a href="http://www.maya.com/infocommons/">MAYA Information Commons</a> project.  Sadly, that work still isn&#8217;t available to the general public, so it&#8217;s not really a contender here.  However, there are a few intriguing new possibilities.</p>

<p>Enter <a href="http://dabbledb.com/">Dabble DB</a>.  At first blush, it looked like just the thing that I was looking for.  It has what&#8217;s probably the best available interface for experimenting with different ways of representing interconnected information.  It&#8217;s pretty straightforward to create an item, add a few fields to it, and make some of those fields two-way links to other items.  That&#8217;s no small feat, since my former co-workers and I spent the better part of 2004 building something similar (and if <em><a href="http://www.amazon.com/Dreaming-Code-Programmers-Transcendent-Software/dp/1400082463">Dreaming in Code</a></em> is to be believed, the folks on the respected <a href="http://chandler.osafoundation.org/">Chandler</a> team were at it for even longer, at around the same time).  So far, so good.  But after an evening trying to make the <a href="http://headwayblog.com">Headway</a> data work in Dabble DB, I&#8217;ve run into a bunch of significant shortcomings.</p>

<h3>No boolean fields</h3>

<p>Starting with the smallest thing, there&#8217;s no straightforward way to represent a simple checkbox for things like &#8220;does this feed contain schedule information&#8221;?  You can work around this by creating a multiple-choice field with the options &#8220;Yes&#8221; and &#8220;No&#8221;, but they&#8217;re missing an opportunity to make entering and displaying these fields simpler.</p>

<h3>Limited spatial information</h3>

<p>Here we are, a couple years after the Google Maps API catalyzed a geographic revolution on the web, and Dabble DB&#8217;s only location options are &#8220;US or Canadian state/province code&#8221; and &#8220;Country Code&#8221;.  To their credit, they do automatically link to a Google Maps search for your term in some cases, but they could provide far more interesting map views if they simply had a lat/lon geocode field and just dumped it into Google maps.</p>

<h3>Ontological limitations</h3>

<p>It&#8217;s very cool that Dabble DB lets you put one item in multiple &#8220;categories&#8221; (schemas, basically).  But in practice, their implementation is less handy than it would seem.  Say you had two kinds of things, &#8220;websites&#8221; and &#8220;data providers&#8221;, both of which have names (of course) along with other more category-specific fields.  If it turns out that you want to represent something that&#8217;s both a website and a data provider, and you put both categories on the same object, you end up with two name fields.</p>

<p>You could take a different tack and say that a &#8220;data provider&#8221; is a specific kind of &#8220;website&#8221;, so only the website category will have a name field.  That&#8217;s great, but then there&#8217;s no easy way to have the system automatically add the &#8220;website&#8221; category when you go to create your next &#8220;data provider&#8221; item.  Even worse, when you go to create a new view of your data based on &#8220;data providers&#8221;, there&#8217;s no way to choose to display the &#8220;name&#8221; field from the &#8220;websites&#8221; category in the table.  (Note: this isn&#8217;t strictly true for the name field, since they special-case it so that you always have some kind of identifier, but it&#8217;s true for other attributes.)</p>

<h3>Rudimentary public views</h3>

<p>I could probably work around all those things, but there&#8217;s one thing that makes Dabble DB unusable for the Headway data set: the public view is horribly impoverished.  <a href="http://headway.dabbledb.com/publish/transitdirectory">Here are the results of my experiments</a>: my lovingly interlinked data has been reduced to a box of yellowing printouts, metaphorically speaking.  There&#8217;s no apparent way for the viewer to see a single entry laid out in a readable form, let alone follow links between items or search &amp; filter by different attributes.</p>

<p>It&#8217;s a shame, because Dabble DB really is the best that I&#8217;ve seen so far in most other respects.</p>

<h3>Freebase to the rescue?</h3>

<p>There&#8217;s another contender on the horizon: the wonderfully named <a href="http://www.freebase.com">Freebase</a>.  Tim O&#8217;Reilly recently <a href="http://radar.oreilly.com/archives/2007/03/freebase_will_p_1.html">threw a debutante ball for it</a> on his influential blog, and it&#8217;s easy to see why it stirred some excitement (and controversy) in the online community.  It sounds quite a bit like the things I was working on at MAYA, but with a pleasantly simple web-based interface and without the radical peer-to-peer architecture.  On the other hand, it&#8217;s hard to say for sure, since the alpha is currently only open to a <a href="http://ptufts.blogspot.com/2007/03/freebase-and-creative-commons.html">few</a> <a href="http://neomeme.wordpress.com/2007/03/14/exploring-all-the-cool-stuff-you-can-do-with-freebasewith-screenshots-part-i/">fortunate</a> <a href="http://semantic.nodix.net/2007/03/freebase.html">souls</a>, and details are scarce.  Hopefully I&#8217;ll get a chance to check it out soon.</p>

<p>In the meantime, Dabble DB has a lot of potential, especially since they recently launched their free Creative Commons version (which made it a viable option for Headway).  Hopefully, with a few refinements, they&#8217;ll be able to turn it into a compelling alternative to developing custom code any time you want to share some interconnected information.</p>
]]></content:encoded>
			<wfw:commentRss>http://retrovirus.com/incr/2007/03/dabble-db-shortcomings/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Geotagging Photos with Picasa and Google Earth</title>
		<link>http://retrovirus.com/incr/2006/06/picasa-geotagging/</link>
		<comments>http://retrovirus.com/incr/2006/06/picasa-geotagging/#comments</comments>
		<pubDate>Sat, 17 Jun 2006 22:36:54 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
		
		<category><![CDATA[geo]]></category>

		<category><![CDATA[gui]]></category>

		<guid isPermaLink="false">http://retrovirus.com/incr/2006/06/picasa-geotagging/</guid>
		<description><![CDATA[

A few weeks ago, I went on a hike to Treasure Island, and I thought it&#8217;d be a good opportunity to try out the state of the art in simple photo geotagging, so that people could see photos of my trip on a map.  My first test involved:


Uploading the photos to Flickr using FlickrExport [...]]]></description>
			<content:encoded><![CDATA[<p><img id="image35" src="http://retrovirus.com/incr/wp-content/uploads/2006/06/picasa-geotag-7.jpg" alt="Geotagged photos" height="303" width="400" /></p>

<p>A few weeks ago, I went on a hike to <a href="http://en.wikipedia.org/wiki/Treasure_Island,_California">Treasure Island</a>, and I thought it&#8217;d be a good opportunity to try out the state of the art in simple photo geotagging, so that people could see photos of my trip on a map.  My first test involved:</p>

<ol>
<li>Uploading the <a href="http://flickr.com/photos/joehughes/sets/72157594147786551/">photos</a> to <a href="http://flickr.com">Flickr</a> using <a href="http://connectedflow.com/flickrexport/">FlickrExport</a> for iPhoto</li>
<li>Finding the spot for each for photo in <a href="http://earth.google.com/">Google Earth</a>, creating a placemark, and copying the latitude and longitude into <code>geo:lat=</code> and <code>geo:lon=</code> tags on the Flickr image.</li>
<li>Using <a href="http://www.dapperscoo.com/flickrgeotag/geotagForm.html">Scott The Hobo&#8217;s Flickr Photoset Maps</a> to turn the geotagged photoset into an online map.</li>
</ol>

<p><a href="http://www.dapperscoo.com/flickrgeotag/flickrGeotag.php?photosetid=72157594147786551">The resulting map</a> is pretty nice, sluggish Yahoo map aside, and the process wasn&#8217;t <em>too</em> painful.  The worst pain point was the cut-and-paste geocoding process.</p>

<p>However, since Google just released <a href="http://googleblog.blogspot.com/2006/06/happy-birthday-google-earth.html">a whole slew of geographic updates</a>, not to mention a barebones (but snappy) <a href="http://googleblog.blogspot.com/2006/06/its-all-about-photos.html">photo hosting service</a>, I thought I&#8217;d give it a try using Google tools.</p>

<p>First step: get the photos into Picasa, Google&#8217;s excellent free Windows photo organizer.  I used <a href="http://greggman.com/pages/flickrdown.htm">FlickrDown</a> to download the photoset from Flickr to my Windows box.  It was simple, though I was sad that there was no way to preserve my photos&#8217; tags.  I then downloaded the new version of Picasa from the <a href="http://picasaweb.google.com">Picasa Web Albums</a> site.  (You need to get this specific version to be able to do the fancy stuff I&#8217;m about to describe.)  Picasa immediately found and imported the downloaded photos&#8212;so far, so good.</p>

<p>Next, I went through and geotagged the photos using Picasa&#8217;s integration with <a href="http://earth.google.com/earth4.html">Google Earth 4</a>.  I highlighted some photos in Picasa and selected the <code>Geotag With Google Earth</code> option hidden away in the <code>Tools</code> menu.</p>

<p><img id="image29" src="http://retrovirus.com/incr/wp-content/uploads/2006/06/picasa-geotag-1.jpg" alt="Geotag Menu" width="400" height="333"/></p>

<p>This took me to a <em>slick</em> geotagging interface in Earth.</p>

<p><img id="image30" src="http://retrovirus.com/incr/wp-content/uploads/2006/06/picasa-geotag-2.jpg" alt="Earth Geotagging" width="400" height="258"/></p>

<p>Basically, you just drag and zoom around in Google Earth until the crosshairs (which are anchored to the middle of the display) are resting on the point that you want to tag the photo with.  Then you just hit the <code>Geotag</code> button, the view bounces to give you visual feedback, and it moves on to the next photo.  This was <em>so</em> much more pleasant than manually copying the location to Flickr.  When I was done, it brought me back to Picasa.  The photos all had little crosshair icons in the corner, indicating that they had been geotagged, and a quick look at the <code>Properties</code> dialog seemed to indicate that the location had been added to the image&#8217;s EXIF data.</p>

<p><img id="image31" src="http://retrovirus.com/incr/wp-content/uploads/2006/06/picasa-geotag-3.jpg" alt="Properties dialog" width="398" height="442"/></p>

<p>Now that the images were geotagged, I found that I could use the <code>View in Google Earth...</code> option to see the photo on the map.  It seems that this is implemented using some sort of dynamic folder in Google Earth called <code>Picasa Link</code> that constantly queries Picasa for images with geotags in their EXIF&#8212;so effectively, you can browse your Picasa library geographically using Earth!  I tried adding <a href="http://akuaku.org/archives/2003/05/gps_tagged_jpeg.shtml">a random geotagged phonecam image</a> from the web, and sure enough, it showed up on Earth.</p>

<p>OK, so now that I had found geotagged image bliss, how could I share it?  I tried the <code>Export to Google Earth File</code> option in the <code>Tools</code> &rarr; <code>Geotag</code> menu, which yielded <a href="http://retrovirus.com/files/2006/treasure_island.kmz">a nice Google Earth KMZ file</a> with the photos embedded.</p>

<p>Since Google Maps recently added support for viewing KML files, I decided to see if I could view my photos there.  The results were <a href="http://maps.google.com/maps?f=q&amp;hl=en&amp;q=http://retrovirus.com/files/2006/treasure_island.kmz&amp;ie=UTF8&amp;om=1">not so hot</a>.</p>

<p><a href="http://maps.google.com/maps?f=q&amp;hl=en&amp;q=http://retrovirus.com/files/2006/treasure_island.kmz&amp;ie=UTF8&amp;om=1"><img border="0" id="image32" src="http://retrovirus.com/incr/wp-content/uploads/2006/06/picasa-geotag-4.jpg" alt="Maps KML failure" width="400" height="268"/></a></p>

<p>As you can see, it wasn&#8217;t a <em>total</em> bust&#8212;the locations show up correctly&#8212;but the actual photos were nowhere to be found.</p>

<p>Since I&#8217;d seen <a href="http://maps.google.com/maps?q=http://kml.lover.googlepages.com/my-vacation-photos.kml">examples</a> of photos on maps, I was sure it could be done&#8212;maybe they just wanted the photos to be linked from the web.  The Google Earth UI didn&#8217;t seem to give me any way to replace the photos with web links to photos.  However, KML is a <a href="http://earth.google.com/kml/index.html">straightforward XML format</a>&#8212;hand-editing ahoy!</p>

<p><img id="image33" src="http://retrovirus.com/incr/wp-content/uploads/2006/06/picasa-geotag-5.jpg" alt="Hand-editing" width="400" height="345"/></p>

<p>(Incidentally, I was hoping that when I uploaded the images from Picasa to my Picasa Web Album account, it would do something smart.  Sadly, Web Albums didn&#8217;t show any recognition that the images were geotagged, not even in the EXIF section.  I&#8217;m sure that they&#8217;ll eventually sort that out, maybe by automatically generating KML links to Maps.)</p>

<p>Back to the hand-editing; first I had to unzip the KMZ file that Picasa had generated.  (It&#8217;s just a normal zip file, rename the <code>.kmz</code> to <code>.zip</code> and you should be able to unzip it normally.)  The only file that I needed was the <code>doc.kml</code> file; the rest of the archive just contained the photos and thumbnails.  I stripped out all the style stuff at the top of the file, since Maps didn&#8217;t seem to be paying attention to the icons anyway.  Then I replaced the contents of the <code>description</code> tag in each placemark with an image reference and link to the images on my Picasa Web Album.  Then I uploaded the KML file, and <a href="http://maps.google.com/maps?f=q&amp;hl=en&amp;q=http://retrovirus.com/files/2006/treasure_island.kml">it worked</a>!</p>

<p><a href="http://maps.google.com/maps?f=q&amp;hl=en&amp;q=http://retrovirus.com/files/2006/treasure_island.kml"><img border="0" id="image34" src="http://retrovirus.com/incr/wp-content/uploads/2006/06/picasa-geotag-6.jpg" alt="Working map" width="400" height="266"/></a></p>

<p>The result isn&#8217;t quite as nice as my original map, because I didn&#8217;t immediately see a way to get smaller images out of Web Album, but it does the job.</p>

<p>The verdict: geotagging with Picasa and Google is a dream, viewing geotagged Picasa photos is awesome, but the web mapping part of the Google photo story needs work.</p>

<p>(Incidentally, while you&#8217;re checking out <a href="http://picasaweb.google.com/incrementalist/TreasureIsland">my Treasure Island album</a> be sure to try pressing the left and right arrow keys while you&#8217;re looking at pictures&#8212;you can flip through photos <em>really</em> quickly in Picasa Web Album!)</p>
]]></content:encoded>
			<wfw:commentRss>http://retrovirus.com/incr/2006/06/picasa-geotagging/feed/</wfw:commentRss>
		</item>
		<item>
		<title>What I&#8217;ve been up to&#8230;</title>
		<link>http://retrovirus.com/incr/2005/12/google-transit/</link>
		<comments>http://retrovirus.com/incr/2005/12/google-transit/#comments</comments>
		<pubDate>Thu, 08 Dec 2005 22:42:04 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
		
		<category><![CDATA[transit]]></category>

		<guid isPermaLink="false">http://retrovirus.com/incr/?p=27</guid>
		<description><![CDATA[&#8230;for 20% of my time, anyway.

My teammates and I are proud to present Google Transit, a new Google Labs experiment focused on helping make public transit information more accessible and understandable.  We&#8217;re starting with Portland, Oregon&#8217;s transit system, but we&#8217;ll be expanding it to support other cities soon.

For more information, check out the announcement, [...]]]></description>
			<content:encoded><![CDATA[<p>&#8230;for 20% of my time, anyway.</p>

<p>My teammates and I are proud to present <a href="http://www.google.com/transit">Google Transit</a>, a new Google Labs experiment focused on helping make public transit information more accessible and understandable.  We&#8217;re starting with Portland, Oregon&#8217;s transit system, but we&#8217;ll be expanding it to support other cities soon.</p>

<p>For more information, check out the <a href="http://googleblog.blogspot.com/2005/12/public-transit-via-google.html">announcement</a>, and if you have feedback or bug reports, we&#8217;d love to hear it at <a href="mailto:labs-transit_feedback@google.com">labs-transit_feedback@google.com</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://retrovirus.com/incr/2005/12/google-transit/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Quicktime 7.0.3 for Windows Installation Problem</title>
		<link>http://retrovirus.com/incr/2005/11/quicktime-problem/</link>
		<comments>http://retrovirus.com/incr/2005/11/quicktime-problem/#comments</comments>
		<pubDate>Sun, 13 Nov 2005 08:06:41 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://retrovirus.com/incr/?p=26</guid>
		<description><![CDATA[This is for the benefit of future searchers: if you&#8217;re trying to install iTunes on Windows and it dies during the Quicktime installation with a &#8220;-3&#8243; error, or you try to install Quicktime 7.0.3 on Windows and you get an Error 1714 or some complaint about not being able to find quicktime.msi even though it&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>This is for the benefit of future searchers: if you&#8217;re trying to install iTunes on Windows and it dies during the Quicktime installation with a &#8220;-3&#8243; error, or you try to install Quicktime 7.0.3 on Windows and you get an Error 1714 or some complaint about not being able to find <code>quicktime.msi</code> even though it&#8217;s there, the way to fix it is to:</p>

<ol>
<li>Open <code>regedit</code></li>
<li>Navigate to <code>HKEY_CLASSES_ROOT</code> &#8211;> <code>Installer</code> and select <code>Products</code></li>
<li>Use the <code>Find</code> menu to find <code>quicktime</code> inside that part of the key</li>
<li>Delete the part of the tree that you find</li>
<li>You should now be able to install Quicktime and iTunes without incident</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://retrovirus.com/incr/2005/11/quicktime-problem/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Google Maps + MBTA Update</title>
		<link>http://retrovirus.com/incr/2005/09/gmbta-update/</link>
		<comments>http://retrovirus.com/incr/2005/09/gmbta-update/#comments</comments>
		<pubDate>Tue, 06 Sep 2005 00:13:55 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
		
		<category><![CDATA[gui]]></category>

		<category><![CDATA[transit]]></category>

		<guid isPermaLink="false">http://retrovirus.com/incr/?p=25</guid>
		<description><![CDATA[Since I had the day off today, I had some time to tinker with my MBTA Google Maps experiment and fix a few things which had been bugging me.  The changes include:


You can now look for times near a particular address using the Location area under the map.  In order to do this, [...]]]></description>
			<content:encoded><![CDATA[<p>Since I had the day off today, I had some time to tinker with my <a href="http://retrovirus.com/experiments/gmbta/">MBTA Google Maps experiment</a> and fix a few things which had been bugging me.  The changes include:</p>

<ul>
<li>You can now look for times near a particular address using the Location area under the map.  In order to do this, I wrote a little proxy to feed addresses entered on this page to the wonderful <a href="http://geocoder.us">geocoder.us</a> free geocoding service, and return the results as JavaScript literals.</li>
<li>The page now remembers your location, zoom level, and selected stop between visits.</li>
<li>It now works in current versions of Internet Explorer.</li>
</ul>

<p>At this point, it&#8217;s almost suitable for regular use.  The biggest improvement that&#8217;s still on my list is to do a better job of handling stops that are too close together.  Right now, stops can fall too close together on the map, making them difficult to click on individually.  Automatically combining these stops would help the situation.</p>
]]></content:encoded>
			<wfw:commentRss>http://retrovirus.com/incr/2005/09/gmbta-update/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Building LuaJava on Mac OS X</title>
		<link>http://retrovirus.com/incr/2005/08/building-luajava/</link>
		<comments>http://retrovirus.com/incr/2005/08/building-luajava/#comments</comments>
		<pubDate>Sun, 21 Aug 2005 18:48:29 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
		
		<category><![CDATA[java]]></category>

		<category><![CDATA[lua]]></category>

		<category><![CDATA[mac]]></category>

		<guid isPermaLink="false">/?p=24</guid>
		<description><![CDATA[In my previous post about coroutines, I mentioned that I&#8217;d be looking into LuaJava (a bridge between Java and the Lua language) as a way to get coroutine behavior in a Java environment.  Since I had some time this afternoon, I decided to get LuaJava up and running on my PowerBook.  Here are [...]]]></description>
			<content:encoded><![CDATA[<p>In my previous <a href="http://retrovirus.com/incr/2005/08/coroutines/">post about coroutines</a>, I mentioned that I&#8217;d be looking into <a href="http://www.keplerproject.org/luajava/">LuaJava</a> (a bridge between Java and the <a href="http://www.lua.org/">Lua</a> language) as a way to get coroutine behavior in a Java environment.  Since I had some time this afternoon, I decided to get LuaJava up and running on my PowerBook.  Here are some steps that you can follow to build LuaJava on Mac OS X 10.4.2 Tiger.  (I&#8217;ve also successfully tested these instructions on Mac OS X  10.3.9 Panther.)</p>

<p>LuaJava requires Lua 5.0, so first we need to download the <a href="http://www.lua.org/ftp/lua-5.0.tar.gz">Lua 5.0 source</a> and build it:</p>

<pre><code>% tar xzvf lua-5.0.tar.gz
% cd lua-5.0
% make
% sudo make install
</code></pre>

<p>Next, we need to build LuaJava.  Download <a href="http://luaforge.net/frs/download.php/947/luajava-1.0.tar.gz">LuaJava 1.0</a>, then extract it and switch to its directory:</p>

<pre><code>% tar xzvf luajava-1.0.tar.gz
% cd luajava-1.0
</code></pre>

<p>Since LuaJava&#8217;s <code>config</code> file comes set up for Linux by default, we need to edit it to Mac OS X-friendly settings.  Comment the following lines:</p>

<pre><code>#JDK= $(JAVA_HOME)
#LIB_EXT= .so
#LIB_OPTION= -shared
#DLLIB= -ldl
</code></pre>

<p>and uncomment the corresponding ones:</p>

<pre><code>JDK=/Library/Java/Home
LIB_EXT= .jnilib
LIB_OPTION= -dynamiclib -all_load
</code></pre>

<p>We also need to change the <code>LIB_LUA</code> line to read:</p>

<pre><code>LIB_LUA=/usr/local/lib/liblua.a /usr/local/lib/liblualib.a
</code></pre>

<p>With those changes in place, we can just type</p>

<pre><code>% make
</code></pre>

<p>and apart from a few JavaDoc warnings, everything should go smoothly.  To test it, we can fire up the LuaJava Console:</p>

<pre><code>% java -cp "luajava-1.0.jar" org.keplerproject.luajava.Console
API Lua Java - console mode.
&gt; print('Hello, world!')
Hello, world!
&gt; exit
</code></pre>

<p>OK, that looks good.  How about the included tests?</p>

<pre><code>% cd test
% ./runawttest.sh
% ./runswingtest.sh
</code></pre>

<p>Again, working fine.  There are a couple of other Lua test files in the <code>test</code> directory that we can run like so:</p>

<pre><code>% java -cp "../luajava-1.0.jar" -Djava.library.path=.. 
    org.keplerproject.luajava.Console testMemory.lua
</code></pre>

<p>(replace <code>testMemory.lua</code> with the name of the file you want to run)</p>

<p>OK, let&#8217;s try creating a program of our own.  There&#8217;s a decent Hello World on the <a href="http://www.keplerproject.org/luajava/examples.html">LuaJava examples page</a>, so (after switching back to the <code>luajava-1.0</code> directory), create the <code>Hello.java</code> and <code>hello.lua</code> files depicted on the examples page.  You&#8217;ll need to add an import line to the top of <code>Hello.java</code> so that Java knows where to find all the LuaJava objects:</p>

<pre><code>import org.keplerproject.luajava.*;
</code></pre>

<p>Once you have the files, compile the Java class:</p>

<pre><code>% javac -classpath luajava-1.0.jar Hello.java
</code></pre>

<p>Now run it:</p>

<pre><code>% java -cp luajava-1.0.jar:. Hello
</code></pre>

<p>If everything is working correctly, you should see:</p>

<pre><code>Hello World from Lua!
Hello World from Java!
</code></pre>

<p>Huzzah!  Now we have all the pieces we need to start embedding Lua functionality in Java code.</p>
]]></content:encoded>
			<wfw:commentRss>http://retrovirus.com/incr/2005/08/building-luajava/feed/</wfw:commentRss>
		</item>
		<item>
		<title>(Lack of) Coroutines in Java</title>
		<link>http://retrovirus.com/incr/2005/08/coroutines/</link>
		<comments>http://retrovirus.com/incr/2005/08/coroutines/#comments</comments>
		<pubDate>Thu, 18 Aug 2005 15:43:43 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
		
		<category><![CDATA[concurrency]]></category>

		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">/?p=23</guid>
		<description><![CDATA[My current work project involves lots of small bits of code talking to each other asynchronously and requesting data from a distributed network.  This means that when my code goes to retrieve a piece of data, it may be returned quickly, slowly, or not at all.  Because of this uncertainty, we wouldn&#8217;t want [...]]]></description>
			<content:encoded><![CDATA[<p>My current work project involves lots of small bits of code talking to each other asynchronously and requesting data from a distributed network.  This means that when my code goes to retrieve a piece of data, it may be returned quickly, slowly, or not at all.  Because of this uncertainty, we wouldn&#8217;t want to hold up other parts of the code while waiting for data, and so we want to put the requesting code aside and just come back to it later if and when the data arrives.</p>

<p>The current state of the art looks a bit like this&#8211;effectively a callback-based state machine:</p>

<pre><code>Snippet establishPreference = new Snippet() {
    // called when the result of requestData is available
    public void dataReceivedCallback(Data d) {
        if (d.getValue("likes_marmalade")) {
            serveToast.requestData("marmalade");
        } else {
            serveBagel.requestData("cream cheese");
        }            
    }
}

Snippet serveToast = new Snippet() {
    public void dataReceivedCallback(Data d) {
        spreadOnToast(d.getValue("spoonful_of_substance"));                  
    }
}

Snippet serveBagel = new Snippet() {
    public void dataReceivedCallback(Data d) {
        spreadOnBagel(d.getValue("spoonful_of_substance"));
    }
}
</code></pre>

<p>To kick off this process, you would call:</p>

<pre><code>establishPreference.requestData("Joe Hughes");
</code></pre>

<p>And then depending on whether I liked marmalade or not, I would eventually get served either toast with marmalade or a bagel with cream cheese.</p>

<p>This works fine, but you can see how it could easily get convoluted once you do any kind of serious branching or looping.  For the sake of easier creation and maintenance of these things, I&#8217;d really like to be able to express these operations more like this:</p>

<pre><code>Data customer = requestData("Joe Hughes");
if (customer.getValue("likes_marmalade")) {
    Data topping = requestData("marmalade");
    spreadOnToast(topping.getValue("spoonful_of_substance"));
} else {
    Data topping = requestData("cream cheese");
    spreadOnBagel(topping.getValue("spoonful_of_substance"));
}
</code></pre>

<p>When you put it that way, it&#8217;s much easier to see what&#8217;s going on.  The problem is that in order for this to work, you have to be able to pause this block of code whenever you go off to do a <code>requestData()</code> call, and then restart it with result when you receive it.  It turns out that what I&#8217;m describing is a somewhat obscure programming language construct called a <a href="http://en.wikipedia.org/wiki/Coroutine"><em>coroutine</em></a>.</p>

<p>Unfortunately, not many modern programming languages natively support coroutines.  Python does, somewhat (through <a href="http://www.stackless.com/">Stackless</a> and the new <a href="http://docs.python.org/tut/node11.html#SECTION00111000000000000000000">Generator</a> construct).  Ruby <a href="http://www.oreillynet.com/pub/wlg/7561">seems to</a>.  <a href="http://www.iolanguage.com/about/">Io</a> and <a href="http://www.lua.org/">Lua</a> do.  Java, however, doesn&#8217;t.</p>

<p>I&#8217;ve certainly been able to use threads to make things that <em>look</em> like coroutines:</p>

<pre><code>public abstract class PseudoCoroutine 
    implements DataListener, Runnable {

    private Data response = null;

    /**
     * This method starts a thread to run the specified task.
     *
     * @param task the PseudoCoroutine subclass to be run.
     */

    public static void doTask(PseudoCoroutine task) {
        t = new Thread(task, task.getClass().getName());
        t.start();
    }

    /**
     * This is a callback method from the DataListener interface
     * provided to the DataService to call when it has retrieved the requested data.
     *
     * @param d the data received
     */

    synchronized public void dataReceived(Data d) {
        this.response = d;
        notifyAll();
    }

    /**
     * Provides a delayed-synchronous way to perform a data request.
     * This method call will block until the response
     * is received from the server. 
     *
     * @param dataID the ID of the data to be requested.
     * @return A Data object corresponding to the requested dataID.
     * @throws InterruptedException
     */

    protected Data requestData(String dataID) throws InterruptedException {
        // second parameter is used to pass this.dataReceived() as a callback
        DataService.getInstance().requestData(dataID, this);

        synchronized (this) {
            while (this.response == null) {
                wait();
            }
        }

        return this.response;
    }

    // to make this a Runnable that can be passed to a thread
    public void run() {
        taskBody();
    }

    /**
     * This is where the PseudoCoroutine subclass should perform its task.
     */

    public abstract void taskBody();
}
</code></pre>

<p>This class lets me just use the code I had written above:</p>

<pre><code>private class ServeBreakfastBread extends PseudoCoroutine {
    private String customerID;

    public ServeBreakfastBread(String customerID) {
        this.customerID = customerID;
    }

    public void taskBody() {
        Data customer = requestData(customerID);
        if (customer.getValue("likes_marmalade")) {
            Data topping = requestData("marmalade");
            spreadOnToast(topping.getValue("spoonful_of_substance"));
        } else {
            Data topping = requestData("cream cheese");
            spreadOnBagel(topping.getValue("spoonful_of_substance"));
        }
    }    
}

...

PseudoCoroutine.doTask(new ServeBreakfastBread("Joe Hughes"));
</code></pre>

<p>This works fine, except that each of these things now requires an OS thread, with their attendant limitations (good luck getting more than a few thousand on a desktop VM).  I&#8217;d also like to have the ability for several of these coroutines to be able to operate on common state information without lots of synchronization hassle, which I can&#8217;t do if each coroutine lives in its own thread.</p>

<p>So, where to now?  Maybe I can embed another language interpreter within my Java system and express the coroutines in that.  Unfortunately, Jython doesn&#8217;t support Generators yet.  I&#8217;ll have to look into <a href="http://www.keplerproject.org/luajava/">LuaJava</a> and <a href="http://jruby.sourceforge.net/">JRuby</a> to see if they have anything to offer.</p>
]]></content:encoded>
			<wfw:commentRss>http://retrovirus.com/incr/2005/08/coroutines/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Teleport</title>
		<link>http://retrovirus.com/incr/2005/08/teleport/</link>
		<comments>http://retrovirus.com/incr/2005/08/teleport/#comments</comments>
		<pubDate>Tue, 16 Aug 2005 14:05:13 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
		
		<category><![CDATA[gui]]></category>

		<category><![CDATA[mac]]></category>

		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">/?p=22</guid>
		<description><![CDATA[

The typical setup in my office is that I have my G5 powering two monitors front and center, and the powerbook beside them, on a (modified) iCurve for ergonomic viewing.  While this is great for the displays, it leaves the problem of controlling the laptop.  At one point I had a KVM switch [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.abyssoft.com/software/teleport/"><img src="http://retrovirus.com/incr/images/2005/teleport.jpg" alt="" border=0 /></a></p>

<p>The typical setup in my office is that I have my G5 powering two monitors front and center, and the powerbook beside them, on a (modified) <a href="http://www.griffintechnology.com/products/icurve/">iCurve</a> for ergonomic viewing.  While this is great for the displays, it leaves the problem of controlling the laptop.  At one point I had a KVM switch set up, but the hassle of plugging in a USB cable and flipping the switch led me to just type un-ergonomically on the laptop&#8217;s keyboard.</p>

<p>Then I came across <a href="http://synergy2.sourceforge.net/">Synergy</a>.  It&#8217;s a cross-platform tool that lets you send your keyboard and mouse commands to other machines on your network&#8211;sort of like VNC without the screen-sharing (since the other screen is right in front of you).  The Synergy team&#8217;s most brilliant innovation, though, is the interface for switching machines.  Basically, you can configure your machines so that when you roll your mouse pointer off the edge of one machine&#8217;s screen, it magically appears on the corresponding edge of a different machine&#8217;s screen.  You can roll your mouse from your Linux box across your Windows box over to your Mac in one smooth motion.  It&#8217;s like the way that multi-monitor setups work, except that under the hood it&#8217;s seamlessly switching to sending your input to another machine over the network.</p>

<p>I&#8217;ve been using Synergy for a few months now, but it&#8217;s not without its rough edges.  Last time I did it, configuration was a text-editing affair, though the <a href="http://software.landryhetu.com/synergy/">SynergyKM</a> preference pane add-on for Mac OS X makes things much more automatic.  I also tended to experience general glitchiness on OS X.  A vestigial mouse pointer would often remain on my main monitor, twitching distractingly, as I controlled the laptop.  It also didn&#8217;t handle modifier and function keys, meaning I still had to press the function keys on the laptop directly to trigger Exposé.</p>

<p>Enter <a href="http://www.abyssoft.com/software/teleport/">Teleport</a>.  While (or perhaps because) it&#8217;s Mac-only, it solves most of the problems I had with Synergy.  The configuration is a breeze (using Rendezvous AKA Bonjour), and input forwarding is smooth and comprehensive.  It also seems to automatically sync clipboards well, something that I was using Erik Lagercrantz&#8217;s <a href="http://www.lagercrantz.ath.cx/software/clipboardsharing/">ClipboardSharing</a> utility for until he failed to update it for Tiger.</p>

<p>So far, I only have a few minor critiques.  First, it doesn&#8217;t appear to allow you to put two remote screens side-by-side&#8211;the remote screens must be adjacent to the main computer&#8217;s screens.  Also, it seems to hit the disk every time I roll over the boundary between two machines, which is audibly distracting and causes an annoying delay in which mouse motion isn&#8217;t counted on the new screen.  Even so, I think it will be a part of my desktop setup from now on.  Thanks <a href="http://www.abyssoft.com/about/?s=resume.html">Julien</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://retrovirus.com/incr/2005/08/teleport/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MBTA Google Maps Experiment</title>
		<link>http://retrovirus.com/incr/2005/07/gmbta/</link>
		<comments>http://retrovirus.com/incr/2005/07/gmbta/#comments</comments>
		<pubDate>Sun, 03 Jul 2005 01:35:18 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
		
		<category><![CDATA[geo]]></category>

		<category><![CDATA[transit]]></category>

		<guid isPermaLink="false">/?p=21</guid>
		<description><![CDATA[

Since Google so graciously released an API for their excellent mapper last week, I figured I&#8217;d take it for a spin.  I had written some code to prise nearby stops and bus times from the MBTA&#8217;s handy trip planner a while back, and so I decided to glom them together and see what happened. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://retrovirus.com/experiments/gmbta/"><img src="http://retrovirus.com/incr/images/2005/gmbta.jpg" width="400px" height="250px" border="0" alt="MBTA Google Maps Experiment" /></a></p>

<p>Since Google so graciously released an <a href="http://www.google.com/apis/maps/">API</a> for their excellent <a href="http://maps.google.com/">mapper</a> last week, I figured I&#8217;d take it for a spin.  I had written some code to prise nearby stops and bus times from the <a href="http://trip.mbta.com">MBTA&#8217;s handy trip planner</a> a while back, and so I decided to glom them together and see what happened.  <a href="http://retrovirus.com/experiments/gmbta/">Here&#8217;s the result.</a></p>

<p>Here&#8217;s how it works:  You pan and zoom around the map until you find an area of Boston you&#8217;re interested in, and then click <code>Recalculate Stops</code>.  The map will then update to show stops within a half-mile of the center of the map.  You can click on any of these points to get the next three times for the routes at that stop.  Seems to work for bus, subway, commuter rail, and ferry routes.</p>

<p>It&#8217;s vaguely useful for an afternoon&#8217;s work, though there are a few quirks:</p>

<ul>
<li>Stops which are too close to each other may be impossible to click on (sometimes you can tell because their shadows look darker)&#8211;I&#8217;d probably have to write some code to combine these into a single marker.</li>
<li>The same subway line is often broken into separate listings.  This is something that the trip planner does, perhaps to get around some sort of database limitation?  In any case, this can probably be remedied with more code on my end.</li>
<li>Other than the subways, each route is listed only once per map, at the nearest stop.  This means that even though the 87 might stop in several places within the mile-wide area being searched, you&#8217;ll only see the stop that&#8217;s nearest to the center of the map.</li>
<li>There&#8217;s no way to jump to a particular address.  The Google Maps API currently doesn&#8217;t do geocoding, though I could integrate <a href="http://geocoder.us">geocoder.us</a> or the trip planner&#8217;s built-in geocoder given a little more time.</li>
<li>Clicking the <code>Recalculate Stops</code> button isn&#8217;t the smoothest thing in the world.  My first attempt updated the query automatically when you panned the map, but that made things a bit too jumpy as you panned around to get a better look at the stops and surroundings.  Needs more work.</li>
<li>The iconography and layout could be better.</li>
<li>I have no official connection with the MBTA, and they could break the scraping code that this depends on at any time.  I hope they&#8217;ll be more flattered than offended if they find this.</li>
</ul>

<p>All in all, the Maps API is pleasant to work with, though the way that Google binds API keys to individual directories keeps you from being able to just copy the source files from  your test directory to your deployment directory.  But that&#8217;s the most minor of nitpicks, given that you can dispense keys for all the directories you want.  They&#8217;ve done a great job, and I think we&#8217;re going to see an even bigger wave of new mapping apps in the coming weeks.</p>
]]></content:encoded>
			<wfw:commentRss>http://retrovirus.com/incr/2005/07/gmbta/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
