<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Kommie P: le blog</title>
 <link href="http://ppanyukov.github.com/atom.xml" rel="self"/>
 <link href="http://ppanyukov.github.com/"/>
 <updated>2011-08-17T14:27:36-07:00</updated>
 <id>http://ppanyukov.github.com/</id>
 <author>
   <name>Kommie P.</name>
   <email>none@none.com</email>
 </author>

 
 <entry>
   <title>Resolving host names on Windows, Linux and Mac</title>
   <link href="http://ppanyukov.github.com/2011/08/17/hostname-resolve.html"/>
   <updated>2011-08-17T00:00:00-07:00</updated>
   <id>http://ppanyukov.github.com/2011/08/17/hostname-resolve</id>
   <content type="html">&lt;h1&gt;Resolving host names on Windows, Linux and Mac&lt;/h1&gt;

&lt;p&gt;Here is the setup. We have a Windows-based network with AD, DHCP, WINS and DNS
servers. We have Windows, Linux and Mac hosts on wired and wireless networks.
The hosts acquire IP addresses using DHCP.&lt;/p&gt;

&lt;p&gt;The task. Be able to ping all hosts using host name.&lt;/p&gt;

&lt;p&gt;When Windows hosts acquire IP address using DHCP, a record for the host is
created in the DNS. So from any host we can do &lt;code&gt;nslookup mywindowshost&lt;/code&gt; and
it works, and so &lt;code&gt;ping&lt;/code&gt; works too. Note, these Windows hosts are joined into
the domain so that may have some bearing on this, don't know.&lt;/p&gt;

&lt;p&gt;The problem is with the Linux and Mac hosts. By default when these get IP
address from DHCP server they don't get the DNS record created for them. As
a consequence, if I do &lt;code&gt;nslookup ubuntuhost&lt;/code&gt; or &lt;code&gt;nslookup machost&lt;/code&gt; I get back
nothing. Also, by default we can't ping those from Windows machines either.&lt;/p&gt;

&lt;p&gt;It is possible to use bonjour to resolve the Linux and Mac hosts but this does
not work between wireless and wired hosts because I think those two networks
are joined by switches and I guess bonjour only works on the same segment?
I don't know much about this though, I may be wrong. Another problem with
bonjour is that by default it's not present on Windows hosts.&lt;/p&gt;

&lt;p&gt;So here is the summary:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Source host     Target host     Command            Status
---------------------------------------------------------
Windows         Windows         ping host          OK
Windows         Windows         ping host.local    XX 

Ubuntu          Windows         ping host          OK
Ubuntu          Windows         ping host.local    XX

Ubuntu          Ubuntu          ping host          XX
Ubuntu (wired)  Ubuntu (wired)  ping host.local    OK
Ubuntu (wired)  Ubuntu (wi-fi)  ping host.local    XX

Mac             Mac             ping host          XX
Mac (wired)     Mac (wired)     ping host.local    OK
Mac (wired)     Mac (wi-fi)     ping host.local    XX

Ubuntu          Mac             ping host          XX
Mac             Ubuntu          ping host          XX
Ubuntu (wired)  Mac    (wired)  ping host.local    OK
Mac    (wired)  Ubuntu (wired)  ping host.local    OK
Ubuntu (wired)  Mac    (wi-fi)  ping host.local    XX
Mac    (wired)  Ubuntu (wi-fi)  ping host.local    XX
---------------------------------------------------------
NOTE: host.local means using bonjour protocol
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The picture is quite patchy, and I want to fix this.&lt;/p&gt;

&lt;p&gt;The idea is to use NetBIOS-to-IP name resolution and the task consists of two parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make host pingable using NetBIOS name from Windows.&lt;/li&gt;
&lt;li&gt;Make Linux and Mac hosts ping other hosts using NetBIOS.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Interestingly, the job turned out much easier on Ubuntu than on a Mac.&lt;/p&gt;

