<?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>...cwbowron...</title>
	<atom:link href="http://www.bowron.us/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.bowron.us</link>
	<description>Nerd Stuff</description>
	<lastBuildDate>Wed, 01 Sep 2010 13:41:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Playlist: Duet Chain</title>
		<link>http://www.bowron.us/?p=488</link>
		<comments>http://www.bowron.us/?p=488#comments</comments>
		<pubDate>Wed, 01 Sep 2010 13:41:45 +0000</pubDate>
		<dc:creator>cwbowron</dc:creator>
				<category><![CDATA[Life]]></category>

		<guid isPermaLink="false">http://www.bowron.us/?p=488</guid>
		<description><![CDATA[<p>As I mentioned in the previous post, I had also thought about putting together a duet chain playlist.  I went through with it and it has some good tracks on it.  You may notice that a bit of a genre change around track 6.</p>
<p>As an added bonus and using a little creativity, I [...]]]></description>
			<content:encoded><![CDATA[<p>As I mentioned in the previous post, I had also thought about putting together a duet chain playlist.  I went through with it and it has some good tracks on it.  You may notice that a bit of a genre change around track 6.</p>
<p>As an added bonus and using a little creativity, I was again able to make a loop.  The last track links the second to last track with the first.</p>
<p><center><br />
<a href="http://content.screencast.com/users/cwbowron/folders/Jing/media/41ed9b63-29da-4e14-94a6-235a62d2538d/2010-09-01_0935.png"><img class="embeddedObject" src="http://content.screencast.com/users/cwbowron/folders/Jing/media/41ed9b63-29da-4e14-94a6-235a62d2538d/2010-09-01_0935.png" width="736" height="257" border="0" /></a><br />
</center></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bowron.us/?feed=rss2&amp;p=488</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Playlist: Cover Song Chain</title>
		<link>http://www.bowron.us/?p=481</link>
		<comments>http://www.bowron.us/?p=481#comments</comments>
		<pubDate>Tue, 31 Aug 2010 14:15:50 +0000</pubDate>
		<dc:creator>cwbowron</dc:creator>
				<category><![CDATA[Life]]></category>

		<guid isPermaLink="false">http://www.bowron.us/?p=481</guid>
		<description><![CDATA[<p>I&#8217;ve had the idea for a while for a couple playlists.  One was to be a duet chain where it started with a duet with A &#038; B and the next song was a song with B &#038; C, then C &#038; D, etc.  My other idea was to try to do a [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had the idea for a while for a couple playlists.  One was to be a duet chain where it started with a duet with A &#038; B and the next song was a song with B &#038; C, then C &#038; D, etc.  My other idea was to try to do a playlist of cover songs.  So the first song is a artist A covering artist B, then the next song is artist B covering artist C, etc.</p>
<p>Yesterday I put together a cover song chain playlist.  It&#8217;s got some good stuff on it, and as an added bonus, the last song in the playlist is a cover version of the first artist, so it&#8217;s a loop.  It&#8217;s also under 80 minutes so it would fit on a CD.</p>
<p>There are two potentially questionable links.  I counted Prince&#8217;s version of Nothing Compares 2 U as a cover of Sinead O&#8217;Connor&#8217;s version even though he wrote it. Also, &#8220;Love the One You&#8217;re With&#8221; is technically a Stephen Stills solo song, but I followed it with a Crosby, Stills and Nash song.  I&#8217;ve seen CSN in concert and they played it, so I&#8217;m going to allow it.</p>
<p><center><br />
<a href="http://content.screencast.com/users/cwbowron/folders/Jing/media/c1a7dcfc-29a5-4913-a365-45917a424c8b/Cover%20Song%20Chain.png"><img class="embeddedObject" src="http://content.screencast.com/users/cwbowron/folders/Jing/media/c1a7dcfc-29a5-4913-a365-45917a424c8b/Cover%20Song%20Chain.png" width="654" height="371" border="0" /></a><br />
</center></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bowron.us/?feed=rss2&amp;p=481</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fireworks!</title>
		<link>http://www.bowron.us/?p=475</link>
		<comments>http://www.bowron.us/?p=475#comments</comments>
		<pubDate>Tue, 24 Aug 2010 12:33:31 +0000</pubDate>
		<dc:creator>cwbowron</dc:creator>
				<category><![CDATA[Life]]></category>

		<guid isPermaLink="false">http://www.bowron.us/?p=475</guid>
		<description><![CDATA[<p>We went to the Tigers game on Saturday with many people from TechSmith and their guests.  We stayed for the fireworks after the game.  A good time was had by all.</p>
<p>Below is an excerpt of the fireworks show.


</p>
]]></description>
			<content:encoded><![CDATA[<p>We went to the Tigers game on Saturday with many people from TechSmith and their guests.  We stayed for the fireworks after the game.  A good time was had by all.</p>
<p>Below is an excerpt of the fireworks show.<br />
<center><br />
<object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/fP0vux0b-T0?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/fP0vux0b-T0?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object><br />
</center></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bowron.us/?feed=rss2&amp;p=475</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Toronto</title>
		<link>http://www.bowron.us/?p=469</link>
		<comments>http://www.bowron.us/?p=469#comments</comments>
		<pubDate>Wed, 18 Aug 2010 15:02:23 +0000</pubDate>
		<dc:creator>cwbowron</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[toronto]]></category>
		<category><![CDATA[vacation]]></category>

		<guid isPermaLink="false">http://www.bowron.us/?p=469</guid>
		<description><![CDATA[<p>In May, Janelle and I went to Toronto for a vacation.  I forgot to post the video here.  Toronto is very, very expensive.  Especially with the weakened exchange rate.  I think excluding hotel rates, Toronto was more expensive than New York.</p>
<p>

</p>
]]></description>
			<content:encoded><![CDATA[<p>In May, Janelle and I went to Toronto for a vacation.  I forgot to post the video here.  Toronto is very, very expensive.  Especially with the weakened exchange rate.  I think excluding hotel rates, Toronto was more expensive than New York.</p>
<p><center><br />
<object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/1MahvLeNONY?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/1MahvLeNONY?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object><br />
</center></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bowron.us/?feed=rss2&amp;p=469</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Racket [Scheme] / Cocoa Glue – Part IV</title>
		<link>http://www.bowron.us/?p=463</link>
		<comments>http://www.bowron.us/?p=463#comments</comments>
		<pubDate>Wed, 18 Aug 2010 14:00:05 +0000</pubDate>
		<dc:creator>cwbowron</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[racket]]></category>
		<category><![CDATA[unit test]]></category>

		<guid isPermaLink="false">http://www.bowron.us/?p=463</guid>
		<description><![CDATA[<p>As promised, here&#8217;s my current unit tests for my Racket / cocoa glue code.  It&#8217;s just tests for my conversion code.</p>

#lang racket

(require rackunit
         &#34;cocoa-glue.rkt&#34;
         ffi/unsafe
         ffi/unsafe/objc)

(test-case
 &#34;string-&#62;NSString and back&#34;
 (let [...]]]></description>
			<content:encoded><![CDATA[<p>As promised, here&#8217;s my current unit tests for my Racket / cocoa glue code.  It&#8217;s just tests for my conversion code.</p>
<pre class="brush: cpp;">
#lang racket

(require rackunit
         &quot;cocoa-glue.rkt&quot;
         ffi/unsafe
         ffi/unsafe/objc)

(test-case
 &quot;string-&gt;NSString and back&quot;
 (let ([strings (list &quot;1&quot; &quot;two&quot; &quot;◻&quot; &quot;◻◾&quot; &quot;◻five◾&quot;)])
   (for ((s strings))
     (let ([converted-string (string-&gt;NSString s)])
       (check-not-equal? s converted-string)
       (check-equal? s (NSString-&gt;string converted-string))))))

(test-case
 &quot;list-&gt;NSArray&quot;
 (let* ([strings (list &quot;a&quot; &quot;b&quot; &quot;c&quot;)]
        [foreign-strings (map string-&gt;NSString strings)]
        [ns-array (list-&gt;NSArray foreign-strings)])
   (check-equal? (NSArray-length ns-array)
                 (length strings))
   (for ((i (in-naturals))
         (string strings))
     (check-equal?
      string
      (NSString-&gt;string
       (NSArray-ref ns-array i))))))

(test-case
 &quot;list-&gt;NSArray-&gt;list&quot;
 (let ([strings (list &quot;1&quot; &quot;two&quot; &quot;◻◾◻&quot;)])
   (check-equal?
    strings
    (map NSString-&gt;string
         (NSArray-&gt;list
          (list-&gt;NSArray
           (map string-&gt;NSString strings)))))))

(define-simple-check (check-dict/NSDictionary-equiv? dict NSDict)
  (check-equal? (tell-int32 NSDict count)
                (dict-count dict))
    (for (((k dict-value) (in-dict dict)))
      (let ([NSDict-value (tell NSDict objectForKey: (string-&gt;NSString k))])
        (check-equal?
         (NSString-&gt;string dict-value)
         (NSString-&gt;string NSDict-value)))))

(let* ([keys (list &quot;a&quot; &quot;b&quot; &quot;c&quot;)]
       [string-values (list &quot;1&quot; &quot;2&quot; &quot;3&quot;)]
       [foreign-values (map string-&gt;NSString string-values)]
       [alist (map cons keys foreign-values)])
  (test-case
   &quot;dictionary-&gt;NSDictionary&quot;
   (check-dict/NSDictionary-equiv?
    alist
    (dictionary-&gt;NSDictionary alist)))
  (test-case
   &quot;dictionary-&gt;NSMutableDictionary&quot;
   (check-dict/NSDictionary-equiv?
    alist
    (dictionary-&gt;NSMutableDictionary alist))))
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.bowron.us/?feed=rss2&amp;p=463</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Racket [Scheme] / Cocoa Glue – Part III</title>
		<link>http://www.bowron.us/?p=456</link>
		<comments>http://www.bowron.us/?p=456#comments</comments>
		<pubDate>Tue, 17 Aug 2010 14:03:12 +0000</pubDate>
		<dc:creator>cwbowron</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[racket]]></category>

		<guid isPermaLink="false">http://www.bowron.us/?p=456</guid>
		<description><![CDATA[<p>For the third installment of my glue code between Cocoa and Racket, here is some data type conversion code.  It&#8217;s all in Racket, using the Objective-C FFI.   It includes conversions for strings to NSString and back, as well as converting between lists and NSArray and Racket dictionaries to NSDictionary and NSMutableDictionary.  [...]]]></description>
			<content:encoded><![CDATA[<p>For the third installment of my glue code between Cocoa and Racket, here is some data type conversion code.  It&#8217;s all in Racket, using the Objective-C FFI.   It includes conversions for strings to NSString and back, as well as converting between lists and NSArray and Racket dictionaries to NSDictionary and NSMutableDictionary.  Also included are some helper functions for accessing NSArrays.</p>
<p>Next installment will be my unit tests for this code, so get excited.</p>
<p>cocoa-glue-data-types.rkt:</p>
<pre class="brush: cpp;">
#lang racket

(provide (all-defined-out))

(require ffi/unsafe
         ffi/unsafe/objc
         ffi/cvector)

(import-class NSString)
(import-class NSArray)
(import-class NSDictionary)
(import-class NSMutableDictionary)

(define-syntax-rule (define-typed-tell fn-id type-id)
  (define-syntax-rule (fn-id obj msg (... ...))
    (tell #:type type-id obj msg (... ...))))

(define-typed-tell tell-int32  _int32)
(define-typed-tell tell-string _string)

(define (objC-tagged p)
  (unless (cpointer-has-tag? p 'id)
    (cpointer-push-tag! p 'id))
  p)

(define (string-&gt;NSString str)
  (tell NSString stringWithUTF8String: #:type _string str))

(define (NSString-&gt;string ns-string)
  (tell-string ns-string UTF8String))

(define (cvector-&gt;NSArray vec)
  (tell NSArray
        arrayWithObjects: #:type _pointer (cvector-ptr vec)
        count: #:type _int32 (cvector-length vec)))

(define (list-&gt;NSArray lst #:type (type _pointer))
  (let ([vec (list-&gt;cvector lst type)])
    (cvector-&gt;NSArray vec)))

(define (NSArray-length ar)
  (tell-int32 ar count))

(define (NSArray-ref ar n)
  (tell ar objectAtIndex: #:type _int32 n))

(define (NSArray-&gt;list array)
  (for/list ((n (in-range (NSArray-length array))))
    (NSArray-ref array n)))

(define (dict-keys dict)
  (dict-map dict (lambda (k v) k)))

(define (dict-values dict)
  (dict-map dict (lambda (k v) v)))

(define (dictionary-&gt;NSDictionary dict)
  (tell NSDictionary
        dictionaryWithObjects: (list-&gt;NSArray (dict-values dict))
        forKeys: (list-&gt;NSArray
                  (map string-&gt;NSString (dict-keys dict)))))

(define (dictionary-&gt;NSMutableDictionary d)
  (let ([mutable (tell NSMutableDictionary dictionaryWithCapacity: #:type _int32 (dict-count d))])
    (for (((key value) (in-dict d)))
      (tell mutable
            setObject: value
            forKey: (string-&gt;NSString key)))
    mutable))
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.bowron.us/?feed=rss2&amp;p=456</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Racket [Scheme] / Cocoa Glue – Part II</title>
		<link>http://www.bowron.us/?p=449</link>
		<comments>http://www.bowron.us/?p=449#comments</comments>
		<pubDate>Mon, 16 Aug 2010 19:18:30 +0000</pubDate>
		<dc:creator>cwbowron</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[glue]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[racket]]></category>

		<guid isPermaLink="false">http://www.bowron.us/?p=449</guid>
		<description><![CDATA[<p>Part two of my enthralling posts about working with Cocoa from Racket.</p>
<p>Below is more of the code from the C / Objective-C library.  You will notice that I use a couple of macros to deal with the NSAutoReleasePools.  It&#8217;s potentially too clever for it&#8217;s own good.  This code deals with opening video [...]]]></description>
			<content:encoded><![CDATA[<p>Part two of my enthralling posts about working with Cocoa from Racket.</p>
<p>Below is more of the code from the C / Objective-C library.  You will notice that I use a couple of macros to deal with the NSAutoReleasePools.  It&#8217;s potentially too clever for it&#8217;s own good.  This code deals with opening video files for reading, writing, adding frames and exporting to h.264.  It also includes a function for getting the contents of the current opengl texture as an NSImage.</p>
<pre class="brush: cpp;">
#define POOL_START() NSAutoreleasePool *GENSYM00 = [[NSAutoreleasePool alloc] init]
#define POOL_DRAIN() [GENSYM00 drain]
#define WITH_POOL(type, f) { POOL_START(); type v = f; POOL_DRAIN(); return v;}
#define WITH_POOL_VOID(f)  { POOL_START(); f; POOL_DRAIN(); }

extern NSImage * glue_get_viewport_NSImage()
{
   GLint viewPort[4];
   glGetIntegerv( GL_VIEWPORT, viewPort );

   int width   = viewPort[2];
   int height  = viewPort[3];

   NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc]
                             initWithBitmapDataPlanes:nil
                             pixelsWide: width
                             pixelsHigh: height
                             bitsPerSample:8
                             samplesPerPixel:4
                             hasAlpha:YES
                             isPlanar:NO
                             colorSpaceName:NSCalibratedRGBColorSpace
                             bytesPerRow:0
                             bitsPerPixel:0] autorelease];

   glReadBuffer( GL_FRONT );
	glReadPixels( 0, 0, width, height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, [rep bitmapData] );
   NSImage * image = glue_NSBitmapImageRep_to_NSImage( rep );
   [image setFlipped:YES];
   // need this to actually flip image?
   [image lockFocusOnRepresentation:rep];
   [image unlockFocus];
   return image;
}

extern void * glue_quicktime_movie_open_write( const char * outputFile )
{
   WITH_POOL( QTMovie*, [[QTMovie alloc]
                         initToWritableFile: [NSString stringWithUTF8String: outputFile]
                         error: NULL] );
}

extern void * glue_quicktime_movie_open_read( const char * inputFile )
{
   WITH_POOL( QTMovie*, ([[QTMovie alloc]
                         initWithAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
                                              [NSString stringWithUTF8String: inputFile],
                                              QTMovieFileNameAttribute,
                                              NO, QTMovieOpenAsyncOKAttribute,
                                              nil]
                         error: nil]) );
}

extern void glue_quicktime_movie_set_current_time( QTMovie * movie, long timeValue, long timeScale )
{
   [movie setCurrentTime: QTMakeTime( timeValue, timeScale)];
}

extern NSImage * glue_quicktime_movie_get_current_frame( QTMovie * movie )
{
   return [movie currentFrameImage];
}

extern long glue_quicktime_movie_get_duration( QTMovie * movie )
{
   QTTime t = [movie duration];
   return (1000 * t.timeValue) / t.timeScale;
}

extern void glue_quicktime_movie_write( QTMovie * movie )
{
   [movie updateMovieFile];
}

extern void glue_quicktime_movie_add_frame( QTMovie * movie, NSImage * img,
                                           int length, int lengthScale )
{
   [movie addImage: img
       forDuration: QTMakeTime(length, lengthScale)
    withAttributes: [NSDictionary dictionaryWithObject: @&quot;tiff&quot;
                                                forKey: QTAddImageCodecType]];
}

extern void glue_quicktime_movie_add_frame_current( QTMovie * movie, int length, int lengthScale )
{
   WITH_POOL_VOID( glue_quicktime_movie_add_frame( movie,
                                                  glue_get_viewport_NSImage(),
                                                  length, lengthScale ) );
}

extern void glue_quicktime_movie_export_mp4_264( QTMovie * movie, const char * filePath )
{
   WITH_POOL_VOID ( ([movie writeToFile: [NSString stringWithUTF8String: filePath]
                         withAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
                                          [NSNumber numberWithBool:YES], QTMovieExport,
                                          [NSNumber numberWithLong:'M4VH'], QTMovieExportType, nil]] ) );
}
</pre>
<p>Here&#8217;s the pertinent pieces of the FFI interface for Racket:</p>
<pre class="brush: cpp;">
(define-glue glue-quicktime-movie-open-write : _string -&gt; _pointer)
(define-glue glue-quicktime-movie-open-read : _string -&gt; _pointer)
(define-glue glue-quicktime-movie-get-duration : _pointer -&gt; _int32)
(define-glue glue-quicktime-movie-set-current-time : _pointer _int32 _int32 -&gt; _void)
(define-glue glue-quicktime-movie-get-current-frame : _pointer -&gt; _pointer)
(define-glue glue-quicktime-movie-add-frame : _pointer _pointer _int32 _int32 -&gt; _void)
(define-glue glue-quicktime-movie-write : _pointer -&gt; _void)
(define-glue glue-quicktime-movie-add-frame-current : _pointer _int32 _int32 -&gt; _void)
(define-glue glue-quicktime-movie-export-mp4-264 : _pointer _string -&gt; _void)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.bowron.us/?feed=rss2&amp;p=449</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Canoeing!</title>
		<link>http://www.bowron.us/?p=443</link>
		<comments>http://www.bowron.us/?p=443#comments</comments>
		<pubDate>Mon, 16 Aug 2010 15:45:47 +0000</pubDate>
		<dc:creator>cwbowron</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[Canoeing]]></category>

		<guid isPermaLink="false">http://www.bowron.us/?p=443</guid>
		<description><![CDATA[<p>Back in July, we went canoeing on the mighty Grand River with our friends Bill and Rhonda.  I forgot to share the video at the time, so here it is:</p>
<p>

</p>
]]></description>
			<content:encoded><![CDATA[<p>Back in July, we went canoeing on the mighty Grand River with our friends Bill and Rhonda.  I forgot to share the video at the time, so here it is:</p>
<p><center><br />
<object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/a43lfewl-_w?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/a43lfewl-_w?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object><br />
</center></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bowron.us/?feed=rss2&amp;p=443</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Racket [Scheme] / Cocoa Glue</title>
		<link>http://www.bowron.us/?p=433</link>
		<comments>http://www.bowron.us/?p=433#comments</comments>
		<pubDate>Fri, 13 Aug 2010 17:55:10 +0000</pubDate>
		<dc:creator>cwbowron</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[glue]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[racket]]></category>

		<guid isPermaLink="false">http://www.bowron.us/?p=433</guid>
		<description><![CDATA[<p>I&#8217;ve been working on some video apps in Racket on my Mac, but I want to use some of the OSX features like Core Image Filters and QTKit.  Racket has really good foreign function interface to both C and Objective-C, but a few things fall through the cracks.  For example, it does not [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on some video apps in Racket on my Mac, but I want to use some of the OSX features like Core Image Filters and QTKit.  Racket has really good foreign function interface to both C and Objective-C, but a few things fall through the cracks.  For example, it does not seem possible to pass a structure on the stack from Racket into Objective-C, which is required for a number of the image and video related APIs.  Some other things are just easier to write in Objective-C.  So I&#8217;ve been working on a library that makes some of these things easier.</p>
<p>My library consists of three pieces.  An Objective-C library with a C interface, a Racket FFI interface to that library, and some Racket wrappers around Objective-C to make the interface simpler.  Here&#8217;s some pieces.</p>
<p>Below is the Objective-C code for the C Interface for some image conversion routines.  The most useful piece of this is the conversion routines from CIImage to NSImage and back, which are useful when using the Core Image Filters.</p>
<pre class="brush: plain;">
extern int glue_image_width( NSImage * img )
{
   return [img size].width;
}

extern int glue_image_height( NSImage * img )
{
   return [img size].height;
}

extern GLuint glue_NSBitmapImageRep_to_texture( NSBitmapImageRep * rep )
{
   GLuint targetTexture;

   glGenTextures( 1, &amp;targetTexture );
   int width            = [rep pixelsWide];
   int height           = [rep pixelsHigh];
   GLenum format        = [rep hasAlpha] ? GL_RGBA : GL_RGB;
   int numPixelsInRow   = [rep bytesPerRow] / ([rep bitsPerPixel] &gt;&gt; 3);

   GLenum target = GL_TEXTURE_RECTANGLE_EXT;
   glBindTexture( target, targetTexture );

   glPixelStorei(GL_UNPACK_ROW_LENGTH, numPixelsInRow); 

   glTexImage2D( target, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_BYTE, [rep bitmapData] );
   glTexParameterf( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
   glTexParameterf( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
   return targetTexture;
}

extern NSBitmapImageRep * glue_NSImage_to_NSBitmapImageRep( NSImage * img )
{
   return [NSBitmapImageRep imageRepWithData: [img TIFFRepresentation]];
}

extern CIImage * glue_NSImage_to_CIImage( NSImage * ns )
{
   NSBitmapImageRep * rep = glue_NSImage_to_NSBitmapImageRep( ns );

   return [[[CIImage alloc]
            initWithBitmapImageRep: rep] autorelease];
}

extern NSImage * glue_CIImage_to_NSImage( CIImage * ci )
{
   int width   = [ci extent].size.width;
   int height  = [ci extent].size.height;

   NSImage * img = [[[NSImage alloc] initWithSize: NSMakeSize(width,height)] autorelease];
   [img lockFocus];
   [[[NSGraphicsContext currentContext] CIContext]
    drawImage: ci
    atPoint: CGPointMake( 0,0 )
    fromRect: [ci extent]];
   [img unlockFocus];
   return img;
}
</pre>
<p>The Racket FFI definitions for the above functions:</p>
<pre class="brush: plain;">
(provide (all-defined-out))

(require ffi/unsafe)
(require ffi/unsafe/define)

(define glue-lib (ffi-lib &quot;./cocoa-glue/build/Debug/cocoa-glue&quot;))

(define-syntax define-glue
  (syntax-rules (:)
    [(_ name : type ...)
     (define name
       (get-ffi-obj
        (regexp-replaces 'name '((#rx&quot;-&quot; &quot;_&quot;)))
        glue-lib (_fun type ...)))]))

(define-glue glue-image-width : _pointer -&gt; _int32)
(define-glue glue-image-height : _pointer -&gt; _int32)
(define-glue glue-CIImage-to-NSImage : _pointer -&gt; _pointer)
(define-glue glue-NSImage-to-CIImage : _pointer -&gt; _pointer)
(define-glue glue-NSBitmapImageRep-to-texture : _pointer -&gt; _uint32)
(define-glue glue-NSImage-to-NSBitmapImageRep : _pointer -&gt; _pointer)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.bowron.us/?feed=rss2&amp;p=433</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Deer!</title>
		<link>http://www.bowron.us/?p=423</link>
		<comments>http://www.bowron.us/?p=423#comments</comments>
		<pubDate>Fri, 13 Aug 2010 12:49:41 +0000</pubDate>
		<dc:creator>cwbowron</dc:creator>
				<category><![CDATA[Life]]></category>

		<guid isPermaLink="false">http://www.bowron.us/?p=423</guid>
		<description><![CDATA[<p>A couple weeks ago, we awoke on Saturday morning to find 4 deer in our backyard.  They stuck around for about half an hour and I was able to record some of it on my Flip.</p>
<p>

</p>
]]></description>
			<content:encoded><![CDATA[<p>A couple weeks ago, we awoke on Saturday morning to find 4 deer in our backyard.  They stuck around for about half an hour and I was able to record some of it on my Flip.</p>
<p><center><br />
<object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/BaOJIudEOWU?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/BaOJIudEOWU?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object><br />
</center></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bowron.us/?feed=rss2&amp;p=423</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
