<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wikidot="http://www.wikidot.com/rss-namespace">

	<channel>
		<title>Piotr Gabryjeluk blog</title>
		<link>http://piotrgabryjeluk.wikidot.com</link>
		<description>Blog, photos and developer notes of Piotr Gabryjeluk, one of Wikidot.com developers.</description>
				<copyright></copyright>
		<lastBuildDate>Thu, 12 Mar 2026 19:24:17 +0000</lastBuildDate>
		
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:centos-chroot</guid>
				<title>Centos Chroot</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:centos-chroot</link>
				<description>

&lt;p&gt;Let&#039;s say you want a chroot with CentOS with an older version of the system to test something.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343456&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 12 Dec 2017 19:49:28 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Let's say you want a chroot with CentOS with an older version of the system to test something.</p> <h1><span>Get the minimal root fs</span></h1> <ol> <li>Check out Docker images for CentOS: <a href="https://hub.docker.com/_/centos/">https://hub.docker.com/_/centos/</a></li> <li>Follow the Dockerfile link for the version you're interested in, say 6.6: <a href="https://github.com/CentOS/sig-cloud-instance-images/blob/8911843d9a6cc71aadd81e491f94618aded94f30/docker/Dockerfile">https://github.com/CentOS/sig-cloud-instance-images/blob/8911843d9a6cc71aadd81e491f94618aded94f30/docker/Dockerfile</a></li> <li>Go one level up in GitHub and locate the centos-*.tar.xz file, it's the archive with the mininal rootfs for CentOS: <a href="https://github.com/CentOS/sig-cloud-instance-images/blob/8911843d9a6cc71aadd81e491f94618aded94f30/docker/centos-6.6-20150304_1234-docker.tar.xz">https://github.com/CentOS/sig-cloud-instance-images/blob/8911843d9a6cc71aadd81e491f94618aded94f30/docker/centos-6.6-20150304_1234-docker.tar.xz</a></li> <li>Click the download link</li> </ol> <h1><span>Prepare a directory, unpack the root fs</span></h1> <div class="code"> <pre><code>sudo mkdir -p /mnt/centos-chroot/ # You may need to uncompress the XZ file, but my tar could deal with it, so try yourself: sudo tar -xf /path/to/centos-6.6-20150304_1234-docker.tar.xz # Mount some pseudo filesystems: cd /mnt/centos-chroot/ sudo mount --bind /sys sys sudo mount --bind /dev dev sudo mount -t proc proc proc</code></pre></div> <h1><span>Enter your precious chroot:</span></h1> <div class="code"> <pre><code>sudo chroot /mnt/centos-chroot/ /bin/bash . /etc/environment</code></pre></div> <p>Done!</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343456" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:server-commander</guid>
				<title>Server Commander</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:server-commander</link>
				<description>

&lt;p&gt;Here&#039;s a problem I&#039;d like was already solved:&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343456&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 12 Jul 2017 04:46:37 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Here's a problem I'd like was already solved:</p> <p>Be able to manage and run &quot;tasks&quot; on a Linux server. More specifically:</p> <ul> <li>There should be a WEB interface where: <ul> <li>I could define commands or tasks that the server is capable of doing</li> <li>I could schedule tasks to run at specific times (like cron)</li> </ul> </li> <li>The tasks/commands should be (optionally) parametrized</li> <li>The tasks/commands should be (optionally) stored in GitHub and/or a database</li> <li>The task runs should not overlap with each other (i.e. when the previous run is still in progress don't start the new one) &#8212; configurable</li> <li>The task configuration should include: <ul> <li>the command to run</li> <li>task timeout &#8212; the task should be killed after the specified time</li> <li>environment variables to set for the task</li> <li>max CPU/memory/disk to use (optional)</li> <li>number of times to retry on failure</li> <li>what to do on success and failure &#8212; e-mail, webhook and trigger another task</li> <li>directory to run the command in: I can specify one, or a temporary one is created for each run and cleared after the run</li> <li>user to run the command as: I can specify one, or a temporary user is created for each run and cleared after the run</li> </ul> </li> <li>The task run view should include <ul> <li>colored command output</li> <li>command exit code: OK/FAIL</li> <li>resources used by the task (optional)</li> <li>time the task took, time the task started and ended</li> <li>environment variables</li> <li>link to next/previous run and a button to re-run</li> </ul> </li> <li>The code should be free and open and extremely easy to install</li> <li>There should be an error log in the UI to track all the jobs failures</li> <li>Misconfigured tasks should not take the machine down &#8212; there should be some level of monitoring &#8212; don't start new jobs when load is high or disk is almost full, etc</li> <li>One should be able to have a nice dashboard with selected tasks for easy launching</li> </ul> <p>What I describe here is to some extent already covered by some of the following:</p> <ul> <li>Jenkins <a href="https://jenkins.io/">https://jenkins.io/</a></li> <li>Travis-CI <a href="https://travis-ci.com/">https://travis-ci.com/</a></li> <li>Rundeck <a href="http://rundeck.org/">http://rundeck.org/</a></li> <li>Minicron <a href="https://github.com/jamesrwhite/minicron/">https://github.com/jamesrwhite/minicron/</a></li> </ul> <p>Here's what's wrong with them:</p> <ul> <li>Jenkins' UI is to complicated for simple tasks, also it feel very heavy</li> <li>in Travis-CI you specify the tasks in your code, not in Travis, also it's not software you run locally</li> <li>My experience with Rundeck is it doesn't work out of the box, I could debug it, but I didn't want to, also UI is a bit too complex</li> <li>Minicron is way too simple and (currently) only allows you to run jobs through ssh (not locally)</li> </ul> <p>To reiterate I'd like:</p> <ul> <li>A web UI for cron, that's also</li> <li>a bit like Jenkins in a way you can see the output of each of the command runs</li> <li>and have ability to sandbox the processes it runs</li> <li>looks nice and is easy to install and doesn't require maintenance</li> </ul> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343456" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:how-to-disable-kinetic-scrolling-on-linux</guid>
				<title>How To Disable Kinetic Scrolling On Linux</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:how-to-disable-kinetic-scrolling-on-linux</link>
				<description>

&lt;p&gt;I spent more time than I wished searching for how to disable kinetic scrolling on Linux. Here&#039;s the spell:&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343456&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 14 Feb 2017 04:44:11 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>I spent more time than I wished searching for how to disable kinetic scrolling on Linux. Here's the spell:</p> <div class="code"> <pre><code>$ synclient CoastingSpeed=0</code></pre></div> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343456" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:monitoring-freezer-temperature</guid>
				<title>Monitoring Freezer Temperature</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:monitoring-freezer-temperature</link>
				<description>

