<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7218232242203115351</id><updated>2010-07-10T04:37:39.881-06:00</updated><title type='text'>One Man Clapping</title><subtitle type='html'>Personal blog for Gary Dusbabek</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default?start-index=26&amp;max-results=25'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>191</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-3848706061738447643</id><published>2010-03-11T13:00:00.007-07:00</published><updated>2010-03-11T13:03:04.098-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cassandra'/><title type='text'>Running Multiple Cassandra Nodes on a Single Host</title><content type='html'>One of the first &lt;a href="http://incubator.apache.org/cassandra/"&gt;Cassandra&lt;/a&gt; tickets I worked on had me reviewing some code that visualized the node ring.&amp;nbsp; Properly testing the code required that I run a cluster.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;But I didn't have access to a cluster. Neither did I feel like creating a virtual cluster by building a VM and cloning it several times.&amp;nbsp; What I wanted was to run several instances of Cassandra on a single machine with multiple interfaces, all pointed at the same compiled code (without multiple svn checkouts).&lt;br /&gt;&lt;br /&gt;The Cassandra wiki explains how to &lt;a href="http://wiki.apache.org/cassandra/RunningCassandra"&gt;tweak Cassandra settings&lt;/a&gt; by editing &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;cassandra.in.sh&lt;/span&gt;, but doesn't explain what needs to be done to run concurrent instances.&lt;br /&gt;&lt;br /&gt;It turned out not to be too difficult.&amp;nbsp; I figured it might be daunting enough to Cassandra noobs (of whom we're seeing more of lately due to &lt;a href="http://nosql.mypopescu.com/post/407159447/cassandra-twitter-an-interview-with-ryan-king"&gt;some&lt;/a&gt; &lt;a href="http://about.digg.com/node/564"&gt;great&lt;/a&gt; &lt;a href="http://www.brianfrankcooper.net/pubs/ycsb-v4.pdf"&gt;exposure&lt;/a&gt;), that a blog post might be helpful.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;This tutorial assumes that you'll want to run multiple instances of Cassandra on code built by &lt;a href="http://ant.apache.org/"&gt;ant&lt;/a&gt; and not a standalone jar.&amp;nbsp; I am also assuming that you are a) just playing around, or b) intend to do some development.&amp;nbsp; This &lt;b&gt;is not&lt;/b&gt; a tutorial explaining how Cassandra should be run in production.&lt;br /&gt;&lt;br /&gt;Note: I apologize for the way this looks.&amp;nbsp; Blogger is not a friend of ordered lists. &lt;br /&gt;&lt;ol type="1"&gt;&lt;li&gt;Make sure you've got aliases to localhost (e.g.: 127.0.0.2, 127.0.0.3, etc.).&amp;nbsp; Mac OS X doesn't have this enabled by default, so you'll have to manually create aliases:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;sudo ifconfig lo0 alias 127.0.0.2 up&lt;/pre&gt;&lt;pre&gt;sudo ifconfig lo0 alias 127.0.0.3 up&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Decide where you're going to keep things.&amp;nbsp; You can keep them with your code, but that just isn't neat.&amp;nbsp; Pick a directory somewhere, call it &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$cass_stuff&lt;/span&gt;. &lt;/li&gt;&lt;li&gt;Then, for each node in your little cluster, do this:&lt;br /&gt;&lt;br /&gt;&lt;ol type="a"&gt;&lt;li&gt;From your svn checkout, copy the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;conf&lt;/span&gt; directory into &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$cass_stuff&lt;/span&gt;.&amp;nbsp; You can rename it to something like &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;conf0&lt;/span&gt; (or &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;conf1&lt;/span&gt;, etc.).&amp;nbsp; I'll assume &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$conf&lt;/span&gt; from here on out.&lt;/li&gt;&lt;li&gt;Copy &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;bin/cassandra.in.sh&lt;/span&gt; to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$cass_stuff&lt;/span&gt;.&amp;nbsp; Give it a name that helps you associate it with the conf directory you just created (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;node0.in.sh&lt;/span&gt; or whatever).&lt;/li&gt;&lt;li&gt;Open &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;node0.in.sh&lt;/span&gt; in an editor and make the following changes:&lt;br /&gt;&lt;br /&gt;&lt;ol type="i"&gt;&lt;li&gt;Hardcode &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;cassandra_home&lt;/span&gt; to the location of your trunk.&amp;nbsp; This will give you the flexibility to run Cassandra from anywhere.&lt;/li&gt;&lt;li&gt;Set &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;CASSANDRA_CONF&lt;/span&gt; to the conf directory you just created.&lt;/li&gt;&lt;li&gt;In the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;JVM_OPTS&lt;/span&gt; change the jdwp &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;address=&lt;/span&gt; setting.&amp;nbsp; The default is &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;8888&lt;/span&gt;, but you should include the unique IP you chose for this node along with the port, e.g.: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;127.0.0.2:8888&lt;/span&gt;.&amp;nbsp; Not specifying a host causes the debugger to bind to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;0.0.0.0:8888&lt;/span&gt; and you'll have port binding problems when you bring up more than one node.&lt;/li&gt;&lt;li&gt;pick a unique port for &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;com.sun.management.jmxremote.port&lt;/span&gt;, but make sure you have at least one node listening on &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;8080&lt;/span&gt; since all the Cassandra tools assume JMX is listening there.&amp;nbsp; Unfortunately, you can't pick the JMX host, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;0.0.0.0&lt;/span&gt; is assumed.&amp;nbsp; I was under the impression this could be changed by specifying &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;java.rmi.server.hostname&lt;/span&gt;, but had no luck going down that road.&amp;nbsp; (Please leave a comment if you figure out a way for this to work, but I think &lt;a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6425769"&gt;it might be hopeless&lt;/a&gt;.)&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;li&gt;Open &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$cass_stuff/$conf/storage-conf.xml&lt;/span&gt; in an editor and make the following changes:&lt;br /&gt;&lt;br /&gt;&lt;ol type="a"&gt;&lt;li&gt;specify unique locations for &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;CommitLogDirectory&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;DataFileDirectory&lt;/span&gt;.&amp;nbsp; Don't bother with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;CalloutLocation&lt;/span&gt; or &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;StagingFileDirectory&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;replace &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ListenAddress&lt;/span&gt; with the IP of your host.&lt;/li&gt;&lt;li&gt;replace &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;RPCAddress&lt;/span&gt; with the IP of your host.&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;/ol&gt;To run you may wish to use another script for each node:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#!/bin/sh&lt;/div&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;CASSANDRA_INCLUDE=$cass_stuff/&lt;/span&gt;&lt;your node.in.sh=""&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; export CASSANDRA_INCLUDE&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; cd &lt;/span&gt;&lt;to code="" is="" source="" wherever="" your=""&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; bin/cassandra -f&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One downside to this approach is that if you're tracking trunk, it is your responsibility to make sure you notice changes to the default &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;storage-conf.xml&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;cassandra.in.sh&lt;/span&gt; and apply them to your environments.&lt;/to&gt;&lt;/your&gt;&lt;br /&gt;&lt;br /&gt;&lt;your node.in.sh=""&gt;&lt;to code="" is="" source="" wherever="" your=""&gt;Cassandra is supported by an active and welcoming community.&amp;nbsp; If you'd like to learn more about the project, check out our &lt;a href="http://wiki.apache.org/cassandra/"&gt;wiki&lt;/a&gt;,  &lt;a href="http://www.mail-archive.com/cassandra-user@incubator.apache.org/"&gt;mailing list&lt;/a&gt; or hop on #cassandra on freenode.&lt;/to&gt;&lt;/your&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-3848706061738447643?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/3848706061738447643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=3848706061738447643' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/3848706061738447643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/3848706061738447643'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2010/03/running-multiple-cassandra-nodes-on.html' title='Running Multiple Cassandra Nodes on a Single Host'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-3073780893766942013</id><published>2009-12-15T18:00:00.004-07:00</published><updated>2009-12-15T18:00:00.138-07:00</updated><title type='text'>Dear Entrepreneurs, this is something I would pay for...</title><content type='html'>Dear Entrepreneurs,&lt;br /&gt;&lt;br /&gt;This is something I would gladly pay $20 a month for...&lt;br /&gt;&lt;br /&gt;A device that, according to my tastes, downloads new music from the Internet whenever it connects.&amp;nbsp; I would be able to listen to music without restriction while I am disconnected from the network.&amp;nbsp; I wouldn't own the music, except for roughly 20 tracks a month that I select which would then become mine as MP3s (for FLAC or whatever DRM-less technology makes sense).&amp;nbsp; I could then load them into iTunes, give them to my brother, or (if I'm feeling sinister) make them available on a P2P network.&lt;br /&gt;&lt;br /&gt;The music could come from anywhere: iTunes, Amazon, The Labels, or artists themselves.&lt;br /&gt;&lt;br /&gt;The content sources exist.&amp;nbsp; The recommendation engines exist.&amp;nbsp; Devices exist.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;I suspect the audience/market exists.&amp;nbsp; (At least, I hope so.&amp;nbsp; If not, and nobody is willing to pay for music, we're going to need to find another model.&amp;nbsp; And it will still necessarily involve a money exchange between producers and cosumers and/or advertisers.)&lt;br /&gt;&lt;br /&gt;Is there such a system already?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-3073780893766942013?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/3073780893766942013/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=3073780893766942013' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/3073780893766942013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/3073780893766942013'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/12/dear-entrepreneurs-this-is-something-i.html' title='Dear Entrepreneurs, this is something I would pay for...'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-8422141135547691947</id><published>2009-12-13T22:00:00.000-07:00</published><updated>2009-12-15T09:35:11.494-07:00</updated><title type='text'>Christmas Mix 2009</title><content type='html'>I've been making&amp;nbsp; Christmas mixes for my family the last couple years.&amp;nbsp; It's not your typical Bing Crosby stuff, and requires some digging on my part.&amp;nbsp; I finally started &lt;a href="http://www.onemanclapping.org/2008/12/christmas-tunes.html"&gt;blogging about it last&lt;/a&gt; year and think I'm going to make it a tradition.&amp;nbsp; So here goes... Christmas with an indie slant.&amp;nbsp; And I did a better job checking on the lyrics this year for family appropriateness. &lt;br /&gt;&lt;br /&gt;The links this year are coming at you from Lala by way of Google.&amp;nbsp; Message me if things stop working.&amp;nbsp; (This blog post has turned out much like my Christmas shopping: it gets sloppy towards the end.)&lt;br /&gt;&lt;br /&gt;1.&amp;nbsp; &lt;a href="http://www.google.com/url?url=http://popup.lala.com/popup/360569470963941402&amp;amp;rct=j&amp;amp;ei=8fYcS-2WJs3jnAfey5TWAw&amp;amp;sa=X&amp;amp;oi=music_play_track&amp;amp;resnum=1&amp;amp;ct=result&amp;amp;cd=2&amp;amp;ved=0CAgQ0wQoADAA&amp;amp;q=holiday+road+matt+pond+pa&amp;amp;usg=AFQjCNFqpZHWrGCoHWcHjrcqD10nMW92Mg"&gt;"Holiday Road"&lt;/a&gt; by &lt;a href="http://www.mattpondpa.com/?cat=1"&gt;Matt Pond PA&lt;/a&gt;.&amp;nbsp; This is the only repeat from last years list.&amp;nbsp; I love this song because the &lt;a href="http://en.wikipedia.org/wiki/National_Lampoon%27s_Vacation"&gt;vacation movies&lt;/a&gt; still connect with me at a level I am entirely uncomfortable with.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;2.&amp;nbsp; &lt;a href="http://www.dreadzeppelin.com/presents.html"&gt;"Blue Christmas"&lt;/a&gt; by &lt;a href="http://www.dreadzeppelin.com/"&gt;Dread Zeppelin&lt;/a&gt;.&amp;nbsp; Believe it or not, there is a nice smattering of Christmas to choose from with these guys. Where else can you get Elvis, Led Zeppelin, Reggae and Christmas in one track?&lt;br /&gt;&lt;br /&gt;3.&amp;nbsp; &lt;a href="http://www.google.com/url?url=http://popup.lala.com/popup/432627082213989860&amp;amp;rct=j&amp;amp;ei=PvgcS4T1K8Wvngfyy9TVAw&amp;amp;sa=X&amp;amp;oi=music_play_track&amp;amp;resnum=1&amp;amp;ct=result&amp;amp;cd=2&amp;amp;ved=0CAgQ0wQoADAA&amp;amp;q=christmas+is+going+to+the+dogs+eels&amp;amp;usg=AFQjCNEsGEbwuYKo_nKrRgJ9--34Z3Rb9Q"&gt;"Christmas is Going to the Dogs"&lt;/a&gt; by &lt;a href="http://www.eelstheband.com/"&gt;Eels&lt;/a&gt;.&amp;nbsp; Hard choice between this and &lt;a href="http://www.google.com/url?url=http://popup.lala.com/popup/432627082213539968&amp;amp;rct=j&amp;amp;ei=oPgcS7GgBtLgnAeLlYXOAw&amp;amp;sa=X&amp;amp;oi=music_play_track&amp;amp;resnum=1&amp;amp;ct=result&amp;amp;cd=2&amp;amp;ved=0CAgQ0wQoADAA&amp;amp;q=everything%27s+gonna+be+cool+this+Christmas+eels&amp;amp;usg=AFQjCNF0Lwgnj3PWMf1DAYbMx6z9ap141A"&gt;"Everything's Gonna Be Cool This Christmas"&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;4.&amp;nbsp; &lt;a href="http://www.youtube.com/watch?v=Tz97VEY9S0w"&gt;"I Wish It Was Christmas Today"&lt;/a&gt;&amp;nbsp; by &lt;a href="http://www.juliancasablancas.com/"&gt;Julian Casablancas&lt;/a&gt;.&amp;nbsp; This one is for the kids.&amp;nbsp; I wish that I could still feel the way I did when I was a young boy after Thanksgiving.&amp;nbsp; Christmas, although only four weeks away, seemed like it sat on the other side of eternity.&amp;nbsp; As an adult, it comes and goes so fast I barely have time to enjoy it.&amp;nbsp; Message to kids: enjoy it while you can.&amp;nbsp; Responsibility steals the fun from Christmas!&lt;br /&gt;&lt;br /&gt;5.&amp;nbsp; "Christmas Time is Here Again (Bring Out the Joy!)" by &lt;a href="http://www.mymorningjacket.com/"&gt;My Morning Jacket&lt;/a&gt;.&amp;nbsp; Peaceful.&amp;nbsp; I'll let you google for this one.&amp;nbsp; It's a live take from a radio broadcast.&lt;br /&gt;&lt;br /&gt;6.&amp;nbsp; "&lt;a href="http://www.google.com/url?url=http://popup.lala.com/popup/360569479536201644&amp;amp;rct=j&amp;amp;ei=RKYlS5fRBtWnnQenwNTwCQ&amp;amp;sa=X&amp;amp;oi=music_play_track&amp;amp;resnum=1&amp;amp;ct=result&amp;amp;cd=2&amp;amp;ved=0CAgQ0wQoADAA&amp;amp;q=Listening+to+Otis+Redding+at+Home+During+Christmas&amp;amp;usg=AFQjCNHxl1LSq-75nBa0le_20FUtHhGSxw"&gt;Listening to Otis Redding at Home During Christmas&lt;/a&gt;" by &lt;a href="http://www.okkervilriver.com/"&gt;Okkervil River&lt;/a&gt;.&amp;nbsp; Not a traditional Christmas tune, but a good one to follow MMJ, if only for the indie vibe.&amp;nbsp; This song reminds me of "New Slang" by The Shins, but with less jade and desperation.&amp;nbsp; Slightly more hopeful. :)&lt;br /&gt;&lt;br /&gt;7.&amp;nbsp; "X-Mas Card" by &lt;a href="http://www.mu330.com/"&gt;MU330&lt;/a&gt;.&amp;nbsp; Not my normal thing, but the instrumental intro with the horns is fun.&lt;br /&gt;&lt;br /&gt;8.&amp;nbsp; "&lt;a href="http://www.google.com/url?url=http://popup.lala.com/popup/432627114183647907&amp;amp;rct=j&amp;amp;ei=O6clS7HALYPknAeUkOXfCQ&amp;amp;sa=X&amp;amp;oi=music_play_track&amp;amp;resnum=1&amp;amp;ct=result&amp;amp;cd=2&amp;amp;ved=0CAgQ0wQoADAA&amp;amp;q=Yule+Shoot+Your+Eye+Out&amp;amp;usg=AFQjCNEHyeNDx6IR6x-c3vhhY2PU1LZ8AQ"&gt;Yule Shoot Your Eye Out&lt;/a&gt;" by &lt;a href="http://www.falloutboyrock.com/"&gt;Fall Out Boy&lt;/a&gt;.&amp;nbsp; If you haven't checked out "Can You See Santa From the Southside," now is the time to skedaddle over to Amazon and do so.&lt;br /&gt;&lt;br /&gt;9.&amp;nbsp; "&lt;a href="http://www.amazon.com/Baby-Outside-Mulato-Remix-remix/dp/B000SCCS6O"&gt;Baby, It's Cold Outside (Mulato Beat Remix)&lt;/a&gt;" by Louis Armstrong and Velma Middleton.&amp;nbsp; Shopko gave away a Christmas sampler in 2004 and this was on it.&amp;nbsp; This is, by far, the Christmas album that gets play in our house (not the one this song links to).&amp;nbsp; It comes on while we're preparing meals and we find ourselves breaking frequently to get our grooves on.&amp;nbsp; No kidding.&amp;nbsp; Six people from 2 to 35 shaking a leg in the kitchen.&lt;br /&gt;&lt;br /&gt;10. "&lt;a href="http://www.google.com/url?url=http://popup.lala.com/popup/432627047853947005&amp;amp;rct=j&amp;amp;ei=-qclS97gDpKEnQf98J3fCQ&amp;amp;sa=X&amp;amp;oi=music_play_track&amp;amp;resnum=1&amp;amp;ct=result&amp;amp;cd=2&amp;amp;ved=0CAgQ0wQoADAA&amp;amp;q=O+Come+All+Ye+Faithful+Weezer&amp;amp;usg=AFQjCNHoIllYRLPEU0UDKGUEKQDNJdMhrQ"&gt;O Come All Ye Faithful&lt;/a&gt;" by &lt;a href="http://www.weezer.com/"&gt;Weezer&lt;/a&gt;.&amp;nbsp; Traditional Christmas tune done right by a modern band.&lt;br /&gt;&lt;br /&gt;And some bonus songs from last years mix:&lt;br /&gt;&lt;br /&gt;Bonus 1:&amp;nbsp; "Fairytale of New York" by the &lt;a href="http://www.pogues.com/"&gt;Pogues&lt;/a&gt;.&amp;nbsp; This one is definitely not for the kids and is a guilty pleasure of mine.&amp;nbsp; Who can resist: "You're a bum, you're a punk / You're an old slut on junk."&amp;nbsp; Ahh, the holidays. &lt;br /&gt;&lt;br /&gt;Bonus 2:&amp;nbsp; "&lt;a href="http://www.google.com/url?url=http://popup.lala.com/popup/1657606159406096950&amp;amp;rct=j&amp;amp;ei=cqglS-SgGZSTnQf3_d3dCQ&amp;amp;sa=X&amp;amp;oi=music_play_track&amp;amp;resnum=1&amp;amp;ct=result&amp;amp;cd=2&amp;amp;ved=0CAgQ0wQoADAA&amp;amp;q=frosty+the+snowman+cocteau+twins&amp;amp;usg=AFQjCNF0tLdJRpPwQJ72VIGsOENQkSBx3w"&gt;Frosty the Snowman&lt;/a&gt;" by the &lt;a href="http://www.cocteautwins.com/"&gt;Cocteau Twins&lt;/a&gt;.&amp;nbsp; Year after year, my favorite Frosty rendition.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-8422141135547691947?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/8422141135547691947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=8422141135547691947' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/8422141135547691947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/8422141135547691947'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/12/christmas-mix-2009.html' title='Christmas Mix 2009'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-7982331734687752157</id><published>2009-11-02T17:00:00.001-07:00</published><updated>2009-11-02T17:00:01.172-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='thrift'/><category scheme='http://www.blogger.com/atom/ns#' term='cassandra'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Building Cassandra Thrift Bindings on OS X</title><content type='html'>A few weeks ago, I came to &lt;a href="http://www.rackspace.com/"&gt;Rackspace&lt;/a&gt; to work full-time on &lt;a href="http://incubator.apache.org/cassandra"&gt;Cassandra&lt;/a&gt; in their &lt;a href="http://www.rackspacecloud.com/"&gt;cloud division&lt;/a&gt;.&amp;nbsp; So far, I'm having fun and learning new things.&amp;nbsp; Apart from Cassandra, one of the projects I get to figure out is &lt;a href="http://incubator.apache.org/thrift"&gt;Thrift&lt;/a&gt;.&amp;nbsp; Thrift is a tool that allows you to define a service interface and then generate stubbed service bindings in different programming languages.&amp;nbsp; A programmer then takes the generated code and makes it do the things it is supposed to.&amp;nbsp; In an ideal world, this simplifies the process of, say, stubbing in a PHP client that can speak to a server stubbed in Java.&lt;br /&gt;&lt;br /&gt;Right now, I'm the lone wolf in the office doing development on OS X.&amp;nbsp; The glitches so far have been minor, but I was forewarned that I might want to reconsider [using linux] when it came time to work with Thrift.&amp;nbsp; Well, that time started today.&amp;nbsp; I've been a faithful linux user for about 10 years, but I've been a faithful Mac user even longer.&amp;nbsp; I'm not ready to make the switch to full-time linux yet; I like my Mac.&lt;br /&gt;&lt;br /&gt;Fortunately, Google was my friend when it came to figuring out the secrets of building Thrift on OS X.&amp;nbsp; Credit goes to Nathan Ostgard and &lt;a href="http://nathanostgard.com/archives/2009/4/23/installing-thrift-mac-os-x/"&gt;his blog post&lt;/a&gt; for getting me going in the right direction.&lt;br /&gt;&lt;br /&gt;1.&amp;nbsp; You definitely want to install &lt;a href="http://www.macports.org/install.php"&gt;macports&lt;/a&gt;.&lt;br /&gt;2.&amp;nbsp; Install boost and log4j&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sudo port install boost&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sudo port install jakarta-log4j&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;3.&amp;nbsp; Download and install thrift&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;curl -o thrift.tgz "http://gitweb.thrift-rpc.org/?p=thrift.git;a=snapshot;h=HEAD;sf=tgz"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;tar -xvf thrift.tgz&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;cd thrift&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;echo "thrift.extra.cpath = /opt/local/share/java/jakarta-log4j.jar" &amp;gt; ~/.thrift-build.properties&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;./bootstrap.sh&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;./configure --prefix=/opt/local&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;4.&amp;nbsp; You're going to get an error during configure:&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;./configure: line 16440: syntax error near unexpected token `MONO,'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;./configure: line 16440: `&amp;nbsp; PKG_CHECK_MODULES(MONO, mono &amp;gt;= 2.0.0, net_3_5=yes, net_3_5=no)'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I couldn't figure out how to tell configure "no csharp, please" through the command line, so I just commented out lines 16439-16442 and ran configure again:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;./configure --prefix=/opt/local&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;5.&amp;nbsp; You know the drill:&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;make&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sudo make install&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;That's it for Thrift.&amp;nbsp; The next step is to generate the Cassandra client.&amp;nbsp; The Cassandra wiki has &lt;a href="http://wiki.apache.org/cassandra/ThriftInterface"&gt;steps to generate a python client&lt;/a&gt;.&amp;nbsp; This works fine except that the thrift python module was installed to a place where the OS X python can't see it. You'll get the following error if you try to run &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Cassandra-remote&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Traceback (most recent call last):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; File "./Cassandra-remote", line 11, in &lt;module&gt;&lt;/module&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; from thrift.transport import TTransport&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ImportError: No module named thrift.transport&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There is probably a right way to fix this problem, a way that is right for OS X, but I had no patience.&amp;nbsp; I added the the following line to my &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;~/.profile&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;export PYTHONPATH=/usr/lib/python2.6/site-packages&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Restart terminal, navigate back to the directory where the python client was generated and try again.&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Cassandra-remote&lt;/span&gt; should spew out a verbose usage directive.&lt;br /&gt;&lt;br /&gt;That's it; you're done.&lt;br /&gt;&lt;br /&gt;If you found this useful, or have feedback, please let me know.&amp;nbsp; I use gmail (gdusbabek).&amp;nbsp; I also emit the occasional tweet; just follow gdusbabek.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;If you're interested in learning more about Cassandra, there is an active and helpful IRC channel (#cassandra) on freenode and &lt;a href="http://incubator.apache.org/cassandra/#resources"&gt;mailing lists&lt;/a&gt; as well.&amp;nbsp; The &lt;a href="http://wiki.apache.org/cassandra/"&gt;wiki&lt;/a&gt; also contains useful information for beginners.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-7982331734687752157?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/7982331734687752157/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=7982331734687752157' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/7982331734687752157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/7982331734687752157'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/11/building-cassandra-thrift-bindings-on.html' title='Building Cassandra Thrift Bindings on OS X'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-4483767764992869926</id><published>2009-09-14T22:00:00.068-06:00</published><updated>2009-09-14T22:00:00.445-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='id3'/><category scheme='http://www.blogger.com/atom/ns#' term='tagfriendly'/><title type='text'>id3 for Python</title><content type='html'>I've been meaning to package up some python code I wrote earlier this year and release it for free as open source software.&amp;nbsp; Several things held me back from doing this.&amp;nbsp; The biggest reason, by far, is that I'm still not proficient at python, and feel like I'm exposing myself by putting this code out for the world to see.&lt;br /&gt;&lt;br /&gt;But then I remembered that my blog doesn't have a lot of readers anyway.&amp;nbsp; So no worries there.&amp;nbsp; And besides, maybe I can garner some constructive criticism to make my python code better.&amp;nbsp; :)&lt;br /&gt;&lt;a href="http://draft.blogger.com/goog_1252965439888"&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.dusbabek.org/%7Egaryd/id3_python/"&gt;http://www.dusbabek.org/~garyd/id3_python/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This library is capable of reading most any correct Id3v2.3 or 2.4 tag, some incorrect ones, and then fails gracefully when things get hopeless.&amp;nbsp; (I run smoke tests on my mp3 collection, which has a lot of nasty debris from the Napster years.)&amp;nbsp;&lt;br /&gt;&lt;br /&gt;It supports unicode, and does a good job handing PIC/APIC tags.&amp;nbsp; I should also mention it is in production at &lt;a href="http://www.tagfriendly.com/"&gt;Tagfriendly&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;For those that do come across this, I'm still trying to figure something out.&amp;nbsp; All the documentation I've come across says that I should structure my directories as such:&lt;br /&gt;&lt;br /&gt;MyModule/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id3/&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; __init__.py &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stuff.py&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; setup.py&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; tests.py&lt;br /&gt;&lt;br /&gt;I include id3.py inside the id3/ directory because that's where I think it should go.&amp;nbsp; But then when I build and test the module, the only way I can access the code is if I &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;import id3.id3&lt;/span&gt;, but I wish I only had to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;import id3&lt;/span&gt;.&amp;nbsp; Clearly, I'm not doing something right.&lt;br /&gt;&lt;br /&gt;My solution, and I know this isn't right, is to do away with the id3/ directory altogether and just have id3.py rubbing elbows with setup.py and test.py.&amp;nbsp; Anyone know what gives?&lt;br /&gt;&lt;br /&gt;Well, enough of all that... id3 for Python is available at &lt;a href="http://www.dusbabek.org/%7Egaryd/id3_python/"&gt;http://www.dusbabek.org/~garyd/id3_python/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;P.S.&amp;nbsp; Thanks to my friends on IRC for reminding me about this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-4483767764992869926?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/4483767764992869926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=4483767764992869926' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/4483767764992869926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/4483767764992869926'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/09/id3-for-python.html' title='id3 for Python'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-2272983985125576541</id><published>2009-08-31T18:00:00.002-06:00</published><updated>2009-08-31T18:00:01.781-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='exercise'/><category scheme='http://www.blogger.com/atom/ns#' term='ipod'/><title type='text'>My New Workout</title><content type='html'>I have been attending the gym regularly, religiously even, for the last 10 years for early morning workouts.&amp;nbsp; What started out as short 20 minute workouts for an out-of-shape 25 year old have turned into 45 minute cardio sessions where I routinely burn 900 calories.&amp;nbsp; It's been a very good thing for me; I wouldn't trade it for the world.&lt;br /&gt;&lt;br /&gt;When I started, I would bring headphones and watch the morning news.&amp;nbsp; Then began a succession of portable music players that started with a &lt;a href="http://en.wikipedia.org/wiki/Rio_500"&gt;Diamond Rio 500&lt;/a&gt;, which I cherished, and culminated with the two iPods I currently use.&amp;nbsp; Over the last several years, gradually, the monotony of a daily workout began combining with my music against me, hampering my motivation.&amp;nbsp; Maybe I can chalk it up to age, or plateauing, but regardless of the cause: I needed to find something else.&lt;br /&gt;&lt;br /&gt;I thought that an iPod video (30 GB) would help, but it turns out the screen is much to small to watch while the rest of my body is moving on a treadmill or elliptical machine.&amp;nbsp; (It is still great on an airplane though.)&amp;nbsp; I've been using an iPod shuffle for the last two years, alternating between &lt;a href="http://lds.org/conference/display/0,5234,23-1,00.html"&gt;general conference sessions&lt;/a&gt; and music.&amp;nbsp; I tried podcasts for a while, but the iPod has such a crappy podcast interface--you can't queue them up in a playlist, and I don't want to fiddle with buttons in the middle of my workout.&lt;br /&gt;&lt;br /&gt;Total frustration. &lt;br /&gt;&lt;br /&gt;Then something happened.&amp;nbsp; My gym began installing televisions on all the cardio equipment.&amp;nbsp; I thought my problem was solved--I'd be able to go back to just bringing a pair of headphones again.&amp;nbsp; That joy was short lived, as I realized that most of what's on television in the early morning is generally crap (informercials) and sometimes downright crude (infomercials for porn--no kidding!).&amp;nbsp; And the news is, well, frankly: not worth watching anymore.&amp;nbsp; Back to square one...&lt;br /&gt;&lt;br /&gt;I don't know why it took so long for the idea to sink in, but I realized that I could connect my iPod video directly to the televisions on the cardio machines using a $5 composite cable I already owned (thank you, Sony), and watch my iPod videos on the TVs.&amp;nbsp; I finally gave it a try this morning.&amp;nbsp; I watched two &lt;a href="http://www.ted.com/"&gt;TED&lt;/a&gt; talks, and an &lt;a href="http://marketplace.publicradio.org/RSS/"&gt;APM Marketplace&lt;/a&gt; podcast about high-frequency trading.&amp;nbsp; The best part is that when it was all over, my 45 minute workout felt like only 15 minutes had gone by!&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Undeniable WIN!&lt;br /&gt;&lt;br /&gt;My next task is to find more podcasts that don't suck.&amp;nbsp; I've already found a decent language training podcast, but what would be really nice is to get a hold of some of the Google tech talks, as they are usually excellent and I don't mind watching them over (indeed, some of them ought to be watched multiple times to absorb the information).&amp;nbsp; I couldn't find them through the iTunes store, but maybe some kind soul has been kind enough to make them available on the outside.&amp;nbsp; Google, ironically, has not.&amp;nbsp; In fact, the Google tech talks are strewn across &lt;a href="http://video.google.com/"&gt;video.google.com&lt;/a&gt; and &lt;a href="http://youtube.com/"&gt;youtube.com&lt;/a&gt; now that Youtube is part of Google.&amp;nbsp; The older video.google videos are easily downloadable, but the Youtube ones are not.&amp;nbsp; At least, not without some real work.&lt;br /&gt;&lt;br /&gt;Then again, there are enough [free] things at iTunes U to keep my mornings occupied for a long time.&amp;nbsp; They have a special section just for &lt;a href="http://deimos3.apple.com/WebObjects/Core.woa/Browse/itunesu.com.1644265768.01644265781"&gt;computer science educational content&lt;/a&gt;.&amp;nbsp; Double plus woot!&lt;br /&gt;&lt;br /&gt;Anyway, all this is a long way of saying something short: iPod + cardio TV == excellent workout.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-2272983985125576541?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/2272983985125576541/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=2272983985125576541' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/2272983985125576541'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/2272983985125576541'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/08/my-new-workout.html' title='My New Workout'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total><georss:point>40.1611 -111.610619</georss:point></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-5877894358388718810</id><published>2009-07-22T08:00:00.004-06:00</published><updated>2009-07-22T08:00:07.732-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Adventures in Javascript</title><content type='html'>Note: Blogger doesn't give me a good way to preview the image before it goes live.&amp;nbsp; If it is too small, my apologies.&amp;nbsp; I'll try to get that fixed before your news reader pulls the feed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;The Question &lt;/b&gt;&lt;/span&gt;&lt;br /&gt;Sometimes I think programmers tend to accept things the way they are without really questioning them, especially when it comes to language quirks.&amp;nbsp; This is something I remember coming across when I was first learning Javascript.&amp;nbsp; I was reminded of it recently while reading a Javascript book. &lt;br /&gt;&lt;br /&gt;Javascript pros will probably quickly recognize what's going on here. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_Uo-_9LOo8vM/SmaEn_fgHYI/AAAAAAAAAYA/wpty1oAE5s0/s1600-h/jsJuly212009.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_Uo-_9LOo8vM/SmaEn_fgHYI/AAAAAAAAAYA/wpty1oAE5s0/s400/jsJuly212009.PNG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;At first I thought the third definition of MyFunc would wipe out the others.&amp;nbsp; And just to verify that declaring a function in that manner normally makes it into the assumed contexts, I did it with YourFunc.&lt;br /&gt;&lt;br /&gt;What gives? &lt;br /&gt;&lt;br /&gt;Go ahead, take a guess...&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;The Answer&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;The interpreter evaluates standalone functions before the other expressions.&amp;nbsp; So it is as if 'function MyFunc...' were written before everything else.&amp;nbsp; This can be verified by calling MyFunc() in the first line of the script.&amp;nbsp; The expressions (which include assignments) are then evaluated.&amp;nbsp; So what appears as the second assignment of MyFunc is really the third, and the third is really first.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-5877894358388718810?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/5877894358388718810/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=5877894358388718810' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/5877894358388718810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/5877894358388718810'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/07/adventures-in-javascript.html' title='Adventures in Javascript'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Uo-_9LOo8vM/SmaEn_fgHYI/AAAAAAAAAYA/wpty1oAE5s0/s72-c/jsJuly212009.PNG' height='72' width='72'/><thr:total>0</thr:total><georss:point>40.1611 -111.610619</georss:point></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-7949289261824297100</id><published>2009-07-21T18:00:00.009-06:00</published><updated>2009-07-21T18:00:01.352-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='newspapers'/><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>My Take on Newspapers in America</title><content type='html'>I have read numerous articles and blog posts over the last 12 months about the decline of the newspaper industry.&amp;nbsp; Having spent a few years in the trenches myself, and having opinions on the matter, I thought I could add something to the discussion.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;A few things about me:&amp;nbsp; From 2000 to 2007 I worked as a programmer for &lt;a href="http://www.dtint.com/"&gt;&lt;/a&gt;&lt;a href="http://www.dtint.com/"&gt;Dgital Technology International&lt;/a&gt; (DTI), one of the leading newspaper software vendors (editorial and advertising) in North America and Europe.&amp;nbsp; I worked primarily on editorial products.&amp;nbsp; I have made roughly 25 visits to customer sites to perform troubleshooting or assist with software installations or upgrades.&amp;nbsp; So I have an insiders look about how newspapers operate, albeit with a technical slant.&amp;nbsp; I never learned much about how newspapers are run though.&amp;nbsp; That kind of knowledge would have made writing this easier.&amp;nbsp; If there are any inaccuracies (and there probably are), feel free to call me out on them, either in the comments or by way of email.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;What is happening to newspapers?&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;To sum it up, the business is drying up.&amp;nbsp; &lt;a href="http://www.nytimes.com/2009/04/28/business/media/28paper.html"&gt;Circulation numbers are in decline&lt;/a&gt;.&amp;nbsp; Whenever this happens, advertisers tend to pull back.&amp;nbsp; The result is a net loss of revenue.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;But why is this happening now?&amp;nbsp; Can it be blamed on the recession?&amp;nbsp; I was around during the last recession.&amp;nbsp; There was a lot of talk in 2001 and 2002 about newspapers going extinct then, since advertising rates had fallen and circulation was in decline, much like it is now.&amp;nbsp; In fact, the biggest difference between now and then is the severity of the problem.&amp;nbsp; For me, watching the Rocky Mountain News shut down operations really opened my eyes to the magnitude of the problem being faced by print journalists.&lt;br /&gt;&lt;br /&gt;So if the slump can be blamed on the economy that would mean that circulation would probably not have declined during the good times.&amp;nbsp; Right?&amp;nbsp; Let's check the numbers.&amp;nbsp; I'll use the New York Times as a metric, even though it's not a good metric for the entire industry.&amp;nbsp; Here are the ups and downs of circulation starting in 1998.&amp;nbsp; I got these numbers from the NYTimes &lt;a href="http://www.nytco.com/investors/financials/nyt-circulation.html"&gt;corporate site&lt;/a&gt;.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;1999: +2.2%, &lt;br /&gt;2000: +1.3%, &lt;br /&gt;2001: +0.1%, &lt;br /&gt;2002: +3.8%,&lt;br /&gt;2003: -5.3 %,&lt;br /&gt;2004: +0.3%,&lt;br /&gt;2005: +0.2%,&lt;br /&gt;2006: +0.5%,&lt;br /&gt;2007: -1.9 %,&lt;br /&gt;2008: -3.9%,&lt;br /&gt;2009: -3.5%&lt;br /&gt;&lt;br /&gt;What I see here is one good year, a few years of stagnation, and a several years (the most recent ones) of significant decline.&amp;nbsp; I don't think the decline of readership can be based on economic factors; there must be something else.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Cultural shift?&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Maybe we're changing as a people.&amp;nbsp; Unscientific guessing tells me that we're working more and doing more things (after all, we're multi-taskers).&amp;nbsp; We don't have time to read the paper in the morning or when we come home at night.&amp;nbsp; Further, when we do make it home, there are so many other things available to occupy us.&amp;nbsp; 100+ channels on the tube, a backlog of events on the TiVo and this miraculous internet invention all await us.&amp;nbsp; There may be studies to support this, but I don't care.&amp;nbsp; This is my hypothesis and I'm running with it: less people read newspapers because they have too many other things to do, and those things are far more interactive.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;What can newspapers do?&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;There are two obvious solutions.&amp;nbsp; The first is to cut costs.&amp;nbsp; The second is to get more readers.&amp;nbsp; Let's take a look at each one individually.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;First, cutting costs...&amp;nbsp; Running a newspaper isn't cheap.&amp;nbsp; There are reporters, editors, more editors, press operators, delivery people, circulation people and advertising people.&amp;nbsp; Some papers have gone web-only.&amp;nbsp; That eliminates the press operators and delivery people, and with the right software-a good chunk of the circulation department too.&amp;nbsp; Give a few good salespeople the right software and analytics and I think advertising and sales would be covered.&amp;nbsp; Could they skimp on reporters and editors--the real content producers?&amp;nbsp; I think so, to a degree.&amp;nbsp; See, if newspapers focused on local news and stopped trying to compete with CNN.com and USA Today for national and world coverage, I think they would be able to own that niche for some time.&amp;nbsp; Radio took a similar path on the advent of the television age when home listeners declined.&amp;nbsp; They found a niche to occupy (the car) and did well there for years.&lt;br /&gt;&lt;br /&gt;Since I am in the software business, I'll go ahead and say that the software could be better.&amp;nbsp; I'm not referring to the quality of the software, but rather what it does and how it used.&amp;nbsp; For instance, at DTI we had release cycles of around 6 months.&amp;nbsp; Imagine waiting 6 months to see something like Twitter or Facebook integration, or integrating the latest Adobe CS suite.&amp;nbsp; Shortening that cycle would have been difficult from quality and cost perspectives.&amp;nbsp; By "better" I mean more nimble.&amp;nbsp; Smaller pieces working together instead of a monolithic suite.&amp;nbsp; It would be hard to do, but I think it could be done.&lt;br /&gt;&lt;br /&gt;Next is readers: how do they get more readers?&amp;nbsp; My first suggestion is to reach out to them wherever they are--not just on their front lawns.&amp;nbsp; Smart phone adoption is on the rise.&amp;nbsp; I get a good chunk of news through my T-Mobile G1.&amp;nbsp; It is easy to scan my syndication feeds when I'm in line for something.&amp;nbsp; But I don't pay for it, which means nothing is going back to the paper, or whoever generated the content in the first place.&amp;nbsp; So increasing readership alone isn't going to keep the papers afloat.&lt;br /&gt;&lt;br /&gt;I just don't see myself paying for news.&amp;nbsp; The Internet has made me used to having things free and my way, and I think a lot of people are with me on this one.&lt;br /&gt;&lt;br /&gt;But this content has value, right?&amp;nbsp; Surely, someone is willing to pay for it.&amp;nbsp; I mean, if the switch were turned off today and all news went away, there would be a hole in my life.&amp;nbsp; Americans need and crave news coverage.&lt;br /&gt;&lt;br /&gt;As in the past, I think the advertisers will step up.&amp;nbsp; But they're probably going to want to know a little bit about you, to, you know, make sure you get the right ad.&amp;nbsp; Consumers benefit from this.&amp;nbsp; Even if you routinely ignore all adversing, under this scenario, you're ignoring advertising targeted to you for stuff that might actually fit your interests.&amp;nbsp; I have found myself, on occasion, clicking on Google ads, even though it rarely results in me buying something.&amp;nbsp; The process works.&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;&lt;br /&gt;My predictions&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;In ten years, there will still be newspapers.&amp;nbsp; But they'll be owned by local television stations, who will have taken over as the main supplier of news content.&amp;nbsp; This suits me: their stories are shorter and I think that fits the lifestyles of more people nowadays.&amp;nbsp; These newspapers will be free and contain copy taken from the newscasts and modified slightly for print.&amp;nbsp; The ads in the papers will be the result of TV spot upsells.&amp;nbsp; There won't be classifieds since you can't execute a full-text search on a newspaper.&lt;br /&gt;&lt;br /&gt;This model cannot currently exist in the United States because laws prevent interests that own one type of media outlet from controlling another type.&amp;nbsp; But that will change soon, if it hasn't already started.&amp;nbsp; (Tracking the status of this without becoming an expert is well nigh impossible.)&lt;br /&gt;&lt;br /&gt;I don't know much about what kind of software TV stations use to handle their content (I know a bit about the advertising side), but I seriously doubt it would integrate well with print content at this point.&amp;nbsp; The disciplines haven't converged enough yet.&lt;br /&gt;&lt;br /&gt;It will be fun to follow this story for a few years to see how things pan out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-7949289261824297100?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/7949289261824297100/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=7949289261824297100' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/7949289261824297100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/7949289261824297100'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/07/my-take-on-newspapers-in-america.html' title='My Take on Newspapers in America'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-3301767378791428468</id><published>2009-06-14T21:07:00.000-06:00</published><updated>2009-06-14T21:07:15.702-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vacation'/><category scheme='http://www.blogger.com/atom/ns#' term='family'/><title type='text'>Simplifying the Trip</title><content type='html'>Our vacation starts soon.&amp;nbsp; We're going some place far away by way of jet.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;We've had a Sony MiniDV camcorder for almost 10 years.&amp;nbsp; It still functions perfectly, but with four children in tow, it has started to feel more like an anchor than anything else.&amp;nbsp; The bug bit last summer and I bought a smallish camcorder that recorded directly to a hard drive.&amp;nbsp; Two days later with a bit of buyers remorse and the utter realization that the camera was completely incompatible with the MacOS (even though the box claimed otherwise) I returned it.&lt;br /&gt;&lt;br /&gt;I decided to be a bit more pragmatic about it this year.&amp;nbsp; After some reasearch I realized that I didn't want to spend good money on a small SD camcorder knowing that I would probably want a HD recorder in the next 5 years.&amp;nbsp; But I'm not ready for an HD recorder yet either (I don't have the storage capacity).&lt;br /&gt;&lt;br /&gt;So what do I do?&lt;br /&gt;&lt;br /&gt;It didn't take long for me to come across the &lt;a href="http://www.amazon.com/gp/product/B001QWF01K"&gt;Sony Webbie&lt;/a&gt; and the &lt;a href="http://www.amazon.com/gp/product/B0023B14TK"&gt;Flip Ultra HD&lt;/a&gt;.&amp;nbsp; These are small devices that record directly to flash in HD mpeg-4 format, priced in the $150-$200 range.&amp;nbsp; Now don't be fooled by the "HD" in the product names.&amp;nbsp; While both devices do record HD video, they do so using a codec that his highly compressed and lossy (think youtube HD quality).&amp;nbsp; They don't do well in low-light situations either. &lt;br /&gt;&lt;br /&gt;All this got me to wondering what the video quality on my digital camera, a two year-old Sony DSC-T20, was like.&amp;nbsp; Turns out, it records 640x480 mpeg-4 at 30fps.&amp;nbsp; This falls in the range of "good enough for me" and it's technically HD like the Sony anf Flip.&amp;nbsp; After all, I'm not going to use it to record piano recitals, awards ceremonies or new babies.&amp;nbsp; I just need something good enough to capture the cute moments that I want to remember when I'm on a trip.&amp;nbsp; And let's face it--Nicole and I only ever go back and watch these videos once or twice a year anyway.&amp;nbsp; (Maybe they will become more important as we age.)&lt;br /&gt;&lt;br /&gt;So it's settled--I'm going to use my digital camera to record video on this trip.&amp;nbsp; I did decide to spring for a larger memory stick though--8GB where there were only 2GB before, and a second battery for hot swapping.&lt;br /&gt;&lt;br /&gt;Side question: I wonder how long before these devices converge?&amp;nbsp; Tangential jab: And will it include a cell phone and app store as well?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-3301767378791428468?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/3301767378791428468/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=3301767378791428468' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/3301767378791428468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/3301767378791428468'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/06/simplifying-trip.html' title='Simplifying the Trip'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-7761252012685662496</id><published>2009-06-03T22:33:00.000-06:00</published><updated>2009-06-03T22:33:11.180-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Stupid CSS Tricks</title><content type='html'>I have recently made the committment to wrap my head around &lt;a href="http://www.w3.org/TR/CSS2/"&gt;CSS&lt;/a&gt;.&amp;nbsp; In other words,&amp;nbsp; I'm tired of guessing.&amp;nbsp; Part of this experience will have me documenting my discoveries on this blog.&lt;br /&gt;&lt;br /&gt;Here is what I learned today:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Verdana,sans-serif;"&gt;&lt;span style="font-size: x-large;"&gt;Pseudo-classes aren't just for anchors.&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;That's right.&amp;nbsp; You're supposed to be able to apply standard pseudo-classes to just about any selector you can come up with.&amp;nbsp; This means you don't to rely on a) &lt;a href="http://www.jquery.com/"&gt;jQuery&lt;/a&gt; or b) onmouseover/onmouseout to do the hover-effect work for you, so long as you can do it all in CSS.&lt;br /&gt;&lt;br /&gt;Here is some sample code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;html&amp;gt;&lt;br /&gt;    &amp;lt;head&amp;gt;&lt;br /&gt;        &amp;lt;style type="text/css"&amp;gt;&lt;br /&gt;  &lt;br /&gt;        /* a class for an element */&lt;br /&gt;        span.my_hover_class:hover {&lt;br /&gt;            background-color:red;&lt;br /&gt;            cursor:pointer;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /* attached to nested elements. */&lt;br /&gt;        div &amp;gt; div &amp;gt; span &amp;gt; span:hover {&lt;br /&gt;            background-color:green;&lt;br /&gt;            cursor:pointer;&lt;br /&gt;        }&lt;br /&gt; &lt;br /&gt;        &amp;lt;/style&amp;gt;&lt;br /&gt;    &amp;lt;/head&amp;gt;&lt;br /&gt;    &amp;lt;body&amp;gt;&lt;br /&gt;        &amp;lt;span class="my_hover_class"&amp;gt;Should hover red (span.my_hover_class)&amp;lt;/span&amp;gt;&lt;br /&gt;  &lt;br /&gt;        &amp;lt;div&amp;gt;&lt;br /&gt;            Should not have hover effect.&lt;br /&gt;            &amp;lt;div&amp;gt;&lt;br /&gt;                &amp;lt;span&amp;gt;&amp;lt;span&amp;gt;Should hover green (div&amp;gt;div&amp;gt;span&amp;gt;span)&amp;lt;span&amp;gt;&amp;lt;span&amp;gt;&lt;br /&gt;            &amp;lt;/div&amp;gt;&lt;br /&gt;        &amp;lt;/div&amp;gt;&lt;br /&gt;    &amp;lt;/body&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I would like to show the effect here, but the Blogger editor insists on tidying up my pasted HTML.&amp;nbsp; I uploaded the file to my &lt;a href="http://www.dusbabek.org/%7Egaryd/css1.html"&gt;website&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This example was tested in Firefox and Safari on a Mac.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-7761252012685662496?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/7761252012685662496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=7761252012685662496' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/7761252012685662496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/7761252012685662496'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/06/stupid-css-tricks.html' title='Stupid CSS Tricks'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-2494463706679674269</id><published>2009-06-01T22:00:00.000-06:00</published><updated>2009-06-01T22:00:39.007-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tagfriendly'/><title type='text'>Tagfriendly Updates, 1 Jun 2009</title><content type='html'>I've been quietly hacking away, albeit slowly, on the next iteration of my Tagfriendly project.&amp;nbsp; The back end is in a state I am happy with, so this version is all about making the front end suck less.&lt;br /&gt;&lt;br /&gt;You can sample the work as it progresses at &lt;a href="http://www.tagfriendly.com/tf2"&gt;http://www.tagfriendly.com/tf2&lt;/a&gt;. This is truly alpha-quality work, lacking much in the way of CSS, but I link here because I know a few people follow this blog and are interested in it.&amp;nbsp; That, and since I'm not actively working on the current version, I feel the need to show something for my efforts.&amp;nbsp; :)&amp;nbsp; I push updated code live about once or twice a week.&lt;br /&gt;&lt;br /&gt;I use more AJAX this time around, including fancy transitions and assembling the page in chunks.&amp;nbsp; I'm not sure if this is the right approach yet or not; I'll see how far it gets me.&lt;br /&gt;&lt;br /&gt;In a few days I'll start work on the new player, now that I've discovered there is a &lt;a href="http://fe2.music.ac4.yahoo.com/api"&gt;published API&lt;/a&gt; for the Yahoo! Media Player (that is very hard to find via google).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;And Now, A Completely Unrelated Gripe:&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I offcially &lt;i&gt;hate&lt;/i&gt; eBay.&amp;nbsp; I sell one or two items on eBay per year, so things are usually in a different place every time I need to sell something.&amp;nbsp; I can handle that, but two things tonight really bugged me.&lt;br /&gt;&lt;br /&gt;1.&amp;nbsp; I could not find a way to sell my stuff without signing up for and agreeing to automatic payment of seller fees.&amp;nbsp; This needless hoop was in my face and prevented me from doing what I needed to do.&lt;br /&gt;&lt;br /&gt;2.&amp;nbsp; I have an unopened seasons 1-5 boxed set of 7th Heaven that I want to get rid of.**&amp;nbsp; Well, in its wisdom, eBay has decided to cap shipping on DVDs at $3.&amp;nbsp; In other words, I couldn't charge more than $3 if I wanted to.&amp;nbsp; But this boxed set weighs about 5 pounds and will easily cost me $6-7 ship.&amp;nbsp; I realize what they're trying to do, which is crack down on S+H abuse, but at what cost?&amp;nbsp; They know the exact item I'm selling because they had me enter the SKU.&amp;nbsp; They should know how much it weights and what it would cost to ship through various methods.&amp;nbsp; Total fail, eBay; it's craigslist from here on out.&lt;br /&gt;&lt;br /&gt;**I really thought Nicole liked the show and it would make an excellent Christmas gift.&amp;nbsp; It turns out she only watches the show on Myth because she can skip the commercials and watch it at 150% speed.&amp;nbsp; Total fail, Gary.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-2494463706679674269?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/2494463706679674269/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=2494463706679674269' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/2494463706679674269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/2494463706679674269'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/06/tagfriendly-updates-1-jun-2009.html' title='Tagfriendly Updates, 1 Jun 2009'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-7293983101385651616</id><published>2009-05-30T07:00:00.000-06:00</published><updated>2009-05-30T07:00:01.682-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='music'/><title type='text'></title><content type='html'>I don't blog about music as much as I would like.&amp;nbsp; I used to do it a lot.&lt;br /&gt;&lt;br /&gt;I &lt;a href="http://www.dusbabek.org/%7Egaryd/#Music"&gt;listen to music all day&lt;/a&gt;, just about every day.&amp;nbsp; I subscribe to *a lot* of music blogs.&amp;nbsp; So much that I decided to create my own &lt;a href="http://www.tagfriendly.com/"&gt;blog aggregator&lt;/a&gt; to help me keep track of things (&lt;a href="http://tagfriendly.com/"&gt;Tagfriendly.com&lt;/a&gt;, for those of you who haven't been there yet.&amp;nbsp; You can create music-related RSS feeds based on your own search criteria.).&lt;br /&gt;&lt;br /&gt;So the problem is &lt;b&gt;not&lt;/b&gt; that I have little to say about new music, or the music scene in general, but that I have &lt;b&gt;*so much*&lt;/b&gt; to say.&amp;nbsp; If I didn't have to make a living doing Other Things, I could write about music (not that anybody would care to read it) all day, every day.&amp;nbsp; Watching the indie scene blossom over the last five or six years with the help of the Internet has been a special thing for me.&amp;nbsp; I listen to more music now than I ever have.&amp;nbsp; And hey, record executives: I buy more music than I ever did too (my wife will attest).&amp;nbsp; Even so, I know that I am just moving slowly across one facet of a very large musical stone.&amp;nbsp; And that is a good thing--I won't be getting bored any time soon.&lt;br /&gt;&lt;br /&gt;To that end, I have decided to carve out a few minutes each day and devote them to writing about music.&amp;nbsp; Some of it will end up on this here blog, hopefully as entries about new music, or music that is at least new to me.&lt;br /&gt;&lt;br /&gt;Let's get started...&lt;br /&gt;&lt;br /&gt;Some good music that you're probably not listening to&lt;br /&gt;&lt;br /&gt;"&lt;a href="http://click.linksynergy.com/fs-bin/stat?id=qYIwruBGkB0&amp;amp;offerid=78941&amp;amp;type=3&amp;amp;subid=0&amp;amp;tmpid=1826&amp;amp;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252FWebObjects%252FMZStore.woa%252Fwa%252FviewAlbum%253Fi%253D308350110%2526id%253D308350066%2526s%253D143441%2526uo%253D6%2526partnerId%253D30"&gt;Oh My God&lt;/a&gt;" by &lt;a href="http://www.idamaria.co.uk/"&gt;Ida Maria&lt;/a&gt; &lt;br /&gt;I thought it was &lt;a href="http://www.clapyourhandssayyeah.com/"&gt;Clap Your Hands Say Yeah&lt;/a&gt; at first, but it wasn't.&amp;nbsp; This is an honest song sung urgently almost desperately, and right on the verge of losing it.&amp;nbsp; "oh you think I'm in control... oh you think it's all for fun".&amp;nbsp; Moving and tender ("find a cure for my life... put a price on my soul"), but dishing it out at the same time.&amp;nbsp; This is the kind of song that makes it hard to stay in my chair.&amp;nbsp; (&lt;a href="http://en.wikipedia.org/wiki/Ida_Maria"&gt;wikipedia link&lt;/a&gt;) &amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;"&lt;a href="http://click.linksynergy.com/fs-bin/stat?id=qYIwruBGkB0&amp;amp;offerid=78941&amp;amp;type=3&amp;amp;subid=0&amp;amp;tmpid=1826&amp;amp;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252FWebObjects%252FMZStore.woa%252Fwa%252FviewAlbum%253Fi%253D270425092%2526id%253D270425056%2526s%253D143441%2526uo%253D6%2526partnerId%253D30"&gt;In the Night&lt;/a&gt;" by &lt;a href="http://www.basiabulat.com/"&gt;Basia Bulat&lt;/a&gt;&lt;br /&gt;That is the sound of an &lt;a href="http://en.wikipedia.org/wiki/Autoharp"&gt;autoharp&lt;/a&gt;, if you're wondering.&amp;nbsp; Organic and edgy, pop-folk for the aughts (what will we call this decade?).&amp;nbsp; I've been saying for several years now that the best new music is coming out of Scotland and Canada.&amp;nbsp; Bulat represents the latter, hailing from Ontario.&amp;nbsp; I like this song because it makes me feel good.&amp;nbsp; It carries a message about rising up above struggles ("Storm and shadows fall to pieces / to my heart like a comet / carry so that I can / soar like an eagle").&amp;nbsp; And while it's still possible for struggles to keep us down ("sometimes it takes the night to fall"), it doesn't have to be that way all the time.&amp;nbsp; (&lt;a href="http://en.wikipedia.org/wiki/Basia_Bulat"&gt;wikipedia link&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;"&lt;a href="http://click.linksynergy.com/fs-bin/stat?id=qYIwruBGkB0&amp;amp;offerid=78941&amp;amp;type=3&amp;amp;subid=0&amp;amp;tmpid=1826&amp;amp;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252FWebObjects%252FMZStore.woa%252Fwa%252FviewAlbum%253Fi%253D161451442%2526id%253D161451407%2526s%253D143441%2526uo%253D6%2526partnerId%253D30"&gt;New Moon&lt;/a&gt;" by &lt;a href="http://www.sambassadeur.com/"&gt;Sambassadeur&lt;/a&gt;&lt;br /&gt;When it comes to twee, you can't beat Tweeden.&amp;nbsp; Er... Sweden.&amp;nbsp; Sambassadeur are utterly forgettable, but still very pleasant (think: "spring time").&amp;nbsp; Proof that good music doesn't have to captivate or mesmerize; it just has to not make me throw up in my mouth.&amp;nbsp; I really don't know much about this band.&amp;nbsp; I suppose they are few Swedish twenty-somethings who will be around for a few years before moving on to meatier projects.&amp;nbsp; (&lt;a href="http://en.wikipedia.org/wiki/Sambassadeur"&gt;wikipedia link&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-7293983101385651616?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/7293983101385651616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=7293983101385651616' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/7293983101385651616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/7293983101385651616'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/05/i-dont-blog-about-music-as-much-as-i.html' title=''/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-4000083677001170420</id><published>2009-05-21T18:00:00.001-06:00</published><updated>2009-05-21T18:00:00.568-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='garden'/><title type='text'>Yes Virginia, there is a garden...</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/_Uo-_9LOo8vM/ShXWevudV6I/AAAAAAAAAXY/USMbQuCkpHI/s1600-h/artichoke.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_Uo-_9LOo8vM/ShXWevudV6I/AAAAAAAAAXY/USMbQuCkpHI/s320/artichoke.png" /&gt;&lt;/a&gt;So many domestic projects and assignments lately leaves little time for writing about other things.&amp;nbsp; Some of those projects have me out in the yard though, so things could be worse.&lt;br /&gt;&lt;br /&gt;During the first week in April I started making trips to the garden to assess things.&amp;nbsp; To my surprise, I discovered that my artichokes from last year survived the winter.&amp;nbsp; (Look at the picture!)&lt;br /&gt;&lt;br /&gt;I first planted artichokes three seasons ago.&amp;nbsp; Starting from seeds I ended up with two plants that year.&amp;nbsp; Neither of them flowered though.&amp;nbsp; I knew that it would take two seasons for the plants to mature, so I bedded them down well (I thought) and let them have the winter off.&lt;br /&gt;&lt;br /&gt;They died.&lt;br /&gt;&lt;br /&gt;So I started the process over last year.&amp;nbsp; For some reason I ended up with a lot more plants.&amp;nbsp; Seven of them.&amp;nbsp; Every seed I planted (from the same seed pouch as the year before) germinated.&amp;nbsp; The season ended, winter came and I bedded the plants down again.&amp;nbsp; I used newspaper and tree leaves, same as I did the year before.&lt;br /&gt;&lt;br /&gt;They made it this time.&amp;nbsp; This means that I should have a really good crop of artichokes this year.&amp;nbsp; Nicole and I are both looking forward to them.&lt;br /&gt;&lt;br /&gt;I planted corn this year, for the first time ever.&amp;nbsp; Normally I skip corn because it is so easy to buy and, to be honest, it would block out a lot of sun other plants in my garden could be using.&amp;nbsp; To keep me interested, I opted for an heirloom popcorn with a shorter habit.&amp;nbsp; The kids are really digging the fact that we are growing popcorn in our garden this year.&amp;nbsp; I noticed the first shoots (corn is a monocot!) poking up on Monday.&lt;br /&gt;&lt;br /&gt;Beans are in the ground, a week late, but should be sprouting any time now.&amp;nbsp; Bush beans this year--I'm tired of managing the trellis.&lt;br /&gt;&lt;br /&gt;Peas were planted at the end of April and are about a foot tall now.&lt;br /&gt;&lt;br /&gt;I had to buy tomato starts for the first time in four or five years.&amp;nbsp; I started my seeds in peat pellets as I normally do.&amp;nbsp; Then I transformed them to styrofoam cups filled with a starter mix, again, as I normally do.&amp;nbsp; I couldn't find my usual starter mix, so I had to use an off brand.&amp;nbsp; That was a mistake.&amp;nbsp; The transplants struggled after that, and really struggled when I began to harden them off a few weeks later.&amp;nbsp; I've all but given up on them now.&lt;br /&gt;&lt;br /&gt;We're doing several different kinds of winter squash this year.&amp;nbsp; Giant pumpkins too.&amp;nbsp; The aim this year is to keep it low maintenance, as we're taking a looooooong vacation in the middle of the summer.&amp;nbsp; Hopefully it will take care of itself, so long as the watering system holds out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-4000083677001170420?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/4000083677001170420/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=4000083677001170420' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/4000083677001170420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/4000083677001170420'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/05/yes-virginia-there-is-garden.html' title='Yes Virginia, there is a garden...'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_Uo-_9LOo8vM/ShXWevudV6I/AAAAAAAAAXY/USMbQuCkpHI/s72-c/artichoke.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-7923632593077168357</id><published>2009-05-05T21:49:00.000-06:00</published><updated>2009-05-05T21:49:35.249-06:00</updated><title type='text'>Tweets and Scrobbling</title><content type='html'>My hobby site, &lt;a href="http://www.tagfriendly.com/"&gt;Tagfriendly&lt;/a&gt;, got with the times last weekend and started using &lt;a href="http://www.twitter.com/"&gt;Twitter&lt;/a&gt;.&amp;nbsp; It tweets new songs as they are found, at a rate of once every 5 minutes.&lt;br /&gt;&lt;br /&gt;Kind of noisy I thought, until people started following.&amp;nbsp; TF followers are, for the most part, record labels.&amp;nbsp; But there are others who are just interested, and others who are just... well, I'm not sure.&amp;nbsp; I'm still trying to figure out how the underbelly of Twitter operates.&lt;br /&gt;&lt;br /&gt;I also took time to get some deeper &lt;a href="http://last.fm/"&gt;Last.fm&lt;/a&gt; integration put together.&amp;nbsp; If you &lt;a href="http://www.tagfriendly.com/persona/details"&gt;allow it&lt;/a&gt;, Tagfriendly can scrobble the songs you love/ban while you are listening to them inside of the TF player.&amp;nbsp; My next step is to give the TF player some UI love so that it can pop out to be its own window and do a few other fancy things.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;I took a quick peek to see what it would take to scrobble all songs played, but it would require the user to give TF his password.&amp;nbsp; I'm not comfortable with that, so until there is another way, TF won't be scrobbling played tracks.&lt;br /&gt;&lt;br /&gt;I'm going to focus a bit more on the player, as I think it can make the site more fun.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-7923632593077168357?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/7923632593077168357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=7923632593077168357' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/7923632593077168357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/7923632593077168357'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/05/tweets-and-scrobbling.html' title='Tweets and Scrobbling'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-2006481594741118815</id><published>2009-04-14T07:00:00.002-06:00</published><updated>2009-04-14T07:00:00.797-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='tagfriendly'/><title type='text'>Hacking the Yahoo! Media Player</title><content type='html'>I've been using the &lt;a href="http://mediaplayer.yahoo.com/"&gt;Yahoo! Media Player&lt;/a&gt; to stream Mp3s at &lt;a href="http://www.tagfriendly.com/"&gt;Tagfriendly&lt;/a&gt;.&amp;nbsp; Minor glitches aside*, the only real complaints I have is that it isn't &lt;a href="http://en.wikipedia.org/wiki/Skinnable"&gt;skinnable&lt;/a&gt; and there is no public API.&lt;br /&gt;&lt;br /&gt;About a month ago I started prodding it to see what would make it squeak.&amp;nbsp; This post documents some of what I've found.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;Disclaimer:&lt;/b&gt; I skimmed over the YMP &lt;a href="http://info.yahoo.com/legal/us/yahoo/utos/utos-173.html"&gt;terms of service&lt;/a&gt; and don't believe I'm breaking any of the rules.&amp;nbsp; You should also know that YMP is a) beta software, and b) a hosted application.&amp;nbsp; This means that any code you write or use that relies on specific methods or objects will be brittle and prone to breaking when Yahoo! releases updates.&amp;nbsp; That said, you're on your own; I didn't make you do anything.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;YMP is one of those nifty internet tools you can use by simply embedding a &amp;lt;script&amp;gt; element in your markup.&amp;nbsp; If the page you've embedded it in contains links to mp3s, or if it links to an &lt;a href="http://www.xspf.org/"&gt;XSPF&lt;/a&gt; playlist, YMP picks it up and makes those MP3s streamable.&amp;nbsp; This is powerful if you're a non-technical blogger and want to have an embedded player on your site.&lt;br /&gt;&lt;br /&gt;My aim is to leverage all of that, but to take the Yahoo! face off and give it my own.&amp;nbsp; I use &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; to manipulate the Tagfriendly DOM, but really, any decent JS toolkit should allow you to get the same results.&lt;br /&gt;&lt;br /&gt;The first thing you need to do is know when YMP is finished loading so that you can tell the UI to go away.&amp;nbsp; Due to the fact that the Javascript you embed includes a bootstrap that downloads other things, you can't count on YMP to be &lt;a href="http://docs.jquery.com/Events/ready"&gt;ready&lt;/a&gt; when your document is.&amp;nbsp; This is easily accomplished with a &lt;a href="http://www.google.com/search?hl=en&amp;amp;q=javascript+timer&amp;amp;btnG=Google+Search&amp;amp;aq=f&amp;amp;oq="&gt;JS timer&lt;/a&gt; that polls to check whether or not &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;YAHOO.MediaPlayer.setPlayerViewState&lt;/span&gt; is defined.&amp;nbsp; When it is, call &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;YAHOO.MediaPlayer.setPlayerViewState(YAHOO.mediaplayer.View.DisplayState.HIDDEN);&lt;/span&gt; to make the YMP user interface go away.&lt;br /&gt;&lt;br /&gt;Now you are in the drivers set to start working with the MediaPlayer object.&amp;nbsp; Here are some useful methods:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;YAHOO.MediaPlayer.getTrackPosition()&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/b&gt;&lt;/span&gt;Gets the position offset (in seconds) of the currently playing (or paused) track.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;YAHOO.MediaPlayer.getTrackDuration()&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/b&gt;Gets the track duration (in seconds).&amp;nbsp; YMP appears to grab this from ID3 tags in the mp3, so you can't always count on this piece of data to be there.&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;YAHOO.MediaPlayer.play()&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;/b&gt;Tells the player to play the currently queued song.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;YAHOO.MediaPlayer.pause()&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/b&gt;&lt;/span&gt;Tells the player to pause the currently playing song.&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;YAHOO.MediaPlayer.previous()&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/b&gt;Go back to the previous song.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;YAHOO.MediaPlayer.controller.EventManager.onNextRequest.fire()&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/b&gt;I found it odd that there was no &lt;i&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;YAHOO.MediaPlayer.next()&lt;/span&gt;&lt;/i&gt; method.&amp;nbsp; This method does what you expect the non-existent &lt;i&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;next()&lt;/span&gt;&lt;/i&gt; would.&amp;nbsp; There are corresponding &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;fire()&lt;/span&gt; objects for play, pause and previous as well.&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;YAHOO.MediaPlayer.getMetaData()&lt;/b&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/b&gt;Returns an object that describes the currently queued song.&amp;nbsp; Useful properties there, gathered from &lt;a href="http://www.id3.org/"&gt;ID3&lt;/a&gt; and the XSPF, include 'title' and 'artistName'.&amp;nbsp; There're more if you care to look.&lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;That's basically it--all you need to subvert the YMP UI and handle things your own way.&amp;nbsp; This really is a guerrila API hack, as I don't think the YMP designers intended a public API.&amp;nbsp; You can see the results&amp;nbsp; on the front page of Tagfriendly.&amp;nbsp; I went as far as providing a progress bar that gets updated as the song plays.&amp;nbsp; The &lt;a href="http://www.tagfriendly.com/tfplayer.js"&gt;Javascript&lt;/a&gt; source is freely available too.&lt;br /&gt;&lt;br /&gt;In the future I plan on displaying cover art and linking the songs to their Tagfriendly description pages as well as to music stores. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;* I suppose not so minor because it really bothers me:&amp;nbsp; YMP breaks down when you try to use a locally hosted XSPF file or the machine it is hosted on is stuck behind NAT.&amp;nbsp; Firebug reports that YMP executes a GET with the URI to the XSPF.&amp;nbsp; The backend of that GET does some data-munging of the XSPF contents.&amp;nbsp; The results contain a basic JSONified playlist.&amp;nbsp; The only problem is that if the [development] server that hosts the XSPF is behind NAT, that backend can't fetch anything.&lt;br /&gt;&lt;script&gt; &lt;/script&gt;&lt;br /&gt;&lt;script&gt; reference anywhere in your markup.&amp;nbsp; It is designed to be simple enough for just about anybody to use, and it largely succeeds there.&lt;/p&gt;&lt;p&gt;What I want to do is leverage their player, but with my own looks.&amp;nbsp; Doing that requires getting dirty with Javascript.&lt;/p&gt;&lt;p&gt;First, &lt;/p&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-2006481594741118815?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/2006481594741118815/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=2006481594741118815' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/2006481594741118815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/2006481594741118815'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/04/hacking-yahoo-media-player.html' title='Hacking the Yahoo! Media Player'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-2563574989448258445</id><published>2009-03-27T05:58:00.002-06:00</published><updated>2009-03-27T06:24:37.457-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>Book Review: The Mystery of the Aleph</title><content type='html'>I am a sucker for a good math book.  No, not the calculus book you had to buy in college--I'm not referring to that.  I suppose I might more properly say that I'm a sucker for a good book about &lt;span style="font-style: italic;"&gt;math history&lt;/span&gt;.  My first exposure to this genre came in high school when I read &lt;a href="http://www.amazon.com/Asimov-Numbers-Isaac/dp/0517371456"&gt;Asimov on Numbers&lt;/a&gt;.  I was not aware then that Asimov wrote non-fiction, but at that point (I was 17, a senior) I barely had time to be aware of the &lt;span style="font-style: italic;"&gt;mandatory&lt;/span&gt; reading assignments I was given (thank you, Milton, Ibsen and Faulkner).&lt;br /&gt;&lt;br /&gt;So it started, and I've read a great number of math books since.  A few weeks ago I picked up &lt;span style="font-style: italic;"&gt;The Mystery of the Aleph: Mathematics, the Kabbalah, and the Search for Infinity&lt;/span&gt; by Amir D. Aczel.  It is about the mathematicians who have studied infinity and the &lt;a href="http://en.wikipedia.org/wiki/Continuum_hypothesis"&gt;continuum&lt;/a&gt;.  Infinity is one of those mathematical concepts that, as a beginner, one thinks he has his head around until he is taught a few advanced concepts.  And then, of course, one realizes he knows almost nothing and it is difficult to trust what you already think you know.&lt;br /&gt;&lt;br /&gt;The book focuses mostly on work done by Georg Cantor and Kurt Gödel, and explains how each lost his sanity during the course of trying to prove different properties related to the continuum hypothesis.  While never able to prove or disprove the continuum hypothesis, each man ended up making valuable contributions to mathematics.  Other disciplines too: as a computer science major I remember learning about how Gödel was able to prove that some problems are not solvable in a given system. &lt;br /&gt;&lt;br /&gt;For the most part, I enjoyed this book.  The math, when presented is covered in terms most non-math types can understand.  There are helpful diagrams that serve to illustrate and clarify difficult points and concepts.  I've read other works by the author and this book is about what I expected.&lt;br /&gt;&lt;br /&gt;Something I didn't care for was the tendency to bring religion into the story where it didn't really fit.  I couldn't see the point of dwelling on Cantors Jewish heritage.  It didn't help the story and almost made me wonder if the author was trying to say "look, Jews have made important contributions to mathematics!"  Big deal.  The only group of people who haven't made important contributions to mathematics are the eskimos, and they're too busy to care.&lt;br /&gt;&lt;br /&gt;So, if you want to learn about how our perception of infinity has changed over the years, go read this book.  It's not bad.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-2563574989448258445?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/2563574989448258445/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=2563574989448258445' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/2563574989448258445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/2563574989448258445'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/03/book-review-mystery-of-aleph.html' title='Book Review: The Mystery of the Aleph'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-4587784141429689804</id><published>2009-03-19T20:25:00.004-06:00</published><updated>2009-03-19T20:36:24.476-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Emotional Investing</title><content type='html'>Nicole and I take X percent of our income each year and put in various retirement investments.  We had a bit left over for 2008 and I've been wanting to invest in wind energy.  Specifically, I'm looking for a wind turbine manufacturer who is well-established elsewhere and trying to break into the burgeoning U.S. market.  (If you find such a company, and it can be easily traded in the U.S., let me know.)&lt;br /&gt;&lt;br /&gt;While researching this I came across &lt;a href="http://finance.yahoo.com/q?s=pwnd"&gt;PWND&lt;/a&gt;.  The techie in my wanted to snatch it up just so I could say I have stock in &lt;a href="http://www.urbandictionary.com/define.php?term=pwnd"&gt;PWND&lt;/a&gt;.  I mean, that would be &lt;a href="http://en.wikipedia.org/wiki/Leet"&gt;l33t&lt;/a&gt;, wouldn't it?  Anyway, I had to pass it up.  What little I know about investing in stocks has taught me to stay away from &lt;a href="http://en.wikipedia.org/wiki/Exchange-traded_fund"&gt;ETF&lt;/a&gt;s.&lt;br /&gt;&lt;br /&gt;Back to the research...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-4587784141429689804?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/4587784141429689804/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=4587784141429689804' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/4587784141429689804'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/4587784141429689804'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/03/emotional-investing.html' title='Emotional Investing'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-8602590618655542152</id><published>2009-02-22T09:46:00.011-07:00</published><updated>2009-02-22T21:28:12.363-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='mythtv'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Restoring Myth Programs Whilst Maintaining Sanity</title><content type='html'>My MythTv system has been running continually, more or less, since October 2006.  Not &lt;span style="font-style: italic;"&gt;too&lt;/span&gt; long, but long &lt;span style="font-style: italic;"&gt;enough&lt;/span&gt;. Long enough, in fact, for cruft to creep in.  I discovered this on Saturday when I went to restore data to the replacement for the myth drive affectionately known as "xfs2" that died about a month ago.&lt;br /&gt;&lt;br /&gt;That drive had a capacity of 250GB.  My myth data is important to me, but not &lt;span style="font-style: italic;"&gt;that&lt;/span&gt; important.  I had it set to back up once a month to another computer in the house via rsync.  I didn't pay too close attention to the way I used rsync though--instead of removing the remote files that had been removed locally, they just stayed there.  In other words, unneeded data on the backup never went away, even when I deleted shows on the myth system.&lt;br /&gt;&lt;br /&gt;So when I went to copy 274GB of data to a drive that would only hold 238GB, things went haywire.&lt;br /&gt;&lt;br /&gt;Thankfully, I am a programmer.  I am equipped for these kinds of situations.&lt;br /&gt;&lt;br /&gt;I needed to figure out which shows missing locally that were present on the backups.  These are the files that needed to be restored.  After that, I figured it would be gravy if I could remove the orphans that were in the database but not on any file system, be it local or backup.&lt;br /&gt;&lt;br /&gt;It turns out that python is incredibly easy to use with MySQL.  I created a simple program that would restore from my backup and also give me a list of orphaned programs.&lt;br /&gt;&lt;br /&gt;Seems easy, right?  The complexity comes when both local and backup storage are strewn across different drives, directories and hosts.  I made it simpler by using smbmount to mount the backup system so it appeared more or less local.  After that it became a matter of letting the script run* and then cleaning up the orphans with a simple sql statement.&lt;br /&gt;&lt;br /&gt;Source code for myth.py is at the bottom of this post.&lt;br /&gt;&lt;br /&gt;* This turned out to be tricky.  Something on my myth host causes it to intermittently hang when copying files to or from a remote host.  It could be my router for all I know.  I do know that *any* keystroke received by the myth system causes it to wake up and start accepting traffic again.  Meanwhile, the system clock thinks nothing has happened and starts up again at the same tick where it fell asleep--so the clock is off.  This problem first started when I decided to upgrade to Ubuntu 8.10 and MythTv 0.21 on the same day.  Truly disturbing, I know.  I circumvent this by bandwidth-limiting scp to 2Mbit for the transfer.  Transfers take longer, but at least they complete. And yes, I am retiring this system in a few weeks.  :)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import MySQLdb as db&lt;br /&gt;import os&lt;br /&gt;import sys&lt;br /&gt;&lt;br /&gt;existing_video_dirs = ["/xfs1/myth/video", "/xfs2/myth/video"]&lt;br /&gt;# If you use scp, backup_video_dirs and backup_scp_paths need to be maintained&lt;br /&gt;# in parallel. For sure though, backup_video_dirs need to be locally mounted.&lt;br /&gt;backup_video_dirs = ["/mnt/remote_backups/myth_backup/xfs1/myth/video", "/mnt/remote_backups/myth_backup/xfs2/myth/video"]&lt;br /&gt;backup_scp_paths = ["garyd@child:/mnt/xfs3/myth_backup/xfs1/myth/video", "garyd@child:/mnt/xfs3/myth_backup/xfs2/myth/video"]&lt;br /&gt;backup_info_dict = zip(backup_video_dirs, backup_scp_paths)&lt;br /&gt;possible_file_extensions = ["mpg", "nuv"]&lt;br /&gt;&lt;br /&gt;# this is the place video gets copied to.&lt;br /&gt;restore_path = "/xfs2/myth/video/"&lt;br /&gt;&lt;br /&gt;# connect to the database and get the list of shows.&lt;br /&gt;con = db.connect(host="localhost", user="root", passwd="root", db="mythconverg")&lt;br /&gt;cur = con.cursor()&lt;br /&gt;cur.execute("select chanid, starttime, title from recordedprogram order by chanid, starttime")&lt;br /&gt;rows = cur.fetchall()&lt;br /&gt;&lt;br /&gt;# keep track of the number that are there or not.&lt;br /&gt;there = 0&lt;br /&gt;not_there = 0&lt;br /&gt;restored = 0&lt;br /&gt;&lt;br /&gt;for row in rows:&lt;br /&gt;    # name of the file is based on row values, plus a file extension.&lt;br /&gt;    fname = "%d_%s" % (row[0], row[1].strftime("%Y%m%d%H%M%S"))&lt;br /&gt;    # see if the file exists in the local myth dirs. If it does, there is no&lt;br /&gt;    # action.&lt;br /&gt;    exists = False&lt;br /&gt;    for dir in existing_video_dirs:&lt;br /&gt;        for ext in possible_file_extensions:&lt;br /&gt;            path = os.path.join(dir, fname + "." + ext)&lt;br /&gt;            if os.path.exists(path):&lt;br /&gt;                exists = True&lt;br /&gt;    if exists:&lt;br /&gt;        there += 1&lt;br /&gt;    else:&lt;br /&gt;        # if the file does not exist locally, look at the backup directories to&lt;br /&gt;        # see if it is there.&lt;br /&gt;        not_there += 1&lt;br /&gt;        backup_exists = False&lt;br /&gt;        backup_at = None # path of backup file.&lt;br /&gt;        backup_scp = None # scp path of backup file.&lt;br /&gt;        #for tup in backup_info_dict:&lt;br /&gt;        for dir, scp in backup_info_dict:&lt;br /&gt;            for ext in possible_file_extensions:&lt;br /&gt;                path = os.path.join(dir, fname + "." + ext)&lt;br /&gt;                if os.path.exists(path):&lt;br /&gt;                    # found a backup! use wild cards so that the video file&lt;br /&gt;                    # and its preview get copied.&lt;br /&gt;                    backup_at = path + "*"&lt;br /&gt;                    backup_scp = scp + "/" + fname + "." + ext + "*"&lt;br /&gt;                    backup_exists = True&lt;br /&gt;        if not backup_exists:&lt;br /&gt;            print "No backup for %s" % (fname)&lt;br /&gt;        else:&lt;br /&gt;            # move the backup to the live system. use cp or scp depending on&lt;br /&gt;            # your preference.&lt;br /&gt;            cmd = "cp %s %s" % (backup_at, restore_path)&lt;br /&gt;            # something on my system is jacked. I need to bandwidth limit scp&lt;br /&gt;            # or else the myth server stalls.&lt;br /&gt;            cmd = "scp -l16000 %s %s" % (backup_scp, restore_path)&lt;br /&gt;            print cmd&lt;br /&gt;            os.popen(cmd)&lt;br /&gt;            restored += 1&lt;br /&gt;&lt;br /&gt;# output the stats.&lt;br /&gt;print "there:%d not_there:%d restored:%d" % (there, not_there, restored)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Update: fixed tabbing in code.  Should have used pastebin.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-8602590618655542152?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/8602590618655542152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=8602590618655542152' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/8602590618655542152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/8602590618655542152'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/02/restoring-myth-programs-whilst.html' title='Restoring Myth Programs Whilst Maintaining Sanity'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-3988875817411843444</id><published>2009-02-21T07:17:00.001-07:00</published><updated>2009-02-21T07:52:18.668-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tagfriendly'/><title type='text'>Tagfriendly Update</title><content type='html'>I am going to tie off version 0.1 since I've accomplished the meager goals I set for myself in January with regard to &lt;a href="http://www.tagfriendly.com/"&gt;Tagfriendly&lt;/a&gt;.  Here is what they were:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Track music blogs.&lt;/li&gt;&lt;li&gt;Full-text search.&lt;/li&gt;&lt;li&gt;Dynamic RSS feeds (turned on last night).&lt;/li&gt;&lt;li&gt;Learn python (still a work-in-progress).&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;I've added other features along the way, but those are the basics that I wanted. Here are some things I've been thinking about for the next iteration (roughly one month):&lt;br /&gt;&lt;ol&gt;&lt;li&gt;More &lt;a href="http://www.last.fm"&gt;Last.fm&lt;/a&gt; (social) integration.  Lots of ideas here.  For example:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;What if when you scanned the recent MP3s, you could know which ones your friends like?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;What if you could create an RSS feed that would generate entries related to your top 10 (20 or 30) songs or bands? (this was suggested by a friend.)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;What if you could scrobble love/hate directly from the website?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Lots of cool things here, and they won't be too hard to implement.&lt;/li&gt;&lt;li&gt;The problem with Last.fm is that using them has a detrimental impact on Tagfriendly site performance (their services are S-L-O-W).  I've used a lot of caching (artist information mostly), but that only gets me so far.&lt;br /&gt;    &lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Simple identity management. This will enable features like "show me all the new stuff since the last time I was here." I'll start with just a cookie. That has limitations, so I'll eventually push for simple email registration.&lt;/li&gt;&lt;li&gt;Flash based in-browser mp3 player to stream the songs from the blogs. The ethics of this are probably dubious, but I have noticed that many of the bloggers deep link to mp3s stored on other sites. I guess we're all in this together.  Hopefully I can find something off the shelf that does this.&lt;/li&gt;&lt;li&gt;I need to clean up the back-end scripts that do the crawling and generate the static pages.&lt;/li&gt;&lt;li&gt;Better tests.&lt;/li&gt;&lt;li&gt;More blogs.  I'm up to 30 and crawling+indexing get done in about 3-4 minutes.  I'd like to scale up to 100 blogs for this iteration and see how things are handled.&lt;br /&gt;  &lt;/li&gt;&lt;/ol&gt;That's about it for a month. I average about an hour a day of Tagfriendly development, so this is about the right amount of work for a month.  (Honestly, I could probably spend an entire month on testing, but how sexy is that?)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-3988875817411843444?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/3988875817411843444/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=3988875817411843444' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/3988875817411843444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/3988875817411843444'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/02/tagfriendly-update.html' title='Tagfriendly Update'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-2111680052506498311</id><published>2009-02-18T18:00:00.000-07:00</published><updated>2009-02-18T18:00:01.629-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>The Saddest Story Ever Told</title><content type='html'>If you depend on a computer like I do, this one will make your innards shrivel up inside you and convince you to become a hermit...&lt;br /&gt;&lt;br /&gt;The display unit in my company-owned MacBookPro when belly up on Monday night (thank you, Nvidia), one day before the one-year warranty would expire.  (This was actually fortuitous, as my employer &lt;span style="font-weight: bold;"&gt;did&lt;/span&gt; spring for Applecare, but it was lost and never registered to my Macbook.  Another story.)  I quickly made plans to take the ailing machine to the Apple Store in Salt Lake City on Tuesday.  Then I set about deciding on how I would work until I got it back.  I am a remote employee; no IT staff to give me a loaner when equipment goes bad.&lt;br /&gt;&lt;br /&gt;Here is the lay of the computers in my house:&lt;br /&gt;1.  Nicole has a 2.5 year old white Macbook (single core Intel 1.2 GHz?)&lt;br /&gt;2.  The kids have a brand new dual core Intel Atom 1.6GHz machine.  It has a 1.5TB drive in it and serves mainly as a network storage device.&lt;br /&gt;3.  MythTv runs on a very old AMD Athlon 1.3 GHz machine.&lt;br /&gt;&lt;br /&gt;Using the Myth server was out of the question.  Not only is it too old to be useful in my work, it has reached mission-critical status in our household.  We need our TV shows.&lt;br /&gt;&lt;br /&gt;Nicole offered, and I breifly considered using her computer.  I decided not to because I thought the kids computer might be a bit more powerful (though not a mac) and I didn't want to bother setting up a my dev environment there.  You see, I had &lt;span style="font-style: italic;"&gt;a plan&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The Plan involved using the kids computer.  It was new, though underpowered, but I figured I could make it work fine.  Before taking my macbook in I made a copy of the windows virtual machine I sometimes work in.  I figured I could install VMWare Player on the kids computer, turn on the VM and I'd be in good shape.  Setting up a non-development machine to do development work usually consumes about half a day for me, so I was keen on avoiding this.&lt;br /&gt;&lt;br /&gt;But it wasn't meant to be.&lt;br /&gt;&lt;br /&gt;The only file system on their computer that had space for the VM was formatted XFS, and I had been having little problems with it that I had mostly chosen to ignore.  VMWare started complaining about 30 seconds after bringing the VM up.  Then the OS dropped the volume completely.  Ouch.&lt;br /&gt;&lt;br /&gt;I ran xfs_repair and re-mounted the volume to try again.  I'm a hopeful person and besides that, I needed to get some work done.  Same exact problem.  Ugh.&lt;br /&gt;&lt;br /&gt;At this point my thoughts were focused on two things:  First, I had a few work tasks that must get accomplished, and I still didn't have a dev environment to do those tasks.  Second, I needed to get rid of XFS on that volume.  It would not be viable in the short- or long-term.&lt;br /&gt;&lt;br /&gt;First things first... I still haven't put the new 250GB hard drive in the myth server to replace the dead one.  I decided to stick a USB enclosure on it, format it as ext3 and move the windows VM to it.  At least then I could get into the VM without it crashing.  The VM ended up performing quite poorly (due to running over USB), but would be ok for an afternoon of work.&lt;br /&gt;&lt;br /&gt;Next I had to figure out how to get rid of the crappy XFS partition that was giving me grief.  The only problem was that it had about 750GB worth of data that I couldn't just delete.  It contained my music backups (expendable), DVD rips (not very expendable, but I could live without them), myth backups (needed for a full recovery if I ever got around to replacing the dead drive in the myth machine) and other assorted backups.&lt;br /&gt;&lt;br /&gt;Luckly, I happened to have an &lt;span style="font-weight: bold;"&gt;extra&lt;/span&gt; 1.5TB drive laying around.  I plan to put together a new Myth server in a few weeks and have started assembling the new hardware.  I briefly tried installing windows XP on that drive (wasn't looking forward to working in a VM), but the aged XP installer didn't like the humongous drove.  Oh well.  You know the drill by now: USB enclosure, format ext3, and move data off the XFS volume.  Ubuntu estimated it would take about 8 hours for the transfer, so I went to bed.&lt;br /&gt;&lt;br /&gt;In the morning, the copy looked good, so I removed the USB drive and set it aside.  Next I unmounted the XFS partition and reformatted it as ext3.  Then I moved my 30 GB VM onto it and fired it up.&lt;br /&gt;&lt;br /&gt;It works a lot better.  Not only is it stable, but it runs a lot faster (this was expected).  I suppose I can work like this for a week until my Macbook comes back.&lt;br /&gt;&lt;br /&gt;The next step will be to restore the backup data off the USB drive back onto the backup machine.  I'm losing the stomach for hardware maintenance, so I'm going to put it off for a day or two.&lt;br /&gt;&lt;br /&gt;NOTE:  I've used every model of 15-inch MacBookPro/PowerBook since the Aluminum G4.  Each one has needed repairs within the first year (one even shipped with a defective trackpad).  My take: &lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;always&lt;/span&gt;&lt;/span&gt; spring for the extended warranty.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-2111680052506498311?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/2111680052506498311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=2111680052506498311' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/2111680052506498311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/2111680052506498311'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/02/saddest-story-ever-told.html' title='The Saddest Story Ever Told'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-7550936479630179118</id><published>2009-02-06T07:00:00.005-07:00</published><updated>2009-02-06T07:00:01.715-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tagfriendly'/><title type='text'>Full-text Indexing on the Cheap</title><content type='html'>&lt;span style="font-style: italic;"&gt;After Christmas I decided I wanted to build an mp3 blog aggregator that would be all my own.  I've decided to &lt;/span&gt;&lt;a style="font-style: italic;" href="http://www.onemanclapping.org/search/label/tagfriendly"&gt;chronicle the process here on my blog&lt;/a&gt;&lt;span style="font-style: italic;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I have been a big fan of &lt;a href="http://lucene.apache.org/"&gt;Lucene&lt;/a&gt; for years, although I now prefer &lt;a href="http://lucene.apache.org/solr"&gt;Solr&lt;/a&gt; (it's still Lucene) for new projects.  The main reason I've stuck to Lucene is that most projects I've worked on have been Java-related and limited hardware resources haven't been an issue.&lt;br /&gt;&lt;br /&gt;All that changed with the latest incarnation of &lt;a href="http://www.tagfriendly.com/"&gt;Tagfriendly&lt;/a&gt;.  I develop it on a linux VM, which has all the hardware resources of my workstation (more than enough to handle Lucene), but I deploy Tagfriendly to a &lt;a href="http://en.wikipedia.org/wiki/Virtual_private_server"&gt;VPS&lt;/a&gt; where my VM is one of many that may be sharing the same physical hardware.  To put it simply: I am hardware-constrained, currently stick with 128MB RAM and 5GB of disk space.  For example, consider this: apt-get update craps out if I'm running &lt;a href="http://www.lighttpd.net/"&gt;lighttpd&lt;/a&gt;+&lt;a href="http://pythonpaste.org/script/"&gt;paster&lt;/a&gt;.  Yeah, it's like that.&lt;br /&gt;&lt;br /&gt;While I can grow to a bigger VPS if I need to, I figured it would be good to build Tagfriendly to be lean on resources.  Bottom line: I couldn't consider using Lucene as the search engine.  So I started to look at other options.&lt;br /&gt;&lt;br /&gt;The first two I considered were &lt;a href="http://www.postgresql.org/docs/current/static/tsearch2.html"&gt;tsearch2&lt;/a&gt; and &lt;a href="http://www.sphinxsearch.com/"&gt;sphinx&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;tsearch2 kind of surpised me.  The last time I looked into it was several years ago when it was a postgres contrib module--not part of the standard release.  Even though the idea of having a full-text search structured like a SQL query was alluring, I didn't consider tsearch2 for long. I knew I wanted to be able throw just about anything into the index and rely on a "type" field to restrict results to particular data (e.g., mp3s or blog entries).&lt;br /&gt;&lt;br /&gt;That left me with sphinx.  I came across it while I was googling for Lucene alternatives.  It has python bindings, is written in C, and claimed to be very lightweight.  Seemed like a good fit.  One downside I noticed is that once a sphinx index is created and initially filled, it can't be added to.  That means I would have to generated the index from scratch every time I need to update it.  Ouch.  (Maybe this isn't true in newer releases.)  I kept Sphinx on the list, but kept looking.&lt;br /&gt;&lt;br /&gt;A day or two later, before I had written any indexing code, a friend pointed me to &lt;a href="http://xapian.org/"&gt;Xapian&lt;/a&gt;, which has a lot of the characteristics of Sphinx, except that Xapian is more mature (and can be updated).  I settled on using &lt;a href="http://xappy.org/"&gt;Xappy&lt;/a&gt; which is a python wrapper around the basic python bindings provided by Xapian. Xappy simplifies the fielded aspect of managing a Xapian index (makes it feel more like Lucene).  After playing with both the standard python Xapian bindings and xappy, I recommend using Xappy for simple indexing projects.  The learning curve for the traditional Xapian API is pretty steep.&lt;br /&gt;&lt;br /&gt;A few hours after finding Xappy (spread out over a few nights of work), I managed to produce a simple index page in pylons and an indexing daemon for Tagfriendly.  The index only contains about 1500 documents at this point, so searching is still quite snappy. We'll see how it goes as the document count grows.&lt;br /&gt;&lt;br /&gt;With an index in place, I am free to move on to some of the really interesting features and ideas I want to explore with Tagfriendly.  For example, I am excited to implement a feature where users can create RSS feeds based on custom search criteria (e.g. includes Morrissey, but not The Smiths).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-7550936479630179118?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/7550936479630179118/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=7550936479630179118' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/7550936479630179118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/7550936479630179118'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/02/full-text-indexing-on-cheap.html' title='Full-text Indexing on the Cheap'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-6819618663851734721</id><published>2009-02-02T06:12:00.004-07:00</published><updated>2009-02-02T08:05:46.502-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='football'/><category scheme='http://www.blogger.com/atom/ns#' term='mythtv'/><title type='text'>Superbowl Notes, 2009</title><content type='html'>I had taken pains to make sure watching the super bowl would be simple and painless.  This included having dinner ready by 4:30 (we get home from church at 4), cookie dough (for snacks) already made, and Mythtv set to record the whole thing starting at 4.&lt;br /&gt;&lt;br /&gt;We were done with dinner at 5.  I took my time cleaning up, even though Gavan was chomping at the bit, unable to wait for us to start watching the game.  I started a batch of cookies and went downstairs to start watching with Gavan.&lt;br /&gt;&lt;br /&gt;I'll interject here and say that I'm not a huge TV sports fan.  I was in my early years, but those tendencies seem to have left me about the same time fatherhood arrived.  (I'm not sure if there is a connection or not.)  The truth is, I would have peeked in on the game at intervals, watching for perhaps five minutes at a time.  In the mean time, Gavan would be riveted to the sofa, basking in every moment of it.  Such is youth.&lt;br /&gt;&lt;br /&gt;None of it was to be though.  Our one-year old, while Nicole was retrieving some items from the crawlspace, where the myth server is kept, managed to press the exact sequence of keys required to send the machine into hibernate.  While it was recording.  The super bowl.&lt;br /&gt;&lt;br /&gt;If you follow this blog, you know that we've had a few &lt;a href="http://www.onemanclapping.org/2009/01/return-of-clone.html"&gt;problems&lt;/a&gt; with our MythTv setup lately.  Apparently, this was too much for the system.  Bringing the machine out of hibernate while in the middle of a write (recording the show), and a read (we were watching it on the MVP) was a Very Bad Thing, at least to the poor XFS filesystem that received the battering.  I had no choice but to bring the system down.  In the process of bringing the system back up again, I was informed by fsck that my disk was in bad shape and that I wouldn't be using it until I personally rectified the situation.  Ouch.  That is two of two disks down for the count.&lt;br /&gt;&lt;br /&gt;All I really wanted to do was watch a few minutes of football with my son.&lt;br /&gt;&lt;br /&gt;I grabbed the nearest piece of long coax, intending to connect it from the dish receiver--in the crawlspace, to the television--in the basement.    I was angry.  And not just a little bit angry.  My daughter's Hello Kitty kick-ball was the nearest object I thought I could kick without injuring anybody, so I took a swing at it.  And when I say "took a swing at it," I really mean to say is that I kicked at it like it was the last kick an unreformed kicking addict would ever kick because it was the last kickable object left in the universe.  I put my heart, soul and body into it.&lt;br /&gt;&lt;br /&gt;I mostly missed the ball.  And mostly kicked the door.  Ouch.  I'm not doing good here.  My foot throbbing and turing grurple (green+purple) in spots, I connected the coax, made sure the game was on, and then let Gavan know to come downstairs.&lt;br /&gt;&lt;br /&gt;It was halftime at this point.  I retreated to a bathroom to let some cold water run over my foot.  I helped some.  I was sure I had broke something.&lt;br /&gt;&lt;br /&gt;The pain subsiding, and firmly in control of myself again, I sat down at the console to take a look at the Myth system.  I set up a temporary space to hold shows and brought it back up, sans 500BG of storage.  Ugh.  But at least it was recording.  I switched the coax back and all was right and sane again.&lt;br /&gt;&lt;br /&gt;I'm kind of glad I missed the first half because the second half was 30 minutes of the best football I had ever watched in my life.  Coming back from 13 points behind is difficult enough.  In fact, the only thing more difficult, I'd say, is coming back after letting a 13 point lead slip away.  And I saw both of those things last night.  Truly remarkable.  In my heart, I was silently rooting for Arizona, the underdogs.  I was elated as I watched Larry Fitzgerald streak 80 yards down the field to put Arizona up.  And then a few minutes later, in awe as I saw a Steelers team, firmly in control, take the ball 99 yards down the field and score on Santonio Holmes pass.  One of the best super bowls ever.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-6819618663851734721?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/6819618663851734721/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=6819618663851734721' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/6819618663851734721'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/6819618663851734721'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/02/superbowl-notes-2009.html' title='Superbowl Notes, 2009'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-6823508415009511725</id><published>2009-01-31T18:00:00.003-07:00</published><updated>2009-01-31T18:00:01.175-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='tagfriendly'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>iTMS link generator API</title><content type='html'>I set about looking for an API that utilizes the&lt;a href="http://apple.com/itunes/linkmaker/"&gt; iTunes Music Store link maker&lt;/a&gt;, thinking they would be all over the place (deep links that is, and includes referral program ids).  Five minutes of half-hearted &lt;a href="http://www.google.com/search?hl=en&amp;amp;q=itms+link+generator+api&amp;amp;btnG=Google+Search&amp;amp;aq=f&amp;amp;oq="&gt;googling&lt;/a&gt; didn't get me anywhere I needed to be, so I decided to take matters into my own hands.  (Note: either I am a crappy googler, or the Apple legal team keeps these things off the air.  Seriously, this code must have already been written 10 or 12 times now.)&lt;br /&gt;&lt;br /&gt;A bit of poking around revealed that Apple (edgesuite, linkshare, linksynergy, whoever!) uses GET for their search forms.  This makes writing a scraper API as complicated as parsing HTML, which is pretty easy in this day and age.  I decided to use python, because I'm learning it by forcing myself to use it for all my extra-curricular projects.&lt;br /&gt;&lt;br /&gt;I've released the &lt;a href="http://www.dusbabek.org/%7Egaryd/itms.py"&gt;source code&lt;/a&gt; under the &lt;a href="http://www.dusbabek.org/%7Egaryd/#Code"&gt;code&lt;/a&gt; section at &lt;a href="http://www.dusbabek.org/%7Egaryd"&gt;my website&lt;/a&gt;.  The license is, uh... liberal.  So don't be afraid to use it if you find it useful.  It depends on the excellent &lt;a href="http://www.crummy.com/software/BeautifulSoup"&gt;BeautifulSoup&lt;/a&gt; library to do the heavy HTML lifting.&lt;br /&gt;&lt;br /&gt;Here is some iTunes deep-linky goodness for you.  These are the top 5 most played songs in my library.  Buy them:&lt;br /&gt;1.  &lt;a href="http://click.linksynergy.com/fs-bin/stat?id=qYIwruBGkB0&amp;amp;offerid=146261&amp;amp;type=3&amp;amp;subid=0&amp;amp;tmpid=1826&amp;amp;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252FWebObjects%252FMZStore.woa%252Fwa%252FviewAlbum%253Fi%253D3271795%2526id%253D3271807%2526s%253D143441%2526partnerId%253D30"&gt;New Slang&lt;/a&gt;, by &lt;a href="http://click.linksynergy.com/fs-bin/stat?id=qYIwruBGkB0&amp;amp;offerid=146261&amp;amp;type=3&amp;amp;subid=0&amp;amp;tmpid=1826&amp;amp;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252FWebObjects%252FMZStore.woa%252Fwa%252FviewArtist%253Fid%253D3271784%2526partnerId%253D30"&gt;The Shins&lt;/a&gt;&lt;br /&gt;2.  &lt;a href="http://click.linksynergy.com/fs-bin/stat?id=qYIwruBGkB0&amp;amp;offerid=146261&amp;amp;type=3&amp;amp;subid=0&amp;amp;tmpid=1826&amp;amp;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252FWebObjects%252FMZStore.woa%252Fwa%252FviewAlbum%253Fi%253D180345358%2526id%253D180345096%2526s%253D143441%2526partnerId%253D30"&gt;Valley Winter Song&lt;/a&gt;, by &lt;a href="http://click.linksynergy.com/fs-bin/stat?id=qYIwruBGkB0&amp;amp;offerid=146261&amp;amp;type=3&amp;amp;subid=0&amp;amp;tmpid=1826&amp;amp;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252FWebObjects%252FMZStore.woa%252Fwa%252FviewArtist%253Fid%253D154213%2526partnerId%253D30"&gt;Fountains of Wayne&lt;/a&gt;&lt;br /&gt;3.  &lt;a href="http://click.linksynergy.com/fs-bin/stat?id=qYIwruBGkB0&amp;amp;offerid=146261&amp;amp;type=3&amp;amp;subid=0&amp;amp;tmpid=1826&amp;amp;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252FWebObjects%252FMZStore.woa%252Fwa%252FviewAlbum%253Fi%253D80427561%2526id%253D80427744%2526s%253D143441%2526partnerId%253D30"&gt;Dreams Anymore&lt;/a&gt;, by &lt;a href="http://click.linksynergy.com/fs-bin/stat?id=qYIwruBGkB0&amp;amp;offerid=146261&amp;amp;type=3&amp;amp;subid=0&amp;amp;tmpid=1826&amp;amp;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252FWebObjects%252FMZStore.woa%252Fwa%252FviewArtist%253Fid%253D7058190%2526partnerId%253D30"&gt;The Magnetic Fields&lt;/a&gt;&lt;br /&gt;4. &lt;a href="http://click.linksynergy.com/fs-bin/stat?id=qYIwruBGkB0&amp;amp;offerid=146261&amp;amp;type=3&amp;amp;subid=0&amp;amp;tmpid=1826&amp;amp;RD_PARM1=%20http%253A%252F%252Fitunes.apple.com%252FWebObjects%252FMZStore.woa%252Fwa%252FviewAlbum%253Fi%253D262848634%2526id%253D262848029%2526s%253D143441%2526partnerId%253D30"&gt; Trust&lt;/a&gt;, by &lt;a href="http://click.linksynergy.com/fs-bin/stat?id=qYIwruBGkB0&amp;amp;offerid=146261&amp;amp;type=3&amp;amp;subid=0&amp;amp;tmpid=1826&amp;amp;RD_PARM1=%20http%253A%252F%252Fitunes.apple.com%252FWebObjects%252FMZStore.woa%252Fwa%252FviewArtist%253Fid%253D78544326%2526partnerId%253D30"&gt;Gravenhurst&lt;/a&gt;&lt;br /&gt;5.  &lt;a href="http://click.linksynergy.com/fs-bin/stat?id=qYIwruBGkB0&amp;amp;offerid=146261&amp;amp;type=3&amp;amp;subid=0&amp;amp;tmpid=1826&amp;amp;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252FWebObjects%252FMZStore.woa%252Fwa%252FviewAlbum%253Fi%253D3863042%2526id%253D3863054%2526s%253D143441%2526partnerId%253D30"&gt;Saint Simon&lt;/a&gt;, by &lt;a href="http://click.linksynergy.com/fs-bin/stat?id=qYIwruBGkB0&amp;amp;offerid=146261&amp;amp;type=3&amp;amp;subid=0&amp;amp;tmpid=1826&amp;amp;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252FWebObjects%252FMZStore.woa%252Fwa%252FviewArtist%253Fid%253D3271784%2526partnerId%253D30"&gt;The Shins&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;BTW, I've resurrected &lt;a href="http://www.tagfriendly.com/"&gt;Tagfriendly&lt;/a&gt; as the mp3 blog aggregator I've been working on, soon to have iTMS referral links.  It isn't much, but I'm adding features all the time.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;(Tagfriendly was, at one time, an &lt;a href="http://www.onemanclapping.org/2004/12/location.html"&gt;automatic ID3 editing tool I created that mostly worked&lt;/a&gt;.)&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-6823508415009511725?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/6823508415009511725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=6823508415009511725' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/6823508415009511725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/6823508415009511725'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/01/itms-link-generator-api.html' title='iTMS link generator API'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-3149817337868811685</id><published>2009-01-30T18:00:00.003-07:00</published><updated>2009-01-30T18:00:00.869-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mythtv'/><title type='text'>Return of the Clone</title><content type='html'>Any time you can mash-up references from Star Wars into a blog entry title that actually applies to the content, it is a Good Thing.&lt;br /&gt;&lt;br /&gt;Over the &lt;a href="http://www.onemanclapping.org/2008/12/upgrading-mythtv.html"&gt;Thanksgiving holiday I did a lot of infrastructure work&lt;/a&gt; on the computers that run in the house.  Part of that work involved setting up a computer to be used by the kids that would also double as a file store for backups (1.5TB disk),  upgrading the &lt;a href="http://www.mythtv.org"&gt;MythTv&lt;/a&gt; server to 0.21 and doubling its storage capacity to 500GB.&lt;br /&gt;&lt;br /&gt;While I was at it, and since I had the space, I decided to set up a weekly rsync to &lt;span style="font-weight: bold;"&gt;clone&lt;/span&gt; ("mirror" is probably more appropriate) the myth video drives to the backup machine.  I'm thankful for that now, as one of the myth drives died last night (250GB Western Digital).  The drive was 3 years old and had spun more or less continually over that time.  I figured its time had come.&lt;br /&gt;&lt;br /&gt;I've ordered a replacement drive which should arrive early next week.  Restoring things should be a simple (gosh, I hope!) as putting in the drive, formatting it, making sure fstab is happy, and then a reverse rsync.  In the meantime, Myth is clipping along using what space is left on the remaining drive.  It had to expire &lt;span style="font-weight: bold;"&gt;A LOT&lt;/span&gt; of stuff, but is doing fine now, except that it still tries to expire shows on the missing drive.  (I wanted to make "phantom" reference here.)&lt;br /&gt;&lt;br /&gt;I did go through the pains of removing the path of the broken drive from its storage group, as myth has a tendency to start recording shows in odd places if it can't find an intended storage group path.  I had to drop down into sql to do this--I couldn't find a way using the UI that didn't involve deleting the entire storage group.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-3149817337868811685?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/3149817337868811685/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=3149817337868811685' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/3149817337868811685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/3149817337868811685'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/01/return-of-clone.html' title='Return of the Clone'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7218232242203115351.post-2115082718108421099</id><published>2009-01-23T22:51:00.006-07:00</published><updated>2009-02-05T16:21:38.413-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='tagfriendly'/><title type='text'>Mp3 Blog Aggregator: status and some code</title><content type='html'>&lt;span style="font-style: italic;"&gt;My &lt;/span&gt;&lt;a style="font-style: italic;" href="http://www.onemanclapping.org/2009/01/mp3-blog-aggregators.html"&gt;last post&lt;/a&gt;&lt;span style="font-style: italic;"&gt; was a lamentation about how the current set of mp3 blog aggregators don't do it for me, and at the same time a declaration that I would do something about it.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I've spent my spare moments this week hacking at the problem and it's starting to bear fruit.&lt;br /&gt;&lt;br /&gt;The first of it is a simple &lt;a href="http://www.dusbabek.org/%7Egaryd/id3.py"&gt;id3 reader&lt;/a&gt; implemented in &lt;a href="http://www.python.org/"&gt;python&lt;/a&gt;.  It simply reaches out over the tubes and grabs the id3 information from an mp3 that is hosted on a server somewhere.  Nothing too complicated, except that it can be configured to extract any images that might be embedded in the mp3.&lt;br /&gt;&lt;br /&gt;Knowledgeable readers might be asking: &lt;span style="font-style: italic;"&gt;"why didn't he use one of the three or four existing python id3 libraries?"&lt;/span&gt;  The answer is this:  I planned on creating a blog crawler (mentioned later) and a website for this idea, and would do it all in python.  As a warm-up exercise, I figured it would be good to create a simple id3 reader.  I had already done it in Java, so it mainly became an act of seeing how the Java idioms I am currently used to translate over into python.  (Note: if you bother to download and read the code, please be gentle.  It's the first real python I've written.  Feedback is appreciated too.)&lt;br /&gt;&lt;br /&gt;The crawler is mostly done.  It came together more quickly than I thought, although it still has rough edges.  It runs a few times a day, notes new blog posts and gathers what information it finds into a database (postgres).&lt;br /&gt;&lt;br /&gt;The website is where the work needs to be done now.  I have gotten no further than creating a few simple query+display pages that I've been using to view results from the crawler.  I've experimented with different ways to present data (entry-centric vs mp3-centric) and still haven't come up with something I like.  I've got time though.  And the longer I wait, the more useful data I'll have from the crawler.&lt;br /&gt;&lt;br /&gt;I'm still using &lt;a href="http://www.pylonshq.com/"&gt;pylons&lt;/a&gt; for the website, although I had second thoughts after spending too much time fighting &lt;a href="http://www.makotemplates.org/"&gt;mako&lt;/a&gt; and the way it manhandled my nice unicode mp3 tags.&lt;br /&gt;&lt;br /&gt;I have yet to tackle the problem of dynamic RSS generation, but I have some good ideas in my head for that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7218232242203115351-2115082718108421099?l=www.onemanclapping.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.onemanclapping.org/feeds/2115082718108421099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7218232242203115351&amp;postID=2115082718108421099' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/2115082718108421099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7218232242203115351/posts/default/2115082718108421099'/><link rel='alternate' type='text/html' href='http://www.onemanclapping.org/2009/01/mp3-blog-aggregator-status-and-some.html' title='Mp3 Blog Aggregator: status and some code'/><author><name>Gary Dusbabek</name><uri>http://www.blogger.com/profile/02822527825865902304</uri><email>gdusbabek@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='01883798811660079782'/></author><thr:total>0</thr:total></entry></feed>