<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/1.5.2" -->
<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/"
>

<channel>
	<title>fdiv.net</title>
	<link>http://fdiv.net</link>
	<description>the floating point divide</description>
	<pubDate>Wed, 30 Jul 2008 17:51:50 +0000</pubDate>
	<generator>http://wordpress.org/?v=1.5.2</generator>
	<language>en</language>

		<item>
		<title>Silicon Dioxide (SiO2)</title>
		<link>http://fdiv.net/2008/07/30/silicon-dioxide-sio2/</link>
		<comments>http://fdiv.net/2008/07/30/silicon-dioxide-sio2/#comments</comments>
		<pubDate>Wed, 30 Jul 2008 17:50:33 +0000</pubDate>
		<dc:creator>cwright</dc:creator>
		
	<category>Social Story</category>
	<category>kineme</category>
	<category>Interactive Media</category>
	<category>Quartz Composer</category>
	<category>Apple</category>
	<category>Software Development</category>
	<category>Kosada</category>
		<guid>http://fdiv.net/2008/07/30/silicon-dioxide-sio2/</guid>
		<description><![CDATA[	In the wee small hours of this morning, Kineme Interactive Media released its first commercial product, QuartzCrystal.
	QuartzCrystal is an offline renderer that turns Quartz Compositions into portable QuickTime movies.  It supports 3rd party plugins, as well as patches that do not work in safe-mode-only environments (such as QuickTime Pro).  It also supports software [...]]]></description>
			<content:encoded><![CDATA[	<p><a href="http://kineme.net/product/QuartzCrystal"><img style="background: none;" align="right" alt="QuartzCrystal Logo" src="http://kineme.net/files/imagecache/product/files/QuartzCrystal-1.0.png" /></a>In the wee small hours of this morning, <a href="http://kineme.net/">Kineme Interactive Media</a> released its first commercial product, <a href="http://kineme.net/product/QuartzCrystal">QuartzCrystal</a>.</p>
	<p>QuartzCrystal is an offline renderer that turns Quartz Compositions into portable QuickTime movies.  It supports 3rd party plugins, as well as patches that do not work in safe-mode-only environments (such as QuickTime Pro).  It also supports software scene antialiasing, so if you have a Mac with plenty of RAM and a hard-core video card, you can make spectacularly beautiful renderings of your plugins, effects, and compositions.</p>
	<p>Beside QuartzCrystal, the only other product that renders and encodes compositions to movies is <a href="http://www.apple.com">Apple</a>&#8217;s own <a href="http://store.apple.com/us/product/D3380Z/A">QuickTime Pro</a>, which doesn&#8217;t support plugins, unsafe patches, or antialiasing.</p>
	<p><a href="http://kineme.net/product/QuartzCrystal"><img style="background: none;" alt="QuartzCrystal Main Window Screenshot" src="http://kineme.net/system/files/QuartzCrystal+Main+Window_1.png" /></a>
</p>
]]></content:encoded>
			<wfw:commentRSS>http://fdiv.net/2008/07/30/silicon-dioxide-sio2/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>Apple Mail Hack: Move Message To Sent Folder</title>
		<link>http://fdiv.net/2008/04/20/apple-mail-hack-move-message-to-sent-folder/</link>
		<comments>http://fdiv.net/2008/04/20/apple-mail-hack-move-message-to-sent-folder/#comments</comments>
		<pubDate>Sun, 20 Apr 2008 14:43:27 +0000</pubDate>
		<dc:creator>smokris</dc:creator>
		
	<category>Apple</category>
	<category>Not Apple</category>
	<category>Software Development</category>
		<guid>http://fdiv.net/2008/04/20/apple-mail-hack-move-message-to-sent-folder/</guid>
		<description><![CDATA[	In the year that has elapsed since I failed to explain why I was using PINE for email, I&#8217;ve switched to Apple Mail.  Don&#8217;t ask.
	Well, it&#8217;s been alright, but much to my regret the improved latency due to keystrokes only traveling around my local machine &#8212; instead of through the interweb and back as [...]]]></description>
			<content:encoded><![CDATA[	<p><img style="background-color: #808080" align="right" src="http://img.b33p.net/pub/bMIYbDwt8DlYjnZCp4wFZ7KxnbSr1o7L" alt="Apple Mail Icon" />In the year that has elapsed since I <a href="http://fdiv.net/2007/05/12/keybindings-in-macosx-terminal-app/">failed to explain</a> why I was using PINE for email, I&#8217;ve switched to <a href="http://www.apple.com/macosx/features/mail.html">Apple Mail</a>.  Don&#8217;t ask.</p>
	<p>Well, it&#8217;s been alright, but much to my regret the improved latency due to keystrokes only traveling around my local machine &#8212; instead of through the interweb and back as was the case with PINE on a remote machine &#8212; makes it almost justifiable.  Almost.<br />
<a id="more-124"></a></p>
	<p>Apple Mail makes it really easy to delete messages.  You just press the &#8220;Delete&#8221; button.  Poof.</p>
	<p>Apple Mail, however, makes it a lot more difficult to SAVE messages.  You have to go to the &#8220;Message&#8221; menu, then select &#8220;Move To&#8221;, then select the mailbox you want to save it in.  Or use the mouse to drag-and-drop it into your mailbox of choice.  But this is not acceptable as using the mouse depletes one&#8217;s indie cred even more than simply using a GUI mail client in the first place.</p>
	<p>So, armed with <a href="http://www.bazza.com/~eaganj/weblog/2008/02/16/demystifying-mailapp-plugins-for-leopard/">James Eagan&#8217;s article on writing mailbundles</a> I wrote a hack which adds a menu item, complete with keyboard shortcut, allowing the user to easily and quickly file one or more messages away in the &#8220;Sent&#8221; folder (*).  See here:</p>
	<p><img align="right" src="http://img.b33p.net/pub/9uPTamngrrI4UzA_STkwRLK0tdJ4o0Rn" alt="Move to Sent Menu Screenshot" /></p>
	<p>(*) Since switching to Apple Mail &#8212; and having access to its nifty and swift full-text search capabilities &#8212; I&#8217;ve abandoned the thousand-or-so individual folders in which I used to file things away.  Mail in my Inbox now goes to one of two destinations:  <i>Trash</i>, for spam and automatic notifications and other stuff I have no interest in ever looking at again, or <i>Sent</i>, for anything written by a human and on occasion important things written by computers.</p>
	<p>Download <a href="http://softpixel.com/~smokris/widgets/appleMail/MoveMessageToSentFolder-1.0.zip">MoveMessageToSentFolder-1.0.zip</a>.<br />
Leopard (Mac OS X 10.5) only.</p>
	<p>To install:</p>
	<ul>
	<li>Copy the mailbundle to <code>~/Library/Mail/Bundles</code>.  Create this folder if it doesn&#8217;t already exist.</li>
	<li>Open Terminal and run the following commands to enable mailbundle support:
	<pre>
defaults write com.apple.mail EnableBundles 1
defaults write com.apple.mail BundleCompatibilityVersion 3
</pre>
	</li>
	</ul>
]]></content:encoded>
			<wfw:commentRSS>http://fdiv.net/2008/04/20/apple-mail-hack-move-message-to-sent-folder/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>Python&#8217;s Flying Circus</title>
		<link>http://fdiv.net/2008/02/22/pythons-flying-circus/</link>
		<comments>http://fdiv.net/2008/02/22/pythons-flying-circus/#comments</comments>
		<pubDate>Fri, 22 Feb 2008 19:35:35 +0000</pubDate>
		<dc:creator>cwright</dc:creator>
		
	<category>kineme</category>
	<category>Antisocial Story</category>
	<category>Language</category>
	<category>Software Development</category>
		<guid>http://fdiv.net/2008/02/22/pythons-flying-circus/</guid>
		<description><![CDATA[	
	Lately I&#8217;ve been working on integrating (or, more accurately, attempting to integrate) the Python scripting language into some plugins for an application we develop plugins for.  We&#8217;ve wrapped many libraries with varying levels of success, so this one wasn&#8217;t going to be much different.  Or, so we thought.
	Technically, we&#8217;re interested in &#8220;Embedding&#8221; Python [...]]]></description>
			<content:encoded><![CDATA[	<p><img src="http://img.b33p.net/pub/cwIngHlMs0BtBweZ0BcHJrnBo3K6wYeW/thumbnail-256" align="right" alt="Python Logo" /></p>
	<p>Lately I&#8217;ve been working on integrating (or, more accurately, attempting to integrate) the Python scripting language into some plugins for an application we develop plugins for.  We&#8217;ve wrapped many libraries with varying levels of success, so this one wasn&#8217;t going to be much different.  Or, so we thought.<a id="more-118"></a></p>
	<p>Technically, we&#8217;re interested in &#8220;Embedding&#8221; Python &#8212; We have a native Objective-C application that needs to make use of the Python interpreter at various stages of execution.  The Python scripts are user-supplied, and are exceptionally free-form:  the functions they write can take variable numbers of inputs, produce variable numbers of outputs, and can use any Python modules they have installed.</p>
	<p>Unfortunately, this makes the embedding process somewhat complicated:  From Objective-C, we need to be able to parse the script, find all its functions, and get all those functions&#8217; input and output parameters.  From this data, we can expose the Python module&#8217;s interface usefully.  Unfortunately, Python does not appear to allow this kind of introspection from the outside (and it&#8217;s questionable whether or not it&#8217;s even possible from the inside.)</p>
	<p>In searching for information on this, <a href="http://davidf.sjsoft.com/mirrors/mcmillan-inc/embed.html">Numerous</a> <a href="http://www.developer.com/lang/other/article.php/2217941">Documents</a> are <a href="http://twistedmatrix.com/users/glyph/rant/extendit.html">Found</a> that <a href="http://www.linuxjournal.com/article/8497">Needlessly</a> <a href="http://www.python.org/doc/current/ext/embedding.html">Complicate</a> or Obfuscate the difference between Embedding and Extending.  As if it&#8217;s really that difficult (<strong>embed</strong> means &#8220;fix firmly and deeply in a surrounding mass&#8221; while <strong>extend</strong> means &#8220;cause to cover a larger area; make longer or wider&#8221;.  From these obvious definitions, we can infer that &#8220;Embedding&#8221; means putting something inside, while &#8220;Extending&#8221; means adding functionality or abilities.  Maybe it&#8217;s not so clear for non-native english speakers.  I don&#8217;t know.)</p>
	<p>Another annoying side-trip of this research was an overwhelmingly smug idea that almost reeks of Java.  This side effect is the recorded smarmy discussion of why one should &#8220;Extend&#8221; rather than &#8220;Embed&#8221; (these reasons are then used to explain away why there isn&#8217;t any good documentation on actually embedding Python).  The arguments go something like this:</p>
	<ul>
	<li>Python&#8217;s so good, cross-platform, and flexible that it&#8217;s actually more cost-effective to <em>Throw Out All Your C/C++/ObjC Code And Rewrite Everything In Python.</em></li>
	<li>Embedding is so cumbersome to code, and so difficult compared to embedding Python in Python, that you should <em>Throw Out All Your C/C++/ObjC Code And Rewrite Everything In Python.</em></li>
	<li>High-performance code can be written in C, and then called from within Python&#8217;s runtime when you actually need to performance boost.  Why not just <em>Throw Out All Your C/C++/ObjC Code And Rewrite Everything In Python</em> Except for the fast bits?</li>
	<li>If you embed Python, you&#8217;ll annoy Python developers who can&#8217;t access the modules they&#8217;re used to using.  Why not <em>Throw Out All Your C/C++/ObjC Code And Rewrite Everything In Python</em> so you don&#8217;t annoy your Python developers?</li>
	</ul>
	<p>These arguments cover some pretty diverse ground there.  Unfortunately, there are 2 fatals flaws in the list above.  </p>
	<p>First, embedded Python _Can_ in fact use installed modules just like raw Python, so point 4 above is flagrantly incorrect.  There are some suggestions that it&#8217;s simply annoying to develop in such an environment because namespaces are all strange (or wrong) and nothing works quite right.  Guess What:  Welcome To Plugin Development!  It&#8217;s like these Python developers have never worked on real projects before or something.</p>
	<p>Second, All of the above points assume that it&#8217;s possible to discard your entire code-base and rewrite everything.  While this is technically possible, it&#8217;s not very likely when you don&#8217;t have access to the source of the application to be discarded (in our case).  The unfortunate downside is that _All The Listed &#8220;Solutions&#8221; Hinge On This One Idea_.</p>
	<p>What&#8217;s with these non-solutions from allegedly flexible languages?  Even Objective-C, a compiled language, and the (totally undocumented) JavaVM-ObjC bridge, offer enough introspection to at least find methods and parameter counts without too much hassle.  Maybe Python does this just as simply, but if so, no one&#8217;s talking about it&#8230;
</p>
]]></content:encoded>
			<wfw:commentRSS>http://fdiv.net/2008/02/22/pythons-flying-circus/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>Zero Grams of Trans Fat Binaries</title>
		<link>http://fdiv.net/2007/12/19/zero-grams-of-trans-fat-binaries/</link>
		<comments>http://fdiv.net/2007/12/19/zero-grams-of-trans-fat-binaries/#comments</comments>
		<pubDate>Wed, 19 Dec 2007 05:36:15 +0000</pubDate>
		<dc:creator>cwright</dc:creator>
		
	<category>Antisocial Story</category>
	<category>Apple</category>
	<category>Not Apple</category>
	<category>Software Development</category>
	<category>Kosada</category>
		<guid>http://fdiv.net/2007/12/19/zero-grams-of-trans-fat-binaries/</guid>
		<description><![CDATA[	People like their applications to work.  Even better, they like them to work, even when things change.  For the WinTel world, this isn&#8217;t a big deal (Vista aside ;), because the underlying CPU architecture hasn&#8217;t really changed, from a program&#8217;s point of view, in the past two decades.  Unless you have a [...]]]></description>
			<content:encoded><![CDATA[	<p><img align="right" src="http://img.b33p.net/pub/ywiHvPcTv8ZWhWv6nf-AHhne2GUlkx99/png-indexed-64" alt="tons of xcode build targets" />People like their applications to work.  Even better, they like them to work, even when things change.  For the WinTel world, this isn&#8217;t a big deal (Vista aside ;), because the underlying CPU architecture hasn&#8217;t really changed, from a program&#8217;s point of view, in the past two decades.  Unless you have a weird program that&#8217;s designed for AMD&#8217;s 3DNow! instruction set and you switch to an Intel CPU, or perhaps an application designed for a more esoteric old SIMD architecture, your application should run just fine (as long as your Operating System is ok with it).</p>
	<p>Mac OS X doesn&#8217;t have the luxury of working on the same underlying CPU though, so things need to be handled a little bit differently.  The solution Apple came up with was <a id="more-115"></a>the idea of a &#8220;Fat&#8221; binary, sometimes called a &#8220;Universal Binary&#8221;.  In other words, instead of a single program being contained in a program file, the program file can contain several programs for different architectures.  For example:</p>
	<pre class="code">
cwright@phendrana:~>file /bin/ls
/bin/ls: Mach-O universal binary with 2 architectures
/bin/ls (for architecture i386):	Mach-O executable i386
/bin/ls (for architecture ppc7400):	Mach-O executable ppc
</pre>
	<p>or an even more convoluted example:</p>
	<pre class="code">
cwright@phendrana:~>file GLTools
GLTools: Mach-O universal binary with 4 architectures
GLTools (for architecture ppc7400):	Mach-O bundle ppc
GLTools (for architecture i386):	Mach-O bundle i386
GLTools (for architecture ppc64):	Mach-O 64-bit bundle ppc64
GLTools (for architecture x86_64):	Mach-O 64-bit bundle x86_64
</pre>
	<p>This increases file size considerably (4x in the last example), but it provides you with the cool side effect of being able to drop the exact same program onto a PowerPC Mac, and have it operate identically &#8212; as long as you&#8217;re properly handling architectural differences such as <a href="http://en.wikipedia.org/wiki/Endianness">endianness</a>.  Overall, this is a pretty slick solution, and with the exception of a few small tweaks, I doubt I could have come up with a better idea.  (The small tweaks, in case you&#8217;re wondering, would be shared data segments across the binaries inside, such that non-code stuff only needs to be included once, instead of 4 times.  This doesn&#8217;t work well when the data contains code though, so you&#8217;d need to have flags to control how it operates).</p>
	<p>One of many problems rears its ugly head though when developing such portable applications:  Linking with static and dynamic libraries.</p>
	<p>Out of the box, OS X ships with many libraries that are all appropriately compiled to support all the above architectures, so you never notice this problem when compiling against standard included libraries.  However, if you stray off the beaten path, and use another library, you&#8217;re destined for trouble.  Open Source libraries, especially the ones whose build system depends on the monstrosity that is <a href="http://en.wikipedia.org/wiki/Autoconf">AutoConf</a> (<code>./configure</code> scripts and all that), are surprisingly difficult to get working.  In part, because they&#8217;re not designed to be built for multiple architectures in parallel, and in part because AutoConf is infuriatingly worthless when it comes to documentation.</p>
	<p>Of course, since I&#8217;m writing all of this, I&#8217;m obviously in the middle of such a battle :)</p>
	<p>By default, I run configure like this: </p>
	<pre class="code">
CFLAGS=\"-Os -fomit-frame-pointer\" ./configure [options]
</pre>
	<p>where options is stuff like <code>--enable-shared</code> and other library stuff.  On occasion (only 85% of the time), I also have to override other environment variables because parts like <code>pkg-config</code> don&#8217;t work, because other libraries don&#8217;t install properly, and a whole host of other problems.  I really can&#8217;t believe I actually <i>liked</i> dealing with this crap when I used linux&#8230;  but I digress.</p>
	<p>So first off, I think &#8220;Hey, I can add some magic to the CFLAGS parameter, and it&#8217;ll just compile!&#8221; &#8230; hahaha &#8230; I wish.  Here&#8217;s what happens:</p>
	<pre class="code">
cwright@phendrana:~/Desktop/Recent Source Stuff/libSomeLib-X.Y.Z>CFLAGS=\"-Os -fomit-frame-pointer -arch i386 -arch ppc -arch x86_64 -arch ppc64\" ./configure --enable-shared
</pre>
	<p>Configure does its thing, and then says it&#8217;s done and you&#8217;re ready to build.  It&#8217;s lying, of course:</p>
	<pre class="code">
cwright@phendrana:~/Desktop/Recent Source Stuff/libSomeLib-X.Y.Z>make
make  all-recursive
Making all in libSomeLib
/bin/sh ../libtool --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -I..    -Os -fomit-frame-pointer -arch i386 -arch ppc -arch x86_64 -arch ppc64 -MT io.lo -MD -MP -MF .deps/io.Tpo -c -o io.lo io.c
 gcc -DHAVE_CONFIG_H -I. -I.. -I.. -Os -fomit-frame-pointer -arch i386 -arch ppc -arch x86_64 -arch ppc64 -MT io.lo -MD -MP -MF .deps/io.Tpo -c io.c  -fno-common -DPIC -o .libs/io.o
gcc-4.0: -E, -S, -save-temps and -M options are not allowed with multiple -arch flags
make[2]: *** [io.lo] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2
</pre>
	<p>So, -M options aren&#8217;t allowed to have multiple arch flags, says gcc.  I do some spelunking to find out exactly what these flags do, and find that they&#8217;re for creating Makefile dependencies.  But wait a minute, isn&#8217;t that Configure&#8217;s job?  Man these build tools are awesome. &#8230;  (technically speaking, it <i>is</i> Make&#8217;s job to make this stuff.  There just isn&#8217;t a hook to add architecture support anywhere else without completely re-engineering the build system.)</p>
	<p>Next up, I read some Apple documentation to see how they go about doing it (for stuff like OpenSSL, etc.).  They recommend making a new XCode project, and then making a <a href="http://developer.apple.com/opensource/images/AllTargets.cropped.jpg">zillion build targets</a>, taped together with some <a href="http://developer.apple.com/opensource/images/BuildPPCScript.cropped.jpg">shell scripts</a>.  To be honest, it doesn&#8217;t seem very Apple-like.  If I&#8217;m going to be dealing with shell scripts, I&#8217;ll just do it myself in Terminal.</p>
	<p>The second attempt consists of duplicating the source tree into 4 directories, one for each architecture.  Then, my plan goes, I&#8217;ll use <code>lipo</code> to glue them all together into a fat binary, and I&#8217;ll be on my way.</p>
	<p>I run configure in each directory tree, careful to include only one <code>-arch</code> parameter in each one.  I issue make in the i386, ppc, and x86_64 trees without issue, and start to think a bit smugly to myself that I&#8217;ve defeated this silly monster.  But then, another Configure Dragon charges.</p>
	<pre class="code">
cwright@phendrana:~/Desktop/Recent Source Stuff/libSomeLib-X.Y.Z-ppc64>CFLAGS=\"-Os -fomit-frame-pointer -arch ppc64\" ./configure --enable-shared
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
/bin/sh: /Users/cwright/Desktop/Recent: No such file or directory
configure: WARNING: `missing' script is too old or missing
checking for a thread-safe mkdir -p... ./install-sh -c -d
checking for gawk... no
checking for mawk... no
checking for nawk... no
checking for awk... awk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... configure: error: cannot run C compiled programs.
If you meant to cross compile, use `--host'.
See `config.log' for more details.
</pre>
	<p>Of course, whenever configure tells you to check &#8220;config.log&#8221; for more details, it&#8217;s about as informative as reading a <a href="http://www.thecybersource.com/images/bsod.jpg">Blue Screen</a>.  Also, note the 4th or 5th line, which shows a lack of quoted paths.  That looks safe&#8230;</p>
	<p>The problem, according to configure, is that it &#8220;cannot run C compiled programs,&#8221; which is actually accurate for this case:  Rosette doesn&#8217;t translate ppc64 binaries to x86.  However, gcc can compile such programs, so we know we can do it.  Configure suggests using the &#8220;-<nop />-host&#8221; command.</p>
	<p>Running configure with -<nop />-help reveals how -<nop />-host is supposed to be used.  It&#8217;ll look like this, I suppose:  &#8220;-<nop />-host=ppc64&#8243;.</p>
	<p>It issues this warning, but continues to do its thing:</p>
	<pre class="code">
configure: WARNING: In the future, Autoconf will not detect cross-tools
whose name does not start with the host triplet.  If you think this
configuration is useful to you, please write to autoconf@gnu.org.
</pre>
	<p>I hope that&#8217;s ok.. ?</p>
	<p>I run make, and it builds, and finishes.  A bit earlier than the others.  In the .libs directory, there&#8217;s no .dylib, which is what &#8211;enable-shared is supposed to create.  So, I look at the output from previous builds, and copy the line it inexplicably skips.  It&#8217;s a pretty long, but simple gcc line that takes all the .o&#8217;s and makes them into a .dylib.  No idea why it skipped over that one&#8230;</p>
	<p>And at last, we&#8217;re able to build our fat binary using lipo.  Hurray for portable cross-platform build tools!
</p>
]]></content:encoded>
			<wfw:commentRSS>http://fdiv.net/2007/12/19/zero-grams-of-trans-fat-binaries/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>iPhoto-Thunderbird Bridge</title>
		<link>http://fdiv.net/2007/08/22/iphoto-thunderbird-bridge/</link>
		<comments>http://fdiv.net/2007/08/22/iphoto-thunderbird-bridge/#comments</comments>
		<pubDate>Wed, 22 Aug 2007 11:59:11 +0000</pubDate>
		<dc:creator>cwright</dc:creator>
		
	<category>softpixel</category>
	<category>Apple</category>
	<category>Not Apple</category>
	<category>Software Development</category>
	<category>Photography</category>
	<category>Kosada</category>
		<guid>http://fdiv.net/2007/08/22/iphoto-thunderbird-bridge/</guid>
		<description><![CDATA[	For years, iPhoto users have been stuck using a limited number of email clients to send their photos easily.  This was mostly remedied by the iPhoto Mailer Patcher, but it left out non-applescript aware applications because, after all, iPhoto uses applescript to interface with them.  One of the more notable omissions is Thunderbird.
	Finally, [...]]]></description>
			<content:encoded><![CDATA[	<p><img align="right" alt="iPhoto logo" src="http://img.b33p.net/pub/HK0-oPRuL9-u_9Wz5KxycaakqUdEXdfI" />For years, iPhoto users have been stuck using a limited number of email clients to send their photos easily.  This was mostly remedied by the <a href="http://homepage.mac.com/jacksim/software/imp403.html">iPhoto Mailer Patcher</a>, but it left out non-applescript aware applications because, after all, iPhoto uses applescript to interface with them.  One of the more notable omissions is Thunderbird.</p>
	<p>Finally, this void has also been filled, via the <a href="http://softpixel.com/~cwright/programming/iPhoto/">iPhoto Thunderbird Bridge</a>.  It&#8217;s still quite primitive, but all the basics are there for iPhoto-Thunderbird integration.</p>
	<p>If you&#8217;re an iPhoto/Thunderbird user, give it a whirl.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://fdiv.net/2007/08/22/iphoto-thunderbird-bridge/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>Leaky NSSpeechSynthesizer</title>
		<link>http://fdiv.net/2007/07/23/leaky-nsspeechsynthesizer/</link>
		<comments>http://fdiv.net/2007/07/23/leaky-nsspeechsynthesizer/#comments</comments>
		<pubDate>Mon, 23 Jul 2007 22:34:24 +0000</pubDate>
		<dc:creator>cwright</dc:creator>
		
	<category>Antisocial Story</category>
	<category>Apple</category>
	<category>Not Apple</category>
	<category>Software Development</category>
		<guid>http://fdiv.net/2007/07/23/leaky-nsspeechsynthesizer/</guid>
		<description><![CDATA[	NSSpeechSynthesizer, the Cocoa class responsible for giving applications a voice under OS X, is leaky.  Creating and destroying thousands of instances of this class slowly consumes all the available memory in a system, leading to degrading performance and eventual application instability.
	The disappointing part is that this bug was first noticed almost two years ago. [...]]]></description>
			<content:encoded><![CDATA[	<p>NSSpeechSynthesizer, the Cocoa class responsible for giving applications a voice under OS X, is leaky.  Creating and destroying thousands of instances of this class slowly consumes all the available memory in a system, leading to degrading performance and eventual application instability.</p>
	<p>The disappointing part is that this bug was <a href="http://www.cocoabuilder.com/archive/message/cocoa/2005/12/20/152921">first noticed</a> almost two years ago.  <a id="more-106"></a>While the extent isn&#8217;t nearly as bad, it&#8217;s still not clean.</p>
	<p>This bug came up in our Speech Synthesizer patch for Quartz Composer, featured at <a href="http://kineme.net/QuartzComposerPatches/SpeechSynthesisPatch">kineme</a>.  After much testing, profiling, and refactoring, a splendidly small demonstration program emerged.</p>
	<pre class="code">
#import &lt;Cocoa/Cocoa.h&gt;
	
int main()
{
        while(1)
        {
                NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
                NSSpeechSynthesizer *speech = [[NSSpeechSynthesizer alloc] init];
                [speech release];
                [pool release];
        }
	
        return 0;
}
</pre>
	<p>This program endlessly allocates an NSAutoreleasePool, used for memory management,  and then an NSSpeechSynthesizer object.  After creating them, it destroys them.  Destroying the synthesizer object should free any associated memory with the object, and releasing the pool should free up any odds and ends left over, just in case.</p>
	<p>Reality paints a much more disappointing picture:</p>
	<pre class="code">cwright@phendrana:~/projects/SpeechTest>./rapid
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Segmentation fault
</pre>
	<p>It starts off looking ok.  It spins for about 15 seconds or so, but then trouble strikes.  As you an see, the class starts to have difficulty mapping a voice file (this is only mentioned once in all of Google&#8217;s wisdom, with no useful insight as to what it means), and eventually the inevitable crash occurs.</p>
	<p>smokris tried this on his MacBook Pro..  Same thing there:</p>
	<pre class="code">
smokris@etu 6 ~/Desktop -> time ./a.out
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Speech Synthesis can't map voice file (12)
Segmentation fault
	
real    0m4.479s
user    0m0.286s
sys     0m0.153s
</pre>
]]></content:encoded>
			<wfw:commentRSS>http://fdiv.net/2007/07/23/leaky-nsspeechsynthesizer/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>Announcing: kineme.net</title>
		<link>http://fdiv.net/2007/07/10/announcing-kinemenet/</link>
		<comments>http://fdiv.net/2007/07/10/announcing-kinemenet/#comments</comments>
		<pubDate>Tue, 10 Jul 2007 22:24:30 +0000</pubDate>
		<dc:creator>cwright</dc:creator>
		
	<category>Social Story</category>
	<category>kineme</category>
	<category>Interactive Media</category>
	<category>Quartz Composer</category>
	<category>Software Development</category>
		<guid>http://fdiv.net/2007/07/10/announcing-kinemenet/</guid>
		<description><![CDATA[	The Kineme Quartz Composer patches now have a proper home at http://kineme.net/, including forums, bug reports, comments, and feature requests &#8212; complete with voting!
	Along with the new site, a few new patches are available as well based on requests from users.

]]></description>
			<content:encoded><![CDATA[	<p><img align="right" src="http://img.b33p.net/pub/0xk3_shbAp63pte73kN2cEqQU7h_WlFM/thumbnail-256" alt="screenshot of kineme.net" />The Kineme Quartz Composer patches now have a proper home at <a href="http://kineme.net/">http://kineme.net/</a>, including forums, bug reports, comments, and feature requests &#8212; complete with voting!</p>
	<p>Along with the new site, a <a href="http://kineme.net/QuartzComposerPatches/ImageDownloaderBlockingPatch">few</a> <a href="http://kineme.net/QuartzComposerPatches/ShellCommandPatch">new</a> <a href="http://kineme.net/QuartzComposerPatches/SpeechSynthesisPatch">patches</a> are available as well based on requests from users.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://fdiv.net/2007/07/10/announcing-kinemenet/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>NSURLConnection&#8217;s sendSynchronousRequest enforces minimum 30 second timeout?</title>
		<link>http://fdiv.net/2007/07/10/nsurlconnection-sendsynchronousrequest-enforces-minimum-30-second-timeout/</link>
		<comments>http://fdiv.net/2007/07/10/nsurlconnection-sendsynchronousrequest-enforces-minimum-30-second-timeout/#comments</comments>
		<pubDate>Tue, 10 Jul 2007 21:47:58 +0000</pubDate>
		<dc:creator>smokris</dc:creator>
		
	<category>Apple</category>
	<category>Software Development</category>
		<guid>http://fdiv.net/2007/07/10/nsurlconnection-sendsynchronousrequest-enforces-minimum-30-second-timeout/</guid>
		<description><![CDATA[	While writing the new Image Downloader (Blocking) QC patch for CoreMelt, I ran into what appears to be a bug in Mac OS X&#8217;s NSURLConnection framework &#8212;  if you construct an NSURLRequest and specify a timeout of less than 30 seconds, it&#8217;s ignored when you perform a [NSURLConnection sendSynchronousRequest:returningResponse:error:].  The request takes at [...]]]></description>
			<content:encoded><![CDATA[	<p>While writing the new <a href="http://kineme.net/QuartzComposerPatches/ImageDownloaderBlockingPatch">Image Downloader (Blocking) QC patch</a> for <a href="http://coremelt.com/">CoreMelt</a>, I ran into what appears to be a bug in Mac OS X&#8217;s NSURLConnection framework &#8212;  if you construct an NSURLRequest and specify a timeout of less than 30 seconds, it&#8217;s ignored when you perform a <code>[NSURLConnection sendSynchronousRequest:returningResponse:error:]</code>.  The request takes at least 30 seconds to time out, contrary to what the documentation suggests..</p>
	<p>Steps to Reproduce:<a id="more-105"></a></p>
	<ol>
	<li>Construct an NSURL with an http-based url pointing to a server that is currently offline.</li>
	<li>Execute the following code block:<br />
	<pre class="code">
NSLog(@&quot;begin&quot;);
NSURLRequest *request=[NSURLRequest
    requestWithURL:url
    cachePolicy:NSURLRequestReloadIgnoringCacheData
    timeoutInterval:5.0];
NSData *data=[NSURLConnection
    sendSynchronousRequest:request
    returningResponse:&#038;response
    error:&#038;error];
NSLog(@&quot;end&quot;);</pre>
</li>
	<li>Compare the timestamps of &#8220;begin&#8221; and &#8220;end&#8221;.  though they should presumably differ by 5 seconds, they actually differ by exactly 30 seconds.</li>
	</ol>
	<p>Any ideas?
</p>
]]></content:encoded>
			<wfw:commentRSS>http://fdiv.net/2007/07/10/nsurlconnection-sendsynchronousrequest-enforces-minimum-30-second-timeout/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>Data Integrity: Resurrection</title>
		<link>http://fdiv.net/2007/07/10/data-integrity-resurrection-jpeg-flash-recovery-from-digital-camera/</link>
		<comments>http://fdiv.net/2007/07/10/data-integrity-resurrection-jpeg-flash-recovery-from-digital-camera/#comments</comments>
		<pubDate>Tue, 10 Jul 2007 21:35:06 +0000</pubDate>
		<dc:creator>cwright</dc:creator>
		
	<category>Antisocial Story</category>
	<category>Software Development</category>
	<category>Photography</category>
		<guid>http://fdiv.net/2007/07/10/data-integrity-resurrection-jpeg-flash-recovery-from-digital-camera/</guid>
		<description><![CDATA[	Faced with a need to recover images from Robert&#8217;s camera after a defective card-reader nuked the filesystem superblock, a quick utility came to mind.  Nuked superblocks mean no file allocation table.  It means no metadata.  But it does not mean no data.
	
	Target medium: 1GB XD card from a digital camera.
	Data to recover: [...]]]></description>
			<content:encoded><![CDATA[	<p><img align="right" src="http://img.b33p.net/pub/qSINxwo6ypJug1meo_-J-LmXjVURmPko/thumbnail-256" alt="flame sign" />Faced with a need to recover images from Robert&#8217;s camera after a defective card-reader nuked the filesystem superblock, a quick utility came to mind.  Nuked superblocks mean no file allocation table.  It means no metadata.  But it does not mean <em>no</em> data.</p>
	<ul>
	<li>Target medium: 1GB XD card from a digital camera.</li>
	<li>Data to recover: JPEGs.  Lots of them.</li>
	</ul>
	<p>Whipping out some jpeg-format-and-filesystem-jutsu, here&#8217;s the solution (for less than that $20 shareware recovery utility):<br />
<a id="more-96"></a><br />
Step one: Create a disk image of the card.<br />
<code>sudo dd if=/dev/disk2 of=~/Desktop/roberts.xd.card.image bs=1048576</code></p>
	<p>Step two: Create a utility to extract JPEGs.</p>
	<pre class="code" style="height: 20em; overflow: scroll;">
#include &lt;stdio.h>
#include &lt;stdlib.h>
#include &lt;fcntl.h>
	
#include &lt;sys/types.h>
#include &lt;sys/stat.h>
#include &lt;sys/mman.h>
	
#include &lt;unistd .h>
	
int main(int argc, char**argv)
{
        int file, filesize, i, j;
        int outfile=0, outfilenum = 0;
        int blocksWritten = 0;
        char outname[42];
        unsigned char *data;
        struct stat fileStat;
	
        if(stat(argv[1],&#038;fileStat))
        {
                printf(&quot;Couldn't stat file!\n&quot;);
                return -1;
        }
	
        file = open(argv[1],O_RDONLY);
	
        if(!file)
        {
                printf(&quot;Couldn't open file!\n&quot;);
                return -1;
        }
	
        filesize = fileStat.st_size;
        if(fileStat.st_size % getpagesize())
        {
                // if we're unaligned, we add the difference to pad up.
                filesize = fileStat.st_size + (getpagesize() - (fileStat.st_size % getpagesize()));
        }
	
        printf(&quot;mmapping %i bytes...\n&quot;,filesize);
	
        data = mmap(0,filesize,PROT_READ,MAP_PRIVATE,file,0);
	
        if(data == -1)
        {
                printf(&quot;Couldn't mmap file...\n&quot;);
                perror(&quot;mmap&quot;);
                return -1;
        }
	
        printf(&quot;Scanning %i blocks for jpegs...\n&quot;,filesize/1024);
	
        j = 0; // found count
        outfile = -1;
        for(i=0;i &lt; (fileStat.st_size/1024);++i)
        {
                if(data[i*1024 + 0] == 0xff &#038;&#038; // SOI (Start of Image) Tag
                   data[i*1024 + 1] == 0xd8 &#038;&#038; //
                   data[i*1024 + 2] == 0xff &#038;&#038; // APP1 (Application 1; exif) Tag
                   data[i*1024 + 3] == 0xe1) //
                {
                        printf(&quot;Probable jpeg at block %i (#%i)\n&quot;,i,j++);
                        if(outfile != -1)
                        {
                                close(outfile);
                                outfile = -1;
                        }
                        snprintf(outname, 42,&quot;recovered.%i.jpg&quot;,outfilenum++);
                        outfile = open(outname,O_RDWR|O_CREAT,0666);
                        write(outfile,data+i*1024,1024);
                        blocksWritten = 1;
                }
                else // non-header block.  write it if we're in a file
                {
                        // write another block.  stop at 4096 blocks (4MB jpegs)
                        if(outfile != -1 &#038;&#038; outfile > 2)
                        {
                                write(outfile,data+i*1024,1024);
                                ++blocksWritten;
                                if(blocksWritten >= 4096)
                                {
                                        close(outfile);
                                        outfile = -1;
                                        blocksWritten = 0;
                                }
                        }
                }
	
                // for progress view
                if( (i%10000) == 0 &#038;&#038; i)
                {
                        printf(&quot;block %i...\n&quot;,i);
                }
        }
	
        return 0;
}
</pre>
	<p>Step three: compile it.  Since we&#8217;re dealing with huge images and I was lazy and used <code>mmap</code>, we need to make it a 64-bit binary.  To do this, we simply run <code>gcc -m64 main.c -o main</code> and we&#8217;re in business.</p>
	<p>Step four: run and enjoy</p>
	<pre class="code" style="height: 10em; overflow: scroll;">
cwright@phendrana:~/projects/getjpeg>./main ~/Desktop/roberts.xd.card.image
mmapping 1048481792 bytes...
Scanning 1023908 blocks for jpegs...
Probable jpeg at block 1632 (#0)
Probable jpeg at block 2864 (#1)
Probable jpeg at block 4208 (#2)
Probable jpeg at block 5424 (#3)
Probable jpeg at block 6640 (#4)
Probable jpeg at block 7840 (#5)
Probable jpeg at block 8976 (#6)
block 10000...
Probable jpeg at block 10224 (#7)
Probable jpeg at block 11488 (#8)
Probable jpeg at block 12768 (#9)
Probable jpeg at block 14192 (#10)
Probable jpeg at block 15520 (#11)
Probable jpeg at block 16880 (#12)
Probable jpeg at block 17760 (#13)
Probable jpeg at block 19024 (#14)
block 20000...
Probable jpeg at block 20208 (#15)
Probable jpeg at block 21408 (#16)
Probable jpeg at block 22608 (#17)
Probable jpeg at block 23840 (#18)
Probable jpeg at block 24976 (#19)
Probable jpeg at block 26128 (#20)
Probable jpeg at block 27296 (#21)
Probable jpeg at block 28432 (#22)
Probable jpeg at block 29584 (#23)
block 30000...
Probable jpeg at block 30720 (#24)
Probable jpeg at block 31968 (#25)
Probable jpeg at block 33056 (#26)
Probable jpeg at block 34272 (#27)
Probable jpeg at block 35456 (#28)
Probable jpeg at block 36720 (#29)
Probable jpeg at block 38000 (#30)
Probable jpeg at block 39120 (#31)
block 40000...
Probable jpeg at block 40336 (#32)
Probable jpeg at block 41488 (#33)
Probable jpeg at block 42800 (#34)
Probable jpeg at block 44064 (#35)
Probable jpeg at block 45312 (#36)
Probable jpeg at block 46528 (#37)
Probable jpeg at block 47648 (#38)
Probable jpeg at block 48864 (#39)
Probable jpeg at block 49984 (#40)
block 50000...
Probable jpeg at block 51088 (#41)
Probable jpeg at block 52192 (#42)
Probable jpeg at block 53280 (#43)
Probable jpeg at block 54416 (#44)
Probable jpeg at block 55536 (#45)
Probable jpeg at block 56480 (#46)
Probable jpeg at block 57488 (#47)
Probable jpeg at block 58448 (#48)
Probable jpeg at block 59360 (#49)
block 60000...
Probable jpeg at block 60352 (#50)
Probable jpeg at block 61040 (#51)
Probable jpeg at block 61808 (#52)
Probable jpeg at block 62736 (#53)
Probable jpeg at block 63472 (#54)
Probable jpeg at block 64256 (#55)
Probable jpeg at block 65072 (#56)
Probable jpeg at block 66016 (#57)
Probable jpeg at block 66832 (#58)
Probable jpeg at block 67680 (#59)
Probable jpeg at block 68368 (#60)
Probable jpeg at block 69168 (#61)
block 70000...
Probable jpeg at block 70016 (#62)
Probable jpeg at block 70736 (#63)
Probable jpeg at block 71504 (#64)
Probable jpeg at block 72688 (#65)
Probable jpeg at block 73776 (#66)
Probable jpeg at block 74960 (#67)
Probable jpeg at block 76016 (#68)
Probable jpeg at block 77040 (#69)
Probable jpeg at block 78176 (#70)
Probable jpeg at block 79248 (#71)
block 80000...
Probable jpeg at block 80400 (#72)
Probable jpeg at block 81504 (#73)
Probable jpeg at block 82640 (#74)
Probable jpeg at block 83840 (#75)
Probable jpeg at block 84752 (#76)
Probable jpeg at block 85664 (#77)
Probable jpeg at block 86560 (#78)
Probable jpeg at block 87552 (#79)
Probable jpeg at block 88528 (#80)
Probable jpeg at block 89456 (#81)
block 90000...
Probable jpeg at block 90416 (#82)
Probable jpeg at block 91392 (#83)
Probable jpeg at block 92384 (#84)
Probable jpeg at block 93312 (#85)
Probable jpeg at block 94400 (#86)
Probable jpeg at block 95536 (#87)
Probable jpeg at block 96688 (#88)
Probable jpeg at block 97824 (#89)
Probable jpeg at block 98832 (#90)
Probable jpeg at block 99824 (#91)
block 100000...
Probable jpeg at block 100656 (#92)
Probable jpeg at block 101520 (#93)
Probable jpeg at block 102624 (#94)
Probable jpeg at block 103776 (#95)
Probable jpeg at block 104880 (#96)
Probable jpeg at block 105952 (#97)
Probable jpeg at block 107056 (#98)
Probable jpeg at block 108208 (#99)
Probable jpeg at block 109472 (#100)
block 110000...
Probable jpeg at block 110672 (#101)
Probable jpeg at block 111824 (#102)
Probable jpeg at block 112976 (#103)
Probable jpeg at block 114096 (#104)
Probable jpeg at block 115296 (#105)
Probable jpeg at block 116384 (#106)
Probable jpeg at block 117584 (#107)
Probable jpeg at block 118704 (#108)
Probable jpeg at block 119888 (#109)
block 120000...
Probable jpeg at block 120864 (#110)
Probable jpeg at block 122016 (#111)
Probable jpeg at block 123216 (#112)
Probable jpeg at block 124352 (#113)
Probable jpeg at block 125408 (#114)
Probable jpeg at block 126480 (#115)
Probable jpeg at block 127536 (#116)
Probable jpeg at block 128752 (#117)
Probable jpeg at block 129952 (#118)
block 130000...
Probable jpeg at block 131104 (#119)
Probable jpeg at block 132192 (#120)
Probable jpeg at block 133264 (#121)
Probable jpeg at block 134416 (#122)
Probable jpeg at block 135568 (#123)
Probable jpeg at block 136784 (#124)
Probable jpeg at block 138016 (#125)
Probable jpeg at block 139264 (#126)
block 140000...
Probable jpeg at block 140496 (#127)
Probable jpeg at block 141168 (#128)
Probable jpeg at block 141952 (#129)
Probable jpeg at block 142912 (#130)
Probable jpeg at block 143856 (#131)
Probable jpeg at block 144944 (#132)
Probable jpeg at block 146000 (#133)
Probable jpeg at block 147056 (#134)
Probable jpeg at block 148272 (#135)
Probable jpeg at block 149504 (#136)
block 150000...
Probable jpeg at block 150672 (#137)
Probable jpeg at block 151888 (#138)
Probable jpeg at block 153120 (#139)
Probable jpeg at block 154352 (#140)
Probable jpeg at block 155648 (#141)
Probable jpeg at block 156944 (#142)
Probable jpeg at block 158192 (#143)
Probable jpeg at block 159472 (#144)
block 160000...
Probable jpeg at block 160768 (#145)
Probable jpeg at block 162016 (#146)
Probable jpeg at block 163264 (#147)
Probable jpeg at block 164480 (#148)
Probable jpeg at block 165760 (#149)
Probable jpeg at block 167008 (#150)
Probable jpeg at block 168272 (#151)
Probable jpeg at block 169536 (#152)
block 170000...
Probable jpeg at block 170800 (#153)
Probable jpeg at block 172224 (#154)
Probable jpeg at block 173456 (#155)
Probable jpeg at block 174704 (#156)
Probable jpeg at block 175936 (#157)
Probable jpeg at block 177184 (#158)
Probable jpeg at block 178432 (#159)
Probable jpeg at block 179712 (#160)
block 180000...
Probable jpeg at block 180992 (#161)
Probable jpeg at block 182240 (#162)
Probable jpeg at block 183568 (#163)
Probable jpeg at block 184976 (#164)
Probable jpeg at block 186288 (#165)
Probable jpeg at block 187744 (#166)
Probable jpeg at block 189104 (#167)
block 190000...
Probable jpeg at block 190512 (#168)
Probable jpeg at block 191792 (#169)
Probable jpeg at block 193184 (#170)
Probable jpeg at block 194496 (#171)
Probable jpeg at block 195776 (#172)
Probable jpeg at block 197136 (#173)
Probable jpeg at block 198512 (#174)
Probable jpeg at block 199808 (#175)
block 200000...
Probable jpeg at block 201088 (#176)
Probable jpeg at block 202352 (#177)
Probable jpeg at block 203664 (#178)
Probable jpeg at block 204992 (#179)
Probable jpeg at block 206304 (#180)
Probable jpeg at block 207504 (#181)
Probable jpeg at block 208816 (#182)
block 210000...
Probable jpeg at block 210144 (#183)
Probable jpeg at block 211472 (#184)
Probable jpeg at block 212832 (#185)
Probable jpeg at block 214240 (#186)
Probable jpeg at block 215632 (#187)
Probable jpeg at block 217056 (#188)
Probable jpeg at block 218416 (#189)
Probable jpeg at block 219808 (#190)
block 220000...
Probable jpeg at block 221072 (#191)
Probable jpeg at block 222400 (#192)
Probable jpeg at block 223808 (#193)
Probable jpeg at block 225232 (#194)
Probable jpeg at block 226576 (#195)
Probable jpeg at block 227888 (#196)
Probable jpeg at block 229296 (#197)
block 230000...
Probable jpeg at block 230560 (#198)
Probable jpeg at block 231904 (#199)
Probable jpeg at block 233216 (#200)
Probable jpeg at block 234544 (#201)
Probable jpeg at block 235920 (#202)
Probable jpeg at block 237216 (#203)
Probable jpeg at block 238528 (#204)
Probable jpeg at block 239888 (#205)
block 240000...
Probable jpeg at block 241232 (#206)
Probable jpeg at block 242512 (#207)
Probable jpeg at block 243904 (#208)
Probable jpeg at block 245280 (#209)
Probable jpeg at block 246592 (#210)
Probable jpeg at block 247952 (#211)
Probable jpeg at block 249328 (#212)
block 250000...
Probable jpeg at block 250672 (#213)
Probable jpeg at block 252000 (#214)
Probable jpeg at block 253264 (#215)
Probable jpeg at block 254608 (#216)
Probable jpeg at block 255904 (#217)
Probable jpeg at block 257200 (#218)
Probable jpeg at block 258480 (#219)
Probable jpeg at block 260000 (#220)
block 260000...
Probable jpeg at block 261504 (#221)
Probable jpeg at block 262896 (#222)
Probable jpeg at block 264320 (#223)
Probable jpeg at block 265744 (#224)
Probable jpeg at block 267120 (#225)
Probable jpeg at block 268592 (#226)
block 270000...
Probable jpeg at block 270064 (#227)
Probable jpeg at block 271488 (#228)
Probable jpeg at block 272912 (#229)
Probable jpeg at block 274400 (#230)
Probable jpeg at block 275936 (#231)
Probable jpeg at block 277360 (#232)
Probable jpeg at block 278800 (#233)
block 280000...
Probable jpeg at block 280176 (#234)
Probable jpeg at block 281712 (#235)
Probable jpeg at block 283200 (#236)
Probable jpeg at block 284688 (#237)
Probable jpeg at block 286016 (#238)
Probable jpeg at block 287552 (#239)
Probable jpeg at block 288992 (#240)
block 290000...
Probable jpeg at block 290544 (#241)
Probable jpeg at block 292000 (#242)
Probable jpeg at block 293440 (#243)
Probable jpeg at block 294800 (#244)
Probable jpeg at block 296208 (#245)
Probable jpeg at block 297472 (#246)
Probable jpeg at block 298720 (#247)
block 300000...
Probable jpeg at block 300080 (#248)
Probable jpeg at block 301504 (#249)
Probable jpeg at block 302784 (#250)
Probable jpeg at block 304064 (#251)
Probable jpeg at block 305008 (#252)
Probable jpeg at block 306016 (#253)
Probable jpeg at block 306976 (#254)
Probable jpeg at block 307984 (#255)
Probable jpeg at block 309216 (#256)
block 310000...
Probable jpeg at block 310592 (#257)
Probable jpeg at block 311888 (#258)
Probable jpeg at block 313152 (#259)
Probable jpeg at block 314352 (#260)
Probable jpeg at block 315664 (#261)
Probable jpeg at block 317024 (#262)
Probable jpeg at block 318272 (#263)
Probable jpeg at block 319568 (#264)
block 320000...
Probable jpeg at block 320928 (#265)
Probable jpeg at block 322176 (#266)
Probable jpeg at block 323568 (#267)
Probable jpeg at block 324800 (#268)
Probable jpeg at block 325984 (#269)
Probable jpeg at block 327232 (#270)
Probable jpeg at block 328480 (#271)
Probable jpeg at block 329776 (#272)
block 330000...
Probable jpeg at block 331088 (#273)
Probable jpeg at block 332320 (#274)
Probable jpeg at block 333616 (#275)
Probable jpeg at block 334912 (#276)
Probable jpeg at block 336256 (#277)
Probable jpeg at block 337648 (#278)
Probable jpeg at block 338880 (#279)
block 340000...
Probable jpeg at block 340208 (#280)
Probable jpeg at block 341264 (#281)
Probable jpeg at block 342272 (#282)
Probable jpeg at block 343552 (#283)
Probable jpeg at block 344832 (#284)
Probable jpeg at block 346080 (#285)
Probable jpeg at block 346992 (#286)
Probable jpeg at block 348368 (#287)
Probable jpeg at block 349760 (#288)
block 350000...
Probable jpeg at block 351168 (#289)
Probable jpeg at block 352448 (#290)
Probable jpeg at block 353760 (#291)
Probable jpeg at block 355136 (#292)
Probable jpeg at block 356368 (#293)
Probable jpeg at block 357712 (#294)
Probable jpeg at block 359040 (#295)
block 360000...
Probable jpeg at block 360464 (#296)
Probable jpeg at block 361808 (#297)
Probable jpeg at block 363200 (#298)
Probable jpeg at block 364144 (#299)
Probable jpeg at block 365488 (#300)
Probable jpeg at block 366752 (#301)
Probable jpeg at block 367808 (#302)
Probable jpeg at block 368848 (#303)
Probable jpeg at block 369856 (#304)
block 370000...
Probable jpeg at block 371072 (#305)
Probable jpeg at block 372272 (#306)
Probable jpeg at block 373568 (#307)
Probable jpeg at block 374864 (#308)
Probable jpeg at block 376144 (#309)
Probable jpeg at block 377504 (#310)
Probable jpeg at block 378512 (#311)
Probable jpeg at block 379824 (#312)
block 380000...
Probable jpeg at block 381120 (#313)
Probable jpeg at block 382320 (#314)
block 390000...
block 400000...
block 410000...
block 420000...
block 430000...
block 440000...
block 450000...
block 460000...
block 470000...
block 480000...
block 490000...
block 500000...
block 510000...
block 520000...
block 530000...
block 540000...
block 550000...
block 560000...
block 570000...
block 580000...
block 590000...
block 600000...
block 610000...
block 620000...
block 630000...
block 640000...
block 650000...
block 660000...
block 670000...
block 680000...
block 690000...
block 700000...
block 710000...
block 720000...
block 730000...
block 740000...
block 750000...
block 760000...
block 770000...
block 780000...
block 790000...
block 800000...
block 810000...
block 820000...
block 830000...
block 840000...
block 850000...
block 860000...
block 870000...
block 880000...
block 890000...
block 900000...
block 910000...
block 920000...
block 930000...
block 940000...
block 950000...
block 960000...
block 970000...
block 980000...
block 990000...
block 1000000...
block 1010000...
block 1020000...
</pre>
	<p>Yay, images from yesterday: Recovered.</p>
	<p>Take it down, flip it, and reverse it.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://fdiv.net/2007/07/10/data-integrity-resurrection-jpeg-flash-recovery-from-digital-camera/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>How to make Pop-Up Menus in Custom Quartz Composer Patches</title>
		<link>http://fdiv.net/2007/07/05/pop-up-menus-in-custom-quartz-composer-patches/</link>
		<comments>http://fdiv.net/2007/07/05/pop-up-menus-in-custom-quartz-composer-patches/#comments</comments>
		<pubDate>Thu, 05 Jul 2007 18:26:27 +0000</pubDate>
		<dc:creator>smokris</dc:creator>
		
	<category>Quartz Composer</category>
	<category>Apple</category>
	<category>Software Development</category>
		<guid>http://fdiv.net/2007/07/05/pop-up-menus-in-custom-quartz-composer-patches/</guid>
		<description><![CDATA[	Making pop-up menus in custom Quartz Composer patches is actually surprisingly easy.
	 This release is only compatible with Tiger (10.4).Please see kineme.net for Leopard-specific informations.
	1.  Set up a QCIndexPort input.  QCIndexPorts provide values from 0 to whatever max you specify using - (void)setMaxIndexValue:(unsigned int)max;.

	
@interface IndexPortPopUpDemoPatch : QCPatch
{
    QCIndexPort *inputPerson;
}
	
...
	
@end

	2.  [...]]]></description>
			<content:encoded><![CDATA[	<p><img align="right" src="http://img.b33p.net/pub/rdbO8vsyz_OYqrtRiObQF5xTYQzJqYES/png-indexed-64" alt="screenshot of a custom Quartz Composer patch's pop-up menu" />Making pop-up menus in custom Quartz Composer patches is actually surprisingly easy.</p>
	<div class="notice"><img src="/wp-content/themes/alternate0/stop.png" /> This release is only compatible with Tiger (10.4).<br />Please see <a href="http://kineme.net/Leopard">kineme.net</a> for Leopard-specific informations.</div>
	<p>1.  Set up a QCIndexPort input.  QCIndexPorts provide values from 0 to whatever max you specify using <code>- (void)setMaxIndexValue:(unsigned int)max;</code>.<br />
<a id="more-102"></a></p>
	<pre class="code">
@interface IndexPortPopUpDemoPatch : QCPatch
{
    QCIndexPort *inputPerson;
}
	
...
	
@end
</pre>
	<p>2.  Add the &#8220;menu&#8221; key to the port&#8217;s input attributes:</p>
	<pre class="code">
	&lt;key&gt;inputAttributes&lt;/key&gt;
	&lt;dict&gt;
		&lt;key&gt;inputPerson&lt;/key&gt;
		&lt;dict&gt;
			&lt;key&gt;description&lt;/key&gt;
			&lt;string&gt;Person&lt;/string&gt;
			&lt;key&gt;name&lt;/key&gt;
			&lt;string&gt;Person&lt;/string&gt;
			&lt;key&gt;menu&lt;/key&gt;
			&lt;array&gt;
				&lt;string&gt;Arthur Dent&lt;/string&gt;
				&lt;string&gt;Ford Prefect&lt;/string&gt;
				&lt;string&gt;Zaphod Beeblebrox&lt;/string&gt;
				&lt;string&gt;Marvin&lt;/string&gt;
				&lt;string&gt;Trillian&lt;/string&gt;
				&lt;string&gt;Slartibartfast&lt;/string&gt;
				&lt;string&gt;Agrajag&lt;/string&gt;
				&lt;string&gt;Wonko the Sane&lt;/string&gt;
			&lt;/array&gt;
		&lt;/dict&gt;
	&lt;/dict&gt;
</pre>
	<p>3.  Make sure you set the max index value in the <code>initWithIdentifier</code> function:</p>
	<pre class="code">
- (id)initWithIdentifier:(id)fp8
{
        id z=[super initWithIdentifier:fp8];
	
        [inputPerson setMaxIndexValue:7];
	
        return z;
}
</pre>
	<p>4.  Read the value out of the QCIndexPort using <code>- (unsigned int)indexValue;</code>.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://fdiv.net/2007/07/05/pop-up-menus-in-custom-quartz-composer-patches/feed/</wfw:commentRSS>
	</item>
	</channel>
</rss>