&lt;p&gt;For some time we&#039;ve had suspicions the freezer in our apartment doesn&#039;t work correctly. Recently my wife reached to it to get some ice cubes but found water in the form instead. That clearly meant the temperature was over the freezing point and stayed there for some time. She put a thermometer on the fridge, put the sensor into the freezer and started watching the readings. The temperature reached around -20°C and stayed there, fluctuating between -15°C and -20°C.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343456&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 25 Sep 2016 22:11:15 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>For some time we've had suspicions the freezer in our apartment doesn't work correctly. Recently my wife reached to it to get some ice cubes but found water in the form instead. That clearly meant the temperature was over the freezing point and stayed there for some time. She put a thermometer on the fridge, put the sensor into the freezer and started watching the readings. The temperature reached around -20°C and stayed there, fluctuating between -15°C and -20°C.</p> <h1><span>The webcam reader</span></h1> <p>I decided, it's time to record the temperature, so I brought the laptop, adjusted the screen angle, set the brightness to max and took a shot from the webcam to see if the thermometer is in the view of the camera:</p> <div class="code"> <pre><code>mplayer tv:// -vo png -frames 3</code></pre></div> <p>This takes 3 frames from the webcam and saves them as PNG files: 00000001.png, 00000002.png, and 00000003.png. If you wonder why I need 3 frames, the first one is always under- or overexposed and out of focus, the second is usually OK and the third is almost always good (as for a webcam), so long story short, I'm giving some time to the camera to auto-adjust its settings.</p> <p>Here's a script that does just a bit more than that:</p> <div class="code"> <pre><code>#!/bin/bash set -e export DISPLAY=:0 curdate=`date +%x-%X | sed 's/[\.:]//g'` outpng=/home/quake/git/thermonitor/out/&quot;$curdate&quot;.png tmppng=/home/quake/git/thermonitor/tmp/00000005.png mkdir -p /home/quake/git/thermonitor/out/ /home/quake/git/thermonitor/tmp cd /home/quake/git/thermonitor/tmp # White background ristretto ../white.png &amp; # Wake screen xte &quot;mousemove 100 100&quot; sleep 0.2 xte &quot;mousemove 99 99&quot; # Dump screen mplayer tv:// -vo png -frames 5 -noconsolecontrols cp &quot;$tmppng&quot; &quot;$outpng&quot; echo &quot;$outpng&quot; kill $!</code></pre></div> <p>It's very hacky, but here are the big parts:</p> <ul> <li><tt>set -e</tt> makes the script stop if any of the commands in it fail</li> <li><tt>export DISPLAY=:0</tt> selects the default X display, so I can run the command from an SSH shell</li> <li>Then we have some hard-coded paths to <tt>tmp</tt> and <tt>out</tt> directories</li> <li><tt>ristretto ./white.png &amp;</tt> starts a image-viewer and shows a <tt>white.png</tt> file which is a big all-white file. This makes the screen display enough white, so the LCD thermometer is properly lit</li> <li>I use <tt>xte</tt> to move the mouse around: this blocks the automatic screen dimming, so the screen continues to be 100% bright</li> <li>Then we have the <tt>mplayer</tt> command from before, just changed to 5 frames (just to be sure) and <tt>-noconsolecontrols</tt>. <tt>mplayer</tt> kind of hangs when you start it without a proper terminal on stdin, unless you pass this option</li> <li>Then I copy the 5th frame to the output file, which has the current date and the time in its path</li> <li>Finally I close the ristretto process I opened before</li> </ul> <p>I run this command in a while loop like that:</p> <div class="code"> <pre><code>while sleep 28 ; do ./dup.sh ; done</code></pre></div> <p><tt>./dup.sh</tt> takes around 2 seconds, so I have about 2 photos a minute.</p> <p>I put that to a screen session.</p> <p>Now in the <tt>out</tt> directory I serve the files using Python HTTP server:</p> <div class="code"> <pre><code>python -m SimpleHTTPServer</code></pre></div> <p>This starts an HTTP server on port 8000 and serves all the files and creates an index of them when requesting /.</p> <h1><span>The processing</span></h1> <p>How easier to copy the HTTP-exposed files than using a plain-old <tt>wget</tt> command?</p> <div class="code"> <pre><code>wget -r http://dell:8000/</code></pre></div> <p>This creates directory <tt>dell:8000</tt> and downloads all the PNG files to it.</p> <p>Once you have that directory you may later want to update it with only the newer files:</p> <div class="code"> <pre><code>rm dell\:8000/index.html wget -nc -r http://dell:8000/</code></pre></div> <p>The <tt>-nc</tt> switch makes <tt>wget</tt> ignore files that are already there. We explicitly remove the <tt>index.html</tt> so it downloads a new list (that includes newer files).</p> <p>I wanted to make a program that gets a photo of the 7-segment display and reads it producing a number that along with the date could be used to graph the temperature over time.</p> <p>First, let's use ImageMagick to:</p> <ul> <li>crop the picture to only the interesting part: the OUT reading</li> <li>shear the picture to make the LCD segments vertical and horizontal, not skewed</li> <li>bump contrast/gamma to remove the noise</li> <li>auto-adjust the visual properties of the picture so it's more consistent across different times (like night vs day)</li> <li>make it black and white &#8212; turned out it works best if I only use the Green channel, R and B turned out more noisy than G.</li> <li>resize to as small size as needed &#8212; for easier and faster processing</li> </ul> <p>Here's the actual command:</p> <div class="code"> <pre><code>convert $file_in -gamma 1.5 -auto-level -brightness-contrast 35x80 -shear -14x0 -crop 260x70+320+227 -channel Green -separate -resize 40x20 $file_out</code></pre></div> <p>Input image:</p> <img src="http://piotrgabryjeluk.wdfiles.com/local--files/blog:monitoring-freezer-temperature/input.png" alt="input.png" class="image" /> <p>Output image:</p> <img src="http://piotrgabryjeluk.wdfiles.com/local--files/blog:monitoring-freezer-temperature/output.png" alt="output.png" class="image" /> <p>Zoomed in:</p> <img src="http://piotrgabryjeluk.wdfiles.com/local--files/blog:monitoring-freezer-temperature/output-scaled.png" alt="output-scaled.png" class="image" /> <p>You can see the bottom segment is not really visible, but that's OK, all the digits can be properly read without that segment being visible, so we'll only consider the 6 segments that we can easily read.</p> <p>Now comes the meat, the Python program reading the file and returning the temperature:</p> <div class="code"> <div class="hl-main"> <pre><span class="hl-comment">#!/usr/bin/env python</span><span class="hl-code"> </span><span class="hl-comment">#encoding: utf-8</span><span class="hl-code"> </span><span class="hl-reserved">from</span><span class="hl-code"> </span><span class="hl-identifier">PIL</span><span class="hl-code"> </span><span class="hl-reserved">import</span><span class="hl-code"> </span><span class="hl-identifier">Image</span><span class="hl-code"> </span><span class="hl-comment"># Points that hold each segment:</span><span class="hl-code"> </span><span class="hl-comment"># d1 is the first digit</span><span class="hl-code"> </span><span class="hl-identifier">d1_sA</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">12</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">13</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">14</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">15</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d1_sB</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">18</span><span class="hl-code">,</span><span class="hl-number">2</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">18</span><span class="hl-code">,</span><span class="hl-number">3</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">18</span><span class="hl-code">,</span><span class="hl-number">4</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">18</span><span class="hl-code">,</span><span class="hl-number">5</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d1_sC</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">18</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">18</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d1_sE</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">11</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">12</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">11</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">12</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-comment"># Don't need this, as we only ever have 1 and 2 in the first place</span><span class="hl-code"> </span><span class="hl-identifier">d1_sF</span><span class="hl-code"> = </span><span class="hl-brackets">[]</span><span class="hl-code"> </span><span class="hl-identifier">d1_sG</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">13</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">14</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">15</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">16</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-comment"># d2 is the second digit</span><span class="hl-code"> </span><span class="hl-identifier">d2_sA</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">24</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">25</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">26</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">27</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d2_sB</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">29</span><span class="hl-code">,</span><span class="hl-number">2</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">29</span><span class="hl-code">,</span><span class="hl-number">3</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">29</span><span class="hl-code">,</span><span class="hl-number">4</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">29</span><span class="hl-code">,</span><span class="hl-number">5</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d2_sC</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">29</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">29</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d2_sE</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">22</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">22</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d2_sF</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">22</span><span class="hl-code">,</span><span class="hl-number">2</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">22</span><span class="hl-code">,</span><span class="hl-number">3</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">22</span><span class="hl-code">,</span><span class="hl-number">4</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">22</span><span class="hl-code">,</span><span class="hl-number">5</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d2_sG</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">24</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">25</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">26</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">24</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">25</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">26</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-comment"># d3 is the small digit (first after the decimal point)</span><span class="hl-code"> </span><span class="hl-identifier">d3_sA</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">35</span><span class="hl-code">,</span><span class="hl-number">4</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">36</span><span class="hl-code">,</span><span class="hl-number">4</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">37</span><span class="hl-code">,</span><span class="hl-number">4</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d3_sB</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">38</span><span class="hl-code">,</span><span class="hl-number">5</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">38</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">38</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d3_sC</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">38</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d3_sE</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">34</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d3_sF</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">34</span><span class="hl-code">,</span><span class="hl-number">5</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">34</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">34</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d3_sG</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">35</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">36</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-comment"># Now the tricky part, for each segment I define a threshold below which I consider it &quot;lit&quot;</span><span class="hl-code"> </span><span class="hl-comment"># 0 means completely black, 255 is white.</span><span class="hl-code"> </span><span class="hl-comment"># Because of uneven lighting, for each segment (and digit, but we ignore that) the value is different.</span><span class="hl-code"> </span><span class="hl-identifier">tA</span><span class="hl-code"> = </span><span class="hl-number">200</span><span class="hl-code"> </span><span class="hl-identifier">tB</span><span class="hl-code"> = </span><span class="hl-number">170</span><span class="hl-code"> </span><span class="hl-identifier">tC</span><span class="hl-code"> = </span><span class="hl-number">120</span><span class="hl-code"> </span><span class="hl-identifier">tE</span><span class="hl-code"> = </span><span class="hl-number">115</span><span class="hl-code"> </span><span class="hl-identifier">tF</span><span class="hl-code"> = </span><span class="hl-number">140</span><span class="hl-code"> </span><span class="hl-identifier">tG</span><span class="hl-code"> = </span><span class="hl-number">170</span><span class="hl-code"> </span><span class="hl-comment"># A threshold for the &quot;-&quot; sign</span><span class="hl-code"> </span><span class="hl-identifier">tSIGN</span><span class="hl-code"> = </span><span class="hl-number">200</span><span class="hl-code"> </span><span class="hl-comment"># All of those were obviously updated on the go to match the files</span><span class="hl-code"> </span><span class="hl-comment"># A nice debugging function that prints which segments the code considers lit</span><span class="hl-code"> </span><span class="hl-comment"># Also if you wondered what A, B, C, E, F, G meant, here's the schematic:</span><span class="hl-code"> </span><span class="hl-reserved">def</span><span class="hl-code"> </span><span class="hl-identifier">print_digit</span><span class="hl-brackets">(</span><span class="hl-identifier">segs</span><span class="hl-brackets">)</span><span class="hl-code">: </span><span class="hl-comment"># Only print this if there's a second argument to the script passed</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-builtin">len</span><span class="hl-brackets">(</span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">)</span><span class="hl-code"> == </span><span class="hl-number">2</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-reserved">print</span><span class="hl-code"> </span><span class="hl-quotes">'''</span><span class="hl-string"> {A}{A} {A}{A} {F} {B} {F} {B} {F} {B} {G}{G} {G}{G} {E} {C} {E} {C} {E} {C} </span><span class="hl-quotes">'''</span><span class="hl-code">.</span><span class="hl-identifier">format</span><span class="hl-brackets">(</span><span class="hl-code"> </span><span class="hl-identifier">A</span><span class="hl-code">=</span><span class="hl-quotes">'</span><span class="hl-string">###</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">A</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string"> </span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">B</span><span class="hl-code">=</span><span class="hl-quotes">'</span><span class="hl-string">###</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">B</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string"> </span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">C</span><span class="hl-code">=</span><span class="hl-quotes">'</span><span class="hl-string">###</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">C</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string"> </span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">E</span><span class="hl-code">=</span><span class="hl-quotes">'</span><span class="hl-string">###</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">E</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string"> </span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">F</span><span class="hl-code">=</span><span class="hl-quotes">'</span><span class="hl-string">###</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">F</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string"> </span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">G</span><span class="hl-code">=</span><span class="hl-quotes">'</span><span class="hl-string">###</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">G</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string"> </span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-comment"># This doesn't do anything spectacular, just passes the coordinates for each of the segments and the average value of the first 9 pixels of the image: (0,0) - (3,3)</span><span class="hl-code"> </span><span class="hl-reserved">def</span><span class="hl-code"> </span><span class="hl-identifier">read_digit</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsA</span><span class="hl-code">, </span><span class="hl-identifier">pointsB</span><span class="hl-code">, </span><span class="hl-identifier">pointsC</span><span class="hl-code">, </span><span class="hl-identifier">pointsE</span><span class="hl-code">, </span><span class="hl-identifier">pointsF</span><span class="hl-code">, </span><span class="hl-identifier">pointsG</span><span class="hl-code">, </span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code">: </span><span class="hl-identifier">segs</span><span class="hl-code"> = </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> += </span><span class="hl-quotes">'</span><span class="hl-string">A</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsA</span><span class="hl-code">, </span><span class="hl-identifier">tA</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> += </span><span class="hl-quotes">'</span><span class="hl-string">B</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsB</span><span class="hl-code">, </span><span class="hl-identifier">tB</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> += </span><span class="hl-quotes">'</span><span class="hl-string">C</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsC</span><span class="hl-code">, </span><span class="hl-identifier">tC</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> += </span><span class="hl-quotes">'</span><span class="hl-string">E</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsE</span><span class="hl-code">, </span><span class="hl-identifier">tE</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> += </span><span class="hl-quotes">'</span><span class="hl-string">F</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsF</span><span class="hl-code">, </span><span class="hl-identifier">tF</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> += </span><span class="hl-quotes">'</span><span class="hl-string">G</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsG</span><span class="hl-code">, </span><span class="hl-identifier">tG</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">print_digit</span><span class="hl-brackets">(</span><span class="hl-identifier">segs</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-comment"># A list of all digits and their representation on the 7-segment display:</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ABCEF</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">0</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">BC</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">1</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ABEG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">2</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ABCG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">3</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">BCFG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">4</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ACFG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">5</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ACEFG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">6</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ABC</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">7</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ABCEFG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">8</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ABCFG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">9</span><span class="hl-code"> </span><span class="hl-comment"># A special case for the first digit, it doesn't display &quot;0&quot;, just doesn't display any segments</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">''</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">0</span><span class="hl-code"> </span><span class="hl-comment"># The function that takes the PIL image object, gets a list of (x,y) coordinates</span><span class="hl-code"> </span><span class="hl-comment"># and checks if the average value of them is smaller than the threshold passed: segment &quot;on&quot;</span><span class="hl-code"> </span><span class="hl-comment"># For 0 points passed it returns False: segment &quot;off&quot;</span><span class="hl-code"> </span><span class="hl-reserved">def</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">points</span><span class="hl-code">, </span><span class="hl-identifier">threshold</span><span class="hl-code">=</span><span class="hl-number">128</span><span class="hl-brackets">)</span><span class="hl-code">: </span><span class="hl-identifier">val</span><span class="hl-code"> = </span><span class="hl-number">0</span><span class="hl-code"> </span><span class="hl-reserved">for</span><span class="hl-code"> </span><span class="hl-identifier">point</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">points</span><span class="hl-code">: </span><span class="hl-identifier">val</span><span class="hl-code"> += </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">(</span><span class="hl-identifier">point</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-identifier">val</span><span class="hl-code"> &lt; </span><span class="hl-identifier">threshold</span><span class="hl-code"> * </span><span class="hl-builtin">len</span><span class="hl-brackets">(</span><span class="hl-identifier">points</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-comment"># Nothing interesting in here, just for printing the date from the file name</span><span class="hl-code"> </span><span class="hl-reserved">def</span><span class="hl-code"> </span><span class="hl-identifier">get_date</span><span class="hl-brackets">(</span><span class="hl-identifier">file_name</span><span class="hl-brackets">)</span><span class="hl-code">: </span><span class="hl-identifier">time_str</span><span class="hl-code"> = </span><span class="hl-identifier">file_name</span><span class="hl-code">.</span><span class="hl-identifier">split</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">-</span><span class="hl-quotes">'</span><span class="hl-brackets">)[</span><span class="hl-code">-</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-code">.</span><span class="hl-identifier">replace</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">.png</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">''</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-identifier">d1</span><span class="hl-code">, </span><span class="hl-identifier">d2</span><span class="hl-code">, </span><span class="hl-identifier">m1</span><span class="hl-code">, </span><span class="hl-identifier">m2</span><span class="hl-code">, </span><span class="hl-identifier">y1</span><span class="hl-code">, </span><span class="hl-identifier">y2</span><span class="hl-code">, </span><span class="hl-identifier">y3</span><span class="hl-code">, </span><span class="hl-identifier">y4</span><span class="hl-code"> = </span><span class="hl-identifier">file_name</span><span class="hl-code">.</span><span class="hl-identifier">split</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">/</span><span class="hl-quotes">'</span><span class="hl-brackets">)[</span><span class="hl-code">-</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-code">.</span><span class="hl-identifier">split</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">-</span><span class="hl-quotes">'</span><span class="hl-brackets">)[</span><span class="hl-number">0</span><span class="hl-brackets">]</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">{}{}/{}{}/{}{}{}{} </span><span class="hl-quotes">'</span><span class="hl-code">.</span><span class="hl-identifier">format</span><span class="hl-brackets">(</span><span class="hl-identifier">m1</span><span class="hl-code">, </span><span class="hl-identifier">m2</span><span class="hl-code">, </span><span class="hl-identifier">d1</span><span class="hl-code">, </span><span class="hl-identifier">d2</span><span class="hl-code">, </span><span class="hl-identifier">y1</span><span class="hl-code">, </span><span class="hl-identifier">y2</span><span class="hl-code">, </span><span class="hl-identifier">y3</span><span class="hl-code">, </span><span class="hl-identifier">y4</span><span class="hl-brackets">)</span><span class="hl-code"> + </span><span class="hl-quotes">'</span><span class="hl-string">{}{}:{}{}:{}{}</span><span class="hl-quotes">'</span><span class="hl-code">.</span><span class="hl-identifier">format</span><span class="hl-brackets">(</span><span class="hl-code">*</span><span class="hl-builtin">list</span><span class="hl-brackets">(</span><span class="hl-identifier">time_str</span><span class="hl-brackets">))</span><span class="hl-code"> </span><span class="hl-comment"># A bunch of imports in the middle of the file</span><span class="hl-code"> </span><span class="hl-comment"># Don't do that at home ;-)</span><span class="hl-code"> </span><span class="hl-reserved">import</span><span class="hl-code"> </span><span class="hl-identifier">sys</span><span class="hl-code"> </span><span class="hl-reserved">import</span><span class="hl-code"> </span><span class="hl-identifier">subprocess</span><span class="hl-code"> </span><span class="hl-comment"># This will be for example: pngs/dell\:8000/24092016-101055.png</span><span class="hl-code"> </span><span class="hl-identifier">file_in</span><span class="hl-code"> = </span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">[</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-code"> </span><span class="hl-comment"># And this: processed-pngs/dell\:8000/24092016-101055.png</span><span class="hl-code"> </span><span class="hl-identifier">file_out</span><span class="hl-code"> = </span><span class="hl-quotes">'</span><span class="hl-string">processed-</span><span class="hl-quotes">'</span><span class="hl-code"> + </span><span class="hl-identifier">file_in</span><span class="hl-code"> </span><span class="hl-comment"># Calling the ImageMagick as discussed in the article</span><span class="hl-code"> </span><span class="hl-identifier">subprocess</span><span class="hl-code">.</span><span class="hl-identifier">check_call</span><span class="hl-brackets">([</span><span class="hl-quotes">'</span><span class="hl-string">convert</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">file_in</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-gamma</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">1.5</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-auto-level</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-brightness-contrast</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">35x80</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-shear</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-14x0</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-crop</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">260x70+320+227</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-channel</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">Green</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-separate</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-resize</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">40x20</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">file_out</span><span class="hl-brackets">])</span><span class="hl-code"> </span><span class="hl-comment"># Reading what it created</span><span class="hl-code"> </span><span class="hl-identifier">im</span><span class="hl-code">=</span><span class="hl-identifier">Image</span><span class="hl-code">.</span><span class="hl-builtin">open</span><span class="hl-brackets">(</span><span class="hl-identifier">file_out</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-comment"># Now a thing I added at some point later.</span><span class="hl-code"> </span><span class="hl-comment"># Because of different lighting throughout the day and because the ImageMagick command</span><span class="hl-code"> </span><span class="hl-comment"># above was not good compensating for it (in spite of auto-level and high contrast)</span><span class="hl-code"> </span><span class="hl-comment"># some of the images were darker than the others. In most images (the ideal scenario for the code)</span><span class="hl-code"> </span><span class="hl-comment"># the first 9 pixels of the image (0,0) to (3,3) were just white (or very close), but in those darker</span><span class="hl-code"> </span><span class="hl-comment"># images the whole image was darker and I used the first 9 pixels to detect how much darker</span><span class="hl-code"> </span><span class="hl-identifier">first9px</span><span class="hl-code"> = </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">0</span><span class="hl-code">,</span><span class="hl-number">0</span><span class="hl-brackets">))</span><span class="hl-code"> + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">0</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">))</span><span class="hl-code"> + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">0</span><span class="hl-code">,</span><span class="hl-number">2</span><span class="hl-brackets">))</span><span class="hl-code"> \ + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">1</span><span class="hl-code">,</span><span class="hl-number">0</span><span class="hl-brackets">))</span><span class="hl-code"> + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">1</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">))</span><span class="hl-code"> + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">1</span><span class="hl-code">,</span><span class="hl-number">2</span><span class="hl-brackets">))</span><span class="hl-code"> \ + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">2</span><span class="hl-code">,</span><span class="hl-number">0</span><span class="hl-brackets">))</span><span class="hl-code"> + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">2</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">))</span><span class="hl-code"> + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">2</span><span class="hl-code">,</span><span class="hl-number">2</span><span class="hl-brackets">))</span><span class="hl-code"> </span><span class="hl-comment"># This is the compensation, for most of the images it's 0 or very few, but for darker images, it's more</span><span class="hl-code"> </span><span class="hl-identifier">avg9px</span><span class="hl-code"> = </span><span class="hl-number">255</span><span class="hl-code">-</span><span class="hl-identifier">first9px</span><span class="hl-code">/</span><span class="hl-number">9</span><span class="hl-code"> </span><span class="hl-identifier">num</span><span class="hl-code"> = </span><span class="hl-quotes">'</span><span class="hl-string">{}{}{}.{}</span><span class="hl-quotes">'</span><span class="hl-code">.</span><span class="hl-identifier">format</span><span class="hl-brackets">(</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">-</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-brackets">[(</span><span class="hl-number">2</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">3</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">4</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)]</span><span class="hl-code">, </span><span class="hl-identifier">tSIGN</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">+</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">read_digit</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">d1_sA</span><span class="hl-code">, </span><span class="hl-identifier">d1_sB</span><span class="hl-code">, </span><span class="hl-identifier">d1_sC</span><span class="hl-code">, </span><span class="hl-identifier">d1_sE</span><span class="hl-code">, </span><span class="hl-identifier">d1_sF</span><span class="hl-code">, </span><span class="hl-identifier">d1_sG</span><span class="hl-code">, </span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-identifier">read_digit</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">d2_sA</span><span class="hl-code">, </span><span class="hl-identifier">d2_sB</span><span class="hl-code">, </span><span class="hl-identifier">d2_sC</span><span class="hl-code">, </span><span class="hl-identifier">d2_sE</span><span class="hl-code">, </span><span class="hl-identifier">d2_sF</span><span class="hl-code">, </span><span class="hl-identifier">d2_sG</span><span class="hl-code">, </span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-identifier">read_digit</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">d3_sA</span><span class="hl-code">, </span><span class="hl-identifier">d3_sB</span><span class="hl-code">, </span><span class="hl-identifier">d3_sC</span><span class="hl-code">, </span><span class="hl-identifier">d3_sE</span><span class="hl-code">, </span><span class="hl-identifier">d3_sF</span><span class="hl-code">, </span><span class="hl-identifier">d3_sG</span><span class="hl-code">, </span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">None</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">not</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">num</span><span class="hl-code">: </span><span class="hl-reserved">print</span><span class="hl-code"> </span><span class="hl-identifier">get_date</span><span class="hl-brackets">(</span><span class="hl-identifier">file_in</span><span class="hl-brackets">)</span><span class="hl-code"> + </span><span class="hl-quotes">'</span><span class="hl-special">\t</span><span class="hl-quotes">'</span><span class="hl-code"> + </span><span class="hl-identifier">num</span><span class="hl-code"> </span><span class="hl-comment"># If there's a second argument to the script passed, show the original image for comparison</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-builtin">len</span><span class="hl-brackets">(</span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">)</span><span class="hl-code"> &gt; </span><span class="hl-number">2</span><span class="hl-code">: </span><span class="hl-identifier">Image</span><span class="hl-code">.</span><span class="hl-builtin">open</span><span class="hl-brackets">(</span><span class="hl-identifier">file_in</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">show</span><span class="hl-brackets">()</span></pre></div> </div> <p>Even though this script is so simple, after tweaking the thresholds, most of the files were recognized correctly, those that weren't had one or more non-recognized digits, so they were easy to filter out. For over 1-day worth of images, only 2 or 3 minutes had a missing reading.</p> <p>I loaded the data to LibreOffice and generated this pretty graph:</p> <img src="http://piotrgabryjeluk.wdfiles.com/local--files/blog:monitoring-freezer-temperature/graph.jpg" style="width: 100%" alt="graph.jpg" class="image" /> <h1><span>Timelapse video</span></h1> <p>Another approach visualizing the data was to create a video.</p> <p>The plan:</p> <ul> <li>Annotate the images with the recorded time</li> <li>Compose the video from single frames, putting 60 frames per a second of the resulting video</li> </ul> <p>60 frames a second with roughly 2 frames captured a minutes means a day of recording is compressed to:</p> <div class="code"> <pre><code>2 frames a minute * 60 minutes an hour * 24 hours a day = 2880 frames 2880 frames / 60 frames a second = 48 seconds</code></pre></div> <p>This makes is &quot;viewable&quot;. 60 FPS (versus 30 FPS at higher speed) means you can pause at any time and read the crisp time and temperature.</p> <p>Here's the annotate part:</p> <div class="code"> <div class="hl-main"> <pre><span class="hl-comment">#!/usr/bin/env python</span><span class="hl-code"> </span><span class="hl-reserved">import</span><span class="hl-code"> </span><span class="hl-identifier">sys</span><span class="hl-code"> </span><span class="hl-reserved">import</span><span class="hl-code"> </span><span class="hl-identifier">subprocess</span><span class="hl-code"> </span><span class="hl-identifier">path_in</span><span class="hl-code"> = </span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">[</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-code"> </span><span class="hl-identifier">path_out</span><span class="hl-code"> = </span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">[</span><span class="hl-number">2</span><span class="hl-brackets">]</span><span class="hl-code"> </span><span class="hl-identifier">date</span><span class="hl-code">, </span><span class="hl-identifier">time</span><span class="hl-code"> = </span><span class="hl-identifier">path_in</span><span class="hl-code">.</span><span class="hl-identifier">replace</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">.png</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">''</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">split</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">/</span><span class="hl-quotes">'</span><span class="hl-brackets">)[</span><span class="hl-code">-</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-code">.</span><span class="hl-identifier">split</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">-</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-identifier">D1</span><span class="hl-code">, </span><span class="hl-identifier">D2</span><span class="hl-code">, </span><span class="hl-identifier">M1</span><span class="hl-code">, </span><span class="hl-identifier">M2</span><span class="hl-code">, </span><span class="hl-identifier">Y1</span><span class="hl-code">, </span><span class="hl-identifier">Y2</span><span class="hl-code">, </span><span class="hl-identifier">Y3</span><span class="hl-code">, </span><span class="hl-identifier">Y4</span><span class="hl-code"> = </span><span class="hl-identifier">date</span><span class="hl-code"> </span><span class="hl-identifier">h1</span><span class="hl-code">, </span><span class="hl-identifier">h2</span><span class="hl-code">, </span><span class="hl-identifier">m1</span><span class="hl-code">, </span><span class="hl-identifier">m2</span><span class="hl-code">, </span><span class="hl-identifier">s1</span><span class="hl-code">, </span><span class="hl-identifier">s2</span><span class="hl-code"> = </span><span class="hl-identifier">time</span><span class="hl-code"> </span><span class="hl-identifier">label</span><span class="hl-code"> = </span><span class="hl-quotes">'</span><span class="hl-string">{}{}/{}{}/{}{}{}{} {}{}:{}{}:{}{}</span><span class="hl-special">\\</span><span class="hl-string">n</span><span class="hl-quotes">'</span><span class="hl-code">.</span><span class="hl-identifier">format</span><span class="hl-brackets">(</span><span class="hl-identifier">M1</span><span class="hl-code">, </span><span class="hl-identifier">M2</span><span class="hl-code">, </span><span class="hl-identifier">D1</span><span class="hl-code">, </span><span class="hl-identifier">D2</span><span class="hl-code">, </span><span class="hl-identifier">Y1</span><span class="hl-code">, </span><span class="hl-identifier">Y2</span><span class="hl-code">, </span><span class="hl-identifier">Y3</span><span class="hl-code">, </span><span class="hl-identifier">Y4</span><span class="hl-code">, </span><span class="hl-identifier">h1</span><span class="hl-code">, </span><span class="hl-identifier">h2</span><span class="hl-code">, </span><span class="hl-identifier">m1</span><span class="hl-code">, </span><span class="hl-identifier">m2</span><span class="hl-code">, </span><span class="hl-identifier">s1</span><span class="hl-code">, </span><span class="hl-identifier">s2</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-identifier">subprocess</span><span class="hl-code">.</span><span class="hl-identifier">check_call</span><span class="hl-brackets">([</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">convert</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">path_in</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-gravity</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">south</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-pointsize</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">45</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-font</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">FreeMono</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-annotate</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">0</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">label</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-fill</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">black</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">path_out</span><span class="hl-code"> </span><span class="hl-brackets">])</span></pre></div> </div> <p>Here's the result:</p> <img src="http://piotrgabryjeluk.wdfiles.com/local--files/blog:monitoring-freezer-temperature/annotated.png" alt="annotated.png" class="image" /> <p>Running this in a loop, 16 images at a time:</p> <div class="code"> <pre><code>#!/bin/bash i=0 for file_in in dell*/*.png; do file_out=&quot;`printf &quot;labeled/%06d.png&quot; $i`&quot; echo ./add-labels.py &quot;$file_in&quot; &quot;$file_out&quot; i=$((i+1)) done | parallel -j 16</code></pre></div> <p>In addition to annotatig the image it also names them as 000001.png, 000002.png etc, which makes it easy for <tt>avconv</tt> to convert them to a video:</p> <div class="code"> <pre><code>avconv -fflags +genpts -r 60 -i labeled/%06d.png -r 60 temperature.mkv</code></pre></div> <p>And here's the video:</p> <p><iframe width="640" height="480" src="https://www.youtube.com/embed/DL9_sbdHlhU" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343456" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:glupia-nawigacja-w-mazdzie-6</guid>
				<title>Głupia Nawigacja w Mazdzie 6</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:glupia-nawigacja-w-mazdzie-6</link>
				<description>

