tag:blogger.com,1999:blog-292732082024-03-13T08:34:08.907+01:00Hawk's blogVincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.comBlogger15125tag:blogger.com,1999:blog-29273208.post-27657208544795585122016-07-25T21:51:00.000+01:002016-07-25T22:11:20.950+01:00Haskell: How (not) to Overload Type Classes <div style="color: #444444; font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; font-size: 16px; line-height: 24px; margin-bottom: 1em; margin-top: 1em;">
After studying haskell as a hobby for some time now, I'm still "thinking OOP"... In particular I still don't find myself comfortable with Type Classes.</div>
<h2 style="border-bottom-color: silver; border-bottom-style: solid; border-bottom-width: 1px; color: #111111; font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; font-size: 2em; font-weight: normal; line-height: 1em; padding-bottom: 5px;">
Extending Type Classes</h2>
<div style="color: #444444; font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; font-size: 16px; line-height: 24px; margin-bottom: 1em; margin-top: 1em;">
Every time I use them I "feel" the need to write a Type Class that extends another one (as if they where c++ classes). But if you want to extend a Type Class you just need a plain function. Like in:</div>
<pre style="background-color: #f8f8f8; border-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 0.94em; line-height: 24px; padding: 5px; white-space: pre-wrap; word-wrap: break-word;"><code style="background: transparent !important; border-radius: 3px; border: 0px !important; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 0.94em; line-height: 1.3em; padding: 0px 3px;">class T1 a where
m1 :: a -> Int
doubleM1 :: (T1 a) => a -> Int
doubleM1 x = 2 * m1 x
</code></pre>
<div style="color: #444444; font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; font-size: 16px; line-height: 24px; margin-bottom: 1em; margin-top: 1em;">
Of course if you can alter the Type Class definition itself you can add doubleM1' to the Type Class itself like in:</div>
<pre style="background-color: #f8f8f8; border-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 0.94em; line-height: 24px; padding: 5px; white-space: pre-wrap; word-wrap: break-word;"><code style="background: transparent !important; border-radius: 3px; border: 0px !important; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 0.94em; line-height: 1.3em; padding: 0px 3px;">class T1 a where
m1 :: a -> Int
doubleM1' :: a -> Int
doubleM1' x = 2 * m1 x
</code></pre>
<div style="color: #444444; font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; font-size: 16px; line-height: 24px; margin-bottom: 1em; margin-top: 1em;">
This second form is more powerful because you can write different implementations for different instances, if so you desire. That is not always a good thing, see:</div>
<pre style="background-color: #f8f8f8; border-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 0.94em; line-height: 24px; padding: 5px; white-space: pre-wrap; word-wrap: break-word;"><code style="background: transparent !important; border-radius: 3px; border: 0px !important; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 0.94em; line-height: 1.3em; padding: 0px 3px;">instance T1 Double where
doubleM1' x = 3 * m1 x
m1 = round
</code></pre>
<h2 style="border-bottom-color: silver; border-bottom-style: solid; border-bottom-width: 1px; color: #111111; font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; font-size: 2em; font-weight: normal; line-height: 1em; padding-bottom: 5px;">
My Question</h2>
<div style="color: #444444; font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; font-size: 16px; line-height: 24px; margin-bottom: 1em; margin-top: 1em;">
Suppose I have two Type Classes (e.g. they are not not my own Type Classes i.e. I can't modify them)</div>
<pre style="background-color: #f8f8f8; border-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 0.94em; line-height: 24px; padding: 5px; white-space: pre-wrap; word-wrap: break-word;"><code style="background: transparent !important; border-radius: 3px; border: 0px !important; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 0.94em; line-height: 1.3em; padding: 0px 3px;">class T1 a where
m1 :: a -> Int
class T2 a where
m2 :: a -> Int
</code></pre>
<div style="color: #444444; font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; font-size: 16px; line-height: 24px; margin-bottom: 1em; margin-top: 1em;">
Can I write a Type Class member (or a plain function) that accepts any instance of T1 or T2 and gives back an Int? For instance like in:</div>
<pre style="background-color: #f8f8f8; border-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 0.94em; line-height: 24px; padding: 5px; white-space: pre-wrap; word-wrap: break-word;"><code style="background: transparent !important; border-radius: 3px; border: 0px !important; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 0.94em; line-height: 1.3em; padding: 0px 3px;">class T a where
m :: => a -> Int
instance T AnyTypeThatHasAnInstanceForT1 where
m = m1
instance T AnyTypeThatHasAnInstanceForT2 where
m = m2
</code></pre>
<div style="color: #444444; font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; font-size: 16px; line-height: 24px; margin-bottom: 1em; margin-top: 1em;">
I think my OOP trained brain wants to use overloading in order to <strong>avoid writing all my instances twice</strong>. What is an idiomatic haskell way of solving such problem?</div>
Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com0tag:blogger.com,1999:blog-29273208.post-79086538542581177392010-10-18T21:14:00.002+01:002010-10-18T21:28:34.532+01:00<span class="Apple-style-span" style="font-size: x-large;">NetwokManager, <span class="Apple-style-span" >resolv.conf</span> & {k,edu,}ubuntu maverick 10.10:</span><div><span class="Apple-style-span" style="font-size: large;">how to tell nm that it must not kill your resolv.conf dns settings</span></div><div><span class="Apple-style-span" style="font-size: medium;"><br /></span></div><div><span class="Apple-style-span" style="font-size: medium;">The problem I'm trying to solve is NetworkManager always overwriting <span class="Apple-style-span" >/etc/resolv.conf</span> at each reboot, regardless of your <span class="Apple-style-span" >/etc/neworking/interfaces</span> file beeing present and setup.</span></div><div><span class="Apple-style-span" style="font-size: medium;"><br /></span></div><div><span class="Apple-style-span" style="font-size: medium;">The problem is quite easy to solve, but I could not find a source of info on the net on how to do it.</span></div><div><span class="Apple-style-span" style="font-size: medium;">Even the official docs make no (eveident) mention to this. So... </span></div><div><span class="Apple-style-span" style="font-size: medium;"><br /></span></div><div><span class="Apple-style-span" style="font-size: medium;">Basically ubuntu is setup to use NM, but the config also tells NM not to manage the interfaces in <span class="Apple-style-span" >/etc/neworking/interfaces</span>. The problem is that, by default, NM clears your /etc/resolv.conf on startup and in <span class="Apple-style-span" >/etc/neworking/interface</span>s there is usually no info to recreate it. </span></div><div><span class="Apple-style-span" style="font-size: medium;"><br /></span></div><div><span class="Apple-style-span" style="font-size: medium;">The fix is just to tell NetworkManager to setup the network in boot using info from the <span class="Apple-style-span" >/etc/neworking/interfaces</span>, plus adding dns info to that file</span></div><div><span class="Apple-style-span" style="font-size: medium;"><br /></span></div><div><span class="Apple-style-span" style="font-size: medium;">In <span class="Apple-style-span" >/etc/NetworkManager/nm-system-settings.conf</span> make sure that you have</span></div><div><span class="Apple-style-span" style="font-size: medium;"><div><span class="Apple-style-span" >[ifupdown]</span></div><div><span class="Apple-style-span" >managed=true</span></div><div><br /></div><div>then in <span class="Apple-style-span" >/etc/neworking/interface</span>s use something like</div><div><div><span class="Apple-style-span" >iface eth0 inet static</span></div><div><span class="Apple-style-span" > address 192.168.1.1</span></div><div><span class="Apple-style-span" > netmask 255.255.255.0</span></div><div><span class="Apple-style-span" > gateway 192.168.1.254</span></div><div><span class="Apple-style-span" > dns-nameservers 8.8.8.8 8.8.4.4</span></div><div><span class="Apple-style-span" > dns-search homelinux.org</span></div></div><div><br /></div><div><br /></div></span></div>Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com0tag:blogger.com,1999:blog-29273208.post-24876474930772252042010-06-13T09:32:00.000+01:002010-06-13T10:02:37.886+01:00<p><span class="Apple-style-span" style="font-size: x-large;">Sony<br /> Vaio VPCZ11X9E, no keyboard/touchpad on_boot or after<br /> suspend/hibernate</span><br /><span class="Apple-style-span" style="font-size: 15.9722px; ">As</span><span class="Apple-style-span" style="font-size: 15.9722px; "><span class="Apple-style-span" style="font-size:medium;">described </span><a href="http://questier.com/2010/04/26/ubuntu-10-4-lucid-lynx-on-sony-vaio-vpcz11x9e/">here</a> </span><span class="Apple-style-span" style="font-size: 15.9722px; ">we must add <span class="Apple-style-span" style="font-family:'courier new';"><b>i8042.nopnp</b></span> to </span><span class="Apple-style-span" style="font-size: 15.9722px; ">the kernel boot parameters in order to use the touchpad at all. </span><span class="Apple-style-span" style="font-size: 15.9722px; ">Anyhow it sometimes happens that you reboot or suspend/hibernate </span><span class="Apple-style-span" style="font-size: 15.9722px; ">and end up without mouse and keyboard. Up to today I always had </span><span class="Apple-style-span" style="font-size: 15.9722px; ">to hard power off the machine, i.e. holding down the power </span><span class="Apple-style-span" style="font-size: 15.9722px; ">button. Even if this only happens about once every 10 reboots, it </span><span class="Apple-style-span" style="font-size: 15.9722px; ">is really annoying, so today I attached an usb keyboard to the </span><span class="Apple-style-span" style="font-size: 15.9722px; ">machine and started investigating.</span></p> <div>I discovered that just reloading the <span class="Apple-style-span" style="font-family:'courier new';"><b>psmouse</b></span> module does the trick of bringing<br /> both the keyboard and the mouse back to life.</div><br /> <div>In order to make this automatic I added a couple of scripts to<br /> my system.</div><br /> <div>The first one goes into <span class="Apple-style-span" style="font-family:'courier new';"><b>/etc/pm/sleep.d/99i8042</b></span><span class="Apple-style-span" style="font-family:'courier new';"><pre>#!/bin/sh<br /><br />case "$1" in<br /> suspend|hybernate)<br /> modprobe -r psmouse<br /> ;;<br /><br /><br /> thaw|resume)<br /> modprobe psmouse<br /> ;;<br />esac</pre></span></div> and the other one, to be saved as <span class="Apple-style-span" style="font-family:'courier new';"><b>/etc/init/fix_touchpad.conf</b> is <pre># reload the psmouse module<br /><br />description "Reload the psmouse driver because the buggy i8042 could mess it up after boot"<br />author "Vincenzo Di Massa <hawk.it@tiscali.it>"<br /><br />start on starting-dm<br />task<br />script<br /> modprobe -r psmouse<br /> sleep 1<br /> modprobe psmouse<br />end script<br /> <pre><br /></pre></pre></span>Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com0tag:blogger.com,1999:blog-29273208.post-7055385895413316692010-06-05T08:23:00.011+01:002010-06-13T08:58:58.184+01:00<span class="Apple-style-span" style="font-size: large;">Ubuntu lucid lynx 10.04 on the sony vaio core i7 2010 VPCZ11Z9E</span><div><span class="Apple-style-span" style="font-size: large;">switching the intel and nvidia cards<br /></span><br /><div>First of all read <a href="http://questier.com/2010/04/26/ubuntu-10-4-lucid-lynx-on-sony-vaio-vpcz11x9e/">http://questier.com/2010/04/26/ubuntu-10-4-lucid-lynx-on-sony-vaio-vpcz11x9e/</a><br /><br />To get suspend to ram working when using the intel ** card add<br /><div><span class="Apple-style-span" style="font-family:'courier new';"><pre>ADD_PARAMETERS="--quirk-test --quirk-s3-bios --quirk-s3-mode"</pre></span><br /></div> to /etc/pm/config.d/default (which does not exist by default) and install uswsusp.<br /><br />To make the nvidia card working I used the the trick described above... I then made it work automatically like this:<br />1) set grub to automatically boot from the 2.6.32 kernel<br />2) create a script in /usr/local/bin/force_reboot which just calls /sbin/reboot -f<br />3) add a grub entry which boots the 2.6.31-20 kernel and add it the parameter init=/usr/local/bin/force_reboot</div><div>4) create the config file for nvidia and intel as /etc/X11/xorg.conf.{intel,nvidia}<br />5) add a boot time service (see the script below) which switches the 2 cards config (must change the xorg.conf file and setup ld.so making it able to find mesa/nvidia libglx.so versions)<br /><br /><span class="Apple-style-span" style="font-family:'courier new';"><pre># goes into /etc/init/vga_card_switch.conf<br /># setup the proper video-card<br /><br />description "Detect wich videocard to use and st it up"<br />author "Vincenzo Di Massa <hawk.it@tiscali.it>"<br /><br />start on filesystem<br />#console output<br />task<br />script<br />FOUND=intel<br />PCIID=$(dmesg | awk '/Boot video device/ {print $4}')<br />PCIID=${PCIID%:*}<br />PCIID=${PCIID#*:}<br />lspci | grep $PCIID | grep -q nVidia && FOUND=nvidia<br />if [ "$FOUND" = "nvidia" ]; then<br />ln -sf /etc/X11/xorg.conf.nvidia /etc/X11/xorg.conf<br />update-alternatives --set gl_conf /usr/lib/nvidia-current/ld.so.conf<br />else<br />ln -sf /etc/X11/xorg.conf.intel /etc/X11/xorg.conf<br />update-alternatives --set gl_conf /usr/lib/mesa/ld.so.conf<br />fi<br />exec ldconfig<br />end script<br /></pre><br /></span><br /><br /><br /><br />** to get intel and nvidia working properly you must install grub, as described above and remove the nomodeset option from the boot parameters</div><div><hawk.it@tiscali.it><br /></hawk.it@tiscali.it></div><div><hawk.it@tiscali.it>Of course all of the above is hackish.</hawk.it@tiscali.it></div></div>Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com4tag:blogger.com,1999:blog-29273208.post-25204765920305353442010-03-08T10:50:00.005+01:002010-03-08T11:02:03.889+01:00<span class="Apple-style-span" style="font-size: x-large;">Exceptions</span><div><span class="Apple-style-span" style="font-size:x-large;"><br /></span></div>Today I discovered that exceptions are great: have you ever realized that the semantic of an exception includes the information about what is the expected branch to take?<br />This means that exceptions (plus a smart compiler) could make your code run faster, in average, than using an ancient language where you must use if-statements.<br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLdlWNRF1Q7aYlAi0N-Blh3vh9AJ0XmrFNMNddl827ONau4qj60YKRuTvwP7L30U_WgtdZ-PnFY1IHRMLmGVOZ-K1SRYgGsUePpvC-9R7vUSEb4UR5djEzq0MDy6ev_TuEOjq0vQ/s1600-h/road+sign.jpg"><img style="cursor:pointer; cursor:hand;width: 250px; height: 320px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLdlWNRF1Q7aYlAi0N-Blh3vh9AJ0XmrFNMNddl827ONau4qj60YKRuTvwP7L30U_WgtdZ-PnFY1IHRMLmGVOZ-K1SRYgGsUePpvC-9R7vUSEb4UR5djEzq0MDy6ev_TuEOjq0vQ/s320/road+sign.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5446200407361846706" /></a><br /><div><br />Maybe this is obvious to most of you, but I'm happy I just "discovered" this.</div>Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com0tag:blogger.com,1999:blog-29273208.post-45621372436776642502010-02-27T16:19:00.008+01:002010-02-27T17:31:00.595+01:00<div><span class="Apple-style-span" style="font-size:x-large;">Speculations about Mobile OSes.</span></div><div><a href="http://thenokiablog.com/2010/02/15/symbian3-unveiled-video/">Here</a> we get a preview on the look of the new Symbian^3 (and Symbian^4 is already ongoing).</div><div><br /></div><div>The iPhone has 15% market share, Symbian has about 40% but it is decreasing.</div><div>It is true that Nokia took 4 long years to understand why it was loosing marker shares, but today it looks like the european phone-maker is moving toward making the gap in UI-design from competitor's phone slimmer.</div><div><br /></div><object width="500" height="300"><param name="movie" value="http://www.youtube.com/v/rdGyZYrix9g&hl=en_US&fs=1&rel=0&color1=0x006699&color2=0x54abd6"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/rdGyZYrix9g&hl=en_US&fs=1&rel=0&color1=0x006699&color2=0x54abd6" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="500" height="300"></embed></object><div><br /></div><div><br /></div><div>Now I get curious: suppose Symbian phones reach GUI feature/beautifulness parity with competitors, will they also be cheaper because of Symbian's low footprint on resources usage?</div><div>Will Symbian phones be lighter and have longer lasting batteries? Will Qt make them more easy/profitable to develop?</div><div><br /></div><div>Suppose the answer to the above question is "yes", will Apple and Google be forced to develop even better GUIs exploiting new interaction design concepts and ideas in order to keep growing on the market? What beautiful interfaces will Nokia's competitor develop if Symbian^3 (and ^4) manages to keep up to par with todays iPhone and Android?</div><div><br /></div><div>This mobile evolution is getting me very curious: since I was born I've never seen so many operating systems fight on the same market... It is wonderfully interesting and it feels so good to know that all of this is possible because of the growth of the Free Software movement :-)</div>Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com0tag:blogger.com,1999:blog-29273208.post-91711744733534482652009-10-31T15:08:00.028+01:002009-11-04T20:58:20.633+01:00<div><span class="Apple-style-span" style="font-size:x-large;">How to embed OpenOffice.org ODP (or office ppt) files as flash content on your webpages (including controls).</span><span class="Apple-style-span" style="font-size:medium;"><br /><span class="Apple-style-span" style="font-family:arial;"><br />I spent some time working on this. It would have been nice to avoid "inventing" this stuff on my own, so I'm going to share it here for others to read.<br />My purpose was to convert my presentations to flash and then to embed them int my webpages along with nice controls. Something similar to what slideshare.com allows, but:you can do it on your websitethe slides are converted to flash using a nice and small script (which uses openoffice)First of all you need to convert your odp (or ppt or anything openoffice can read) into flash: to achieve this just open the file in openoffice and export as flash (really! openoffice can do that out of the box).<br />Now you can put your files on the web and serve them. If you are happy you are done :-)<br />If you would like to embed the flash content into the webpage you need to write something like the following into your webpage:<br /></span></span><pre><br /><div class="slides"><br /><object<br /> type="application/x-shockwave-flash"<br /> width="600"<br /> height="450"<br /> data="<?php echo $filename; ?>"<br /> id="<?php echo $filename; ?>"<br /> ><br /> <param<br /> name="<?php echo $filename; ?>"<br /> value="<?php echo $filename; ?>"<br /> ><br /></object><br /></div><br /></pre><span class="Apple-style-span" style="font-size:medium;">Of course <?php echo $filename; ?> must be replaced with your filename if you are not using php :-)<br />Now your slides are embedded but you can't control how they are played. Let's add some controls. First of all you need some javascript functions: <pre><br /> function RewindSlides(slides)<br /> {<br /> var text = document.getElementById("Page_"+slides);<br /> text.value = 1;<br /> SlideGoto(slides);<br /> }<br /><br /> function SlidePrev(slides)<br /> {<br /> SlideMove(slides, -1);<br /> }<br /><br /> function SlideNext(slides)<br /> {<br /> SlideMove(slides, 1);<br /> }<br /><br /> function SlideMove(slides, movement)<br /> {<br /> var flashSlide=document.getElementById(slides);<br /> var text = document.getElementById("Page_"+slides);<br /> text.value = parseInt(text.value)+movement;<br /> SlideGoto(slides);<br /> }<br /><br /> function SlideGoto(slides)<br /> {<br /> var flashSlide=document.getElementById(slides);<br /> var totalFrames = flashSlide.TotalFrames();<br /><br /> var text = document.getElementById("Page_"+slides);<br /> var n = text.value;<br /><br /> if (n<1)<br /> n=1;<br /> else if (n>totalFrames/2)<br /> n = parseInt(totalFrames/2);<br /> text.value = n;<br /> <br /> if (n*2 >= totalFrames - 1 )<br /> flashSlide.GotoFrame(totalFrames - 5);<br /> else if (n<2)><br /><br /><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:medium;">And then you can just out the following controls into your HTML: </span></span><pre><br /> <input type="button" value="Rewind" name="Rewind" <br /> onClick="RewindSlides('<?php echo $filename; ?>');"><br /> <input type="button" value="Prev" name="Prev" <br /> onClick="SlidePrev('<?php echo $filename; ?>');"><br /> <input type="button" value="Next" name="Next" <br /> onClick="SlideNext('<?php echo $filename; ?>');"><br /> <input type="button" value="Goto" name="Goto" <br /> onClick="SlideGoto('<?php echo $filename; ?>');"><br /> <input type="text" <br /> value="1" name="Page_<?php echo $filename; ?>" <br /> id="Page_<?php echo $filename; ?>"><br /></pre><br /><br /><span class="Apple-style-span" style="font-size:medium;"><span class="Apple-style-span" style="font-family:arial;">The end result can be shown on <a href="http://www.dii.unisi.it/%7Edimassa/Didattica/2009/Informatica/">my page</a>:<br /></span></span><br /><br /></pre></span></div>Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com0tag:blogger.com,1999:blog-29273208.post-44667828502973886632008-12-09T17:27:00.003+01:002008-12-09T18:33:13.257+01:00<span style="font-size:130%;">After a long time... here it is a </span><span style="font-weight: bold;font-size:130%;" >New Post<br /><br /></span>Since Google gave us <a href="http://www.google.com/friendconnect/">friend connect</a>, I felt I had to start using it from the very beginning.<br />I have just invited some friends to join my blog but... the last post was from Summer 2006: I guess they would not be pleased to be invited to read such old info, so I'm writing this very short blog post.<br /><br />Who knows... maybe I could start blogging if I have enough fun!<br />The topic for new posts will probably still be <a href="http://www.kde.org/">KDE4</a>: I just love it.Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com1tag:blogger.com,1999:blog-29273208.post-1157403067999398112006-09-04T21:20:00.000+01:002006-09-04T22:05:15.096+01:00<span style="font-size:180%;">Phonon-NMM Status after SoC.</span><br /><br />Wow. After months of coding together with Marco and Matthias, I could finally see the results of my efforts.<br />The code is on the <a href="http://websvn.kde.org/trunk/KDE/kdemultimedia/phonon-nmm/">KDE4 svn</a>.<br />I could not add many new features: my main goal has been to make the backend usable in everyday use. I proof tested it to work on corner case events (short media file, multiple files played at the same time, file played to multiple AudioOutput, user pressing commands at random...) and made sure it works in a predictable manner without crashing.<br />I also added to the backend the ability to play files from protocols NMM does not understand (like smb:// tar:// media:// fish:// and all the ones KIO can read). I did that implementing the Phonon ByteStream protocol as an NMM plugin. That plugin is not Phonon specific: developers can use the NMM::ByteStreamNode plugin to push theyr own data into an NMM flow graph.<br />Apart from that I did a complete refactor of GraphHnadler, which now has almost the same API (just some bits added) but is internally coded following the Object Oriented paradigm. The immediate benefit of the refactoring is the ability of adding multiple sinks to a a branch. The code is also more readable.<br />Talking to my mentors has been very instructive: I have learnt theyr code so deeply that I could suggest modification in both Phonon (stop/buffering functionality) and NMM (GraphHandler, progress update).<br /><br />It has been fun working with NMM and Phonon (kde) developers. NMM and Phonon are both implementations of a very smart idea: I have no doubt those ideas will have success even is the projects are still in a quite early stage of adoption. I plan to go on coding with them.Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com0tag:blogger.com,1999:blog-29273208.post-1155461947636287982006-08-13T09:54:00.000+01:002006-08-13T10:39:07.646+01:00<span style="font-size:180%;">Bugs, bugs and ... bugs!</span><br /><br />During the last days I did not much progress on implementing new functionality.<br />My new schedule is to...<br />1) fix the backend to make <span style="font-family: courier new;">ByteStream</span> work<br />2) allow each branch of <span style="font-family: courier new;">GraphHandler</span> to have more sinks connected<br />3) port fub's gui config app to dbus<br />4) make kcm work (this involves frontend work as well)<br /><br />The reason for my slow process have been bugs.<br />First I had to figure out that the Phonon <span style="font-family: courier new;">ByteStream</span>/<span style="font-family: courier new;">MediaObject</span> frontend states had problems... the KIO object setup was done only in <span style="font-family: courier new;">setUrl().</span>.. Matthias fixed it in a minute.<br />Then I found corner cases where NMM/Phonon/KIO cooperation becomes difficolt: that is when the kio object finishes sending data before phonon-nmm has finished its initialization (happens when the media file is really short). Also this involved both backend and frontend changes.<br />Then the other day I updated dbus from CVS and... bang!!!! Someone on 8/8/06 has introducd a really nice in configure in. It took an entire afternoon to make dbus work again (I'm not an autotools expert, I had to learn-try-fail-learn_more-...<br />Then I found a nice bad bug in NMM <span style="font-family: courier new;">MPEGDecodeNode.</span> track_size is not initialized and track_duration is computed from it. If you play a live stream (for example an mp3 file streamed from <span style="font-family: courier new;">Phonon::Bytestream</span>) track_duration can't be told... a random value was inserted into the <span style="font-family: courier new;">CEvent</span>. After fixing it I found that if track_duration is 0 progress events are not emitted; I can't see the reason for this: you can have progress even if you don't know where you are inside the file.<br />I see from vlagrind output that there are some other uninitialized variblas on which a control statement depends on... but I was not able to fix those jet.<br /><br />Those were just the things I was able to fix!<br />I still have some bugs. The big problem working on phonon-nmm is that you have to work on bleeding edge code (kdelibs, KIO, Phonon, NMM -should be the more stable here-, Qt4, dbus) and you have to do a lto of tricks to make them work. I have spend almost a week in the beginning writing a script to set up all the environment vars and daemons (I was inspired by a script sent to me by Matthias).<br />The hardest problem is that Qt4/KDE4 code confuses debuggers and memory checkers like gdb and valgrind! So you have to fill the code with debug statements and recompile and... well, when you type make in the Qt, NMM, or kdelibs source trees... you'll heat your CPU for quite a lot of time! That is way icecream (<span style="font-family: courier new;">icecc</span>) comes in the story: this tool allows you to easily cluster your machines into a renderfarm. It is one of the pieces of code in the world, it saves so many compile time! But... a tiny little bug in the kubuntu package I had made me mad... so I had compile the latest svn version, find another little bug ,report it to the icecream main developer (coolo on #kde4-devel) and wait (minutes really) for the fix.<br />Back to phonon-nmm my favourite bug is... <span style="font-weight: bold;">UNKOWN</span>! Maybe it is more than one bug.<br />The symptoms are random. Sometimes kdeinit can't unload phonon-nmm because of NMM not releasing the soundcard device. Sometimes in <span style="font-family: courier new;">ByteStreamNode</span> I push_back into a list 23 <span style="font-family: courier new;">Buffers*</span> and then I iterate on 23 elements... Ah, that is ok, I know... buth the size of the first element is the sum of the others :-)<br />I'm working on this bug right now. I hope to resolve this, but ATM I really don't know how to understand where it comes from.<br /><br />I must be crazy anyway. Because...<br /><br />I'm having fun!!!!!!Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com0tag:blogger.com,1999:blog-29273208.post-1152878366239792992006-07-14T12:42:00.000+01:002006-07-14T12:59:26.246+01:00<span style="font-size:180%;">Bugs: no progress</span><br /><br />During the last days I had problems with compiling kdelibs4. Matthias has updated phonon implementation in kdelibs4_snapshot, so I had to catch up whith that new code and install the new snapshot.<br />KDE4 will ship with Qt 4.2.x: for this reason the KDE4 svn qt-copy has been updated to the new 4.2.0. This version is now required to install KDE4 libs.<br />KDE svn hosts a copy of Qt where patches not already accepted by Qt developers are availabele: qt-copy. qt-copy has a patches subdir and an <span style="font-family: courier new;">apply_patches</span> script that applies them and keeps track of already applied patches.<br />Well things changed and the <span style="font-family: courier new;">apply_patches</span> script has become buggy: some patches marked as already applied are not applied... booom. I had to figure out what the prbolem was, contacted David, and finally applied a patch to fix that script.<br />The good news is that (after recompiling Qt, kdelibs & C.o.) a bug that prevented <span style="font-family: courier new;">ByteStream</span> from working has vanished! Great! It must have been a cmake cuased bug, it was a nasty bug that made this pointer become 0x0 after a simple member function call... I was going mad figuring out where that bug was coming from and spent quite a lot of time on it! Luckily it is gone now!<br />My next step will be <span style="font-family: courier new;">AudioOutput.</span><br />I'm really looking forward to make config-proxy work again using dbus.Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com0tag:blogger.com,1999:blog-29273208.post-1151859683531432502006-07-02T17:17:00.000+01:002006-07-02T18:01:23.560+01:00<span style="font-size:180%;">Yay! Some fast progress now!</span><br /><br />After resolving the kdelibs problems I started trying to improve the already (somehow) working <span style="font-family:courier new;">ByteStream.</span> One of the first things I wanted to do was to reconsider the way time reporting is done in the backend: even if NMM can sent time progrss events, the backend was using an internal timer to do time reporting. Talking to My mentors and to fub (Bernard) they all agreed that a nice thing to do would have been to use the NMM events to signal time progress. Well I was just looking at it and... done. It was indeed quite easy. And I think it could have been done even in an easier way!<br /><br />In order to do it I:<br />Moved the callback functions from <span style="font-family:courier new;">MediaObject</span> to <span style="font-family:courier new;">AbstreactMediaProducer</span> (so they will be usefull in <span style="font-family:courier new;">ByteStream</span> too one day)<br />Added an <span style="font-family:courier new;">Phonon::AudioPath::insertInto(NMM::GraphHandler)</span> that inserts the <span style="font-family:courier new;">AudioPath</span>'s branch into the <span style="font-family:courier new;">GraphHandler</span>. This is called from <span style="font-family:courier new;">internal_addBranch</span> in <span style="font-family:courier new;">Phonon::AbstreactMediaProducer</span>.<br />Made the <span style="font-family:courier new;">Phonon::AudioOutput</span> create a sink Node in the constructor (it will use info from <span style="font-family:courier new;">kcm</span> to decide the node type) and enabled <span style="font-family:courier new;">setTimeProgress</span> events from that node.<br />Made <span style="font-family:courier new;">Phonon::AudioPath</span> add its <span style="font-family:courier new;">Phonon::AudioOutput</span>'s sink (already created) Node to the <span style="font-family:courier new;">NMM::GraphHandler</span>.<br /><br />This changes make the backed architecture reflect the <span style="font-family:courier new;">NMM::GraphHandler</span> architecture better : <span style="font-family:courier new;">Phonon::AudioOutput</span> wraps a sink Node, <span style="font-family:courier new;">Phonon::AudioPath</span> wraps a brach in <span style="font-family:courier new;">NMM::GraphHandler</span>, and <span style="font-family:courier new;">Phonon::AbstreactMediaProducer</span> wraps the wole <span style="font-family:courier new;">Phonon::AbstreactMediaProducer</span>.<br /><br />Thanks to this changes (that enable the sink node to send progrss events) it was easy to attach those events to callbacks in <span style="font-family:courier new;">Phonon::AbstreactMediaProducer</span> that report the event to KDE using QT signals.Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com0tag:blogger.com,1999:blog-29273208.post-1151533254292339212006-06-28T22:01:00.000+01:002006-06-28T23:48:34.593+01:00<span style="font-size:180%;">Problems Resolved: Bugs and my understanding of NMM.</span><br /><br /><span style="font-size:130%;">Part I kde bug.</span><br />During the last 2 weeks I had to fight against a KDE4 (kdelibs) bug: I was no more able to build a proper KDE System Configuration Cache ksycoca. Everything was set up according to the docs, the debug output of kde apps was not spotting any problem, some components were even able to run... but I could not use kcmshell (the KDE control center application and framework).<br />The problem with ksycoca was triggered by the presence of the <span style="font-family:courier new;">/etc/xdg/menus/applications.menu</span> file. That file is installed by the gnome-menus package on kubuntu dapper (the distro I'm using). The effect of the the bug is that kbuildsycoca is no more able to find the proper KDE4 .menu files after processing <span style="font-family:courier new;">/etc/xdg/menus/applications.menu</span>.<br />Finding that out was really difficolt (I'd never been able to do that on my own, Vir and dfaure helped a lot on freenode #phonon and #kde4-devel): first we had to find out that the problem was ksycoca related, then we had to figure out that this problem was caused by the presence of <span style="font-family:courier new;">/etc/xdg/menus/applications.menu</span> even if kbuildsycoca does not print a single warning or error when analyzing that file.<br /><br /><span style="font-size:130%;">Part II: ByteStreamNode properly coded.</span><br />My prevoius attempt to write the <span style="font-family:courier new;">ByteStreamNode</span> was succesfull in practice, but it was coded without compliance to the NMM architecture (I was not skilled enought).<br />Thanks to the the help of Marco (my menthor) I finally understood how to pass data to remote running nodes using NMM proxies and interface. NMM is a so powerfull architecture that understanding all of it at a time is hard even if the docs are very usefull and cover most aspect.<br />Using sample code that Marco sent me I could code a proper <span style="font-family:courier new;">NMM::Interface</span> for ByteStreamNode.<br />The interface is:<br /><span style="font-family:courier new;">module NMM{</span><br /><span style="font-family:courier new;"> interface IByteStreamNode {</span><br /><span style="font-family:courier new;"> void sendBuffer2(in TransferBuffer2 buffer);</span><br /><span style="font-family:courier new;"> int getSize();</span><br /><span style="font-family:courier new;"> int getMaxSize();</span><br /><span style="font-family:courier new;"> };</span><br /><span style="font-family:courier new;">}</span><br /><br />Using ByteStreamNode and its interface IByteStreamNode it is possible to inject arbitrary data from applications into NMM flow graphs. To achieve this the application developer creates the flow graph as described in the NMM documentiation using <span style="font-family:courier new;">NMM::ByteStreamNode</span> as the source node and using its interface to send data to the node. Data sent to the node is buffered into a streamqueue from where <span style="font-family:courier new;">processBuffer</span> (the "main/core" function of NMM nodes) extracts it later. The application can query the current fill size and maximum allowed size of the internal streamqueue using the interface functions <span style="font-family:courier new;">getSize</span> and <span style="font-family:courier new;">getMaxSize</span>.<br /><br />The only cave at for using <span style="font-family:courier new;">ByteStreamNode</span> is that the first chunk of data must be passed to the node (using <span style="font-family:courier new;">sendBuffer2)</span> before <span style="font-family:courier new;">initOutput</span> is called in order to let <span style="font-family:courier new;">initOutput</span> to find data mime-type (using libmagic).<br /><br />The phonon nmm backend uses ByteStreamNode as a fallback when a NMM unsupported protocol is specified in the url to be played. For such urls NMM throws an exception in GraphHandler::stage1 which is catched by Phonon and used to trigger the creation of a Phonon::ByteStream object. That object is responsible for calling GraphHandler::stage1_bs and passing data to the returned IByteStreamNode interface. Another task for Phonon::ByteStream is to suspend and resume the KIO::TransferJob as soon as the ByteStreamNode's internal StreamQueue gets full or empty.<br /><br /><span style="font-size:130%;">Part III: plans</span><br />After all this learning and coding I'm becoming more experienced with both NMM andn Phonon.<br />I thought I would have been able to proceed faster, but KDE4 beeing not mature and NMM beeing a completely new concept to me really slowed me down since now.<br /><br />My next steps will be:<br /><ol><li>Resurrect the config-app<br /></li><li>Implement AudioOutputDevice selection (the interface that let users chose which NMM audio output node to use)</li><li>VolumeControlNode: a software volume slider node</li></ol>One idea I would like to implement is a app/user interface that detects other NMM hosts on the network and shows theyr speakers to the user. Using this is interface it would be possible to use a desktop computer and a laptop computer as a 4 speaker system (-almost- anyone has a laptop and a desktop nowdays).Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com0tag:blogger.com,1999:blog-29273208.post-1149850749553708962006-06-09T11:14:00.000+01:002007-02-08T01:53:55.645+01:00<span style="font-size:180%;">The birth of the ByteStreamNode</span><br /><span style="font-size:150%;">and its problems</span><br /><br />First of all let me explain how Phonon-nmm interaction works.<br />Suppose a KDE4-NMM user whats to play an url, when behind the scenes the following happens:<br /><ul><br /><li>Phonon looks for a Phonon backend (Phonon-NMM in this case) and loads it</li><br /><li>The backend configures its media framework (the backend is the <span style="font-family:courier new;">Phonon::nmm::Backend</span> object, the framework is NMM)</li><br /><li>Phonon creates a <span style="font-family:courier new;">Phonon:nmm::MediaObject</span> and calls its <span style="font-family:courier new;">setUrl()</span>method</li><br /><li>If the setUrl call fails the <span style="font-family:courier new;">MediaObject</span> is destroied and a <span style="font-family:courier new;">Phonon:nmm::ByteStream</span> object is created which receives the raw stream data in a <span style="font-family:courier new;">writeData()</span> callback method (actually a qt-slot) from a KDE4 <span style="font-family:courier new;">KIO::TransferJob</span> instance.<br /></li><br /><li>After an <span style="font-family:courier new;">Phonon::nmm::AbstractMediaProducer</span> subclass, <span style="font-family:courier new;">MediaObject</span> or the <span style="font-family:courier new;">ByteStream</span>, is setup Phonon assumes the media framework is ready to start</li><br /><li>The <span style="font-family:courier new;">AbstractMediaProducer::play</span> method is called which call the media framework playing functionality</li><br /></ul><br />The glue between NMM and Phonon is the <span style="font-family:courier new;">NMM::GraphHandler</span> class. This class is meant for creating flowgraph from an URL and for playing it. If NMM cannot understand the url (maybe because the protocol is not supported by NMM) <span style="font-family:courier new;">GraphHandler</span> throws an exception that Phonon detects (that functionality is in <span style="font-family:courier new;">GraphHandler::stage1()</span> which is called from <span style="font-family:courier new;">MediaObject::setUrl()</span> ). If <span style="font-family:courier new;">stage1()</span> throws any exception, Phonon (in the ByteStream class) calls <span style="font-family:courier new;">GraphHandler::stage1_bs()</span> from the <span style="font-family:courier new;">ByteStream::writeData()</span>.<br />The <span style="font-family:courier new;">writeData()</span> method is responsible for coping the data packets incoming from the running <span style="font-family:courier new;">KIO::TransferJob</span> into a local buffer (actually an <span style="font-family:courier new;">NMM::StreamBuffer</span> instance) and for initaliazing the <span style="font-family:courier new;">GraphHandler</span> by means of calling its <span style="font-family:courier new;">stage1_bs()</span> when the first chunk of stream is available. Basically untill the the <span style="font-family:courier new;">GraphHandler</span> is initialized writeData pushes incoming data into the buffer and tries to initalize <span style="font-family:courier new;">GraphHandler</span> using that growing buffer.<br />The <span style="font-family:courier new;">GraphHandler</span> initialization in <span style="font-family:courier new;">stage1_bs()</span> (whose prototype is <span style="font-family:courier new;">void stage1_bs(NMMApplication& app, StreamQueue* sq))</span> creates a new <span style="font-family:courier new;">ByteStreamNode</span> from the rgistry and registers the sq into the <span style="font-family:courier new;">ByteStreamNode</span>.<br />For that purpose <span style="font-family:courier new;">ByteStreamNode</span> implements the <span style="font-family:courier new;">IByteStreamNode</span> interface which just defines <span style="font-family:courier new;">void setStreamQueue(in int sq)</span>. As you can see this is really an awfull trick I did.<br />That interface should take a <span style="font-family:courier new;">StreamQueue*</span> as input, but I was not able to define it that way (I need input from Marco here). The other alternative would be to create the the <span style="font-family:courier new;">ByteStreamNode</span> from <span style="font-family:courier new;">stage1_bs()</span> without using the registry (and without defining any <span style="font-family:courier new;">IByteStreamNode</span>) and then getting its <span style="font-family:courier new;">INode</span> interface using <span style="font-family:courier new;">getInterface<inode>()</inode></span>; this way the ByteStreamNode could be compiled with <span style="font-family:courier new;">GraphHandler</span>, and not as a plugin. Maybe this is better?<br /><br />Once the <span style="font-family:courier new;">ByteStreamNode</span> is started all it has to do in <span style="font-family:courier new;">processBuffer</span> is to get one buffer from the <span style="font-family:courier new;">streamQueue</span> filled by KIO and return it.<br />The only other functionalty of <span style="font-family:courier new;">ByteStreamNode</span> is stream type finding, done using the first buffer in the registered streamBuffer and passing its data to libmagic.Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com0tag:blogger.com,1999:blog-29273208.post-1149468282083222672006-06-05T01:43:00.000+01:002007-02-08T01:54:45.142+01:00<span style="font-weight: bold;font-size:180%;" >SoC report<br /></span><br />This is the first report about my SoC phonon-nmm project.<br />So far I have studied the Phonon and NMM code, tried to resolve an rtti bug in NMM event handling (my co mentor mkrez fixed it) and I added some functionality into the phonon nmm backend and in the GraphHandler class to support the phonon bytestream KIO data passing interface.<br /><br />At the moment I evolved <span style="font-family:courier new;">NMM::GraphHandler</span> and <span style="font-family:courier new;">Phonon::nmm::ByteStream</span> making them capable of using a <span style="font-family:courier new;">ByteStreamNode</span> (yet to be implemented) to pass data.<br /><br />What I did was to change the <span style="font-family:courier new;">GraphHandler::stage1</span> method to make it able to get an <span style="font-family:courier new;">StreamQueue</span> as optional input. What stage1 now does is to try to detect the media steram format from the <span style="font-family:courier new;">NMM::Buffer</span>s in the <span style="font-family:courier new;">NMM::StreamQueue</span>.In order to do that I added a tiny helper function that uses <span style="font-family:courier new;">libmagic</span> to detect mime type.<br /><br />On the Phonon side I implemented some functionality into <span style="font-family:courier new;">ByteStream<span style="font-family:georgia;">.<br />The ByteStream object tries to initalize the <span style="font-family:courier new;">GraphHandler</span> object as soon as the first data chunck arrives (in the <span style="font-family:courier new;">ByteStream::writeData</span> member). The data to be passed to NMM is inserted into a <span style="font-family:courier new;">StreamQueue</span> object that is registered into the <span style="font-family:courier new;">ByteStyreamNode</span> during <span style="font-family:courier new;">GraphHandler::stage1</span>.<br /></span></span>Vincenzohttp://www.blogger.com/profile/12879490062291392436noreply@blogger.com1