<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>BadMagicNumber</title>
	
	<link>http://nicklothian.com/blog</link>
	<description>My Blog, Take 4</description>
	<lastBuildDate>Wed, 16 Dec 2009 00:09:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Badmagicnumber" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="badmagicnumber" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Using Flash to shim a webcam to Canvas</title>
		<link>http://nicklothian.com/blog/2009/12/15/using-flash-to-shim-a-webcam-to-canvas/</link>
		<comments>http://nicklothian.com/blog/2009/12/15/using-flash-to-shim-a-webcam-to-canvas/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 00:09:58 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=441</guid>
		<description><![CDATA[A couple of weeks ago I posted my work on developing virtual keypad using HTML5 video. That worked surprisingly well, but had some unfortunate requirements in that HTML5 doesn&#8217;t really support access to webcams.
Flash Does.
I&#8217;ve developed a Flash shim, which gets access to your webcam, and copies frames to data urls which can be used [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of weeks ago I posted my work on developing <a href="http://nicklothian.com/blog/2009/11/18/augmented-reality-virtual-keyboard-using-html-5-video/">virtual keypad using HTML5 video</a>. That worked surprisingly well, but had some unfortunate requirements in that HTML5 doesn&#8217;t really support access to webcams.</p>
<p>Flash Does.</p>
<p>I&#8217;ve developed a Flash shim, which gets access to your webcam, and copies frames to data urls which can be used in HTML DOM images.</p>
<p>This works well, within some limits:</p>
<ul>
<li>The performance of the Flash-&gt;Javascript interface is adequate for normal use, but drops off as the data being copied across increases in size. This means that you need to have a postage stamp sized (80&#215;60) video in flash to get adequate performance in HTML (~25 fps).</li>
<li>Chrome (and Safari?) leaks memory when new data URLs are created. (See <a href="http://code.google.com/p/chromium/issues/detail?id=25047">bug</a>). Apart from that, this technique works on both Chrome &amp; Firefox, but my virtual keypad is Firefox only ATM</li>
<li>I don&#8217;t really know Flash. I downloaded the Flex SDK a few days ago and started hacking, so I&#8217;m pretty sure <a href="http://demo.nicklothian.com/flashcamshim/cam.mxml">my Flash code</a> sucks.</li>
</ul>
<p><a href="http://demo.nicklothian.com/flashcamshim/">Here&#8217;s a demo</a>. Take a look at the <a href="http://nicklothian.com/blog/2009/11/18/augmented-reality-virtual-keyboard-using-html-5-video/">previous post</a> to see how you are supposed to use it. I started work on making a proper Javascript API for it, but yeah&#8230; The code is on GitHub, though: <a href="http://github.com/nlothian/FlashCamShim">http://github.com/nlothian/FlashCamShim</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=dKjtIBz6NXA:pkyosA6Tu_g:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=dKjtIBz6NXA:pkyosA6Tu_g:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Badmagicnumber/~4/dKjtIBz6NXA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/12/15/using-flash-to-shim-a-webcam-to-canvas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Augmented Reality Virtual Keyboard using HTML 5 video</title>
		<link>http://nicklothian.com/blog/2009/11/18/augmented-reality-virtual-keyboard-using-html-5-video/</link>
		<comments>http://nicklothian.com/blog/2009/11/18/augmented-reality-virtual-keyboard-using-html-5-video/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 07:47:20 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=417</guid>
		<description><![CDATA[I&#8217;ve been pretty impressed with some of the stuff ARKit can do, as well as the Microsoft Surface demos.
I decided that we need to do that on the web, too, so I build a virtual keypad, using HTML5 video and a webcam.
In HTML5, a common (example 1, example 2) pattern is to take an image [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been pretty impressed with some of the stuff <a href="http://www.youtube.com/watch?v=TeGdWu9tl1A">ARKit</a> can do, as well as the <a href="http://www.youtube.com/watch?v=Zxk_WywMTzc">Microsoft Surface demos</a>.</p>
<p>I decided that we need to do that on the web, too, so I build a virtual keypad, using HTML5 video and a webcam.</p>
<p>In HTML5, a common (<a href="http://people.mozilla.com/~prouget/demos/tracker/tracker.xhtml">example 1</a>, <a href="http://www.mozbox.org/pub/green/index.xhtml">example 2</a>) pattern is to take an image from a video, copy it to a canvas and manipulate it here using Javascript. That&#8217;s the general pattern I&#8217;ve used.</p>
<p>I use a colored marker (setup in a calibration phase) and track its location. In order to take account of brightness changes, etc, I do cosine similarity tests on average color vectors for each &#8220;key&#8221; on the keypad using the <a href="http://sylvester.jcoglan.com/">Sylvester Javascript vector library</a>.</p>
<p>I think there&#8217;s a fair bit of potential for video based interfaces. I&#8217;d like to see a combination of this and the <a href="http://www.randomthink.net/labs/html5drums/?/lab/html5drums/">HTML5 drumkit</a>, for example.</p>
<p>You can try it out here: <a href="http://demo.nicklothian.com/keypad/">http://demo.nicklothian.com/keypad/</a>. You&#8217;ll need to be using Firefox 3.5+.</p>
<p>Here&#8217;s a demo video (ironically as an embedded flash video):</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="665" height="513" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="play" value="true" /><param name="src" value="http://nicklothian.com/blog/wp-content/uploads/2009/11/keypad.swf" /><embed type="application/x-shockwave-flash" width="665" height="513" src="http://nicklothian.com/blog/wp-content/uploads/2009/11/keypad.swf" play="true"></embed></object></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=9Kl4JdHLOIA:5xNXQrxzbQw:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=9Kl4JdHLOIA:5xNXQrxzbQw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Badmagicnumber/~4/9Kl4JdHLOIA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/11/18/augmented-reality-virtual-keyboard-using-html-5-video/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using a webcam with HTML 5  via VLC</title>
		<link>http://nicklothian.com/blog/2009/11/17/using-a-webcam-with-html-5-via-vlc/</link>
		<comments>http://nicklothian.com/blog/2009/11/17/using-a-webcam-with-html-5-via-vlc/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 00:18:36 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=391</guid>
		<description><![CDATA[HTML 5 includes the &#60;video&#62; tag to enable embedding of video.
Unfortunately, and unlike Flash, there is no way to directly use a webcam with it. However, if you want to experiment with it some VLC+Apache magic can help.
Firstly, you need to setup VLC to do HTTP streaming. These instructions are for windows, but it works [...]]]></description>
			<content:encoded><![CDATA[<p>HTML 5 includes the &lt;video&gt; tag to enable embedding of video.</p>
<p>Unfortunately, and unlike Flash, there is no way to directly use a webcam with it. However, if you want to experiment with it some VLC+Apache magic can help.</p>
<p>Firstly, you need to setup VLC to do HTTP streaming. These instructions are for windows, but it works on Linux, too (Linux seems a lot less stable. I suspect that is a Firefox problem rather than VLC, though). VLC can be somewhat obtuse to use, so here&#8217;s how I got it working</p>
<h3>Step 1: Open VLC and select streaming</h3>
<p><img class="alignnone size-full wp-image-404" title="VLC - Select Streaming" src="http://nicklothian.com/blog/wp-content/uploads/2009/11/vlc1.png" alt="VLC - Select Streaming" width="367" height="387" /></p>
<h3>Step 2: Select Capture Device</h3>
<p><img class="alignnone size-full wp-image-405" title="VLC Select Capture Device" src="http://nicklothian.com/blog/wp-content/uploads/2009/11/vlc2.png" alt="VLC Select Capture Device" width="500" height="403" /></p>
<p>Click the &#8220;Stream&#8221; button.</p>
<h3>Step 3: Stream Dialog</h3>
<p><img class="alignnone size-full wp-image-407" title="VLC Stream Dialog" src="http://nicklothian.com/blog/wp-content/uploads/2009/11/vlc3.png" alt="VLC Stream Dialog" width="500" height="349" /></p>
<p>Click the &#8220;Next&#8221; button.</p>
<h3>Step 4: Add stream destination</h3>
<p><img class="alignnone size-full wp-image-408" title="VLC Add Destination" src="http://nicklothian.com/blog/wp-content/uploads/2009/11/vlc4.png" alt="VLC Add Destination" width="500" height="327" /></p>
<p>Select &#8220;HTTP&#8221;, check &#8220;Display Locally&#8221;, select the &#8220;Video &#8211; Thora + Vorbis (OGG)&#8221; profile and click &#8220;Add&#8221;</p>
<h3>Step 5: Configure the stream</h3>
<p><img class="alignnone size-full wp-image-409" title="VLC Configure Stream" src="http://nicklothian.com/blog/wp-content/uploads/2009/11/vlc5.png" alt="VLC Configure Stream" width="500" height="430" /></p>
<p>Note that I changed the port from the default of 8080 to 8081. This is optional, but note what port you use. Verify the profile is correct, and click the &#8220;Next&#8221; button.</p>
<h3>Step 6: Modify the stream path</h3>
<p><img class="alignnone size-full wp-image-410" title="VLC Modify Stream Path" src="http://nicklothian.com/blog/wp-content/uploads/2009/11/vlc6.png" alt="VLC Modify Stream Path" width="500" height="287" /></p>
<p>Carefully alter the &#8220;Generated stream output string&#8221; to include &#8220;/stream.ogg&#8221; after the port. You need to do this because Firefox uses the file extension to work out how to handle the file (in the absence of correct headers).</p>
<p>Click Stream, and VLC should display a window showing your webcam.</p>
<h3>Step 7: Verify streaming is working</h3>
<p>Go to http://localhost:8081/stream.ogg in Firefox. Chrome kind of works, too, sometime (I usually get the first frame, and then it stops playing).</p>
<h3>Optional Step</h3>
<p>This stream can be embedded in a webpage using the URL above. However, if you want to manipulate it in Javascript at all you will quickly run into the same-origin restriction. It&#8217;s possible to get around this by using Apache to proxy the stream onto the same site you serve yout pages and javascript from.</p>
<h3>Step 8: Configure Apache to Proxy Stream</h3>
<p>I use mod_proxy, and add the following:</p>
<pre><tt>ProxyPass /stream/stream.ogg http://localhost:8081/stream.ogg</tt></pre>
<p>That will allow you to view the stream from http://yourwebserver:port/stream/stream.ogg.</p>
<p>In my next post I aim to show something you can do with this stream.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=LvLqB64aeNE:2yTUKDl-1RE:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=LvLqB64aeNE:2yTUKDl-1RE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Badmagicnumber/~4/LvLqB64aeNE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/11/17/using-a-webcam-with-html-5-via-vlc/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Chrome Extension: Chrome Reload</title>
		<link>http://nicklothian.com/blog/2009/11/13/chrome-extension-chrome-reload/</link>
		<comments>http://nicklothian.com/blog/2009/11/13/chrome-extension-chrome-reload/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 10:20:09 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=399</guid>
		<description><![CDATA[I wrote my first Chrome extension. The APIs are pretty nice.
From the project page:

Chrome-Reload is an extension for the Chrome web browser to allow automatic periodic reloading of a page. It allows the you to configure how often each page reloads and see a count-down until the next load.
This is useful for scenarios such as [...]]]></description>
			<content:encoded><![CDATA[<p>I wrote my first Chrome extension. The APIs are pretty nice.</p>
<p>From the <a href="http://code.google.com/p/chrome-reload/">project page</a>:</p>
<blockquote><p>
Chrome-Reload is an extension for the Chrome web browser to allow automatic periodic reloading of a page. It allows the you to configure how often each page reloads and see a count-down until the next load.</p>
<p>This is useful for scenarios such as monitoring constantly changing pages (eg, search results), or for keeping sessions alive in web applications. </p></blockquote>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=xPJtPnS3qs8:-MgWiK3y5Tw:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=xPJtPnS3qs8:-MgWiK3y5Tw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Badmagicnumber/~4/xPJtPnS3qs8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/11/13/chrome-extension-chrome-reload/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Solr+Cassandra</title>
		<link>http://nicklothian.com/blog/2009/10/27/solr-cassandra-solandra/</link>
		<comments>http://nicklothian.com/blog/2009/10/27/solr-cassandra-solandra/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 03:15:21 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[cassandra]]></category>
		<category><![CDATA[solr]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=392</guid>
		<description><![CDATA[I&#8217;ve been a big fan of Solr for quite a long time, and have used it extensively at work.
I noticed a few weeks ago that Jake Luciani had managed to get Lucene (which Solr uses) working on Cassandra (Facebook&#8217;s highly scalable keystore).
The next step had an obvious name: Solandra &#8211; Solr running on Cassandra.
Basically there [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been a big fan of <a href="http://lucene.apache.org/solr/">Solr</a> for quite a long time, and have used it extensively at work.</p>
<p>I noticed a few weeks ago that <a href="http://3.rdrail.net/blog/">Jake Luciani</a> had managed to get Lucene (which Solr uses) <a href="http://github.com/tjake/Lucandra">working </a>on <a href="http://incubator.apache.org/cassandra/">Cassandra</a> (Facebook&#8217;s highly scalable keystore).</p>
<p>The next step had an obvious name: Solandra &#8211; Solr running on Cassandra.</p>
<p>Basically there wasn&#8217;t too much to getting it going in the limited form it is now &#8211; a few minor changes to Jake&#8217;s Lucandra code, a custom Solr FieldType (exactly why I needed this I&#8217;m unsure) and correctly configured solrconfig.xml and schema.xml files.</p>
<p>I haven&#8217;t tested updates, so you&#8217;ll probably need Jake&#8217;s <a href="http://github.com/tjake/Lucandra/blob/master/test/lucandra/demo/BookmarksDemo.java">BookmarkDemo</a> to load data in.</p>
<p>My changes to the Lucandra index reader include hard coding (!) the fields returned by getFieldNames(..) to match the Solr schema and the fields added in the demo.</p>
<p>If anyone is interested, the code is available: <a href="http://nicklothian.com/files/solandra28102009.zip">solandra.zip</a>. You&#8217;ll need to be a Java developer to use it, though.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=9AW0m5-jewI:WU1ZrdwzRT8:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=9AW0m5-jewI:WU1ZrdwzRT8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Badmagicnumber/~4/9AW0m5-jewI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/10/27/solr-cassandra-solandra/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cross domain, cross window Javascript communication</title>
		<link>http://nicklothian.com/blog/2009/08/05/cross-domain-cross-window-javascript-communication/</link>
		<comments>http://nicklothian.com/blog/2009/08/05/cross-domain-cross-window-javascript-communication/#comments</comments>
		<pubDate>Thu, 06 Aug 2009 02:24:34 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=379</guid>
		<description><![CDATA[The scenario: A typical meeting, they want to pop up our search screen, select an item and have it post back via Javascript the selected item. &#8220;Sure, no problem&#8221; I say. &#8220;Can you do cross domain Javascript like that&#8221; their dev asks, and I think for a second about all the IFrame proxy hacks I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>The scenario: A typical meeting, they want to pop up our search screen, select an item and have it post back via Javascript the selected item. &#8220;Sure, no problem&#8221; I say. &#8220;Can you do cross domain Javascript like that&#8221; their dev asks, and I think for a second about all the IFrame proxy hacks I&#8217;ve seen and say &#8220;yeah, no problems&#8221;.</p>
<p>Doh.</p>
<p>So I get back to work, and talk to Ben-out-local-Javascript-god, who points me at the location-fragment for communication hack (see, for example <a href="http://tagneto.blogspot.com/2006/06/cross-domain-frame-communication-with.html">Cross Domain Frame Communication with Fragment Identifiers (for Comet?)</a>) and away I go.</p>
<p>I quickly discover that all the documentation on that is for use with frames, not windows, and windows work slightly different. For example, the parent window can&#8217;t poll the child for it&#8217;s location.hash, nor can the child set the parent&#8217;s location.hash. </p>
<p>Doh Doh.</p>
<p>Anyway to cut a long story short and to document it for anyone else, you can make it work. The child window needs to contain a iframe from the parent domain, then proxy communication though that. Modern non IE browsers can use <a href="http://ejohn.org/blog/cross-window-messaging/">Window.postMessage</a> to do the same thing (Actually, IE8 supports Window.postMessage, too, but I couldn&#8217;t get it to work properly).</p>
<p>The core of the IE specific code looks like this. The child window uses this object:</p>
<p><code></p>
<pre>
/*
  XDCommsChild - Cross Domain Communication, Child Object.

   Create this in the child window with the address of the xdomaincomms.html file on the same domain as the parent window
*/
var XDCommsChild = function(xdomaincommsAddress) {
    this.xdomaincommsAddress = xdomaincommsAddress;

    this.isIe = isInternetExplorer();

    if (isIe) {
        // need hidden frame for communication. IE8 is supposed to support postMessage, but I can't get it to work properly
        document.writeln("<iframe style='display:none' name='xdcomms' src='" + this.xdomaincommsAddress + "' width='1px' height='1px'></iframe>")
    }

    this.postBack = function(data) {
        if (isIe) {
            // this method tested against IE6,7 &#038; 8
            window.open(this.xdomaincommsAddress + '#data=' + data, 'xdcomms'); // MUST use window.open. frame.src or frame.location both fail
        } else {
            // for everything else - tested against Firefox 3, Chrome, Safari
            window.opener.postMessage(data, '*'); // should really restrict the domain data can come from here
        }
    }

    this.postBackAndCloseWindow = function(data){
        this.postBack(data);
        setTimeout("window.close()", 200); // need to use a timeout to make sure the javascript in the frame has executed if we are using that communication model
    }
}
</pre>
<p></code></p>
<p>Then the included proxy frame (deployed on the parent domain) looks like this:</p>
<p><code> </p>
<pre>
           var hash = null;

            function sendData() {
                hash = location.hash;
                if (hash != null &#038;&#038; hash.length > 1) {
                    window.parent.opener.location.hash=hash;
                    location.hash = '#';
                }
            }

            setInterval("sendData()", 50);
</pre>
<p></code></p>
<p>The the parent window uses this object:</p>
<p><code></p>
<pre>
/*
  XDCommsParent - Cross Domain Communication, Parent Object.

   Create this in the parent window with a callback function that will recieve data.
*/
var XDCommsParent = function(dataRecievedCallback) {
    this.dataRecievedCallback = dataRecievedCallback;

    this.isIe = isInternetExplorer();

    this.receiveMessage = function(event) {
        dataRecievedCallback(event.data);
    }

    if (this.isIe) {
        window.setInterval("pollForData()", 200);
    } else {
        window.addEventListener("message", this.receiveMessage, false);
    }

}
</pre>
<p></code></p>
<p>The final piece of the solution is calling it from the child window. I do this:</p>
<p><code></p>
<pre>
&lt;button onclick="javascript:xDCommsChild.postBackAndCloseWindow(document.getElementById('thevalue').value);"&gt;Send to Parent Window&lt;/button&gt;
</pre>
<p></code></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=L6t3kpJCPFk:JBL89iAS2w8:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=L6t3kpJCPFk:JBL89iAS2w8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Badmagicnumber/~4/L6t3kpJCPFk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/08/05/cross-domain-cross-window-javascript-communication/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Fixing Firefox performance and lock-ups on Linux</title>
		<link>http://nicklothian.com/blog/2009/05/05/fixing-firefox-performance-and-lock-ups-on-linux/</link>
		<comments>http://nicklothian.com/blog/2009/05/05/fixing-firefox-performance-and-lock-ups-on-linux/#comments</comments>
		<pubDate>Tue, 05 May 2009 23:32:18 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[random]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=373</guid>
		<description><![CDATA[I&#8217;ve been using Ubuntu (8.04 then 8.10) reasonably heavily over the last 12 months or so as my main operating system on two of my home computers (a Dell Mini 9&#8243; and a quad core desktop).
I&#8217;ve been pretty happy with it except for the infuriating habit Firefox has for &#8220;locking up&#8221; periodically. The symptoms of [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using Ubuntu (8.04 then 8.10) reasonably heavily over the last 12 months or so as my main operating system on two of my home computers (a Dell Mini 9&#8243; and a quad core desktop).</p>
<p>I&#8217;ve been pretty happy with it except for the infuriating habit Firefox has for &#8220;locking up&#8221; periodically. The symptoms of this include non-reponsiveness, screen freezing and even the computer being unusable for 30 seconds at a time. The only clue I had was there seemed to be large amounts of disk usage.</p>
<p>After a while bitching and moaning about it I got so annoyed I started looking for a fix. </p>
<p>The first thing I tried was the Chromium Linux nightly builds. Google says &#8220;blogging about this isn&#8217;t helpful&#8221;, so I won&#8217;t except to say that I&#8217;ve got pretty high expectations of Chrome on Linux and so far I haven&#8217;t had to re-apprise that.</p>
<p>All the same, I wanted to fix Firefox. The next thing I tried was moving Firefox cache to a RAM drive. That&#8217;s pretty easy &#8211; just set it to use a directory under /dev/shm/ for the cache location. </p>
<p>I think that improved the situation marginally, but not enough to call it a fix.</p>
<p>The next thing I tried was to raise a <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=491413">Firefox bug</a>. Somewhat to my surprise that got linked to <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=421482">another bug</a> which was marked as fixed.</p>
<p>The comments on that bug are quite long, but the story is this:</p>
<ul>
<li>Firefox uses <a href="http://www.sqlite.org/">SQLite</a> as a database for its history and bookmarks.</li>
<li>SQLite, being a database is very concerned about <a href="http://www.sqlite.org/lockingv3.html">data integrity</a>, and to implement this it relies on the fsync system call.</li>
<li>fsync has performance issues on ext3 filesystems. See for example, <a href="http://lwn.net/Articles/328363/">http://lwn.net/Articles/328363/</a>:<br />
<blockquote><p>
The problem, in short, is this: the ext3 filesystem, when running in the default data=ordered mode, can exhibit lengthy stalls when some process calls fsync() to flush data to disk. This issue most famously manifested itself as the much-lamented Firefox system-freeze problem, but it goes beyond just Firefox.
</p></blockquote>
<li>SQLite has a no-sync mode, which trades reliability for performance.</li>
<li>Firefox can use this mode via a config setting.</li>
</ul>
<p>So the outcome of all that is this:</p>
<p><strong>Create a new config key &#8220;toolkit.storage.synchronous&#8221; and set it to the integer 0 to stop Firefox lock-ups on Linux </strong>(but be aware that there is some chance a power failure could cause loss of your history and/or bookmarks).</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=xDMvsJBeZ38:xIHZHH7Qd1E:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=xDMvsJBeZ38:xIHZHH7Qd1E:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Badmagicnumber/~4/xDMvsJBeZ38" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/05/05/fixing-firefox-performance-and-lock-ups-on-linux/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The AppEngine is forking Java “controversy”</title>
		<link>http://nicklothian.com/blog/2009/04/13/the-appengine-is-forking-java-controversy/</link>
		<comments>http://nicklothian.com/blog/2009/04/13/the-appengine-is-forking-java-controversy/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 01:01:00 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=370</guid>
		<description><![CDATA[So there has been some noise from Sun about how Google AppEngine is evil because it&#8217;s not supporting the complete set of classes in the JRE. I&#8217;m sorry Sun &#8211; I&#8217;m a Java programmer, and I think that argument is shit. I&#8217;d much prefer a partial Java implementation with well defined limitations than PHP, or [...]]]></description>
			<content:encoded><![CDATA[<p>So there has been some noise from Sun about how Google AppEngine is evil because it&#8217;s not supporting the complete set of classes in the JRE. I&#8217;m sorry Sun &#8211; I&#8217;m a Java programmer, and I think that argument is shit. I&#8217;d much prefer a partial Java implementation with well defined limitations than PHP, or Python or Ruby.</p>
<p>AFAIK, no one has posted a list of classes missing. I can&#8217;t be bothered doing that either, but I did manually take a look at package level. Here&#8217;s it looks like GAE/J is missing:</p>
<p>java.applet<br />
java.awt.*<br />
javax.activation<br />
javax.imageio.*<br />
javax.jws.*<br />
javax.management.*<br />
javax.naming.*<br />
javax.net.*<br />
javax.print.*<br />
javax.rmi.*<br />
javax.sound.*<br />
javax.swing.*<br />
javax.tools<br />
javax.xml.bind.*<br />
javax.xml.crypto.*<br />
javax.xml.soap<br />
javax.xml.stream.*<br />
javax.xml.ws<br />
org.ietf.jgss<br />
org.omg.*</p>
<p>From that list, I&#8217;d like to see javax.activation, javax.management and the remaining javax.xml.* and maybe javax.tools packages supported. The rest really don&#8217;t seem at all relevant to the AppEngine environment.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=sHRrkEU9vgc:HmzXqWLu_xo:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=sHRrkEU9vgc:HmzXqWLu_xo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Badmagicnumber/~4/sHRrkEU9vgc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/04/13/the-appengine-is-forking-java-controversy/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Random MP3 metadata code</title>
		<link>http://nicklothian.com/blog/2009/03/18/random-mp3-metadata-code/</link>
		<comments>http://nicklothian.com/blog/2009/03/18/random-mp3-metadata-code/#comments</comments>
		<pubDate>Wed, 18 Mar 2009 09:08:59 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=364</guid>
		<description><![CDATA[I&#8217;ve been doing random MP3 metadata work lately. Here&#8217;s some code which others might find useful.
Extracting MP3 tags from mp3 file hosted on server using HTTP Range queries.
So I was using Apache Tika for various metadata stuff. I wanted to get the song title for a file hosted on a server, but Tika only supports [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been doing random MP3 metadata work lately. Here&#8217;s some code which others might find useful.</p>
<p><strong>Extracting MP3 tags from mp3 file hosted on server using HTTP Range queries.</strong></p>
<p>So I was using <a href="http://lucene.apache.org/tika/">Apache Tika</a> for various metadata stuff. I wanted to get the song title for a file hosted on a server, but Tika only supports MP3 ID3v1 metadata, which exists at the end of a file. Downloading an entire MP3 just for the title is wasteful, but fortunatly HTTP Range queries can help us out.</p>
<p><tt></p>
<pre>HttpClient httpClient = new HttpClient();
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(10000);
httpClient.getHttpConnectionManager().getParams().setSoTimeout(10000);

String address = "http://address of mp3 file here";

HttpMethod method = new HeadMethod();
method.setURI(new URI(address,true));

Header contentLengthHeader = null;
Header acceptHeader = null;

httpClient.executeMethod(method);
try {
	//System.out.println(Arrays.toString(method.getResponseHeaders()));
	contentLengthHeader = method.getResponseHeader("Content-Length");
	acceptHeader = method.getResponseHeader("Accept-Ranges");
} finally {
	method.releaseConnection();
}

if ((contentLengthHeader != null) &amp;&amp; (acceptHeader != null) &amp;&amp; "bytes".equals(acceptHeader.getValue())) {
	long contentLength = Long.parseLong(contentLengthHeader.getValue());
	long metaDataStartRange = contentLength - 128;
	if (metaDataStartRange &gt; 0) {
		method = new GetMethod();
		method.setURI(new URI(address,true));
		method.addRequestHeader("Range", "bytes=" + metaDataStartRange + "-" + contentLength);
		System.out.println(Arrays.toString(method.getRequestHeaders()));
		httpClient.executeMethod(method);
		try {
			Parser parser = new AutoDetectParser();

			Metadata metadata = new Metadata();
			metadata.set(Metadata.RESOURCE_NAME_KEY, address);
			InputStream stream = method.getResponseBodyAsStream();
			try {
				parser.parse(stream, new DefaultHandler(), metadata);
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				stream.close();
			}
			System.out.println(Arrays.toString(metadata.names()));
			System.out.println("Title: " + metadata.get("title"));
			System.out.println("Author: " + metadata.get("Author"));
		} finally {
			method.releaseConnection();
		}
	}
} else {
	System.err.println("Range not supported. Headers were: ");
	System.err.println(Arrays.toString(method.getResponseHeaders()));
}
</pre>
<p></tt></p>
<p>The next thing I needed to do was extract song titles from a shoutcast stream. Shoutcast streams are kinda-but-not-quite http. Metadata is embedded in the stream (not as part of the MP3). That makes the code pretty ugly, but whatever&#8230; This code will open a connection, read the metadata and close, so you don&#8217;t need to keep downloading gigs of data.
</p>
<p><tt></p>
<pre>
URL url = new URL("http://scfire-ntc-aa01.stream.aol.com:80/stream/1074");
URLConnection con = url.openConnection();
con.setRequestProperty("Icy-MetaData", "1");

InputStream stream = con.getInputStream();
try {

	BufferedReader in = new BufferedReader(new InputStreamReader(stream));

	String metaIntervalString = null;
	// get the headers
	StringBuilder headers = new StringBuilder();
	char c;
	while ((c = (char)in.read()) != -1) {
		headers.append(c);
		if (headers.length() > 5 &#038;&#038; (headers.substring((headers.length() - 4), headers.length()).equals("\r\n\r\n"))) {
			// end of headers
			break;
		}
	}

	//System.out.println(headers);
	// headers look like this:
	//		ICY 200 OK
	//		icy-notice1: <BR>This stream requires <a href="http://www.winamp.com/">Winamp</a><BR>
	//		icy-notice2: Firehose Ultravox/SHOUTcast Relay Server/Linux v2.6.0<BR>
	//		icy-name: .977 The 80s Channel
	//		icy-genre: 80s Pop Rock
	//		icy-url: http://www.977music.com
	//		content-type: audio/mpeg
	//		icy-pub: 1
	//		icy-metaint: 16384
	//		icy-br: 128

	Pattern p = Pattern.compile("\\r\\n(icy-metaint):\\s*(.*)\\r\\n");
	Matcher m = p.matcher(headers.toString());
	if (m.find()) {
		metaIntervalString = m.group(2);
	}

	if (metaIntervalString != null) {
		int metaInterval = Integer.parseInt(metaIntervalString.trim());

		if (metaInterval > 0) {
			int b;
			int count = 0;
			int metaDataLength = 4080; // 4080 is the max length
			boolean inData = false;
			StringBuilder metaData = new StringBuilder();
			while ((b = stream.read()) != -1) {
				count++;

				if (count == metaInterval + 1) {
					metaDataLength = b * 16;
				}

				if (count > metaInterval + 1 &#038;&#038; count < (metaInterval + metaDataLength)) {
					inData = true;

				} else {
					inData = false;
				}

				if (inData) {
					if (b != 0) {
						metaData.append((char)b);
					}
				}

				if (count > (metaInterval + metaDataLength)) {
					break;
				}

			}
			String metaDataString = metaData.toString();
			System.out.println(metaDataString);
		}
	}
} finally {
	stream.close();
}
</pre>
<p></tt></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=kzA80MEvpI4:DyIv3ea4O0o:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=kzA80MEvpI4:DyIv3ea4O0o:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Badmagicnumber/~4/kzA80MEvpI4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/03/18/random-mp3-metadata-code/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ROME 1.0 Released</title>
		<link>http://nicklothian.com/blog/2009/03/11/rome-10-released/</link>
		<comments>http://nicklothian.com/blog/2009/03/11/rome-10-released/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 00:47:43 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[ROME]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=360</guid>
		<description><![CDATA[I&#8217;ve just pushed out ROME 1.0 and ROME Fetcher 1.0.
As they say with open source projects &#8211; &#8220;it&#8217;s done when it&#8217;s done&#8221;. But nearly 5 years to get to version 1.0 is kind of long.
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just pushed out <a href="http://rome.dev.java.net/">ROME 1.0</a> and <a href="http://wiki.java.net/bin/view/Javawsxml/RomeFetcher">ROME Fetcher 1.0</a>.</p>
<p>As they say with open source projects &#8211; &#8220;it&#8217;s done when it&#8217;s done&#8221;. But nearly 5 years to get to version 1.0 is kind of long.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=ugUvUWf6CaQ:Zd7_N-o1i54:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Badmagicnumber?a=ugUvUWf6CaQ:Zd7_N-o1i54:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Badmagicnumber?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Badmagicnumber/~4/ugUvUWf6CaQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/03/11/rome-10-released/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss><!-- Dynamic Page Served (once) in 0.592 seconds -->