&lt;p&gt;Gdy kupowaliśmy naszą Mazdę, pracownik dilera nie mógł przestać zachwalać systemu &amp;quot;infotainmentu&amp;quot;, który Mazda posiada. W mojej ocenie system jest w porządku, ale szału nie robi.&lt;/p&gt;
&lt;p&gt;Ogólnie moja opinia na temat samochodów i ich ekranów multimedialnych, jest taka, że dla wszystkich byłoby dużo lepiej, gdyby producenci samochodów przestali się tym w ogóle zajmować, tylko dali jakąś dobrą integrację z tabletem, który można byłoby sobie wsadzić w odpowiedni slot w samochodzie.&lt;/p&gt;
&lt;p&gt;Ale do rzeczy. Dlaczego system w aucie, który kupiliśmy jest według mnie taki słaby?&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343456&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sat, 13 Feb 2016 21:14:30 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Gdy kupowaliśmy naszą Mazdę, pracownik dilera nie mógł przestać zachwalać systemu &quot;infotainmentu&quot;, który Mazda posiada. W mojej ocenie system jest w porządku, ale szału nie robi.</p> <p>Ogólnie moja opinia na temat samochodów i ich ekranów multimedialnych, jest taka, że dla wszystkich byłoby dużo lepiej, gdyby producenci samochodów przestali się tym w ogóle zajmować, tylko dali jakąś dobrą integrację z tabletem, który można byłoby sobie wsadzić w odpowiedni slot w samochodzie.</p> <p>Ale do rzeczy. Dlaczego system w aucie, który kupiliśmy jest według mnie taki słaby?</p> <div class="content-separator" style="display: none:"></div> <p>Po pierwsze <strong>sposób w jaki startuje</strong>. Nawigacja i reszta bajerów (radio, odtwarzacz MP3 itd) uruchamia się dopiero po &quot;przekręceniu kluczyka&quot;. Uruchomienie systemu trwa około minutę, więc nici z szybkiego ustawienia nawigacji czy wyboru stacji przed ruszeniem w podróż.</p> <p>System mógłby już zacząć się uruchamiać gdy otwieramy drzwi a nawet gdy kluczyk zbliża się do auta (mamy czujnik bliskości), wtedy długi czas uruchamiania systemu (o ile nie można go sensownie skrócić) nie byłby taki straszny, bo proces miałby miejsce zanim wsiądziemy do auta.</p> <p>Po drugie <strong>brak możliwości sterowania nawigacją w czasie jazdy</strong>. Gdy przekraczamy około 5 mil na godzinę nawigacja przechodzi w tryb ograniczonego sterowania: niemożliwe jest wpisywanie adresu czy nazwy pożądanego punktu, a jeśli nazwę już wpisaliśmy w czasie, gdy auto się toczyło: niemożliwe jest zatwierdzenie wpisanej nazwy.</p> <p>Są dostępne tylko niektóre opcje, wybrane chyba zupełnie losowo, bo o logice ciężko w tej sytuacji rozmawiać. Auto nie jest zainteresowane kto obsługuje nawigację. Niezależnie od tego, czy następny punkt podróży chce wpisać kierowca czy pasażer &quot;z powodów bezpieczeństwa&quot; jest to niemożliwe.</p> <p>W sytuacji gdy jedziemy autostradą i w wyniku zmiany planów (np. ktoś się źle poczuł i należy podjechać po drodze do apteki) należy zatrzymać auto (albo zwolnić do około 5 mph) i dopiero wtedy możliwe jest ustawienie następnego punktu podróży.</p> <p>Jeśli w Mazdzie nazywa się to bezpieczeństwem (zatrzymywanie auta na autostradzie), to jest po prostu głupia (tak jak i ich nawigacja).</p> <p>Po konsultacji na forum Mazdy6 w Polsce dowiedziałem się, że zabezpieczenie, o którym piszę wcale nie występuje w Polskich samochodach. Bardzo mnie to zdziwiło, bo jeżeli to kwestia bezpieczeństwa, to chyba powinno to działać tak samo we wszystkich krajach? Dla dociekliwych, to też nie kwestia regulacji prawnych w stanach, bo inne marki samochodów nie utrudniają w ten sposób życia swoim kierowcom.</p> <p>Jak zwykle w takich sytuacjach zwróciłem się do Mazdy z pytaniem jak to naprawić.</p> <p>Niestety nie mam zapisanego mojego pytania, ale dotyczyło ono dlaczego niemożliwe jest w aucie sterowanie nawigacją (nawet przez pasażera) w czasie jazdy. Oto odpowiedź:</p> <blockquote> <p>Dear Piotr Gabryjeluk,</p> <p>Good Morning</p> <p>Apologies that you are unhappy with our navigation system , to answer your question about operating the navigation while the vehicle is in motion , for safety precautions it could be a distraction to operate while in the vehicle is in motion. For the other issues with the navigation if it is not working as normal I suggest taking the vehicle into a local Mazda dealer to inspect your concern.</p> <p>Thank you for contacting Mazda Customer Experience Center.</p> <p>If you have any questions in the future, you can reach me directly using the number and extension below.</p> <p>Sincerely,</p> <p>William</p> <p>Representative, Customer Experience</p> </blockquote> <p>Nie można takiej odpowiedzi pozostawić bez odzewu, więc zadałem kolejne pytanie w nawiązaniu do tej odpowiedzi:</p> <blockquote> <p>Dear William,</p> <p>Could you please tell me how exactly operating the navigation system by a passenger is a distraction?</p> <p>Thank you very much,<br /> Piotr Gabryjeluk</p> </blockquote> <p>Po ośmiu dniach nie dostałem żadnej odpowiedzi, więc zapytałem:</p> <blockquote> <p>Hi there,</p> <p>Am I going to get the response from William?</p> <p>My issue is definitely NOT SOLVED!</p> <p>Thanks,<br /> Piotr Gabryjeluk</p> </blockquote> <p>Odpowiedź:</p> <blockquote> <p>Dear Piotr Gabryjeluk,</p> <p>Good Morning Apologies but it looks like I did supply the answer for you in regards why your not able to use the navigation while vehicle is in motion.</p> <p>Thank you for contacting Mazda Customer Experience Center.</p> <p>If you have any questions in the future, you can reach me directly using the number and extension below.</p> <p>Sincerely,<br /> William<br /> Representative, Customer Experience</p> </blockquote> <p>Moja odpowiedź:</p> <blockquote> <p>Dear William,</p> <p>You claimed that my navigation system cannot be operated by the passenger, because it is a security threat. I asked you why is that a security issue. You did not answer to that. Please answer that question.</p> <p>Thank you,<br /> Piotr Gabryjeluk</p> </blockquote> <p>Brak odpowiedzi. Nikt się nie przejmuje. Po przeszukaniu Internetu mam wrażenie, że nie tylko ja mam ten problem i wszyscy są jednakowo <strong>ignorowani przez Mazdę</strong>.</p> <p><strong>Jak to naprawić?</strong></p> <p>Skoro Mazda ma w dupie wygodę klientów, może jest jakiś sposób na naprawę problemu? Wygląda na to, że jest to możliwe. Na stronie forum Mazdy6: <a href="http://forum.mazda6club.com/car-electronics/351338-infotainment-hacks.html">http://forum.mazda6club.com/car-electronics/351338-infotainment-hacks.html</a> znalazłem informację o tym, że problem może być rozwiązany przez zalogowanie się przez ssh do samochodu i wyłączenie flagi.</p> <p>Tylko jak się zalogować? Okazuje się, że wystarczy podpiąć kartę Ethernetową do złącza USB w aucie, a auto pobierze adres IP przez DHCP, następne pod tym adresem na standardowym porcie SSH należy się zalogować na roota (hasło jci), przemontować system plików w tryb read-write <tt>mount -o rw,remount /</tt> a następnie wyedytować skrypt <tt>/jci/scripts/set_lvds_speed_restriction_config.sh</tt> wykomentowując linię zawierającą <tt>enable_speed_restriction</tt>.</p> <p><strong>Co z tego wynika?</strong></p> <p>Jeżeli to prawda (jeszcze tego nie sprawdzałem), to znaczy, że Mazda mając techniczną możliwość zdjęcia &quot;zabezpieczenia&quot; (które zresztą jest włączone tylko w niektórych krajach) odmawia tego klientom powołując się na kompletnie bezsensowne argumenty (że jest to podobno kwestia bezpieczeństwa). Dodatkowo obsługa klienta Mazdy nie odpowiada na pytania i ignoruje klientów.</p> <p>Jednocześnie, zgodnie z opiniami Mazdofili, wychodzi na to, że Mazda postawiła na sprawdzone rozwiązanie (wygląda na to, że pod &quot;maską&quot; systemu infotainmentu mamy dość standardowego Linuxa) co powinno się przełożyć na niezawodność systemu.</p> <p>Kwestię umożliwienia logowania na konto roota i trzyliterowe hasło zostawiam bez komentarza. Auto nie jest standardowo podłączone z Internetem i wymagany jest fizyczny dostęp do samochodu, żeby się dostać do systemu. Zakładam, że takie &quot;standardowe&quot; hasło i logowanie bezpośrednio na konto roota ułatwia pracę serwisantom, więc nie widzę w tym dużego zagrożenia.</p> <h2><span>Linki</span></h2> <ul> <li><a href="http://forum.mazda6club.com/car-electronics/351338-infotainment-hacks.html">http://forum.mazda6club.com/car-electronics/351338-infotainment-hacks.html</a></li> <li><a href="https://github.com/mazdahacks/tweaks">https://github.com/mazdahacks/tweaks</a></li> <li><a href="http://mazda3revolution.com/forums/2014-2016-mazda-3-skyactiv-audio-electronics/104730-index-infotainment-project.html">http://mazda3revolution.com/forums/2014-2016-mazda-3-skyactiv-audio-electronics/104730-index-infotainment-project.html</a></li> <li><a href="http://openmzdc.wikia.com/">http://openmzdc.wikia.com/</a></li> <li><a href="http://www.lukasz-skalski.com/portfolio/mazda-media-player/">http://www.lukasz-skalski.com/portfolio/mazda-media-player/</a> (klonowanie obrazu z Androida na wyświetlacz Mazdy)</li> </ul> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343456" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:converting-mp4-with-subs-for-roku</guid>
				<title>Converting MP4 with subtitles for Roku</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:converting-mp4-with-subs-for-roku</link>
				<description>

