<?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>Ray Rischpater's Blog</title>
	<atom:link href="http://www.lothlorien.com/kf6gpe/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.lothlorien.com/kf6gpe</link>
	<description>Ray's remarks on mobile computing, programming, and writing.</description>
	<lastBuildDate>Sun, 15 Mar 2009 01:09:03 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Finally&#8230; updates to the Mac OS X eReader scripts!</title>
		<link>http://www.lothlorien.com/kf6gpe/?p=106</link>
		<comments>http://www.lothlorien.com/kf6gpe/?p=106#comments</comments>
		<pubDate>Sat, 14 Mar 2009 22:29:22 +0000</pubDate>
		<dc:creator>kf6gpe</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[ebook]]></category>
		<category><![CDATA[ereader]]></category>
		<category><![CDATA[Mac OS X]]></category>

		<guid isPermaLink="false">http://www.lothlorien.com/kf6gpe/?p=106</guid>
		<description><![CDATA[I&#8217;ve been using Kovid Goyal&#8217;s excellent Calibre application for a few months now to manage ebooks on my Sony eReader. It&#8217;s a great tool for managing my library of ebooks, and can also automatically download, convert, and install news from any RSS feed you throw at it. I&#8217;ve converted a lot of stuff I had [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using Kovid Goyal&#8217;s excellent <a href="http://calibre.kovidgoyal.net/">Calibre</a> application for a few months now to manage ebooks on my Sony eReader. It&#8217;s a great tool for managing my library of ebooks, and can also automatically download, convert, and install news from any RSS feed you throw at it. I&#8217;ve converted a lot of stuff I had in LIT format using it, and been very pleased with Kovid&#8217;s work overall.</p>
<p>At the same time, I&#8217;ve used <a href="http://feedbooks.com/">Feedbooks</a> as a source for ebooks, especially classic literature. Feedbooks provides all the formats you&#8217;d expect, and its ePub output looks really nice on the eReader. It also provides reading lists so I can tag content I want to download later, and has the makings of a social network for bookworms through those lists. I frequently download ePubs from Feedbooks and drop them on the eReader via Calibre, so I can keep both current events and literature on the device.</p>
<p>Last night, I took a look at the <a href="http://feedbooks.com/news/">News</a> section of Feedbooks, and was I impressed! They have a lot of RSS feeds they&#8217;re aggregating and formatting, and it looks great on the eReader. Sadly, since I&#8217;m using Mac OS X, I can&#8217;t use their News Stand application to automate content downloads when I attach the eReader.</p>
<p>But I liked the idea of getting the news formatted content straight from a server; not only would it be faster, but I wouldn&#8217;t have to either leave Calibre running or launch it every morning. Since automating the download and installation of Feedbooks news content is an extension of what I&#8217;d already done <a href="http://www.lothlorien.com/kf6gpe/?p=64">previously</a> for PDF printing, I figured it was time to do a bit more hacking.<br />
<span id="more-106"></span><br />
Feedbooks has a nice REST API, which they document <a href="http://feedbooks.com/api">on their site</a>. While they don&#8217;t directly document their news endpoint yet, it&#8217;s based on the same service, so it&#8217;s easy to pull content using <code>curl</code>, which is really cool. In about three minutes, I was able to put together a little bash script that pulled a book from Feedbooks and drop it on my eReader.</p>
<p>Before I began working on the automated solution, I figured it was time to move everything to launchd, as I said I&#8217;d do <a href="http://www.lothlorien.com/kf6gpe/?p=93">three months ago</a>.  Launchd can start scripts at predetermined times or when a volume is mounted, so it doesn&#8217;t rely on the Finder and Automator; instead I can just write a few scripts and stitch them together with launchd directly. I won&#8217;t bore you with the details, as there are a lot of good tutorials on how to use launchd; head over to Google and noodle around if you&#8217;ve never done anything with it. Instead, I&#8217;ll give you another hint: <a href="http://tuppis.com/lingon/">Lingon</a>. With Lingon, writing a launchd plist is as easy as as fillig out a form. For example, I was able to ditch all the Automator junk to detect the eReader and instead create a launchd entry to do it by filling out a form, like this:</p>
<div id="attachment_110" class="wp-caption alignnone" style="width: 310px"><a href="http://www.lothlorien.com/kf6gpe/wp-content/uploads/2009/03/lingon-transfer.png"><img class="size-medium wp-image-110" title="lingon-transfer" src="http://www.lothlorien.com/kf6gpe/wp-content/uploads/2009/03/lingon-transfer-300x278.png" alt="Lingon Configuration for Automating eReader PDF Transfers" width="300" height="278" /></a><p class="wp-caption-text">Lingon Configuration for Automating eReader PDF Transfers</p></div>
<p> </p>
<p>I wrote a second script that pulls a few Feedbooks news items and drops them in a second news directory; launchd just calls this script on a regular basis so that I now have reasonably up-to-date news stories anytime I cable the eReader.  Doing this correctly was a bit finicky; because all of this runs on my laptop, I wanted to make sure that in the process of pulling a file that it wouldn&#8217;t overwrite a previous copy. That way, if it wasn&#8217;t on the network, the previous file could still be put on the eReader. I ended up using curl to pull content to working files in /tmp, and checking the result code from curl before copying the results to an intermediate spool directory where the results would wait until I tethered the eReader.</p>
<p>Finally, I reworked the transfer script quite a bit to simplify things. It&#8217;s now two scripts: transfer.sh, which launchd starts whenever I connect the eReader, and update-ereader.sh, which actually does the updating of both PDF and ePub files from Feedbooks. The new transfer.sh script invokes an Automator action that prompts me once all the files have been moved to the eReader, so I can tether and go easily, or go back and start Calibre and move more content to the eReader.</p>
<p>As is usual with my shell scripting, these scripts demonstrates my cargo cult mentality; there&#8217;s probably better ways to do much of this using bash. But I&#8217;m pleased that I no longer need to leave Calibre running all the time and yet getting my news is as seamless as getting what I&#8217;ve printed. You&#8217;re welcome to use these scripts as you see fit, of course; <a href="http://www.lothlorien.com/kf6gpe/wp-content/uploads/2009/03/ereader-macosxintegration-20090314.zip">grab this</a> and have fun. A word of warning: expect to do some customization (you&#8217;ll want to edit the files and specify paths, and need to set up the launchd magic on your own. Although all of this is still Mac OS X centric, I suspect that if you&#8217;re using Linux there may be pieces you can use here, too, especially now that I&#8217;ve ditched most of the dependencies on Automator. (I&#8217;ve not looked in to how to detect eReader mounts on Linux, though.)</p>
<p>Speaking of cargo cult programming, here are a few tidbits I picked up that may come in handy for others&#8230;</p>
<p>Most important to me from a cosmetic perspective was getting spaces back into file names and dropping the PDF extension on files. CUPS happily converts spaces in file names to underscores, which is great for scripting, but looks really ugly on the eReader display. A quick pass over a filename with sed fixed that:<br />
<code>dest=`echo "$base" | sed -e 's/_/ /g' -e 's/.pdf//g'`</code><br />
Of course, if you&#8217;ve got spaces in file names, bash itself is going to get mad when you try to walk over the list of files in a directory; instead of something like<br />
<code>for f in `ls $spool/*`; do... done</code><br />
write<br />
<code> find ${spool} -type file -print0 | while read -d $'\0' f; do ... done</code><br />
The first will fail if any file name has whitespace, while the second uses find to grab each file name, terminate it with a null. and pass it to read, which reads the whole file name up to the trailing null appended by find and stashes the resulting file name in the variable <code>f</code>. Nifty trick, that.</p>
<p>One thing that still bugs me about this solution is that because launchd starts the transfer operation on any mount operation, not just the eReader card mount. That&#8217;s a launchd behavior; it starts scripts on volume mounts, not a specific volume mount, and gets twitchy if you tell it to watch a file and the file comes and goes (so you can&#8217;t trigger on a directory being mounted.) Because I have a card in the eReader, the eReader presents two separate mount events, and launchd invokes the transfer script twice. I&#8217;d hacked around that <a href="http://www.lothlorien.com/kf6gpe/?p=98">previously</a> using a lock file, which is a usual UNIX pattern to deal with this sort of thing, but didn&#8217;t really like it. This version of the scripts uses ps to see if the script is running, like this:<br />
<code><br />
me=$0<br />
ps -ax | grep $me | grep -v grep | grep -v $$ &gt; /dev/null<br />
if [ $? -eq 0 ]; then exit 0; fi<br />
</code><br />
I have this nasty feeling that spawning all those grep commands is actually slower than simply testing for a file on the file system, though. Oh, well &#8212; performance isn&#8217;t that important, as the entire process is bound by the speed of writing to the eReader&#8217;s flash file system over USB anyway.</p>
<p>Finally, by separating the update operation from the mount detection, I can update the eReader when other content generation operations (such as a scheduled news download or my printing something else) occurs. The script that fetches my news kicks the update script, as does the cups printing job &#8212; I just stick a call to the update-ereader.sh script as the value of the PostProcessing directive in /etc/cups/cups-pdf.conf. (Actually, I&#8217;ve got a bigger script than that that runs; it does some stuff to try to strip margins and growls completion of each print job&#8230; but I&#8217;m not ready to talk about that, as it&#8217;s shamefully fragile at the moment.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lothlorien.com/kf6gpe/?feed=rss2&amp;p=106</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Whither thee launchd?</title>
		<link>http://www.lothlorien.com/kf6gpe/?p=98</link>
		<comments>http://www.lothlorien.com/kf6gpe/?p=98#comments</comments>
		<pubDate>Mon, 19 Jan 2009 05:18:06 +0000</pubDate>
		<dc:creator>kf6gpe</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[ebook]]></category>
		<category><![CDATA[ereader]]></category>
		<category><![CDATA[Mobile & Wireless]]></category>

		<guid isPermaLink="false">http://www.lothlorien.com/kf6gpe/?p=98</guid>
		<description><![CDATA[Unfortunately, for a number of reasons, I&#8217;ve been far too busy to follow up my previous post to use Mac OS X&#8217;s launchd to detect when the Sony eReader connects. There&#8217;s a lot of good launchd stuff on the Web, though, and it promises to be pretty easy once I sit down and actually write a plist [...]]]></description>
			<content:encoded><![CDATA[<p>Unfortunately, for a number of reasons, I&#8217;ve been far too busy to follow up my previous <a title="Better printing to the Sony eReader using CUPS-PDF" href="http://www.lothlorien.com/kf6gpe/?p=93">post</a> to use Mac OS X&#8217;s launchd to detect when the Sony eReader connects. There&#8217;s a lot of good launchd stuff on the Web, though, and it promises to be pretty easy once I sit down and actually write a plist for it.</p>
<p>In the mean time, here&#8217;s a revised script for moving the printed PDF files from a spooling directory to the eReader on connection. The setup is <a title="Improving Interaction Between the Sony eReader and Mac OS X" href="http://www.lothlorien.com/kf6gpe/?p=64">the same as before</a>; simply kick the script with a Folder Action.</p>
<pre>#!/usr/bin/env sh
PATH=/opt/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
export PATH

readermain="/Volumes/PRS 700"
readercard="/Volumes/700 CARD"
spool="/Users/kf6gpe/.cups-pdf-spool"
pdfdest="$readercard/PDFs/"

growl()
{
    message="$*"
    which growlnotify &gt; /dev/null
    if [ $? -eq 0 ]; then
        echo $message | growlnotify -t "eReader" -p -2 -a /Applications/Preview.app
    fi
}

if [ -f "/tmp/prs-busy" ]; then
    exit 0;
fi

if [ -d "$readercard" ]; then
    touch /tmp/prs-busy
    growl "Device detetected.";
    for f in `ls $spool/*.pdf`
    do
        cp $f "$pdfdest"
        if [ $? -eq 0 ]; then
            rm -f $f
            growl "Transferred `basename $f`."
        fi
    done
    growl "PDF transfer complete.";
    rm /tmp/prs-busy
else
    rm /tmp/pre-busy 2&gt;&amp;1 /dev/null
fi</pre>
<pre>exit 0</pre>
<p>The changes are pretty self-explanatory. In brief:</p>
<ol>
<li>Have use Preview&#8217;s icon, in case Calibre isn&#8217;t installed.</li>
<li>Only look for the eReader&#8217;s card; there&#8217;s really no reason to look for both volumes. </li>
<li>Use the lock file <tt>/tmp/prs-busy</tt> to ensure that the actual movement of the files doesn&#8217;t occur while it&#8217;s actually running. </li>
</ol>
<p>Of these changes, (3) was certainly the most important, because if you mounted another volume (say, a digital camera) while the script was doing things, weird things could happen. In practice, I never saw anything amiss, but this makes me sleep better at night.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lothlorien.com/kf6gpe/?feed=rss2&amp;p=98</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Better printing to the Sony eReader using CUPS-PDF</title>
		<link>http://www.lothlorien.com/kf6gpe/?p=93</link>
		<comments>http://www.lothlorien.com/kf6gpe/?p=93#comments</comments>
		<pubDate>Sun, 04 Jan 2009 23:04:55 +0000</pubDate>
		<dc:creator>kf6gpe</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[ebook]]></category>
		<category><![CDATA[ereader]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Mobile & Wireless]]></category>

		<guid isPermaLink="false">http://www.lothlorien.com/kf6gpe/?p=93</guid>
		<description><![CDATA[After the recent work I&#8217;ve done integrating my Sony eReader with Mac OS X, I still wanted to be able to optimize page layout for the device. 
After some digging around and realizing that I don&#8217;t have ppdc I grabbed a PPD file for a generic Postscript printer and started hacking. 
Download ereader.ppd
The results work pretty well, although I [...]]]></description>
			<content:encoded><![CDATA[<p>After the <a href="http://www.lothlorien.com/kf6gpe/?p=64">recent work</a> I&#8217;ve done integrating my Sony eReader with Mac OS X, I still wanted to be able to optimize page layout for the device. </p>
<p>After some digging around and realizing that I don&#8217;t have <code>ppdc</code> I grabbed a PPD file for a generic Postscript printer and started hacking. </p>
<p><a href="http://www.lothlorien.com/kf6gpe/wp-content/uploads/2009/01/ereader.ppd">Download ereader.ppd</a></p>
<p>The results work pretty well, although I see goofy margins from some applications such as <a title="TextMate" href="http://macromates.com/" target="_blank">TextMate</a>.</p>
<p>Next up? Ditching the Folder Action script I wrote about <a href="http://http://www.lothlorien.com/kf6gpe/?p=64">yesterday</a> in favor of <code>launchd</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lothlorien.com/kf6gpe/?feed=rss2&amp;p=93</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Improving Interaction Between the Sony eReader and Mac OS X</title>
		<link>http://www.lothlorien.com/kf6gpe/?p=64</link>
		<comments>http://www.lothlorien.com/kf6gpe/?p=64#comments</comments>
		<pubDate>Sat, 03 Jan 2009 20:07:27 +0000</pubDate>
		<dc:creator>kf6gpe</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[ebook]]></category>
		<category><![CDATA[ereader]]></category>
		<category><![CDATA[Mobile & Wireless]]></category>

		<guid isPermaLink="false">http://www.lothlorien.com/kf6gpe/?p=64</guid>
		<description><![CDATA[I have always read a ridiculous amount. Sadly, in recent years as I&#8217;ve taken greater advantage of resources such as the Association for Computing Machinery&#8217;s Digital Library, what that really means is that I print a lot.  There&#8217;s a definite advantage to paper; you can stick it in your bag, or put your feet up and lean [...]]]></description>
			<content:encoded><![CDATA[<p>I have always read a ridiculous amount. Sadly, in recent years as I&#8217;ve taken greater advantage of resources such as the <a title="ACM" href="http://www.acm.org/" target="_blank">Association for Computing Machinery</a>&#8217;s <a title="ACM Digital Library" href="http://portal.acm.org/dl.cfm" target="_blank">Digital Library</a>, what that really means is that I <em>print</em> a lot.  There&#8217;s a definite advantage to paper; you can stick it in your bag, or put your feet up and lean back more so than with a laptop or desktop PC. At the same time, I don&#8217;t archive what I read on paper; I either make notes citing the papers I&#8217;ve read, or if the paper is really important to me, I archive a copy of the PDF itself. As a result, my professional reading workflow is one of researching, printing, reading, and recycling the results. This is a tremendous waste of paper.</p>
<p>While I&#8217;ve tried various ebook solutions on PDAs over the years, I&#8217;ve never been particularly happy with PDF handling on mobile devices.  I&#8217;ve watched with interest the growing market for ebooks on devices including the Sony eReader and the Amazon Kindle, although until recently neither has had particularly good PDF handling either.</p>
<p>Last month I laid hands on a Sony eReader, and really liked what I saw. PDF presentation with later firmware in the PRS 505 is much improved over previous firmware releases, and both the PRS 505 and PRS 700 support Secure Digital cards. As USB devices, these products show up as a mass storage device when mounted on Mac OS X. As an added bonus, Kovid Goyal&#8217;s <a title="Calibre" href="http://calibre.kovidgoyal.net/" target="_blank">Calibre</a> application supports both format translation and automatic harvesting of Web content from RSS feeds. I have to admit that it&#8217;s pretty spiffy to get up in the morning, grab the eReader from my desk and have the latest content from both <a title="The New York Times" href="http://nytimes.com/" target="_blank">The New York Times</a> and <a title="The Economist" href="http://www.economist.com/" target="_blank">The Economist</a> at my fingertips. In conjunction with the large number of freely available books from <a title="Feedbooks" href="http://feedbooks.com/" target="_blank">Feedbooks</a>, it&#8217;s a leisure reader&#8217;s dream.</p>
<p>Although the eReader&#8217;s appearance as a mass storage device in the Mac OS X Finder is useful, I quickly tired of downloading papers and manually copying them to the device.  Intuitively, it seemed that what I wanted to be able to do was to treat the eReader as another printer. </p>
<p>Upon reflection, this idea is quite compelling. It doesn&#8217;t require me to change my work flow at all; moreover, there is something cool about the idea of an eInk device being directly accessible as a printer.</p>
<p><span id="more-64"></span>First on the list was creating a printer that saves its output as PDF files. This is no harder than installing and configuring <a title="CUPS-PDF for Mac OS X" href="http://www.codepoetry.net/projects/cups-pdf-for-mosx" target="_blank">CUPS-PDF for Mac OS X</a>, a build of CUPS-PDF from <a href="http://www.codepoetry.net" target="_blank">codepoetry</a> that streamlines printing to PDF files. CUPS-PDF let me print documents to PDF without the need to choose &#8220;Save as PDF&#8221; anywhere or enter a file name. </p>
<p>CUPS-PDF is actually more useful than it sounds, because once I installed it I could easily create PDF content for the eReader from sources other than PDF documents.  While Calibre converts between a number of formats and has both command-line and GUI interfaces, I quickly found that in practice the additional number of steps meant that I didn&#8217;t put the content on the eReader but printed it or pasted it to <a href="http://www.evernote.com/" target="_blank">Evernote</a> anyway.</p>
<p>By default, CUPS-PDF dumps its output in a directory on the desktop. This is fine, but I&#8217;d already established a directory hierarchy for eBooks and PDFs anyway, so I changed that. You can, too: simply open up Terminal and as root using <code>sudo</code> edit <code>/etc/cups/cups-pdf.conf</code> and change the <code>Out</code> directive. (As I recall, you&#8217;ll need to reboot your system for the change to take effect.) As an added convenience, I shared this printer using Mac OS X printer sharing so I could print to the eReader from any computer on our home network.</p>
<p>Of course, I wanted to be able to create PDFs for the eReader whether or not the eReader was connected. I was impressed that Calibre handled news transfers automatically; ideally the process of connecting the eReader should update not just the Calibre news stories on the eReader, but transfer any new PDFs I had created as well.</p>
<p>Given that the eReader&#8217;s memory shows up as folders on Mac OS X in <code>/Volumes</code>, I knew it was time to see what Mac OS X Automator could do. Within an afternoon, I had an Automator action that moves PDFs to the eReader every time it mounts, complete with <a href="http://growl.info/" target="_blank">Growl</a> status notifications.</p>
<p>The trick was to take advantage of Mac OS X&#8217;s Folder Actions, which can run a script any time the contents of a folder changes. By hooking a Folder Action to the <code>/Volumes</code>, I can trigger the PDF transfer whenever the eReader is connected, because on connection the eReader&#8217;s storage appears as directories in <code>/Volumes</code>.</p>
<p>I use a simple Bourne shell to actually perform the document transfer. The script looks like this:</p>
<pre>#!/usr/bin/env sh
PATH=/opt/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/usr/local/bin
export PATH

readermain="/Volumes/PRS 700"
readercard="/Volumes/700 CARD"
spool="/Users/kf6gpe/Documents/eBooks/Spool"
pdfdest="$readercard/PDFs/"

growl()
{
    message="$*"
    which growlnotify &gt; /dev/null
    if [ $? -eq 0 ]; then
        echo $message | growlnotify -t "eReader" -p -2 -a /Applications/calibre.app
    fi
}

if [ -d "$readermain" -a -d "$readercard" ];
then
    growl "Device detetected.";
        for f in `ls $spool/*.pdf`
        do
            mv $f "$pdfdest"
            growl "Transferred `basename $f`."
        done
    growl "PDF transfer complete.";
fi</pre>
<p><br/><br />
You&#8217;re welcome to the script.  If you take it, be sure to update the <code>readermain</code>, <code>readercard</code>, <code>spool</code>, and <code>pdfdest</code> variables, as follows:</p>
<ul>
<li><code>readermain</code> should be the path to the eReader&#8217;s directory for its main storage.</li>
<li>If you use a memory card with your eReader, <code>readercard</code> should point to the path to the card. (If you&#8217;re not using a memory card, you&#8217;ll need to remove this variable and modify the <code>if</code> statement to test only for the presence of the eReader&#8217;s main directory. In addition, you&#8217;d probably need to make additional changes if you&#8217;re using a PRS 700 with memory cards in both slots.)</li>
<li><code>spool</code> must be the directory where CUPS-PDFs dumps your PDFs.</li>
<li><code>pdfdest</code> must be the already-created directory on the eReader where you want your PDFs.</li>
</ul>
<p>Integrating the script with Automator wasn&#8217;t hard, but getting it as a Folder Action on the <code>/Volumes</code> directory was tricker than I imagined. To do this, follow these steps:</p>
<ol>
<li>Start Automator. (It&#8217;s in Applications).</li>
<li>In the window that appears, choose &#8220;Custom&#8221; and press &#8220;Choose&#8221;.</li>
<li>From the Library of the Actions Pane, choose &#8220;Utilities&#8221; and drag &#8220;Run Shell Script&#8221; to the empty region on the right.</li>
<li>In the &#8220;Run Shell Script&#8221; that appears, choose <code>/bin/sh</code> as the shell and paste the aforementioned shell script in the main region.</li>
<li>Save the workflow using &#8220;Save As&#8230;&#8221; from the &#8220;File&#8221; menu. This is important, because once you export it as a Folder Action, you can&#8217;t seem to edit the results easily. I learned this the hard way.</li>
<li>Save the script as a plug-in by
<ol>
<li>Choose the &#8220;Save as Plug-in&#8230;&#8221; from the &#8220;File&#8221; menu.</li>
<li>In the dialog that appears, select &#8220;Folder Actions&#8221; as the plug-in type.</li>
<li>Select the &#8220;Attached to Folder&#8221; menu and choose &#8220;Other&#8230;&#8221;</li>
<li>In the file dialog that appears, type a <code>~</code>. A new input line labeled &#8220;Go to the folder:&#8221; appears.</li>
<li>In input line, delete the <code>~</code> you typed and enter <code>/Volumes</code>. Press &#8220;Go&#8221;.</li>
<li>Press &#8220;Open&#8221;.</li>
<li>Give the plug-in a reasonable name.</li>
<li>If it&#8217;s visible, be sure that the &#8220;Enable Folder Actions&#8221; box is checked.</li>
<li>Press &#8220;Save&#8221;</li>
</ol>
</li>
</ol>
<p>Phew!</p>
<p>Frustratingly, this didn&#8217;t work right away for me. If you have problems, it&#8217;s worth reading <a href="http://www.peachpit.com/articles/article.aspx?p=1215430" target="_blank">this page</a> by Ben Waldie, which explains much of what happens in the Finder behind the scenes to make Folder Actions work. Strangely, when I first put all this together it didn&#8217;t work because one of the directories the Finder uses (I think it was  <code>~/Library/Scripts/Folder Action Scripts/</code>, but I really don&#8217;t recall now) mysteriously was given read-only file permissions and Automator&#8217;s plug-in creation process would silently fail. So if you&#8217;ve never used Folder Actions or Automator, it&#8217;s worth looking at some of the other tutorials on the Web before you try to wire one to a shell script.</p>
<p>While it&#8217;s pretty slick and I&#8217;m quite pleased with the results, the resulting interaction between the Macintosh and the eReader still leaves room for improvement.</p>
<p>First, I&#8217;d like to add an eReader-specific paper size to the CUPS-PDF printer options for when I print content such as Web pages.  Adding a custom paper size to Mac OS X is easy, although for some reason it doesn&#8217;t show up for the CUPS-PDF printer.  I&#8217;m now starting to look at how CUPS uses PostScript Printer Definition (PPD) files to describe printers and figure out how to do this, although frankly the whole thing makes my head spin.</p>
<p>Second, about 90% of what goes to the eReader this way starts its life as a PDF generated using TeX; such is the stuff of a paper typeset by and for computer scientists. I love TeX and its output, especially the wide margins, because the result is so easy to read. Unfortunately, those same margins occupy a ridiculous amount of space on the eReader screen, space that&#8217;s probably better used for the text itself. The <a title="Comprehensive TeX Archive Network" href="http://www.ctan.org" target="_blank">Comprehensive TeX Archive Network</a> has a script called <code>pdfcrop</code> that determines the bounding box of each page in a PDF and creates a new PDF consisting of pages without their margins, and I&#8217;ve been experimenting with that. Either that or more work with CUPS itself would enable me to rid myself of margins, which would make better use of the eReader&#8217;s screen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lothlorien.com/kf6gpe/?feed=rss2&amp;p=64</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Capturing Stack Crawls in Application Emulation under Win32</title>
		<link>http://www.lothlorien.com/kf6gpe/?p=41</link>
		<comments>http://www.lothlorien.com/kf6gpe/?p=41#comments</comments>
		<pubDate>Mon, 27 Oct 2008 01:30:34 +0000</pubDate>
		<dc:creator>kf6gpe</dc:creator>
				<category><![CDATA[Mobile & Wireless]]></category>

		<guid isPermaLink="false">http://www.lothlorien.com/kf6gpe/?p=41</guid>
		<description><![CDATA[I have always freely admitted that Win32 development is not my thing. What started as a religious conviction (UNIX being what it was when I was a lad&#8230;) and later became first a lack of opportunity and exposure and most recently a conscious choice to keep my skills marketable in niche markets, I&#8217;ve just done [...]]]></description>
			<content:encoded><![CDATA[<p>I have always freely admitted that Win32 development is not my thing. What started as a religious conviction (UNIX being what it was when I was a lad&#8230;) and later became first a lack of opportunity and exposure and most recently a conscious choice to keep my skills marketable in niche markets, I&#8217;ve just done very little work on the platform. Sure, during the heyday of Windows CE (now Windows Mobile) I learned enough to talk with skilled Win32 developers transitioning to Windows CE, and successfully managed WinCE-based development projects, but that&#8217;s not engineering. More recently, I wrote <a href="http://www.amazon.com/dp/1590593014?tag=lothloriencom&#038;camp=14573&#038;creative=327641&#038;linkCode=as1&#038;creativeASIN=1590593014&#038;adid=1S38JKNWPWJ2DMBYSBCT&#038;">a book on developing applications for eBay</a>  that included examples in C#, but that&#8217;s different. C# is managed code, and anyway, writing still isn&#8217;t really engineering.</p>
<p>Nonetheless, much of my career has been spent working within the confines of the Win32 platform. Many mobile platforms such as Qualcomm BREW stage their development environments on top of Win32, providing emulators in which the application you&#8217;re writing is linked in as a Win32 DLL. While this has its limitations&#8212;emulation isn&#8217;t simulation, etc&#8212;it&#8217;s definitely a good way to go for platform vendors, because the Win32 tool chain is well-understood by countless developers, even if the intricacies of a specific mobile platform isn&#8217;t. </p>
<p>At the day job, I recently came across a need to track down a number of memory leaks in a C-based application for Qualcomm BREW. The code had already been written, so it wasn&#8217;t feasible to go back and implement a wrapper to the memory management utilities that tracked allocation and free operations using the __FILE__ and __LINE__ macros; even if I could, I also needed to track down a few BREW component instance leaks, which would be considerably more complex to track using wrappers. Because of the need to determine component instance leaks and how the BREW simulator manages its own heap (providing leak reporting, at least), tools like Purify weren&#8217;t really an option either.</p>
<p>By hand-editing the include files that define BREW&#8217;s object creation and memory allocation routines (AEEShell.h and StdLib.h) I could directly hook the memory allocations, giving me an opportunity to determine the source of the leaks&#8230;if only I knew what portions of the code were performing the allocations. Using a dictionary matching pointers to memory or components and information about how those regions re allocated isn&#8217;t my idea; it&#8217;s hardly new, and frankly, I don&#8217;t know where it originated. It is a good idea, though, because it makes the work go a lot faster. By instrumenting allocations to track where in the code the allocation is being made (typically inserting that information in a dictionary keyed by the pointer to the region or component being allocated) and instrumenting the deallocation to release those records, an examination of the resulting dictionary after a run gives you a list of points in your code that may be allocating resources that aren&#8217;t freed later. The technique isn&#8217;t perfect, of course, especially if you pass references to memory or components around to other systems that you can&#8217;t instrument, but it&#8217;s a good start. I had a <a href="http://www.devx.com/wireless/Article/36032">dictionary implementation</a> that I could use to store information about each allocation referenced by pointer; if I could get stack frame data at the points where I hooked the allocator and deallocators, the work would become much easier.</p>
<p>I knew that I <i>should</i> be able to programmatically get stack trace information running under the simulator on Win32, although I had no idea how. Oddly, this doesn&#8217;t seem to be common knowledge, either, after pinging a few colleagues on the subject. However, after more reading of MSDN articles and googling than I care to admit, I came across Jochen Kalmbach&#8217;s <a href="http://www.codeproject.com/KB/threads/StackWalker.aspx">StackWalker</a> class, a C++ class that provides an utterly simple interface to obtain a stack crawl anywhere in your Win32 application. Great stuff, and I&#8217;m glad I found it! Using it was far simpler for me than trying to wrap my head (and some new code) around the debugger API that Microsoft provides.</p>
<p>I was quickly able to modify it to meet our needs to run within the Qualcomm BREW simulator and provide stack dumps to a log file; after those changes and a bit of truly shameless hacking on private copies of AEEStdlib.h and AEEShell.h, leak tracking became much easier. At some point I plan on providing a simple BREW component for simulator-only use that incorporates his code and provides much of the same functionality; it may make a good article or blog post in the future. In the mean time, I hope that simply describing the process here helps someone.</p>
<p>This experience provides a situation supporting my belief that a general interest in computing and computing platforms is key to being a good software engineer; if I&#8217;d thought too narrowly about the problem as being inherent to an application running on Qualcomm BREW, I might never have decided to add a bit of simulation-specific code to automate the bookkeeping behind my debugging.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lothlorien.com/kf6gpe/?feed=rss2&amp;p=41</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Common Lisp on Mac OS X</title>
		<link>http://www.lothlorien.com/kf6gpe/?p=24</link>
		<comments>http://www.lothlorien.com/kf6gpe/?p=24#comments</comments>
		<pubDate>Fri, 19 Sep 2008 20:18:26 +0000</pubDate>
		<dc:creator>kf6gpe</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Lisp]]></category>

		<guid isPermaLink="false">http://www.lothlorien.com/kf6gpe/?p=24</guid>
		<description><![CDATA[I&#8217;ve been a Lisp nut for years. I was first exposed to Lisp on my TRS-80, when I was about thirteen; Randy Beer had written a Lisp introduction in the March &#8216;83 issue of 80 Micro, and I remember reading it again and again. I&#8217;ve used various flavors of Lisp for exploratory prototyping programming over [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been a Lisp nut for years. I was first exposed to Lisp on my TRS-80, when I was about thirteen; Randy Beer had written a Lisp introduction in the March &#8216;83 issue of 80 Micro, and I remember reading it again and again. I&#8217;ve used various flavors of Lisp for exploratory prototyping programming over the years, and have enjoyed using both Scheme and Common Lisp.</p>
<p>Getting a dialect of Common Lisp running on Mac OS X isn&#8217;t hard &#8212; in fact, if you&#8217;re just setting out, an excellent choice is <a href="http://www.lispworks.com/downloads/index.html">LispWorks Personal Edition</a>. I&#8217;ve recently gotten to the point, however, where I&#8217;ve wanted to do some work with the Common Lisp Interface Manager, which isn&#8217;t supported in LispWorks Personal Edition under Mac OS X, and set out to configure a Common Lisp installation on my MacBook from the ground up.</p>
<p>It wasn&#8217;t difficult, although it took some Googling to get all the pieces together; shortly after I finished, someone on the <a href="http://www.bayfp.org/blog/">Bay Area Functional Programmer</a>&#8217;s mailing list asked about running Common Lisp on Mac OS X, and I put together my notes on the topic and replied. The list is fairly small &#8212; less than 300 members &#8212; and I promised them and myself that I&#8217;d organize the notes and provide them in a more accessible location.</p>
<p>What follows is a step-by-step installation guide to installing <a title="Steel Bank Common Lisp" href="http://www.sbcl.org/">Steel Bank Common Lisp</a> (SBCL) and <a title="McCLIM - A powerful GUI toolkit for Common Lisp" href="http://common-lisp.net/project/mcclim/">McCLIM</a> on a PowerBook G4; I undertook this from the initial notes I took configuring the MacBook. I chose SBCL because it&#8217;s well-supported by the open source community and works well with McCLIM; I have nothing against other Common Lisp implementations, including <a title="Clozure CL" href="http://trac.clozure.com/openmcl">Clozure</a>. </p>
<p>A word of warning is in order: I&#8217;m comfortable with Common Lisp, but relatively unfamiliar with how Common Lisp programmers handle package distribution. I get the basic idea behind <a href="http://common-lisp.net/project/asdf-install/">ASDF</a>, of course, but I&#8217;m not seasoned in its use. Consequently, I had a get-things-working-and-clean-up-later mentality when I undertook my first SBCL-McCLIM configuration, and this largely remained when I wrote what follows. Other Lisp developers may have better ways to organize their working environments, and I&#8217;d welcome positive comments (drop me an email, and we&#8217;ll figure out how to incorporate your feedback).</p>
<p>Starting out, you should have a relatively up-to-date Mac OS X box (I&#8217;ve done this on Mac OS X 10.4.x and 10.5.x systems). When you&#8217;re done, you will have installed <a title="Carbon Emacs Package" href="http://homepage.mac.com/zenitani/emacs-e.html">Carbon Emacs</a>, <a title="SLIME: The Superior Lisp Interaction Mode for Emacs" href="http://common-lisp.net/project/slime/">SLIME</a>, <a title="About - Steel Bank Common Lisp" href="http://www.sbcl.org/">SBCL</a>,and <a title="McCLIM - A powerful GUI toolkit for Common Lisp" href="http://common-lisp.net/project/mcclim/">McCLIM</a> configured to work with the X Windows erver Mac OS X provides, along with <a title="darcs" href="http://darcs.net/">darcs</a>. </p>
<h2><span id="more-24"></span>Carbon Emacs</h2>
<p>Carbon Emacs on Mac OS X provides you with an Emacs instance running as a Mac OS X application. I like it for general editing, as well as the obvious purpose of giving me a place to run SLIME and do my Lisp development.</p>
<ol>
<li>Get Carbon Emacs from its <a title="Carbon Emacs Package" href="http://homepage.mac.com/zenitani/emacs-e.html">home page</a>. If you need a version for a version of Mac OS X other than 10.5, check <a href="http://macwiki.sourceforge.jp/emacs/">here</a>.</li>
<li>Mount the disk image you download, and copy Emacs.app to your Applications folder.</li>
</ol>
<h2>Steel Bank Common Lisp</h2>
<ol>
<li>Download <a title="Download - Steel Bank Common Lisp" href="http://www.sbcl.org/platform-table.html">SBCL</a>. Choose either X or P on this page for the X86 or PPC build, respectively.</li>
<li>Unpack the distribution, and open a Terminal to the directory where you&#8217;ve unpacked the distribution.</li>
<li>Install per the INSTALL instructions. I used the default options, placing SBCL in /usr/local by issuing:
<pre>KF6GPEs-PB-G4:~/Desktop/sbcl-1.0.2-powerpc-darwin kf6gpe$ sudo sh
Password: &lt;entered password&gt;
# INSTALL_ROOT=/usr/local sh install.sh</pre>
</li>
</ol>
<p>At this point in time, you should be able to run SBCL from the shell.</p>
<h2>SLIME</h2>
<p>SLIME in Carbon Emacs is swell.</p>
<ol>
<li><a title="SLIME: The Superior Lisp Interaction Mode for Emacs" href="http://common-lisp.net/project/slime/">Download</a> SLIME. I used CVS in the terminal, stashing the whole thing in a hidden directory. If you use a lot of emacs packages, you may well already have a directory for them, and you can put SLIME there as well.
<pre>KF6GPEs-PB-G4:~ kf6gpe$ cvs -d :pserver:anonymous:anonymous@common-lisp.net:/project/slime/cvsroot co slime
KF6GPEs-PB-G4:~ kf6gpe$ mv slime ~/.slime</pre>
</li>
<li>Wire SLIME up to your emacs installation. I followed the instructions in the SLIME documentation.<br />
In a nutshell, it says to add the following to your ~/.emacs:    </p>
<pre>   (setq inferior-lisp-program "/usr/local/bin/sbcl")
   (add-to-list 'load-path "~/.slime")
   (require 'slime)
   (slime-setup)</pre>
<p>where<br />
/usr/local/bin/sbcl is the path to SBCL you specified in the previous section, and<br />
~/.slime is the path to the slime directory you specified in the previous step.</li>
</ol>
<p>You can stop at this point if you don&#8217;t want to work with McCLIM; you have a working SBCL<br />
environment using Carbon Emacs and SLIME. To use SLIME, start emacs from the Terminal or<br />
Carbon Emacs and run SLIME using M-x slime.</p>
<h2>darcs</h2>
<p>Some of the stuff you need for McCLIM is kept in a darcs repository, so you first need to <a href="http://darcs.net/">get and install darcs</a>. I used one of the <a href="http://wiki.darcs.net/DarcsWiki/CategoryBinaries">pre-built binaries</a>. Make sure that however you do this, darcs is in your path when you&#8217;re done installing, of course.<br />
 </p>
<h2>McCLIM</h2>
<p>I followed <a title="Getting Started with McCLIM" href="http://mcclim.cliki.net/GettingStarted">these steps</a>  to build and configure McCLIM from source.</p>
<ol>
<li>You&#8217;re going to use ASDF to get various Common Lisp packages, and you need a place to put the resulting files, as well as to tell SBCL where that place is. Make a directory ~/lispsystems in your home directory, and configure SBCL by adding the following to your ~/.sbclrc file:
<pre>(require 'asdf)
(push (truename "~/lispsystems") asdf:*central-registry*)</pre>
</li>
<li>Fetch the McCLIM sources.
<pre>KF6GPEs-PB-G4:~/lispsystems kf6gpe$ cvs -z3 -d:pserver:anonymous:anonymous@common-lisp.net:/project/mcclim/cvsroot co mcclim
KF6GPEs-PB-G4:~/lispsystems kf6gpe$ ln -s mcclim/mcclim.asd .
KF6GPEs-PB-G4:~/lispsystems kf6gpe$ ln -s mcclim/clim-examples.asd .</pre>
</li>
<li>Fetch McCLIM&#8217;s dependencies: the Common Lisp Library for X, spatial-trees, and flexichain:
<pre>KF6GPEs-PB-G4:~/lispsystems kf6gpe$ darcs get http://common-lisp.net/~crhodes/clx
KF6GPEs-PB-G4:~/lispsystems kf6gpe$ ln -s clx/clx.asd .
KF6GPEs-PB-G4:~/lispsystems kf6gpe$ curl http://ftp.linux.org.uk/pub/lisp/cclan/spatial-trees.tar.gz &gt; spatial-trees.tar.gz
KF6GPEs-PB-G4:~/lispsystems kf6gpe$ tar -xvzf spatial-trees.tar.gz
KF6GPEs-PB-G4:~/lispsystems kf6gpe$ curl http://common-lisp.net/project/flexichain/download/flexichain_latest.tgz &gt; flexichain_latest.tgz
KF6GPEs-PB-G4:~/lispsystems kf6gpe$ tar -xvzf flexichain_latest.tgz
KF6GPEs-PB-G4:~/lispsystems kf6gpe$ ln -s spatial-trees-0.2/spatial-trees.asd .
KF6GPEs-PB-G4:~/lispsystems kf6gpe$ ln -s flexichain_1.5.1/flexichain.asd .</pre>
</li>
<li>Build the McCLIM system. Fire up Carbon Emacs, run SLIME using M-x slime, and enter:
<pre>CL-USER&gt; (asdf:oos 'asdf:load-op :mcclim)</pre>
<p>Be prepared to wait a while as the system builds for the first time. </li>
<li>To see if everything works as expected, you can build the samples:
<pre>CL-USER&gt; (asdf:oos 'asdf:load-op :clim-examples)</pre>
</li>
<li>To play with the samples:
<pre>CL-USER&gt; (clim-demo::run-test 'clim-demo::demodemo)</pre>
</li>
</ol>
<p>You also have the option of getting McCLIM using <a title="clbuild" href="http://common-lisp.net/project/clbuild/">clbuild</a>, as <a title="McCLiki: Getting started using clbuild" href="http://mcclim.cliki.net/Getting%20started%20using%20clbuild">this page</a> describes. That worked for me under Mac OS X 10.5, but did not under Mac OS X 10.4, and I didn&#8217;t bother to investigate what was different. </p>
<p>Good luck and happy hacking!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lothlorien.com/kf6gpe/?feed=rss2&amp;p=24</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The obligatory first post&#8230;</title>
		<link>http://www.lothlorien.com/kf6gpe/?p=20</link>
		<comments>http://www.lothlorien.com/kf6gpe/?p=20#comments</comments>
		<pubDate>Fri, 19 Sep 2008 19:05:24 +0000</pubDate>
		<dc:creator>kf6gpe</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Writing]]></category>

		<guid isPermaLink="false">http://www.lothlorien.com/kf6gpe/?p=20</guid>
		<description><![CDATA[Installing and configuring WordPress has been on my personal to-do list for an absurdly long amount of time. Back in February 2002, I started a personal blog on LiveJournal, which I kept up-to-date on an intermittent basis. I&#8217;d always planned on using it both as a professional soapbox and a personal journal, although it quickly became [...]]]></description>
			<content:encoded><![CDATA[<p>Installing and configuring <a title="WordPress" href="http://wordpress.org/" target="_blank">WordPress</a> has been on my personal to-do list for an absurdly long amount of time. Back in February 2002, I started a personal blog on <a title="LiveJournal" href="http://www.livejournal.com">LiveJournal</a>, which I kept up-to-date on an intermittent basis. I&#8217;d always planned on using it both as a professional soapbox and a personal journal, although it quickly became more of the latter than the former. In recent years, it&#8217;s largely lain fallow, a victim of benign neglect as I tackle professional writing and engineering commitments.</p>
<p>With the imminent publication of my latest book, <a href="http://www.amazon.com/gp/product/1430210613?ie=UTF8&amp;tag=lothloriencom&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=1430210613">Beginning Java™ ME Platform (Beginning from Novice to Professional)</a><img style="border:none !important; margin:0px !important;" src="http://www.assoc-amazon.com/e/ir?t=lothloriencom&amp;l=as2&amp;o=1&amp;a=1430210613" border="0" alt="" width="1" height="1" />, it&#8217;s again apparent that I should put more effort into reaching out to both those I know and those who read my work. Not only is this an important part of publicity for me as an author, but it&#8217;s also a service to you, my readers, because it gives me an opportunity to keep you up to date. I only hope that I am more successful in keeping you up to date than I am self-publicity, something I have generally neglected. </p>
<p>Hence, this blog.</p>
<p>I&#8217;m not certain what all I will post here, or how frequently I will post. You can certainly expect any updates or feedback on my books, of course, but I&#8217;m also planning on using this as a working notebook for other technical musings. I don&#8217;t have any plans to become a career blogger and make this a central part of my professional activities; to be frank I think there&#8217;s too much of that on the Internet already! Instead, I think this is going to fill a very narrow nice, with me posting the occasional update to a previous (probably paper) publication, various tips and tricks I&#8217;ve picked up in my engineering career, and possibly some engineering notes about things I&#8217;ve found difficult in the hopes that capturing it here will help others.</p>
<p>Thanks for stopping by!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lothlorien.com/kf6gpe/?feed=rss2&amp;p=20</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