&lt;h2&gt;Linux (Ubuntu)&lt;/h2&gt;

&lt;p&gt;First, make the Linux host pingable from Windows. Simply install &lt;code&gt;samba&lt;/code&gt;
package. It will install &lt;code&gt;nmbd&lt;/code&gt; daemon which seems to be the one that makes
this work.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# get samba
sudo apt-get install samba

# verify the thing is running
ps -ef | grep nmbd
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now doing &lt;code&gt;ping ubuntuhost&lt;/code&gt; from Windows should work. But this is not
sufficient to make ping work on Linux. The second step is required.&lt;/p&gt;

&lt;p&gt;Second step is to install a WINS resolution thing which is provided by
&lt;code&gt;winbind&lt;/code&gt; package and bit of config file fiddling. Just follow these steps:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# install winbind
sudo apt-get install winbind

# verify the winbindd daemon is running
ps -ef | grep winbindd

# add WINS to the list of resolves in /etc/nsswitch.conf file
# here is the line to modify, simply add &quot;wins&quot; to the end.
hosts:          files mdns4_minimal [NOTFOUND=return] dns mdns4 wins

# now we should be able to ping using NetBIOS name:
ping netbioshost
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After installing &lt;code&gt;winbind&lt;/code&gt; I can now ping Linux host which have samba installed
on them, or Mac hosts which have the same.&lt;/p&gt;

&lt;h2&gt;Mac OS X Snow Leopard&lt;/h2&gt;

&lt;p&gt;This is surprising hard to get the same thing working on Mac. The first
step is easy and the second step, well, I still don't have a solution.&lt;/p&gt;

&lt;p&gt;First, to make a Mac host pingable using NetBIOS name, I had to enable file
sharing and tick the &quot;SMB&quot; option. Here is exactly what I did:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1. Open System Preferences
2. Click &quot;Sharing&quot;
3. Enable &quot;File Sharing&quot; by ticking the checkbox
4. Click &quot;Options&quot; button there, and
5. Make sure the &quot;Share files and folders using SMB (Windows)&quot; is ticked.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you should have &lt;code&gt;nmbd&lt;/code&gt; daemon running. Verify this by opening terminal and:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ps -ef | grep nmbd
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After this I can ping my Mac host from Windows and Linux which has samba installed.&lt;/p&gt;