&lt;p&gt;I recently bought a HiSense Roku TV and it&#039;s awesome (I&#039;ve never had a Roku device before).&lt;/p&gt;
&lt;p&gt;The problem is that even though the TV has an USB port and Roku has a &amp;quot;Roku Media Player&amp;quot; channel that allows you plan video and audio files from the USB disk, not all formats are accepted.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343456&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 28 Oct 2015 06:37:49 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>I recently bought a HiSense Roku TV and it's awesome (I've never had a Roku device before).</p> <p>The problem is that even though the TV has an USB port and Roku has a &quot;Roku Media Player&quot; channel that allows you plan video and audio files from the USB disk, not all formats are accepted.</p> <div class="content-separator" style="display: none:"></div> <p>Interestingly Roku has support for subtitles, but the support is quite limited. I found out that one of the options that work nicely is to have the subtitles embedded into the movie itself, given the movie uses Matroska container (.mkv files).</p> <p>On a side note, if the files are not encoded &quot;properly&quot; (Roku only supports a selection of video and audio codecs), you'll need to re-encode the video using ffmpeg or avconv, but how to do it is much simpler to Google than how to deal with the subtitles. In this post I'll only show you how to deal with the subtitles.</p> <p>So let's see what we have:</p> <div class="code"> <pre><code>quake@quake-laptop:~/movies$ ls movie.mp4 movie.txt</code></pre></div> <p>There's a MP4 file and subtitles in a separate file.</p> <div class="code"> <pre><code>quake@quake-laptop:~/movies$ avconv -i movie.mp4 -f microdvd -sub_charenc cp1250 -i movie.txt -c:v copy -c:a copy movie-with-subs.mkv</code></pre></div> <p>Let's look at this command part by part:</p> <ul> <li>avconv &#8212; the tool we're using</li> <li>-i movie.mp4 &#8212; the movie to convert</li> <li>-f microdvd &#8212; format for the subtitles (this part is actually optional)</li> <li>-sub_charenc cp1250 &#8212; the encoding of the subtitles (optional if UTF-8)</li> <li>-i movie.txt &#8212; the subtitles</li> <li>-c:v copy -c:a copy &#8212; copy the audio and video stream (rather than re-encode)</li> <li>movie-with-subs.mkv &#8212; the output file</li> </ul> <p>Which is very nice is this command will not do any re-coding, it will only repackage the movie from MPEG to Matroska container and convert the subtitles. This means there's no quality lost and it only takes a few seconds.</p> <p>As noted above if the file is not playable on Roku (or there's audio missing) you may actually need to transcode the file (omitting or modifying the -c:v copy -c:a copy line).</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343456" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:work-around-buggy-soundcard</guid>
				<title>Working around a buggy sound card</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:work-around-buggy-soundcard</link>
				<description>

