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

<channel>
	<title>Martin Ankerl &#187; tutorial</title>
	<atom:link href="http://martin.ankerl.com/category/tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>http://martin.ankerl.com</link>
	<description>No movement is faster than no movement</description>
	<lastBuildDate>Tue, 13 Jul 2010 05:31:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=abc</generator>
		<item>
		<title>How to Generate Random Colors Programmatically</title>
		<link>http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/</link>
		<comments>http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 19:09:17 +0000</pubDate>
		<dc:creator>Martin Ankerl</dc:creator>
				<category><![CDATA[coding]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://martin.ankerl.com/?p=254</guid>
		<description><![CDATA[Creating random colors is actually more difficult than it seems. The randomness itself is easy, but aesthetically pleasing randomness is more difficult. For a little project at work I needed to automatically generate multiple background colors with the following properties: Text over the colored background should be easily readable Colors should be very distinct The [...]]]></description>
			<content:encoded><![CDATA[<p>Creating random colors is actually more difficult than it seems. The randomness itself is easy, but aesthetically pleasing randomness is more difficult. For a little project at work I needed to automatically generate multiple background colors with the following properties:</p>
<ul>
<li>Text over the colored background should be easily readable</li>
<li>Colors should be very distinct</li>
<li>The number of required colors is not initially known</li>
</ul>
<h1>Naïve Approach</h1>
<p>The first and simplest approach is to create random colors by simply using a random number between <tt>[0, 256[</tt> for the R, G, B values. I have created a little Ruby script to generate sample HTML code:
<pre class="brush: ruby;"># generates HTML code for 26 background colors given R, G, B values.
def gen_html
  ('A'..'Z').each do |c|
    r, g, b = yield
    printf &quot;&lt;span style=\&quot;background-color:#%02x%02x%02x; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;\&quot;&gt;#{c}&lt;/span&gt; &quot;, r, g, b
  end
end

# naive approach: generate purely random colors
gen_html { [rand(256), rand(256), rand(256)] }</pre>
<p> The generated output looks like this:
<p style="text-align:center;"><span style="background-color:#a69dd8; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">A</span> <span style="background-color:#0c35b0; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">B</span> <span style="background-color:#f82750; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">C</span> <span style="background-color:#0ebd31; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">D</span> <span style="background-color:#5fab4f; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">E</span> <span style="background-color:#c538cf; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">F</span> <span style="background-color:#014a59; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">G</span> <span style="background-color:#e14af8; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">H</span> <span style="background-color:#9fb730; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">I</span> <span style="background-color:#4bec60; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">J</span> <span style="background-color:#ef9345; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">K</span> <span style="background-color:#d2ece0; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">L</span> <span style="background-color:#9cda80; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">M</span> <span style="background-color:#dbc07c; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">N</span> <span style="background-color:#7328dd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">O</span> <span style="background-color:#1e9942; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">P</span> <span style="background-color:#621b7b; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Q</span> <span style="background-color:#c830b2; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">R</span> <span style="background-color:#362332; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">S</span> <span style="background-color:#e8c55d; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">T</span> <span style="background-color:#bd8787; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">U</span> <span style="background-color:#66c6a4; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">V</span> <span style="background-color:#21ec4b; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">W</span> <span style="background-color:#782364; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">X</span> <span style="background-color:#c3bf15; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Y</span> <span style="background-color:#3db35a; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Z</span>
</p>
<p>As you can see this is quite suboptimal. Some letters are hard to read because the background is too dark (B, Q, S), other colors look very similar (F, R).</p>
<h1>Using HSV Color Space</h1>
<p><a href="http://en.wikipedia.org/wiki/File:HSV_cylinder.png"><img src="http://martin.ankerl.com/wp-content/uploads/2009/12/HSV_cylinder_small.png" alt="HSV_cylinder_small" title="HSV_cylinder_small" width="250" height="200" style="float:right;margin-left:10px; margin-bottom:10px;" /></a>Let's fix the too dark / too bright problem first. A convenient way to do this is to not use the RGB color space, but <a href="http://en.wikipedia.org/wiki/HSL_and_HSV">HSV</a> (Hue, Saturation, Value). Here you get equally bright and colorful colors by using a fixed value for saturation and value, and just modifying the hue.</p>
<p>Based on the description provided by the wikipedia article on <a href="http://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB">conversion from HSV to RGB</a> I have implemented a converter:
<pre class="brush: ruby;"># HSV values in [0..1[
# returns [r, g, b] values from 0 to 255
def hsv_to_rgb(h, s, v)
  h_i = (h*6).to_i
  f = h*6 - h_i
  p = v * (1 - s)
  q = v * (1 - f*s)
  t = v * (1 - (1 - f) * s)
  r, g, b = v, t, p if h_i==0
  r, g, b = q, v, p if h_i==1
  r, g, b = p, v, t if h_i==2
  r, g, b = p, q, v if h_i==3
  r, g, b = t, p, v if h_i==4
  r, g, b = v, p, q if h_i==5
  [(r*256).to_i, (g*256).to_i, (b*256).to_i]
end</pre>
<p>Using the generator and fixed values for saturation and value:
<pre class="brush: ruby;"># using HSV with variable hue
gen_html { hsv_to_rgb(rand, 0.5, 0.95) }</pre>
<p>returns something like this:<center><span style="background-color:#f379ad; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">A</span> <span style="background-color:#7979f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">B</span> <span style="background-color:#9079f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">C</span> <span style="background-color:#79e5f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">D</span> <span style="background-color:#8979f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">E</span> <span style="background-color:#79f396; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">F</span> <span style="background-color:#79cff3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">G</span> <span style="background-color:#79b1f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">H</span> <span style="background-color:#7979f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">I</span> <span style="background-color:#799ef3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">J</span> <span style="background-color:#ecf379; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">K</span> <span style="background-color:#80f379; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">L</span> <span style="background-color:#797cf3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">M</span> <span style="background-color:#79f3f0; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">N</span> <span style="background-color:#9af379; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">O</span> <span style="background-color:#79f37a; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">P</span> <span style="background-color:#f3ad79; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Q</span> <span style="background-color:#f3e179; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">R</span> <span style="background-color:#79b9f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">S</span> <span style="background-color:#e8f379; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">T</span> <span style="background-color:#f3b379; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">U</span> <span style="background-color:#f379c9; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">V</span> <span style="background-color:#79b8f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">W</span> <span style="background-color:#f379dc; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">X</span> <span style="background-color:#79f37b; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Y</span> <span style="background-color:#8e79f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Z</span><br />
</center><br />
Much better. The text is easily readable, and all colors have a similar brightness. Unfortunately, since we have limited us to less colors now, the difference between the randomly generated colors is even less than in the first approach.</p>
<h1>Golden Ratio</h1>
<p>Using just <tt>rand()</tt> to choose different values for hue does not lead to a good use of the whole color spectrum, it simply is too random.<center><img src="http://martin.ankerl.com/wp-content/uploads/2009/12/distribution-random.png" alt="distribution-random" title="distribution-random" width="483" height="291" class="alignright size-full wp-image-273" /></center></p>
<p>Here I have generated 2, 4, 8, 16, and 32 random values and printed them all on a scale. Its easy to see that some values are very tightly packed together, which we do not want.</p>
<p>Lo and behold, some mathematician has discovered the <a href="http://en.wikipedia.org/wiki/Golden_ratio">Golden Ratio</a> more than 2400 years ago. It has lots of interesting properties, but for us only one is interesting:</p>
<blockquote><p>[...] Furthermore, it is a property of the golden ratio, <em>&Phi;</em>, that each subsequent hash value divides the interval into which it falls according to the golden ratio!<br />
-- <a href="http://brpreiss.com/books/opus4/html/page214.html">Bruno R. Preiss, P.Eng.</a></p></blockquote>
<p>Using the golden ratio as the spacing, the generated values look like this:<br />
<center><img src="http://martin.ankerl.com/wp-content/uploads/2009/12/distribution-goldenratio.png" alt="distribution-goldenratio" title="distribution-goldenratio" width="483" height="291" class="alignright size-full wp-image-274" /></center></p>
<p>Much better! The values are very evenly distributed, regardless how many values are used. Also, the algorithm for this is extremly simple. Just add 1/&Phi; and modulo 1 for each subsequent color.</p>
<pre class="brush: ruby;"># use golden ratio
golden_ratio_conjugate = 0.618033988749895
h = rand # use random start value
gen_html {
  h += golden_ratio_conjugate
  h %= 1
  hsv_to_rgb(h, 0.5, 0.95)
}</pre>
<p>The final result:<br />
<center><span style="background-color:#f37e79; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">A</span> <span style="background-color:#7998f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">B</span> <span style="background-color:#bbf379; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">C</span> <span style="background-color:#f379df; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">D</span> <span style="background-color:#79f3e3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">E</span> <span style="background-color:#f3bf79; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">F</span> <span style="background-color:#9c79f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">G</span> <span style="background-color:#7af379; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">H</span> <span style="background-color:#f3799d; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">I</span> <span style="background-color:#79c1f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">J</span> <span style="background-color:#e4f379; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">K</span> <span style="background-color:#de79f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">L</span> <span style="background-color:#79f3ba; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">M</span> <span style="background-color:#f39779; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">N</span> <span style="background-color:#797ff3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">O</span> <span style="background-color:#a2f379; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">P</span> <span style="background-color:#f379c6; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Q</span> <span style="background-color:#79e9f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">R</span> <span style="background-color:#f3d979; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">S</span> <span style="background-color:#b579f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">T</span> <span style="background-color:#79f392; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">U</span> <span style="background-color:#f37984; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">V</span> <span style="background-color:#79a8f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">W</span> <span style="background-color:#cbf379; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">X</span> <span style="background-color:#f379ee; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Y</span> <span style="background-color:#79f3d3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Z</span></center></p>
<p>You can see that the first few values are very different, and the difference decreases as more colors are added (Z and E are already quite similar). Anyways, this is good enough for me.</p>
<p>And because it is so beautiful, here are some more colors <img src='http://martin.ankerl.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /><br />
<tt>s=0.99, v=0.99</tt>, <tt>s=0.25, h=0.8</tt>, and <tt>s=0.3, v=0.99</tt> <center><span style="background-color:#024bfd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">A</span> <span style="background-color:#94fd02; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">B</span> <span style="background-color:#fd02de; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">C</span> <span style="background-color:#02fdd3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">D</span> <span style="background-color:#fd8a02; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">E</span> <span style="background-color:#4102fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">F</span> <span style="background-color:#0dfd02; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">G</span> <span style="background-color:#fd0256; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">H</span> <span style="background-color:#029ffd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">I</span> <span style="background-color:#e8fd02; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">J</span> <span style="background-color:#c802fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">K</span> <span style="background-color:#02fd7f; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">L</span> <span style="background-color:#fd3602; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">M</span> <span style="background-color:#0217fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">N</span> <span style="background-color:#61fd02; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">O</span> <span style="background-color:#fd02aa; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">P</span> <span style="background-color:#02f3fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Q</span> <span style="background-color:#fdbe02; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">R</span> <span style="background-color:#7402fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">S</span> <span style="background-color:#02fd2b; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">T</span> <span style="background-color:#fd0222; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">U</span> <span style="background-color:#026bfd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">V</span> <span style="background-color:#b5fd02; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">W</span> <span style="background-color:#fc02fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">X</span> <span style="background-color:#02fdb3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Y</span> <span style="background-color:#fd6a02; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Z</span><br />
</center></p>
<p><center><span style="background-color:#99a8cc; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">A</span> <span style="background-color:#b7cc99; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">B</span> <span style="background-color:#cc99c6; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">C</span> <span style="background-color:#99ccc4; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">D</span> <span style="background-color:#ccb599; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">E</span> <span style="background-color:#a699cc; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">F</span> <span style="background-color:#9bcc99; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">G</span> <span style="background-color:#cc99aa; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">H</span> <span style="background-color:#99b9cc; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">I</span> <span style="background-color:#c8cc99; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">J</span> <span style="background-color:#c299cc; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">K</span> <span style="background-color:#99ccb3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">L</span> <span style="background-color:#cca499; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">M</span> <span style="background-color:#999dcc; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">N</span> <span style="background-color:#accc99; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">O</span> <span style="background-color:#cc99bb; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">P</span> <span style="background-color:#99cacc; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Q</span> <span style="background-color:#ccbf99; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">R</span> <span style="background-color:#b099cc; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">S</span> <span style="background-color:#99cca2; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">T</span> <span style="background-color:#cc99a0; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">U</span> <span style="background-color:#99afcc; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">V</span> <span style="background-color:#becc99; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">W</span> <span style="background-color:#cc99cc; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">X</span> <span style="background-color:#99ccbd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Y</span> <span style="background-color:#ccae99; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Z</span></center></p>
<p><center><span style="background-color:#b1c7fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">A</span> <span style="background-color:#ddfdb1; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">B</span> <span style="background-color:#fdb1f3; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">C</span> <span style="background-color:#b1fdf0; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">D</span> <span style="background-color:#fddab1; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">E</span> <span style="background-color:#c4b1fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">F</span> <span style="background-color:#b4fdb1; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">G</span> <span style="background-color:#fdb1ca; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">H</span> <span style="background-color:#b1e1fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">I</span> <span style="background-color:#f7fdb1; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">J</span> <span style="background-color:#edb1fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">K</span> <span style="background-color:#b1fdd7; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">L</span> <span style="background-color:#fdc1b1; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">M</span> <span style="background-color:#b1b7fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">N</span> <span style="background-color:#cefdb1; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">O</span> <span style="background-color:#fdb1e4; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">P</span> <span style="background-color:#b1fafd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Q</span> <span style="background-color:#fdeab1; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">R</span> <span style="background-color:#d4b1fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">S</span> <span style="background-color:#b1fdbd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">T</span> <span style="background-color:#fdb1bb; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">U</span> <span style="background-color:#b1d1fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">V</span> <span style="background-color:#e7fdb1; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">W</span> <span style="background-color:#fdb1fd; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">X</span> <span style="background-color:#b1fde7; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Y</span> <span style="background-color:#fdd0b1; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;">Z</span></center></p>
<p>Have fun!<br />
Martin</p>
<div style='clear:both'></div><img src="http://martin.ankerl.com/?ak_action=api_record_view&id=254&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>How To: Download Any Flash Video with flashrip in Ubuntu</title>
		<link>http://martin.ankerl.com/2009/11/15/how-to-download-any-flash-video-with-flashrip-in-ubuntu/</link>
		<comments>http://martin.ankerl.com/2009/11/15/how-to-download-any-flash-video-with-flashrip-in-ubuntu/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 11:57:37 +0000</pubDate>
		<dc:creator>Martin Ankerl</dc:creator>
				<category><![CDATA[downloads]]></category>
		<category><![CDATA[freeware]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[tricks]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[videos]]></category>

		<guid isPermaLink="false">http://martin.ankerl.com/?p=218</guid>
		<description><![CDATA[Downloading flash videos in Linux was already not too difficult, but thanks to flashrip, it has gotten very easy. Here is a little demo how it works: Once installed, you basically use one click to get a video preview and then a prompt with the filename to save the file. The script works by looking [...]]]></description>
			<content:encoded><![CDATA[<p>Downloading flash videos in Linux was already <a href="http://www.youtube.com/watch?v=vxBGr2T1Ueo">not too difficult</a>, but thanks to <tt>flashrip</tt>, it has gotten very easy. Here is a little demo how it works:<br />
<center><br />
<object width="560" height="370"><param name="movie" value="http://www.youtube.com/v/qvxHQKGci9o&#038;hl=en_US&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/qvxHQKGci9o&#038;hl=en_US&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="370"></embed></object><br />
</center></p>
<p>
Once installed, you basically use one click to get a video preview and then a prompt with the filename to save the file. The script works by looking into the newest flash files in your <tt>/tmp</tt> folder, and creates a hardlink to the save destination. When the video has fully loaded, you can close the browser window. The temp file will get deleted, and the linked copy will remain.</p>
<h2>Installing flashrip</h2>
<p>Open a terminal like gnome-terminal or konsole, and run these commands:</p>
<pre>wget http://martin.ankerl.com/wp-content/uploads/2009/11/flashrip.sh
chmod 755 flashrip.sh
sudo mv flashrip.sh /usr/local/bin</pre>
<p>Now all thats left to do is to create a link in your gnome panel for ease of use: Right click the gnome panel, &#8220;Add to panel&#8230;&#8221;, choose &#8220;Custom Application Launcher&#8230;&#8221;. Choose a proper name, and a command like this:
<pre>/usr/local/bin/flashrip.sh /home/manker/Videos</pre>
<p>For the command, replace the second parameter with the default location where you want to save the ripped videos (you have to use the full path here!)</p>
<p>I have tested this in Ubuntu, but it should work on any linux where gnome is installed. </p>
<p>Have fun!</p>
<div style='clear:both'></div><img src="http://martin.ankerl.com/?ak_action=api_record_view&id=218&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://martin.ankerl.com/2009/11/15/how-to-download-any-flash-video-with-flashrip-in-ubuntu/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Beautiful Font Hinting in Ubuntu 8.10 and 9.04</title>
		<link>http://martin.ankerl.com/2009/01/22/beautiful-font-hinting-in-ubuntu-810/</link>
		<comments>http://martin.ankerl.com/2009/01/22/beautiful-font-hinting-in-ubuntu-810/#comments</comments>
		<pubDate>Thu, 22 Jan 2009 20:59:03 +0000</pubDate>
		<dc:creator>Martin Ankerl</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[news]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tricks]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://martin.ankerl.com/?p=197</guid>
		<description><![CDATA[Even though I have an LCD monitor, I always have the subpixel hinting switched off because it is just painfully ugly to my eyes. Even when hinting is switched to maximum, the fonts are quite blurry (if you don&#8217;t believe me, type xmag and take a screenshot of your font. You can see red and [...]]]></description>
			<content:encoded><![CDATA[<p>Even though I have an LCD monitor, I always have the subpixel hinting switched off because it is just painfully ugly to my eyes. Even when hinting is switched to maximum, the fonts are quite blurry (if you don&#8217;t believe me, type <tt>xmag</tt> and take a screenshot of your font. You can see red and blue linese everywhere). My eyes hurt when I see this. </p>
<p>Thanks to <a href="http://johan.kiviniemi.name/blag/ubuntu-fonts/">Johan Kivinemi</a> I have just found out how to bring back the excellent legacy subpixel hinting engine. This has a much more crisp hinting, and uses subpixels only where it really is an improvement:</p>
<p>Just open these files in your home directory, and copy the content into them:</p>
<h2>~/.fonts.conf</h2>
<pre class="brush: xml;">
&lt;?xml version='1.0'?&gt;
&lt;!DOCTYPE fontconfig SYSTEM 'fonts.dtd'&gt;
&lt;fontconfig&gt;
  &lt;match target=&quot;font&quot;&gt;
    &lt;edit name=&quot;antialias&quot; mode=&quot;assign&quot;&gt;
      &lt;bool&gt;true&lt;/bool&gt;
    &lt;/edit&gt;
    &lt;edit name=&quot;hinting&quot; mode=&quot;assign&quot;&gt;
      &lt;bool&gt;true&lt;/bool&gt;
    &lt;/edit&gt;
    &lt;edit name=&quot;hintstyle&quot; mode=&quot;assign&quot;&gt;
      &lt;const&gt;hintfull&lt;/const&gt;
    &lt;/edit&gt;
    &lt;edit name=&quot;lcdfilter&quot; mode=&quot;assign&quot;&gt;
      &lt;const&gt;lcdlegacy&lt;/const&gt;
    &lt;/edit&gt;
    &lt;edit name=&quot;rgba&quot; mode=&quot;assign&quot;&gt;
      &lt;const&gt;rgb&lt;/const&gt;
    &lt;/edit&gt;
  &lt;/match&gt;
&lt;/fontconfig&gt;
</pre>
<h2>~/.Xresources</h2>
<pre class="brush: xml;">
Xft.antialias:  true
Xft.hinting:    true
Xft.hintstyle:  hintfull
Xft.lcdfilter:  lcdlegacy
Xft.rgba:       rgb
</pre>
<p>This should work in Ubuntu 8.04, 8.10, and 9.04 too, and makes all fonts much more crisp. Of course, your mileage may vary.</p>
<h1>UPDATE: Comparison Screenshots</h1>
<p>As promised on <a href="http://www.reddit.com/r/linux/comments/7ru91/beautiful_font_hinting_in_ubuntu_810/">reddit</a>, I got back from an awesome snowboard trip so I am able to put up extensive comparison screenshots of the two subpixel hinting engines. Move your mouse over the following images to see the differences. Watch especially out for letters like &#8220;m&#8221; where the spacing between the lines is very small. You might have to wait a bit for the image to load.</p>
<p>I have used all of the most important fonts that I usually use, and just for fun I have added &#8220;Dijkstra&#8221;, which just looks cool.</p>
<h2>Sans Fonts</h2>
<p>Mouse to see the same fonts with the legacy hinter.</p>
<style type="text/css"><!-- #sans a { text-decoration:none; display:block; background-image:url(http://martin.ankerl.com/wp-content/uploads/2009/01/sans-normal.png); width:395px; height:850px; } #sans a:hover {background-image:url(http://martin.ankerl.com/wp-content/uploads/2009/01/sans-legacy.png); } --> </style>
<div id="sans">
<a href="#">&nbsp;</a>
</div>
<h2>Mono Fonts</h2>
<p>Mouse to see the same fonts with the legacy hinter.</p>
<style type="text/css"><!-- #mono a { text-decoration:none; display:block; background-image:url(http://martin.ankerl.com/wp-content/uploads/2009/01/mono-normal.png); width:430px; height:940px; } #mono a:hover {background-image:url(http://martin.ankerl.com/wp-content/uploads/2009/01/mono-legacy.png); } --> </style>
<div id="mono">
<a href="#">&nbsp;</a>
</div>
<h2>Zoomed Comparison Screenhots</h2>
<p>Here is an excerpt with 400% magnifications. Mouse over the pictures to see the legacy hinter.</p>
<h3>Zoomed Sans</h3>
<style type="text/css"><!-- #sanszoom a { text-decoration:none; display:block; background-image:url(http://martin.ankerl.com/wp-content/uploads/2009/01/sans-normal-zoomed.png); width:400px; height:200px; } #sanszoom a:hover {background-image:url(http://martin.ankerl.com/wp-content/uploads/2009/01/sans-legacy-zoomed.png); } --> </style>
<div id="sanszoom">
<a href="#">&nbsp;</a>
</div>
<h3>Zoomed Mono</h3>
<style type="text/css"><!-- #monozoom a { text-decoration:none; display:block; background-image:url(http://martin.ankerl.com/wp-content/uploads/2009/01/mono-normal-zoomed.png); width:400px; height:200px; } #monozoom a:hover {background-image:url(http://martin.ankerl.com/wp-content/uploads/2009/01/mono-legacy-zoomed.png); } --> </style>
<div id="monozoom">
<a href="#">&nbsp;</a>
</div>
<div style='clear:both'></div><img src="http://martin.ankerl.com/?ak_action=api_record_view&id=197&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://martin.ankerl.com/2009/01/22/beautiful-font-hinting-in-ubuntu-810/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Top 10 Posts of 2008</title>
		<link>http://martin.ankerl.com/2008/12/27/top-10-posts-of-2008/</link>
		<comments>http://martin.ankerl.com/2008/12/27/top-10-posts-of-2008/#comments</comments>
		<pubDate>Sat, 27 Dec 2008 18:08:44 +0000</pubDate>
		<dc:creator>Martin Ankerl</dc:creator>
				<category><![CDATA[news]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://martin.ankerl.com/?p=186</guid>
		<description><![CDATA[Everybody loves top 10 lists. It is amazing how much traffic they can generate with the least bit of effort. So, without further ado, here is the list of the top 10 articles on this blog for 2008. 10. Top 10 Eclipse Hotkeys Ironically, this list starts with another top 10 list, namely Top 10 [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody loves top 10 lists. It is amazing how much traffic they can generate with the least bit of effort. So, without further ado, here is the list of the top 10 articles on this blog for 2008.</p>
<dl>
<dt>10. Top 10 Eclipse Hotkeys</dt>
<dd><center><img src="http://martin.ankerl.com/wp-content/uploads/2008/12/hotkeys.png" alt="" title="hotkeys" width="456" height="91" style="margin:10px;"/></center><br />
Ironically, this list starts with another top 10 list, namely <a href="http://martin.ankerl.com/2006/07/20/top-10-eclipse-hotkeys/">Top 10 Eclipse Hotkeys</a>. This article from 2006 has just made it onto this top list. With 3,302 pageviews it seems that these keys are still relevant.
</dd>
<dt>9. Human Compact Themes for Ubuntu 8.10</dt>
<dd><center><img src="http://martin.ankerl.com/wp-content/uploads/2008/12/compact810.png" alt="" title="compact810" width="270" height="110" style="margin:10px;"/></center> Number 9 is a modification of the <a href="http://martin.ankerl.com/2008/11/04/human-compact-themes-for-ubuntu-810/">Ubuntu&#8217;s default theme that is optimized for small screens</a>. With the recent rise of netbooks this becomes more and more wanted.<br />
<center></center>
</dd>
<dt>8. Logical Volume Manager Cheatsheet</dt>
<dd>
<pre style="margin:10px 50px 10px 50px; padding:0px;">sudo pvcreate /dev/sdg1
sudo vgcreate ext_vg /dev/sdg1
sudo lvcreate -L 450G -n ext ext_vg
sudo mkfs.ext3 -m 0 /dev/ext_vg/ext</pre>
<p></center>A compact little cheat sheet that explains <a href="http://martin.ankerl.com/2008/02/05/logical-volume-manager-cheatsheet/">how to easily combine two harddisks into one large volume</a>. I have used this to combine two 500GB disks into one large 1TB filesystem.
</dd>
<dt>7. Comprehensive Linux Terminal Performance Comparison</dt>
<dd><center><img src="http://martin.ankerl.com/wp-content/uploads/2008/12/term-small.png" alt="" title="term-small" width="400" height="117" style="margin:10px;" /></center> In this highly controversial article I have compared <a href="http://martin.ankerl.com/2007/09/01/comprehensive-linux-terminal-performance-comparison/">how long several different terminals (xterm, gnome-terminal, etc.) take when displaying one large textfile</a>. I still believe this is relevant, especially when compiling stuff and text flies by. You don&#8217;t want your terminal be the limiting factor for your compile speed! I would perform the test yourself, as this seems to be highly dependent on the graphics card driver.
</dd>
<dt>6. Howto Create MANIFEST.MF Classpath from Ant</dt>
<dd>
<pre class="brush: xml;">
&lt;!-- name of the output .jar file --&gt;
&lt;property name=&quot;jar.name&quot; value=&quot;ourjarfile.jar&quot; /&gt;
</pre>
<p>This HOWTO describes <a href="http://martin.ankerl.com/2005/11/30/howto-create-manifestmf-classpath-from-ant/">a simple way to create the classpath in a MANIFEST.MF file automatically</a> from the libraries available on the harddisk. I have been using this since 2005, and it has never failed me.
</dd>
<dt>5. Human Compact Gnome Theme (for Ubuntu 8.04)</dt>
<dd><center><img src="http://martin.ankerl.com/wp-content/uploads/2008/12/s1.png" alt="" title="s1" width="414" height="119" style="margin:10px;" /></center><a href="http://martin.ankerl.com/2008/05/13/human-compact-gnome-theme/">Another Compact theme</a> has made it on the list, this time for 8.04. I have used this theme for quite a while, even on a large 1680&#215;1050 monitor because it really saves a lot of screen space. For everybody still using Ubuntu 8.04, this is the best choice to use a compact layout while still having the default Human look.
</dd>
<dt>4. Optimized pow() approximation for Java, C / C++, and C#</dt>
<dd>
<pre class="brush: java;">
public static double pow(final double a, final double b) {
    final int x = (int) (Double.doubleToLongBits(a) &gt;&gt; 32);
    final int y = (int) (b * (x - 1072632447) + 1072632447);
    return Double.longBitsToDouble(((long) y) &lt;&lt; 32);
}
</pre>
<p>Through some funny floating point representation tricks it is possible to create <a href="http://martin.ankerl.com/2007/10/04/optimized-pow-approximation-for-java-and-c-c/">an approximative calculation of the pow() operator</a>, that is a hell of a lot faster than the standard calculation which has to be extremely precise. This might be useful for games, Artificial Intelligence applications, and everywhere else where performance is an issue and not precision.
</dd>
<dt>3. Ajax Dojo Comet Tutorial</dt>
<dd><center><img src="http://martin.ankerl.com/wp-content/uploads/2008/12/hello.png" alt="" title="hello" width="325" height="85" style="margin:10px;" /></center> One of the most often seen article contains 3 buzzwords at once: <a href="http://martin.ankerl.com/2007/08/21/ajax-dojo-comet-tutorial/">Ajax, Dojo, Comet</a>. This page was linked several times, and it is getting quite a bit of attention. The article was written by an intern at my workplace and he allowed me to put it up here.
</dd>
<dt>2. Clearlooks Compact Gnome Theme</dt>
<dd><center><img src="http://martin.ankerl.com/wp-content/uploads/2008/12/clearlooks-compact.png" alt="" title="clearlooks-compact" width="435" height="121" style="margin:10px;" /></center> Yet another theme! This startet it all. The <a href="http://martin.ankerl.com/2007/11/04/clearlooks-compact-gnome-theme/">Clearlooks Compact Theme</a> was the first compact theme I have created. It is just a modification of the original Clearlooks theme, with tighter spacing. This has been linked quite a lot of time and I get a continuous stream of visitors who are in the need for a compact theme.
</dd>
<dt>1. How to get Enough Sleep Despite StumbleUpon With Ubuntu</dt>
<dd><center><img src="http://martin.ankerl.com/wp-content/uploads/2008/01/stumbling-insomnia.jpg" width="450" height="314" style="margin:10px;"></center> This post about me struggling with <a href="http://martin.ankerl.com/2008/01/24/howto-get-enough-sleep-despite-stumbleupon-with-ubuntu/">getting enough sleep despite StumbleUpon</a> was by far the most viewed article on the blog, it has received more than 4 times as much visits as the second best. I guess I hit some nerve with it in the large Linux using StumbleUpon crowd. The article is almost a year old, and I still get lots of visitors each and every day. Happy stumbling!
</dd>
</dl>
<p>Thank you everybody for coming to this site and posting your thoughts. I appreciate each and every feedback. Happy christmas and happy new year!</p>
<div style='clear:both'></div><img src="http://martin.ankerl.com/?ak_action=api_record_view&id=186&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://martin.ankerl.com/2008/12/27/top-10-posts-of-2008/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ripping Multilanguage DVDs with Subtitles using Mencoder</title>
		<link>http://martin.ankerl.com/2008/12/25/ripping-multilanguage-dvds-with-subtitles-using-only-mencoder/</link>
		<comments>http://martin.ankerl.com/2008/12/25/ripping-multilanguage-dvds-with-subtitles-using-only-mencoder/#comments</comments>
		<pubDate>Thu, 25 Dec 2008 22:06:11 +0000</pubDate>
		<dc:creator>Martin Ankerl</dc:creator>
				<category><![CDATA[howto]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[tricks]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[videos]]></category>

		<guid isPermaLink="false">http://martin.ankerl.com/?p=185</guid>
		<description><![CDATA[Yesterday at Christmas I got the Akira Kurosawa Samurai Edition, which is a 7 disc DVD set of his awesome movies. I am converting it into the best quality files currently possible: MKV as the container, x264 codec for the video, dual audio, and with subtitles. This is short Howto so that I won&#8217;t forget [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday at Christmas I got the <a href="http://en.wikipedia.org/wiki/Akira_Kurosawa">Akira Kurosawa</a> Samurai Edition, which is a 7 disc DVD set of his awesome movies. I am converting it into the best quality files currently possible: MKV as the container, x264 codec for the video, dual audio, and with subtitles. This is short Howto so that I won&#8217;t forget how <img src='http://martin.ankerl.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
<span id="more-185"></span></p>
<ol>
<li>Create a file <tt>~/.mplayer/mencoder.conf</tt> with default compression settings. I use this, with encoding quality settings I have from <a href="http://www.mplayerhq.hu/DOCS/HTML/en/menc-feat-x264.html#menc-feat-x264-example-settings">mplayer&#8217;s x264 examples</a>:
<pre class="brush: ruby;">
o=out.avi
ovc=x264=yes
oac=mp3lame=yes

#lameopts=preset=medium
lameopts=aq=2:vbr=4
#lameopts=preset=voice

# the lower crf, the better
# 20: very good
# 22: Medium Quality DVD rips
# 23: quite ok
# 25: so-so
# 30: acceptable
# 40: my eyes hurt
# 50: my eyes bleed
x264encopts=threads=auto:crf=20:subq=7:partitions=all:8x8dct:me=umh:frameref=5:bframes=3:b_pyramid:weight_b

# deinterlace
# vf=yadif

# slight denoise
# vf=hqdn3d=3:2:3:3

# turbo encoding (low quality!)
#x264encopts=threads=auto:crf=23:turbo=2:subq=1:frameref=1
</pre>
<li>I use constant quality setting. The advantage is that it requires only one pass, and you get, well, constant quality <img src='http://martin.ankerl.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  In the config file find the <tt>crf=20</tt> section and change it to your desire.
<li>Find out which DVD chapter you want to rip, starting with 1 up (e.g. <tt>mplayer dvd://1</tt>).
<li>If the DVD has black borders, find out their sizes with
<pre>mplayer dvd://2 -vf cropdetect</pre>
<p>Fast forward a bit into the movie so that the ratio can be trusted.<br />
<strong>WARNING</strong> Some DVDs like Natural Born Killers are shot with multiple different films, so the border changes! Take care not to crop anything important away. Copy the -crop printouts into the clipboard.</p>
<li>Open another console window, run <tt>mplayer dvd://2 -identify</tt>, and quit. Now scroll up, there is some important information about the tracks which you need in the next step. I have extraced the important information here:
<pre class="brush: ruby;">
ID_AUDIO_ID=128
ID_AID_128_LANG=de
...
ID_AUDIO_ID=129
ID_AID_129_LANG=ja
...
subtitle ( sid ): 0 language: de
...
subtitle ( sid ): 1 language: de
</pre>
<p>So there is audio language <tt>de</tt> and <tt>ja</tt>, and 2 subtitles for de. Mplayer the DVD and press <tt>J</tt> to find out which subtitles you want to have. (mplayer shows the ID, like <tt>(0) de</tt>).</p>
<li>I have chosen AID 129 and sid 1. In the other window, start ripping the movie:
<pre class="brush: ruby;">
mencoder dvd://2 -vf crop=704:432:0:72 -aid 129 -o Yojimbo.avi -vobsubout subs -vobsuboutindex 0 -sid 1</pre>
<p>This will get you 3 files: <tt>Yojimbo.avi</tt> with Japanese audio and x264 encoded movie video, and <tt>subs.idx</tt> and <tt>subs.sub</tt> with the subtitles. Play the movie to check everything works as it should.</p>
<li>Rip additional sound tracks now, if you want them. You can rip one additional subtitle at the same time. To do this, increase the vobsuboutindex by one, or choose another filename. I choose to rip the german audio and another subtitle track:
<pre class="brush: ruby;">
mencoder dvd://2 -aid 128 -ovc frameno -o de.avi -vobsubout out -vobsuboutindex 0 -sid 1
</pre>
<p>The <tt>-ovc frameno</tt> part is important, because this skips video encoding. Encoding is much faster this way because we already have the video anyways.</p>
<li>Merge everything together with <tt>mmg</tt>, this is a GUI interface for <tt>mkvmerge</tt> which you get via <tt>sudo apt-get install mkvtoolnix</tt>. Select the correct languages for the audio and subtitle tracks.
</ol>
<p>I think that&#8217;s about it. This way you will get very high quality, multi language rips with subtitles. Oh, some other interesting points to note:</p>
<ul>
<li>I <em>always</em> encode with the same resolution as the source, no rescaling. Rescaling is very bad, I much prefer that quality is reduced by the codec and not preemptively through scaling down. Even a HDTV ripped to 700MB gets you a much better quality when not rescaled than a DVD ripped to 700MB. The x264 does an awesome job at preserving quality where it is important.
<li>I only rip with variable bitrate VBR. It has very good quality, but it is not surround sound.
</ul>
<div style='clear:both'></div><img src="http://martin.ankerl.com/?ak_action=api_record_view&id=185&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://martin.ankerl.com/2008/12/25/ripping-multilanguage-dvds-with-subtitles-using-only-mencoder/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Amazing Caching Proxy in Java</title>
		<link>http://martin.ankerl.com/2008/12/22/amazing-caching-proxy-in-java/</link>
		<comments>http://martin.ankerl.com/2008/12/22/amazing-caching-proxy-in-java/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 21:53:59 +0000</pubDate>
		<dc:creator>Martin Ankerl</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tricks]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://martin.ankerl.com/?p=184</guid>
		<description><![CDATA[Use Case Imagine you have some Java code that does lots and lots of computation. All the time intensive calculations is performed by the class SlowCalculator which implements the interface Calculator: public static interface Calculator { public String calculate(int a, String b); } public static void main(String[] args) { Calculator c = new SlowCalculator(); // [...]]]></description>
			<content:encoded><![CDATA[<h2>Use Case</h2>
<p>Imagine you have some Java code that does lots and lots of computation. All the time intensive calculations is performed by the class <tt>SlowCalculator</tt> which implements the interface <tt>Calculator</tt>:</p>
<pre class="brush: java;">
public static interface Calculator {
    public String calculate(int a, String b);
}

public static void main(String[] args) {
    Calculator c = new SlowCalculator();
    // call c.calculate() a lot of times here...
}
</pre>
<p>You notice that <tt>calculate()</tt> is often called with the same parameters which lead to the exact same result (<tt>SlowCalculator</tt> is stateless). This means it is possible to cache values so there&#8217;s no need to recompute. Using the generic CachingProxy&trade; described below, you can create a cached proxy for any class with just one single line of code:</p>
<pre class="brush: java;">
// ...

public static void main(String[] args) {
    Calculator c = new SlowCalculator();
    c = CachedProxy.create(Calculator.class, c);
    // call c.calculate() a lot of times here...
}
</pre>
<p>That&#8217;s it, and the application is blazingly fast again.</p>
<p><strong>UPDATE</strong>: Support for <tt>null</tt> values, transparently handles exceptions, better hash, nullpointer-bugfix.</p>
<p><strong>UPDATE</strong>: Here is an article &#8220;<a href="http://www.onjava.com/pub/a/onjava/2003/08/20/memoization.html">Memoization in Java Using Dynamic Proxy Classes</a>&#8221; that does (almost) exactly the same as this code.</p>
<p><span id="more-184"></span></p>
<h2>How To Do This</h2>
<p>All this sounds nice, but can you do this in java? Turns out you can and it is not that difficult either. The feature that makes it all possible is <a href="http://java.sun.com/j2se/1.4.2/docs/guide/reflection/proxy.html">Dynamic Proxy</a>. With it you can implement interfaces <em>at runtime</em>. You take an interface, create a proxy for it with <tt><a href="http://java.sun.com/javase/6/docs/api/java/lang/reflect/Proxy.html">Proxy</a>.newProxyInstance(...)</tt>, supply an <a href="http://java.sun.com/javase/6/docs/api/java/lang/reflect/InvocationHandler.html">InvocationHandler</a> that implements the <tt><a href="http://java.sun.com/javase/6/docs/api/java/lang/reflect/InvocationHandler.html#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])">invoke()</a></tt> method, and you are done.</p>
<p>The code for the <tt>CachedProxy.create()</tt> method is this:</p>
<pre class="brush: java;">
    /**
     * Creates an intermediate proxy object that uses cached results if
     * available, otherwise calls the given code.
     *
     * @param &lt;T&gt;
     *            Type of the class.
     * @param cl
     *            The interface for which the proxy should be created.
     * @param code
     *            The actual calculation code that should be cached.
     * @return The proxy.
     */
    @SuppressWarnings(&quot;unchecked&quot;)
    public static &lt;T&gt; T create(final Class&lt;T&gt; cl, final T code) {
        // create the cache
        final Map&lt;Args, Object&gt; argsToOutput = new HashMap&lt;Args, Object&gt;();

        // proxy for the interface T
        return (T) Proxy.newProxyInstance(cl.getClassLoader(), new Class&lt;?&gt;[] { cl }, new InvocationHandler() {

            @Override
            public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
                final Args input = new Args(method, args);
                Object result = argsToOutput.get(input);
                // check containsKey to support null values
                if (result == null &amp;&amp; !argsToOutput.containsKey(input)) {
                    // make sure exceptions are handled transparently
                    try {
                        result = method.invoke(code, args);
                        argsToOutput.put(input, result);
                    } catch (InvocationTargetException e) {
                        throw e.getTargetException();
                    }
                }
                return result;
            }
        });
    }
</pre>
<ol>
<li>First I create a <tt>HashMap</tt> that is the cache for the return values. I have written a class <tt>Args</tt> (omitted here) that is as the key to map from the method and the parameters to the cached output.
<li>A Proxy is created for the interface <tt>cl</tt>, with an InvocationHandler that does all the magic.
<li>The magic is actually very simple: If there is no cached result already available (line 25), perform the computation (line 26) and store the result in the map, then return the result.
</ol>
<h2>Download</h2>
<p>You can get the full code at my github repository:</p>
<ul>
<li>
<a href="http://github.com/martinus/java-playground/tree/master/src/java/com/ankerl/proxy/CachedProxy.java">CachedProxy</a>
</li>
</ul>
<h2>Benchmarks</h2>
<p>In my benchmark I can run about 8 million calls per secons via the cached proxy. That&#8217;s not too bad, given all the additional overhead with reflection and the HashMap.</p>
<p>Do you know of any way to improve this? Any ideas or suggestions are welcome!</p>
<div style='clear:both'></div><img src="http://martin.ankerl.com/?ak_action=api_record_view&id=184&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://martin.ankerl.com/2008/12/22/amazing-caching-proxy-in-java/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>How to Make a Compact Gnome Theme</title>
		<link>http://martin.ankerl.com/2008/10/10/how-to-make-a-compact-gnome-theme/</link>
		<comments>http://martin.ankerl.com/2008/10/10/how-to-make-a-compact-gnome-theme/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 22:18:31 +0000</pubDate>
		<dc:creator>Martin Ankerl</dc:creator>
				<category><![CDATA[howto]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://martin.ankerl.com/?p=179</guid>
		<description><![CDATA[The themes Human Compact and Clearlooks Compact have been quite a success, and I got several requests to make a tutorial on how to create such a compact theme. UPDATE: Human Compact Theme for Ubuntu 8.10 (Intrepid Ibex) is available! Well, it is a bit difficult to create a step-by-step tutorial, but I will try [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://brainstorm.ubuntu.com/idea/6772/"><img style="float:right; margin-left:20px; margin-bottom:20px" src="http://brainstorm.ubuntu.com/idea/6772/image/1/" /></a>The themes <a href="http://martin.ankerl.com/2008/05/13/human-compact-gnome-theme/">Human Compact</a> and <a href="http://martin.ankerl.com/2007/11/04/clearlooks-compact-gnome-theme/">Clearlooks Compact</a> have been quite a success, and I got several requests to make a tutorial on how to create such a compact theme.</p>
<p><strong>UPDATE</strong>: <a href="http://martin.ankerl.com/2008/11/04/human-compact-themes-for-ubuntu-810/">Human Compact Theme for Ubuntu 8.10 (Intrepid Ibex)</a> is available!</p>
<p>Well, it is a bit difficult to create a step-by-step tutorial, but I will try anyways. Prepare to fiddle around with your configuration and try it out several times until you get the desired results.</p>
<ol>
<li>All your Gnome themes are located under <tt>/usr/share/themes</tt>. Find the theme of which you want to create a compact one, and copy it into your home directory with e.g.
<pre>cp -r /usr/share/themes/Human ~/.themes/Human-Compact</pre>
<li>If there is a file <tt>index.theme</tt>, open it and change all the names (e.g. add &#8220;Compact&#8221; where appropriate). This file is necessary if you want to directly choose the theme from the Appearance Preferences; if it is not available you have to choose a theme and select &#8220;customize&#8221; to select the compact controls for it.
<li>Now to the fiddling part. Open <tt>gtk-2.0/gtkrc</tt>, and change lots of thickness and width settings&#8230; When you do this, always check how your changes work visibly, e.g. if the application still have usable borders etc. To help with the fiddling, I have added a <a href="#diff">diff of the Human vs. the Compact theme</a>, you might be able to reuse some of the settings there.
<li>Once you are satisfied with your theme, you can create a <tt>.tar.bz2</tt> distribution for backup or to be used by others, e.g. with this command:
<pre>cd ~/.themes
tar cjvf ~/Human-Compact.tar.bz2 Human-Compact</pre>
<li>That&#8217;s it. Have fun with your theme!
</ol>
<p><span id="more-179"></span><br />
<a name="diff"></a>Diff between &#8220;Human&#8221; and &#8220;Human Compact&#8221;</p>
<pre class="brush: ruby;">
--- /usr/share/themes/Human/gtk-2.0/gtkrc	2008-07-03 18:13:20.000000000 +0200
+++ .themes/Human Compact/gtk-2.0/gtkrc	2008-05-22 21:11:07.000000000 +0200
@@ -10,29 +10,61 @@

 gtk_color_scheme = &quot;fg_color:#101010\nbg_color:#EFEBE7\nbase_color:#FFF\ntext_color:#000\nselected_bg_color:#FFD799\nselected_fg_color:#000\ntooltip_bg_color:#F5F5B5\ntooltip_fg_color:#000\norange_color:#FF6D0C\nmetacity_frame_color:#CC863E\nextra_view_widgets_color:#F5C07F&quot;

-gtk-icon-sizes = &quot;panel-menu=24,24&quot;
+gtk-icon-sizes = &quot;panel-menu=16,16 : gtk-menu=16,16 : gtk-button=16,16 : gtk-small-toolbar=16,16 : gtk-large-toolbar=16,16 : gtk-dialog=32,32 : gtk-dnd=32,32&quot;

 style &quot;ubuntulooks-default&quot;
 {
-	GtkButton      ::default_border    = { 0, 0, 0, 0 }
+	# base class for everything
+        # setting this to 0 has *very* tight packing. 1-2 looks better.
+	GtkWidget      ::focus_padding        = 0
+
+	GtkButton      ::child-displacement-x = 1
+	GtkButton      ::child-displacement-y = 1
+	GtkButton      ::default-border       = { 0, 0, 0, 0 }
+	GtkButton      ::default-outside-border={ 0, 0, 0, 0 }
+
+	GtkButtonBox   ::child_min_width      = 0
+	GtkButtonBox   ::child_min_heigth     = 0
+	GtkButtonBox   ::child_internal_pad_x = 0
+	GtkButtonBox   ::child_internal_pad_y = 0
+
+	GtkPaned       ::handle_size       = 4
+
 	GtkRange       ::trough_border     = 0
-	GtkPaned       ::handle_size       = 6
-	GtkRange       ::slider_width      = 15
+	GtkRange       ::slider_width      = 14
 	GtkRange       ::stepper_size      = 15
+	GtkRange       ::stepper_spacing   = 0

-	GtkScrollbar   ::min_slider_length = 35
+	GtkScrollbar   ::min_slider_length = 30
+	GtkScrolledWindow::scrollbar_spacing = 0
 	GtkCheckButton ::indicator_size    = 14
 	GtkMenuBar     ::internal-padding  = 0
-	GtkTreeView    ::expander_size     = 14
-	GtkExpander    ::expander_size     = 16
-	GtkScale       ::slider-length     = 31
+
+	GtkMenu        ::horizontal-padding   = 0
+	GtkMenu        ::vertical-padding     = 0
+
+	GtkOptionMenu  ::indicator_size       = 0
+	GtkOptionMenu  ::indicator_spacing    = 0
+
+
+	GtkTreeView    ::expander_size     = 11
+	GtkTreeView    ::expander_spacing  = 0
+	GtkTreeView    ::vertical-separator = 0
+	GtkTreeView    ::horizontal-separator = 0
+
+	GtkExpander    ::expander_size     = 11
+	GtkExpander    ::expander_spacing  = 0
+	GtkScale       ::slider-length     = 23
+	GtkScale       ::value_spacing     = 0
+
+	GtkToolbar     ::internal-padding  = 0
+	GtkToolbar     ::space-size        = 10
+
 	# GtkToolbar     ::button-relief     = GTK_RELIEF_NORMAL
 	# GtkMenuBar     ::shadow-type       = GTK_SHADOW_OUT
 	# GtkScrollbar   ::has-secondary-forward-stepper = 1
 	# GtkScrollbar   ::has-secondary-backward-stepper = 1

-	GtkButton      ::child-displacement-x = 0
-	GtkButton      ::child-displacement-y = 0

 	xthickness = 1
 	ythickness = 1
@@ -92,8 +124,8 @@

 style &quot;ubuntulooks-wide&quot; = &quot;ubuntulooks-default&quot;
 {
-	xthickness = 2
-	ythickness = 2
+	xthickness = 0
+	ythickness = 0
 }

 style &quot;ubuntulooks-wide-orange&quot; = &quot;ubuntulooks-wide&quot;
@@ -104,7 +136,7 @@
 style &quot;ubuntulooks-wider&quot; = &quot;ubuntulooks-default&quot;
 {
 	xthickness = 3
-	ythickness = 3
+	ythickness = 2
 }

 style &quot;ubuntulooks-wider-orange&quot; = &quot;ubuntulooks-wider&quot;
@@ -114,12 +146,18 @@

 style &quot;ubuntulooks-button&quot; = &quot;ubuntulooks-wider-orange&quot;
 {
+	xthickness   = 0
+	ythickness   = 0
+
 	bg[PRELIGHT] = shade (1.02, @bg_color)
 	bg[ACTIVE]   = shade (0.90, @bg_color)
 }

 style &quot;ubuntulooks-notebook&quot; = &quot;ubuntulooks-wide-orange&quot;
 {
+	xthickness = 0
+	ythickness = 0
+
 	bg[NORMAL]      = shade (0.99, @bg_color)
 	bg[ACTIVE]      = shade (0.85, @bg_color)
 	bg[INSENSITIVE] = shade (0.99, @bg_color)
@@ -127,14 +165,14 @@

 style &quot;ubuntulooks-tasklist&quot; = &quot;ubuntulooks-default&quot;
 {
-	xthickness = 5
-	ythickness = 3
+	xthickness = 0
+	ythickness = 0
 }

 style &quot;ubuntulooks-menu&quot; = &quot;ubuntulooks-default&quot;
 {
-	xthickness = 2
-	ythickness = 1
+	xthickness = 0
+	ythickness = 0
 	bg[NORMAL] = shade (1.04, @bg_color)
 }

@@ -145,8 +183,9 @@

 style &quot;ubuntulooks-menu-item&quot; = &quot;ubuntulooks-default&quot;
 {
-	xthickness     = 2
-	ythickness     = 3
+	xthickness     = 1
+	ythickness     = 1
+
 	bg[SELECTED]   = @selected_bg_color
 	fg[PRELIGHT]   = @selected_fg_color
 	text[PRELIGHT] = @text_color
@@ -171,19 +210,26 @@

 style &quot;ubuntulooks-progressbar&quot; = &quot;ubuntulooks-wide-orange&quot;
 {
-	xthickness    = 2
-	ythickness    = 2
+	xthickness    = 0
+	ythickness    = 0
 	fg[PRELIGHT]  = @base_color
 }

 style &quot;ubuntulooks-treeview&quot; = &quot;ubuntulooks-wide-orange&quot;
 {
-	xthickness    = 2
-	ythickness    = 2
+	xthickness    = 0
+	ythickness    = 0
 	fg[NORMAL]  = @text_color
 	fg[SELECTED]  = @base_color
 }

+# style are overriden again.
+style &quot;ubuntulooks-treeview-header&quot; = &quot;ubuntulooks-default&quot;
+{
+	xthickness = 0
+	ythickness = 0
+}
+
 style &quot;ubuntulooks-combo&quot; = &quot;ubuntulooks-button&quot;
 {
 }
</pre>
<p>Any questions, comments?</p>
<div style='clear:both'></div><img src="http://martin.ankerl.com/?ak_action=api_record_view&id=179&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://martin.ankerl.com/2008/10/10/how-to-make-a-compact-gnome-theme/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Logical Volume Manager Cheatsheet</title>
		<link>http://martin.ankerl.com/2008/02/05/logical-volume-manager-cheatsheet/</link>
		<comments>http://martin.ankerl.com/2008/02/05/logical-volume-manager-cheatsheet/#comments</comments>
		<pubDate>Mon, 04 Feb 2008 23:08:47 +0000</pubDate>
		<dc:creator>Martin Ankerl</dc:creator>
				<category><![CDATA[howto]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://martin.ankerl.com/2008/02/05/logical-volume-manager-cheatsheet/</guid>
		<description><![CDATA[Today I got a new harddisk, so it was finally time for me to have an in depth look at LVM. I use it to combine two harddisks /dev/sdg1 and /dev/sdb1 into one volume group ext_vg which contains one big logical volume /dev/ext_vg/ext. In short, my 250GB and 500GB harddisks are used in one big [...]]]></description>
			<content:encoded><![CDATA[<p>Today I got a new harddisk, so it was finally time for me to have an in depth look at <a href="http://sources.redhat.com/lvm2/">LVM</a>. I use it to combine two harddisks <tt>/dev/sdg1</tt> and <tt>/dev/sdb1</tt> into one volume group <tt>ext_vg</tt> which contains one big logical volume <tt>/dev/ext_vg/ext</tt>. In short, my 250GB and 500GB harddisks are used in one big 750GB ext3 mount point.</p>
<p>I followed the excellent <a href="http://www.linuxconfig.org/Linux_lvm_-_Logical_Volume_Manager">LVM Tutorial</a>, and was surprised how easy everything goes. Here is a short cheat sheet of the important commands (take care to exchange the partition/volume names if you use this):</p>
<h2>Installation</h2>
<p>I use <a href="http://www.ubuntu.com/">Ubuntu</a>, so this is a piece of cake:
<pre>sudo apt-get install lvm2</pre>
<p>There is also <a href="http://ubuntuforums.org/showthread.php?t=216117">a GUI available</a>, but I found the command line tools are very easy to use so there is no real need. I wouldn&#8217;t use <a href="https://wiki.ubuntu.com/Evms">EVMS</a> as it is not supported in Ubuntu 7.10 and may cause problems.</p>
<h2>Create a New Filesystem</h2>
<p>First I create the physical volume on the partition <tt>sdg1</tt>, create a new volume group <tt>ext_vg</tt> that contains this physical volume, and create a new logical volume of size 450GB within the volume group. Finally create the filesystem (disabled reservation space, see <a href="http://martin.ankerl.com/2008/01/12/get-more-space-out-of-your-ext3-partition/">Get More Space Out of Your ext3 Partition</a>).
<pre>sudo pvcreate /dev/sdg1
sudo vgcreate ext_vg /dev/sdg1
sudo lvcreate -L 450G -n ext ext_vg
sudo mkfs.ext3 -m 0 /dev/ext_vg/ext</pre>
<h2>Show Status</h2>
<p>Each LVM layer has its corresponding command to get information about the metadata:
<pre>sudo pvdisplay
sudo vgdisplay
sudo lvdisplay
sudo pvs
sudo vgs
sudo lvs</pre>
<h2>Mount via fstab</h2>
<p>I use the filesystem mainly for data, so allowing just <tt>rw</tt> is enough (no executables allowed). <tt>noatime</tt> allows quicker access.
<pre>sudo mkdir /media/mega
/dev/ext_vg/ext /media/mega     ext3    rw,noatime,user 0       2
mount /media/mega</pre>
<h2>Resize</h2>
<p>It is even possible to do an online resize of the system, wohoo <img src='http://martin.ankerl.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  This extends the logical volume by 200MB.
<pre>sudo lvextend -L +200 /dev/ext_vg/ext
sudo resize2fs -p /dev/ext_vg/ext</pre>
<p> You can watch the resize process going on with <tt>df -h</tt>.</p>
<h2>Add Another Partition to the Logical Volume</h2>
<p>To add another partition and use up all the available space in the logical volume, first add the physical volume to the volume group, then use <tt>pvdisplay</tt> to find out the total available number of free PE (add the numbers from the physical volumes), then use <tt>lvextend</tt> to use up all this available space.
<pre>sudo pvcreate /dev/sdb1
sudo vgextend ext_vg /dev/sdb1
sudo pvdisplay
sudo lvextend -l +63602 /dev/ext_vg/ext
sudo resize2fs /dev/ext_vg/ext</pre>
<p>That&#8217;s it! Any questions? please post.</p>
<div style='clear:both'></div><img src="http://martin.ankerl.com/?ak_action=api_record_view&id=119&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://martin.ankerl.com/2008/02/05/logical-volume-manager-cheatsheet/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Howto Get Enough Sleep Despite StumbleUpon with Ubuntu</title>
		<link>http://martin.ankerl.com/2008/01/24/howto-get-enough-sleep-despite-stumbleupon-with-ubuntu/</link>
		<comments>http://martin.ankerl.com/2008/01/24/howto-get-enough-sleep-despite-stumbleupon-with-ubuntu/#comments</comments>
		<pubDate>Thu, 24 Jan 2008 22:06:44 +0000</pubDate>
		<dc:creator>Martin Ankerl</dc:creator>
				<category><![CDATA[howto]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[tricks]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[getsomesleep]]></category>
		<category><![CDATA[lifehack]]></category>

		<guid isPermaLink="false">http://martin.ankerl.com/2008/01/24/howto-get-enough-sleep-despite-stumbleupon-with-ubuntu/</guid>
		<description><![CDATA[What? I am a long-term StumbleUpon user, which means that I don&#8217;t get much sleep. Now, after almost 4 years of stumbling, I have decided to get my life back. Well, at least some sleep! What does this do? Every night when I have to work on the next day (Sunday night to Thursday night [...]]]></description>
			<content:encoded><![CDATA[<h2>What?</h2>
<p><a href='http://martin.ankerl.com/wp-content/uploads/2008/01/stumbling-insomnia.jpg'><img src="http://martin.ankerl.com/wp-content/uploads/2008/01/stumbling-insomnia.jpg" alt="" title="stumbleupon insomnia" width="150" height="104" style="float:right;" /></a>I am a long-term <a href="http://www.stumbleupon.com/">StumbleUpon</a> user, which means that I don&#8217;t get much sleep. Now, after <a href="http://martinus.stumbleupon.com/public/">almost 4 years of stumbling</a>, I have decided to get my life back. Well, at least some sleep! </p>
<h2>What does this do?</h2>
<p>Every night when I have to work on the next day (Sunday night to Thursday night ), at 23:25 my computer shows me this little warning message:<br />
<center><img src='http://martin.ankerl.com/wp-content/uploads/2008/01/screenshot-warning.png' alt='go to bed warning' /></center><br />
After the 5 minutes have passed, the computer shuts itself automatically down.</p>
<p>I use this little trick with <a href="http://www.ubuntu.com/">Ubuntu,</a> but it should work anywhere where <a href="http://www.gnome.org/">Gnome</a> is installed.</p>
<h2>How?</h2>
<p>Thanks to the power of Linux, this is not difficult to do for yourself, and configure it however you want it to behave:</p>
<ol>
<li>Open <tt>/etc/crontab</tt> with your favourite text editor (no need for <tt>crontab -e</tt> since this is the system wide crontab), e.g.
<pre>sudo gedit /etc/crontab</pre>
</li>
<li>Add the following lines (replace <tt>manker</tt> with your username!)
<pre>25 23 * * 0-4   manker  /usr/bin/zenity --display :0 --warning --text="Shutdown in 5 minutes. Go to bed."
25 23 * * 0-4   root    shutdown -h +5</pre>
<li>The first part of both lines <tt>25 23 * * 0-4</tt> means that the commands are executed at 23:25, but only Sunday (day 0) to Thursday (day 4). Read <tt>man 5 crontab</tt> for a detailed description of that format.</li>
<li>The first command uses <tt>zenity</tt> to show a warning message. You have to execute this as the same user that you use for working, or you will not see the message, so change <tt>manker</tt> to your username (root does not work either).
<li>The second command <tt>shutdown -h +5</tt> means that the computer will halt in 5 minutes.  This has to be run as root, and it also shows nice warning messages in all your open terminals so you can&#8217;t really miss it.</li>
<li>Save the file, and stumble until it is 23:25.</ul>
</ol>
<p>Sweet dreams!</p>
<div style='clear:both'></div><img src="http://martin.ankerl.com/?ak_action=api_record_view&id=106&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://martin.ankerl.com/2008/01/24/howto-get-enough-sleep-despite-stumbleupon-with-ubuntu/feed/</wfw:commentRss>
		<slash:comments>72</slash:comments>
		</item>
		<item>
		<title>Ajax Dojo Comet Tutorial</title>
		<link>http://martin.ankerl.com/2007/08/21/ajax-dojo-comet-tutorial/</link>
		<comments>http://martin.ankerl.com/2007/08/21/ajax-dojo-comet-tutorial/#comments</comments>
		<pubDate>Tue, 21 Aug 2007 12:41:22 +0000</pubDate>
		<dc:creator>Martin Ankerl</dc:creator>
				<category><![CDATA[ajax]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[videos]]></category>
		<category><![CDATA[comet]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[howto]]></category>

		<guid isPermaLink="false">http://martin.ankerl.com/?p=92</guid>
		<description><![CDATA[EDIT: This tutorial is for an old version of dojo / comet, and it will not work in a recent version! Markus Holzmann, an intern at Profactor of my fellow colleague Philipp Hartl, had the opportunity to experiment with Ajax during his job. He wrote a tutorial about how to push events from the server [...]]]></description>
			<content:encoded><![CDATA[<p><strong>EDIT</strong>: This tutorial is for an old version of dojo / comet, and it will not work in a recent version!</p>
<p>Markus Holzmann, an intern at <a href="http://www.profactor.at/">Profactor</a> of my fellow colleague <a href="http://leanaustria.net/">Philipp Hartl</a>, had the opportunity to experiment with <a href="http://en.wikipedia.org/wiki/Ajax_(programming)">Ajax</a> during his job. He wrote a tutorial about how to push events from the server to the client. For example, display popup messages on all browsers at the same time (see screencast in <a href="/files/hello_comet.html" target="_blank">full resolution here</a>):<br />
<center><br />
<a href="/files/hello_comet.html" target="_blank">  <object width="400" height="317"><param name="wmode" value="transparent"></param>
    <embed src="/files/Hello_Comet.swf" wmode="transparent" width="401" height="317" type="application/x-shockwave-flash"></embed></object><br />
</a><br />
</center><br />
Read on how Markus did this:</p>
<p><span id="more-92"></span></p>
<h1>Cometd Hello World</h1>
<p>
I&#8217;ve read Chris Bucchere&#8217;s <a href="http://thebdgway.blogspot.com/2006/11/say-hello-world-to-comet.html">Say Hello World to Comet</a> and built an application based on this using a more current version of <a href="http://www.mortbay.org/">Jetty</a> (version <a href="http://dist.codehaus.org/jetty/jetty-6.1.5/">6.1.5</a>) which I embedded into a <a href="http://tomcat.apache.org/">Tomcat</a> v5.5 Server. For the developing I used <a href="http://www.eclipse.org/">Eclipse</a> 3.2.</p>
<p><h1>Start your Engines</h1>
<p>At first you have to get the server running. As I mentioned I embedded Jetty into a Tomcat server. Therefore you have configure the libraries:</p>
<ol>
<li>Add the packages <tt>org.mortbay.cometd</tt> and <tt>dojox.cometd</tt> to your source folder and delete the <tt>client</tt> package in the <tt>org.mortbay.cometd</tt> package.</li>
<li>Add <tt>jetty-util-6.1.5.jar</tt>, <tt>jetty-6.1.5.jar</tt> and <tt>servlet-api-2.5-6.1.5.jar</tt> to your build path.</li>
<li>Copy the <tt>jetty-util-6.1.5.jar</tt> file into the <tt>/lib</tt> folder in the <tt>WEB-INF</tt> directory.</li>
</ol>
<p>Replace the existing servlets in your web.xml &#8211; file in the WEB-INF &#8211; folder with the following servlets:</p>
<pre>&lt;servlet&gt;
  &lt;servlet-name&gt;cometd&lt;/servlet-name&gt;
  &lt;servlet-class&gt;org.mortbay.cometd.continuation.ContinuationCometdServlet&lt;/servlet-class&gt;
  &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
  &lt;servlet-name&gt;cometd&lt;/servlet-name&gt;
  &lt;url-pattern&gt;/cometd/*&lt;/url-pattern&gt;
 &lt;/servlet-mapping&gt;</pre>
<p>For the project I used the <a href="http://dojotoolkit.org/">dojo toolkit</a> (version 0.4.3) which has an integrated <a href="http://www.cometd.com/">COMETd</a> class that makes it easy to build comet projects. <a href="http://download.dojotoolkit.org/release-0.4.3/dojo-0.4.3-ajax.tar.gz">Download it</a> and add it to your <tt>WebContent</tt> folder.</p>
<p>
When you&#8217;ve done all this, the hardest piece of work for this program is already done.</p>
<h1>Hack the Code</h1>
<p>Now you can implement the code for the client side: You need a HTML file with a button on it. The code for this looks like this (<a href="/files/hello_comet_test.html">download</a>):</p>
<pre>&lt;html&gt;
  &lt;head&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;../dojo.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;<b>
      dojo.require(&quot;dojo.io.cometd&quot;);

      cometd.init({}, &quot;cometd&quot;);

      cometd.subscribe(&quot;/hello/world&quot;, false, &quot;publishHandler&quot;);

      publishHandler = function(msg) {
        alert(msg.data.test);
      }</b>
    &lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;input type=&quot;button&quot;
       onclick=&quot;<b>cometd.publish('/hello/world', { test: 'hello world' } )</b>&quot;
       value=&quot;Click Me!&quot;&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
<p>Line by line, the above bold code works like this:</p>
<ol>
<li>In the line
<pre>&lt;script type="text/javascript" src="../dojo.js"&gt;&lt;/script&gt;</pre>
<p> you integrate the dojo toolkit into the project.</p>
<li>To activate the cometd class of dojo:
<pre>dojo.require("dojo.io.cometd");</pre>
<li>Connect the server with the client:
<pre>cometd.init({}, "cometd");</pre>
<li>Here we say what to do when there is a subscribe event:
<pre>cometd.subscribe("/hello/world", false, "publishHandler");</pre>
<li>Last but not least, the <tt>publishHandler</tt> function serves as the callback function, which uses <tt>alert</tt> to show a simple message box:
<pre>publishHandler = function(msg) {
  alert(msg.data.test);
}</pre>
</ol>
<h1>Give it a Try</h1>
<p>When you load the HTML file now, you can click on the button and an alert box saying <i>hello world</i> will appear:</p>
<p>
<center><img src="/files/helloworld.png" width="324" height="124" /></center></p>
<p>
The reason for this is that when you click the code
<pre>cometd.publish('/hello/world', { test: 'hello world' } )</pre>
<p> is executed which publishes a text on the channel with the id <tt>/hello/world</tt>.</p>
<p>
The funny thing is that this is able to run on any number of browsers. Everytime when a client clicks the button, on <i>all</i> browsers that view this page the alert box is shown. (See screencast above).</p>
<h1>Pushing Data from Server to Client</h1>
<p>You can also add serverside code to trigger an event. I wrote a JSP file with the following code:</p>
<pre>&lt;%@page import="java.util.*"%&gt;
&lt;%@page import="dojox.cometd.*" %&gt;
&lt;%
Bayeux b = (Bayeux)getServletContext().getAttribute(Bayeux.DOJOX_COMETD_BAYEUX);
Channel c = b.getChannel("/hello/world",false);

Map&lt;String,Object&gt; message = new HashMap&lt;String,Object&gt;();
message.put("test", "jsp: hello world");

c.publish(b.newClient("server_user",null),message, "new server message");
%&gt;</pre>
<p>When this page is loaded, an alert popup appears at the page saying <i>jsp: hello world</i>.</p>
<p>That&#8217;s it. Happy hacking!</p>
<div style='clear:both'></div><img src="http://martin.ankerl.com/?ak_action=api_record_view&id=92&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://martin.ankerl.com/2007/08/21/ajax-dojo-comet-tutorial/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
	</channel>
</rss>
