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

<channel>
	<title>jonathanwatmough.com</title>
	<atom:link href="http://jonathanwatmough.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://jonathanwatmough.com</link>
	<description>Jonathan</description>
	<pubDate>Fri, 25 Jul 2008 03:29:09 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Rome Vacation</title>
		<link>http://jonathanwatmough.com/2008/07/rome-vacation/</link>
		<comments>http://jonathanwatmough.com/2008/07/rome-vacation/#comments</comments>
		<pubDate>Fri, 25 Jul 2008 03:08:38 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
		
		<category><![CDATA[Photography]]></category>

		<guid isPermaLink="false">http://jonathanwatmough.com/?p=230</guid>
		<description><![CDATA[I finally got round to posting up some of my photography from our vacation in Rome in 2007. We had a fantastic time in Rome, and saw lots of wonderful sights. I hope you enjoy some of the pictures!
Included in Day 1 is pictures of our rented apartment, and the Colliseum.

Meredith at the Colliseum

Included in [...]]]></description>
			<content:encoded><![CDATA[<p>I finally got round to posting up some of my photography from our vacation in Rome in 2007. We had a fantastic time in Rome, and saw lots of wonderful sights. I hope you enjoy some of the pictures!</p>
<p>Included in <a href="http://www.shutterfly.com/pro/JWatmough/Rome/RomeDay1">Day 1</a> is pictures of our rented apartment, and the Colliseum.</p>
<p><a href="http://jonathanwatmough.com/wp-content/uploads/2008/07/rome-day-1-7.jpg"><img class="alignnone size-thumbnail wp-image-231" title="Meredith at the Colliseum" src="http://jonathanwatmough.com/wp-content/uploads/2008/07/rome-day-1-7-150x150.jpg" alt="Meredith at the Colliseum" width="150" height="150" /><br />
<strong>Meredith at the Colliseum</strong><br />
</a></p>
<p>Included in <a title="Rome Day 2" href="http://www.shutterfly.com/pro/JWatmough/Rome/RomeDay2">Day 2</a> is pictures of The Holy Father, and art at the Vatican Museum.</p>
<p><a href="http://jonathanwatmough.com/wp-content/uploads/2008/07/rome-day-2-1_lq.jpg"><strong></strong></a></p>
<p><a href="http://jonathanwatmough.com/wp-content/uploads/2008/07/rome-day-2-1_lq.jpg"><img class="alignnone size-thumbnail wp-image-232" title="St Peter\'s Basilica" src="http://jonathanwatmough.com/wp-content/uploads/2008/07/rome-day-2-1_lq-150x150.jpg" alt="St Peter\'s Basilica" width="150" height="150" /><br />
<strong>St Peter&#8217;s Basilica</strong></a><a href="http://jonathanwatmough.com/wp-content/uploads/2008/07/rome-day-2-1_lq.jpg"><br />
</a></p>
<p>Included in <a href="http://www.shutterfly.com/pro/JWatmough/Rome/RomeDay3">Day 3</a> is pictures of the interior of Basilica of St Peter.</p>
<p><a href="http://jonathanwatmough.com/wp-content/uploads/2008/07/rome-day-3-5_lq.jpg"><img class="alignnone size-thumbnail wp-image-233" title="Interior of St Peter\'s Basilica" src="http://jonathanwatmough.com/wp-content/uploads/2008/07/rome-day-3-5_lq-150x150.jpg" alt="Interior of St Peter\'s Basilica" width="150" height="150" /><br />
<strong>Interior of St Peter&#8217;s Basilica</strong></a><a href="http://jonathanwatmough.com/wp-content/uploads/2008/07/rome-day-2-1_lq.jpg"> </a></p>
<p>A link to all the pictures on <a href="http://www.shutterfly.com/pro/JWatmough/Rome">Shutterfly</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanwatmough.com/2008/07/rome-vacation/feed/</wfw:commentRss>
		</item>
		<item>
		<title>San Antonio</title>
		<link>http://jonathanwatmough.com/2008/07/san-antonio/</link>
		<comments>http://jonathanwatmough.com/2008/07/san-antonio/#comments</comments>
		<pubDate>Thu, 24 Jul 2008 00:02:22 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
		
		<category><![CDATA[Home Life]]></category>

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

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

		<guid isPermaLink="false">http://jonathanwatmough.com/?p=228</guid>
		<description><![CDATA[For our wedding anniversary this year, we visited San Antonio.
Some pictures from the trip are online at Shutterfly.

I also made a nice picture of The Alamo at night, which can be seen here.
Buy a Print of The Alamo.
]]></description>
			<content:encoded><![CDATA[<p>For our wedding anniversary this year, we visited San Antonio.</p>
<p>Some pictures from the trip are online at <a href="http://www.shutterfly.com/pro/JWatmough/SanAntonio/SanAntonio" target="_self">Shutterfly</a>.</p>
<p><a href="http://www.shutterfly.com/pro/JWatmough/SanAntonio/TheAlamo"><img class="alignnone size-medium wp-image-229" title="The Alamo San Antonio" src="http://jonathanwatmough.com/wp-content/uploads/2008/07/dsc_3751-300x199.jpg" alt="The Alamo San Antonio" width="193" height="128" /></a></p>
<p>I also made a nice picture of The Alamo at night, which can be seen here.</p>
<p><a title="Buy a print of the Alamo" href="http://www.shutterfly.com/pro/JWatmough/SanAntonio/TheAlamo" target="_self">Buy a Print of The Alamo</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanwatmough.com/2008/07/san-antonio/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Butterfly Scans on Shutterfly</title>
		<link>http://jonathanwatmough.com/2008/07/butterfly-scans-on-shutterfly/</link>
		<comments>http://jonathanwatmough.com/2008/07/butterfly-scans-on-shutterfly/#comments</comments>
		<pubDate>Wed, 23 Jul 2008 02:26:22 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
		
		<category><![CDATA[Photography]]></category>

		<guid isPermaLink="false">http://jonathanwatmough.com/?p=226</guid>
		<description><![CDATA[I ran across some old scans of some butterfly pictures I&#8217;d done as a test of my Nikon F3, PK-13 macro attachment and Nikon SB-13 flash unit. Here is my very favorite image from this batch.

I&#8217;ve posted the full resolution scans up on Shutterfly who can fulfil print orders up to 20&#215;30&#8243; at very reasonable [...]]]></description>
			<content:encoded><![CDATA[<p>I ran across some old scans of some butterfly pictures I&#8217;d done as a test of my Nikon F3, PK-13 macro attachment and Nikon SB-13 flash unit. Here is my very favorite image from this batch.</p>
<p><a href="http://jonathanwatmough.com/wp-content/uploads/2008/07/scan05_1024.jpg"><img class="alignnone size-medium wp-image-227" title="scan05_1024" src="http://jonathanwatmough.com/wp-content/uploads/2008/07/scan05_1024-300x200.jpg" alt="You can buy me on Shutterfly!" width="210" height="140" /></a></p>
<p>I&#8217;ve posted the full resolution scans up on <a href="http://www.shutterfly.com/pro/JWatmough/Butterfly">Shutterfly</a> who can fulfil print orders up to 20&#215;30&#8243; at very reasonable cost.</p>
<p>I have some great photography sitting around in various boxes of slides and it&#8217;s about time some of it found a wider audience. I&#8217;m looking forward to catching up with some of my old pictures.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanwatmough.com/2008/07/butterfly-scans-on-shutterfly/feed/</wfw:commentRss>
		</item>
		<item>
		<title>iPhone Application Design: A Time Tracking App</title>
		<link>http://jonathanwatmough.com/2008/07/designing-an-iphone-time-tracking-app/</link>
		<comments>http://jonathanwatmough.com/2008/07/designing-an-iphone-time-tracking-app/#comments</comments>
		<pubDate>Sun, 13 Jul 2008 06:40:26 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
		
		<category><![CDATA[Computers and Software]]></category>

		<category><![CDATA[iPhone Development]]></category>

		<guid isPermaLink="false">http://jonathanwatmough.com/?p=224</guid>
		<description><![CDATA[Outline

It&#8217;s pretty hackneyed, but I could actually use a decent application for tracking my times and expenses on my iPhone. I work 9 - 10 hours a day, on various projects, and sometimes have to resort to looking at my sent and received emails to find out what I was actually doing.
Requirements
I have a fairly [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Outline<br />
</strong></p>
<p>It&#8217;s pretty hackneyed, but I could actually use a decent application for tracking my times and expenses on my iPhone. I work 9 - 10 hours a day, on various projects, and sometimes have to resort to looking at my sent and received emails to find out what I was actually doing.</p>
<p><strong>Requirements</strong></p>
<p>I have a fairly simple list of requirements for tracking time:</p>
<ul>
<li>Track time starting &#8216;now&#8217;</li>
<li>Track time against a project</li>
<li>Track time against a project task</li>
<li>Allow editing of billable time</li>
<li>Allow projects and tasks to be pre-populated</li>
<li>Associate a comment with billable time</li>
<li>Generate a simple report and email it</li>
</ul>
<p>Given these requirements, it looks like the most important aspect of the application is the ability to add new periods of billable time, and to view what you&#8217;ve recently worked on.</p>
<p><strong>Thoughts on Implementation</strong></p>
<p>Bearing in mind that this is an iPhone application, performance must be fast, and the user interface must be clear, clean and smooth.</p>
<p>Other features should include being able to view work by project, and setting up projects and tasks.</p>
<p>Non-features in a version 0.5, but which are probably work thinking about include the ability to generate and track an actual invoice.</p>
<p><strong>Doing a Mock-Up</strong></p>
<p>I haven&#8217;t seen much information on the web about how to design an iPhone application, so at least for me, I&#8217;m looking for a comfortable and lightweight way to pull the &#8216;feel&#8217; of an application together.</p>
<p>I started with Pencil software for Firefox, but it seemed clunky and difficult to use. Especially, the process and changing fonts, and laying out pieces of text seemed to be harder than necessary.</p>
<p>Next up and much more comfortable was the Apple presentation software Keynote. I was able to fairly quickly over the course of a couple of hours, distill the needed views and data down into a few screens.</p>
<p>The following shows what I ended up with.</p>
<p><a href="http://jonathanwatmough.com/wp-content/uploads/2008/07/picture-4.png"><img class="alignnone size-medium wp-image-225" title="iPhoneMockupTimeTracker" src="http://jonathanwatmough.com/wp-content/uploads/2008/07/picture-4-300x223.png" alt="iPhone Time Tracking App Mock-Up" width="300" height="223" /></a></p>
<p>This mock-up consists of just the regular Keynote text blocks in bold and regular 18 point text. It couldn&#8217;t really be much simpler, but I think it&#8217;s starting to look like a real application.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanwatmough.com/2008/07/designing-an-iphone-time-tracking-app/feed/</wfw:commentRss>
		</item>
		<item>
		<title>My New Dental Implants</title>
		<link>http://jonathanwatmough.com/2008/05/my-new-dental-implants/</link>
		<comments>http://jonathanwatmough.com/2008/05/my-new-dental-implants/#comments</comments>
		<pubDate>Fri, 16 May 2008 02:40:36 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
		
		<category><![CDATA[Home Life]]></category>

		<guid isPermaLink="false">http://jonathanwatmough.com/?p=223</guid>
		<description><![CDATA[I&#8217;ve been catching up on some dental treatment recently.
Today I got the first part of an implant procedure and now have two large titanium posts embedded in my lower jaw.
Once these get sufficiently attached to my jaw bone, essentially grafted in, they will get two crowns built up on top of them. This should stop [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been catching up on some dental treatment recently.</p>
<p>Today I got the first part of an implant procedure and now have two large titanium posts embedded in my lower jaw.</p>
<p>Once these get sufficiently attached to my jaw bone, essentially grafted in, they will get two crowns built up on top of them. This should stop worse things happening in the rest of my jaw.</p>
<p>Next week is the first appointment for a bunch more general work that will catch up on some the other problems.</p>
<p>You can google for dental implants to see a lot of scary pictures. I glad my teeth aren&#8217;t that bad.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanwatmough.com/2008/05/my-new-dental-implants/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Simple SparkLine Generator in Clojure</title>
		<link>http://jonathanwatmough.com/2008/02/simple-sparkline-generator-in-clojure/</link>
		<comments>http://jonathanwatmough.com/2008/02/simple-sparkline-generator-in-clojure/#comments</comments>
		<pubDate>Thu, 28 Feb 2008 04:47:55 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
		
		<category><![CDATA[Clojure]]></category>

		<category><![CDATA[Computers and Software]]></category>

		<guid isPermaLink="false">http://jonathanwatmough.com/?p=220</guid>
		<description><![CDATA[The following is a little SparkLine generator written in the Clojure language.
There&#8217;s an example in the code that covers the usage.
Please post a comment if you find it useful, or have suggestions. 
I have since updated this program. It should be pixel-perfect, and much more resistant to bad data.
Thanks Rich, for the comment below. I [...]]]></description>
			<content:encoded><![CDATA[<p>The following is a little SparkLine generator written in the <a href="http://clojure.sourceforge.net" title="Clojure">Clojure</a> language.</p>
<p>There&#8217;s an example in the code that covers the usage.</p>
<p>Please post a comment if you find it useful, or have suggestions. </p>
<p>I have since updated this program. It should be pixel-perfect, and much more resistant to bad data.</p>
<p>Thanks Rich, for the comment below. I have updated the main function to use destructuring bind on the function parameters.</p>
<p><a href="http://jonathanwatmough.com/wp-content/uploads/2008/03/sparkline.jpg" title="SparkLine"><img src="http://jonathanwatmough.com/wp-content/uploads/2008/03/sparkline.jpg" alt="SparkLine" /></a></p>
<pre>; Sparkline Generator
; Copyright (c) Jonathan A Watmough. All Rights Reserved.
;
; The use and distribution terms for this software are covered by the
; Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.txt).
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license. Do not remove this notice.
&nbsp;
(defn 
#^{ :doc &quot;Scale a list of numeric &#039;values&#039; to a max height of &#039;height&#039;.&quot;
&nbsp;&nbsp;&nbsp;&nbsp;:private true}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scale-values ([values height]
&nbsp;&nbsp;(let [highest (apply max (filter identity values))]
&nbsp;&nbsp;&nbsp;&nbsp;(map #(if % (dec (- height (/ (* % (- height 3)) highest))) nil) values))))
&nbsp;
(defn 
#^{:doc &quot;Make a Win-style java.awt.image.BufferedImage of &#039;width&#039; x &#039;height&#039;.&quot;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;make-buffered-image ([width height]
&nbsp;&nbsp;(let [image-type (. java.awt.image.BufferedImage TYPE_3BYTE_BGR)]
&nbsp;&nbsp;&nbsp;&nbsp;(new java.awt.image.BufferedImage width height image-type))))
&nbsp;
(defn 
#^{:doc &quot;Create pixel-accurate sparkline bitmap graphic from {:width :height :values :marker}. :marker=-1 for last entry.&quot;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;make-sparkline ([{ w :width h :height v :values m :marker }]
&nbsp;&nbsp;(let [v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (scale-values v h)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bitmap&nbsp;&nbsp;(make-buffered-image w h)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (. bitmap (getGraphics))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (if (and m (&lt; m 0)) (+ m (count v)) m)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;step&nbsp;&nbsp;&nbsp;&nbsp;(/ (- w 3) (- (count v) 1))]
&nbsp;&nbsp;&nbsp;&nbsp;(do (doto g (setColor (. java.awt.Color white))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fillRect 0 0 w h)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(setColor (. java.awt.Color gray)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(dotimes idx (count v)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [x-pos&nbsp;&nbsp;&nbsp;&nbsp;(inc (* idx step))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prev-val (nth v idx)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this-val (nth v (inc idx))]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when (and prev-val this-val)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (drawLine x-pos (dec prev-val) (+ x-pos step) (dec this-val))))))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; Draw marker if present and return the sparkline bitmap
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when (and m (nth v m))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [bx&nbsp;&nbsp;(* m step)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;by&nbsp;&nbsp;(- (nth v m) 2)]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(doto g (setColor (. java.awt.Color red))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fillOval bx by 2 2))))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (dispose))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bitmap))))
&nbsp;
(defn 
#^{:doc &quot;Test code for sparklines graphic generator.&quot;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test-sparklines []
&nbsp;&nbsp;(let [spark (make-sparkline {:width 100 :height 30 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:values [1 2 10 8 2 5 8 12 14 3 4 15]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:marker -1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;})
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;icon&nbsp;&nbsp;(new javax.swing.ImageIcon spark)]
&nbsp;&nbsp;&nbsp;&nbsp;(doto (new javax.swing.JFrame &quot;Sparkline Test&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(add (new javax.swing.JLabel icon))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(pack)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(setVisible true))))
&nbsp;
(test-sparklines)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://jonathanwatmough.com/2008/02/simple-sparkline-generator-in-clojure/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Prototyping Code in Clojure - A Simple Audio Displaying App</title>
		<link>http://jonathanwatmough.com/2008/02/prototyping-code-in-clojure/</link>
		<comments>http://jonathanwatmough.com/2008/02/prototyping-code-in-clojure/#comments</comments>
		<pubDate>Sun, 24 Feb 2008 22:39:59 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
		
		<category><![CDATA[Clojure]]></category>

		<category><![CDATA[Computers and Software]]></category>

		<guid isPermaLink="false">http://jonathanwatmough.com/?p=218</guid>
		<description><![CDATA[Clojure is a new Lisp, created by Rich Hickey. The primary portal to all things Clojure is here on Source Forge.
I just got through prototyping a little app that takes in sound samples, and displays a stacked series of frequency spectra, and a 2d &#8217;sonogram&#8217; type display. The running app looks like:

Not so easy to [...]]]></description>
			<content:encoded><![CDATA[<p>Clojure is a new Lisp, created by Rich Hickey. The primary portal to all things Clojure is <a href="http://clojure.sourceforge.net/">here</a> on Source Forge.</p>
<p>I just got through prototyping a little app that takes in sound samples, and displays a stacked series of frequency spectra, and a 2d &#8217;sonogram&#8217; type display. The running app looks like:</p>
<p><a href="http://jonathanwatmough.com/wp-content/uploads/2008/02/clojure-freq-spectra.jpg" title="Frequency Spectra in Clojure"><img src="http://jonathanwatmough.com/wp-content/uploads/2008/02/clojure-freq-spectra.thumbnail.jpg" alt="Frequency Spectra in Clojure" /></a></p>
<p>Not so easy to see, but the lower part of the screen is a 2d sonogram.</p>
<p>With the help of the KJ DSP library (which has a homepage on SourceForge), the app runs in real-ish time, and does a creditable job of displaying frequency spectra.</p>
<p>I hoped to try and get it running on Windows too, but the Java sampling api under Windows has defeated me for now. The code below works on a Mac Book Pro. Nothing else is tested.</p>
<p>The code is split into two main parts, which deal with getting sound samples, and with displaying a simple gui. I&#8217;ve reproduced the code below.</p>
<p>Note that this code isn&#8217;t complete, since I have a separate jar KJ.JAR which has the FFT code, and a NetBeans front end that provides isometric.gui (controls: start, stop, test:JButton, inputs:JCombobox, isopanel, sonopanel:JPanel).</p>
<pre>
; The following file is written by Jonathan Watmough
; This file is free for any use, providing this notice is preserved.
;
; This file works with the sound system on a Mac Book Pro.
; Nothing else is tested.
&nbsp;
; imports
(import &#039;(java.lang Thread))
(import &#039;(java.nio ByteBuffer ShortBuffer))
(import &#039;(javax.sound.sampled DataLine AudioSystem LineEvent LineListener AudioFormat))
;(import &#039;(javax.sound.sampled.DataLine Info))
&nbsp;
; supported audio filetypes
(def filetypes (. AudioSystem (getAudioFileTypes)))
(print (str &quot;Supported audio: &quot; (seq filetypes)))
(newline)
&nbsp;
; supported mixers
(def mixer-info (seq (. AudioSystem (getMixerInfo))))
&nbsp;
; get mixer-info, name, description of each mixer
(def mixer-info-list
&nbsp;&nbsp;(map #(let [m %] { :mixer-info m 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :name (. m (getName))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :description (. m (getDescription))}) mixer-info))
&nbsp;
; 
;&#45;&#45;&#45;- user interface &#45;&#45;&#45;-
&nbsp;
; create a desired pcm audio format
; -&gt; float sampleRate, int sampleSizeInBits, int channels, boolean signed, boolean bigEndian
(def format (new AudioFormat 44100 16 1 false true))
(def buffer-size (* 22050 2))&nbsp;&nbsp; ; 44k = 1/2 sec x 2 bytes / sample mono
&nbsp;
; set a ref for the open line
(def input (ref nil))
&nbsp;
; from each mixer-info, get the target data lines (inputs)
(def input-lines
&nbsp;&nbsp;(mapcat #(let [mix-info (:mixer-info %)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mixer&nbsp;&nbsp;&nbsp;&nbsp;(. AudioSystem (getMixer mix-info))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; targets&nbsp;&nbsp;(. mixer (getTargetLineInfo))]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(map #(let [target-info&nbsp;&nbsp;&nbsp;&nbsp; %
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get-line&nbsp;&nbsp;&nbsp;&nbsp;(fn[] 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [mixer (. AudioSystem (getMixer mix-info))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line&nbsp;&nbsp;(. mixer (getLine target-info))]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do (. line (open format buffer-size))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. line (start))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sync nil
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; ### should close old input - When @input &#46;..
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set input (. mixer (getLine target-info)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. @input (start))))))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mixer-name&nbsp;&nbsp;(. mix-info (getName))]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:mixer-name&nbsp;&nbsp;mixer-name
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :get-line&nbsp;&nbsp;&nbsp;&nbsp;get-line}) targets)) mixer-info-list))
&nbsp;
; get a set of samples for level-checking in ui
; assume we are dealing with signed 16 bit samples (short = 2 x bytes)
; may want to sync on &#039;input&#039;
(defn get-inst-samples ([num-samples]
&nbsp;&nbsp;(do 
&nbsp;&nbsp;&nbsp;&nbsp;(if (not (. @input (isOpen)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. @input (open format buffer-size)))
&nbsp;&nbsp;&nbsp;&nbsp;(if (not (. @input (isRunning)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. @input (start)))
&nbsp;&nbsp;&nbsp;&nbsp;(let [bytes&nbsp;&nbsp; (make-array (. Byte TYPE) (* 2 num-samples))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bcount&nbsp;&nbsp;(. @input (read bytes 0 (* 2 num-samples)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bbyte&nbsp;&nbsp; (. ByteBuffer (wrap bytes))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bshort&nbsp;&nbsp;(. bbyte (asShortBuffer))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shorts&nbsp;&nbsp;(make-array (. Short TYPE) num-samples)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do (print &quot;Read: &quot; (str bcount) &quot; bytes.&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(newline)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. *out* (flush))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. bshort (get shorts 0 num-samples))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shorts)))))
&nbsp;
(comment
&nbsp;
; &quot;Built-in Microphone&quot;&nbsp;&nbsp;&lt;&#45;- we&#039;ll use this
&nbsp;
; get the mixer info for the mic
(def mic-mixer-info
&nbsp;&nbsp;(:mixer-info (first (filter #(= &quot;Built-in Microphone&quot; (:name %)) mixer-info-list))))
&nbsp;
; get the built in mic mixer
(def mic (. AudioSystem (getMixer mic-mixer-info)))
&nbsp;
; get the supported source and target lines for the mixer
(def sources (seq (. mic (getSourceLineInfo))))&nbsp;&nbsp; ; nil
(def targets (seq (. mic (getTargetLineInfo))))&nbsp;&nbsp; ; (interface TargetDataLine supporting 72 audio formats)
&nbsp;
; get a target line
(def line-info (first targets))
(def mic-line (. mic (getLine line-info)))
&nbsp;
; add a line listener for events on the line
(. mic-line (addLineListener
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(implement [LineListener]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(update [evt]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do (print &quot;Event: &quot; (. evt (getType)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(newline)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. *out* (flush)))))))
&nbsp;
; check if we can get this format from the built in mic
(. mic-line (open format buffer-size))
&nbsp;
; start the input
(. mic-line (start))&nbsp;&nbsp;

; try looping and counting available samples
(dotimes i 100
&nbsp;&nbsp;(print &quot;Available data: &quot; (. mic-line (available)))
&nbsp;&nbsp;(newline)
&nbsp;&nbsp;(. *out* (flush))
&nbsp;&nbsp;(let [buffer&nbsp;&nbsp;(make-array (. Byte TYPE) 2048)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bcount&nbsp;&nbsp;(. mic-line (read buffer 0 2048))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bbyte&nbsp;&nbsp; (. ByteBuffer (wrap buffer))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bshort&nbsp;&nbsp;(. bbyte (asShortBuffer))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]
&nbsp;&nbsp;&nbsp;&nbsp;(print &quot;Read: &quot; bcount &quot; bytes. Buffer state:&quot; (str bshort))
&nbsp;&nbsp;&nbsp;&nbsp;(print &quot; &#46;.. Converted to short: &quot;&nbsp;&nbsp;(str (. bshort (get 0))))
&nbsp;&nbsp;&nbsp;&nbsp;(newline))
&nbsp;&nbsp;(. Thread (sleep 20)))&nbsp;&nbsp; ; 1 milli sleep = 1/1000 of a sec = 44 samples
&nbsp;
; stop the input
;(. mic-line (stop))
&nbsp;
; close mic
;(. mic-line (close))
&nbsp;
)
&nbsp;
</pre>
<p><strong>GUI Code</strong><br />
The following is the GUI part of the code. It generates some functions that draw over a couple of passed in controls. Create a simple GUI interface, then pass a couple of labels.</p>
<pre>; osx sampling code
(load-file &quot;iso-source.clj&quot;)
&nbsp;
; load in the windows sampling code
;(load-file &quot;iso-source-win.clj&quot;)
&nbsp;
; graphics code
(import &#039;(java.awt Color Polygon))
(import &#039;(java.awt.event ActionListener))
(import &#039;(java.awt.image BufferedImage VolatileImage))
(import &#039;(javax.swing JLabel JFrame ImageIcon))
(import &#039;(java.lang Thread))
(import &#039;(java.util.concurrent Executors))
&nbsp;
; make a set of functions that are associated with a graphcs in the ui
; this function is called with a couple of labels that we will draw on
(defn get-oscilloscope ([iso sono]
&nbsp;&nbsp;(let [c&nbsp;&nbsp; iso
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;&nbsp; sono
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of&nbsp;&nbsp;false
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oc&nbsp;&nbsp;100
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa&nbsp;&nbsp;(ref nil)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; store previous array so we can undraw
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ox&nbsp;&nbsp;(ref 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oy&nbsp;&nbsp;(ref 0)
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; might be neat to &#039;fade out&#039;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;turn-off 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn []
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(print &quot;Turned off. Fading.&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(newline))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; draw an oscilloscope grid
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;turn-on
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn []
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [g&nbsp;&nbsp; (. c (getGraphics))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;&nbsp; (. c (getX))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y&nbsp;&nbsp; (. c (getY))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w&nbsp;&nbsp; (. c (getWidth))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;h&nbsp;&nbsp; (. c (getHeight))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;&nbsp; 7
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xs&nbsp;&nbsp;(/ (- w 1) (- r 1))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ys&nbsp;&nbsp;(/ (- h 1) (- r 1))]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (clearRect x y w h))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (setColor (. Color gray)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (fillRect x y w h))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (setColor (. Color lightGray)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(dotimes ix r
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (drawLine (+ x (* ix xs)) y (+ x (* ix xs)) (+ y h))))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(dotimes iy r
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (drawLine x (+ y (* iy ys)) (+ x w) (+ y (* iy ys)))))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (setColor (. Color white)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (dispose)))))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; draw a set of samples, then xor out next time round
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw-samples
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn [samples]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [g (. c (getGraphics))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x (. c (getX))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y (. c (getY))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w (. c (getWidth))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;h (. c (getHeight))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n (count samples)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s (/ w n)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m 32768&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; signed 16-bit samples
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do (print &quot;Drawing at &quot; x &quot;,&quot; y &quot; size: &quot; w &quot; by &quot; h &quot;. Sample count: &quot; n )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(newline)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. *out* (flush))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (setColor (. Color gray)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (setXORMode (. Color white)))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; undraw the old one
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when @pa
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (drawPolygon @pa)))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; draw the new one
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(loop [i&nbsp;&nbsp;&nbsp;&nbsp;0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xa&nbsp;&nbsp; (make-array (. Integer TYPE) n)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ya&nbsp;&nbsp; (make-array (. Integer TYPE) n)]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if (&lt; i n)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [nx (int (+ x (* i s)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ny (int (- (/ h 2) (/ (* (aget samples i) h) m)))]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do (aset-int xa i nx)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(aset-int ya i ny)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(recur (+ i 1) xa ya)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [p (new Polygon xa ya n)]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do (sync nil (set pa p))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (drawPolygon p))))))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; clean up graphics context
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (dispose)))))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; draw a 2d sonogram - need a better color scheme
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;si&nbsp;&nbsp;(ref 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw-sono
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn [samples]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [g&nbsp;&nbsp; (. s (getGraphics))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w&nbsp;&nbsp; (. s (getWidth))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;h&nbsp;&nbsp; (. s (getHeight))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;&nbsp; (. s (getX))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y&nbsp;&nbsp; h
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n&nbsp;&nbsp; (/ (count samples) 4)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ss&nbsp;&nbsp;(/ h n)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m&nbsp;&nbsp; 32768&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; signed 16-bit samples
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sx&nbsp;&nbsp;(+ x (* ss @si))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; start pos
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(dotimes iy n
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [sy&nbsp;&nbsp;(- y (* iy ss) ss)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gain&nbsp;&nbsp; 3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; sonogram gain
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;&nbsp; (int (* gain 255 (/ (aget samples iy) m)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;&nbsp; (if (&gt; c 255) 255 c)]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do (. g (setColor (new Color c c c)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (fillRect sx sy ss ss)))))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (dispose))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if (&gt; (* @si ss) w)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sync nil (set si 0))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sync nil (set si (+ 1 @si))))))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; draw a frequency spectra and let it &#039;walk&#039; down screen +x+y
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; should clamp either end of spectra to zero to fix graphic glitches
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw-frequencies
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn [spectra]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [g (. c (getGraphics))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x (. c (getX))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y (. c (getY))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w (. c (getWidth))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;h (. c (getHeight))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n (/ (count spectra) 4)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s (/ (- w 100) n)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m 32768&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; signed 16-bit samples
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do ; bump iso
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sync nil 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set ox (+ @ox 1))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set oy (+ @oy 1))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when (&gt; @ox (- (/ h 2) 40))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(turn-on)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set ox 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set oy 0)))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; Fill a red polygon, and outline in white
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(loop [i&nbsp;&nbsp;&nbsp;&nbsp;0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xl&nbsp;&nbsp; (make-array (. Integer TYPE) n)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yl&nbsp;&nbsp; (make-array (. Integer TYPE) n)]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if (&lt; i n)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [nx&nbsp;&nbsp;(+ x (* i s) @ox)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ny&nbsp;&nbsp;(- (+ (/ h 2) @oy) (/ (* (aget spectra i) h) m))]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do (aset-int xl i nx)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(aset-int yl i ny)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(recur (+ i 1) xl yl)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do (let [p&nbsp;&nbsp; (new Polygon xl yl n)]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (setColor (. Color red)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (fillPolygon p))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (setColor (. Color white)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (drawPolygon p))))))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. g (dispose)))))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;; return our &#039;vtable&#039; associated with the two labels
&nbsp;&nbsp;&nbsp;&nbsp;{ :turn-on&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;turn-on 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:draw-samples draw-samples 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:draw-sono&nbsp;&nbsp;&nbsp;&nbsp;draw-sono 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:draw-frequencies draw-frequencies})))
&nbsp;
;&#45;&#45;&#45;- lame utility functions &#45;&#45;&#45;-
&nbsp;
; convert an array of shorts to floats
; there *has* to be a better way. But how?
(defn get-as-floats ([shorts]
&nbsp;&nbsp;(let [n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (count shorts)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;floats&nbsp;&nbsp;(make-array (. Float TYPE) n)]
&nbsp;&nbsp;&nbsp;&nbsp;(dotimes idx n (aset floats idx (aget shorts idx)))
&nbsp;&nbsp;&nbsp;&nbsp;floats)))
&nbsp;
;&#45;&#45;&#45;- load up the GUI, capture and analyze samples &#45;&#45;&#45;-
&nbsp;
; create an analyzer
(def fft (new kj.dsp.KJFFT 512))
&nbsp;
; running flag
(def running (ref nil))
&nbsp;
; oscilloscope
(defn oscilloscope ([]
&nbsp;&nbsp;(let [gui&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (new isometric.gui)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ipanel&nbsp;&nbsp;&nbsp;&nbsp;(. gui isopanel)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iw&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. ipanel (getWidth))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ih&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. ipanel (getHeight))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iimage&nbsp;&nbsp;&nbsp;&nbsp;(new BufferedImage iw ih (. BufferedImage TYPE_3BYTE_BGR))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iicon&nbsp;&nbsp;&nbsp;&nbsp; (new ImageIcon iimage)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ilabel&nbsp;&nbsp;&nbsp;&nbsp;(new JLabel iicon)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spanel&nbsp;&nbsp;&nbsp;&nbsp;(. gui sonopanel)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sw&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. spanel (getWidth))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. spanel (getHeight))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;simage&nbsp;&nbsp;&nbsp;&nbsp;(new BufferedImage sw sh (. BufferedImage TYPE_3BYTE_BGR))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sicon&nbsp;&nbsp;&nbsp;&nbsp; (new ImageIcon simage)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;slabel&nbsp;&nbsp;&nbsp;&nbsp;(new JLabel sicon)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;startbutton&nbsp;&nbsp; (. gui start)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oneshotbutton (. gui test)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stopbutton&nbsp;&nbsp;&nbsp;&nbsp;(. gui stop)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inputs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. gui inputs)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. Executors (newFixedThreadPool 1))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]
&nbsp;&nbsp;&nbsp;&nbsp;(. ilabel (setSize iw ih))
&nbsp;&nbsp;&nbsp;&nbsp;(. ipanel (add ilabel))
&nbsp;&nbsp;&nbsp;&nbsp;(. ipanel (doLayout))
&nbsp;&nbsp;&nbsp;&nbsp;(. slabel (setSize sw sh))
&nbsp;&nbsp;&nbsp;&nbsp;(. spanel (add slabel))
&nbsp;&nbsp;&nbsp;&nbsp;(. spanel (doLayout))
&nbsp;&nbsp;&nbsp;&nbsp;(. gui (pack))
&nbsp;&nbsp;&nbsp;&nbsp;(. gui (setVisible true))
&nbsp;&nbsp;&nbsp;&nbsp;; populate input sources
&nbsp;&nbsp;&nbsp;&nbsp;(doseq inp input-lines
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. inputs (addItem (:mixer-name inp))))
&nbsp;&nbsp;&nbsp;&nbsp;(let [funcs&nbsp;&nbsp;&nbsp;&nbsp; (get-oscilloscope ilabel slabel)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;turn-on&nbsp;&nbsp; (:turn-on funcs)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw-freq (:draw-frequencies funcs)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw-samp (:draw-samples funcs)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw-sono (:draw-sono funcs)
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; worker function that samples and calls the draw functions
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;worker
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn [] 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(turn-on)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(loop []
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [samples (get-inst-samples 512)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;floats&nbsp;&nbsp;(get-as-floats samples)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spectra (. fft (calculate floats))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(aset-float spectra 0 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(draw-freq spectra)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(draw-sono spectra)
;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(draw-samp samples)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. Thread (sleep 10))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if @running
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(recur)))))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; starts a worker, who will quit if @running == nil
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn []
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when (not @running)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sync nil (set running true))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. pool (submit worker)))))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; one-shot, sample and analyze a single &#039;frame&#039;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;one-shot
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn []
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when (not @running)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. pool (submit worker)))))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; kil the worker by setting @running = nil
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stop
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn []
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sync nil (set running nil)))]
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; set up UI buttons
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. inputs
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(addActionListener
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(implement [ActionListener]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(actionPerformed [evt]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [mixer-name&nbsp;&nbsp;(. inputs (getSelectedItem))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sel-line&nbsp;&nbsp;&nbsp;&nbsp;(:get-line (first (filter #(= mixer-name (:mixer-name %)) input-lines)))]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do (print &quot;Selecting: &quot; mixer-name)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(newline)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sel-line)))))))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. startbutton
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(addActionListener
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(implement [ActionListener]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(actionPerformed [evt]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(start)))))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. oneshotbutton
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(addActionListener
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(implement [ActionListener]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(actionPerformed [evt]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(one-shot)))))
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. stopbutton
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(addActionListener
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(implement [ActionListener]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(actionPerformed [evt]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(print &quot;=== STOP ===&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(newline)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(. *out* (flush))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(stop)))))

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(print &quot;Hit start to go&#46;..&quot;))))))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;
; comment out the following to have it not start automatically
(oscilloscope)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://jonathanwatmough.com/2008/02/prototyping-code-in-clojure/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Helpful Guide to Setting Up an SVN Repository</title>
		<link>http://jonathanwatmough.com/2008/02/if-you-hown-a-mac-with-leopard-and-havent-setup-a-svn-repository-you-are-crazy/</link>
		<comments>http://jonathanwatmough.com/2008/02/if-you-hown-a-mac-with-leopard-and-havent-setup-a-svn-repository-you-are-crazy/#comments</comments>
		<pubDate>Thu, 21 Feb 2008 02:10:46 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
		
		<category><![CDATA[Computers and Software]]></category>

		<guid isPermaLink="false">http://jonathanwatmough.com/?p=217</guid>
		<description><![CDATA[Regular Backups!
If you value your peace of mind, you will have already bought a few external hard drives, and backed up your computer on a regular(ish) basis. If you haven&#8217;t, and you own a mac, go to Shirt Pocket Software and download Super Duper, I can wait.
Setting Up an SVN Repository
Ok, now that&#8217;s out of [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Regular Backups!</strong></p>
<p>If you value your peace of mind, you will have already bought a few external hard drives, and backed up your computer on a regular(ish) basis. If you haven&#8217;t, and you own a mac, go to <a href="http://www.shirt-pocket.com/" title="Shirt Pocket Software">Shirt Pocket Software</a> and download <a href="http://www.shirt-pocket.com/SuperDuper/SuperDuperDescription.html" title="Super Duper!">Super Duper</a>, I can wait.</p>
<p><strong>Setting Up an SVN Repository</strong></p>
<p>Ok, now that&#8217;s out of the way, here are the indicators that you need to set up your own version control system&#8230;</p>
<ul>
<li>You work on any information that is important to you.</li>
<li>You work on multiple projects on multiple computers, and it can be hard to keep everything straight.</li>
<li>You work on software, or web pages, or documents where it would be beneficial to be able to recover to older versions.</li>
<li>You&#8217;d like to track (exactly) what you did (with diffs), and when you did it.</li>
</ul>
<p>If any of these sound like you, then you probably already realize that you could benefit from a version control system. Here&#8217;s why it can be much easier than you think:</p>
<ul>
<li>Mac OS X Leopard comes with a version control system called <a href="http://subversion.tigris.org/">Subversion</a> already installed! (Even if you didn&#8217;t install developer tools.)</li>
<li>Subversion, or svn for short, is super easy to set up.</li>
<li>Lots of common programs, such as NetBeans and TextMate, already support Subversion directly.</li>
<li>Subversion can be used easily from the command line.</li>
<li>As with most Unix tools, subversion works great over the network, including ssh, and has Windows clients too, like TortoiseSVN.</li>
<li>Subversion is Open Source software and can be built from sources. Barring hardware and software failures, you will never lose access to code, data and information that you entrust to Subversion.</li>
</ul>
<p>With all those reasons to install version control, you should be persuaded! If you aren&#8217;t, please post in the comments and let me know why. Seriously.</p>
<p>And without further, prevarication, prognostication or procrastination, here are the steps you need to set up a basic Subversion repository, and check in your first few folders:</p>
<p><strong>Decide where you want your repository.</strong><br />
The repository stores everything that you check-in, and tracks it by version. You could put the repository in your home folder, or on an external drive, but for simplicity, I&#8217;ll assume you have admin rights and we&#8217;ll put in in &#8216;/&#8217;.</p>
<p>The command to create your repository is:</p>
<p><code>svnadmin create /svnrepo</code></p>
<p>where &#8217;svnrepo&#8217; is whatever name you want. I wanted something easy to remember, and quick to type.</p>
<p><strong>Edit the configuration file and password file.</strong><br />
The default setup is to have read access for guest or anonymous, and write access for the logged-in user.</p>
<p>Edit the following lines in /svnrepo/conf/svnserve.conf to fix the access permissions.</p>
<p><code>anon-access = none<br />
auth-access = write</code></p>
<p>Now you have to manually add passwords to the file /svnrepo/conf/passwd. Add lines like the examples,</p>
<p><code>yourname = yourpassword</code></p>
<p>and save the file. ESC :wq if you are in vi.</p>
<p><strong>Setup an editor for Subversion.<br />
</strong>Before you can interact with Subversion, you must setup an editor for Subversion to use to allow you to input import and check-in comments. Add the following command to your ~/.profile:</p>
<p><code>export SVN_EDITOR=vi</code></p>
<p>Of course, you could pick any editor that you&#8217;re comfortable with!</p>
<p><strong>Import a Project.</strong><br />
Now you are ready to import your first folder into Subversion! As an example, you might want to import your Documents folder, or your Sites folder. In this example, I&#8217;ll import my Sites folder, on the same machine as the svn repository, assuming my Subversion repository is at /svnrepo.</p>
<p><code>svn import Sites file:///svnrepo/Sites</code></p>
<p>Subversion will bring up your editor. Type a line that describes the import. Since we are local, the Sites folder and contents will be imported to your repository. Note that the URL in the above command starts with file://.</p>
<p><strong>Start the Subversion server.<br />
</strong>We&#8217;ll start a server to allow you to access the repository across your network. Type the following command:</p>
<p><code>svnserve -d</code></p>
<p>This starts the server. Now you will be able to do a &#8216;check-out&#8217; of the files in your server to any other machine on your network! Let&#8217;s do another import first, but <em>across the network</em>. Type the following (but replace my folder with your folder, my username with your svn username, my ip with your ip, my repository with your repository&#8230;):</p>
<p><code>svn import PDFs svn://jonathan@192.168.0.3/svnrepo/PDFs</code></p>
<p>You should be able to understand the command now. svn import is the main command. PDFs is the folder we want to import to the repository. svn://jonathan@192.168.0.3/svnrepo/PDFs is the (take a deep breath) file protocol, user name, ip address, repository base, repository folder (phew!) that we want the files to be placed under.</p>
<p>After giving a check-in comment, and your password, the PDFs folder, or whatever you specified will be imported to your server.</p>
<p><strong>Getting a folder listing from Subversion.</strong><br />
It would be cruel to leave you without a means of at least getting a file listing. Here&#8217;s the &#8216;ls&#8217; of Subversion:</p>
<p><code>svn ls file:///svnrepo<br />
svn ls file:///svnrepo/Path</code></p>
<p><strong>Checking out files from Subversion</strong><br />
To get files out of Subversion, and copy them under the folder &#8216;WorkArea&#8217;, it&#8217;s easy:</p>
<p><code>cd ~/WorkArea<br />
svn co file:///svnrepo/PDFs PDFs</code></p>
<p>Specifying the folder as the last part of the command makes Subversion create that folder if it doesn&#8217;t already exist. If you only want the files copied into the current folder, replace PDFs, in this example, with &#8216;.&#8217;.</p>
<p>Even if you just imported a folder to Subversion, and you want to track some changes that you are about to make, you <em> must</em> check-out the folder so that Subversion can create some files that allow the files to be checked back in correctly when you are done.</p>
<p><strong>Updating the files in the repository after changes</strong><br />
Once you have made some changes, it&#8217;s easy to push the changes back to Subversion. Don&#8217;t worry! Any changes you made can be rolled back, and you can recover older versions at any time. Save your work! Here&#8217;s how:</p>
<p>Go to the parent of the folder that you checked-out, and type:</p>
<p><code>svn commit PDFs</code></p>
<p>Subversion will display an editor and wait for a check-in comment. Describe your changes. When you quit the editor, your changes will copied into the Subversion repository.</p>
<p>You should practice all these commands until you are comfortable with them.</p>
<p>Well, that&#8217;s it for now! Take it easy and post if you&#8217;d like me to do more on this topic, or if you have other feedback. Good luck with Subversion.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanwatmough.com/2008/02/if-you-hown-a-mac-with-leopard-and-havent-setup-a-svn-repository-you-are-crazy/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Google Charts from Clojure</title>
		<link>http://jonathanwatmough.com/2008/02/google-charts-from-clojure/</link>
		<comments>http://jonathanwatmough.com/2008/02/google-charts-from-clojure/#comments</comments>
		<pubDate>Sat, 16 Feb 2008 06:37:46 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
		
		<category><![CDATA[Clojure]]></category>

		<category><![CDATA[Computers and Software]]></category>

		<guid isPermaLink="false">http://jonathanwatmough.com/?p=211</guid>
		<description><![CDATA[I wrote up a very simple example of calling Google Charts api from Clojure.

Note: Rich Hickey actually emailed with some suggestions, and these have been added. I added a comment on the one I found most interesting, which is a function literal. Thanks Rich!

(in-ns &#039;google-chart)
(clojure/refer &#039;clojure)

(def *amp* &#34;&#38;&#34;)
&#160;
; &#45;&#45;&#45;- connect to google charts and retrieve [...]]]></description>
			<content:encoded><![CDATA[<p>I wrote up a very simple example of calling Google Charts api from Clojure.</p>
<p><a href="http://jonathanwatmough.com/?attachment_id=213" rel="attachment wp-att-213" title="Example Google Charts Graph"><img src="http://jonathanwatmough.com/wp-content/uploads/2008/02/googlechart.thumbnail.jpg" alt="Example Google Charts Graph" /></a></p>
<p><strong>Note:</strong> Rich Hickey actually emailed with some suggestions, and these have been added. I added a comment on the one I found most interesting, which is a function literal. <em>Thanks Rich!</em></p>
<pre>
(in-ns &#039;google-chart)
(clojure/refer &#039;clojure)

(def *amp* &quot;&amp;&quot;)
&nbsp;
; &#45;&#45;&#45;- connect to google charts and retrieve a chart &#45;&#45;&#45;-
(defn get-google-chart [request]
&nbsp;&nbsp;(new javax.swing.ImageIcon (new java.net.URL request) &quot;Google Chart&quot;))
&nbsp;
; &#45;&#45;&#45;- pop-up a png in a dialog frame &#45;&#45;&#45;-
(import &#039;(javax.swing JLabel JFrame))
&nbsp;
(defn show-chart [request]
&nbsp;&nbsp;(println &quot;Showing chart: &quot; request)
&nbsp;&nbsp;(doto (new JFrame &quot;Google Chart&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;(add (new JLabel (get-google-chart request)))
&nbsp;&nbsp;&nbsp;&nbsp;(pack)
&nbsp;&nbsp;&nbsp;&nbsp;(setVisible true)))
&nbsp;
; display the hello-world chart
;(show-chart (str &quot;http://chart.apis.google.com/chart?&quot;
;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;cht=p3&amp;chd=s:hW&amp;chs=250×100&amp;chl=Hello|World&quot;))
&nbsp;
; &#45;&#45;&#45;- simple encoding to 0 - 61 in chars &#45;&#45;&#45;-
&nbsp;
(defn encode [val scale]
&nbsp;&nbsp;(if (nil? val)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;_&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [val (. Math (floor (* 61 (/ val scale))))]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(nth &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789&quot; val))))
&nbsp;
; &#45;&#45;&#45;- build a chart &#45;&#45;&#45;-
&nbsp;
(defn base-url []
&nbsp;&nbsp;&quot;http://chart.apis.google.com/chart?&quot;)
&nbsp;
(defn chart-size [x y]
&nbsp;&nbsp;(str &quot;chs=&quot; x &quot;x&quot; y))
&nbsp;
(defn chart-type [type]
&nbsp;&nbsp;(str &quot;cht=&quot; type))
&nbsp;
(defn chart-data [data]
&nbsp;&nbsp;(let [mx (apply max data)]
&nbsp;&nbsp;&nbsp;&nbsp;(apply str &quot;chd=s:&quot; (map #(encode % mx) data))))&nbsp;&nbsp; ; function literal

;### fix spaces -&amp;gt; +
(defn chart-title [title]
&nbsp;&nbsp;(str &quot;chtt=&quot; title))

(defn chart-axis [x y]
&nbsp;&nbsp;; really basic, just an x and y axis
&nbsp;&nbsp;(apply str &quot;chxt=x,y&quot; *amp*
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;chxl=0:&quot; (concat (interleave (repeat &quot;|&quot;) x)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [&quot;|1:&quot;] (interleave (repeat &quot;|&quot;) y))))

;; Test it out &#46;..
(comment
(show-chart
&nbsp;&nbsp;(str
&nbsp;&nbsp;&nbsp;&nbsp;(base-url)
&nbsp;&nbsp;&nbsp;&nbsp;(chart-size 480 480) *amp*
&nbsp;&nbsp;&nbsp;&nbsp;(chart-type &quot;lc&quot;) *amp*
&nbsp;&nbsp;&nbsp;&nbsp;(chart-data (map (fn [x] (* x x)) (range -50 51))) *amp*
&nbsp;&nbsp;&nbsp;&nbsp;(chart-title &quot;x+squared&quot;) *amp*
&nbsp;&nbsp;&nbsp;&nbsp;(chart-axis [&quot;-5&quot; &quot;0&quot; &quot;5&quot;] [&quot;&quot; &quot;&quot; &quot;y-axis&quot;]))))
&nbsp;
; Test it out &#46;..
(show-chart
&nbsp;&nbsp;(str
&nbsp;&nbsp;&nbsp;&nbsp;(base-url)
&nbsp;&nbsp;&nbsp;&nbsp;(chart-size 480 240) *amp*
&nbsp;&nbsp;&nbsp;&nbsp;(chart-type &quot;lc&quot;) *amp*
&nbsp;&nbsp;&nbsp;&nbsp;(chart-data [188.5 186 181.5 183 179.5 181]) *amp*
&nbsp;&nbsp;&nbsp;&nbsp;(chart-title &quot;Jonathan+Weight&quot;) *amp*
&nbsp;&nbsp;&nbsp;&nbsp;(chart-axis [&quot;Week+1&quot; &quot;Week+2&quot; &quot;Week+3&quot;] [&quot;&quot; &quot;&quot; &quot;190+lbs&quot;])))
</pre>
]]></content:encoded>
			<wfw:commentRss>http://jonathanwatmough.com/2008/02/google-charts-from-clojure/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Regular Expression Helper</title>
		<link>http://jonathanwatmough.com/2008/02/regular-expression-helper/</link>
		<comments>http://jonathanwatmough.com/2008/02/regular-expression-helper/#comments</comments>
		<pubDate>Mon, 11 Feb 2008 00:10:30 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
		
		<category><![CDATA[CSS and Javascript]]></category>

		<category><![CDATA[Computers and Software]]></category>

		<guid isPermaLink="false">http://jonathanwatmough.com/?p=210</guid>
		<description><![CDATA[Click here to play with a simple reg exp helper for JavaScript.

Paste some text in, then experiment with typing in regular expressions, and watching the matches listed as you type.
]]></description>
			<content:encoded><![CDATA[<p>Click <a href="RegExpHelper.html">here</a> to play with a simple reg exp helper for JavaScript.</p>
<p><a href="http://jonathanwatmough.com/wp-content/uploads/2008/02/regexp.jpg" title="Regular Expression Helper in JavaScript"><img src="http://jonathanwatmough.com/wp-content/uploads/2008/02/regexp.thumbnail.jpg" alt="Regular Expression Helper in JavaScript" /></a></p>
<p>Paste some text in, then experiment with typing in regular expressions, and watching the matches listed as you type.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanwatmough.com/2008/02/regular-expression-helper/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