&lt;p&gt;I found the laptop I bought recently has a weird thing with its soundcard. It plays music OK, it also allows you to change the mixer levels, nothing special, but when you try changing mixer setting while the music is playing the music starts getting choppy and the process handling the mixer tend to freeze. Also you cannot pause the music, sometimes it repeats the same sample over and over and it gets very annoying.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343456&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 02 Dec 2014 23:34:29 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>I found the laptop I bought recently has a weird thing with its soundcard. It plays music OK, it also allows you to change the mixer levels, nothing special, but when you try changing mixer setting while the music is playing the music starts getting choppy and the process handling the mixer tend to freeze. Also you cannot pause the music, sometimes it repeats the same sample over and over and it gets very annoying.</p> <div class="content-separator" style="display: none:"></div> <p>My approach to this issue was to use PulseAudio software mixer capabilities, so the hardware mixer is never adjusted (other than for the initial setup).</p> <h1><span>Step 1. Getting PulseAudio to use the software mixer</span></h1> <p>I found no good documentation on this other than PulseAudio uses <em>paths</em> to convert the desired volume to the hardware mixer settings and if it lacks the ability to do so it would turn the volume up/down using software. Reading between the lines I realized if I remove the <em>paths</em> I will get what I want. Just do this and restart pulseaudio and you'll have PulseAudio doing all the mixing in software:</p> <div class="code"> <pre><code>sudo mv /usr/share/pulseaudio/alsa-mixer/paths /usr/share/pulseaudio/alsa-mixer/paths.bak</code></pre></div> <h2><span>Verifying it works</span></h2> <p>Open two terminal windows. In each of them open alsamixer. Both should display very simple controls and say Card: PulseAudio. Use F6 to switch to the real card in one of the windows. Usually the cards have plethora of controls, so should yours.</p> <p>Now change the output volume in the alsamixer still saying &quot;Card: PulseAudio&quot;. If the volume reported by the other alsamixer does not change, it works as expected!</p> <p>If you now rename the paths directory back and restart the pulseaudio process, updating the PulseAudio volume should update the real device volume as well.</p> <h1><span>Step 2. Integrating this with XFCE (or other DE)</span></h1> <p>The way xfce4 handles the volume is two-fold:</p> <ul> <li>There's a xfce4-volumed daemon. It only controls the key bindings. It binds volume up, volume down and mute keys to control the real device controls</li> <li>There's a panel applet called &quot;Audio Mixer&quot; that shows the current volume level and lets you change the volume as well.</li> </ul> <p>Both component are optional and both seem to not work with PulseAudio (even through PulseAudio ALSA emulation which tricks alsamixer for instance).</p> <p>We're going to overcome this problem by replacing these components with two other programs.</p> <h2><span><a href="https://github.com/fernandotcl/pa-applet">pa-applet</a></span></h2> <p>pa-applet will replace the &quot;Audio Mixer&quot; applet. The difference is the pa-applet docks to the systray, so is not XFCE-specific. The downside is we don't have control over the specific position of the icon, all we know is it will appear in the systray (so don't forget to have the systray applet added to the panel).</p> <p>In order to install this software you need to clone the source, and run ./autogen.sh, ./configure, make, sudo make install. You will get information about deps missing, for instance:</p> <div class="code"> <pre><code>configure: error: Package requirements (glib-2.0) were not met: No package 'glib-2.0' found</code></pre></div> <p>You need to find the proper *-dev package for each unmet dependency (for this one it will be libglib2.0-dev).</p> <p>I came across one additional problem. The software seems not updated after some GTK+ 3 updates and it uses a deprecated function. Because the code is configured in a way that every warning stops the compilation, it wouldn't let you compile the code unless you open the src/Makefile file and then find and remove the -Werror flag from it.</p> <h2><span><a href="https://launchpad.net/xfce4-volumed-pulse">xfce4-volumed-pulse</a></span></h2> <p>This part will take care of binding the media keys to the pulse audio controls (rather than to the sound card controls).</p> <p>You need to download the tar package, untar it, ./configure, make, sudo make install. It also requires quite a few libs to be installed, but I didn't found any issues when compiling.</p> <h2><span>Hooking this up together</span></h2> <p>Since I didn't need the original xfce4-volume anymore I decided to remove it:</p> <div class="code"> <pre><code>apt-get remove xfce4-volumed</code></pre></div> <p>But because XFCE will try to launch this anyway on each start, I decided to take advantage of it and replace it with a script:</p> <div class="code"> <pre><code>#!/bin/bash /usr/local/bin/xfce4-volumed-pulse /usr/local/bin/pa-applet</code></pre></div> <p>Add the executable bit, restart the laptop and all should be working correctly at this moment.</p> <h1><span>Setting the hw mixer controls</span></h1> <p>Since PulseAudio won't update the hw controls after you follow up this little howto, it's quite important to set all the important channels to 100% (or other number up to your taste). The way to update the hw controls was described before.</p> <p>Open the terminal, type alsamixer and hit F6. This will give the list of ALSA devices besides the PulseAudio emulation, your real sound cards should display as well. Choose the right one and you should be given access to tweak the real card controls.</p> <p>Note if you removed the PulseAudio paths, the PulseAudio controls wouldn't update when you tweak the hw controls.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343456" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:accessing-https-over-http</guid>
				<title>Accessing HTTPS Over HTTP</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:accessing-https-over-http</link>
				<description>

&lt;p&gt;For one my internal projects, I needed a HTTP-to-HTTPS proxy in a way that a client connects to HTTP network inside the trusted network and the server connects through the Internet to the service via HTTPS.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343456&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sat, 01 Nov 2014 16:47:51 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>For one my internal projects, I needed a HTTP-to-HTTPS proxy in a way that a client connects to HTTP network inside the trusted network and the server connects through the Internet to the service via HTTPS.</p> <div class="content-separator" style="display: none:"></div> <p>I quickly set this up using Apache. Here's the virtual host file:</p> <div class="code"> <pre><code>&lt;VirtualHost *:8371&gt; ServerName localhost ProxyPreserveHost Off SSLProxyEngine On Header edit Set-Cookie secure;.HttpOnly HttpOnly RewriteEngine On RewriteRule ^/(.*) https://remote-server.com/$1 [P,L] ProxyPassReverse / https://remote-server.com/ &lt;/VirtualHost&gt;</code></pre></div> <p>You need to enable the following modules for that: proxy, proxy_http, rewrite, headers</p> <p>Note, above I also mangle the Set-Cookie response headers in a way, that every http-only secure cookie (this means a cookie is transmitted to the server only over a secure transport and is not available on the client side) is converted to a http-only but non-secure.</p> <p>The rule I produced (convert regexp &quot;secure;.HttpOnly&quot; to just &quot;HttpOnly&quot;) may not work for you because I targeted one particular service and the construction of such cookies may be different for the one you want to proxy.</p> <p>The second note is that, the service you're proxying might actually check the protocol on the client side as well, which we cannot mock on the server-level. I was lucky my service didn't have such checks.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343456" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:cups-and-easy-printer-sharing</guid>
				<title>Cups And Easy Printer Sharing</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:cups-and-easy-printer-sharing</link>
				<description>

&lt;p&gt;Today I decided I want to share an USB printer via CUPS. This has always been fun and easy thing to do.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343456&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 22 Apr 2014 20:53:10 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Today I decided I want to share an USB printer via CUPS. This has always been fun and easy thing to do.</p> <p>After spending some time figuring out why this doesn't work out of the box, I learned most of the tutorials are not right about one thing. They claim to share the network in the same (sub)network you don't need any special configuration on the client. That's wrong. You need to install cups-browsed package on the client:</p> <div class="code"> <pre><code>sudo apt-get install cups-browsed</code></pre></div> <p>Then you just wait 30 seconds and you're remote printers should appear in <a href="http://localhost:631/printers">http://localhost:631/printers</a></p> <p>If you want to print from a different network (or your stupid router doesn't bridge Wifi and Ethernet networks) you may need to add a line like that:</p> <div class="code"> <pre><code>BrowsePoll server-name</code></pre></div> <p>to the <tt>/etc/cups/cups-browsed.conf</tt> file.</p> <p>An update: actually BrowsePoll server-name doesn't seem to work. I needed to replace the server name with the server IP address.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343456" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:flash-i-silverlight</guid>
				<title>Flash I Silverlight</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:flash-i-silverlight</link>
				<description>

&lt;p&gt;Z Flashem do niedawna było całkiem nieźle. Wsparcie dla Linuksa było. Paczki w apcie były. W miarę działało. Silverlight był gorszy. Niby był moonlight, ale nigdy nie działał akurat z tymi stronami co się chciało.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343456&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 16 Mar 2014 20:18:47 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Z Flashem do niedawna było całkiem nieźle. Wsparcie dla Linuksa było. Paczki w apcie były. W miarę działało. Silverlight był gorszy. Niby był moonlight, ale nigdy nie działał akurat z tymi stronami co się chciało.</p> <p>Teraz Flash na Linuksa dostępny jest tylko w wersji 11. Jak chcesz wersję 12, to musisz mieć Chrome'a. Można jakimś hakiem wyciągnąć z Chrome'a samą wtyczkę i wrzucić do Chromium, ale to już trochę bez sensu.</p> <p>Natomiast o Moonlighcie to już chyba wszyscy zapomnieli. Przekierowanie ze strony Microsoftu (gdzie kierują strony &quot;brak wtyczki) prowadzi do 404-ki, w apcie susza, w sumie nie wiadomo co robić.</p> <p>Ale dzisiaj odkryłem rozwiązanie obu problemów. Nazywa się ono <a href="http://fds-team.de/cms/pipelight-installation.html">pipelight</a>. Jest to sprytna biblioteka instalująca Windowsowe wtyczki do przeglądarek jako wtyczki do przeglądarek na Linuksie, np. Firefoksa. Korzysta to z wine'a i sprawdziłem, że działa. Zarówno Silverlight jak i Flash 12 odtąd działa elegancko. Przynajmniej do oglądania filmów i transmisji na żywo. Obsługa kamerki w tej &quot;wersji&quot; Flasha nie działa.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343456" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:ubuntu-11-04-natty-on-sony-vaio-sz640</guid>
				<title>Ubuntu 11.04 (Natty) on Sony Vaio SZ640</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:ubuntu-11-04-natty-on-sony-vaio-sz640</link>
				<description>