&lt;p&gt;Now to be able to ping hosts using NetBIOS name from Mac -- that's a completely
different story. Basically, there is no &lt;code&gt;/etc/nsswitch.conf&lt;/code&gt; file. And there is
no &lt;code&gt;winbindd&lt;/code&gt; daemon running (even though it's there). I don't have sufficient
knowledge of OS X to get &lt;code&gt;winbindd&lt;/code&gt; start at boot, but even starting manually
I got some weird errors (which I fixed) but then there is no
&lt;code&gt;/etc/nsswitch.conf&lt;/code&gt; file so the ping still didn't work. But anyway here is
what I did:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# first set the file permissions, as otherwise things don't work
sudo chmod 750 /private/var/samba/winbindd_privileged

# start winbindd without becoming a daemon and with output to terminal
sudo winbindd -i

# try ping my ubuntu host, doesn't work!
ping ubuntuhost
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I have spent some time to try and find what's going on with the &lt;code&gt;nsswitch.conf&lt;/code&gt;
file and how to add wins to the resolvers on Snow Leopard and couldn't find
anything. The only thing I can think of is use &lt;code&gt;nmblookup&lt;/code&gt; to get the IP
address and then use IP address, e.g.:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;nmblookup ubuntuhost
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If anyone knows how to get this working properly, drop me a line.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;On Linux, install &lt;code&gt;samba&lt;/code&gt; and &lt;code&gt;winbind&lt;/code&gt; packages, then edit
&lt;code&gt;/etc/nsswitch.conf&lt;/code&gt; file. This will make the host pingable using NetBIOS names
and also it will be possible to ping other NetBIOS hosts.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# get packages
sudo apt-get install samba
sudo apt-get install winbind

# add wins to the /etc/nsswitch.conf
hosts:          files mdns4_minimal [NOTFOUND=return] dns mdns4 wins
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On Mac, make the host pingable by enabling file sharing for Windows clients.
This will start &lt;code&gt;nmbd&lt;/code&gt; daemon. I couldn't figure out what needs to be done to
ping from Mac using NetBIOS. Still work in progress.&lt;/p&gt;

&lt;p&gt;Here is the summary of the achievement:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Source host     Target host     Command            Status
---------------------------------------------------------
Windows         Windows         ping host          OK
Windows         Ubuntu          ping host          OK
Windows         Mac             ping host          OK

Ubuntu          Ubuntu          ping host          OK
Ubuntu          Windows         ping host          OK
Ubuntu          Mac             ping host          OK

Mac             Ubuntu          ping host          XX
Mac             Mac             ping host          XX
Mac             Windows         ping host          OK
---------------------------------------------------------
NOTE: I didn't include bonjour here, as there is no point
NOTE: Assume that Windows hosts are resolved by nslookup
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you know how to get this completed on a Mac, drop me a line at &lt;code&gt;ppanyukov at
googlemail.com&lt;/code&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Le C# Grit</title>
   <link href="http://ppanyukov.github.com/2011/07/14/why-C%23-sucks.html"/>
   <updated>2011-07-14T00:00:00-07:00</updated>
   <id>http://ppanyukov.github.com/2011/07/14/why-C#-sucks</id>
   <content type="html">&lt;h1&gt;Le C# Grit&lt;/h1&gt;

&lt;p&gt;This is a growing list of my annoyances with C# which emerged after my exploration of other languages, in particular F#.&lt;/p&gt;

&lt;h1&gt;Functions are not first class citizens&lt;/h1&gt;

&lt;p&gt;There are many, many times when I want to have a nice function which does
something but I need or want to break it into several smaller functions.
In C# it often goes like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Foo_Traditional
{
    public object GetStuff(object input)
    {
        object temp_A = this.GetStuff_Helper_A(input);
        object temp_B = this.GetStuff_Helper_B(temp_A);
        return temp_B;
    }

    private object GetStuff_Helper_A(object input)
    {
        return input.ToString() + &quot;/GetStuff_Helper_A&quot;;
    }

    private object GetStuff_Helper_B(object input)
    {
        return input.ToString() + &quot;/GetStuff_Helper_B&quot;;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is not nice because &lt;code&gt;GetStuff_Helper_A&lt;/code&gt; and &lt;code&gt;GetStuff_Helper_B&lt;/code&gt; are used
only by one method but are now exposed as the class-level methods. What I want
is to make those helper methods private to the implementation of &lt;code&gt;GetStuff&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;OK, let's rewrite this as lambdas.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Foo_Lambdas_attempt_1
{
    public object GetStuff(object input)
    {
        // Error here: can't declare variable &quot;input&quot; as it's already declared!
        Func&amp;lt;object, object&amp;gt; get_stuff_helper_a = (input) =&amp;gt;
            {
                return input.ToString() + &quot;/GetStuff_Helper_A (lambda)&quot;;
            };

        // Error here: can't declare variable &quot;input&quot; as it's already declared!
        Func&amp;lt;object, object&amp;gt; get_stuff_helper_b = (input) =&amp;gt;
        {
            return input.ToString() + &quot;/GetStuff_Helper_B (lambda)&quot;;
        };

        object temp_A = get_stuff_helper_a(input);
        object temp_B = get_stuff_helper_b(temp_A);
        return temp_B;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Two things to notice here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;It's not just a matter of copy/paste of class-level members. We must do
some work to convert them to lambdas. And this involves declaring things
like &lt;code&gt;Func&amp;lt;object,object&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can't use the same variable name &lt;code&gt;input&lt;/code&gt; as the parameter for the lambda
because it's already delcared in outer scope. But what do we do? What if it
makes perfect sense to call that variable &lt;code&gt;input&lt;/code&gt;?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;There are two solutions to the latter, none of which make things any easier:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Rename &lt;code&gt;input&lt;/code&gt; to something else like &lt;code&gt;input1&lt;/code&gt;; or&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the parameter from the lambda and use the one that's already
declared. This will mean re-writing the &lt;code&gt;Func&amp;lt;object,object&amp;gt;&lt;/code&gt; declaration
into &lt;code&gt;Fun&amp;lt;object&amp;gt;&lt;/code&gt; and removing the parameters. More work!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;OK, I prefer to rename the parameters and end up with this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Foo_Lambdas_attempt_2_which_compiles
{
    public object GetStuff(object input)
    {
        // OK now, renamed input to input2
        Func&amp;lt;object, object&amp;gt; get_stuff_helper_a = (input2) =&amp;gt;
        {
            return input2.ToString() + &quot;/GetStuff_Helper_A (lambda)&quot;;
        };

        // OK now, renamed input to input2
        Func&amp;lt;object, object&amp;gt; get_stuff_helper_b = (input2) =&amp;gt;
        {
            return input2.ToString() + &quot;/GetStuff_Helper_B (lambda)&quot;;
        };

        object temp_A = get_stuff_helper_a(input);
        object temp_B = get_stuff_helper_b(temp_A);
        return temp_B;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now lets say I need a helper function which returns a &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt;. I go an
try to enhance my function with this helper lambda:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Foo_with_enumerables
{
    public object GetStuff(object input)
    {
        Func&amp;lt;IEnumerable&amp;lt;string&amp;gt;&amp;gt; get_stuff_helper_c = () =&amp;gt;
            {
                // ERROR! Only methods, operators and accessors could contain 'yield' statement.
                yield return &quot;this sucks&quot;;
            };

        ...
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And why the hell can't I have the lambda which returns an &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt;???
What do I do now? Back to the class-level method I guess.&lt;/p&gt;

&lt;p&gt;THIS SUCKS.&lt;/p&gt;

&lt;h3&gt;The F# way&lt;/h3&gt;

&lt;p&gt;Here is the same starting point, with main function and helpers being separate:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Starting point
let get_stuff_helper_a input = 
    input.ToString() + &quot;/GetStuff_Helper_A (F#)&quot;

let get_stuff_helper_b input = 
    input.ToString() + &quot;/GetStuff_Helper_A (F#)&quot;

let DoStuff input = 
    let temp_A = get_stuff_helper_a input
    let temp_B = get_stuff_helper_b temp_A
    temp_B
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice one thing immediately: there is much less clutter to start with.&lt;/p&gt;

&lt;p&gt;Now let's hide those helper functions.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Hide the helper functions
let DoStuff input = 
    let get_stuff_helper_a input = 
        input.ToString() + &quot;/GetStuff_Helper_A (F#)&quot;

    let get_stuff_helper_b input = 
        input.ToString() + &quot;/GetStuff_Helper_A (F#)&quot;

    let temp_A = get_stuff_helper_a input
    let temp_B = get_stuff_helper_b temp_A
    temp_B
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Wow, just cut and paste them to be inside &lt;code&gt;DoStuff&lt;/code&gt;, no change required!&lt;/p&gt;

&lt;p&gt;And now lets see if we can add helper function which returns &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Add helper function returning IEnumerable&amp;lt;T&amp;gt;
let DoStuff input = 
    let get_stuff_helper_a input = 
        input.ToString() + &quot;/GetStuff_Helper_A (F#)&quot;

    let get_stuff_helper_b input = 
        input.ToString() + &quot;/GetStuff_Helper_A (F#)&quot;

    let get_stuff_helper_c () = seq {
        yield &quot;this rocks!&quot;
    }

    let temp_A = get_stuff_helper_a input
    let temp_B = get_stuff_helper_b temp_A
    temp_B
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It works! And, incidentally, the function &lt;code&gt;DoStuff&lt;/code&gt; is automatically generic:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'a -&amp;gt; string
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which translates in C# terms as&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;string GetStuff&amp;lt;T&amp;gt;(T input)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In C# I would have to explicitly make the function generic (which is another story).&lt;/p&gt;

&lt;p&gt;Lets summarise. In F# we have:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cut/paste functions without changes. No can do in C#.&lt;/li&gt;
&lt;li&gt;Re-bind different value to same name (aka no need to rename parameter). No can do in C#.&lt;/li&gt;
&lt;li&gt;Can have &lt;em&gt;any&lt;/em&gt; function within function, including those returning &lt;code&gt;IEnumuerable&amp;lt;T&amp;gt;&lt;/code&gt;. No can do in C#.&lt;/li&gt;
&lt;li&gt;Functions are generic by default. Not in C#.&lt;/li&gt;
&lt;li&gt;Code seems to be much more concise and readable. C# has too much clutter, it's too verbose.&lt;/li&gt;
&lt;/ol&gt;


&lt;hr /&gt;

&lt;h1&gt;Can't assign lambdas to implicit variables&lt;/h1&gt;

&lt;p&gt;Scanario. I want to write something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// C# -- This doesn't work
var someFun = (x) =&amp;gt; 
{
    if (x &amp;gt; 0)
        return true;
    else
        return false;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;No can do! Gives me a compiler error: &lt;em&gt;error CS0815: Cannot assign lambda expression to an implicitly-typed local variable&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Instead I have to do the full type specification:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// C# -- This works
Func&amp;lt;int,bool&amp;gt; somFun = (x) =&amp;gt;
{
    if (x &amp;gt; 0)
        return true;
    else
        return false;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It might be OK if the types in use are simple like above, but what if they are not? For example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// C# -- really bad
Fun&amp;lt;Map&amp;lt;string,DisposableWrapper&amp;lt;_MailItem&amp;gt;&amp;gt;, Tuple&amp;lt;DisposableWrapper&amp;lt;_MailItem&amp;gt;&amp;gt;&amp;gt; someFun2 = (stuffIn) =&amp;gt;
{
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;THIS SUCKS.&lt;/p&gt;

&lt;h3&gt;The F# way&lt;/h3&gt;

&lt;p&gt;And here is F#:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// F# -- this works
let someFun x = 
    if x &amp;gt; 0 then 
        true 
    else 
        false
&lt;/code&gt;&lt;/pre&gt;
</content>
 </entry>
 
 <entry>
   <title>Burning DVD images from AVI files</title>
   <link href="http://ppanyukov.github.com/2011/07/11/create-dvd-from-avi.html"/>
   <updated>2011-07-11T00:00:00-07:00</updated>
   <id>http://ppanyukov.github.com/2011/07/11/create-dvd-from-avi</id>
   <content type="html">&lt;h1&gt;Burning DVD images from AVI files&lt;/h1&gt;

&lt;h2&gt;General sequence&lt;/h2&gt;

&lt;p&gt;My understanding is that  the general sequence is like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;AVI -&amp;gt; MPEG2 -&amp;gt; DVD File System -&amp;gt; DVD ISO -&amp;gt; DVD Disk
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In order to do all this, we need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tools to do each of the steps;&lt;/li&gt;
&lt;li&gt;codecs to encode/decode video and audio embedded in the AVI/MPEG2 files.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;This may not be so easy, especially on Windows, but is manageable on Linux.&lt;/p&gt;

&lt;h2&gt;On Windows&lt;/h2&gt;

&lt;p&gt;So you are on Windows and want to burn that AVI files your friends gave you to
a DVD and watch it on telly. From what I remember, this is all very painful.
The problems generally are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The AVI files may use codecs which you don't have;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The players you use (e.g. Windows Media Player) doesn't tell you which
codecs you need, it just refuses to play the stuff.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No idea where to take those codecs even if you knew which ones you need.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even if you have the codecs, you still need the software to create the DVD!
And they are not free and all of those I used were beyond crap.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;What to do? Here is a quick solution:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Get yourself &lt;a href=&quot;http://www.virtualbox.org/&quot;&gt;Oracle VirtualBox&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get yourself a distribution of Linux. &lt;a href=&quot;http://www.ubuntu.com/download&quot;&gt;Ubuntu&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install it and follow instructions for Linux. Easy!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;And besides, the benefit is learning Linux too.&lt;/p&gt;

&lt;h1&gt;Creating DVD images from AVI files on Linux&lt;/h1&gt;

&lt;h2&gt;Tools&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;Tool      Step                          Apt-get package
---------------------------------------------------------
ffmpeg    (AVI -&amp;gt; MPEG2)                gstreamer0.10-*
dvdauthor (MPEG2 -&amp;gt; DVD File System)    dvdauthor
mkisofs   (DVD File System -&amp;gt; DVD ISO)  genisoimage
growisofs (DVD ISO -&amp;gt; DVD)              growisofs
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To install these do from command line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo apt-get install gstreamer0.10.-* dvdauthor genisoimage growisofs
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Details&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Export the video format as an environmental variable, otherwise there may
be problems with the DVD file system.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;export VIDEO_FORMAT=PAL
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Encode &lt;em&gt;AVI&lt;/em&gt; file into &lt;em&gt;MPEG2&lt;/em&gt;. This will take a while!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ffmpeg -i &amp;lt;input_avi&amp;gt; -target pal-dvd -ps 2000000000 -aspect 16:9 output.mpg
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a DVD file system from the MPEG2 file. (NOTE: delete the target directory first).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;dvdauthor -o &amp;lt;output_dir&amp;gt; -t -v &quot;PAL+16:9&quot; -f output.mpg

(NOTE: I'm not sure this command line works properly, I think the
switch should be &quot;-T&quot; instead of &quot;-t&quot; but I haven't checked this yet.)
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a DVD ISO image from the directory.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mkisofs -dvd-video -o dvd.iso dvd/
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Burn the DVD ISO onto disk&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;growisofs -dvd-compat -Z /dev/dvd=dvd.iso
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>Retabbing files using VIM</title>
   <link href="http://ppanyukov.github.com/2011/06/29/retabbing-in-vim.html"/>
   <updated>2011-06-29T00:00:00-07:00</updated>
   <id>http://ppanyukov.github.com/2011/06/29/retabbing-in-vim</id>
   <content type="html">&lt;h1&gt;Retabbing files using VIM&lt;/h1&gt;

&lt;p&gt;Recently I've made a mistake of using 2 spaces to indent my F# program. After
some thought I decided to stick to 4 spaces like everyone else does.&lt;/p&gt;

&lt;p&gt;Here is how it looked:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;module foomodule
  let foo = 
    let bar = 
      get_file_names()
      |&amp;gt; Seq.filter (f -&amp;gt; f.EndsWith(&quot;.cs&quot;)
    let bar2 = do_something_with_bar bar
    bar2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And here is how I wanted it to look&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;module foomodule
    let foo = 
        let bar = 
            get_file_names()
            |&amp;gt; Seq.filter (f -&amp;gt; f.EndsWith(&quot;.cs&quot;)
        let bar2 = do_something_with_bar bar
        bar2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What to do? This is not as trivial as it may look. But not if use use VIM!&lt;/p&gt;

&lt;p&gt;Here is how to retab everything using VIM:&lt;/p&gt;

&lt;p&gt;Step 0. (Optional) Tell VIM to show whitespace:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:set list
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Step 1. Tell VIM what the the current tabsize is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:set tabstop=2      &quot; Tab size is 2 spaces
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Step 2. Convert spaces to real tabs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:set noexpandtab    &quot; Use real tab instead of space
:retab!             &quot; Replace all space-tabs with real tabs
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Step 3. Convert real tabs back to spaces, using tabsize 4&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:set expandtab      &quot; User spaces instead ot tab
:set tabstop=4      &quot; 4 spaces for each tab
:retab              &quot; Reformat using new tabbing policy
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It's possible to get all this on one line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:set ts=2 noet | retab! | set et ts=4 | retab
&lt;/code&gt;&lt;/pre&gt;
</content>
 </entry>
 
 <entry>
   <title>Le Test</title>
   <link href="http://ppanyukov.github.com/2011/06/11/le-test.html"/>
   <updated>2011-06-11T00:00:00-07:00</updated>
   <id>http://ppanyukov.github.com/2011/06/11/le-test</id>
   <content type="html">&lt;h1&gt;Test&lt;/h1&gt;

&lt;h2&gt;Sub-heading&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Item 1&lt;/li&gt;
&lt;li&gt;Item 2&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Why is the code below highlighted as a &lt;em&gt;comment&lt;/em&gt;?&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;n&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Program&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Hello, World&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
 </entry>
 
 <entry>
   <title>Esoteric languages</title>
   <link href="http://ppanyukov.github.com/2011/06/10/le-lingo.html"/>
   <updated>2011-06-10T00:00:00-07:00</updated>
   <id>http://ppanyukov.github.com/2011/06/10/le-lingo</id>
   <content type="html">&lt;h1&gt;Esoteric languages&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Brainfuck&quot;&gt;brainfuck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/LOLCODE&quot;&gt;LOLCODE&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;brainfuck&lt;/h2&gt;

&lt;p&gt;The following program prints &quot;Hello World!&quot; and a newline to the screen:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    +++++ +++++             initialize counter (cell #0) to 10
    [                       use loop to set the next four cells to 70/100/30/10
        &amp;gt; +++++ ++              add  7 to cell #1
        &amp;gt; +++++ +++++           add 10 to cell #2 
        &amp;gt; +++                   add  3 to cell #3
        &amp;gt; +                     add  1 to cell #4
        &amp;lt;&amp;lt;&amp;lt;&amp;lt; -                  decrement counter (cell #0)
    ]                   
    &amp;gt; ++ .                  print 'H'
    &amp;gt; + .                   print 'e'
    +++++ ++ .              print 'l'
    .                       print 'l'
    +++ .                   print 'o'
    &amp;gt; ++ .                  print ' '
    &amp;lt;&amp;lt; +++++ +++++ +++++ .  print 'W'
    &amp;gt; .                     print 'o'
    +++ .                   print 'r'
    ----- - .               print 'l'
    ----- --- .             print 'd'
    &amp;gt; + .                   print '!'
    &amp;gt; .                     print '\n'
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;LOLCODE&lt;/h2&gt;

&lt;h3&gt;Example 1&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;    HAI
    CAN HAS STDIO?
    VISIBLE &quot;HAI WORLD!&quot;
    KTHXBYE
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Example 2&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;    HAI CAN HAS STDIO?
    PLZ OPEN FILE &quot;LOLCATS.TXT&quot;?
        AWSUM THX
            VISIBLE FILE
        O NOES
            INVISIBLE &quot;ERROR!&quot;
    KTHXBYE
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Example 3&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;    HAI
    CAN HAS STDIO?
    I HAS A VAR
    IM IN YR LOOP
       UP VAR!!1
       VISIBLE VAR
       IZ VAR BIGGER THAN 10? KTHX
    IM OUTTA YR LOOP
    KTHXBYE
&lt;/code&gt;&lt;/pre&gt;
</content>
 </entry>
 
 
</feed>
