<?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>Paul Legato &#187; Tech</title>
	<atom:link href="http://www.paullegato.com/blog/category/tech/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.paullegato.com</link>
	<description></description>
	<lastBuildDate>Tue, 06 Dec 2011 00:52:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Torrent Contents &#8211; List Files in a Torrent</title>
		<link>http://www.paullegato.com/blog/torrent-contents-list-files/</link>
		<comments>http://www.paullegato.com/blog/torrent-contents-list-files/#comments</comments>
		<pubDate>Tue, 31 May 2011 01:51:10 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=526</guid>
		<description><![CDATA[List the contents of a BitTorrent .torrent file with this small Ruby script.]]></description>
			<content:encoded><![CDATA[<p>List the files in a BitTorrent torrent with this quick Ruby script. Requires that you <code>gem install bencode awesome_print</code> before you run it.</p>
<pre class="brush: ruby; title: ; notranslate">

#!/usr/bin/env ruby
#
# torrentdump - prints the contents of a torrent.
#
# Copyright (C) 2011 Paul Legato. All rights reserved.
# Licensed for personal, non-commercial use only.
# This code comes with NO WARRANTY, express or implied.
#
# Prerequisite gem setup:
#   sudo gem install bencode awesome_print
#

require 'rubygems'
require 'bencode'
require 'awesome_print'

unless ARGV[0]
  STDERR.puts &lt;&lt;END

Usage: torrentdump &lt;filename&gt; &lt;-v&gt;

If -v is given, prints the entire contents of the torrent except the binary &quot;pieces&quot; hash data.

If -vv is given, prints everything, including the binary hash data.

Otherwise, prints only the file list.

END
  exit 1
end

# Method from http://stackoverflow.com/questions/3201890/is-there-an-elegant-way-to-remove-a-specific-key-from-a-hash-and-its-sub-hashes
def recursive_delete!(hash, to_remove)
  hash.delete(to_remove)
  hash.each_value do |value|
    recursive_delete!(value, to_remove) if value.is_a? Hash
  end
end

data = BEncode.load(File.read(ARGV[0]).force_encoding(&quot;binary&quot;))

if ARGV[1] == &quot;-vv&quot;
  ap data
elsif ARGV[1] == &quot;-v&quot;
  recursive_delete!(data, &quot;pieces&quot;)
  ap data
else
  if data[&quot;info&quot;][&quot;files&quot;]
    dir = data[&quot;info&quot;][&quot;name&quot;] || &quot;&quot;
    ap data[&quot;info&quot;][&quot;files&quot;].map {|x| dir + &quot;/&quot; + x[&quot;path&quot;].join(&quot;/&quot;) }
  else
    ap data[&quot;info&quot;][&quot;name&quot;]
  end
end
</pre>
<p>A quick example:</p>
<pre class="brush: plain; title: ; notranslate">
% torrentdump ubuntu-10.04.2-server-i386.iso.torrent
&quot;ubuntu-10.04.2-server-i386.iso&quot;
</pre>
<h2>Torrent dissection: of interest here..</h2>
<ul>
<li><a target="_blank" href="http://blog.grayproductions.net/articles/understanding_m17n" >Ruby 1.9 imposes a character encoding on every string</a> by default. This is fine for dealing with text, but caused errors in the <a target="_blank" href="https://github.com/dasch/ruby-bencode" >BEncode</a> library. (For some reason, the authors of BitTorrent chose to re-invent the wheel and developed their own binary encoding format.) We use the <code>#force_encoding</code> method on the torrent data to make Ruby treat the data as raw binary data and not try to interpret it. </li>
<li><a target="_blank" href="http://wiki.theory.org/BitTorrentSpecification" >More than you ever wanted to know about what&#8217;s inside a <code>.torrent file</code></a></li>
</ul>
<p>The <a target="_blank" href="https://github.com/pjlegato/torrentdump" >Torrentdump source code</a> is available on GitHub.</p>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=526&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/torrent-contents-list-files/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stop Calling Your Tests &#8220;Stories&#8221;</title>
		<link>http://www.paullegato.com/blog/stop-calling-your-tests-stories/</link>
		<comments>http://www.paullegato.com/blog/stop-calling-your-tests-stories/#comments</comments>
		<pubDate>Thu, 14 Apr 2011 22:28:08 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=515</guid>
		<description><![CDATA[Stop calling your tests &#8220;stories.&#8221; Really. They&#8217;re not &#8220;stories&#8221;. They&#8217;re tests. They don&#8217;t tuck you into bed with a glass of warm milk and a nice fairytale to dream about; they assert that certain things should happen and complain when they don&#8217;t, in a purely mechanical and precise way. We&#8217;re programming computers, machines of pure [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Stop calling your tests &#8220;stories.&#8221;</strong> Really.</p>
<p>They&#8217;re not &#8220;stories&#8221;. They&#8217;re tests. They don&#8217;t tuck you into bed with a glass of warm milk and a nice fairytale to dream about; they assert that certain things should happen and complain when they don&#8217;t, in a purely mechanical and precise way. We&#8217;re programming computers, machines of pure logic here, not reading to children. Let&#8217;s dispense with the pointless cutesy façade and focus precisely on the task at hand. </p>
<p>They don&#8217;t deliver what they promise, anyway. Frameworks like <a target="_blank" href="http://rspec.info/" >RSpec</a> and <a target="_blank" href="http://cukes.info/" >Cucumber</a> do <strong>not</strong> let you write tests in &#8220;plain English&#8221;. They let you write tests in a horrible chimeric programming language that adopts a superficial English-like veneer over top of what&#8217;s essentially a regular old unit testing framework.</p>
<p>It winds up giving you the benefits of neither English nor a well written testing API; your code simply becomes excessively verbose for the sake of a (highly fake and brittle) natural language veneer. You&#8217;re still highly restricted in what you can say, just like a regular old programming language. The set of Englishisms that you can use is so grossly restricted and precisely defined that you can&#8217;t think in anything remotely like English. You have to memorize a precise set of rigid, fixed English labels and use that and only that. You do get the verbosity of natural language, though, along with the restricted semantic domain of the API. You get the benefits of neither and the disadvantages of both.</p>
<p>Since you&#8217;re memorizing a highly restricted API anyway, skip the twee cruft and just use a <a target="_blank" href="https://github.com/seattlerb/minitest" >short and</a> <a target="_blank" href="http://test-unit.rubyforge.org/test-unit/Test/Unit/Assertions.html" >precise API</a> from the start, without the pseudo-natural language clutter.</p>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=515&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/stop-calling-your-tests-stories/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Custom Dialog Boxes Using Cocos2d on iPhone</title>
		<link>http://www.paullegato.com/blog/custom-dialog-boxes-cocos2d-iphone/</link>
		<comments>http://www.paullegato.com/blog/custom-dialog-boxes-cocos2d-iphone/#comments</comments>
		<pubDate>Mon, 13 Dec 2010 10:13:03 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[cocos2d]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[objective c]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=432</guid>
		<description><![CDATA[Custom dialog boxes are a must for any game. iPhone&#8217;s standard dialog boxes are fine for a business or productivity app, but in a game they look out of place. Users play games to escape from their everyday lives. Showing them the same exact graphic design that they associate with work and ordinary routine is [...]]]></description>
			<content:encoded><![CDATA[<p>Custom dialog boxes are a must for any game. iPhone&#8217;s standard dialog boxes are fine for a business or productivity app, but in a game they look out of place. Users play games to escape from their everyday lives. Showing them the same exact graphic design that they associate with work and ordinary routine is a great way to subtly interrupt the immersiveness of their gameplay experience. We don&#8217;t want that, so we need to customize.</p>
<div id="attachment_434"  class="wp-caption center"  style="width: 779px;"><a href="http://www.paullegato.com/wp-content/uploads/2010/12/iPhone-custom-dialog-box.png"  class="galleryAndCaptionItem" title=""><img class="size-full wp-image-434" title="iPhone UIAlertView to custom dialog box example" src="http://www.paullegato.com/wp-content/uploads/2010/12/iPhone-custom-dialog-box.png" alt="iPhone UIAlertView to custom dialog box example. Doesn't the custom one look much better?" width="769" height="268"/></a><span class="wp-caption-text"></span></div>
<p><a target="_blank" href="http://www.cocos2d-iphone.org/" >Cocos2d</a> makes it easy to convert your drab standard UIAlertViews into glorious customized color dialog boxes. Above is an actual UIAlertView / custom dialog box transition from my upcoming iPhone game. Here&#8217;s how I did it. <span id="more-432"></span></p>
<h1>Implementing a Custom Dialog Box in Cocos2d</h1>
<h2>Cocos2d Scene Structure</h2>
<p>Cocos2d uses a <a target="_blank" href="http://en.wikipedia.org/wiki/Scene_graph" >scene graph</a> to hold everything being displayed at any given point in a game. Informally, this data structure is a hierarchy of objects, each of which might display something onscreen, contain other objects to be displayed onscreen, or both. In Cocos2d, these objects are descendants of the <code>CCNode</code> class. </p>
<p>Related objects can be placed into a single container object, which allows them all to be manipulated as a unit when necessary. The root, or lowest-level, container at any given time is an instance of the <code>CCScene</code> class. A <code>CCScene</code> contains <code>CCLayer</code> objects, which themselves contain other objects such as menu labels or sprites to be displayed. Layers, as the name implies, are displayed superimposed upon each other onscreen, which makes a <code>CCLayer</code> perfect for our custom dialog box.</p>
<h2>Custom <code>CCLayer</code></h2>
<p>Here&#8217;s the code for <code>DialogLayer.h</code> and <code>DialogLayer.m</code>. These implement a basic but perfectly servicable custom iPhone dialog box. It can be used as-is or expanded in any number of ways for particular situations. Take a look through the finished product, and then we&#8217;ll go over it below.</p>
<h3><code>DialogLayer.h</code></h3>
<pre class="brush: objc; title: ; notranslate">
//
//  DialogLayer.h
//  concentrate
//
//  Created by Paul Legato on 12/4/10.
//  Copyright 2010 Paul Legato. All rights reserved.
//

#import &lt;Foundation/Foundation.h&gt;
#import &quot;cocos2d.h&quot;

@interface DialogLayer : CCLayer {
  NSInvocation *callback;
}

-(id) initWithHeader:(NSString *)header andLine1:(NSString *)line1 andLine2:(NSString *)line2 andLine3:(NSString *)line3 target:(id)callbackObj selector:(SEL)selector;
-(void) okButtonPressed:(id) sender;

@end
</pre>
<h3><code>DialogLayer.m</code></h3>
<pre class="brush: objc; title: ; notranslate">
//
//  DialogLayer.m
//  concentrate
//
//  Created by Paul Legato on 12/4/10.
//  Copyright 2010 Paul Legato. All rights reserved.
//

#import &quot;DialogLayer.h&quot;
#import &quot;GameSoundManager.h&quot;

#define DIALOG_FONT @&quot;bicho.fnt&quot;

@implementation DialogLayer
-(id) initWithHeader:(NSString *)header andLine1:(NSString *)line1 andLine2:(NSString *)line2 andLine3:(NSString *)line3 target:(id)callbackObj selector:(SEL)selector
 {
   if((self=[super init])) {

     NSMethodSignature *sig = [[callbackObj class] instanceMethodSignatureForSelector:selector];
     callback = [NSInvocation invocationWithMethodSignature:sig];
     [callback setTarget:callbackObj];
     [callback setSelector:selector];
     [callback retain];

     CGSize screenSize = [CCDirector sharedDirector].winSize;

     CCSprite *background = [CCSprite node];
     [background initWithFile:@&quot;Dialog.png&quot;];
     [background setPosition:ccp(screenSize.width / 2, screenSize.height / 2)];
     [self addChild:background z:-1];

     CCLabelBMFont *headerShadow = [CCLabelBMFont labelWithString:header fntFile:DIALOG_FONT];
     headerShadow.color = ccGRAY;
     headerShadow.opacity = 127;
     [headerShadow setPosition:ccp(243, 262)];
     [self addChild:headerShadow];

     CCLabelBMFont *headerLabel = [CCLabelBMFont labelWithString:header fntFile:DIALOG_FONT];
     headerLabel.color = ccBLACK;
     [headerLabel setPosition:ccp(240, 265)];
     [self addChild:headerLabel];

     //////////////////

     CCLabelBMFont *line1Label = [CCLabelBMFont labelWithString:line1 fntFile:DIALOG_FONT];
     line1Label.color = ccBLACK;
     line1Label.scale = 0.84f;
     [line1Label setPosition:ccp(240, 200)];
     [self addChild:line1Label];

     CCLabelBMFont *line2Label = [CCLabelBMFont labelWithString:line2 fntFile:DIALOG_FONT];
     line2Label.color = ccBLACK;
     line2Label.scale = 0.84f;
     [line2Label setPosition:ccp(240, 160)];
     [self addChild:line2Label];

     CCLabelBMFont *line3Label = [CCLabelBMFont labelWithString:line3 fntFile:DIALOG_FONT];
     line3Label.color = ccBLACK;
     line3Label.scale = 0.84f;
     [line3Label setPosition:ccp(240, 120)];
     [self addChild:line3Label];

     CCMenuItemImage *okButton = [CCMenuItemImage itemFromNormalImage:@&quot;OKButton.png&quot; selectedImage:@&quot;OKButtonSelected.png&quot; target:self selector:@selector(okButtonPressed:)];
     [okButton setPosition:ccp(0, 60)];

     CCMenu *menu = [CCMenu menuWithItems: okButton, nil];
     menu.position = ccp(240,0);
     [self addChild:menu];
   }
   return self;
 }

-(void) okButtonPressed:(id) sender
 {
   [[GameSoundManager sharedManager].soundEngine playEffect:@&quot;OK.caf&quot;
                                    pitch:1.0f
                                    pan:0.0f
                                    gain:1.0f];

   [self removeFromParentAndCleanup:YES];
   [callback invoke];
 }

-(void) dealloc
 {
   [callback release];
   [super dealloc];
 }
@end
</pre>
<p><H1>Custom dialog box code analysis</h1>
<h2>Overview</h2>
<p>The dialog box is implemented as a subclass of <code>CCLayer</code>. An <code>initWithHeader</code> method is provided to initialize the layer with a given message and a specified callback method that will be invoked when the dialog&#8217;s &#8220;OK&#8221; button is pressed. It also plays a confirmation sound and switches the &#8220;OK&#8221; button&#8217;s image to a &#8220;pressed button&#8221; when the user taps it.</p>
<p><code>DialogLayer.m</code> requires a few external supports, which must be available as project resources. <code>Dialog.png</code> is the dialog box&#8217;s background image. <code>bicho.fnt</code> is an AngelCode format bitmapped font, used for the labels, and can be substituted with any font you like. <code>OKButton.png</code> and <code>OKButtonSelected.png</code> are the images to be used for the button in unpressed and pressed forms. Finally, <code>OK.caf</code> is the audio file to be played when the user taps the button.</p>
<h2>Analysis</h2>
<h3>Storing the callback</h3>
<pre class="brush: objc; title: ; notranslate">
     NSMethodSignature *sig = [[callbackObj class] instanceMethodSignatureForSelector:selector];
     callback = [NSInvocation invocationWithMethodSignature:sig];
     [callback setTarget:callbackObj];
     [callback setSelector:selector];
     [callback retain];
</pre>
<p>This code is Objective C&#8217;s (massively redundant) way of storing the callback to be activated when the dialog&#8217;s button is pressed. It&#8217;s based on the callback code in Cocos2d itself. (We could also have used <a target="_blank" href="http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html" >Objective C&#8217;s new closure data type, called &#8220;blocks&#8221;</a>, but that syntax grates my Lispy sensibilities even more than the overly verbose Javaish mess here, besides not working out of the box on older versions of iOS.) </p>
<p>The <code>initWithHeader</code> method is given a target object and a method selector. It looks up the class of the target object and then looks up the selector on that class at line 1, resulting in a <code>NSMethodSignature</code> object which encapsulates the class-method combination. Line 2 transforms that class-method signature into an &#8220;invocation,&#8221; which represents the act of actually calling that method on some as yet unspecified object. Line 3 associates the invocation with the particular target object we were given, and line 4 associates the selector (which is utterly odd, since the desired method is encoded in the signature object already.) Finally, we retain the callback so that we can save it for later (to be activated when the user actually presses the &#8220;OK&#8221; button) and it won&#8217;t be deallocated at the end of the present scope.</p>
<h3>Setting up the background and labels</h3>
<p>The remainder of the <code>initWithHeader</code> method, lines 25 to 68 in the main listing above, is pretty straightforward. A <code>CCSprite</code> object is created to store the background image and added to <code>self</code>, that is, to the new custom layer being created. Its position is set to be the center of the screen, and its level on the Z axis is set to -1 so that it will appear below anything else added in the layer.</p>
<p><code>CCLabelBMFont</code>s are then created for the given text and added to the new layer. A shadow effect is created for the header by writing the same thing in grey at a slight offset underneath the main text. All lines except the header are then scaled down to 0.84 of their natural size, so as to enhance the prominence of the header.</p>
<p>A <code>CCMenuItemImage</code> is finally created to be the &#8220;OK&#8221; button. It&#8217;s added to a <code>CCMenu</code>, which handles the logic of button presses for us, and the <code>CCMenu</code> is then added to the new layer. It will take a little experimentation to get the exact placement of the OK button correct (lines 64 and 67) relative to your background image.</p>
<p>Note that the OK button itself takes callback arguments of exactly the same type that our <code>initWithHeader</code> method does (line 63). We might be tempted to forego the construction of our own callback object and just pass the given target and selector on to the OK button, simplifying the design of our <code>DialogLayer</code> a bit, but then we wouldn&#8217;t have the chance to play a sound when the OK buton is pressed. More seriously, we would have no way to destroy the dialog layer and remove it from the screen. So, we give the OK button a target of <code>self</code> and tell it to call the <code>okButtonPressed</code> method when OK is pressed.</p>
<h3>The <code>okButtonPressed</code> callback</h3>
<p>The <code>CCMenuItemImage</code> will invoke this method when the user presses &#8220;OK&#8221;. This means that it&#8217;s time to remove the <code>DialogLayer</code> from the scene (easy enough, line 80). Here, we also play a little click-type sound to make the game seem more interactive; also easy with CocosDenshion, lines 75-78. If you don&#8217;t want to play a sound, you can remove those lines and the <code>GameSoundManager.h</code> include file.</p>
<h3>dealloc</h3>
<p>Nothing fancy here; we just release our retained <code>callback</code> object and then defer to <code>super</code>.</p>
<h1>Using the custom <code>DialogLayer</code></h1>
<p>Adding a custom dialog layer to your game scene is very easy:</p>
<pre class="brush: objc; title: ; notranslate">
   CCLayer *dialogLayer = [[[DialogLayer alloc]
                            initWithHeader:@&quot;Level 1&quot;
                            andLine1:@&quot;Tilt The Phone&quot;
                            andLine2:@&quot;To Balance&quot;
                            andLine3:@&quot;The Ball!&quot;
                            target:self
                            selector:@selector(beginLevelOne)] autorelease];
   [self addChild:dialogLayer z:200];
</pre>
<h1>Future Expansions</h1>
<p><code>DialogLayer</code> is a simple modal dialog box that can only accept one action from the user. It can easily be enhanced in many ways, depending on your needs. The most obvious enhancement is to add multiple buttons to allow the user to make a choice rather than simply dismissing the box. It could be modified to accept an arbitrary amount of text and divide it up automatically into an aesthetically pleasing configuration.</p>
<p>One thing that <code>DialogLayer</code> does <em>not</em> do is pause the game. I decided that that is not necessarily desirable in all cases; many game scenarios need to present information to the user without stopping the action. It&#8217;s easy enough to pause manually when activating the dialog.</p>
<p>Little enhancements like this are critical as &#8216;polish&#8217; for your game.</p>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=432&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/custom-dialog-boxes-cocos2d-iphone/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>HowTo: projectM visualization + mp3 = video for YouTube</title>
		<link>http://www.paullegato.com/blog/projectm-visualization-youtube/</link>
		<comments>http://www.paullegato.com/blog/projectm-visualization-youtube/#comments</comments>
		<pubDate>Wed, 27 Oct 2010 00:37:06 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[music]]></category>
		<category><![CDATA[visualization]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=416</guid>
		<description><![CDATA[projectM (or its Windows-only predecessor, Milkdrop) can be used to make interesting visualizations for your music. Want to put your music on YouTube? You need to supply a video to accompany it. A projectM visualization makes an interesting and relatively easy accompaniment &#8212; far better than the typical static &#8220;picture of a CD cover&#8221; that [...]]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://projectm.sourceforge.net/" >projectM</a> (or its Windows-only predecessor, <a target="_blank" href="http://www.nullsoft.com/free/milkdrop/"  class="broken_link">Milkdrop</a>) can be used to make interesting visualizations for your music. Want to put your music on YouTube? You need to supply a video to accompany it. A projectM visualization makes an interesting and relatively easy accompaniment &mdash; far better than the typical static &#8220;picture of a CD cover&#8221; that most bands use:</p>
<p><object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/8o4ePoOdwoU?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/8o4ePoOdwoU?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object></p>
<p>This HowTo tells you what software you need and how to do it on your Mac.<span id="more-416"></span></p>
</p>
<h2>Recording projectM Videos to Disk</h2>
<ol>
<li><b>Install <a target="_blank" href="http://www.jackosx.com/" >Jack OS X</a>.</b> Jack is an audio routing program &mdash; it allows you to connect the inputs and outputs of different programs together as you like. We&#8217;ll be using it to connect iTunes&#8217; output (that is, our song) to projectM&#8217;s input (as well as playing it over the speakers.)</li>
<li><b>Install projectM.</b> There are many different precompiled versions available on the <a target="_blank" href="http://sourceforge.net/projects/projectm/files/" >projectM download page</a>. We want the latest build of projectm-jackosx.</li>
<li><b>Install <a target="_blank" href="http://www.telestream.net/screen-flow/overview.htm" >ScreenFlow</a></b> or other screen capture software. I personally like the rudimentary video editor included with ScreenFlow for preparing my movies as it saves the trouble of having to run a separate video editor, and is perfectly adequate for the relatively simple editing task at hand. Many people like <a target="_blank" href="http://www.syniumsoftware.com/screenium/" >Screenium</a>, too. Use whatever you prefer.</li>
<li><b>Start the JackPilot app.</b> This is the audio routing utility included with Jack OS X, where you actually specify which applications&#8217; sound output should be routed to others&#8217; input. Click &#8220;Start&#8221; to activate Jack. Then click the &#8220;Routing&#8221; button to bring up the &#8220;Connections Manager,&#8221; Jack&#8217;s routing table.</li>
<li>
<p><b>Change the default sound output to &#8220;JackRouter&#8221;.</b> Since iTunes doesn&#8217;t allow you to specify which audio device to use as its output, you will need to go into System Preferences -> Sound and change the systemwide default sound output to &#8220;JackRouter&#8221;. When you do this, a new item called iTunes should appear in the &#8220;Send Ports&#8221; list in JackPilot&#8217;s Connections Manager, as illustrated to the right.</p>
<p><a href="http://www.paullegato.com/wp-content/uploads/2010/10/Jack-Connections-Manager-Mac.png" ><img src="http://www.paullegato.com/wp-content/uploads/2010/10/Jack-Connections-Manager-Mac.png" alt="Jack&#039;s Connections Manager, showing that iTunes is routed to the system output (i.e. the speakers or headphones.)" title="Jack-Connections-Manager-Mac" width="588" height="359" class="alignright size-full wp-image-427" /></a>Connections Manager represents its connection information in a rather counterintuitive way, but it&#8217;s fairly straightforward once you understand what&#8217;s going on. At any time, there is one &#8220;focused&#8221; device whose connection information is shown in the GUI. It might be in either the Send or Receive column. The focused device has white text on a blue background. It&#8217;s &#8220;system&#8221; in the Receive column in the screenshot to the right. &#8220;System&#8221; devices are the built-in microphone and speaker/headphone connections.</p>
<p>Devices of the opposite polarity that are connected to that device are printed in red text. All connections of the focused device (the one highlighted in blue) are also redundantly shown in the &#8220;Connections&#8221; column on the far right. In this case, we can see that iTunes, in the Send column, is connected to system. The effect here is that any sound sent (played by) iTunes is routed to the system device, which plays it over the speakers or headphones. If you focus on &#8220;iTunes&#8221; by clicking it in the Send column, the display reverses; iTunes is highlighted in blue and system is printed in red and displayed in the &#8220;Connections&#8221; column.</p>
</li>
<li>
<p><b>Start projectM.</b> The Mac build is a bit flaky here. Launching it from Finder has never worked well for me. I start it directly from a terminal window with <code>/Applications/projectM-jack.app/Contents/MacOs/projectM-jack</code>. This allows me to see any error messages rather than sending them to the black hole.</p>
<p>At this point, you should get a visualization window that is visualizing whatever music you&#8217;re playing in iTunes. If it doesn&#8217;t respond to the music, check your JackPilot Connections Manager to make sure it looks like the screenshot.</p>
</li>
<li>
<p><b>Set projectM&#8217;s settings as you like.</b> Different visualizations blend better with different types of music. Experiment with the playlist and see what works for your tune. I like to use Ctrl-L, lock to preset, to prevent random switching and switch manually during the performance.</p>
<p>The projectM user interface is not exactly Mac-friendly. Viewing the hotkey list from the help menu blocks all user input, meaning that you have to close the hotkey list before you can actually use any of the hotkeys. Several hotkeys, such as Ctrl-E (open preset editor) and Ctrl-B (Show/hide menu and status bar) don&#8217;t seem to do anything on my computer. For our purposes, the most interesting are:
</p>
<ul>
<li>Ctrl-B: disable status bar. Be sure to do this before recording, or you&#8217;ll lose screen real estate to a white strip with the names of the presets you play.</li>
<li>Ctrl-L: lock/unlock active preset</li>
<li>Ctrl-N, Ctrl-P: next/previous preset</li>
<li>Ctrl-R: random preset</li>
<li>Ctrl-F: fullscreen mode</li>
<li>Ctrl-M: Show playlist (called &#8220;menu display&#8221; in projectM, for some reason)</li>
</ul>
<p>Be careful with the playlist. Pressing the third button along the top clears the entire playlist, and it&#8217;s really annoying to rebuild it by hand.</p>
</li>
<li><b>When you&#8217;re happy with your visualization choices, start a screen capture.</b> I don&#8217;t record audio with the screen grab; I add it back in afterwards from the original lossless file. This avoids audio degradation that would occur by re-capturing the analog signal and digitizing it again via Jack.</li>
<li><b>Edit your video as necessary.</b> You might want to trim the video to only show the active projectM window, if not running in fullscreen mode, and if you didn&#8217;t capture audio with the video you&#8217;ll want to add audio, of course.</lI>
<li><b>Export and upload to YouTube!</b> <a target="_blank" href="http://www.google.com/support/youtube/bin/answer.py?hl=en&#038;answer=132461" >They prefer</a> H.264 1280&#215;720 or 640&#215;480 video with MP3 or AAC audio.</li>
</ol>
<p>Check out <a target="_blank" href="http://www.youtube.com/user/LambdaAutomaton" >my YouTube channel</a> for more of my music and visualizations.</p>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=416&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/projectm-visualization-youtube/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Android or iPhone Development?</title>
		<link>http://www.paullegato.com/blog/android-iphone-development/</link>
		<comments>http://www.paullegato.com/blog/android-iphone-development/#comments</comments>
		<pubDate>Wed, 06 Oct 2010 20:28:40 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=381</guid>
		<description><![CDATA[Which platform should I target first? iPhone, for now, though it's close. Android cannot (yet) provide the same level of developer tools or paying user base, the Android emulator can't handle graphics, and I already own an iPhone. I do expect that Android's competitive position will improve significantly over the next few years, but it's not there yet.]]></description>
			<content:encoded><![CDATA[<p>Android or iPhone? Which platform should I target first? iPhone, for now, though it&#8217;s close. Android cannot (yet) provide the same level of developer tools or paying user base, the Android emulator can&#8217;t handle graphics, and I already own an iPhone. I do expect that Android&#8217;s competitive position will improve significantly over the next few years, but it&#8217;s not there yet.<span id="more-381"></span></p>
<h2>iPhone Pros</h2>
<ul>
<li><strong>iPhones are all (almost) exactly the same.</strong> 4th generation iPhones do support an optional higher screen resolution than previous models, but they&#8217;re 100% binary backwards compatible. This is a trivial difference when put up against the <a href= "https://secure.wikimedia.org/wikipedia/en/wiki/Comparison_of_Android_devices"> dozens of different Android devices</a> available with radically different hardware, and the <a href= "http://developer.android.com/guide/practices/screens_support.html"> hoops that you as a developer have to jump through</a> to make sure your app runs correctly on all of them.</li>
<li><strong>Large, high-end user base that demonstrably spends money on apps.</strong> iPhone users have already shown their willingness to buy large numbers of apps; Android users, not so much. This seems to be slowly changing over time as the Android app store matures, but for now, iPhone is still the cash cow.  </li>
<li><strong>Beautiful and well-designed UI and system architecture.</strong> iPhones have been designed as an integrated and coherent experience. Apple&#8217;s renowned mastery of intuitive human-computer interaction is evident at every step while using the device. There is an overall (and well documented) unifying strategic vision of how different subsystems should fit together seamlessly and present a unified interface to the user. Their development libraries have been designed to support this theme at every level. Android, by contrast, reads much more like KDE or Gnome; it was bolted together out of disparate pieces written by different groups working in isolation with minimal coordination. Perceived technical coolness from the perspective of a software engineer who is already intimately familiar with the system&#8217;s internals took precedent over usability. Android&#8217;s user interface is generally much uglier and much less intuitive.</li>
<li><strong>iPhones support low latency audio.</strong> Android uses ALSA internally, which does support low-latency audio, but the low-latency API is not exposed to developers, and <a href= "https://code.google.com/p/android/issues/detail?id=3434">Google does not seem to be interested in fixing this</a>. Android latency is unacceptably high for realtime sound synthesis unless you hack it and use the ALSA API, which is officially forbidden and in any case could change significantly and without warning between Android operating system updates and between phones. iPhone, on the other hand, has an <a href= "http://developer.apple.com/library/ios/#codinghowtos/AudioAndVideo/index.html#PLAYBACK-MINIMIZE_PLAYBACK_LATENCY"> officially supported low latency audio API</a>, and there are many successful realtime sound synthesizer apps in the app store.</li>
<li><strong>XCode.</strong> XCode is a really well done IDE. I normally don&#8217;t like IDEs. I normally use Emacs for everything. But, in all fairness, I decided to give XCode and Eclipse with the Android plugins a shot. Eclipse is nice, but a little rough around the edges. I ran into a few bizarre IDE error messages while developing my Android test projects that required extensive Googling and hours of experimentation to unravel. XCode, as one would expect from a flagship Apple product, is immaculately polished and completely integrated from top to bottom.</li>
</ul>
<h2>iPhone cons</h2>
<ul>
<li> <strong>Objective C.</strong> While Objective C was really cool and innovative in 1988, today it seems archaic. Nobody uses it except Apple. It&#8217;s laden with tons of cruft. It still feels like it&#8217;s a bolt-on afterthought preprocessor for a C compiler. For example:</p>
<ul>
<li><a href= "http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/ObjectiveC/Articles/ocSelectors.html"><strong>Selectors</strong></a>: you can&#8217;t refer to method names directly; you have to use the special <code>@selector()</code> compiler directive to look up their index number. This probably made great sense when CPUs were very slow and doing a lookup in an ASCII table was a significant performance hit over doing an integer offset jump, but on modern computers, this is just annoying. CPU time is cheaper than engineer time.</li>
<li>
<p><strong>Manual reference-counted memory management is an obsolete and extremely fragile pain in the ass.</strong> Lisp had GC ~40 years ago. The vast set of problems introduced by manual memory management, such as buffer overflows and memory leaks, is just not worth the small gain in efficiency that you get from not periodically running a garbage collector. Again, CPU time is cheaper than engineer time. Android does GC on a phone just fine, so I don&#8217;t buy the argument that a phone can&#8217;t support that kind of overhead. Garbage collection was recently introduced for the Mac OS X desktop system, but is as of yet not available on the iPhone.</p>
<p>(I&#8217;m aware that C and C++ are widely used and both still make you do manual memory management, too. Far from regarding this as a vehicle for a macho display of programming prowess, I find manual memory management to be more of an annoyance, something that the computer should be handling for me automatically, much like how figuring out the exact memory address of a function was automated long ago and is no longer something we as application-level programmers ever need to worry about much.)</p>
</li>
<li><a href= "http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-DontLinkElementID_66"><strong>The use of <code>+</code> and <code>-</code> to mark methods as class or instance methods.</strong></a> Principle of least surprise; why not just use, say, the English word <code>class</code> or <code>static</code> or something to that effect to designate class methods, and leave instance methods unmarked? Perhaps using 1 character symbols rather than entire English words as the token improved compile times on large, complex projects in the &#8217;80s, but the time savings is infinitesimal on a modern computer, so I&#8217;ll vote for obviousness and clarity rather than crypticity.</a></li>
<li><strong>The use of [] (square brackets) for message passing, and the requirement for named (but non-reorderable) arguments.</strong>
<p>Perhaps this was done out of a well-intentioned effort to make the programmer notice that these are messages and not function calls or C++ methods, and to make the code self-documenting. I find the introduction of new syntax rather unwarranted and distracting. I&#8217;d much prefer the familiar <code>object.message(argument1, argument2)</code> over the verbose and unwieldly <code>[object message:argument1 parameterName:argument2]</code>. You can&#8217;t even re-order the named arguments, so including the argument name is just noise in the code. I guess I&#8217;ve been spoiled by Clojure and Lisp, where there&#8217;s almost no syntax.</p>
<p>If they really felt strongly about the need to pedantically differentiate messages from function calls or methods at the syntax level, they should at least have retained the general function/method syntactic template and chosen a different separator character, so as to enable programmers to re-use most of their neural syntax parsing circuitry rather than force us to introduce an entirely new syntactic template that performs only 1 task. For example, a more intuitive syntax that still emphasizes the fact that this is not a function or method call could be something like <code>object#message(argument1, argument2)</code> or <code>object<-message(argument1, argument2)</code>.
 </ul>
</li>
<li><strong>Closed platform.</strong> The source code to the vast Cocoa library is proprietary. You can develop with things Apple tells you you may develop with, and nothing else. They only recently <a target="_blank" href="http://www.macrumors.com/2010/09/09/apple-opens-app-store-to-third-party-development-tools-publishes-review-guidelines/" >relaxed the restriction on using any third party tools</a> at all. <a target="_blank" href="https://encrypted.google.com/search?q=iphone+cpu+java" >The iPhone's CPU is widely reported to have built-in hardware level Java bytecode support</a>, but that's off-limits. </li>
<li><strong>Vendor lock-in.</strong> This is a huge and obvious minus for the iPhone. Your ability to generate revenue is 100% dependent upon Apple's whims, upon remaining in Apple's good graces. Uncountable horror stories circulate online about developers who invested months and many thousands of dollars into a project only to have it rejected by Apple, often after a considerable delay and with little or no explanation.</li>
</ul>
<h2>Android pros</h2>
<ul>
<li><strong>Java (almost).</strong> Android apps are written in Java. (Well, technically not in Java due to licensing issues, but in a language that is 99.9% the same as Java.) If you already know Java, as I do, this is a big plus. You can easily re-use your code elsewhere, on any platform, with minor or no modifications. Objective C code is rather limited in what you can do with it: you can re-use it in your Apple desktop apps. (Yes, there is a free GNU Objective C compiler, but almost all real-world Objective C code is locked into Apple's proprietary Cocoa runtime system.)</li>
<li><strong>A JVM, almost.</strong> Android doesn't run a true JVM, unfortunately, as part of a licensing dispute between Google and Sun, but it's close. Android's <a target="_blank" href="http://en.wikipedia.org/wiki/Dalvik_(software)" >Dalvik</a> is a cleanroom reimplementation of part of Java, designed to avoid triggering what Google regards as onerous licensing fees for the use of a true JVM on a mobile handset. In any case, it's close enough that the door is open to potentially running Clojure and other JVM languages on it someday.</li>
<li><strong>No upfront developer fees. Develop for free.</strong> You can download the SDK and go nuts, upload your code to a real handset to test, send your apps to the app store for sale, whatever. There is no $99 developer tax.  </li>
<li><strong>Larger ultimate user base.</strong> Android phones are now outselling iPhones, and this trend looks set to continue. The price you pay is coding for 200 slightly different handsets.</li>
<li><strong>Open source platform.</strong> Most of the Android system is freely available, precluding vendor lock-in, at least in theory.</li>
</ul>
<h2>Android cons</h2>
<ul>
<li><strong>Android emulator lacks hardware accelerated graphics.</strong> This is a big minus. I made a very simple bouncing-ball demo with <a target="_blank" href="http://www.rokonandroid.com/" >Rokon</a> that got about 6 or 7 fps in the emulator. Full games often take multiple seconds per frame, completely unusable. If you want to write games (or anything else where graphical performance is key), you absolutely need to have a hardware handset from the start. If you don't already own an Android phone anyway, this means you have to invest hundreds of dollars upfront, just to see if the platform is for you.</li>
<li><strong>Lack of interest from Google.</strong> Google has many, many pots cooking at once. While they do devote significant resources to Android's maintenance and expansion, it's nowhere near as important a product for them as the iPhone is for Apple, and you can tell. The iPhone is a core strategic product for Apple, whereas Android is a relatively minor satellite project for Google. Correspondingly, Apple's general support of the iPhone and its developers seems far better.  </li>
<li><strong>Relatively few libraries.</strong> For the moment, there seem to be more third party libraries available for the iPhone, and they seem to be more mature and robust than what's out there for Android. This will change in time, as more and more app developers begin to use Android. </li>
</ul>
<p>It was a close call. I did some exploratory coding on both platforms &mdash; there's no substitute for direct experience. Though I much prefer Java over Objective C as a language, the universe of extant Android libraries is much smaller and less mature. I may have been able to live with that in order to be able to code in Java and avoid Apple's vendor lock-in. In the end, the tipping point was practical: the Android emulator's lack of hardware accelerated graphics left me with an unusable framerate, so I'd have to spend hundreds of dollars on a handset to do even trivial demo development, whereas I already own an iPhone.</p>
<p>I'll be checking back in on Android periodically, as I expect its long-term position will improve substantially in time, but for now, I'm going with the iPhone.</p>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=381&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/android-iphone-development/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Dell PowerEdge BIOS Upgrade on Linux</title>
		<link>http://www.paullegato.com/blog/dell-poweredge-bios-linux/</link>
		<comments>http://www.paullegato.com/blog/dell-poweredge-bios-linux/#comments</comments>
		<pubDate>Sat, 31 Jul 2010 05:13:59 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=372</guid>
		<description><![CDATA[How to flash the BIOS on a Linux Dell PowerEdge system without having to use MS Windows.]]></description>
			<content:encoded><![CDATA[<p>Dell only provides certain PowerEdge BIOS flash upgrades in the form of Windows-only self-extracting archives (despite the facts that they claim to officially support Linux and that the BIOS flash utility itself is a DOS program.) Ordinary <code>unzip</code> won&#8217;t open the self-extracting archive. You need to run it on a Windows system, which I don&#8217;t have. Here&#8217;s how to flash your PowerEdge BIOS without Windows.</p>
<p>Dell provides the <a target="_blank" href="http://linux.dell.com/projects.shtml#biosdisk"  class="broken_link">biosdisk utility</a> to make a bootable FreeDOS image with the BIOS upgrade executable on it, but it doesn&#8217;t work with the Windows-only PowerEdge 4400 BIOS upgrade, since that won&#8217;t run on FreeDOS. They claim that <code>biosdisk</code> isn&#8217;t intended for PowerEdge systems, since they all have Linux BIOS flashes available; this does not seem to actually be the case for the 4400.</p>
<p>The Windows self-extractor <em>does</em> run under WINE, but it demands an actual floppy drive device to write to, which my computer doesn&#8217;t have. WINE also doesn&#8217;t seem to support mounting an image file as a floppy device, for some reason. You&#8217;ll need to use something like VMWare or a computer with a physical floppy drive to get this to extract itself.</p>
<p>Once you have a floppy image, here&#8217;s how to flash without biosdisk or Windows available: <span id="more-372"></span></p>
<ol>
<li><strong>Use <a target="_blank" href="http://wiki.winehq.org/FrontPage" >WINE</a> to extract the archive.</strong> For maximum fun, the upgrade I have refuses to just extract itself; instead, it requires that it has access to a floppy drive to write to directly. Sigh. Ok. Working on that. Updates to come. <code>winecfg</code>
<li><strong>Install <a target="_blank" href="http://syslinux.zytor.com/wiki/index.php/The_Syslinux_Project" >syslinux</a>.</strong>  (<code>apt-get install syslinux</code>). We are going to use <a target="_blank" href="http://syslinux.zytor.com/wiki/index.php/MEMDISK" >memdisk</a>, a boot loader that creates a RAM drive and then loads an operating system, to load FreeDOS.</li>
<li><strong>Get a<a target="_blank" href="http://www.fdos.org/bootdisks/" > FreeDOS boot disk image</a> and add your flashing .exe to it.</strong>Mount with something like <code>mount -t vfat /path/to/freedos.img /mnt -o loop</code>, then just <code>cp</code> your flashing .exe to <code>/mnt</code>. (If you got a gzipped image, <code>gunzip</code> it first.</li>
<li><strong>Edit /etc/grub.d/40_custom to add a boot menu entry for memdisk/FreeDOS.</strong>
<pre class="brush: plain; title: ; notranslate">
menuentry &quot;FreeDOS&quot; {
    set root=(hd0,2) #### &lt;--- Change this to your /boot partition!
    linux16 /memdisk floppy
    initrd16 /freedos.img
}
</pre>
<p>As noted, change the root entry to point to your actual /boot partition, so GRUB can find the images. Also note that the partition normally mounted at <code>/boot</code> will be mounted as the root directory (/) at boot time, so it&#8217;s not necessary to prefix <code>/boot</code> before the image file names.</p>
<p>Then, reboot and select FreeDos from the GRUB menu. Run your DOS-based flash program, and all is well.</p>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=372&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/dell-poweredge-bios-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Swing-Clojure GUI for the Black-Scholes Option Modeler</title>
		<link>http://www.paullegato.com/blog/swing-clojure-gui-black-scholes/</link>
		<comments>http://www.paullegato.com/blog/swing-clojure-gui-black-scholes/#comments</comments>
		<pubDate>Thu, 15 Jul 2010 07:55:56 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[finance]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=352</guid>
		<description><![CDATA[Now that we have implemented Black-Scholes in Clojure, let&#8217;s make a Swing GUI for it. The Swing GUI will have text boxes for all the necessary inputs, and calculate prices and Greeks when the button is pressed. It&#8217;s a simple and straightforward way to get started in Swing GUI programming in Clojure. Here&#8217;s what it [...]]]></description>
			<content:encoded><![CDATA[<p>Now that we have implemented <a href="http://www.paullegato.com/blog/black-scholes-clojure/" >Black-Scholes in Clojure</a>, let&#8217;s make <a target="_blank" href="http://github.com/pjlegato/clojure_options" >a Swing GUI for it</a>. The Swing GUI will have text boxes for all the necessary inputs, and calculate prices and Greeks when the button is pressed. It&#8217;s a simple and straightforward way to get started in Swing GUI programming in Clojure. Here&#8217;s what it looks like. <a href="http://www.paullegato.com/wp-content/uploads/2010/07/Swing-GUI-Clojure-Black-Scholes.png" ><img src="http://www.paullegato.com/wp-content/uploads/2010/07/Swing-GUI-Clojure-Black-Scholes.png" alt="Screenshot of the Swing GUI for the Black-Scholes option modeler, implemented in Clojure" title="Swing-GUI-Clojure-Black-Scholes" width="569" height="355" class="alignright size-full wp-image-354" /></a></p>
<p>The GUI is written entirely in Clojure with the Swing toolkit. Calculation state is stored in a series of atoms. Watches are used to update the output table automatically when an atom changes, <a target="_blank" href="http://kotka.de/blog/2010/05/Decoupling_Logic_and_GUI.html" >an idea from Kotka</a>. I used the excellent <a target="_blank" href="http://www.miglayout.com/" >MiG Layout</a> for general layout functionality, and generic Swing widgets (JTextFields and a JTable) for the input and output.<br />
<span id="more-352"></span></p>
<h2>Clojure code</h2>
<p>The Black-Scholes GUI is launched with the<code>main</code> function. The Swing GUI is actually created in the <code>initialize-gui</code> function, but since <a target="_blank" href="http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html" >Swing widgets are not threadsafe</a>, we must use the <code>do-swing*</code> helper function from Clojure Contrib to spin off the real GUI creation code into the Swing event thread.</p>
<pre class="brush: clojure; title: ; notranslate">
(defn initialize-gui
  []
  (let [frame (JFrame. &quot;Black-Scholes Option Modeler&quot;)]

    (doto frame
      (.setDefaultCloseOperation JFrame/DISPOSE_ON_CLOSE)
      (-&gt; .getContentPane
          (.add (miglayout (JPanel.)

                           (input-panel
                            (fn [_]
                              (do-swing
                               (doto frame
                                 (.setVisible false)
                                 (.dispose)))))

                           (result-table)

                           )))

      (.setDefaultCloseOperation JFrame/DISPOSE_ON_CLOSE)
      (.pack)
      (.setVisible true))
     ))

(defn main
  []
  (do-swing* :now initialize-gui))
</pre>
<p>This is pretty straightforward. We make a (locally scoped) JFrame to be the main container at line 3. Within the context of the <code>let</code>, we add a JPane using MiG Layout to its content area (starting at line 8). The JPanel itself contains two subwidgets, which are those returned from the <code>input-panel</code> and <code>result-table</code> functions.</p>
<p>Note that we are passing an anonymous function to <code>input-panel</code> at line 11. The input panel contains the &#8220;Quit&#8221; button, and that button needs to know what to do when it&#8217;s pressed. We want it to close the GUI; that is, it should destroy the outer JFrame. To do that, it needs a reference to it. However, as a local variable in <code>initialize-gui</code>, the JFrame is not in scope elsewhere; we have to pass it in. The given function closes over the JFrame reference (line 13) and transports it to <code>input-panel</code>, where that function will be called as an event listener when the &#8220;Quit&#8221; button is pressed.</p>
<p>We could also have simply passed the bare JFrame rather than a function, and moved the frame-closing code into <code>input-panel</code>, but that would imply that the input panel must always be in a JFrame, which will not necessarily the case. Passing in an external anonymous function to be activated by the &#8220;Quit&#8221; button allows the input panel to be used generically in any sort of container, with the container deciding what to do when &#8220;Quit&#8221; is pressed.</p>
<h3>The Input Panel</h3>
<pre class="brush: clojure; title: ; notranslate">

(defn- input-panel [quit-action]
    (let [
          ;; Fields
          spot (doto (JFormattedTextField. (NumberFormat/getNumberInstance))
                 (.setColumns 6)
                 (.setValue @*spot*))

          strike (doto (JFormattedTextField. (NumberFormat/getNumberInstance))
                   (.setColumns 6)
                   (.setValue @*strike*))

          days-till-expiry (doto (JFormattedTextField. (NumberFormat/getIntegerInstance))
                             (.setColumns 6)
                             (.setValue @*days-till-expiry*))

          riskfree (doto (JFormattedTextField. (NumberFormat/getNumberInstance))
                     (.setColumns 6)
                     (.setValue @*riskfree*))

          volatility (doto (JFormattedTextField. (NumberFormat/getNumberInstance))
                       (.setColumns 6)
                       (.setValue @*volatility*))

          ;; Buttons
          calculate (JButton. &quot;Calculate&quot;)
          quit (JButton. &quot;Quit&quot;)
          ]

      (add-action-listener
       calculate
       (fn [_]
         (update-all-calculations
          (Double/parseDouble (.getText spot))
          (/ (Integer/parseInt (.getText days-till-expiry)) *trading-days-per-year*)
          (Double/parseDouble (.getText strike))
          (Double/parseDouble (.getText riskfree))
          (Double/parseDouble (.getText volatility)))))

      (add-action-listener
       quit
       quit-action)

      (miglayout (JPanel.)
                 :layout  [:wrap 2 ]

                 (JLabel. &quot;Spot&quot;) [:align &quot;right&quot;]
                 spot

                 (JLabel. &quot;Strike&quot;) [:align &quot;right&quot;]
                 strike

                 (JLabel. &quot;Risk-free rate&quot;) [:align &quot;right&quot;]
                 riskfree

                 (JLabel. &quot;Volatility&quot;) [:align &quot;right&quot;]
                 volatility

                 (JLabel. &quot;Days till expiry&quot;) [:align &quot;right&quot;]
                 days-till-expiry

                 calculate
                 quit)))
</pre>
<p>The input widgets are local variables in the input panel function, along with the two buttons. The widgets are initialized from the state atoms (which are then unused again; see discussion below.) The &#8220;Quit&#8221; button is given the event callback passed in as an argument (so it can manipulate the enclosing JFrame as per above.) The &#8220;Calculate&#8221; button is given an event callback that calls the <code>update-all-calculations</code> function with the values in the input widgets.</p>
<p>The lot are then stuffed into a JPanel with a MiG Layout and returned.</p>
<h3>The Output Table</h3>
<pre class="brush: clojure; title: ; notranslate">
(defn- update-cell
  &quot;Updates the given AbstractTableModel cell and fires a change event for that cell.&quot;
  [model data row col]
  (.setValueAt model data row col)
  (.fireTableCellUpdated model row col))

(defn- result-table []
  (let [
        column-names [&quot;&quot; &quot;Call&quot; &quot;Put&quot;]
        row-names [&quot;Price&quot; &quot;Delta&quot; &quot;Theta&quot; &quot;Rho&quot; &quot;Gamma&quot; &quot;Vega&quot;]
        table-model (proxy [AbstractTableModel] []
                      (getColumnCount [] (count column-names))
                      (getRowCount [] (count row-names))
                      (isCellEditable [] false)
                      (getColumnName [col] (nth column-names col))
                      (getValueAt [row col]
                                  (condp = col
                                      0 (nth row-names row) ;; Return the row name for column zero
                                      (condp = [row col]
                                          [0 1] @*call-price*
                                          [0 2] @*put-price*

                                          [1 1] @*call-delta*
                                          [1 2] @*put-delta*

                                          [2 1] @*call-theta*
                                          [2 2] @*put-theta*

                                          [3 1] @*call-rho*
                                          [3 2] @*put-rho*

                                          [4 1] @*gamma*
                                          [4 2] &quot;==&quot;

                                          [5 1] @*vega*
                                          [5 2] &quot;==&quot;

                                          nil))))

        table (doto (JTable. table-model)
                (.setGridColor java.awt.Color/DARK_GRAY))
        ]

    (add-watch *call-price* ::update-call-price (fn [_ _ _ newprice] (update-cell table-model newprice 0 1)))
    (add-watch *put-price* ::update-put-price (fn [_ _ _ newprice] (update-cell table-model newprice 0 2)))

    (add-watch *call-delta* ::update-call-delta (fn [_ _ _ newval] (update-cell table-model newval 1 1)))
    (add-watch *put-delta* ::update-put-delta (fn [_ _ _ newval] (update-cell table-model newval 1 2)))

    (add-watch *call-theta* ::update-call-theta (fn [_ _ _ newval] (update-cell table-model newval 2 1)))
    (add-watch *put-theta* ::update-put-theta (fn [_ _ _ newval] (update-cell table-model newval 2 2)))

    (add-watch *call-rho* ::update-call-rho (fn [_ _ _ newval] (update-cell table-model newval 3 1)))
    (add-watch *put-rho* ::update-put-rho (fn [_ _ _ newval] (update-cell table-model newval 3 2)))

    (add-watch *gamma* ::update-gamma (fn [_ _ _ newval] (update-cell table-model newval 4 1)))
    (add-watch *vega* ::update-vega (fn [_ _ _ newval] (update-cell table-model newval 5 1)))

    ;; This shrinks the table's preferred viewport down to its actual size.
    ;; (The default is to make a huge viewport, even though the table is small.)
    (.setPreferredScrollableViewportSize table (.getPreferredSize table))

    (JScrollPane. table)
    ))
</pre>
<p>The output table itself is a standard JTable. Its model is initialized from the output state atoms. The watches at lines 44-57 are the most interesting part; they allow arbitrary code to be called when the output state atoms change. This allows the Black-Scholes calculation to happen independently of the output widget. When one of those atoms is changed, it self-updates automatically via the watches.</p>
<p>The helper function at lines 1-5 updates the appropriate model cell and fires an event to tell the JTable to repaint it.</p>
<p>The scrollable viewport business at line 61 is to work around a questionable Java design decision where a JTable, by default, tells its container to make its viewport enormous, even though it have very little data. (That&#8217;s not an error, that&#8217;s subjunctive.)</p>
<h2>Design considerations</h2>
<h3>GUI and business logic decoupling</h3>
<p>Above all, the GUI has to be decoupled from the model itself. Internal changes to one should never affect the other, and the two should be independently testable. In such a simple application, this was easy enough. A more complex app that requires several information round trips would be trickier. We now have a good foundation for such an app. No business calculations are performed in the GUI code namespace. The sole point of connection is in the update-all-calculations function:</p>
<pre class="brush: clojure; title: ; notranslate">

(defn- update-all-calculations [spot timeleft strike riskfree sigma]
  (swap! *call-price* (fn [_] (bs/call spot timeleft strike riskfree sigma)))
  (swap! *put-price* (fn [_] (bs/put spot timeleft strike riskfree sigma)))

  (swap! *call-delta* (fn [_] (bs/call-delta spot timeleft strike riskfree sigma)))
  (swap! *put-delta* (fn [_] (bs/put-delta spot timeleft strike riskfree sigma)))

  (swap! *call-theta* (fn [_] (bs/call-theta spot timeleft strike riskfree sigma)))
  (swap! *put-theta* (fn [_] (bs/put-theta spot timeleft strike riskfree sigma)))

  (swap! *call-rho* (fn [_] (bs/call-rho spot timeleft strike riskfree sigma)))
  (swap! *put-rho* (fn [_] (bs/put-rho spot timeleft strike riskfree sigma)))

  (swap! *vega* (fn [_] (bs/vega spot timeleft strike riskfree sigma)))
  (swap! *gamma* (fn [_] (bs/gamma spot timeleft strike riskfree sigma))))
</pre>
<h3>Atoms to hold state</h3>
<p>As we can see above, set of atoms holds state for the GUI, in keeping with the general Clojure principle of isolating state into transactional memory. (Actually, I cheated a bit. Our full state consists of the input values and the results of our Black-Scholes calculations. Although I created atoms for the input state values as well, I calculate the results directly from the widgets. It is a trivial exercise to alter the &#8220;Calculate&#8221; button callback to use the atoms. This would be more useful in the case where changes to a widget fire an event that triggers recalculation, which is not done in this demo as per below. I would use the atoms in a real application.)</p>
<p>I/O is inherently stateful, as are GUIs. There was therefore the temptation to use the Swing widget objects themselves as state-holders, and in fact it requires extra code to shuttle data back and forth between the widgets and the atoms. In such a simple app as this, using the GUI widgets as state-holders does not make much practical difference, but in a more complex app, a well designed set of state atoms and watches can automate much of the tedious GUI logic.</p>
<p>Using the widgets directly as state holders implies a tight coupling between the input widgets, the business logic, and the output widgets. Changing any one of them would invariably have required changes to the linking logic.</p>
<p>For example, suppose we were using widgets-as-state, and we changed the &#8220;days left till expiry&#8221; input to a slider rather than a text box, or suppose we wanted to read it from a file or from an API. We would have to update the code that reads it, calculates the model, and puts the results into the output table. Touching that code implies a non-zero likelihood of breaking it. Why even introduce the potential for breaking something that is unrelated to the task at hand, in this case the business logic and output code?</p>
<p>Again, this seems trivial with such a very small application that is only a few lines long, but the design principle is what&#8217;s important. Imagine applying it to a much larger application with hundreds of inputs spread across 4 windows, 3 databases, and 6 web feeds to see why this is a good idea.</p>
<h3>Auto-updating results when input changes</h3>
<p>I wanted the results to auto-update anytime an input is changed, without resorting to a &#8220;Calculate&#8221; button. Having the button trigger the calculation and output update allows the state of the input and the output to become decoupled, which can be confusing for the user. Worse, it could be unnoticed by a user who is doing other things at the same time.</p>
<p>Due to typical Java overengineering, there is no straightforward way to simply <code>(add-action-listener)</code> on the JTextField and get notifications when it changes. Instead, <a target="_blank" href="http://download.oracle.com/docs/cd/E17409_01/javase/tutorial/uiswing/components/generaltext.html#document" >each Swing widget implements full-blown model-view separation</a>, and so you have to get the document underlying the JTextField. Yes, the view components of your MVC application themselves contain both models and views. Each and every field contains an entire implementation of the document object and associated cruft, all for itself. If you want to monitor changes in the widget, you need to build out a <code>DocumentListener</code> to watch for such events.</p>
<p>In a real application, I&#8217;d bite the bullet and implement it, but it&#8217;s not worth the extra time for the purposes of this demo, so we are left with a &#8220;Calculate&#8221; button and manual updating.</p>
<h2>Clojure-Options on Github</h2>
<p>The entire package so far is now <a target="_blank" href="http://github.com/pjlegato/clojure_options" >available on my GitHub page</a>. Patches are welcome. Atomizing the input widgets and adding the appropriate event callbacks and watches to eliminate the &#8220;Calculate&#8221; button is particularly welcome. <img src='http://www.paullegato.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=352&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/swing-clojure-gui-black-scholes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Black-Scholes in Clojure</title>
		<link>http://www.paullegato.com/blog/black-scholes-clojure/</link>
		<comments>http://www.paullegato.com/blog/black-scholes-clojure/#comments</comments>
		<pubDate>Sun, 11 Jul 2010 00:51:27 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[finance]]></category>
		<category><![CDATA[quant]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=345</guid>
		<description><![CDATA[The Black-Scholes option pricing model, implemented in Clojure based on the description at Wikipedia and these code samples. This code uses the new Incanter Distributions module, which hasn&#8217;t been released yet, so it requires the latest master version from Github. Most of the values agree with those produced at BloBek&#8217;s calculator, with the exception of [...]]]></description>
			<content:encoded><![CDATA[<p>The Black-Scholes option pricing model, implemented in Clojure based on <a target="_blank" href="https://secure.wikimedia.org/wikipedia/en/wiki/Black–Scholes" >the description at Wikipedia</a> and <a target="_blank" href="http://www.espenhaug.com/black_scholes.html" >these code samples</a>.<br />
<span id="more-345"></span></p>
<pre class="brush: clojure; title: ; notranslate">
;;
;; Black-Scholes option pricing model
;;
;; Copyright (C) 2010 Paul Legato. All rights reserved.
;; Licensed under the New BSD License. See the README file for details.
;;
;; Disclaimer: This code comes with NO WARRANTY, express or implied.
;; There may be any number of bugs. Use at your own risk.
;;
;; References:
;; - https://secure.wikimedia.org/wikipedia/en/wiki/Black%E2%80%93Scholes
;; - http://www.espenhaug.com/black_scholes.html

(ns clojure-options.black-scholes
  (:require incanter.distributions))

(defn d1
  [spot timeleft strike riskfree sigma]
  (/
   (+ (Math/log (/ spot strike))
      (* (+ riskfree (/ (* sigma sigma) 2))
         timeleft))
   (* sigma (Math/sqrt timeleft))))

(defn d2
  [spot timeleft strike riskfree sigma]
  (- (d1 spot timeleft strike riskfree sigma) (* sigma (Math/sqrt timeleft))))

(defn- n [val] (incanter.distributions/cdf (incanter.distributions/normal-distribution) val))

(defn call
  &quot;Returns the theoretic value of a European call option on the given underlying based on the Black-Scholes model.

 * spot - spot price of the underlying
 * timeleft - time to expiration, in years
 * strike - option strike price
 * riskfree - annual continuous risk-free interest rate
 * sigma - volatility of the underlying

&quot;
  [spot timeleft strike riskfree sigma]
  (- (* spot (n (d1 spot timeleft strike riskfree sigma)))
     (* strike
        (Math/exp (* (- riskfree) timeleft))
        (n (d2 spot timeleft strike riskfree sigma)))))

(defn put
  &quot;Returns the theoretic value of a European put option on the given underlying based on the Black-Scholes model.

 * spot - spot price of the underlying
 * timeleft - time to expiration, in years
 * strike - option strike price
 * riskfree - annual continuous risk-free interest rate
 * sigma - volatility of the underlying

&quot;
  [spot timeleft strike riskfree sigma]
  (- (* strike
        (Math/exp (* (- riskfree) timeleft))
        (n (- (d2 spot timeleft strike riskfree sigma))))
     (* spot (n (- (d1 spot timeleft strike riskfree sigma))))))

(defn call-delta
  [spot timeleft strike riskfree sigma]
  (n (d1 spot timeleft strike riskfree sigma)))

(defn put-delta
  [spot timeleft strike riskfree sigma]
  (- (n (d1 spot timeleft strike riskfree sigma)) 1))

(defn- nprime [val] (incanter.distributions/pdf (incanter.distributions/normal-distribution) val))

(defn gamma
  [spot timeleft strike riskfree sigma]
  (/ (nprime (d1 spot timeleft strike riskfree sigma))
     (* spot sigma (Math/sqrt timeleft))))

(defn vega
  [spot timeleft strike riskfree sigma]
  (* spot (nprime (d1 spot timeleft strike riskfree sigma)) (Math/sqrt timeleft)))

(defn call-theta
  [spot timeleft strike riskfree sigma]
  (-
   (- (/ (* spot (nprime (d1 spot timeleft strike riskfree sigma)) sigma)
         (* 2 (Math/sqrt timeleft))))
   (* riskfree strike (Math/exp (* (- riskfree) timeleft)) (n (d2 spot timeleft strike riskfree sigma)))))

(defn put-theta
  [spot timeleft strike riskfree sigma]
  (-
   (- (/ (* spot (nprime (d1 spot timeleft strike riskfree sigma)) sigma)
         (* 2 (Math/sqrt timeleft))))
   (* riskfree strike (Math/exp (* (- riskfree) timeleft)) (n (- (d2 spot timeleft strike riskfree sigma))))))

(defn call-rho
  [spot timeleft strike riskfree sigma]
  (* strike timeleft (Math/exp (* (- riskfree) timeleft)) (n (d2 spot timeleft strike riskfree sigma))))

(defn put-rho
  [spot timeleft strike riskfree sigma]
  (* (- strike) timeleft (Math/exp (* (- riskfree) timeleft)) (n (- (d2 spot timeleft strike riskfree sigma)))))
</pre>
<p>This code uses the new <a target="_blank" href="http://liebke.github.com/incanter/distributions-api.html" >Incanter Distributions module</a>, which hasn&#8217;t been released yet, so it requires the latest master version from Github.</p>
<p>Most of the values agree with those produced at <a target="_blank" href="http://www.blobek.com/black-scholes.html"  class="broken_link">BloBek&#8217;s calculator</a>, with the exception of theta. I imagine this has to do with the units used for the &#8220;days left to expiration&#8221; field; my calculator uses fractions of a year, while BloBek doesn&#8217;t specify whether his days are to be trading days or calendar days. It could also be a bug in one of our implementations.</p>
<p>In Part 2, I&#8217;ll build a simple Swing GUI for the calculator.<br />
<b>Update:</b> <a href="http://www.paullegato.com/blog/swing-clojure-gui-black-scholes/" >Part 2, with the Swing GUI</a>, is now available. You can also get <a target="_blank" href="http://github.com/pjlegato/clojure_options" >the entire project&#8217;s source code</a> from GitHub.</p>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=345&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/black-scholes-clojure/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Lazy-spy: Clojure logging/spy for lazy sequences</title>
		<link>http://www.paullegato.com/blog/lazy-spy-clojure-logging-lazy-sequences/</link>
		<comments>http://www.paullegato.com/blog/lazy-spy-clojure-logging-lazy-sequences/#comments</comments>
		<pubDate>Mon, 24 May 2010 02:27:16 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=315</guid>
		<description><![CDATA[Clojure.contrib's log/spy macro does not realize the contents of lazy sequences by default when logging, as they might be infinitely long. If you're sure that your lazy sequence is finite, you can use this lazy-spy macro to force it to be realized when it's logged, so that you can inspect the contents.]]></description>
			<content:encoded><![CDATA[<p>Clojure.contrib&#8217;s <a target="_blank" href="http://richhickey.github.com/clojure-contrib/logging-api.html#clojure.contrib.logging/spy" ><code>logging/spy</code> macro</a> is really useful for quick investigation of bugs with unclear stack traces, and to check that intermediate values in a calculation are being returned and composed correctly. Lazy sequences don&#8217;t get logged correctly, however:</p>
<pre class="brush: clojure; title: ; notranslate">
&gt; (log/spy [1 2 3 4 5])
[1 2 3 4 5] ;;; prints &quot; [1 2 3 4 5] =&gt; [1 2 3 4 5]&quot; to the log
&gt; (log/spy (take 3 [1 2 3 4 5]))
(1 2 3) ;;; prints &quot;(take 3 [1 2 3 4 5]) =&gt; clojure.lang.LazySeq@8592&quot; to the log
</pre>
<p>The <code>spy</code> macro logs a string realization of the sequence per se, rather than its constituents. In the case of a concrete, fully realized sequence such as the literal vector in the first example, all values are known in advance, and the vector&#8217;s string realization in the log can helpfully be its actual contents. In the case of the lazy sequence returned by <code>take</code>, however, we get a less than helpful class name and some sort of instance identifier code rather than the actual contents of the sequence. A lazy sequence saves resources by merely promising to provide the values when asked. If they&#8217;re never asked for, they&#8217;re never computed. Since they haven&#8217;t been computed, they can&#8217;t be printed. A lazy sequence can also potentially be infinitely long, another good reason why they are not realized by default when converting the sequence to a string.</p>
<p>In our case, we don&#8217;t care about the resource usage, and we&#8217;re sure the sequence is finite. We want to force all values to be computed for manual inspection. (There are <a target="_blank" href="http://stackoverflow.com/questions/1641626/how-to-covert-a-lazy-sequence-to-a-non-lazy-in-clojure" >several ways of going about this</a>.) The following modification of the <code>spy</code> macro converts the lazy sequence into a regular seq:</p>
<pre class="brush: clojure; title: ; notranslate">
(defmacro lazy-spy
  &quot;Evaluates expr and outputs the form and its result to the debug log.
   If the result is a lazy sequence, it is realized concretely in the log.
   Returns the result of expr.&quot;
  [expr]
  `(let [a# ~expr] (log/log :debug (str '~expr &quot; =&gt; &quot;
                                    (if (= clojure.lang.LazySeq (class a#))
                                      (seq a#)
                                       a#)))
        a#))
</pre>
<p>This gives us:</p>
<pre class="brush: clojure; title: ; notranslate">
&gt; (lazy-spy  (take 3 [1 2 3 4 5]))
(1 2 3) ;;; prints &quot;(take 3 [1 2 3 4 5]) =&gt; (1 2 3)&quot; to the log
</pre>
<h2>Clojure posts you might also like:</h2>
<ul>
<li><a href="http://www.paullegato.com/blog/log4j-clojure/" >Log4J and Clojure Configuration</a></li>
<li><a href="http://www.paullegato.com/blog/setting-clojure-log-level/" >Setting Clojure’s Log Level</a></li>
<li><a href="http://www.paullegato.com/blog/sql-where-clojure-s-expressions/" >SQL WHERE clauses in Clojure from S-Expressions</a>
<li><a href="http://www.paullegato.com/blog/dtd-validation-malformed-xml-clojure/" >XML DTD Validation in Clojure: Turning It Off, Parsing Malformed XML</a></li>
</ul>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=315&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/lazy-spy-clojure-logging-lazy-sequences/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Log4J and Clojure Configuration</title>
		<link>http://www.paullegato.com/blog/log4j-clojure/</link>
		<comments>http://www.paullegato.com/blog/log4j-clojure/#comments</comments>
		<pubDate>Sun, 16 May 2010 22:12:48 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=292</guid>
		<description><![CDATA[Clojure, Log4J, and clojure.contrib.logging can play nicely together. Here's a reasonable default configuration.]]></description>
			<content:encoded><![CDATA[<p>Clojure, Log4J, and <code>clojure.contrib.logging</code> can play nicely together. Here&#8217;s a reasonable default configuration.</p>
<ol>
<li>
<p>If using <a target="_blank" href="http://github.com/technomancy/leiningen" >Leiningen</a>, add</p>
<pre class="brush: clojure; title: ; notranslate">
:dependencies [
                 [log4j &quot;1.2.15&quot; :exclusions [javax.mail/mail
                                              javax.jms/jms
                                              com.sun.jdmk/jmxtools
                                              com.sun.jmx/jmxri]]
]
</pre>
<p>to your <code>project.clj</code> file and rerun <code>lein deps</code> to auto-install the Log4J JAR.
</p>
<p>If not using Leiningen, <a target="_blank" href="http://logging.apache.org/log4j/1.2/download.html" >acquire a Log4J JAR</a> and put it on your classpath.</p>
</li>
<li>Create a file called <code>log4j.properties</code> on your classpath and put the following into it:
<pre class="brush: plain; title: ; notranslate">
# Based on the example properties given at http://logging.apache.org/log4j/1.2/manual.html
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern= %-5p %c - %m%n
</pre>
</li>
</ol>
<p>That&#8217;s the short version. Read on for the gory details.<span id="more-292"></span></p>
<h2>Logging philosophy</h2>
<p>My logging requirements are simple at the moment. I want to write messages to the console, each tagged with a log level (&#8220;INFO&#8221;, &#8220;WARN&#8221;, &#8220;ERROR&#8221;, etc.) I want to be able to set a log level, and only see log messages of that severity or higher. That&#8217;s it. I take this to be the canonical base case of logging that covers 80% of needs. All other logging features (e.g. logging to a file, differentiating by class or namespace) are nice, but much less common, and ought to be handled via configurable deviations from this default case.</p>
<p><code>clojure.contrib.logging</code> does not presently make it easy to do any of this common base case out of the box. The Lispy façade quickly falls apart; you&#8217;re <a href="http://www.paullegato.com/blog/setting-clojure-log-level/" >dumped into the deep end of the Java overengineering mire</a> without a life vest when you simply want to change the log level temporarily. </p>
<h3>What&#8217;s wrong with clojure.contrib.logging&#8217;s defaults?</h3>
<p><code>clojure.contrib.logging</code> with no special configuration done prefaces each and every logged line on my system with:</p>
<pre class="brush: plain; title: ; notranslate">
[null] May 16, 2010 1:08:48 PM clojure.contrib.logging$eval__2077$impl_write_BANG___2088 invoke
</pre>
<p>I have no idea why. This makes it very hard to read the log when logging any nontrivial amount of information.</p>
<p><a target="_blank" href="http://richhickey.github.com/clojure-contrib/logging-api.html" >clojure.contrib.logging&#8217;s documentation</a> contains a rather cryptic offhanded remark, with no further explanation: <em>Note: your log configuration should display the name that was passed to the logging implementation, and not perform stack-inspection, otherwise you&#8217;ll see something like &#8220;fn__72$impl_write_BANG__39__auto____81&#8243; in your logs.</em></p>
<p>My log configuration? Stack inspection? Why do I need to have a log configuration to just dump strings to the console? Why is the default case to print a verbose and useless header for each line? Isn&#8217;t this Javaesque mess &mdash; <a target="_blank" href="http://wiki.apache.org/logging-log4j/Log4jXmlFormat" >obscure 50 line XML configuration files just to get basic logging functionality working</a> &mdash; exactly what we&#8217;re trying to avoid?</p>
<h2>Log4J with <code>clojure.contrib.logging</code> configuration</h2>
<p>Ah, well, there&#8217;s nothing for it, I suppose.  Better just get a serious logging library and figure out how to configure it. The docs say that <code>clojure.contrib.logging</code> delegates to the first supported logging implementation that it finds. I am apparently using <a href="http://www.paullegato.com/blog/setting-clojure-log-level/" >the builtin JDK logger</a> by default, and Apache Commons&#8217; logger is just another wrapper, so I added Log4J to Leiningen&#8217;s project.clj and it installed the jar for me.</p>
<p>Now, I get:</p>
<pre class="brush: plain; title: ; notranslate">
     [null] log4j:WARN No appenders could be found for logger (my-project-name).
     [null] log4j:WARN Please initialize the log4j system properly.
</pre>
<p>Followed by dead silence.</p>
<p>Hm.</p>
<p>I can only imagine that Log4j was never intended to be used without a custom configuration. Odd. Why people design software that comes without reasonable defaults pre-set to cover the common base case is beyond me. I fully understand that strange setups will require customized configuration, but &#8220;dumping strings to the console&#8221; does not seem like a bizarre edge case for a logging package. A default case of &#8220;send all log messages to the black hole unless configured to do otherwise&#8221; makes little sense.</p>
<p>So, how hard can it be to configure Log4J for this base case functionality? The &#8220;<a target="_blank" href="http://logging.apache.org/log4j/1.2/manual.html" >short introduction to log4j</a>&#8221;  is 19 pages long. Sigh. (<a target="_blank" href="http://www.qos.ch/shop/products/log4jManual" >The complete manual</a> is proudly described as &#8220;over 200 pages.&#8221; I sometimes wonder if they overengineer Java libraries on purpose just to drive book sales.) </p>
<p>I do not want to know what a Nested Diagnostic Context is, or the precise semantic distinction between &#8220;Loggers,&#8221; &#8220;Appenders,&#8221; and &#8220;Layouts.&#8221; I don&#8217;t care about &#8220;Appender Additivity&#8221; and &#8220;Named Hierarchies,&#8221; and I certainly don&#8217;t want to write an XML configuration file. I Just want to log tagged strings to the console, and have them print without a bizarre autogenerated header line. That&#8217;s it. I fully appreciate that those things will be useful for some people &mdash; maybe even for me, when my project grows to become more complex. I have nothing against their existence; but for the base case, one should not need to know of it.</p>
<p>On page 9 of the &#8220;short&#8221; manual, after a boatload of irrelevant information, we have an answer: there is a class called <code>BasicConfigurator</code> with a static method that does reasonable initialization for logging to the console. We can just do <code>(org.apache.log4j.BasicConfigurator/configure)</code> and get that.</p>
<p>However, we are still getting log messages like:</p>
<pre class="brush: plain; title: ; notranslate">
     [null] 3702 [8633270@qtp-3149669-2] INFO my.namespace - log message
</pre>
<p>We have to learn something about <a target="_blank" href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/EnhancedPatternLayout.html" >Layouts</a> now. The thread names generated by Clojure are apparently not very useful, so we&#8217;re going to turn them off. And while interesting when profiling, the number of milliseconds since program start is just going to be visual clutter 98% of the time, so I&#8217;m going to turn that off, too, until I actually need it.</p>
<p>The result is the <code>log4j.properties</code> file listed above. Just copy and paste it into your classpath. If you want more or different information in your logs, take a look at the <a target="_blank" href="http://logging.apache.org/log4j/1.2/apidocs/index.html?org/apache/log4j/PatternLayout.html" >PatternLayout API documentation</a> and alter the <code>ConversionPattern</code> line according to your preferences.</p>
<p>The result:</p>
<pre class="brush: plain; title: ; notranslate">
     [null] INFO  my.namespace - log message
</pre>
<p>I&#8217;m still not sure where the <code>[null]</code> comes from, but overall, it&#8217;s very readable.</p>
<h2>Clojure posts you might also like:</h2>
<ul>
<li><a href="http://www.paullegato.com/blog/lazy-spy-clojure-logging-lazy-sequences/" >Lazy-spy: Clojure logging/spy for lazy sequences</a></li>
<li><a href="http://www.paullegato.com/blog/setting-clojure-log-level/" >Setting Clojure’s Log Level</a></li>
<li><a href="http://www.paullegato.com/blog/sql-where-clojure-s-expressions/" >SQL WHERE clauses in Clojure from S-Expressions</a>
<li><a href="http://www.paullegato.com/blog/dtd-validation-malformed-xml-clojure/" >XML DTD Validation in Clojure: Turning It Off, Parsing Malformed XML</a></li>
</ul>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=292&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/log4j-clojure/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