&lt;p&gt;As always, when a new Ubuntu release is done, I&#039;m installing in onto my Sony Vaio SZ series laptop and experience some problems, that I later work on and finally fix.&lt;/p&gt;
&lt;p&gt;To let others use this knowledge every half a year a note like this is written onto my blog.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343456&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 10 May 2011 16:49:09 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>As always, when a new Ubuntu release is done, I'm installing in onto my Sony Vaio SZ series laptop and experience some problems, that I later work on and finally fix.</p> <p>To let others use this knowledge every half a year a note like this is written onto my blog.</p> <div class="content-separator" style="display: none:"></div> <h1><span>Installation</span></h1> <p>You can read about installation LiveCD issues in a <a href="http://piotrgabryjeluk.wikidot.com/dev:ubuntu-11-04-final">separate blog post</a>. Let's concentrate on things specific to Sony Vaio (mostly the dual-graphics system we have from Sony).</p> <p>Let's just say it's much better to install Ubuntu using the Intel graphics (the graphics-card switch in STAMINA position) card, since it's supported much much better by Linux.</p> <h1><span>Installing nVidia drivers</span></h1> <p>This should be easy, but is not due to a few glitches. Let's get through them step by step:</p> <ol> <li>Have the Ubuntu installed using Intel graphics card (STAMINA mode)</li> <li>Stop the laptop</li> <li>Put the graphics-mode switch to SPEED mode</li> <li>Start the laptop again</li> <li>Wait till you can log in</li> <li>Log in. You won't be able to use the Unity desktop, so classic Ubuntu desktop should be launched (if not, choose &quot;Classic Ubuntu (no effects)&quot; from drop-down list when logging in)</li> <li>Click System &#187; Administration &#187; Additional drivers</li> <li>Choose recommended driver and click enable. This will download and install the nVidia drivers for you.</li> <li>Don't reboot yet. You need to blacklist the nouveau driver (it's the open-source 3D nVidia driver attempt). Do this:<br /> <span class="code-block-inside-li">echo blacklist nouveau | sudo tee /etc/modprobe.d/blacklist-nv.conf</span></li> <li>OK. Now you can reboot. The nvidia driver should kick in and you should have working Unity desktop</li> </ol> <p>One more thing. Intel 3D drivers are now broken, so you won't have the Unity desktop working in there. Let's fix it!</p> <h1><span>Make 3D graphics (and Unity desktop) work in both Intel and nVidia</span></h1> <p>This is basically the same as explained in <a href="http://piotrgabryjeluk.wikidot.com/dev:ubuntu-11-04-final">the previous post</a>, but using separate script (so it's more elegant).</p> <p>Create executable file <tt>/usr/local/bin/detect-gl</tt> :</p> <div class="code"> <pre><code>sudo touch /usr/local/bin/detect-gl sudo chmod +x /usr/local/bin/detect-gl</code></pre></div> <p>Edit it:</p> <div class="code"> <pre><code>sudo gedit /usr/local/bin/detect-gl</code></pre></div> <p>Put the following into it:</p> <div class="code"> <pre><code>#!/bin/bash if ls -l /etc/alternatives/gl_conf | grep nvidia; then link=nvidia else link=mesa fi if lspci | grep 'VGA compatible controller: nVidia Corporation'; then hw=nvidia else hw=intel fi if [ &quot;$link&quot; = &quot;nvidia&quot; -a &quot;$hw&quot; = &quot;intel&quot; ]; then update-alternatives --set gl_conf /usr/lib/mesa/ld.so.conf ldconfig killall Xorg fi if [ &quot;$link&quot; = &quot;mesa&quot; -a &quot;$hw&quot; = &quot;nvidia&quot; ]; then update-alternatives --set gl_conf /usr/lib/nvidia-current/ld.so.conf ldconfig killall Xorg fi</code></pre></div> <p>Call that script from /etc/rc.local (commands from this script are launched on each boot). Open file /etc/rc.local:</p> <div class="code"> <pre><code>sudo gedit /etc/rc.local</code></pre></div> <p>before <tt>exit 0</tt> line, put the following line:</p> <div class="code"> <pre><code>/usr/local/bin/detect-gl</code></pre></div> <p>Your whole file should look more or less like this:</p> <div class="code"> <pre><code>#!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will &quot;exit 0&quot; on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. /usr/local/bin/detect-gl exit 0</code></pre></div> <p>This script will make sure the proper GL library is used for both graphics cards (Mesa lib for Intel, nVidia lib for nVidia card).</p> <h1><span>Fixing nVidia backlight issues</span></h1> <p>This is the most elegant solution I could think of. As the brightness settings almost work (when you press the Fn-F5, Fn-F6 keys, the notification appears and the bar shows you the backlight changes) we'll use D-Bus to listen for backlight change signal to set the backlight using nvclock command.</p> <p>Install nvclock:</p> <div class="code"> <pre><code>sudo apt-get install nvclock</code></pre></div> <p>Now create executable file:</p> <div class="code"> <pre><code>sudo touch /usr/local/bin/nvidia-brightness-helper.py sudo chmod +x /usr/local/bin/nvidia-brightness-helper.py</code></pre></div> <p>Edit it:</p> <div class="code"> <pre><code>sudo gedit /usr/local/bin/nvidia-brightness-helper.py</code></pre></div> <p>Put the following into it:</p> <div class="code"> <div class="hl-main"> <pre><span class="hl-comment">#!/usr/bin/env python</span><span class="hl-code"> </span><span class="hl-reserved">import</span><span class="hl-code"> </span><span class="hl-identifier">dbus</span><span class="hl-code">, </span><span class="hl-identifier">gobject</span><span class="hl-code"> </span><span class="hl-reserved">from</span><span class="hl-code"> </span><span class="hl-identifier">subprocess</span><span class="hl-code"> </span><span class="hl-reserved">import</span><span class="hl-code"> </span><span class="hl-identifier">call</span><span class="hl-code"> </span><span class="hl-reserved">from</span><span class="hl-code"> </span><span class="hl-identifier">dbus</span><span class="hl-code">.</span><span class="hl-identifier">mainloop</span><span class="hl-code">.</span><span class="hl-identifier">glib</span><span class="hl-code"> </span><span class="hl-reserved">import</span><span class="hl-code"> </span><span class="hl-identifier">DBusGMainLoop</span><span class="hl-code"> </span><span class="hl-reserved">def</span><span class="hl-code"> </span><span class="hl-identifier">apply_brightness</span><span class="hl-brackets">(</span><span class="hl-identifier">new_brightness</span><span class="hl-brackets">)</span><span class="hl-code">: </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">new_brightness</span><span class="hl-code"> &lt; </span><span class="hl-number">15</span><span class="hl-code">: </span><span class="hl-identifier">new_brightness</span><span class="hl-code"> = </span><span class="hl-number">15</span><span class="hl-code"> </span><span class="hl-identifier">call</span><span class="hl-brackets">([</span><span class="hl-quotes">'</span><span class="hl-string">nvclock</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-S</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-builtin">str</span><span class="hl-brackets">(</span><span class="hl-identifier">new_brightness</span><span class="hl-brackets">)])</span><span class="hl-code"> </span><span class="hl-comment"># only launch when nVidia is present</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">call</span><span class="hl-brackets">([</span><span class="hl-quotes">'</span><span class="hl-string">bash</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-c</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">lspci | grep &quot;VGA compatible controller: nVidia Corporation&quot; 1&gt;/dev/null</span><span class="hl-quotes">'</span><span class="hl-brackets">])</span><span class="hl-code"> == </span><span class="hl-number">0</span><span class="hl-code">: </span><span class="hl-identifier">dbus</span><span class="hl-code">.</span><span class="hl-identifier">mainloop</span><span class="hl-code">.</span><span class="hl-identifier">glib</span><span class="hl-code">.</span><span class="hl-identifier">DBusGMainLoop</span><span class="hl-brackets">(</span><span class="hl-identifier">set_as_default</span><span class="hl-code">=</span><span class="hl-reserved">True</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-identifier">bus</span><span class="hl-code"> = </span><span class="hl-identifier">dbus</span><span class="hl-code">.</span><span class="hl-identifier">SessionBus</span><span class="hl-brackets">()</span><span class="hl-code"> </span><span class="hl-identifier">bus</span><span class="hl-code">.</span><span class="hl-identifier">add_signal_receiver</span><span class="hl-brackets">(</span><span class="hl-identifier">apply_brightness</span><span class="hl-code">, </span><span class="hl-identifier">dbus_interface</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">org.gnome.PowerManager.Backlight</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">signal_name</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">BrightnessChanged</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-identifier">loop</span><span class="hl-code"> = </span><span class="hl-identifier">gobject</span><span class="hl-code">.</span><span class="hl-identifier">MainLoop</span><span class="hl-brackets">()</span><span class="hl-code"> </span><span class="hl-identifier">loop</span><span class="hl-code">.</span><span class="hl-identifier">run</span><span class="hl-brackets">()</span></pre></div> </div> <p>Now open your <em>Startup programs</em> configuration dialog and add the script to things started when you log in.</p> <h1><span>Fixing suspend</span></h1> <p>I must confess I haven't check the suspend without doing this but suspecting it IS broken like in was in Maverick, I've blacklisted the TPM modules by putting:</p> <div class="code"> <pre><code>blacklist tpm blacklist tpm_bios blacklist tpm_tis blacklist tpm_infineon</code></pre></div> <p>into <tt>/etc/modprobe.d/blacklist-tpm.conf</tt> file.</p> <h1><span>Poor 3D performance</span></h1> <p>When running Unity all the 3D games have poor performance. I found the easiest workaround is to log in into <em>Classic Ubuntu (with no effects)</em> desktop, which gives you standard GNOME with no compiz and nice 3D performance for launched apps.</p> <h1><span>Dual-screen issues</span></h1> <p>I'm using a dual-screen setup (laptop's LCD + external monitor connected via VGA port). The current version of Ubuntu has multiple issues with this, especially when aligning the screens in vertical (laptop's screen being the bottom one, big LCD the top one). The &quot;dock&quot; or &quot;launcher&quot; if you wish appears on the wrong screen (the small laptop instead of on the big screen). To fix this do this:</p> <div class="code"> <pre><code>xrandr --output VGA1 --primary</code></pre></div> <p>Log out and in again after doing this. Launcher is on top screen now :-).</p> <p>I found another irritating bug: when you plug in a big external monitor into the VGA port, the desktop automatically expands to both monitor (not a bug yet), but on one or both of them, some area is black, so you can't see the menus and windows. Logging out and in is also a workaround for this.</p> <p>When you log in with an external monitor connected, the desktop is strangely stretched and has some artifacts. Interestingly taping Super button (to show the Ubuntu Dash) and Escape (to hide it) refreshes the screen and it looks OK then.</p> <p>It's hard to put some windows on the bottom screen (your mouse pointer stops on the bottom of the top screen while dragging). You can move the windows even further down using Alt and dragging by window content (and not the title bar).</p> <p>Once a window is on the bottom screen, trying to resize it crashes the application and it disappears&#8230; The workaround is to resize by holding Alt key and drag with middle mouse button.</p> <h1><span>Other issues</span></h1> <p>When using Intel graphics card and Unity, Adobe Flash movies (YouTube for example) shows some artifacts. From time to time they also crash the whole X session (I'm not sure why).</p> <p>OK, this would be it. Hope this helps someone.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343456" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:ubuntu-11-04-final</guid>
				<title>Ubuntu 11.04 final</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:ubuntu-11-04-final</link>
				<description>

&lt;p&gt;A few weeks after testing &lt;a href=&quot;http://piotrgabryjeluk.wikidot.com/dev:ubuntu-11-04-beta-1&quot;&gt;Ubuntu 11.04 beta 1&lt;/a&gt; which brought me a bit of disappointment, I decided to test the recently released final version of this most popular Linux distribution.&lt;/p&gt;
&lt;p&gt;As I had no more CDs or DVDs, I decided to try booting the distribution from USB drive that I assembled from microSDHC card reader and a microSD 4GB card that I got with my Android phone using standard Ubuntu tool called &amp;quot;Boot disk assistant&amp;quot;, which burns CD ISO file onto a USB drive in a way that it becomes bootable equivalent of the CD with additional option to save the modifications you make to the Live system on the disk itself, so that it becomes more or less persistent.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343456&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Thu, 05 May 2011 17:45:25 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>A few weeks after testing <a href="http://piotrgabryjeluk.wikidot.com/dev:ubuntu-11-04-beta-1">Ubuntu 11.04 beta 1</a> which brought me a bit of disappointment, I decided to test the recently released final version of this most popular Linux distribution.</p> <p>As I had no more CDs or DVDs, I decided to try booting the distribution from USB drive that I assembled from microSDHC card reader and a microSD 4GB card that I got with my Android phone using standard Ubuntu tool called &quot;Boot disk assistant&quot;, which burns CD ISO file onto a USB drive in a way that it becomes bootable equivalent of the CD with additional option to save the modifications you make to the Live system on the disk itself, so that it becomes more or less persistent.</p> <div class="content-separator" style="display: none:"></div> <h1><span>LiveUSB creation</span></h1> <p>First I decided to use that option and let the program use about 3&#160;GB for the overlay file. This made the program busy for about a half an hour, the card reader (actually writer) got warm, and the result was the USB was not that bootable.</p> <p>A day after that attempt I decided to give it a try without the persistence and it worked this time. The problem came when I tried to &quot;Try Ubuntu&quot; (in opposite to &quot;Install Ubuntu&quot;). The graphic mode quited and I got nothing in return. I tried multiple things to do in text mode, rebooted a few times and after that it appeared that the graphic mode re-run after about a minute. The CPU was completely idle in this time as was the disk, so this wasn't reasonable thing.</p> <p>Anyways it appeared the release was much more stable than the beta version I tested and it kind of even worked. I found a few concepts useful and cool, so I decided to put the system on my disk to give it a serious try.</p> <h1><span>Having it on disk</span></h1> <p>Automatically detecting an external monitor was the biggest positive surprise for me. This never worked in Ubuntu till now. The downside is the graphics got crazy and displayed desktop in not really usable chunks, but I moved some windows around and it got fixed.</p> <h1><span>nVidia troubles</span></h1> <p>Then I tried booting with nVidia graphics card enabled (I have a dual-graphics Sony Vaio laptop) to see if the drivers would automatically install. Ubuntu first booted into classic Ubuntu mode (no fancy Unity desktop shell) but it was usable. I navigated to <em>System &#187; Administration &#187; Additional Drivers</em> and chose the recommended proprietary nVidia drivers to install. They got installed and I was asked to reboot the computer so I did.</p> <p>After the reboot graphic mode was not working and so didn't the text mode. I rebooted with Intel graphics card to discover that installing the nVidia drivers broke Intel drivers which made me without Unity desktop shell even on previously working Intel card. Since I knew what to do to &quot;fix&quot; nVidia I did this &#8212; I blacklisted the <tt>nouveau</tt> module and also a bunch of <tt>tpm</tt> modules that prevented from proper resume after suspend in previous version of Ubuntu. And rebooted with nVidia card chosen.</p> <p>This time Xorg went up, the Unity showed up and everything was more or less OK. After removing nVidia drivers (<tt>apt-get remove nvidia-current</tt>) Intel got working Unity back. But I wanted to have Unity working on both graphics card without constant installing and uninstalling nVidia drivers and I figured out how to do it.</p> <h1><span>Automating Intel/nVidia boots</span></h1> <p>In <tt>/etc/rc.local</tt> before <tt>exit 0</tt> I entered something like this:</p> <div class="code"> <pre><code>if ls -l /etc/alternatives/gl_conf | grep nvidia; then link=nvidia else link=mesa fi if lspci | grep 'VGA compatible controller: nVidia Corporation'; then hw=nvidia else hw=intel fi if [ &quot;$link&quot; = &quot;nvidia&quot; -a &quot;$hw&quot; = &quot;intel&quot; ]; then update-alternatives --set gl_conf /usr/lib/mesa/ld.so.conf ldconfig killall Xorg fi if [ &quot;$link&quot; = &quot;mesa&quot; -a &quot;$hw&quot; = &quot;nvidia&quot; ]; then update-alternatives --set gl_conf /usr/lib/nvidia-current/ld.so.conf ldconfig killall Xorg fi</code></pre></div> <p>This code checks whether current GL implementation is nVidia (valid for nVidia card) or Mesa (valid for Intel card), then checks current card by examining the output of <tt>lspci</tt> command and uses certain <tt>update-alternatives</tt> lines followed by <tt>ldconfig</tt> to update the GL implementations. <tt>killall Xorg</tt> kills the X server which is brought back by login manager with GL library updated.</p> <p>This is a dirty hack but it works just well for me and made both graphic cards working with no additional work.</p> <h1><span>Glitches/Summary</span></h1> <p>Ubuntu seems very stable now, but X server crashed a few times (especially loading Flash videos from Vimeo in Firefox). There are some problems in multi-monitor configurations, like no way to move the window to bottom monitor (if they are aligned vertically) by dragging its top bar (moving with Alt works). The windows on bottom monitor are not maximized properly (they are maximized on the top monitor instead) and they can't be resized by dragging the resize handles (but resizing with Alt+middle mouse button works).</p> <p>There were some other small random issues, either not really relevant or easily fixable, but overall it seems a <em>very good beta release</em>. But wait. This is no beta, but final release. In this case it's not good. It's OK for a Linux user like me, but it definitely should not be released for regular users. Shame on you Canonical. They promised they release in April, but they should have release another beta release, do a serious testing (what I did was anything but unusual), <strong>fix the remaining bugs and then release the final version</strong>.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343456" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:wrtu54g-tm-running-x-wrt</guid>
				<title>WRTU54G-TM running X-Wrt</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:wrtu54g-tm-running-x-wrt</link>
				<description>

&lt;p&gt;OK, so some time ago I bought a Linksys WRTU54G-TM. It&#039;s powered by Infineon ADM8668 processor (at 200&amp;#160;MHz) and has 64&amp;#160;MB RAM, which makes is pretty powerful router. Also it&#039;s really cheap. It looks like this:&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343457&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 20 Apr 2011 20:59:29 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>OK, so some time ago I bought a Linksys WRTU54G-TM. It's powered by Infineon ADM8668 processor (at 200&#160;MHz) and has 64&#160;MB RAM, which makes is pretty powerful router. Also it's really cheap. It looks like this:</p> <div class="content-separator" style="display: none:"></div> <p style="text-align: center;"><img src="http://farm4.static.flickr.com/3238/2612942957_3197bdd443.jpg" alt="2612942957_3197bdd443.jpg" class="image" /></p> <p>The problem with this router is that there was no cool open source software for it. Linksys opened its sources, but I meant something like DD-WRT or OpenWRT. The problem is that the CPU architecture is different from for example the widely known and used WRT54G series.</p> <p>Nonetheless there was some heavy work done to run a custom Linux firmware on it. After some successes, the author decided to port OpenWRT distribution to this router. And this is how it's done :-).</p> <p>The OpenWRT is a command-line distribution of Linux for a bunch of routers. There is a web interface called X-Wrt which is installable as a opkg package to the OpenWRT systems, but there is no real information of how to install it on specifically WRTU54G-TM.</p> <p>The good news is it can be done, the bad news is you have to hack it a little (but only very little). So let's go.</p> <p>First, you need to &quot;update&quot; the software of the router to the OpenWRT version. The reference here is: <a href="http://wiki.scottn.us/wrtu54g-tm">http://wiki.scottn.us/wrtu54g-tm</a>. Just log in to the router WWW interface, select Administration &#187; Firmware Upgrade and choose this file wrtu54g-tm-openwrt-devel-b5.bin (download it from <a href="http://wrt.scottn.us/wrtu54g-tm-openwrt-devel-b5.bin">http://wrt.scottn.us/wrtu54g-tm-openwrt-devel-b5.bin</a>).</p> <p>This takes a while. Router then reboots. Give it a few minutes to load and install. After that the power LED keeps blinking which is probably a bug (in the official firmware, the LED blinks while the system is loading, but once it's up it lights still).</p> <p>Connect to one of 4 Ethernet ports and you should be given an address IP in the 192.168.1.* network. If not, assign yourself one (for example 192.168.1.10). Then you can confirm the router is up, by pinging it:</p> <div class="code"> <pre><code>ping 192.168.1.1</code></pre></div> <p>Trying to ssh to it will reveal you can't really do it, since you don't know the root password. This is tricky, but you need telnet to the router:</p> <div class="code"> <pre><code>telnet 192.168.1.1</code></pre></div> <p>You'll be given the root shell. Set the password:</p> <div class="code"> <pre><code>passwd</code></pre></div> <p>You'll need to enter the password twice for confirmation. Don't forget it :-).</p> <p>Now you can ssh to the router:</p> <div class="code"> <pre><code>ssh root@192.168.1.1</code></pre></div> <p>Deal with the RSA &quot;host not known&quot; warnings etc, and supply the password you just set.</p> <p>If you connected the router to the network (by Ethernet cable to the &quot;Internet&quot; port) and your ISP has DHCP server, you should already have the Internet connectiong:</p> <div class="code"> <pre><code>ping google.com</code></pre></div> <p>If you need to supply the static IP address, edit the following file:</p> <div class="code"> <pre><code>/etc/config/network</code></pre></div> <p>You can use vim (busybox version) editor:</p> <div class="code"> <pre><code>vim /etc/config/network</code></pre></div> <p><tt>wan</tt> network corresponds to the Internet connection, while <tt>lan</tt> to the 4-port switch.</p> <p>In this scenario it's possible you also have to supply the DNS servers, so instead of checking the Internet connectivity by pinging google.com, ping some IP address, like:</p> <div class="code"> <pre><code>ping 8.8.8.8</code></pre></div> <p>Once you have the Internet connection, you can update the packages repositories, so you can install the X-Wrt interface:</p> <div class="code"> <pre><code>mv /etc/opkg.conf /etc/original.opkg.conf cat &gt; /etc/opkg.conf</code></pre></div> <p>Enter the following:</p> <div class="code"> <pre><code>src/gz adm8668 http://wrt.scottn.us/packages src/gz snapshots http://downloads.openwrt.org/snapshots/trunk/brcm47xx/packages dest root / dest ram /tmp lists_dir ext /var/opkg-lists option overlay_root /overlay arch all 5 arch brcm47xx 10 arch adm8668 20</code></pre></div> <p>&#8230; and press Ctrl-D. Your /etc/opkg.conf file should now contain the lines above. Update the repositories:</p> <div class="code"> <pre><code>opkg update</code></pre></div> <p>Install the X-Wrt, which is packed in package named webif:</p> <div class="code"> <pre><code>opkg install webif</code></pre></div> <p>Now if you point your web browser to <a href="http://192.168.1.1/">http://192.168.1.1/</a> you should have a poor 404 page. It seems the permissions of the /www directory are wrong. I just did that to fix the problem:</p> <div class="code"> <pre><code>chmod -R a+rX /www /etc/init.d/uhttpd restart</code></pre></div> <p>Now you can log to the Web interface in with your login (root) and password.</p> <p>You can now play with the router settings using the browser :-). Much simpler.</p> <p>References:</p> <p><a href="http://wiki.scottn.us/wrtu54g-tm">http://wiki.scottn.us/wrtu54g-tm</a><br /> <a href="http://wiki.openwrt.org/doc/start">http://wiki.openwrt.org/doc/start</a></p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343457" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:ubuntu-11-04-beta-1</guid>
				<title>Ubuntu 11.04 Beta 1</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:ubuntu-11-04-beta-1</link>
				<description>

&lt;p&gt;Let&#039;s talk about Ubuntu 11.04 Beta 1. Honestly I don&#039;t think it really should be beta already. It just doesn&#039;t work for me. I think the only reason the &amp;quot;release&amp;quot; is called beta is that it&#039;s April already and the stable version of the system should be delivered to the end of it to justify the 11.04 name/version.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343457&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Fri, 08 Apr 2011 21:05:12 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Let's talk about Ubuntu 11.04 Beta 1. Honestly I don't think it really should be beta already. It just doesn't work for me. I think the only reason the &quot;release&quot; is called beta is that it's April already and the stable version of the system should be delivered to the end of it to justify the 11.04 name/version.</p> <div class="content-separator" style="display: none:"></div> <p>Let's start from the beginning. I'm having a Sony Vaio laptop with dual graphics system. During boot I can switch if nVidia or Intel graphics card is used. While on nVidia card, I didn't encounter any problems but the thing in &quot;Extra Drivers&quot; no nVidia card was detected. I'm not sure, maybe this &quot;automatic&quot; 3rd party driver installation is only activated after a real install.</p> <p>I really wanted to see the new Ubuntu interface, so I switched to Intel graphics card and rebooted the machine. After a while I was able to &quot;Try Ubuntu&quot;, I started the Firefox and then I noticed I don't have a network connection configured, so I clicked the network manager icon, chose my wifi network and tried to enter the password, but this caused compiz to close unexpectedly. Multiple times. After I managed to click &quot;cancel&quot; button the window decorations were gone and keyboard focus was not passed to clicked field, which made my system unusable. The standard shortcut to run command in Ubuntu: Alt-F2 didn't work either.</p> <p>This was a pretty short test, but not passed at all. Ubuntu 11.04 doesn't deserve beta status, there are stability issues. For example trying to suspend the laptop in nVidia mode (without any commercial drivers) froze it instead so i had to reboot :-(.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343457" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:sony-vaio-vgn-sz640-ubuntu-maverick</guid>
				<title>Sony Vaio VGN-SZ640 Ubuntu Maverick</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:sony-vaio-vgn-sz640-ubuntu-maverick</link>
				<description>

&lt;p&gt;Recently I updated the Ubuntu I&#039;m using on my laptop to version 10.10 (codename Maverick).&lt;/p&gt;
&lt;p&gt;Although things work pretty good, I had to do some tricks to make it work in specific areas.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343457&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Thu, 04 Nov 2010 20:21:19 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Recently I updated the Ubuntu I'm using on my laptop to version 10.10 (codename Maverick).</p> <p>Although things work pretty good, I had to do some tricks to make it work in specific areas.</p> <div class="content-separator" style="display: none:"></div> <h1><span>Broken suspend</span></h1> <p>It seems tpm* modules (who knows what they are for?) break this. Putting file like this:</p> <div class="code"> <pre><code># With these modules loaded suspend doesn't work blacklist tpm blacklist tpm_bios blacklist tpm_tis blacklist tpm_infineon</code></pre></div> <p>to /etc/modprobe.d/blacklist-tpm.conf (and rebooting) solves the problem for me.</p> <h1><span>Brightness buttons not working</span></h1> <p>Run this code in terminal:</p> <div class="code"> <pre><code>while true; do line=`acpi_listen | head -n 1`; if echo &quot;$line&quot; | grep 'sony/hotkey SPIC 00000001 00000010'; then xbacklight -dec 25 -time 0 -steps 1 smartdimmer -d fi if echo &quot;$line&quot; | grep 'sony/hotkey SPIC 00000001 00000011'; then xbacklight -inc 25 -time 0 -steps 1 smartdimmer -i fi done</code></pre></div> <p>You need to have smartdimmer and xbacklight package. The keys kind of work now (but quite lamely).</p> <h1><span>Other stuff</span></h1> <p>The <tt>Ubuntu</tt> font is great. I love it. It seems nouveaux driver (for nVidia card) is really good. It supports multi-monitor configuration via xrandr and other standard stuff. Unfortunately you won't get 3D effects (Compiz) with it and you'll need to install nVidia commercial drivers for it.</p> <p>Consult <a href="http://piotrgabryjeluk.wikidot.com/sony-vaio-sz-series-and-linux">Sony Vaio SZ Series And Linux</a> for more (mostly old) information.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343457" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:playing-unreal-tournament-on-ubuntu-lucid</guid>
				<title>Playing Unreal Tournament On Ubuntu Lucid</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:playing-unreal-tournament-on-ubuntu-lucid</link>
				<description>

&lt;p&gt;I wanted to play Unreal Tournament on Ubuntu 10.04 (Lucid Lynx) 64-bit. Linux is theoretically supported by Unreal Tournament, by using custom installer. So this is how to do it:&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343457&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Mon, 17 May 2010 07:16:31 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>I wanted to play Unreal Tournament on Ubuntu 10.04 (Lucid Lynx) 64-bit. Linux is theoretically supported by Unreal Tournament, by using custom installer. So this is how to do it:</p> <div class="content-separator" style="display: none:"></div> <h1><span>Get Unreal Tournament</span></h1> <p>The most likely version to obtain is UT GOTY (Game Of The Year edition).</p> <h1><span>Get Installer</span></h1> <p>Go here:</p> <p><a href="http://www.liflg.org/?catid=6&amp;gameid=51">http://www.liflg.org/?catid=6&amp;gameid=51</a></p> <p>There are two installers. Download both using BitTorrent client. For me the one witout &quot;goty&quot; worked.</p> <p>Run installer like this:</p> <blockquote> <p>sudo bash /path/to/unreal.tournament_436-multilanguage.run</p> </blockquote> <p>Probably it won't run, because you don't have GTK 1.2. Bad news, GTK 1.2 isn't even available in system repository. The last Ubuntu version that shipped GTK 1.2 was Ubuntu Jaunty. My favorite trick to get packages from older distros is as follows:</p> <blockquote> <p>sudo sed s/lucid/jaunty/g /etc/apt/sources.list -i<br /> sudo aptitude update<br /> sudo aptitude install -y libgtk1.2<br /> sudo sed s/jaunty/lucid/g /etc/apt/sources.list -i<br /> sudo aptitude update</p> </blockquote> <p>Try to run the installer, it should work now.</p> <p>Default options are generally OK, so you can keep them. Once &quot;enter CD&quot; dialog appears, you need to either enter the CD or mount the ISO image using the following command:</p> <blockquote> <p>sudo mount /path/to/the/iso-file.iso /media/cdrom</p> </blockquote> <p>Click OK, and the installer continues to run. If you're asked to enter CD2 and you don't have one, try the second installer (the one without &quot;goty&quot;) from loki site.</p> <h1><span>Running UT</span></h1> <p>I had no luck in running UT:</p> <blockquote> <p>quake@vaio ~ $ ut<br /> Signal: SIGIOT [iot trap]<br /> Aborting.</p> </blockquote> <p>From <a href="http://www.unrealadmin.org/forums/showthread.php?t=12432">this thread</a> I've learned it could be solved by doing this:</p> <blockquote> <p>cd /usr/local/games/ut/System<br /> for i in ../Maps/*.uz ; do sudo ./ucc-bin decompress $i ; done<br /> mv *.unr ../Maps</p> </blockquote> <p>After doing this, you should be able, to run ut successfully.</p> <h1><span>Changing resolution</span></h1> <p>I was not able to change resolution (once I changed it, it was going back to 640x480 after a few seconds). Open file ~/.loki/ut/System/UnrealTournament.ini, locate &quot;640&quot; and &quot;480&quot; in it and change to desired resolution.</p> <h1><span>High speed</span></h1> <p>When I run UT it seemed going about 5 times faster than it should. After reading much about -cpuspeed option and playing with CPU downclocking I figured out that without sound it runs OK. After some experimenting it seems, that it's pulseaudio is causing it, once I killed it and prevented to run (it auto-respawns for some reason) UT finally worked at good speed.</p> <blockquote> <p>sudo chmod -x /usr/bin/pulseaudio<br /> killall pulseaudio<br /> ut</p> </blockquote> <p>The problem with this is that some process continuously tries to run pulseaudio, which causes CPU to be loaded and ut to run not smoothly.</p> <p>So this should work:</p> <blockquote> <p>sudo mv /usr/bin/pulseaudio /usr/bin/pulseaudio.original<br /> echo -e '#!/bin/bash\nsleep 10000' | sudo tee /usr/bin/pulseaudio<br /> sudo chmod +x /usr/bin/pulseaudio<br /> killall pulseaudio<br /> ut</p> </blockquote> <p>Remember to do this after playing ut:</p> <blockquote> <p>sudo mv /usr/bin/pulseaudio.original /usr/bin/pulseaudio</p> </blockquote> <p>If you have some problems with sound after playing UT, log out and in again, and it should be OK.</p> <p><strong>NOTE:</strong> this trick should be equivalent to running pasuspender ut, but for some reason it does not work.</p> <h1><span>More tricks</span></h1> <p>When playing on LAN party we discovered more tricks:</p> <p>To let UT correctly determine CPU speed, you need to set CPU frequency (using some applet or cpufrequtils) and disable additional cores (leaving one):</p> <blockquote> <p>echo 0 | sudo tee /sys/devices/system/cpu/cpu1/online<br /> echo 0 | sudo tee /sys/devices/system/cpu/cpu2/online<br /> echo 0 | sudo tee /sys/devices/system/cpu/cpu3/online<br /> echo 0 | sudo tee /sys/devices/system/cpu/cpu4/online<br /> echo 0 | sudo tee /sys/devices/system/cpu/cpu5/online<br /> echo 0 | sudo tee /sys/devices/system/cpu/cpu6/online<br /> echo 0 | sudo tee /sys/devices/system/cpu/cpu7/online</p> </blockquote> <p>(if you have 8 cores, cpu0 will be online, the rest offline).</p> <p>Next trick is disabling desktop effects or window composing. For one person this meant much smoother graphics, for other it meant working sound (which is very weird, but yes, that's true).</p> <h1><span>UPDATE: Maverick Audio</span></h1> <p>It seems that on maverick the pulseaudio hack is not working, but here's what you can do instead:</p> <ul> <li>edit /usr/local/bin/ut (may be located somewhere else, find when you installed the game)</li> <li>find this line: ./$GAME_BINARY &quot;$CMD_ARGS&quot; &quot;$@&quot;</li> <li>replace with: <strong>padsp</strong> ./$GAME_BINARY &quot;$CMD_ARGS&quot; &quot;$@&quot;</li> <li>(make sure you have the padsp binary, just run try to run it)</li> <li>then just run <tt>ut</tt> and sound works :-)</li> </ul> <p><strong>UPDATE</strong>: this works, but gives significant audio lags (200-300&#160;ms!). This basically sucks. So the other workaround is:</p> <ul> <li>having alsa-oss installed (program aoss)</li> <li>having a proper .asoundrc in home directory:</li> </ul> <div class="code"> <pre><code>ctl.!default { type hw card 0 } pcm.dmixer { #this virtual device does the mixing of type dmix #the various signals ipc_key 1024 slave { pcm &quot;hw:0,0&quot; period_time 0 period_size 1024 buffer_size 4096 rate 44100 } bindings { 0 0 1 1 } } pcm.!default { #this means that applications use the mixer type plug #by default, so you can hear everything slave.pcm &quot;dmixer&quot; }</code></pre></div> <ul> <li>having 32 bit alsa-oss libs installed (getlibs -p alsa-oss)</li> </ul> <p>You need /usr/lib32/libaoss.so. Once you have it backup /usr/lib/libaoss.so and link it to the 32 bit version: /usr/lib32/libaoss.so. Then edit the <tt>ut</tt> script like before but instead of <tt>padsp</tt> use <tt>aoss</tt>. This works for me. WARNING: this overrides all ALSA applications. If you want the default configuration (that routes the audio to pulseaudio), you'll need to change .asoundrc file name after playing UT.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343457" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:home-directory-snapshots</guid>
				<title>Home Directory Snapshots</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:home-directory-snapshots</link>
				<description>

&lt;p&gt;Your home directory is where the most important data is stored.&lt;/p&gt;
&lt;p&gt;But from time to time you just simply &lt;tt&gt;rm -Rf ~&lt;/tt&gt; and your all precious data is totally out of luck. Backups you say, don&#039;t you?&lt;/p&gt;
&lt;p&gt;So let&#039;s think how do you do backups. &lt;tt&gt;cp /home/quake /my/distant/location&lt;/tt&gt; ? On my 24&amp;#160;GB home directory? It would take hours. &lt;tt&gt;cp /home/quake /home/backups/quake/date&lt;/tt&gt; ? Better, this will take a few minutes, but wait, I have like 120&amp;#160;GB of disk space, which means I can have no more than 5 backups.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343457&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 25 Oct 2009 16:12:38 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Your home directory is where the most important data is stored.</p> <p>But from time to time you just simply <tt>rm -Rf ~</tt> and your all precious data is totally out of luck. Backups you say, don't you?</p> <p>So let's think how do you do backups. <tt>cp /home/quake /my/distant/location</tt> ? On my 24&#160;GB home directory? It would take hours. <tt>cp /home/quake /home/backups/quake/date</tt> ? Better, this will take a few minutes, but wait, I have like 120&#160;GB of disk space, which means I can have no more than 5 backups.</p> <div class="content-separator" style="display: none:"></div> <p>What to do with this? There are two posibilities. Either you minimize data to backup to only backup important data (but figuring out what data is important may take some time and be inappropriate) or move to smarter solution, like incremental backups. Or snapshots.</p> <p>Having brtfs as the filesystem for my home directory, I chose to make a snapshot of it each hour. It takes between 0 and 1 second to complete and uses almost no disk space. Why? Btrfs is copy-on-write filesystems, which means cloning a filesystems is instant as it only makes it available under two locations. And then modifying one of the two makes a real copy of the modified fragment of it and changes that copy.</p> <p>OK. How to do it.</p> <p>First create a btrfs filesystem (you'll need a recent kernel and btrfs-utils):</p> <div class="code"> <pre><code># mkfs.btrfs /dev/sda7</code></pre></div> <p>(sda7 is partition for my /home directory)</p> <p>Then mount it somewhere else than /home, let's use /vol as an example:</p> <div class="code"> <pre><code># mount /dev/sda7 /vol</code></pre></div> <p>Create some volumes on that filesystem: home, quake, snapshots:</p> <div class="code"> <pre><code># btrfsctl -S home /vol # btrfsctl -S quake /vol # btrfsctl -S snapshots /vol</code></pre></div> <p>The volumes are accessible as the subdirectories of /vol:</p> <div class="code"> <pre><code># ls -la /vol drwx------ 1 root root 36 1970-01-01 01:00 . drwxr-xr-x 24 root root 4096 2009-10-25 15:04 .. drwx------ 1 root root 20 2009-10-25 15:51 home drwx------ 1 root root 11488 2009-10-25 16:17 quake drwx------ 1 root root 76 2009-10-25 15:40 snapshots</code></pre></div> <p>But you can mount then separately:</p> <div class="code"> <pre><code># mount /dev/sda7 /home -o subvolume=home # mkdir /home/quake # mount /dev/sda7 /home/quake -o subvolume=quake</code></pre></div> <p>Fix permissions:</p> <div class="code"> <pre><code># chown quake:quake /home/quake /vol/quake /vol/snapshots # chmod 0755 /home/ /home/quake</code></pre></div> <p>Now you're ready to do snapshots. Now populate the /home/quake directory:</p> <div class="code"> <pre><code>$ mkdir /home/quake/abcd $ mkdir /home/quake/dddd $ mkdir /home/quake/abcd/eeee $ echo testtest &gt; /home/quake/testfile</code></pre></div> <p>Aaaaaand, make snapshots!</p> <div class="code"> <pre><code>$ btrfs -s /vol/snapshots/quake-`date +%Y%m%d-%H%M` /vol/quake</code></pre></div> <p>I figured out, that it's quite important to point to /vol/quake and not /home/quake. At first it seams that it's totally the same, but on /home/quake there can be some other filesystems mounted (like .gvfs for GNOME virtual file systems) and /vol/quake contains &quot;pure data&quot;. When doing snapshots of /home/quake with filesystems mounted under it, the filesystems freezes for me (btrfs is still experimental, they say). So as noted above, it's better to snapshot pure data directory.</p> <p>Now, the /vol/snapshots/quake-20091025-1653 (or whatever your date is) and /vol/quake should list the same files and the operation of &quot;cloning&quot; should be just instant no matter how much data you have. But now modifying the contents of /vol/quake should not change anything in /vol/snapshots/quake-20091025-1653 (but of course should in /home/quake).</p> <p>Also the snapshot doesn't really take any disk space as long as you keep the /vol/quake directory unchanged. Once you change some file from /vol/quake, it needs to really keep two copies of it, so this is when additional space is allocated.</p> <p>To sum up let's have a table listing possibilities to have the same contents in two directories:</p> <table class="wiki-content-table"> <tr> <th>method</th> <th>file copy</th> <th>symbolic link</th> <th>hard link</th> <th>bind-mount</th> <th>btrfs' clone</th> </tr> <tr> <th>how</th> <td>cp -a dir1 dir2</td> <td>ln -s dir1 dir2</td> <td>ln dir1 dir2</td> <td>mount -o bind dir1 dir2</td> <td>btrfs-bcp dir1 dir2</td> </tr> <tr> <th>time</th> <td>long</td> <td><strong>instant</strong></td> <td><strong>instant</strong></td> <td><strong>instant</strong></td> <td><strong>instant</strong></td> </tr> <tr> <th>takes disk space</th> <td>yes</td> <td><strong>no</strong></td> <td><strong>no</strong></td> <td><strong>no</strong></td> <td><strong>no</strong> (only the difference)</td> </tr> <tr> <th>points to the same data<br /> (changing file in dir1 changes it in dir2)</th> <td><strong>no</strong></td> <td>yes</td> <td>yes</td> <td>yes</td> <td><strong>no</strong></td> </tr> <tr> <th>notes</th> <td></td> <td></td> <td>not on Linux (Mac only?)</td> <td></td> <td>btrfs-bcp not distributed in Ubuntu's btrfs-tools</td> </tr> </table> <p>More notes on btrfs and snapshotting:</p> <ul> <li>What can be done with btrfs-bcp on directories level can be done with snapshots on volumes level (as described in this post)</li> <li>Snapshots in btrfs are not removable yet. You can clear them and reclaim the space taken by saved difference from the starting point. Still a few bytes is taken by having the directory that is not removable. Deleting snapshots is to be implemented in stable version of btrfs.</li> </ul> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343457" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:ubuntu-and-intel-agn-wireless-card</guid>
				<title>Ubuntu And Intel AGN Wireless Card</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:ubuntu-and-intel-agn-wireless-card</link>
				<description>

&lt;p&gt;I &lt;strong&gt;finally&lt;/strong&gt; managed to get a version of kernel/modules that work nice on my wireless card:&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343457&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 19 May 2009 15:20:42 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>I <strong>finally</strong> managed to get a version of kernel/modules that work nice on my wireless card:</p> <div class="content-separator" style="display: none:"></div> <div class="code"> <pre><code>06:00.0 Network controller: Intel Corporation PRO/Wireless 4965 AG or AGN [Kedron] Network Connection (rev 61)</code></pre></div> <p>I had problems since late Hardy or Intrepid, using different kernel from that time with no luck. The worst case was connecting to WPA2 Enterprise (user/password) secured network. In worst subcase, I had the connection for 5-20 minutes and after that the network card or driver hanged and then only computer reboot used to help.</p> <p>I was used to see <tt>iwlist scan</tt> errors like &quot;Resource temporarily unavailable&quot; or &quot;Busy&quot;. <tt>dmesg</tt> showed different things on different kernels.</p> <p>My frustration was great, when the problem started (after some upgrades that meant to improve things) to appear even on unsecured network. The connection was broken and I had to notoriously reconnect with my NetworkManager.</p> <p>Finally I found a version of kernel that plays well.</p> <p>It's from jaunty-proposed repository (enable it in your Synaptic or other package manager). Don't use jaunty-backports (this one was only broken). The package that solves things is: <strong>linux-backports-modules-jaunty</strong> version <strong>2.6.28.12.16</strong>. The install should also update the linux-image to 2.6.18-12 (update your grub.conf as usual to include the changes).</p> <p>After rebooting, run uname, to verify the kernel version:</p> <div class="code"> <pre><code># uname -a Linux vaio 2.6.28-12-generic #43-Ubuntu SMP Fri May 1 19:31:32 UTC 2009 x86_64 GNU/Linux</code></pre></div> <p>This is crucial here: <strong>2.6.28-12-generic</strong>. The original Ubuntu kernel is 2.6.28-11 not -12.</p> <p>Hope this helps someone (with VAIO SZ or any other Intel AGN-enabled notebook with Ubuntu).</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343457" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:snapshots-of-filesystems-under-linux</guid>
				<title>Snapshots Of Filesystems Under Linux</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:snapshots-of-filesystems-under-linux</link>
				<description>

&lt;p&gt;Today I&#039;ve learnt about making snapshots of regular filesystems in Linux.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773343457&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Fri, 07 Mar 2008 21:47:09 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Today I've learnt about making snapshots of regular filesystems in Linux.</p> <p>First of all, this is a link to the article I've found and seems to be quite OK: <a href="http://howtoforge.com/linux_lvm_snapshots_p2">http://howtoforge.com/linux_lvm_snapshots_p2</a></p> <p>The idea is simple. We have to:</p> <ol> <li>Have LVM partition</li> <li>Set up some (I believe this is not limited to standard ext3) partitions on it</li> <li>Prepare some place for backups (over network or on a separate disk)</li> <li>Then at any time, we can just create a snapshot - this does not really consume MUCH resources &#8212; but consumes SOME.</li> <li>This takes not more than 1 second and creates a device/file/something that is an image of the filesystem in the exact moment of creating the snapshot.</li> <li>Having the image (snapshot) we can do anything with it (like with a block device) &#8212; mount (and backup the files), create a raw-copy, export to another machine, clone, whatever.</li> </ol> <h3><span>Notes</span></h3> <ul> <li>The author believes one can safely restore a backup without even restarting services. <ul> <li>Will we need to rely on this? 60 seconds of down-time is acceptable and guaranties that nothing bad happens.</li> </ul> </li> </ul> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1773343457" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
				</channel>
</rss>