<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-172996211129286102</id><updated>2011-11-24T12:07:22.599+01:00</updated><category term='linux'/><category term='opencv'/><category term='lighttpd'/><category term='fastcgi'/><category term='cli'/><category term='konsola'/><category term='rtlinux'/><category term='programming'/><category term='politechnika'/><category term='sqlite'/><category term='rtai'/><category term='texmaker'/><category term='django'/><category term='netbeans'/><category term='kompilacja'/><category term='c'/><category term='visual studio'/><category term='napisy'/><category term='mvc'/><category term='automatyka'/><category term='laboratorium'/><category term='sql'/><category term='python'/><category term='filmy'/><category term='lpt'/><category term='kernel'/><category term='wav'/><category term='openwrt'/><category term='pyrkon'/><category term='CUDA'/><category term='ubuntu'/><category term='97things'/><category term='c++'/><category term='fstab'/><category term='LaTeX'/><category term='google'/><category term='pyplot'/><title type='text'>Szkoda czasu</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://szkodaczasu.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>30</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-3118704925983565543</id><published>2011-09-18T21:10:00.001+02:00</published><updated>2011-09-18T21:10:41.066+02:00</updated><title type='text'>How to secure your webpage with lighttpd mod_auth</title><content type='html'>Here's the setup:&lt;br /&gt;There's a web page served by lighttpd by my OpenWRT router. Unfortunately the content shouldn't be available for everyone. Here's the solution:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;h&gt;Install mod_auth&lt;h&gt;&lt;br /&gt;&lt;p&gt;You can do it with:&lt;br /&gt;&lt;pre&gt;opkg install lighttpd-mod-auth&lt;/pre&gt; &lt;/li&gt;&lt;li&gt;&lt;h&gt;Create password file&lt;/h&gt;&lt;br /&gt;I first used plain authentication just to see if it's that easy as it's written in documentation. It turned out it is! Better solution is to use htdigest. You just need to create a file that looks like this:&lt;br /&gt;&lt;pre&gt;user1:realm:passwordhash&lt;br /&gt;user2:realm:passwordhash&lt;br /&gt;user3:another realm:passwordhash&lt;/pre&gt;Realm is a name of a section of your website that you declare in configuration file. I just use one realm called "download", because I don't need anything more at the moment.&lt;br /&gt;Password hash is md5 sum calculated from a following string: &lt;pre&gt;username:realm:password&lt;/pre&gt;e. g. john:website:qwerty would result in hash: 329516de44fe7cf1216194bb02348284.&lt;br /&gt;Entry in the password file would look like this:&lt;br /&gt;&lt;pre&gt;john:website:329516de44fe7cf1216194bb02348284&lt;/pre&gt;&lt;br /&gt;Put your file somewhere where it's not accessible from outside of your server. You don't want anyone to be able to download this file and get to know all users' passwords.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;h&gt;Update configuration&lt;/h&gt;&lt;br /&gt;Uncomment mod_auth in server.modules, for example:&lt;br /&gt;&lt;pre&gt;server.modules = (&lt;br /&gt;#       "mod_rewrite",&lt;br /&gt;        "mod_redirect",&lt;br /&gt;        "mod_alias",&lt;br /&gt;        "mod_auth",&lt;br /&gt;#       "mod_status",&lt;br /&gt;#       "mod_setenv",&lt;br /&gt;#       "mod_fastcgi",&lt;br /&gt;#       "mod_proxy",&lt;br /&gt;#       "mod_simple_vhost",&lt;br /&gt;#       "mod_cgi",&lt;br /&gt;#       "mod_ssi",&lt;br /&gt;#       "mod_usertrack",&lt;br /&gt;#       "mod_expire",&lt;br /&gt;#       "mod_webdav"&lt;br /&gt;)&lt;/pre&gt;&lt;br /&gt;Then add this somewhere down the line:&lt;br /&gt;&lt;pre&gt;## AUTH&lt;br /&gt;auth.debug = 0&lt;br /&gt;auth.backend = "htdigest"&lt;br /&gt;auth.backend.htdigest.userfile = "/path/to/your/file/called/for/example/htdigest.user"&lt;br /&gt;&lt;/pre&gt;When you want to secure access to your website with a password add:&lt;br /&gt;&lt;pre&gt;auth.require = ( "" =&gt;&lt;br /&gt;                        (&lt;br /&gt;                                "method" =&gt; "digest",&lt;br /&gt;                                "realm" =&gt; "website",&lt;br /&gt;                                "require" =&gt; "valid-user"&lt;br /&gt;                        )&lt;br /&gt;                       )&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;h&gt;Restart lighttpd&lt;/h&gt;&lt;br /&gt;You can do it with: &lt;pre&gt;/etc/init.d/lighttpd restart&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Now try to access your webpage. You should be greeted with a dialogbox asking for user name and password. In case it's not working increase debug level to 1 or 2 and check out /var/log/lighttpd/error.log to find out what's wrong. Maybe wrong file name, file permissions or password hash? Good luck.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-3118704925983565543?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/3118704925983565543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/3118704925983565543'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2011/09/how-to-secure-your-webpage-with.html' title='How to secure your webpage with lighttpd mod_auth'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-8494570689871253955</id><published>2011-04-06T21:51:00.002+02:00</published><updated>2011-04-06T21:54:57.810+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='filmy'/><category scheme='http://www.blogger.com/atom/ns#' term='openwrt'/><category scheme='http://www.blogger.com/atom/ns#' term='napisy'/><title type='text'>Automatyczne pobieranie na napisów na OpenWRT</title><content type='html'>&lt;h1&gt;Opis&lt;/h1&gt;Poniższa instrukcja opisuje w jaki sposób zaplanować automatyczne poszukiwanie napisów dla filmów i odcinków seriali na routerze z systemem OpenWRT w wersji Backfire 10.03.&lt;h1&gt;Instalacja&lt;/h1&gt;&lt;p&gt;Potrzebny będzie pakiet napiprojekt, który znajduje się tutaj: &lt;a href="http://eko.one.pl/openwrt/index.php?path=backfire%2F10.03/"&gt;napiprojekt&lt;/a&gt;. Instalacja następuje za pomocą: &lt;pre&gt;opkg install http://eko.one.pl/openwrt/backfire/10.03/napiprojekt_6_ar71xx.ipk&lt;/pre&gt;Opkg zainstaluje potrzebne zależności z wyjątkiem p7zip, który można dostać stąd: &lt;a href="http://ecco.selfip.net/backfire/packages/"&gt;p7zip&lt;/a&gt;. Instalujemy go podobnie: &lt;pre&gt;opkg install http://ecco.selfip.net/backfire/packages/p7zip_9.13-3_ar71xx.ipk&lt;/pre&gt;&lt;/p&gt;&lt;h1&gt;Skrypt&lt;/h1&gt;Tworzymy nowy skrypt wydając polecenie:&lt;pre&gt;nano /usr/bin/napisy.sh&lt;/pre&gt;Dzięki umieszczeniu w katalogu /usr/bin, który znajduje się w zmiennej środowiskowej $PATH, plik będzie można uruchomić z dowolnego miejsca w systemie.Następnie w treści pliku powinno znaleźć się:&lt;pre name="code" class="bash"&gt;#!/bin/sh&lt;br /&gt;# Przejrzyj po kolei wymienione katalogi&lt;br /&gt;for katalog in /srv/filmy /srv/seriale&lt;br /&gt;do&lt;br /&gt; # Znajdz wszystkie pliki avi, wypisz pelna sciezke: "1 linia = 1 plik", wczytuj po jednej linii do zmiennej&lt;br /&gt; # Uzycie read zabezpiecza przed sytuacją w której w nazwie pliku występują spacje&lt;br /&gt; find $katalog -name "*.avi" | while read plik_z_filmem&lt;br /&gt; do&lt;br /&gt;  # Zamien rozszerzenie avi na txt, zeby utworzyc nazwe pliku z napisami do danego filmu&lt;br /&gt;  # Otaczamy nazwe zmiennej cudzyslowem na wypadek gdyby nazwa pliku zawierala spacje&lt;br /&gt;  plik_z_napisami=$(dirname "$plik_z_filmem")/$(basename "$plik_z_filmem" .avi).txt&lt;br /&gt;  # Jesli nie istnieje plik z napisami&lt;br /&gt;  if [ ! -e "$plik_z_napisami" ]&lt;br /&gt;  then&lt;br /&gt;   # Szukaj napisow dla danego pliku&lt;br /&gt;   napiprojekt "$plik_z_filmem"&lt;br /&gt;  fi&lt;br /&gt; done&lt;br /&gt;done&lt;/pre&gt;Plikowi należy nadać pozwolenie na wykonywanie: &lt;pre&gt;chmod +x /usr/bin/napisy.sh&lt;/pre&gt;&lt;h1&gt;Cron&lt;/h1&gt;Dzięki temu, że skrypt pomija filmy i odcinki dla których już ściągnął napisy, można spokojnie zaplanować jego cogodzinne wykonywanie. W tym celu należy dodać następującą linijkę do pliku /etc/crontabs/root:&lt;pre&gt;* */1 * * * napisy.sh&lt;/pre&gt;Przystępne wyjaśnienie i wygodny "kalkulator" dla crona można znaleźć na &lt;a href="http://eko.one.pl/?p=openwrt-cron"&gt;http://eko.one.pl/?p=openwrt-cron&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-8494570689871253955?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/8494570689871253955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/8494570689871253955'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2011/04/automatyczne-pobieranie-na-napisow-na.html' title='Automatyczne pobieranie na napisów na OpenWRT'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-4684650067196763270</id><published>2011-03-21T20:55:00.025+01:00</published><updated>2011-03-21T21:50:07.532+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pyrkon'/><title type='text'>Kalendarz Pyrkon 2011</title><content type='html'>&lt;h1&gt;Calendar&lt;/h1&gt;&lt;iframe src="https://www.google.com/calendar/embed?title=Pyrkon%202011&amp;amp;mode=AGENDA&amp;amp;height=600&amp;amp;wkst=2&amp;amp;hl=pl&amp;amp;bgcolor=%23FFFFFF&amp;amp;src=kp3oeuein1rlld00j6nsq4spqg%40group.calendar.google.com&amp;amp;color=%23691426&amp;amp;src=vl8lu3jo0mc7lvhqjgk915m808%40group.calendar.google.com&amp;amp;color=%23A32929&amp;amp;src=tq1mfllik4bhue5vstspkl50es%40group.calendar.google.com&amp;amp;color=%232F6213&amp;amp;src=ufj01v1ionre5fg5nto41umpqk%40group.calendar.google.com&amp;amp;color=%23333333&amp;amp;src=0ut2gulrcqnkf71sl8fggih7i8%40group.calendar.google.com&amp;amp;color=%230D7813&amp;amp;src=f2qgvcfqnbv8sra64up3mcjkuk%40group.calendar.google.com&amp;amp;color=%23113F47&amp;amp;src=15ld22nc82k93t65bbh7fkd4qg%40group.calendar.google.com&amp;amp;color=%235F6B02&amp;amp;src=jrc9mb4r1c00jm5c1fo57vec98%40group.calendar.google.com&amp;amp;color=%23853104&amp;amp;src=080j156jb4c3v32j5k3lf2evis%40group.calendar.google.com&amp;amp;color=%23060D5E&amp;amp;src=moc25amnth3vei2e4ikatg26es%40group.calendar.google.com&amp;amp;color=%23711616&amp;amp;src=ctu21bhnuub1n0d1ql0678i9vs%40group.calendar.google.com&amp;amp;color=%23875509&amp;amp;src=sgjinen5711f6q0eomd7egr1tk%40group.calendar.google.com&amp;amp;color=%23754916&amp;amp;src=fouo33m9a9le7mn84l1orscvdg%40group.calendar.google.com&amp;amp;color=%235B123B&amp;amp;src=fvrhsrhn0scdpfcth0bekevoec%40group.calendar.google.com&amp;amp;color=%23856508&amp;amp;src=dfnsfjecq59tcoekp2fhouenk0%40group.calendar.google.com&amp;amp;color=%23125A12&amp;amp;src=gqg8smadtet50su37tef31g7og%40group.calendar.google.com&amp;amp;color=%232952A3&amp;amp;src=60emvlallhoasskv0ehie12tpg%40group.calendar.google.com&amp;amp;color=%23AB8B00&amp;amp;src=mailbot2000%40gmail.com&amp;amp;color=%23182C57&amp;amp;src=e7uuau1162v4eau8gkgd4buu8s%40group.calendar.google.com&amp;amp;color=%230F4B38&amp;amp;src=qgmiu471ocueu7g26pecvro5pg%40group.calendar.google.com&amp;amp;color=%235C1158&amp;amp;src=gqvgfmlm10cpa4l37om6ugav3c%40group.calendar.google.com&amp;amp;color=%238C500B&amp;amp;src=ne5sno8l92gn7gakm1rn4kfrpc%40group.calendar.google.com&amp;amp;color=%2342104A&amp;amp;src=2kfnkphmia1sasonisib99c9ic%40group.calendar.google.com&amp;amp;color=%2323164E&amp;amp;src=up5mmj20i4u06u39im4g3s12gc%40group.calendar.google.com&amp;amp;color=%236B3304&amp;amp;src=roroa2pis7kid4jlqac4c1ofkk%40group.calendar.google.com&amp;amp;color=%232F6309&amp;amp;ctz=Europe%2FWarsaw" style=" border-width:0 " width="800" height="600" frameborder="0" scrolling="no"&gt;&lt;/iframe&gt;&lt;h1&gt;Code&lt;/h1&gt;This code helped me to automate most of the work. Last year I used gdata directly, but this year I got so frustrated that I decided I need something simpler. The tradeoff is that the events are not described in details as they used to be. This year I'm not making a mistake of not keeping the code, so here it is.There are basically three steps:&lt;ol&gt;&lt;li&gt;Scrape the website to gather information&lt;/li&gt;&lt;li&gt;Build a shell command to call googlecl - google command line interface that provides some ability to use Google services from command line.&lt;/li&gt;&lt;li&gt;Run the command in the terminal. Keep retrying if it failed for any reason.&lt;/li&gt;&lt;/ol&gt;There were some issues:&lt;ul&gt;&lt;li&gt;Doubled entries that migrated from calendar "Naukowa 2" to "Naukowa", but showed up in their proper place too.&lt;/li&gt;&lt;li&gt;Sometimes starting times where off by an hour or two. For example by 1 hour on Friday, 1 hour on Saturday, 2 hours on Sunday. WTF? I noticed it happened on calendars that have numbers in their names, but most of them do, so I might be just imagining it.&lt;/li&gt;&lt;li&gt;Some problems with encoding. I could never understand when I need to decode/encode a string.&lt;/li&gt;&lt;/ul&gt;&lt;pre name="code" class="python"&gt;#!/usr/bin/python&lt;br /&gt;# -*- coding:utf8 -*-&lt;br /&gt;&lt;br /&gt;from BeautifulSoup import BeautifulSoup&lt;br /&gt;import urllib2&lt;br /&gt;import re&lt;br /&gt;import subprocess&lt;br /&gt;&lt;br /&gt;# Download the page&lt;br /&gt;# You may want to save the page in the browser and use a local copy&lt;br /&gt;# for example: 'file:///home/daniel/Pobrane/pyrkon.html'&lt;br /&gt;page = urllib2.urlopen('http://www.pyrkon.pl/2011/index.php?go2=program')&lt;br /&gt;soup = BeautifulSoup(page)&lt;br /&gt;&lt;br /&gt;# Find div with the content&lt;br /&gt;content = soup.find('div', id='content')&lt;br /&gt;# Get all his children which are divs too&lt;br /&gt;divs = content.findAll('div')&lt;br /&gt;&lt;br /&gt;# Set starting index in case you wanted to start in the middle after some interruption&lt;br /&gt;start_from = 0&lt;br /&gt;i = 0&lt;br /&gt;l = len(divs) - start_from&lt;br /&gt;&lt;br /&gt;for div in divs[start_from:]:&lt;br /&gt; # Name and lecturer are easy&lt;br /&gt; tytul = div.contents[1].b.string&lt;br /&gt; prowadzacy = div.contents[1].i.string&lt;br /&gt; # I can never understand when I need to decode/encode from/to utf-8.&lt;br /&gt; # This was done by trial and error.&lt;br /&gt; &lt;br /&gt; # Madafaking new lines are contents too, so&lt;br /&gt; #  div.contents[2] == u'\n'&lt;br /&gt; &lt;br /&gt; # Place&lt;br /&gt; miejsce = re.search('^&amp;lt;b&amp;gt;miejsce: &amp;lt;/b&amp;gt;(?P&amp;lt;miejsce&amp;gt;.+?)&amp;lt;br /&amp;gt;', div.contents[3].renderContents(), re.M).group('miejsce')&lt;br /&gt; miejsce = miejsce.decode('utf-8')&lt;br /&gt;&lt;br /&gt; # Show some progress information&lt;br /&gt; i += 1&lt;br /&gt; print '[%d/%d] %s: %s' % (i, l, miejsce, tytul)&lt;br /&gt;&lt;br /&gt; # Event start time&lt;br /&gt; czas = re.search('^&amp;lt;b&amp;gt;termin: &amp;lt;/b&amp;gt; (?P&amp;lt;dzien&amp;gt;pią|sob|nd)(\s*)(?P&amp;lt;godzina&amp;gt;\d{2}):(?P&amp;lt;minuta&amp;gt;\d{2})', div.contents[3].renderContents(), re.M)&lt;br /&gt; dzien, godzina, minuta = czas.group('dzien', 'godzina', 'minuta')&lt;br /&gt; godzina = int(godzina)&lt;br /&gt; minuta = int(minuta)&lt;br /&gt; &lt;br /&gt; # Conversion from name of the day to number of the day&lt;br /&gt; if dzien == 'pią':&lt;br /&gt;  dzien = 25&lt;br /&gt; elif dzien == 'sob':&lt;br /&gt;  dzien = 26&lt;br /&gt; elif dzien == 'nd':&lt;br /&gt;  dzien = 27&lt;br /&gt; else:&lt;br /&gt;  raise ValueError('Błędny dzień')&lt;br /&gt; &lt;br /&gt; # How long it lasts&lt;br /&gt; dlugosc = re.search('^&amp;lt;b&amp;gt;czas trwania: &amp;lt;/b&amp;gt;(?P&amp;lt;godzin&amp;gt;\d+):(?P&amp;lt;minut&amp;gt;\d{2}) h&amp;lt;br /&amp;gt;', div.contents[3].renderContents(), re.M)&lt;br /&gt; godzin, minut = dlugosc.group('godzin', 'minut')&lt;br /&gt; godzin = int(godzin)&lt;br /&gt; minut = int(minut)&lt;br /&gt; &lt;br /&gt; # Build shell command for googlecl - google command line interface (available at code.google.com)&lt;br /&gt; # uses "Quick Add" syntax&lt;br /&gt; polecenie = '''google calendar add --cal='%s' '%s - %s on %d/03/2011 %d:%02d for %d minutes in %s' ''' % (miejsce, tytul, prowadzacy, dzien, godzina, minuta, godzin * 60 + minut, miejsce)&lt;br /&gt;&lt;br /&gt; # Keep calling shell command until it succeeds&lt;br /&gt; # Sometimes it throws gdata.service.RequestError with status 302 and reason 'Redirect received, but redirects_remaining &amp;lt;= 0'&lt;br /&gt; return_code = 1&lt;br /&gt; while return_code != 0:&lt;br /&gt;  print polecenie&lt;br /&gt;  return_code = subprocess.call(polecenie, shell=True)&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-4684650067196763270?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://szkodaczasu.blogspot.com/feeds/4684650067196763270/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=172996211129286102&amp;postID=4684650067196763270' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4684650067196763270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4684650067196763270'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2011/03/kalendarz-pyrkon-2011.html' title='Kalendarz Pyrkon 2011'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-1753723414980570401</id><published>2011-02-21T13:43:00.002+01:00</published><updated>2011-02-21T22:34:51.684+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='97things'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>"97 things every programmer should know" is going to be translated to Polish</title><content type='html'>I volunteered to help translating "97 things programmers should know". Here's our progress:&lt;script type="text/javascript" src="//ajax.googleapis.com/ajax/static/modules/gviz/1.0/chart.js"&gt; {"chartType":"BarChart","chartName":"Podsumowanie","dataSourceUrl":"//spreadsheets.google.com/tq?key=0AnD5GaP8XmnCdERwLUNaZ3dFZ1VpSDIxaHVqbkoyb1E&amp;range=A1%3AD2&amp;gid=2&amp;transpose=0&amp;headers=1&amp;pub=1","options":{"displayAnnotations":true,"showTip":true,"nonGeoMapColors":["#38761d","#ffff00","#ff9900","#ff0000","#990099","#0099C6","#DD4477","#66AA00","#B82E2E","#316395"],"reverseCategories":false,"dataMode":"markers","titleX":"Liczba artyku\u0142\u00f3w","maxAlternation":1,"pointSize":"0","colors":["#38761d","#ffff00","#ff9900","#ff0000","#990099","#0099C6","#DD4477","#66AA00","#B82E2E","#316395"],"smoothLine":false,"lineWidth":"2","labelPosition":"right","is3D":false,"logScale":false,"hasLabelsColumn":false,"wmode":"opaque","title":"","legend":"bottom","allowCollapse":true,"cht":"bhs","reverseAxis":false,"isStacked":true,"mapType":"hybrid","width":724,"height":156},"refreshInterval":5} &lt;/script&gt;You can find it at &lt;a href="http://97rzeczy.devblogi.pl/"&gt;97rzeczy.devblogi.pl&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-1753723414980570401?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/1753723414980570401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/1753723414980570401'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2011/02/translation.html' title='&quot;97 things every programmer should know&quot; is going to be translated to Polish'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-251285757234640124</id><published>2010-12-19T23:29:00.006+01:00</published><updated>2010-12-20T00:09:57.431+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='django'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='lighttpd'/><category scheme='http://www.blogger.com/atom/ns#' term='openwrt'/><category scheme='http://www.blogger.com/atom/ns#' term='fastcgi'/><title type='text'>OpenWRT + Lighttpd + Fastcgi + Django</title><content type='html'>&lt;h1&gt;Introduction&lt;/h1&gt;&lt;p&gt;Here's something I was fighting with for about 3 days. At first I wanted to use virtualenv too, but it all resulted in a headache. I'm a novice in these matters, so forgive me.&lt;/p&gt;&lt;p&gt;Recently I bought a router TP-Link WR-1043ND. Not the best choice now, I'm aware: TP-Link MR3420 has higher quality to price ratio. Anyway, my router got upgraded to OpenWRT, version Backfire 10.3-RC4, thanks to great work of &lt;a href="http://eko.one.pl"&gt;Cezary Jackiewicz aka Obsy&lt;/a&gt;.&lt;h1&gt;Installation&lt;/h1&gt;&lt;h2&gt;Opkg packages&lt;/h2&gt;&lt;p&gt;First packages that we can install with OpenWRT package manager:&lt;ul&gt;&lt;li&gt;lighttpd, lighttpd-mod-alias, lighttpd-mod-rewrite, lighttpd-mod-fcgi - packages needed for http server called lighty&lt;/li&gt;&lt;li&gt;pysqlite, libsqlite3 - the database&lt;/li&gt;&lt;li&gt;python wasn't installed at first, so we'll need this too&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;opkg install lighttpd lighttpd-mod-alias lighttpd-mod-rewrite lighttpd-mod-fcgi&lt;br /&gt;opkg python libsqlite3 pysqlite&lt;/pre&gt;&lt;/p&gt;&lt;h2&gt;Python packages&lt;/h2&gt;&lt;p&gt;These will be installed from Python Package Index (PyPI).We will need:&lt;ul&gt;&lt;li&gt;setuptools - Go to pypi.python.org, search for setuptools, follow the instructions.&lt;/li&gt;&lt;li&gt;pip - We should be able to call: &lt;i&gt;easy_install pip&lt;/i&gt; to obtain it.&lt;/li&gt;&lt;li&gt;django - With pip in place getting django is as easy as &lt;i&gt;pip install django&lt;/i&gt;. Pip, contrary to easy_install, has a nice uninstall option.&lt;/li&gt;&lt;li&gt;flup - For FastCGI related stuff&lt;/li&gt;&lt;/ul&gt;There we go. It's all installed.&lt;/p&gt;&lt;h1&gt;Configuration&lt;/h1&gt;&lt;h2&gt;3 ways of doing this&lt;/h2&gt;First of all, let me briefly explain how FastCGI works. Actually this might not be a good idea to believe me, because, as I said, I'm a layman in this matters. There are 3 entities in this process: the browser, the server (Lighttpd), the FastCGI process (Django).&lt;br/&gt;First step is forwarding the http request for a webpage to FastCGI process:&lt;pre&gt;Browser =&gt; Lighttpd =&gt; Django FCGI&lt;/pre&gt;Request is processed and Django returns html source code of a webpage. Shove it back to your browser and render it.&lt;pre&gt;Browser &lt;= Lighttpd &lt;= Django FCGI&lt;/pre&gt;&lt;ol&gt;I came to conclusion that there are 3 ways of setting this up.&lt;li&gt;By bin-path&lt;/li&gt;&lt;li&gt;By host and port&lt;/li&gt;&lt;li&gt;By socket&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;My app's directory: &lt;i&gt;/www/apps/homepage&lt;/i&gt;. It doesn't have to be anything fancy. It's ok to use brand new project created with &lt;i&gt;django-admin.py startproject homepage&lt;/i&gt;.&lt;/p&gt;&lt;h2&gt;Bin-path&lt;/h2&gt;&lt;p&gt;This method is my favourite so far. We tell lighttpd where to find executable file .fcgi and it starts FCGI processes by itself. All we need to take care of now is that the server is started after reboot. Here are the details:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Contents of .fcgi file. It sits at the django project's directory.&lt;br&gt;&lt;pre&gt;#!/usr/bin/env python&lt;br /&gt;import sys, os&lt;br /&gt;&lt;br /&gt;# Add a custom Python path.&lt;br /&gt;sys.path.insert(0, "/www/apps")&lt;br /&gt;&lt;br /&gt;# Set the DJANGO_SETTINGS_MODULE environment variable.&lt;br /&gt;os.environ['DJANGO_SETTINGS_MODULE'] = "homepage.settings"&lt;br /&gt;&lt;br /&gt;from django.core.servers.fastcgi import runfastcgi&lt;br /&gt;# maxspare=2 is minimum from what i saw&lt;br /&gt;runfastcgi(method="threaded", daemonize="false", maxspare=2)&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Lighttpd config file from /etc/lighttpd/lighttpd.conf. It is edited version of default config file. I just omitted most of commented out lines.&lt;pre&gt;# lighttpd configuration file&lt;br /&gt;# &lt;br /&gt;## modules to load&lt;br /&gt;# all other module should only be loaded if really neccesary&lt;br /&gt;# - saves some time&lt;br /&gt;# - saves memory&lt;br /&gt;server.modules = ( &lt;br /&gt; "mod_rewrite", &lt;br /&gt;# "mod_redirect", &lt;br /&gt; "mod_alias", &lt;br /&gt;# "mod_auth", &lt;br /&gt;# "mod_status", &lt;br /&gt;# "mod_setenv",&lt;br /&gt; "mod_fastcgi",&lt;br /&gt;# "mod_proxy",&lt;br /&gt;# "mod_simple_vhost",&lt;br /&gt;# "mod_cgi",&lt;br /&gt;# "mod_ssi",&lt;br /&gt;# "mod_usertrack",&lt;br /&gt;# "mod_expire",&lt;br /&gt;# "mod_webdav"&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;# force use of the "write" backend (closes: #2401)&lt;br /&gt;server.network-backend = "write"&lt;br /&gt;&lt;br /&gt;## a static document-root, for virtual-hosting take look at the &lt;br /&gt;## server.virtual-* options&lt;br /&gt;server.document-root = "/www/public"&lt;br /&gt;&lt;br /&gt;## where to send error-messages to&lt;br /&gt;server.errorlog = "/var/log/lighttpd/error.log"&lt;br /&gt;&lt;br /&gt;## files to check for if .../ is requested&lt;br /&gt;index-file.names = ( "index.html", "default.html", "index.htm", "default.htm" )&lt;br /&gt;&lt;br /&gt;## mimetype mapping&lt;br /&gt;mimetype.assign = (  &lt;br /&gt; ".pdf"   =&gt; "application/pdf",&lt;br /&gt; ".class" =&gt; "application/octet-stream",&lt;br /&gt; ".pac"   =&gt; "application/x-ns-proxy-autoconfig",&lt;br /&gt; ".swf"   =&gt; "application/x-shockwave-flash",&lt;br /&gt; ".wav"   =&gt; "audio/x-wav",&lt;br /&gt; ".gif"   =&gt; "image/gif",&lt;br /&gt; ".jpg"   =&gt; "image/jpeg",&lt;br /&gt; ".jpeg"  =&gt; "image/jpeg",&lt;br /&gt; ".png"   =&gt; "image/png",&lt;br /&gt; ".css"   =&gt; "text/css",&lt;br /&gt; ".html"  =&gt; "text/html",&lt;br /&gt; ".htm"   =&gt; "text/html",&lt;br /&gt; ".js"    =&gt; "text/javascript",&lt;br /&gt; ".txt"   =&gt; "text/plain",&lt;br /&gt; ".dtd"   =&gt; "text/xml",&lt;br /&gt; ".xml"   =&gt; "text/xml"&lt;br /&gt; )&lt;br /&gt;&lt;br /&gt;$HTTP["url"] =~ "\.pdf$" {&lt;br /&gt; server.range-requests = "disable"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;##&lt;br /&gt;# which extensions should not be handle via static-file transfer&lt;br /&gt;#&lt;br /&gt;# .php, .pl, .fcgi are most often handled by mod_fastcgi or mod_cgi&lt;br /&gt;static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )&lt;br /&gt;&lt;br /&gt;## to help the rc.scripts&lt;br /&gt;server.pid-file = "/var/run/lighttpd.pid"&lt;br /&gt;&lt;br /&gt;#### fastcgi module&lt;br /&gt;## read fastcgi.txt for more info&lt;br /&gt;# this line may help with finding what's wrong, check out errorlog file&lt;br /&gt;# fastcgi.debug=1&lt;br /&gt;fastcgi.server = (&lt;br /&gt; "/homepage.fcgi" =&gt; (&lt;br /&gt;  "main" =&gt; (&lt;br /&gt;   "host" =&gt; "127.0.0.1",&lt;br /&gt;   "port" =&gt; 3033,&lt;br /&gt;   "check-local" =&gt; "disable",&lt;br /&gt;   "max-procs" =&gt; 1,&lt;br /&gt;   "bin-path" =&gt; "/www/apps/homepage/homepage.fcgi"&lt;br /&gt;  )&lt;br /&gt; )&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;alias.url = (&lt;br /&gt;                "/media" =&gt; "/www/apps/homepage/media",&lt;br /&gt;        )&lt;br /&gt;&lt;br /&gt;url.rewrite-once = (&lt;br /&gt;                "^(/media.*)$" =&gt; "$1",&lt;br /&gt;                "^/favicon\.ico$" =&gt; "/media/favicon.ico",&lt;br /&gt;                "^(/.*)$" =&gt; "/homepage.fcgi$1",&lt;br /&gt;        )&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Host:port&lt;/h2&gt;&lt;p&gt;You don't need .fcgi file in this method. Remove line with "bin-path" in fastcgi.server section of lighttpd config. Now you need to make sure that you run this at every boot (maybe you can use start-stop-daemon tool for this):&lt;pre&gt;/www/apps/homepage/manage.py runfcgi method=threaded host="127.0.0.1" port=3033&lt;/pre&gt;This will start FastCGI threads. Lighttpd will expect them to be there when he needs a page. Otherwise you'll get 503 or 500. This method is said to be easier because there is no need to set permissions on TCP socket.&lt;/p&gt;&lt;h2&gt;Socket&lt;/h2&gt;&lt;p&gt;In this method FCGI process and HTTP Server communicate through a socket (aka named pipe). Proper permissions must be in place. FCGI file is also not needed here. You must make sure that you run similar command as in the second method:&lt;pre&gt;/www/apps/homepage/manage.py runfcgi method=threaded socket=/www/apps/homepage/homepage.socket&lt;/pre&gt;Lines in fastcgi.server with port and host get removed. Instead add &lt;pre&gt;"socket" =&gt; "/www/apps/homepage/homepage.socket"&lt;/pre&gt;&lt;/p&gt;&lt;h1&gt;Conclusion&lt;/h1&gt;&lt;p&gt;I use a lot of bad practices here:&lt;ul&gt;&lt;li&gt;do everything as root&lt;/li&gt;&lt;li&gt;not using virtualenv&lt;/li&gt;&lt;li&gt;keeping my app in /www (but I changed my document-root, so maybe I'm ok?)&lt;/li&gt;&lt;/ul&gt;This is an example of work done by someone who came from "no idea" to "it started working" and all this happens on a router that won't be under a lot of load or work in a cloud of virtual machines. Certainly it's not state of the art, but gets the job done.&lt;/p&gt;&lt;p&gt;There's quite a lot of this kind of tutorials, but to someone without proper knowledge all these terms and blindly followed instructions are no good if something doesn't work as expected. I hope someone will find the wording I used useful. I hope will when I'll need to do everything all over again.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-251285757234640124?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://szkodaczasu.blogspot.com/feeds/251285757234640124/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=172996211129286102&amp;postID=251285757234640124' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/251285757234640124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/251285757234640124'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2010/12/openwrt-lighttpd-fastcgi-django.html' title='OpenWRT + Lighttpd + Fastcgi + Django'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-304990797158994961</id><published>2010-08-12T21:33:00.000+02:00</published><updated>2010-08-12T21:33:45.911+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Kernel log spammed with rt2500 errors</title><content type='html'>&lt;p&gt;My wifi card kept spamming kernel log with messages like this: "phy0 -&gt; rt2500pci_set_device_state: Error - Device failed to enter state 1 (-16)". The solution is easily found among launchpad bug reports. Power management needs to be turned off for the card. It's easy to do: &lt;br/&gt;&lt;pre&gt;iwconfig wlan0 power off&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;To make it permanent edit /etc/rc.local adding this line before exit 0. Reboot and you're done! Confirm that with calling iwconfig:&lt;/p&gt;&lt;p&gt;&lt;pre&gt;lo        no wireless extensions.&lt;br /&gt;&lt;br /&gt;eth0      no wireless extensions.&lt;br /&gt;&lt;br /&gt;wlan0     IEEE 802.11bg  ESSID:"TP69"  &lt;br /&gt;          Mode:Managed  Frequency:2.422 GHz  Access Point: 00:23:CD:15:F2:A0   &lt;br /&gt;          Bit Rate=48 Mb/s   Tx-Power=20 dBm   &lt;br /&gt;          Retry  long limit:7   RTS thr:off   Fragment thr:off&lt;br /&gt;          Power Management:off&lt;br /&gt;          Link Quality=60/70  Signal level=-50 dBm  &lt;br /&gt;          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0&lt;br /&gt;          Tx excessive retries:0  Invalid misc:0   Missed beacon:0&lt;/pre&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-304990797158994961?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://szkodaczasu.blogspot.com/feeds/304990797158994961/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=172996211129286102&amp;postID=304990797158994961' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/304990797158994961'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/304990797158994961'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2010/08/kernel-log-spammed-with-rt2500-errors.html' title='Kernel log spammed with rt2500 errors'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-7975530236190617504</id><published>2010-06-01T19:40:00.001+02:00</published><updated>2010-06-01T19:41:08.826+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rtai'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='lpt'/><title type='text'>First success with RTAI</title><content type='html'>&lt;p&gt;Recently I've been trying to grok Real Time Application Interface (more on www.rtai.org). It certainly wasn't a walk in the park, but still far far easier than RTLinux. This time at least I had a clue what was going on. Following this tutorial worked for me: &lt;a href="http://qrtailab.sourceforge.net/rtai_installation.html"&gt;http://qrtailab.sourceforge.net/rtai_installation.html&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Finally when everything is set up you can do: &lt;i&gt;sudo start_rtai&lt;/i&gt; on command line. This starts RTAI.&lt;/p&gt;&lt;p&gt;Now for some programming. Here's a snippet:&lt;pre name="code" class="C++"&gt;/* led1.c, an LXRT LED blinker */&lt;br /&gt;&lt;br /&gt;#include &amp;lt;rtai_lxrt.h&gt;&lt;br /&gt;#include &amp;lt;pthread.h&gt;&lt;br /&gt;#include &amp;lt;sys/mman.h&gt;&lt;br /&gt;#include &amp;lt;sys/io.h&gt;&lt;br /&gt;&lt;br /&gt;// delay in nanoseconds&lt;br /&gt;#define TICKS 500000000 &lt;br /&gt;&lt;br /&gt;main()&lt;br /&gt;{&lt;br /&gt;        RT_TASK *task;&lt;br /&gt;        int priority = 0, i;&lt;br /&gt;        int stack_size = 4096;&lt;br /&gt;        int msg_size = 0; // use default&lt;br /&gt;&lt;br /&gt;        // get enough privilege to &lt;br /&gt;        // access the I/O ports.&lt;br /&gt;&lt;br /&gt;        iopl(3);&lt;br /&gt;&lt;br /&gt;        task = rt_task_init(nam2num("main"), priority, stack_size, msg_size);&lt;br /&gt;        if(task == 0)&lt;br /&gt;        {&lt;br /&gt;         printf("Task could not be initialized. Are you root?");&lt;br /&gt;         exit(1);&lt;br /&gt;        }&lt;br /&gt;        rt_set_oneshot_mode();&lt;br /&gt;        start_rt_timer(0);&lt;br /&gt;        mlockall(MCL_CURRENT|MCL_FUTURE);&lt;br /&gt;        rt_make_hard_real_time();&lt;br /&gt;&lt;br /&gt;        for(i = 0; i &lt; 10; i++) {&lt;br /&gt;                outb(0xff, 0x378);&lt;br /&gt;                rt_sleep(nano2count(TICKS));&lt;br /&gt;                outb(0x0, 0x378);&lt;br /&gt;                rt_sleep(nano2count(TICKS));&lt;br /&gt;        }&lt;br /&gt;        // back to non-rt land!&lt;br /&gt;        rt_make_soft_real_time();&lt;br /&gt;        stop_rt_timer();&lt;br /&gt;        rt_task_delete(task);&lt;br /&gt;        return 0;&lt;br /&gt;}&lt;/pre&gt;It's a program that comes from &lt;a href="http://linuxgazette.net/114/pramode.html"&gt;this article&lt;/a&gt; with added troubleshooting comment.&lt;/p&gt;&lt;p&gt;To compile this program it's necessary to run:&lt;br/&gt;&lt;blockquote&gt;CFLAGS=$(rtai-config --lxrt-cflags&lt;br/&gt;LDFLAGS=$(rtai-config --lxrt-ldflags&lt;br/&gt;gcc $(CFLAGS) $(LDFLAGS) main.c -o blinker&lt;/blockquote&gt;Where main.c is the name of the source file and blinker is the name of output executable.&lt;br/&gt;To run it you should write &lt;i&gt;sudo ./blinker&lt;/i&gt;. Sudo is needed because of the direct hardware access. You should see that the leds hooked up to lpt port are blinking.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-7975530236190617504?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/7975530236190617504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/7975530236190617504'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2010/06/first-success-with-rtai.html' title='First success with RTAI'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-5562099398300896883</id><published>2010-05-17T13:35:00.000+02:00</published><updated>2010-05-17T13:35:03.752+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lpt'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>LPT port access with C</title><content type='html'>I found this useful snippet on &lt;a href="http://blog.kirves.pri.ee/2009/03/lpt-programming-example-in-c-for-ubuntu-linux/"&gt;another blog&lt;/a&gt;.&lt;pre name="code" class="C++"&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/io.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#define BASEPORT 0x378 /* lp1 */&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;  unsigned char c = 0;&lt;br /&gt;  int n, tem;&lt;br /&gt;&lt;br /&gt;   printf("Hit enter to stop\n");&lt;br /&gt;&lt;br /&gt;  if (ioperm(BASEPORT, 3, 1)) &lt;br /&gt;  {&lt;br /&gt;   perror("ioperm");&lt;br /&gt;   exit(1);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  tem = fcntl(0, F_GETFL, 0);&lt;br /&gt;  fcntl (0, F_SETFL, (tem | O_NDELAY));&lt;br /&gt;  &lt;br /&gt;  while (1) {&lt;br /&gt;    n = read(0, &amp;c, 1);&lt;br /&gt;    if (n &amp;gt; 0) break;&lt;br /&gt;&lt;br /&gt;     outb(c, BASEPORT);&lt;br /&gt;     usleep(c * 1000);&lt;br /&gt;     c++;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  fcntl(0, F_SETFL, tem);&lt;br /&gt;  outb(0, BASEPORT);&lt;br /&gt;&lt;br /&gt;  if (ioperm(BASEPORT, 3, 0)) &lt;br /&gt;  {&lt;br /&gt;   perror("ioperm");&lt;br /&gt;   exit(1);&lt;br /&gt;  }&lt;br /&gt;  exit(0);&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-5562099398300896883?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://szkodaczasu.blogspot.com/feeds/5562099398300896883/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=172996211129286102&amp;postID=5562099398300896883' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/5562099398300896883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/5562099398300896883'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2010/05/lpt-port-access-with-c.html' title='LPT port access with C'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-1990616221637175794</id><published>2010-03-22T23:01:00.002+01:00</published><updated>2010-03-22T23:01:25.453+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pyrkon'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><title type='text'>Multikalendarz Pyrkon 2010</title><content type='html'>&lt;iframe src="http://www.google.com/calendar/embed?title=Pyrkon%20Agenda&amp;amp;showTitle=0&amp;amp;showNav=0&amp;amp;showDate=0&amp;amp;showPrint=0&amp;amp;showTabs=0&amp;amp;mode=AGENDA&amp;amp;height=600&amp;amp;wkst=1&amp;amp;bgcolor=%23FFFFFF&amp;amp;src=fo7cqq6nrrlhd3ed2831r1v82o%40group.calendar.google.com&amp;amp;color=%230D7813&amp;amp;src=vco4dha7q6pjg1q7kvd547bv3c%40group.calendar.google.com&amp;amp;color=%235229A3&amp;amp;src=9am0mro45qv4rdmmeb2ibfbcpc%40group.calendar.google.com&amp;amp;color=%23705770&amp;amp;src=f49d7mc4d2qimkoihdr3nlf800%40group.calendar.google.com&amp;amp;color=%232952A3&amp;amp;src=mbf1bc3dhou6q9b8t123femd7o%40group.calendar.google.com&amp;amp;color=%2329527A&amp;amp;src=9m3u7gnfcv0evnmf7hhpamhn5k%40group.calendar.google.com&amp;amp;color=%23865A5A&amp;amp;src=92no23goqp2dol7b4k4nnlpjcc%40group.calendar.google.com&amp;amp;color=%23B1440E&amp;amp;src=fk19pkmupkqm5uj45g40uv2v64%40group.calendar.google.com&amp;amp;color=%234E5D6C&amp;amp;src=sfolkh6q354ruq3v6et97km0cc%40group.calendar.google.com&amp;amp;color=%23BE6D00&amp;amp;src=rek8qks5426l0l5il2icblipug%40group.calendar.google.com&amp;amp;color=%235A6986&amp;amp;src=eun81o9pijvhdoa45819soa0e8%40group.calendar.google.com&amp;amp;color=%23B1365F&amp;amp;src=eceececr0seb88bth1nasqdh2k%40group.calendar.google.com&amp;amp;color=%2388880E&amp;amp;src=3dcpmiadknv20qhb0iu8sgok20%40group.calendar.google.com&amp;amp;color=%23528800&amp;amp;src=dd69t6sh4jjtcl2vbdtno90580%40group.calendar.google.com&amp;amp;color=%23A32929&amp;amp;src=9s8qdjkflmd2i515ef2odbuies%40group.calendar.google.com&amp;amp;color=%237A367A&amp;amp;src=u9bfam3qjb4vsjr4n859m0nm0s%40group.calendar.google.com&amp;amp;color=%236E6E41&amp;amp;src=nvh92m0u84gg822v62mk1d7ovg%40group.calendar.google.com&amp;amp;color=%23B1440E&amp;amp;src=5hmg2gic5n7vg1o9867glk7kf4%40group.calendar.google.com&amp;amp;color=%235229A3&amp;amp;src=1so4e103gugc97mkldaegf0oik%40group.calendar.google.com&amp;amp;color=%2328754E&amp;amp;src=g1d18htfes1eld0dvn1nio66q8%40group.calendar.google.com&amp;amp;color=%238D6F47&amp;amp;src=mp2ftdgqikfd2obpkgrg3f6sdo%40group.calendar.google.com&amp;amp;color=%238D6F47&amp;amp;src=72ba4g682dt1ca0c4ej2uo9vnc%40group.calendar.google.com&amp;amp;color=%234A716C&amp;amp;src=ml3l2e6l1lf69omh19c20mar10%40group.calendar.google.com&amp;amp;color=%231B887A&amp;amp;src=sm6sqa5gqlj44g5n72u11kb9uc%40group.calendar.google.com&amp;amp;color=%230D7813&amp;amp;src=ajht3r0suldkahq261ngl5asfs%40group.calendar.google.com&amp;amp;color=%23AB8B00&amp;amp;ctz=Europe%2FWarsaw" style=" border-width:0 " width="800" height="600" frameborder="0" scrolling="no"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-1990616221637175794?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/1990616221637175794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/1990616221637175794'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2010/03/multikalendarz-pyrkon-2010.html' title='Multikalendarz Pyrkon 2010'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-8810253575615640573</id><published>2010-03-22T22:13:00.000+01:00</published><updated>2010-03-22T22:13:06.152+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pyrkon'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><title type='text'>Kalendarz Pyrkon 2010</title><content type='html'>&lt;iframe src="http://www.google.com/calendar/embed?title=Pyrkon%20Agenda&amp;amp;showTitle=0&amp;amp;showNav=0&amp;amp;showDate=0&amp;amp;showPrint=0&amp;amp;showTabs=0&amp;amp;showCalendars=0&amp;amp;mode=AGENDA&amp;amp;height=600&amp;amp;wkst=2&amp;amp;hl=pl&amp;amp;bgcolor=%23ffffcc&amp;amp;src=cur9h3ofg7piiuc3mee8e2v8rg%40group.calendar.google.com&amp;amp;color=%23AB8B00&amp;amp;ctz=Europe%2FWarsaw" style=" border-width:0 " width="800" height="600" frameborder="0" scrolling="no"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-8810253575615640573?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://szkodaczasu.blogspot.com/feeds/8810253575615640573/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=172996211129286102&amp;postID=8810253575615640573' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/8810253575615640573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/8810253575615640573'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2010/03/kalendarz-pyrkon-2010.html' title='Kalendarz Pyrkon 2010'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-2642621029958484987</id><published>2010-03-12T12:22:00.000+01:00</published><updated>2010-03-12T12:22:33.839+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='visual studio'/><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Don't code while designing</title><content type='html'>There's plenty of comments all over the Internet about "coding now, designing later" made by seasoned developer's. Right now I'm working with my colleagues on a project that needs to be written from scratch. Fighting the need to write something first I decided I won't do any implementation in advance.&lt;br /&gt;My working environment is MS Visual Studio 2008. Recently I found there a feature which turned out very useful in my current situation: Class Diagram. I'm going to implement basic MVC framework as I understand it based on various tutorials I've read. It may not be 100% correct. Sorry.&lt;ol&gt;&lt;li&gt; Create new project in a new solution. &lt;/li&gt;&lt;li&gt; Right click on project's name in Solution Explorer and choose View Class Diagram. &lt;/li&gt;&lt;li&gt; Rename file Class1.cs to Model.cs and change Class1 name to Model. &lt;/li&gt;&lt;li&gt; Add 2 more classes dragging them from Toolbox and giving names: View and Controller. &lt;/li&gt;&lt;li&gt; To add a method to a class right click on class box and choose Add-&gt;Method or go to Class Details window and add the new method there. If you don't see Class Details window, right click on a class and choose Class Details.&lt;/li&gt;&lt;li&gt; View should have methods: AttachDataSource and Update. &lt;/li&gt;&lt;li&gt; Controller should have methods: AttachModel, RequestAttachingView, RequestChangeState.&lt;/li&gt;&lt;li&gt; Model should have methods: AttachView, ChangeState, ServeData, UpdateViews &lt;/li&gt;&lt;li&gt; You don't want your classes to directly depend from each other, but use interfaces instead. To extract interface right click on class box, choose Refactor-&gt;Extract Interface... and choose methodes and properties that will form an interface.&lt;/li&gt;&lt;li&gt; Extract IView interface from View with methods: AttachDataSource, Update. &lt;/li&gt;&lt;li&gt; Extract IViewDataSource from Model with method ServeData. &lt;/li&gt;&lt;li&gt; Extract IControllable from Model with methods: AttachView, ChangeState. &lt;/li&gt;&lt;li&gt; Now add field viewDataSource to View of type IViewDataSource. &lt;/li&gt;&lt;li&gt; Add field view to Model of type IView. &lt;/li&gt;&lt;li&gt; Add field controlledModel to Controller of type IControllable. &lt;/li&gt;&lt;li&gt; For some more readability you can right click on a field and choose Show as Association. &lt;/li&gt;&lt;/ol&gt;Your current state should be something like this:&lt;br /&gt;&lt;img src="http://imgur.com/XcQES.png" alt="Hosted by imgur.com" /&gt;&lt;br /&gt;Notice you didn't write anything in code yet. Next step will be implementation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-2642621029958484987?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://szkodaczasu.blogspot.com/feeds/2642621029958484987/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=172996211129286102&amp;postID=2642621029958484987' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/2642621029958484987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/2642621029958484987'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2010/03/dont-code-while-designing.html' title='Don&apos;t code while designing'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-7833899009708346163</id><published>2010-03-05T17:45:00.005+01:00</published><updated>2010-03-05T17:57:44.239+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pyplot'/><category scheme='http://www.blogger.com/atom/ns#' term='wav'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Python i wykrycie beatu</title><content type='html'>W zasadzie nie wiem jak przetłumaczyć "beat" - uderzenie, rytm? Napisałem skrypt szukający beatów w pliku dźwiękowym. Jako materiał do analizy posłużyło pierwszy 10 sekund piosenki. Beat zdefiniowany jest jako skok chwilowej energii sygnału, co odbierane jest przez ucho jako głośniejszy dźwięk.&lt;br /&gt;Więcej informacji tutaj: &lt;a href="http://www.gamedev.net/reference/programming/features/beatdetection/"&gt;http://www.gamedev.net/reference/programming/features/beatdetection/&lt;/a&gt;&lt;br /&gt;&lt;pre name="code" class="python"&gt;__author__ = "daniel"&lt;br /&gt;__date__ = "$2010-03-04 00:21:00$"&lt;br /&gt;&lt;br /&gt;from scipy.io import wavfile&lt;br /&gt;import matplotlib.pyplot as pyplot&lt;br /&gt;import numpy&lt;br /&gt;&lt;br /&gt;if __name__ == "__main__":&lt;br /&gt;# wczytanie pliku&lt;br /&gt;fs, dane = wavfile.read("/home/daniel/Muzyka/steady10s.wav")&lt;br /&gt;# laczenie dwoch kanalow w jeden&lt;br /&gt;print dane.shape&lt;br /&gt;dane = dane[:, 0] / 2.0 + dane[:, 1] / 2.0&lt;br /&gt;# normalizacja&lt;br /&gt;dane = dane / max(dane)&lt;br /&gt;# obliczanie energii przenoszonej przez sygnal&lt;br /&gt;dane = dane**2&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# o tyle probek bedziemy skakac w czasie analizy&lt;br /&gt;k = fs / 10&lt;br /&gt;# dlugosc okna analizy&lt;br /&gt;N = 2 ** 10&lt;br /&gt;i = 0&lt;br /&gt;# ilosc probek w pliku&lt;br /&gt;length, = dane.shape&lt;br /&gt;# const, ile razy wieksza musi byc wartosc energii sygnalu zeby uznany byl za beat&lt;br /&gt;C = 2&lt;br /&gt;srednia = []&lt;br /&gt;# w ktorych momentach wykryto beat&lt;br /&gt;beats = []&lt;br /&gt;while i*k+N &lt;= length:&lt;br /&gt;srednia.append(abs(dane[i*k:i*k+N-1].mean()))&lt;br /&gt;# sprawdzamy ostatnie 42 usrednienia, czyli ~1s&lt;br /&gt;if (sum(srednia[-42:])/42 * C &lt; srednia[-1]):&lt;br /&gt;#print "Beat @", i*k+N/2, "i:", i&lt;br /&gt;beats.append(i)&lt;br /&gt;i+=1&lt;br /&gt;&lt;br /&gt;srednia = numpy.array(srednia)&lt;br /&gt;# skalowanie ybeats do 2-krotności średniej energii w danym punkcie (dla przejrzystosci)&lt;br /&gt;ybeats = numpy.ones(shape=len(beats))&lt;br /&gt;for i, b in enumerate(beats):&lt;br /&gt;ybeats[i] *= srednia[b] * 2&lt;br /&gt;&lt;br /&gt;# rysowanie wykresów (mocno podobne do matlaba)&lt;br /&gt;pyplot.plot(srednia)&lt;br /&gt;pyplot.hold(True)&lt;br /&gt;pyplot.stem(beats, ybeats, 'k')&lt;br /&gt;pyplot.title("Beats")&lt;br /&gt;pyplot.savefig("/home/daniel/Obrazy/steady10sbeats.png")&lt;br /&gt;pyplot.show()&lt;/pre&gt;A oto wynik:&lt;img src="http://imgur.com/2l2zj.png" alt="Hosted by imgur.com" /&gt;Szczęśliwym trafem Steady as she goes ma bardzo wyraźny rytm na początku, więc łatwo go wykryć. Kolejnym krokiem będzie analiza trudniejszego materiału.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-7833899009708346163?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/7833899009708346163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/7833899009708346163'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2010/03/python-i-wykrycie-beatu.html' title='Python i wykrycie beatu'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-4964938624881657151</id><published>2010-03-05T15:22:00.004+01:00</published><updated>2010-03-05T17:48:02.729+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pyplot'/><category scheme='http://www.blogger.com/atom/ns#' term='wav'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Python i analiza dźwięku</title><content type='html'>Skrypt analizujący głośność dźwięku zapisanego w pliku wav napisany w Pythonie. Obliczana jest wartość średnia w oknie o długości N. Kolejne okna to k:k+N-1, 2*k:2*k+N-1, ... , gdy k &lt; N to okna się nakładają. Na końcu z pomocą biblioteki matplotlib rysowany jest wykres głośności.&lt;pre name="code" class="python"&gt;__author__ = "daniel"&lt;br /&gt;&lt;br /&gt;__date__ = "$2010-03-04 00:21:00$"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;from scipy.io import wavfile&lt;br /&gt;&lt;br /&gt;import matplotlib.pyplot as pyplot&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;if __name__ == "__main__":&lt;br /&gt;&lt;br /&gt;# wczytanie pliku &lt;br /&gt;&lt;br /&gt;fs, dane = wavfile.read("/home/daniel/Muzyka/labedzie.wav")&lt;br /&gt;&lt;br /&gt;# laczenie dwoch kanalow w jeden&lt;br /&gt;&lt;br /&gt;dane = dane[:, 0] / 2.0 + dane[:, 1] / 2.0&lt;br /&gt;&lt;br /&gt;# normalizacja&lt;br /&gt;&lt;br /&gt;dane = dane / max(dane)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# o tyle probek bedziemy skakac w czasie analizy&lt;br /&gt;&lt;br /&gt;k = fs / 10&lt;br /&gt;&lt;br /&gt;# dlugosc okna analizy&lt;br /&gt;&lt;br /&gt;N = 2 ** 13&lt;br /&gt;&lt;br /&gt;i = 0&lt;br /&gt;&lt;br /&gt;# ilosc probek w pliku&lt;br /&gt;&lt;br /&gt;length, = dane.shape&lt;br /&gt;&lt;br /&gt;srednia = []&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;while i * k + N &lt; length:&lt;br /&gt;        srednia.append(abs(dane[i*k:i*k+N-1].mean()))&lt;br /&gt;        i+=1&lt;br /&gt;&lt;br /&gt;    pyplot.plot(srednia)&lt;br /&gt;    pyplot.title("Wykres glosnosci")&lt;br /&gt;    pyplot.show()&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-4964938624881657151?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4964938624881657151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4964938624881657151'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2010/03/python-i-analiza-dzwieku.html' title='Python i analiza dźwięku'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-4742089907983935693</id><published>2010-03-01T15:44:00.001+01:00</published><updated>2010-03-01T15:45:14.087+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='kernel'/><category scheme='http://www.blogger.com/atom/ns#' term='kompilacja'/><title type='text'>Kompilacja kernela 2.6.9 na RedHat 8.0</title><content type='html'>RedHat 8.0 zainstalowałem z 5 płyt CD z których w czasie instalacji potrzebne są chyba tylko 2 pierwsze.&lt;br /&gt;W trakcie instalacji pozaznaczałem, że chcę mieć zainstalowane narzędzia programistyczne (m. in. kernel development).&lt;br /&gt;&lt;br /&gt;Po ściągnięciu i rozpakowaniu kernela podawałem kolejno komendy:&lt;br /&gt;&lt;blockquote&gt;make mrproper&lt;br /&gt;make menuconfig (tu trzeba pamiętać, żeby obsługa ext3fs była wbudowana w kernel, a nie jako moduł, ponieważ partycja boot jest w ext3)&lt;br /&gt;make dep&lt;br /&gt;make clean&lt;br /&gt;make bzImage&lt;br /&gt;make modules&lt;br /&gt;make modules_install (jako root, i nie "make module_install"!!!)&lt;br /&gt;&lt;br /&gt;/sbin/mkinitrd /boot/initrd-2.6.9 2.6.9&lt;br /&gt;&lt;br /&gt;cp arch/i386/boot/bzImage /boot/vmlinuz-2.6.9&lt;br /&gt;cp System.map /boot/System.map-2.6.9&lt;br /&gt;ln -s /boot/System.map /boot/System.map-2.6.9&lt;/blockquote&gt;&lt;br /&gt;W pliku /boot/grub/grub.conf należy dodać wpis:&lt;br /&gt;&lt;blockquote&gt;title Red Hat Linux (2.6.9)&lt;br /&gt;        root (hd0,0)&lt;br /&gt;        kernel /vmlinuz-2.6.9 ro root=LABEL=/&lt;br /&gt;        initrd /initrd-2.6.9.img&lt;/blockquote&gt;&lt;br /&gt;Błędy:&lt;br /&gt;&gt;&gt; depmod can't open /lib/modules/2.4.18-14/modules.dep for writing&lt;br /&gt;&gt;&gt; Warning: you may have to install module-init-tools&lt;br /&gt;Rozwiązanie jest takie jak w warning - zainstalować module-init-tools. Przeprowadzi przez to ten poradnik: http://www.linuxquestions.org/linux/answers/Applications_GUI_Multimedia/How_to_Compile_2_6_kernel_for_RedHat_9_8 w krokach 2:4.&lt;br /&gt;&lt;br /&gt;Grub: nie można znaleźć pliku, error 15. Czy na pewno przekopiowany jest bzImage i System.map ? Ścieżka powinna zaczynać się od /, a nie od /boot/ - patrz NOTICE w grub.conf.&lt;br /&gt;Błąd "pivotroot: pivot_root(/sysroot,/sysroot/initrd) failed" oznacza, że obsługa ext3fs nie jest wbudowana w kernel. Trzeba ją dodać z pomocą "y" w kroku z make menuconfig.&lt;br /&gt;&lt;br /&gt;Teraz pozostaje tylko restart i użycie nowego kernela. Mi podczas wstawania systemu wyskoczyła tylko niepokojąca mnie informacja o jakichś problemach z eth0, ale do projektu nie będzie mi to potrzebne najprawdopodobniej, więc na razie się nie martwię.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-4742089907983935693?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4742089907983935693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4742089907983935693'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2010/03/kompilacja-kernela-269-na-redhat-80.html' title='Kompilacja kernela 2.6.9 na RedHat 8.0'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-7736164927378016007</id><published>2010-01-23T01:13:00.002+01:00</published><updated>2010-01-23T01:25:06.775+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='konsola'/><title type='text'>Wyszukiwanie tekstu w plikach za pomocą konsoli</title><content type='html'>Stanąwszy dzisiaj w obliczu potrzeby wyszukania pewnego tekstu w plikach tekstowych, które znajdują się w biężącym katalogu lub w którymś z jego podkatalogów poszperałem trochę w pomocy i wynalazłem taką kombinację:&lt;br /&gt;&lt;b&gt;cat $(find . -name "*.txt" -print) | grep -H -i tekst&lt;/b&gt;&lt;br /&gt;Od początku:&lt;br /&gt;&lt;b&gt;find . -name "*.txt" -print&lt;/b&gt; - wyszukuje wszystkie pliki w katalogu bieżacym (.) lub głębiej o nazwie pasującej do *.txt i wyświetla na ekranie (-print)&lt;br /&gt;&lt;b&gt;$(find . -name "*.txt" -print)&lt;/b&gt; - otoczenie nawiasami ochronnymi aby wynik find "wkleił" się jako argument polecenia cat. Taki sam efekt można uzyskać przy pomocy otoczenia ` ` (znak nad tabem).&lt;br /&gt;&lt;b&gt;cat $(find . -name "*.txt" -print)&lt;/b&gt; - wypisuje zawartość plików podanych przez find&lt;br /&gt;&lt;b&gt;cat $(find . -name "*.txt" -print) | grep -H -i tekst&lt;/b&gt; - wyjście cat jest podawane do grepa, który wyszukuje w nim tekstu "tekst" będąc niewrażliwym na wielkość liter (-i) oraz dodając nazwę pliku dla każdej linii w której znajduje się trafienie (-H).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-7736164927378016007?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/7736164927378016007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/7736164927378016007'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2010/01/wyszukiwanie-tekstu-w-plikach-za-pomoca.html' title='Wyszukiwanie tekstu w plikach za pomocą konsoli'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-273578711608352574</id><published>2010-01-17T19:36:00.000+01:00</published><updated>2010-01-17T19:36:39.238+01:00</updated><title type='text'>Głośniki w laptopie i słuchawki/głośniki</title><content type='html'>Okazuje się, że Karmic Koala również ma problem z przełączaniem się pomiędzy głośnikami laptopa i słuchawkami czy głośnikami. Po włożeniu wtyczki grają oba zestawy. Oto co dostaję po wykonaniu &lt;b&gt;&lt;i&gt;lspci | grep -i audio&lt;/i&gt;&lt;/b&gt;: &lt;blockquote&gt;00:1b.0 Audio device: Intel Corporation 82801H (ICH8 Family) HD Audio Controller (rev 03)&lt;/blockquote&gt;Natomiast mikser alsa pokazał mi, że mam jakąś kartę Realtek. Rozwiązaniem okazało się dodanie w pliku /etc/modprobe.d/alsa-base.conf linijki: &lt;i&gt;options snd-hda-intel model=auto&lt;/i&gt;. Po restarcie komputera wszystko działa już jak należy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-273578711608352574?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/273578711608352574'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/273578711608352574'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2010/01/gosniki-w-laptopie-i-suchawkigosniki.html' title='Głośniki w laptopie i słuchawki/głośniki'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-4116078401508270653</id><published>2010-01-01T21:43:00.009+01:00</published><updated>2010-01-01T23:12:47.196+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rtlinux'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='kernel'/><category scheme='http://www.blogger.com/atom/ns#' term='kompilacja'/><title type='text'>Kompilacja kernela RTLinux</title><content type='html'>Jakiś czas żyłem w przekonaniu, że dostępna w repozytorium paczka linux-image-rt zawiera to samo jądro które jest podstawą RTLinuxa &lt;a href="http://www.rtlinuxfree.com"&gt;strona domowa RTLinux&lt;/a&gt;. Zatem aby skompilować jądro z patchem RTLinuxa będę musiał włożyć w to więcej wysiłku.&lt;br /&gt;Zacząłem od ściągnięcia patcha RTLinux ze strony domowej, a następnie kodu źródłowego kernela z &lt;a href="http://www.kernel.org"&gt;www.kernel.org&lt;/a&gt;. Dopiero po jakimś czasie zorientowałem się, że nie mogę używać kodu ostatniego kernela, bo nie ma dostępnego dla niego patcha. Musiałem więc ściągnąć kernel w wersji 2.6.9. Dalsze postępowanie wyglądało następująco:&lt;br /&gt;Skopiowałem plik rtlinux-3.2-wr.tar.bz2 do katalogu /usr/src.&lt;br /&gt;Rozpakowałem go poleceniem &lt;span style="font-weight:bold;"&gt;tar xjf rtlinux-3.2-wr.tar.bz2&lt;/span&gt;&lt;br /&gt;Wszedłem do katalogu rtlinux-3.2-wr&lt;br /&gt;Skopiowałem tu plik linux-2.6.9.tar.bz2 i rozpakowałem.&lt;br /&gt;Utworzyłem dowiązanie symboliczne: &lt;span style="font-weight:bold;"&gt;ln -fs linux-2.6.9 linux&lt;/span&gt;&lt;br /&gt;Wszedłem przez link linux do katalogu z rozpakowanymi źródłami kernela.&lt;br /&gt;Teraz należy zaaplikować patch, który znajduje się &lt;a href="http://www.kernel.org/pub/linux/devel/binutils/linux-2.6-seg-5.patch"&gt;tutaj&lt;/a&gt;. Inaczej otrzymamy błędy kompilacji w postaci: &lt;blockquote&gt;{standard input}: Assembler messages:&lt;br /&gt;{standard input}:607: Error: suffix or operands invalid for `mov'&lt;br /&gt;{standard input}:630: Error: suffix or operands invalid for `mov'&lt;br /&gt;{standard input}:1144: Error: suffix or operands invalid for `mov'&lt;br /&gt;{standard input}:1145: Error: suffix or operands invalid for `mov'&lt;br /&gt;{standard input}:1146: Error: suffix or operands invalid for `mov'&lt;br /&gt;{standard input}:1147: Error: suffix or operands invalid for `mov'&lt;br /&gt;make[1]: *** [arch/x86_64/kernel/process.o] Error 1&lt;br /&gt;make: *** [arch/x86_64/kernel] Error 2&lt;/blockquote&gt; &lt;a href="http://kerneltrap.org/node/5785"&gt;Rozwiązanie przyszło stąd.&lt;/a&gt; Zatem należy wykonać: &lt;span style="font-weight:bold;"&gt;patch -p1 &lt; /sciezka/do/patcha/linux-2.6-seg-5.patch&lt;/span&gt;&lt;br /&gt;Następnie zaaplikować patch RTLinuksa: &lt;span style="font-weight:bold;"&gt;patch -p1 &lt; ../patches/kernel_patch-2.6.9-rtl3.2-rc1&lt;/span&gt;&lt;br /&gt;Po tym wszystkim należe skonfigurować opcje kernela za pomocą jednego z poleceń: &lt;span style="font-weight:bold;"&gt;make menuconfig, make xconfig, make gconfig&lt;/span&gt;. Pojawi się menu w którym można wybrać czy dana opcja ma być wkompilowana w jądro czy doinstalowywana jako moduł lub całkowicie usunięta.&lt;br /&gt;Teraz postępując dalej wg tej instrukcji: &lt;a href="http://blog.0x1fff.com/2009/04/debian-gnulinux-kompilacja-jadra.html"&gt;http://blog.0x1fff.com/2009/04/debian-gnulinux-kompilacja-jadra.html&lt;/a&gt;&lt;br /&gt;Dostałem błąd o ponownie definiowanych makrach fake_stake_cośtam i unfake_stake_itd. Jak dowiedziałem się na jakimś forum należy otworzyć plik w którym makra są ponownie definiowane i po prostu je usunąć. Niestety zgubił mi się już link, gdzie to przeczytałem.&lt;br /&gt;&lt;br /&gt;W tej chwili otrzymuję błędy o niepełnym typie tablicy.&lt;blockquote&gt;In file included from fs/compat_ioctl.c:69,&lt;br /&gt;                 from arch/x86_64/ia32/ia32_ioctl.c:14:&lt;br /&gt;include/linux/i2c.h:58: error: array type has incomplete element type&lt;br /&gt;include/linux/i2c.h:205: error: array type has incomplete element type&lt;br /&gt;make[2]: *** [arch/x86_64/ia32/ia32_ioctl.o] Błąd 1&lt;br /&gt;make[1]: *** [arch/x86_64/ia32] Błąd 2&lt;br /&gt;make[1]: Opuszczenie katalogu `/usr/src/rtlinux-3.2-wr/linux-2.6.9'&lt;br /&gt;make: *** [debian/stamp/build/kernel] Błąd 2&lt;br /&gt;&lt;/blockquote&gt; Powodowane jest to tym, że w czasach kernela 2.6.9 używało się starszych narzędzi kompilacji, które najwyraźniej były bardziej pobłażliwe niż obecne.&lt;br /&gt;Zamieniłem linię 58 w incude/linux/i2c.h:&lt;br /&gt;extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],int num);&lt;br /&gt;na&lt;br /&gt;extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg,int num);&lt;br /&gt;oraz&lt;br /&gt; int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg msgs[], &lt;br /&gt;                    int num);&lt;br /&gt;na&lt;br /&gt; int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg *msgs, &lt;br /&gt;                    int num);&lt;br /&gt;W pliku /include/linux/fb.h linia 751:&lt;br /&gt;extern const struct fb_videomode vesa_modes[];&lt;br /&gt;na&lt;br /&gt;extern const struct fb_videomode *vesa_modes;&lt;br /&gt;&lt;br /&gt;Teraz zatrzymałem się z błędem:&lt;blockquote&gt;/usr/bin/ld: arch/x86_64/ia32/vsyscall-sysenter.so: Not enough room for program headers, try linking with -N&lt;br /&gt;/usr/bin/ld: final link failed: Bad value&lt;br /&gt;collect2: ld returned 1 exit status&lt;br /&gt;make[2]: *** [arch/x86_64/ia32/vsyscall-sysenter.so] Błąd 1&lt;br /&gt;make[1]: *** [arch/x86_64/ia32] Błąd 2&lt;br /&gt;make[1]: Opuszczenie katalogu `/usr/src/rtlinux-3.2-wr/linux-2.6.9'&lt;br /&gt;make: *** [debian/stamp/build/kernel] Błąd 2&lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-4116078401508270653?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4116078401508270653'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4116078401508270653'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2010/01/kompilacja-kernela-rtlinux.html' title='Kompilacja kernela RTLinux'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-4082071179825562271</id><published>2009-11-27T22:06:00.008+01:00</published><updated>2009-11-28T10:52:32.051+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sqlite'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>Tysiąc insertów na sekundę</title><content type='html'>Dokładniej 50,000 na typowym komputerze - tak przynajmniej twierdzą &lt;a href="http://www.sqlite.org/faq.html#q19"&gt;twórcy sqlite3 w FAQ.&lt;/a&gt; Miałem okazję przekonać się o tym na własnej skórze. W programie o którym wcześniej pisałem chciałbym zapisywać dane o cząsteczkach w danej iteracji algorytmu. Oto kod przed optymalizacją:&lt;br /&gt;&lt;pre name="code" class="c++"&gt;void SaveResultsToDatabase(sqlite3* db, Particle* host_agents, const int N, const int generation) {&lt;br /&gt;    char stmt[90];&lt;br /&gt;    char* errorMsg = NULL;&lt;br /&gt;    int returnCode;&lt;br /&gt;&lt;br /&gt;    int i = 0;&lt;br /&gt;    for (i = 0; i &lt; N; ++i) {&lt;br /&gt;        sprintf(stmt, "insert into pso values (%d, %d, %f, %f); ",&lt;br /&gt;                generation,&lt;br /&gt;                i,&lt;br /&gt;                host_agents[i].current.x,&lt;br /&gt;                host_agents[i].current.y);&lt;br /&gt;        returnCode = sqlite3_exec(db, stmt, NULL, NULL, &amp;errorMsg);&lt;br /&gt;        if (returnCode != SQLITE_OK) {&lt;br /&gt;            if (errorMsg != NULL) {&lt;br /&gt;                printf("%s", errorMsg);&lt;br /&gt;                sqlite3_free(errorMsg);&lt;br /&gt;            } else {&lt;br /&gt;                printf("Return code: %d\n", returnCode);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;} &lt;/pre&gt; W tym przypadku czas wykonania to około minuty dla 1000 wpisów. Każdy &lt;span style="font-weight:bold;"&gt;insert&lt;/span&gt; jest wykonywany, baza czeka aż dane będą bezpieczne i dopiero wykonuje następny wpis. Jednak tak jak to jest opisane w FAQ można tego uniknąć tworząc jedną wielką transakcję zamkniętą w klamry &lt;span style="font-weight:bold;"&gt;BEGIN TRANSACTION;&lt;/span&gt; i &lt;span style="font-weight:bold;"&gt;COMMIT&lt;/span&gt;:&lt;br /&gt;&lt;pre name="code" class="c++"&gt; void SaveResultsToDatabase(sqlite3* db, Particle* host_agents, const int N, const int generation) {&lt;br /&gt;    char buffer[90];&lt;br /&gt;    char stmt [N * 90];&lt;br /&gt;    strcpy(stmt, "BEGIN TRANSACTION; ");&lt;br /&gt;    char* errorMsg = NULL;&lt;br /&gt;    int returnCode;&lt;br /&gt;&lt;br /&gt;    int i = 0;&lt;br /&gt;    for (i = 0; i &lt; N; ++i) {&lt;br /&gt;        sprintf(buffer, "insert into pso values (%d, %d, %f, %f); ",&lt;br /&gt;                generation,&lt;br /&gt;                i,&lt;br /&gt;                host_agents[i].current.x,&lt;br /&gt;                host_agents[i].current.y);&lt;br /&gt;        strcat(stmt, buffer);&lt;br /&gt;    }&lt;br /&gt;    strcat(stmt, "COMMIT");&lt;br /&gt;    returnCode = sqlite3_exec(db, stmt, NULL, NULL, &amp;errorMsg);&lt;br /&gt;    if (returnCode != SQLITE_OK) {&lt;br /&gt;        if (errorMsg != NULL) {&lt;br /&gt;            printf("%s", errorMsg);&lt;br /&gt;            sqlite3_free(errorMsg);&lt;br /&gt;        } else {&lt;br /&gt;            printf("Return code: %d\n", returnCode);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;} &lt;/pre&gt; W tym przypadku czas wykonania jest poniżej sekundy. Niezła optymalizacja.&lt;br /&gt;BREAKING NEWS. Właśnie spróbowałem zapisać 100000 wpisów i okazało się, że trwa to około 1,5 minuty. Nie wiedziałem dlaczego aż tyle. Z początku myślałem, że chodzi o manipulowanie char*, ciągłe przydzielanie pamięci itp, ale potem przypomniało mi się, że ktoś pisał o tym, żeby znaleźć "optimal insert size for your database". Czas zatem na kolejną zmianę kodu:&lt;br /&gt;&lt;pre name="code" class="c++"&gt;void SaveResultsToDatabase(sqlite3* db, Particle* host_agents, const int N, const int generation) {&lt;br /&gt;    printf("Saving to database\n");&lt;br /&gt;    const int partSize = 5000;&lt;br /&gt;    char buffer[90];&lt;br /&gt;    char stmt [partSize * 90];&lt;br /&gt;    int i = 0;&lt;br /&gt;    while (i &lt; N) {&lt;br /&gt;        strcpy(stmt, "BEGIN TRANSACTION; ");&lt;br /&gt;        char* errorMsg = NULL;&lt;br /&gt;        int returnCode;&lt;br /&gt;&lt;br /&gt;        do {&lt;br /&gt;            sprintf(buffer, "insert into pso values (%d, %d, %f, %f); ",&lt;br /&gt;                    generation,&lt;br /&gt;                    i,&lt;br /&gt;                    host_agents[i].current.x,&lt;br /&gt;                    host_agents[i].current.y);&lt;br /&gt;            strcat(stmt, buffer);&lt;br /&gt;            ++i;&lt;br /&gt;        } while ((i % partSize != 0) &amp;&amp; i &lt; N);&lt;br /&gt;        strcat(stmt, "COMMIT");&lt;br /&gt;        returnCode = sqlite3_exec(db, stmt, NULL, NULL, &amp;errorMsg);&lt;br /&gt;        if (returnCode != SQLITE_OK) {&lt;br /&gt;            if (errorMsg != NULL) {&lt;br /&gt;                fprintf(stderr, "%s\n", errorMsg);&lt;br /&gt;                sqlite3_free(errorMsg);&lt;br /&gt;            } else {&lt;br /&gt;                fprintf(stderr, "sqlite3 return code: %d\n", returnCode);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; W obecnej postaci wykonanie kodu trwa 23 sekundy dla 3 iteracji po 100000 cząsteczek, włączając w to przesyłanie danych, obliczenia na karcie graficznej i wyświetlanie komunikatów w terminalu (to chyba najbardziej spowalnia program). Przypuszczam, że jeszcze będę eksperymentować z wielkością wrzutów do bazy danych.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-4082071179825562271?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4082071179825562271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4082071179825562271'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2009/11/tysiac-insertow-na-sekunde.html' title='Tysiąc insertów na sekundę'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-30370205438489374</id><published>2009-11-27T21:08:00.003+01:00</published><updated>2009-11-27T21:38:54.253+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cli'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>Przeszukiwanie listy argumentów linii poleceń w C</title><content type='html'>Po długich i wyczerpujących walkach z nvcc (kod skompilowany nvcc nie bardzo się komponuje z g++, nie wiem czemu, innym DZIAŁA - SOA#1) postanowiłem, że algorytm optymalizacji rojem będzie miał postać programu w C, który zapisze wynik działania algorytmu w bazie sqlite3, a ja sobie w innej aplikacji skompilowanej już normalnym kompilatorem będę te dane obrabiał. W międzyczasie okazało się, że fajnie byłoby ustalać liczbę cząsteczek roju i postanowiłem do tego wykorzystać argumenty linii poleceń. Wtedy pojawił się problem jak z &lt;span style="font-weight:bold;"&gt;argc&lt;/span&gt; i &lt;span style="font-weight:bold;"&gt;argv&lt;/span&gt; wyciągnąć to o co mi chodzi. Czynność ta jest wykorzystywana na porządku dziennym w programach, więc istnieje w tym celu odpowiednia procedura, a nazywa się ona &lt;span style="font-weight:bold;"&gt;getopt()&lt;/span&gt; i znajduje się w pliku nagłówkowym &lt;span style="font-weight:bold;"&gt;unistd.h&lt;/span&gt;. W obecnej chwili używam dwóch opcji: &lt;span style="font-weight:bold;"&gt;-n&lt;/span&gt; oraz &lt;span style="font-weight:bold;"&gt;-o&lt;/span&gt;. Obie wymagają argumentu. Oto kod:&lt;br /&gt;&lt;pre name="code" class="C++"&gt;#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;int main(int argc, char** argv) {&lt;br /&gt;    //initialize variables&lt;br /&gt;    int N = 10; // Ilosc agentow&lt;br /&gt;    int c = 0;&lt;br /&gt;    char* dbfilename = NULL;&lt;br /&gt;   &lt;br /&gt;    while((c = getopt(argc, argv, "n:o:")) != -1)&lt;br /&gt;    {&lt;br /&gt;        switch(c)&lt;br /&gt;        {&lt;br /&gt;            case 'n':&lt;br /&gt;                N = atoi(optarg);&lt;br /&gt;                printf("Number of particles: %d\n", N);&lt;br /&gt;                if (N &lt;= 0)&lt;br /&gt;                {&lt;br /&gt;                    fprintf(stderr, "Invalid number of particles, setting to default = 10\n");&lt;br /&gt;                    N = 10;&lt;br /&gt;                }&lt;br /&gt;                break;&lt;br /&gt;            case 'o':&lt;br /&gt;                dbfilename = optarg;&lt;br /&gt;                printf("Output to file: %s\n", dbfilename);&lt;br /&gt;                break;&lt;br /&gt;            case '?':&lt;br /&gt;                switch(optopt)&lt;br /&gt;                {&lt;br /&gt;                    case 'n':&lt;br /&gt;                    fprintf(stderr, "Option -n sets number of particles and requires integer argument.\n");&lt;br /&gt;                    break;&lt;br /&gt;                    case 'o':&lt;br /&gt;                        fprintf(stderr, "Option -o sets name of output file and requires a string argument.\n");&lt;br /&gt;                        break;&lt;br /&gt;                    default:&lt;br /&gt;                        fprintf(stderr, "Unknown option: %c\n", optopt);&lt;br /&gt;                };&lt;br /&gt;                break;&lt;br /&gt;            default:&lt;br /&gt;                printf("Abort: %d = %c\n", c, c);&lt;br /&gt;                abort();&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt; Przede wszystkim po "przegryzieniu się" przez wszystkie argumenty &lt;span style="font-weight:bold;"&gt;getopt()&lt;/span&gt; zwraca &lt;span style="font-weight:bold;"&gt;-1&lt;/span&gt;, dlatego taki warunek jest w while. W przeciwnym przypadku dostaniemy wartość znaku, który reprezentuje opcję. Opcje jakie przewidujemy w programie podajemy jako trzeci argument. Aby zaznaczyć, że opcja ma wymagany argument należy dodać po niej "&lt;span style="font-weight:bold;"&gt;:&lt;/span&gt;". Aby zaznaczyć, że opcja ma opcjonalny argument dodajemy "&lt;span style="font-weight:bold;"&gt;::&lt;/span&gt;". W switch podejmujemy odpowiednią akcję w zależności od opcji.&lt;br /&gt;Dla &lt;span style="font-weight:bold;"&gt;-n&lt;/span&gt; będzie to zamiana alphanumeric to integer, czyli zamiana łańcucha znaków na liczbę całkowitą, a następnie sprawdzenie czy wartość ta jest większa od 0. Argument dla opcji jest przechowywany w &lt;span style="font-weight:bold;"&gt;optarg&lt;/span&gt; jako łańcuch znaków.&lt;br /&gt;Opcja &lt;span style="font-weight:bold;"&gt;-o&lt;/span&gt; odpowiada za nazwę pliku wynikowego. Jak widać można przypisać wskaźnik &lt;span style="font-weight:bold;"&gt;optarg&lt;/span&gt; do wskaźnika typu char*, czyli nie jest on typu const char* (tak jakby to było w przypadku np printf("Tekst typu const char*"). Dokładniej &lt;span style="font-weight:bold;"&gt;optarg&lt;/span&gt; wskazuje na jeden z elementów &lt;span style="font-weight:bold;"&gt;argv&lt;/span&gt;, więc można go modyfikować. W przypadku błędów podawana jest wartość &lt;span style="font-weight:bold;"&gt;'?'&lt;/span&gt; co może oznaczać brak argumentu dla opcji lub nieznaną opcję.&lt;br /&gt;Opcja &lt;span style="font-weight:bold;"&gt;default&lt;/span&gt; z tego co zrozumiałem nie ma prawa się wydarzyć, ale dodałem tam trochę kodu, żeby dowiedzieć się co się dzieje w razie czego. W końcu dobry programista patrzy w obie strony przed przejściem przez jednokierunkową ulicę.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-30370205438489374?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/30370205438489374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/30370205438489374'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2009/11/przeszukiwanie-listy-argumentow-linii.html' title='Przeszukiwanie listy argumentów linii poleceń w C'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-4697270977354050045</id><published>2009-11-06T17:39:00.003+01:00</published><updated>2009-11-06T18:46:05.509+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CUDA'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>CUDA 2.3 na Ubuntu 9.10 cz. 2</title><content type='html'>Teraz należałoby sprawdzić czy wszystko jest poprawnie zainstalowane kompilując przykładowe projekty.&lt;br /&gt;Skracając cały proces pokonywania błędów jakie wystąpiły w czasie tego polecenia:&lt;br /&gt;1) CUDA nie działa z kompilatorami w wersji 4.4. Niestety odinstalowanie gcc-4.4 nie wchodziło w grę, gdyż musiałbym również odinstalować świeżo zainstalowane sterowniki. Zainstalowałem więc gcc i g++ w wersji 4.3.&lt;blockquote&gt;sudo apt-get install gcc-4.3 g++-4.3&lt;/blockquote&gt;Potem próbowałem zmienić makefile, aby zamiast &lt;blockquote&gt;CXX        := g++&lt;br /&gt;CC         := gcc&lt;br /&gt;LINK       := g++ -fPIC&lt;br /&gt;&lt;/blockquote&gt; mieć &lt;blockquote&gt;CXX        := g++-4.3&lt;br /&gt;CC         := gcc-4.3&lt;br /&gt;LINK       := g++-4.3 -fPIC&lt;br /&gt;&lt;/blockquote&gt;Niestety to nic nie dało. Jeden z użytkowników z forum NVIDIA doszedł do wniosku, że zmienne te &lt;a href="http://forums.nvidia.com/index.php?showtopic=104525&amp;view=findpost&amp;p=945801"&gt;nadpisywane są w którymś z innych makefile'ów&lt;/a&gt;. Cofnąłem zmiany i zamiast tego zmieniłem dowiązanie /usr/bin/gcc z gcc-4.4 na gcc-4.3.&lt;br /&gt;&lt;blockquote&gt;sudo rm /usr/bin/gcc&lt;br /&gt;sudo ln -s -v gcc-4.3 /usr/bin/gcc&lt;/blockquote&gt; Analogiczną operację przeprowadziłem też dla g++. Sprawdziłem czy pod linkiem gcc jest kompilator o właściwej wersji: &lt;blockquote&gt;gcc --version&lt;br /&gt;gcc (Ubuntu 4.3.4-5ubuntu1) 4.3.4&lt;br /&gt;Copyright (C) 2008 Free Software Foundation, Inc.&lt;br /&gt;This is free software; see the source for copying conditions.  There is NO&lt;br /&gt;warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.&lt;br /&gt;&lt;/blockquote&gt;2) Potrzebne też będą paczki libxmu-dev libxi-dev freeglut3 freeglut3-dev.&lt;br /&gt;&lt;br /&gt;3) Teraz można już budować projekty.&lt;blockquote&gt;cd ~/Projects/NVIDIA_GPU_Computing_SDK/C&lt;br /&gt;make&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Jeśli wszystko dobrze zapamiętałem to nie powinno być żadnych błędów kompilacji i będzie można uruchomić podstawowe programy testujące na obecność urządzenia cuda capable.&lt;blockquote&gt;daniel@daniel-laptop:~/Projects/NVIDIA_GPU_Computing_SDK/C/bin/linux/release$ ./deviceQuery&lt;br /&gt;CUDA Device Query (Runtime API) version (CUDART static linking)&lt;br /&gt;There is 1 device supporting CUDA&lt;br /&gt;&lt;br /&gt;Device 0: "GeForce 8400M GS"&lt;br /&gt;  CUDA Driver Version:                           2.30&lt;br /&gt;  CUDA Runtime Version:                          2.30&lt;br /&gt;  CUDA Capability Major revision number:         1&lt;br /&gt;  CUDA Capability Minor revision number:         1&lt;br /&gt;  Total amount of global memory:                 267714560 bytes&lt;br /&gt;  Number of multiprocessors:                     2&lt;br /&gt;  Number of cores:                               16&lt;br /&gt;  Total amount of constant memory:               65536 bytes&lt;br /&gt;  Total amount of shared memory per block:       16384 bytes&lt;br /&gt;  Total number of registers available per block: 8192&lt;br /&gt;  Warp size:                                     32&lt;br /&gt;  Maximum number of threads per block:           512&lt;br /&gt;  Maximum sizes of each dimension of a block:    512 x 512 x 64&lt;br /&gt;  Maximum sizes of each dimension of a grid:     65535 x 65535 x 1&lt;br /&gt;  Maximum memory pitch:                          262144 bytes&lt;br /&gt;  Texture alignment:                             256 bytes&lt;br /&gt;  Clock rate:                                    0.80 GHz&lt;br /&gt;  Concurrent copy and execution:                 Yes&lt;br /&gt;  Run time limit on kernels:                     Yes&lt;br /&gt;  Integrated:                                    No&lt;br /&gt;  Support host page-locked memory mapping:       No&lt;br /&gt;  Compute mode:                                  Default (multiple host threads can use this device simultaneously)&lt;br /&gt;&lt;br /&gt;Test PASSED&lt;/blockquote&gt;oraz&lt;blockquote&gt;Running on......&lt;br /&gt;      device 0:GeForce 8400M GS&lt;br /&gt;Quick Mode&lt;br /&gt;Host to Device Bandwidth for Pageable memory&lt;br /&gt;.&lt;br /&gt;Transfer Size (Bytes) Bandwidth(MB/s)&lt;br /&gt; 33554432  1473.1&lt;br /&gt;&lt;br /&gt;Quick Mode&lt;br /&gt;Device to Host Bandwidth for Pageable memory&lt;br /&gt;.&lt;br /&gt;Transfer Size (Bytes) Bandwidth(MB/s)&lt;br /&gt; 33554432  898.1&lt;br /&gt;&lt;br /&gt;Quick Mode&lt;br /&gt;Device to Device Bandwidth&lt;br /&gt;.&lt;br /&gt;Transfer Size (Bytes) Bandwidth(MB/s)&lt;br /&gt; 33554432  4197.4&lt;br /&gt;&lt;br /&gt;&amp;&amp;&amp;&amp; Test PASSED&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-4697270977354050045?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4697270977354050045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4697270977354050045'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2009/11/cuda-23-na-ubuntu-910-cz-2.html' title='CUDA 2.3 na Ubuntu 9.10 cz. 2'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-3644814904281062803</id><published>2009-11-06T14:15:00.006+01:00</published><updated>2009-11-06T17:30:15.669+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CUDA'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>CUDA 2.3 na Ubuntu 9.10 cz. 1</title><content type='html'>Kolejne podejście do używania CUDA na Ubuntu. Po kłopotach jakie miałem ze sterownikami NVIDIA na Ubuntu 8.04 postanowiłem przenieść się na najnowsze wydanie 9.10 (flash nie reaguje na kliknięcia, komputer nie wykrywa, że podłączyłem słuchawki - nie ukrywam, że to niemiłe rozczarowanie). Przy okazji zrobiłem upgrade z XP na Windows7.&lt;br /&gt;Najnowsze sterowniki (w wersji 190) zainstalowałem z pomocą tego &lt;a href="http://www.ubuntugeek.com/install-nvidia-graphics-drivers-190-42-in-ubuntu-karmicjauntyintrepidhardy.html"&gt;poradnika z Ubuntu Geek&lt;/a&gt;. W skrócie:&lt;br /&gt;&lt;blockquote&gt;sudo add-apt-repository ppa:nvidia-vdpau/ppa&lt;br /&gt;sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CEC06767&lt;br /&gt;sudo apt-get update&lt;br /&gt;sudo apt-get install nvidia-190-modaliases nvidia-glx-190 nvidia-settings-190&lt;/blockquote&gt;&lt;br /&gt;Należy je jeszcze aktywować w System -&gt; Administracja -&gt; Sterowniki.&lt;br /&gt;&lt;br /&gt;Teraz potrzebne będą Cuda Toolkit 2.3 - nie ma wersji dla Ubuntu 9.10, więc wybrałem wersję dla 9.04. Instalacja według instrukcji przebiega bezproblemowo. Potem zainstalowałem CUDA SDK również w wersji 2.3 dla Ubuntu 9.10.&lt;br /&gt;&lt;br /&gt;Kolejnym krokiem było dodanie ścieżek cuda toolkit do zmiennych środowiskowych. W pliku ~/.bashrc dodałem:&lt;br /&gt;&lt;blockquote&gt;if [ -d "/usr/local/cuda" ] ; then&lt;br /&gt;  PATH="/usr/local/cuda:$PATH"&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;if [ -d "/usr/local/cuda/lib64" ] ; then&lt;br /&gt;  LD_LIBRARY_PATH="/usr/local/cuda/lib64:$LD_LIBRARY_PATH"&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;if [ -d "/usr/local/cuda/bin" ] ; then&lt;br /&gt;  PATH="/usr/local/cuda/bin:$PATH"&lt;br /&gt;fi&lt;/blockquote&gt;Pierwszy if sprawdza czy istnieje /usr/local/cuda, a jeśli tak to dodaje tę ścieżkę do zmiennej systemowej PATH. Kolejny if dodaje ścieżkę do bibliotek odpowiednich dla 64-bitowego systemu. Następnie dodawany jest katalog z plikami wykonawczymi aby móc korzystać z polecenia nvcc bez wpisywania całej ścieżki.&lt;br /&gt;Nie jestem pewien czy w umieściłem ten skrypt w dobrym pliku - jeśli dobrze pamiętam to jest on wywoływany przy każdym włączeniu konsoli. Dobrze by było by dodawało się ono tylko raz przy starcie systemu i tak już zostawało. Po kilku uruchomieniach PATH wygląda tak:&lt;br /&gt;&lt;blockquote&gt;daniel@daniel-laptop:~$ printenv PATH&lt;br /&gt;/usr/local/cuda/bin:/usr/local/cuda:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games&lt;/blockquote&gt;Do tej pory wszystko przebiegało gładko i prawdziwe problemy dopiero się zaczną.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-3644814904281062803?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/3644814904281062803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/3644814904281062803'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2009/11/cuda-23-na-ubuntu-910-cz-1.html' title='CUDA 2.3 na Ubuntu 9.10 cz. 1'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-4103031582175660530</id><published>2009-10-27T16:10:00.006+01:00</published><updated>2009-10-27T16:57:14.316+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CUDA'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>CUDA ruszyła</title><content type='html'>Pierwszy projekt z wykorzystaniem CUDA mam już za sobą. Sam kod nie był trudny do napisania. Najgorsze było skłonienie Visual Studio do podpowiadania kodu (co do tej pory mi się nie udało - podpowiada kod tylko dla zmiennych i funkcji nieCUDA). Kolejna sprawa, która mnie irytowała to ścieżki dla plików nagłówkowych i bibliotek. Na początku zakładałem projekt w Moje Dokumenty\Visual Studio 2008\Projects i usiłowałem w ustawieniach projektu dodać ścieżki do CUDA SDK. Kompilator wywalał błędy, że nie może znaleźć pliku cuda.h podczas gdy wydawało mi się, że wszystko jest w porządku. Ostatecznie wyszło na to, że następujące ustawienia są prawidłowe (dla konfiguracji Debug):&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;- Linker -&gt; General -&gt; Additional Library Directories:&lt;/span&gt; &lt;span style="font-style:italic;"&gt;"C:\CUDA\lib";"C:\Documents and Settings\Yelonek\Ustawienia lokalne\dane aplikacji\NVIDIA Corporation\NVIDIA CUDA SDK\common\lib"&lt;/span&gt; (tutaj taka dziwna ścieżka, bo wybrałem "instaluj tylko dla mnie" podczas instalacji pakietu i nie chciało mi się tego odkręcać)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;- Linker -&gt; Input -&gt; Additional Dependencies:&lt;/span&gt; &lt;span style="font-style:italic;"&gt;cudart.lib cutil32d.lib&lt;/span&gt;&lt;br /&gt;Następny problem jaki się pojawił to to, że VS nie koloruje składni w plikach cu. Można to obejść w następujący sposób:&lt;br /&gt;W katalogu NVIDIA CUDA SDK\doc\syntax_highlighting znajduje się plik usertype.dat, który należy umieścić w katalogu Microsoft Visual Studio 8\Common7\IDE. Następnie w samym VS należy w Tools... -&gt; Options otworzyć Text Editor w liście po lewej i wybrać File Extension. Wpisujemy cu w polu Extension, ustawiamy edytor na MS Visual C++ i klikamy Add. Po zatwierdzeniu zmian i restarcie programu można się już cieszyć pokolorowaną składnią przy przeglądaniu plików cu.&lt;br /&gt;Istnieje jeszcze jeden sposób na trochę wygodniejsze pisanie programów. Patent ten można znaleźć na innych stronach i blogach, ale też go tu opiszę. Polega on na tym, że program piszemy w pliku C, a podczas budowania projektu plik c kopiuje się do pliku cu, a dopiero plik cu jest budowany za pomocą nvcc. Dokonać tego można definiując własne zasady budowania plików. Po kliknięciu ppm na projekt w Solution Explorerze wybieramy Custom Build Steps... Tworzymy nowy plik zasad (New Rule File), podajemy nazwę jaka będzie wyświetlana w VS, nazwę pliku oraz ściężkę w jakiej chcemy go zapisać. Dodajemy nową zasadę (Add Build Rule). Pierwsza zasada to kopiowanie pliku c do cu.&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-weight:bold;"&gt;Command line:&lt;/span&gt;copy $(InputFileName) $(InputName).cu&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Display Name&lt;/span&gt;: Zamiana pliku c na cu&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Execution Description:&lt;/span&gt; $(InputFileName) ------&gt; $(InputName).cu&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;File Extensions:&lt;/span&gt; *.c&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Name:&lt;/span&gt; Zamiana pliku c na cu&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Outputs:&lt;/span&gt; $(InputName).cu&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Show Only Rule Properties:&lt;/span&gt; True&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Supports File Batching:&lt;/span&gt; False&lt;br /&gt;&lt;/blockquote&gt;Druga zasada to kompilacja plików cu za pomocą nvcc:&lt;blockquote&gt;&lt;span style="font-weight:bold;"&gt;Additional dependencies:&lt;/span&gt; $(CUDA_INC_PATH)";"../../common/inc"&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Command Line:&lt;/span&gt; "$(CUDA_BIN_PATH)\nvcc.exe" -ccbin "$(VCInstallDir)bin" -c -D_DEBUG -DWIN32 -D_CONSOLE -D_MBCS -Xcompiler /EHsc,/W3,/nologo,/Wp64,/Od,/Zi,/RTC1,/MTd -I"$(CUDA_INC_PATH)" -I../../common/inc -o $(ConfigurationName)\$(InputName).obj $(InputFileName)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Display Name:&lt;/span&gt; Kompilacja NVIDIA C for CUDA&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Execution Description:&lt;/span&gt; Wywoływanie NVCC&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;File Extension:&lt;/span&gt; *.cu&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Name:&lt;/span&gt; Kompilacja plików CUDA&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Outputs:&lt;/span&gt; $(ConfigurationName)\$(InputName).obj&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Show Only Rule Properties:&lt;/span&gt; True&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Supports File Batching:&lt;/span&gt; False&lt;/blockquote&gt;Teraz tworzymy plik main.c w którym piszemy kod aplikacji. Kopiujemy go (tylko za pierwszym razem) i nazywamy main.cu, a następnie dodajemy do projektu. We właściwościach pliku main.c zamieniamy Tool z C/C++ Compiler na "Zamiana c na cu", a we właściwościach plik main.cu wybieramy "Kompilacja NVIDIA C for CUDA". Od tej pory można już budować projekt za pomocą F6 bez żadnych problemów.&lt;br /&gt;Należy przy tym pamiętać, aby zmian dokonywać w pliku C, a nie CU!!! Gdyby kompilacja projektu się nie udała, to dostaniemy błędy tak jak zawsze, ale dwukrotne kliknięcie przeniesie nas do pliku CU, a nie C!!! Jeśli o tym zapomnimy i zmienimy plik cu, a następnie ponownie zbudujemy projekt wszystko będzie działać: plik c jest niezmieniony, więc VS go ponownie nie buduje (więc plik c nie zostanie skopiowany na plik cu). Załóżmy teraz, że zamknęliśmy projekt, otwieramy go ponownie i edytujemy plik c. Co się dzieje? Plik cu został nadpisany, znika kod pracowicie przez nas napisany i ponownie pojawiają się błędy kompilatora z którymi walczyliśmy przed zamknięciem programu. Można tak stracić parę godzin pracy, więc radzę uważać.&lt;br /&gt;&lt;br /&gt;Na koniec przykładowy kod:&lt;br /&gt;&lt;pre name="code" class="C++"&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#include &amp;lt;cuda.h&amp;gt;&lt;br /&gt;&lt;br /&gt;// Struktura danych pojedynczego agenta&lt;br /&gt;struct Agent&lt;br /&gt;{&lt;br /&gt; float x;&lt;br /&gt; float y;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// Kernel który będzie wykonywał się na karcie&lt;br /&gt;__global__ void Fitness(Agent* agent, int N, float* results)&lt;br /&gt;{&lt;br /&gt; int idx = blockIdx.x * blockDim.x + threadIdx.x;&lt;br /&gt; if (idx &amp;lt; N)&lt;br /&gt; {&lt;br /&gt;  results[idx] = 2 * agent[idx].x * agent[idx].x - agent[idx].x + 3;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Funkcja ktora bedzie wykonywac sie na hoscie&lt;br /&gt;int main(void)&lt;br /&gt;{&lt;br /&gt; // Deklaracja zmiennych&lt;br /&gt; const int N = 10000;        // Ilosc agentow&lt;br /&gt; Agent *host_agents = NULL, *device_agents = NULL; // Wskaznik do tablic u hosta (_h) i na karcie (_d)&lt;br /&gt; size_t size_agents = N * sizeof(Agent);    // Obliczenie rozmiaru tablicy agentow w bajtach&lt;br /&gt; &lt;br /&gt; float *host_results = NULL, *device_results = NULL; // Wskaznik do tablic z wynikami&lt;br /&gt; size_t size_results = N * sizeof(float);   // Obliczenie rozmiarow tablicy wynikow w bajtach&lt;br /&gt;&lt;br /&gt; // Przydzial pamieci&lt;br /&gt; host_agents = (Agent *)malloc(size_agents);        // Przydzial pamieci dla agentow na hoscie&lt;br /&gt; cudaMalloc((void **) &amp;device_agents, size_agents);   // Przydzial pamieci dla agentow na karcie&lt;br /&gt; host_results = (float *)malloc(size_results);  //Przydzial pamieci na wyniki na hoscie&lt;br /&gt; cudaMalloc((void **) &amp;device_results, size_results); //Przydzial pamieci na wyniki na karcie&lt;br /&gt;  &lt;br /&gt; // Wpisanie wartosci poczatkowych do tablicy&lt;br /&gt; for (int i=0; i &amp;lt; N; i++) &lt;br /&gt; {&lt;br /&gt;  host_agents[i].x = (float)(rand()%100);&lt;br /&gt;  host_agents[i].y = (float)(rand()%100);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; //Skopiowanie tablicy z hosta do karty&lt;br /&gt; cudaMemcpy(device_agents, host_agents, size_agents, cudaMemcpyHostToDevice);&lt;br /&gt; // Wywolanie kernela&lt;br /&gt; int block_size = 4;&lt;br /&gt; int n_blocks = N/block_size + (N%block_size == 0 ? 0:1);&lt;br /&gt;&lt;br /&gt; Fitness &amp;lt;&amp;lt;&amp;lt; n_blocks, block_size &amp;gt;&amp;gt;&amp;gt; (device_agents, N, device_results);&lt;br /&gt;&lt;br /&gt; // Odebranie wyników z karty i zapisanie ich w tablicy na hoscie&lt;br /&gt; cudaMemcpy(host_results, device_results, size_results, cudaMemcpyDeviceToHost);&lt;br /&gt;&lt;br /&gt; // Wypisz wyniki&lt;br /&gt; for (int i = 0; i &amp;lt; N; i++) &lt;br /&gt;  printf("%05d: f(%04.4f, %04.4f) = %04.4f;\n", i, host_agents[i].x, host_agents[i].y, host_results[i]);&lt;br /&gt; // Cleanup&lt;br /&gt; free(host_agents);&lt;br /&gt; free(host_results);&lt;br /&gt; cudaFree(device_agents);&lt;br /&gt; cudaFree(device_results);&lt;br /&gt; system("pause");&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-4103031582175660530?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4103031582175660530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/4103031582175660530'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2009/10/cuda-ruszya.html' title='CUDA ruszyła'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-3522545547981495467</id><published>2009-10-20T11:58:00.004+02:00</published><updated>2009-10-27T17:08:44.234+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CUDA'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>CUDA NVidia</title><content type='html'>Niedawno otrzymałem zadanie wykorzystania CUDA w algorytmie optymalizacji polegającym na przeszukiwaniu przestrzeni rozwiązań za pomocą "roju". Zaletą CUDA jest wykorzystanie procesora graficznego do przeprowadzania równoległych obliczeń na wielu zmiennych (przynajmniej w tej chwili tak to rozumiem).&lt;br /&gt;Pomyślałem, że mogę wykonać ten projekt na Ubuntu 8.04.&lt;br /&gt;Udałem się na stronę NVIDIA, gdzie w tej chwili znajdują się sterowniki w wersji 185 oraz CUDA Toolkit 2.2.&lt;br /&gt;Niestety poniosłem porażkę - nie umiałem zainstalować sterowników. Po każdej instalacji Xy wstawały w trybie niskiej jakości grafiki. Doczytałem w internecie, że envyNG instaluje sterowniki NVIDIA wraz z biblioteką libcuda. Za pomocą tego programu udało mi się zainstalować sterowniki w wersji 173. Następnie zainstalowałem CUDA Toolkit oraz CUDA SDK. Zacząłem budować przykładowe projekty. Po wykonaniu make dostałem informację, że nie można znaleźć bibliotek libglut, więc zainstalowałem ją z repozytorium - `&lt;span style="font-weight:bold;"&gt;sudo apt-get install libglut3 libglut3-dev&lt;/span&gt;`. Następnym problemem okazał się projekt threadMigration - tutaj po prostu zmieniłem nazwę Makefile na Makefile-renamed i tego projektu nie uda mi się odpalić. W końcu wszystkie projekty zbudowane i wchodzę do katalogu &lt;span style="font-weight:bold;"&gt;/home/daniel/NVIDIA_CUDA_SDK/bin/linux/release/&lt;/span&gt;. Tutaj najpierw uruchamiam &lt;span style="font-weight:bold;"&gt;./deviceQuery&lt;/span&gt; z następującym rezultatem:&lt;br /&gt;&lt;blockquote&gt;CUDA Device Query (Runtime API) version (CUDART static linking)&lt;br /&gt;There is 1 device supporting CUDA&lt;br /&gt;&lt;br /&gt;Device 0: "GeForce 8400M GS"&lt;br /&gt;  CUDA Capability Major revision number:         1&lt;br /&gt;  CUDA Capability Minor revision number:         1&lt;br /&gt;  Total amount of global memory:                 267714560 bytes&lt;br /&gt;  Number of multiprocessors:                     16&lt;br /&gt;  Number of cores:                               128&lt;br /&gt;  Total amount of constant memory:               65536 bytes&lt;br /&gt;  Total amount of shared memory per block:       16384 bytes&lt;br /&gt;  Total number of registers available per block: 8192&lt;br /&gt;  Warp size:                                     32&lt;br /&gt;  Maximum number of threads per block:           512&lt;br /&gt;  Maximum sizes of each dimension of a block:    512 x 512 x 64&lt;br /&gt;  Maximum sizes of each dimension of a grid:     65535 x 65535 x 1&lt;br /&gt;  Maximum memory pitch:                          262144 bytes&lt;br /&gt;  Texture alignment:                             256 bytes&lt;br /&gt;  Clock rate:                                    0.80 GHz&lt;br /&gt;  Concurrent copy and execution:                 Yes&lt;br /&gt;  Run time limit on kernels:                     No&lt;br /&gt;  Integrated:                                    Yes&lt;br /&gt;  Support host page-locked memory mapping:       Yes&lt;br /&gt;  Compute mode:                                  Default (multiple host threads can use this device simultaneously)&lt;br /&gt;&lt;br /&gt;Test PASSED&lt;br /&gt;&lt;br /&gt;Press ENTER to exit...&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Co oznacza, że mam urządzenie "CUDA Capable". Następny test na porozumiewanie się urządzenia z systemem: &lt;span style="font-weight:bold;"&gt;./bandwidthTest&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;Running on......&lt;br /&gt;      device 0:GeForce 8400M GS&lt;br /&gt;Quick Mode&lt;br /&gt;Host to Device Bandwidth for Pageable memory&lt;br /&gt;.&lt;br /&gt;Transfer Size (Bytes) Bandwidth(MB/s)&lt;br /&gt; 33554432  856.9&lt;br /&gt;&lt;br /&gt;Quick Mode&lt;br /&gt;Device to Host Bandwidth for Pageable memory&lt;br /&gt;.&lt;br /&gt;Transfer Size (Bytes) Bandwidth(MB/s)&lt;br /&gt; 33554432  895.4&lt;br /&gt;&lt;br /&gt;Quick Mode&lt;br /&gt;Device to Device Bandwidth&lt;br /&gt;.&lt;br /&gt;Transfer Size (Bytes) Bandwidth(MB/s)&lt;br /&gt; 33554432  4214.5&lt;br /&gt;&lt;br /&gt;&amp;&amp;&amp;&amp; Test PASSED&lt;br /&gt;&lt;br /&gt;Press ENTER to exit...&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Zatem teoretycznie wszystko dobrze, ale nie mogę uruchomić żadnego przykładu. Najczęstszym błędem jest "&lt;span style="font-style:italic;"&gt;cudaSafeCall() Runtime API error in file &lt;bicubicTexture.cu&gt;, line 51 : feature is not yet implemented.&lt;/span&gt;" Wynika z tego, że CUDA 2.2 nie da rady działać na obecnych sterownikach i będę musiał walczyć z tymi ściągniętymi ze strony NVIDIA.&lt;br /&gt;&lt;br /&gt;EDIT:&lt;br /&gt;Z ostatniej chwili: udało mi się zainstalować sterowniki na XP. Pomogło wybranie sterowników dla notebooków. Pozwala to wykorzystywać CUDA w wersji 2.2.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-3522545547981495467?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/3522545547981495467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/3522545547981495467'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2009/10/cuda-nvidia.html' title='CUDA NVidia'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-3682285240339338597</id><published>2009-09-18T10:27:00.004+02:00</published><updated>2009-09-18T12:35:05.244+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fstab'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Fstab i montowanie podkatalogów</title><content type='html'>Postanowiłem dzisiaj, że dysk z XPkiem będzie się montował przy każdym starcie systemu. Docelowo chcę ujednolicić katalogi ściągania, obrazów, kodu itd., tak abym nie musiał przeszukiwać raz dysku z XP, raz dysku z Ubuntu w poszukiwaniu tego czym się akurat zajmuję. Na przykład mogę pracować nad sprawozdaniem w OO.org w Windowsie i w Ubuntu, ale nie mam dostępu do partycji ext3 z Windowsa. Dlatego podlinkuję sobie Moje Dokumenty do /home/daniel, a w tym celu potrzebuję odpowiednich wpisów w fstab.&lt;br /&gt;&lt;br /&gt;Było z tym trochę problemu, ale nic czego nie załatwiłoby użycie wyszukiwarki.&lt;br /&gt;Po kolei:&lt;br /&gt;Można wpisać "&lt;span style="font-weight:bold;"&gt;sudo fdisk -l&lt;/span&gt;" aby dostać listę wszystkich dysków. Jako że mój dysk jest wewnętrzny i nie ma szansy, aby zmieniła się jego nazwa, to mógłbym odwołać się właśnie po niej: &lt;span style="font-weight:bold;"&gt;/dev/sda1/&lt;/span&gt;. Jednak inne dyski w fstab odwołują się do UUID dysku, więc ja też tak zrobię. Taka mała dygresja: mam dwa dyski zewnętrzne i pendrive'a. Mogę kazać im montować się nie w katalogu /media/disk i /media/disk1, ale na przykład w katalogu /media/czarny i /media/srebrny w zależności od tego który z nich jest podłączony.&lt;br /&gt;Aby uzyskać UUID dysku należy wpisać:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;sudo vol_id /dev/sda1&lt;/span&gt;&lt;br /&gt;W moim przypadku dostałem:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ID_FS_UUID=5E543A8F543A69C3&lt;/span&gt;&lt;br /&gt;Teraz trzeba otworzyć fstab:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;gksu gedit /etc/fstab&lt;/span&gt;&lt;br /&gt;i na końcu dodać:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;#dysk z XP&lt;br /&gt;UUID=5E543A8F543A69C3 /media/XP ntfs-3g defaults 0 0&lt;br /&gt;&lt;/span&gt;Ja oddzielam kolumny tabem, ale można też spacją. Po kolei są to: identyfikator dysku, punkt montowania, system plików, opcje i kolejne jakieś 2 parametry, które przeważnie są zerami. Coś związanego z częstotliwością jakiejś czynności, ale nie wiem jakiej bo nie zagłębiałem się w temat. ;) Alternatywnym wpisem może być:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;/dev/sda1 /media/XP ntfs-3g defaults 0 0&lt;/span&gt;&lt;br /&gt;Tutaj odwołuję się do dysku po jego nazwie. Więcej informacji po czym jeszcze można się odwoływać znajduje się w internecie.&lt;br /&gt;Na koniec zapisujemy zmiany i wracamy do konsoli. Teraz trzeba dać znać systemowi, żeby przemontował wszystkie dyski zgodnie z nowym plikiem fstab:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;sudo mount -a&lt;/span&gt;&lt;br /&gt;No i błąd:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;mount: mount point /media/XP does not exist&lt;/span&gt;&lt;br /&gt;Zatem trzeba naprawić to niedopatrzenie:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;sudo mkdir /media/XP&lt;/span&gt;&lt;br /&gt;Tym razem &lt;span style="font-weight:bold;"&gt;sudo mount -a&lt;/span&gt; nie wyrzuca żadnych komunikatów i można cieszyć się zamontowanym dyskiem.&lt;br /&gt;&lt;br /&gt;Teraz przykładowe dowiązanie katalogu z obrazami:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;/media/XP/Documents\040and\040Settings/Yelonek/Moje\040dokumenty/Moje\040obrazy /home/daniel/Obrazy none bind 0 0&lt;br /&gt;&lt;/span&gt;Co to za \040? Otóż jeśli w nazwie występuje spacja, to zamiast niej dajemy odpowiadający jej "escape sequence". Jest to wartość 32(kod ANSI dla spacji) w systemie ósemkowym. Gdyby wstawić tam zwykłą spację, to po wywołaniu sudo mount -a dostaniemy komunikat, że "fstab is bad", bo program uzna spację za przejście do następnej kolumny.&lt;br /&gt;&lt;br /&gt;Ponowne wywołanie &lt;span style="font-weight:bold;"&gt;sudo mount -a&lt;/span&gt; spowoduje, że w katalogu ~/Obrazy zobaczymy plik z Moje obrazy z dysku XP. Ale moment! Przecież w Obrazy miałem kilka innych plików na dysku Ubuntu, a teraz ich nie widać. No tak, nie widać ich, bo teraz Obrazy są dowiązane do Moje obrazy. Nie wszystko jednak stracone. Co zatem zrobić? Można skasować linijkę odpowiadającą za to dowiązanie i zresetować komputer... Ale to bardzo niewygodne. :] Dlatego należy wpisać:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;sudo umount ~/Obrazy&lt;/span&gt;&lt;br /&gt;i znowu widzimy stare pliki. Można je przenieść do katalogu Moje obrazy i ponownie dowiązać katalogi. Teraz już wszystko jest tak jak być powinno.&lt;br /&gt;&lt;br /&gt;* PS ~ (tylda) oznacza katalog domowy użytkownika, czyli w moim przypadku /home/daniel&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-3682285240339338597?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/3682285240339338597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/3682285240339338597'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2009/09/fstab-i-montowanie-podkatalogow.html' title='Fstab i montowanie podkatalogów'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-3184788782398303813</id><published>2009-09-16T19:06:00.021+02:00</published><updated>2009-09-18T12:33:38.042+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='sqlite'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Sqlite - wprawka</title><content type='html'>Zainteresowałem się ostatnio kolejnym tematem, a mianowicie SQL. Do tej pory słyszałem, że to potężne narzędzie do zarządzania bazami danych, ale jakoś nigdy nie wziąłem się za siebie i nie przysiadłem do tego. Ostatnio mam trochę wolnego czasu, więc zajrzałem na stronę: &lt;a href="http://www.w3schools.com/sql/default.asp"&gt;www.w3schools.com&lt;/a&gt; gdzie znajduje się wiele materiałów o SQL i to w bardzo przystępnej formie. Po przejściu podstaw miałem okazję wystosować parę zapytań do treningowej bazy danych. Okazało się to łatwiejsze niż przypuszczałem.&lt;br /&gt;&lt;br /&gt;Jako bibliotekę obsługującą bazę danych wybrałem sobie Sqlite3. Jest dość nieskomplikowana i nie trzeba stawiać żadnych serwerów SQL czy coś takiego. Instaluje się ją poleceniem:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;sudo apt-get install libsqlite3-0 libsqlite3-dev&lt;/span&gt;&lt;br /&gt;Bardzo prawdopodobne, że libsqlite3-0 będzie już w systemie gdyż korzysta z niej na przykład Firefox.&lt;br /&gt;&lt;br /&gt;Teraz należy stworzyć nowy projekt, dodać do linkera &lt;span style="font-weight:bold;"&gt;/usr/lib/libsqlite3.so&lt;/span&gt; i napisać trochę kodu:&lt;br /&gt;&lt;pre name="code" class="C++"&gt;/* &lt;br /&gt; * File:   main.cpp&lt;br /&gt; * Author: daniel&lt;br /&gt; *&lt;br /&gt; * Created on 14 wrzesień 2009, 22:24&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#include &amp;lt;sqlite3.h&amp;gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;lt;string&amp;gt;&lt;br /&gt;#include &amp;lt;sstream&amp;gt;&lt;br /&gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;using std::cout;&lt;br /&gt;using std::endl;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt; * &lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;//pokazuje wiadomość błędu jeśli istnieje, a jeśli nie to wartość kodu&lt;br /&gt;void handleReturnCode(int returnCode, char* ErrorMsg = NULL) {&lt;br /&gt;    if (returnCode != SQLITE_OK) {&lt;br /&gt;        if (ErrorMsg != NULL) {&lt;br /&gt;            std::cout &lt;&lt; ErrorMsg &lt;&lt; std::endl;&lt;br /&gt;            sqlite3_free(ErrorMsg);&lt;br /&gt;        } else {&lt;br /&gt;            std::cout &lt;&lt; "Return code: " &lt;&lt; returnCode &lt;&lt; std::endl;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//struktura przechowująca dane o osobie&lt;br /&gt;struct sOsoba {&lt;br /&gt;    std::string imie;&lt;br /&gt;    std::string nazwisko;&lt;br /&gt;    int rokUrodzenia;&lt;br /&gt;&lt;br /&gt;    sOsoba(const char* p_imie, const char* p_nazwisko, const int p_rokUrodzenia) {&lt;br /&gt;        imie = p_imie;&lt;br /&gt;        nazwisko = p_nazwisko;&lt;br /&gt;        rokUrodzenia = p_rokUrodzenia;&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;int main(int argc, char** argv) {&lt;br /&gt;    sqlite3* db;&lt;br /&gt;    int returnCode;&lt;br /&gt;&lt;br /&gt;    cout &lt;&lt; "Otwieranie bazy danych: " &lt;&lt; endl;&lt;br /&gt;    returnCode = sqlite3_open("test2.db", &amp;db);&lt;br /&gt;    if (returnCode != 0) std::cout &lt;&lt; returnCode &lt;&lt; std::endl;&lt;br /&gt;    char* ErrorMsg;&lt;br /&gt;&lt;br /&gt;    cout &lt;&lt; "Usunięcie tabeli tab" &lt;&lt; endl;&lt;br /&gt;    returnCode = sqlite3_exec(db, "drop table if exists tab", NULL, NULL, &amp;ErrorMsg);&lt;br /&gt;    handleReturnCode(returnCode, ErrorMsg);&lt;br /&gt;&lt;br /&gt;    cout &lt;&lt; "Utworzenie tabeli tab" &lt;&lt; endl;&lt;br /&gt;    returnCode = sqlite3_exec(db,&lt;br /&gt;                                 "create table tab (imie string, nazwisko string,&lt;br /&gt;                                 rokUrodzenia integer);",&lt;br /&gt;                               NULL, NULL, &amp;ErrorMsg);&lt;br /&gt;    handleReturnCode(returnCode, ErrorMsg);&lt;br /&gt;&lt;br /&gt;    cout &lt;&lt; "Utworzenie listy osob" &lt;&lt; endl;&lt;br /&gt;    std::vector&amp;lt;sOsoba&amp;gt; listaOsob;&lt;br /&gt;    listaOsob.push_back(sOsoba("Donald", "Tusk", 1957));&lt;br /&gt;    listaOsob.push_back(sOsoba("Lech", "Kaczyński", 1949));&lt;br /&gt;    listaOsob.push_back(sOsoba("Jarosław", "Kaczyński", 1949));&lt;br /&gt;    listaOsob.push_back(sOsoba("Grzegorz", "Napieralski", 1974));&lt;br /&gt;    listaOsob.push_back(sOsoba("Waldemar", "Pawlak", 1959));&lt;br /&gt;    listaOsob.push_back(sOsoba("Grzegorz", "Schetyna", 1963));&lt;br /&gt;&lt;br /&gt;    //Dodawanie kolejnych nazwisk&lt;br /&gt;    std::vector&amp;lt;sOsoba&amp;gt;::iterator it = listaOsob.begin();&lt;br /&gt;    while (it != listaOsob.end()) {&lt;br /&gt;        cout &lt;&lt; "Dodawanie " &lt;&lt; it-&gt;imie&lt;&lt; " " &lt;&lt; it-&gt;nazwisko &lt;&lt; endl;&lt;br /&gt;        std::stringstream query;&lt;br /&gt;        query &lt;&lt; "insert into tab values (\"" &lt;br /&gt;        &lt;&lt; it-&gt;imie &lt;br /&gt;        &lt;&lt;"\", \""&lt;br /&gt;        &lt;&lt; it-&gt;nazwisko &lt;br /&gt;        &lt;&lt; "\", " &lt;br /&gt;        &lt;&lt; it-&gt;rokUrodzenia &lt;&lt;");";&lt;br /&gt;        returnCode = sqlite3_exec(db, query.str().c_str(), NULL, NULL, &amp;ErrorMsg);&lt;br /&gt;        handleReturnCode(returnCode, ErrorMsg);&lt;br /&gt;        it++;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    char** result;&lt;br /&gt;    int nRows, nCols;&lt;br /&gt;    //zapytanie o polityków którzy urodzili się po 1960&lt;br /&gt;    sqlite3_get_table(db, &lt;br /&gt;                         "select nazwisko, rokUrodzenia&lt;br /&gt;                          from tab&lt;br /&gt;                          where rokUrodzenia &gt; 1960 &lt;br /&gt;                          order by rokUrodzenia asc",&lt;br /&gt;                        &amp;result, &amp;nRows, &amp;nCols, &amp;ErrorMsg);&lt;br /&gt;    cout &lt;&lt; "Result: [" &lt;&lt; nRows &lt;&lt; ", " &lt;&lt; nCols &lt;&lt; "]" &lt;&lt; endl;&lt;br /&gt;    //zerowy wiersz to nagłówki tabeli, a reszta to wyniki, więc rzędów jest nRows + 1&lt;br /&gt;    for (int i = 0; i &lt;= nRows; i++) { &lt;br /&gt;        for (int j = 0; j &lt; nCols; j++) {&lt;br /&gt;            cout &lt;&lt; result[i * nCols + j] &lt;&lt; "\t";&lt;br /&gt;            if (j &gt; 0 &amp;&amp; i&gt;0) {&lt;br /&gt;                //dla sprawdzenia czy da się łatwo skonwertować liczbę&lt;br /&gt;                int rok = atoi(result[i * nCols + j]);&lt;br /&gt;                cout &lt;&lt; "\t skonwertowany rok: " &lt;&lt; rok;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        cout &lt;&lt; endl;&lt;br /&gt;    }&lt;br /&gt;    //zwalnianie pamięci przydzielonej dla tabeli&lt;br /&gt;    sqlite3_free_table(result);&lt;br /&gt;&lt;br /&gt;    cout &lt;&lt; "Zamykanie bazy danych" &lt;&lt; endl;&lt;br /&gt;    sqlite3_close(db);&lt;br /&gt;    //wywołanie polecenia systemowego eksportującego tabelę tab do pliku csv&lt;br /&gt;    system("sqlite3 -csv test2.db \"select * from tab;\" &gt; wyjscie.csv");&lt;br /&gt;    cout &lt;&lt; endl;&lt;br /&gt;    //wyświetlenie zawartości pliku csv w konsoli&lt;br /&gt;    system("cat wyjscie.csv");&lt;br /&gt;&lt;br /&gt;    return (EXIT_SUCCESS);&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-3184788782398303813?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/3184788782398303813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/3184788782398303813'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2009/09/sqlite-wprawka.html' title='Sqlite - wprawka'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-838134870051499358</id><published>2009-07-23T00:17:00.027+02:00</published><updated>2009-07-23T01:35:47.602+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='netbeans'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><category scheme='http://www.blogger.com/atom/ns#' term='opencv'/><title type='text'>OpenCV</title><content type='html'>OpenCV to prawdopodobnie najbardziej znana biblioteka związana z komputerową "wizją". Chodź od dłuższego czasu nic w niej się nie dzieje, to wydaje się nie tracić na popularności. Miałem okazję zapoznać się z nią na laboratorium przedmiotu Sensoryka i Systemy Wizyjne. Na zajęciach wykorzystywaliśmy Visual C++, a teraz chciałbym móc pracować z tą biblioteką w NetBeans na Ubuntu 8.04. Okazało się, że chęć tę bardzo łatwo przekuć w czyn. Oto co należy zrobić:&lt;br /&gt;Nie zamierzam instalować ostatniej wersji z CVS czy SVN. Chcę wykorzystać to co jest w repozytorium Ubuntu. Mamy tam dostępną wersję 1.0.0. Aby dowiedzieć się jakie są nazwy paczek należy wpisać:&lt;blockquote&gt;apt-cache search opencv&lt;/blockquote&gt;. W odpowiedzi dostaniemy:&lt;blockquote&gt;libcv-dev - development files for libcv&lt;br /&gt;libcv1 - computer vision library&lt;br /&gt;libcvaux-dev - development files for libcvaux&lt;br /&gt;libcvaux1 - computer vision extension library&lt;br /&gt;libhighgui-dev - development files for libhighgui&lt;br /&gt;libhighgui1 - computer vision GUI library&lt;br /&gt;opencv-doc - OpenCV documentation and examples&lt;br /&gt;python-opencv - Python bindings for the computer vision library&lt;/blockquote&gt;&lt;br /&gt;Nie potrzebujemy dokumentacji, która jest dostępna &lt;a href="http://www.cs.indiana.edu/cgi-pub/oleykin/website/OpenCVHelp/"&gt;tutaj (dla wersji 1.0)&lt;/a&gt; lub &lt;a href="http://opencv.willowgarage.com/documentation/index.html"&gt;tutaj (dla wersji 1.1)&lt;/a&gt;. W repozytorium znajduje się wersja 1.0. Wydaje mi się, że nie różni się ona zbytnio od 1.1, ale nie przeglądałem changeloga, więc nie wiem na pewno. W każdym razie dokumentacja jest w internecie, a Pythona nie zamierzam używać.&lt;br /&gt;Zatem instalujemy paczki:&lt;blockquote&gt;sudo apt-get install libcv1 libcv-dev libcvaux1 libcvaux-dev libhighgui1 libhighgui-dev&lt;/blockquote&gt;W odpowiedzi dostaniemy:&lt;blockquote&gt;&lt;span style="font-weight:bold;"&gt;Czytanie list pakietów... Gotowe&lt;br /&gt;Budowanie drzewa zależności       &lt;br /&gt;Odczyt informacji o stanie... Gotowe&lt;br /&gt;Zostaną zainstalowane następujące dodatkowe pakiety:&lt;/span&gt;&lt;br /&gt;  libatk1.0-dev libavcodec-dev libavformat-dev libavutil-dev libcairo2-dev libdc1394-13-dev libexpat1-dev libfontconfig1-dev libfreetype6-dev libglib2.0-dev libgsm1-dev libgtk2.0-dev libice-dev libjpeg62-dev libogg-dev libpango1.0-dev libpixman-1-dev libpng12-dev libpthread-stubs0 libpthread-stubs0-dev libraw1394-dev libsm-dev libtheora-dev libtiff4-dev libtiffxx0c2 libvorbis-dev libx11-dev libxau-dev libxcb-xlib0-dev libxcb1-dev libxcomposite-dev libxcursor-dev libxdamage-dev libxdmcp-dev libxext-dev libxfixes-dev libxft-dev libxi-dev libxinerama-dev libxrandr-dev libxrender-dev x11proto-composite-dev x11proto-core-dev x11proto-damage-dev x11proto-fixes-dev x11proto-input-dev x11proto-kb-dev x11proto-randr-dev x11proto-render-dev x11proto-xext-dev x11proto-xinerama-dev xtrans-dev zlib1g-dev&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Sugerowane pakiety:&lt;/span&gt;&lt;br /&gt;  libcairo2-doc libglib2.0-doc libgtk2.0-doc imagemagick libpango1.0-doc&lt;br /&gt;  libraw1394-doc&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Zostaną zainstalowane następujące NOWE pakiety:&lt;/span&gt;&lt;br /&gt;  libatk1.0-dev libavcodec-dev libavformat-dev libavutil-dev libcairo2-dev libcv-dev libcv1 libcvaux-dev libcvaux1 libdc1394-13-dev libexpat1-dev libfontconfig1-dev libfreetype6-dev libglib2.0-dev libgsm1-dev libgtk2.0-dev libhighgui-dev libhighgui1 libice-dev libjpeg62-dev libogg-dev libpango1.0-dev libpixman-1-dev libpng12-dev libpthread-stubs0 libpthread-stubs0-dev libraw1394-dev libsm-dev libtheora-dev libtiff4-dev libtiffxx0c2 libvorbis-dev libx11-dev libxau-dev libxcb-xlib0-dev libxcb1-dev libxcomposite-dev libxcursor-dev libxdamage-dev libxdmcp-dev libxext-dev libxfixes-dev libxft-dev libxi-dev libxinerama-dev libxrandr-dev libxrender-dev x11proto-composite-dev x11proto-core-dev x11proto-damage-dev x11proto-fixes-dev x11proto-input-dev x11proto-kb-dev x11proto-randr-dev x11proto-render-dev x11proto-xext-dev x11proto-xinerama-dev xtrans-dev zlib1g-dev&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;0 aktualizowanych, 59 nowo instalowanych, 0 usuwanych i 0 nieaktualizowanych.&lt;br /&gt;Konieczne pobranie 0B/17,3MB archiwów.&lt;br /&gt;Po tej operacji zostanie dodatkowo użyte 62,9MB miejsca na dysku.&lt;br /&gt;Czy chcesz kontynuować [T/n]? &lt;/span&gt;&lt;/blockquote&gt;Odpowiadamy, że oczywiście tak. Jak widać instaluje się mnóstwo innych paczek - z tego co widać jedne służą do obsługi różnych formatów obrazów i filmów, a inne do obsługi interface'u (np libgtk2.0-dev). Gdy ta czynność się zakończy pliki nagłówkowe będą zainstalowane w /usr/include/opencv, a biblioteki w /usr/lib.&lt;br /&gt;Zaczynamy teraz pracę z NetBeans:&lt;br /&gt;Tworzymy nowy projekt typu "C/C++ Application". Nadajemy mu nazwę "openCV Hello World".&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lh3.ggpht.com/_SdUjEZ9rpzA/SmeWVcHGjUI/AAAAAAAADHI/woiaNn2G-hU/s576/zrzutekranu-New%20C-C%2B%2B%20Application.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 576px; height: 371px;" src="http://lh3.ggpht.com/_SdUjEZ9rpzA/SmeWVcHGjUI/AAAAAAAADHI/woiaNn2G-hU/s576/zrzutekranu-New%20C-C%2B%2B%20Application.png" border="0" alt="" /&gt;&lt;/a&gt;Mamy czysty projekt z pojedynczym plikiem main.cpp. Teraz trzeba powiedzieć kompilatorowi, gdzie znajdują się biblioteki, które ma dołączyć do projektu. Należy kliknąć prawym przyciskiem w oknie "Projects" na obecnym projekcie i przejść do jego właściwości (Properties). Po wybraniu "Linker" dodać ścieżkę do bibliotek (Additional Library Directories): /usr/lib oraz biblioteki (Libraries): cv, cvaux, highgui.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_SdUjEZ9rpzA/SmeZw9xa29I/AAAAAAAADHQ/_Ow3iaRQ6uc/s1600-h/zrzutekranu-Project+Properties+-+openCv+Hello+World.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 270px;" src="http://3.bp.blogspot.com/_SdUjEZ9rpzA/SmeZw9xa29I/AAAAAAAADHQ/_Ow3iaRQ6uc/s400/zrzutekranu-Project+Properties+-+openCv+Hello+World.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361422947902479314" /&gt;&lt;/a&gt;&lt;br /&gt;Teraz możemy napisać trochę kodu. Oto propozycja:&lt;pre name="code" class="c++"&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#include "opencv/cv.h"&lt;br /&gt;#include "opencv/cvaux.h"&lt;br /&gt;#include "opencv/highgui.h"&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt; * &lt;br /&gt; */&lt;br /&gt;int main(int argc, char** argv) {&lt;br /&gt;    //tworzenie zmiennej przechowującej obraz i załadowanie obrazu z pliku, 0 = czarno-biały&lt;br /&gt;    IplImage* obraz = cvLoadImage("/home/daniel/Obrazy/hello.jpg", 0);&lt;br /&gt;    //utworzenie okna nazwanego Hello World&lt;br /&gt;    cvNamedWindow("Hello world");&lt;br /&gt;    //wyświetlenie obrazu&lt;br /&gt;    cvShowImage("Hello world", obraz);&lt;br /&gt;    //oczekiwanie na wciśnięcie klawisza, domyślnie 0 = nieskonczonosc&lt;br /&gt;    cvWaitKey();&lt;br /&gt;    //zamknięcie okna, można użyć cvDestroyAllWindows()&lt;br /&gt;    cvDestroyWindow("Hello world");&lt;br /&gt;    //zwalniamy pamięć zajętą przez zmienną obraz&lt;br /&gt;    cvReleaseImage(&amp;obraz);&lt;br /&gt;    return (EXIT_SUCCESS);&lt;br /&gt;}&lt;/pre&gt;Efekt po wciśnięciu F6:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_SdUjEZ9rpzA/SmefrfDKQkI/AAAAAAAADHY/RqRDARanc04/s1600-h/efekt+hello+world.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 250px;" src="http://1.bp.blogspot.com/_SdUjEZ9rpzA/SmefrfDKQkI/AAAAAAAADHY/RqRDARanc04/s400/efekt+hello+world.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361429450825810498" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-838134870051499358?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/838134870051499358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/838134870051499358'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2009/07/opencv.html' title='OpenCV'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_SdUjEZ9rpzA/SmeWVcHGjUI/AAAAAAAADHI/woiaNn2G-hU/s72-c/zrzutekranu-New%20C-C%2B%2B%20Application.png' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-5002181538887926171</id><published>2009-07-19T23:23:00.007+02:00</published><updated>2011-09-30T14:00:15.082+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='texmaker'/><category scheme='http://www.blogger.com/atom/ns#' term='LaTeX'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>LaTeX</title><content type='html'>Przeglądałem dziś sobie jakie programy są dostępne przez "Dodaj/Usuń programy" w Ubuntu i w oczy rzucił mi się Texmaker. Zainstalowałem go i próbowałem stworzyć prosty dokument. Skonfigurowałem sobie opcję "Quick build", aby po naciśnięciu F1 otrzymać gotowy plik PDF. Niestety dostawałem błędy w stylu "błąd podczas wykonywania polecenia", "nie istnieje plik dziennika (log file)". Swego czasu próbowałem już skompilować dokument na Windowsie i poległem. Za to w trakcie prób rozwiązania problemu natrafiałem na instrukcję dla Linuksów. Było tam wspomniane o poleceniach typu &lt;span style="font-style:italic;"&gt;pdflatex&lt;/span&gt;. Sprawdziłem w terminalu czy mam coś takiego zainstalowanego. Okazało się, że nie, więc trzeba je doinstalować. Tylko jak się nazywa ta paczka. Poszukiwania (&lt;span style="font-style:italic;"&gt;apt-cache search latex | less&lt;/span&gt;) doprowadziły do tego, że w oczy rzuciła mi się duża ilość paczek z "texlive" na początku. Tylko jak będzie się nazywać główny pakiet? Pewnie texlive. Polecenie &lt;span style="font-style:italic;"&gt;apt-cache show texlive&lt;/span&gt; upewniło mnie, że zgadłem:&lt;blockquote&gt;This metapackage provides a decent selection of the TeX Live packages which should suffice for the most common tasks.&lt;/blockquote&gt;Zainstalowałem zatem paczkę texlive wraz z texlive-lang-pl, gdyż uznałem, że ta druga może się przydać. Po tym wszystkim odinstalowałem i zainstalowałem ponownie Texmakera.&lt;br /&gt;Teraz ponownie skonfigurowałem Quick Build, żeby tworzyło pdfa. Następnie przy wykorzystaniu "Quick Wizard" stworzyłem następujący dokument:&lt;blockquote&gt;\documentclass[10pt,a4paper]{article}&lt;br /&gt;\usepackage[latin2]{inputenc}&lt;br /&gt;\author{Imię Nazwisko}&lt;br /&gt;\title{O pisaniu w LaTeXu}&lt;br /&gt;\begin{document}&lt;br /&gt;Treść dokumentu&lt;br /&gt;\end{document}&lt;/blockquote&gt;Zapisałem do pliku /home/daniel/Dokumenty/LaTeX/pierwszy. To był mój pierwszy błąd- pliki należy zapisywać koniecznie z rozszerzeniem .tex. Udało mi się skompilować tekst do pdfa, ale zamiast ź otrzymałem jakieś L z zawijasami. Zacząłem kombinować z różnymi paczkami:&lt;blockquote&gt;\usepackage[polish]{babel}&lt;br /&gt;\usepackage[]{polski}&lt;br /&gt;\usepackage[OT4]{polski}&lt;br /&gt;\usepackage[T1]{polski}&lt;br /&gt;\usepackege[MeX]{polski}&lt;/blockquote&gt;Za każdym razem dostawałem inny efekt. A to zamiast ź było ij, a to w ogóle ź zostało pominięte. Przez pewien czas pomyślałem, że może brakuje mi czcionek, ale wersja zapisu ź z akcentem działała (wpisanie \'z również powoduje wyświetlenie ź).&lt;br /&gt;Wtedy trafiłem na stronę &lt;a href="http://morony.pl/?p=146"&gt;morony.pl&lt;/a&gt;, gdzie opisywano instalację paczek dla Windows. Wykorzystałem przykładowy plik LaTeXa:&lt;blockquote&gt;\documentclass[11pt,a4paper]{article}&lt;br /&gt;\usepackage{polski}&lt;br /&gt;\usepackage[cp1250]{inputenc}&lt;br /&gt;\title{\LaTeX}&lt;br /&gt;\author{Marcin Polkowski}&lt;br /&gt;\begin{document}&lt;br /&gt;\maketitle&lt;br /&gt;\section{Matematyka}&lt;br /&gt;$$f(x)=\left\{&lt;br /&gt;\begin{array}{ccc}&lt;br /&gt;\sin{x}&amp;\mbox{dla}&amp;x&lt;0\\0&amp;\mbox{dla}&amp;x=0\\\cos{x}&amp;\mbox{dla}&amp;x&gt;0&lt;br /&gt;\end{array}&lt;br /&gt;\right.$$&lt;br /&gt;\section{Polskie krzaczki}&lt;br /&gt;Późną nocą grań olśniła księżyca jasność.&lt;br /&gt;Pchnąć w tę łódź jeża lub ośm skrzyń fig.&lt;br /&gt;Różowy słoń ma usiąść na tępych gwoździach&lt;br /&gt;\end{document}&lt;/blockquote&gt;Jako, że używam Ubuntu zmieniłem windowsowe kodowanie cp1250 na latin2. Nikt nie potrafi wyobrazić sobie mojego zdziwienia, gdy powyższy tekst skompilował się do pięknego pdfa. Na razie służy mi jako szablon do tworzenia kolejnych dokumentów. Może jak kiedyś zrozumiem na czym polega ustawianie opcji poszczególnych paczek to będę pisał preambułę sam. Na razie jest to dla mnie czarna magia i to rozwiązanie jest wystarczająco dobre.&lt;br /&gt;&lt;br /&gt;Taka drobnostka, co do której nie jestem pewien czy ma znaczenie: w Options-&gt;Configure Texmaker-&gt;Editor ustawiłem kodowanie edytora na ISO-8859-2&lt;br /&gt;&lt;br /&gt;Pomocą służyły mi dwa główne opracowania:&lt;br /&gt;&lt;a href="http://www.lmgtfy.com/?q=nie+za+kr%C3%B3tkie+wprowadzenie+do+systemu+latex"&gt;Nie za krótkie wprowadzenie do systemu LaTeX&lt;/a&gt; oraz &lt;a href="http://www.lmgtfy.com/?q=jak+szybko+zacz%C4%85%C4%87+pisa%C4%87+w+latex"&gt;Jak szybko zacząć pisać w LaTeX&lt;/a&gt; Pomocna również była strona Grupy Użytkowników Systemu Tex (w skrócie GUST).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-5002181538887926171?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/5002181538887926171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/5002181538887926171'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2009/07/latex.html' title='LaTeX'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-910684678189191351</id><published>2009-07-13T11:27:00.008+02:00</published><updated>2009-07-19T23:54:29.559+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='netbeans'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>NetBeans i C/C++</title><content type='html'>Jako że będę niedługo potrzebował umiejętności pisania programów w C z Linuksem jako docelową platformą postanowiłem zrobić coś w tym kierunku. Korzystać będę z Ubuntu 8.04 LTS.&lt;br /&gt;Rozpocząłem od przejrzenia książki &lt;span style="font-style:italic;"&gt;Beginning Linux Programming&lt;/span&gt; z której to dowiedziałem się jak kompilować programy z pomocą linii komend. Zdaję sobie sprawę, że niektórzy to lubią i ma to "oldskulowy" urok, ale jednak cenię sobie wyżej wygodę niż bajery.&lt;br /&gt;Swego czasu dużo dobrego słyszałem o NetBeans i postanowiłem je wypróbować. Jest to środowisko programistyczne, które można wykorzystać do programowania w wielu językach (pierwotnie była to chyba Java). Mnie interesowała wersja dla C/C++, toteż ściągnąłem odpowiedni instalator ze strony &lt;a href="http://www.netbeans.org/downloads/index.html"&gt;http://www.netbeans.org/downloads/index.html&lt;/a&gt;. Na stronie dostępne są też tutoriale dotyczące obsługi tego środowiska.&lt;br /&gt;Instalację przeprowadzałem już jakiś czas temu, więc nie pamiętam wszystkich szczegółów, ale wydaje mi się, że brakowało tam kompilatora C++ - wystarczy doinstalować g++ na przykład za pomocą Synaptica i w Narzędzia=&gt;Opcje=&gt;C/C++=&gt;Build Tools w okienku &lt;span style="font-style:italic;"&gt;C++ Compiler:&lt;/span&gt; wpisać &lt;span style="font-style:italic;"&gt;/usr/bin/g++&lt;/span&gt;. Od teraz można już działać bez przeszkód.&lt;br /&gt;Moje dotychczasowe doświadczenia z programowaniem w C++ to głównie 2 programy: MS Visual Studio i C++ Builder z Borlanda. Ten drugi to już zabytek, więc nie ma co porównywać. Jak na tak stary program jest bardzo wygodny, ale znalezienie jakiejś instalki w internecie, a do niej jeszcze klucza rejestracyjnego to już nie jest zabawne. Acha, żeby działał debugger należy się zarejestrować. Swojego czasu ominąłem rejestrację i zachodziłem w głowę dlaczego debugger, który kiedyś działał bez problemu, teraz w ogóle nie chce tego robić. Wracając jednak do sedna - porównanie będzie odbywać się między VS, a NetBeans.&lt;br /&gt;Jest kilka funkcji, które w IDE są przeze mnie wymagane. Działający debugger to podstawa - byłem bardzo mile zaskoczony, gdy zobaczyłem w NetBeans, że mogę bez problemu włączyć uruchomienie programu linia po linii wraz z poglądem zmiennych, dodawanie watchów itp. Bardzo miłe zaskoczenie.&lt;br /&gt;Pisząc program bardzo pomocne są podpowiedzi nazw zmiennych i funkcji. Zarówno w VS, jak i NB mamy je dostępne pod ctrl+spacja, ale w tym drugim mamy to bardziej rozbudowane - podpowiadane są też nazwy plików nagłówkowych, dyrektywy preprocesora, rozwinięcia kodu (napisz "for", naciśnij ctrl+spacja, a dostaniesz podpowiedź "fori", które po wybraniu rozwija się w pętlę for ze zmienną &lt;span style="font-style:italic;"&gt;i&lt;/span&gt;. To jeszcze nie koniec - zmienna &lt;span style="font-style:italic;"&gt;i&lt;/span&gt; jest w polu, które uaktywnia się po rozwinięciu. Możemy wpisać dowolną nazwę zmiennej, a zastąpi ona &lt;span style="font-style:italic;"&gt;i&lt;/span&gt; we wszystkich miejscach w pętli. Coś takiego dostępne w VS jest chyba tylko wtedy gdy piszemy w C# (albo może wszystko pisane przy użyciu CLR ma taką właściwość). Nie udało mi się za to znaleźć jak włączyć podpowiedź listy parametrów w funkcji, czyli odpowiednik Visualowego ctrl+shift+spacja, ale to pewnie jeszcze gdzieś to się przede mną ukrywa.&lt;br /&gt;Co jeszcze mi się podoba w NB, a nie widziałem w VS to ilustracja czasu wykonywania programu i zużycia pamięci. Wciskamy F6, aby uruchomić nasz projekt i widzimy jak rośnie czy spada rozmiar naszego programu. Inny przykład to kombinacja alt+shift+f, która ładnie formatuje kod - wstawia spację między operatorami, wyrównuje wszystko, generalnie sprawia, że kod staje się czytelny.&lt;br /&gt;Dodatkowo mamy integrację z CVS, SVN, Kenai i nie wiem nawet czym jeszcze. Trochę czasu minie zanim odkryję wszystkie funkcje. Wrażenia z użytkowania są niezmiernie zadowalające - obecnie staram się rozwiązać jak najwięcej zadań z &lt;a href="http://projecteuler.net/"&gt;Projektu Euler&lt;/a&gt; o którym napiszę więcej wkrótce.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-910684678189191351?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/910684678189191351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/910684678189191351'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2009/07/netbeans-i-cc.html' title='NetBeans i C/C++'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-3653198242485009034</id><published>2008-06-19T21:59:00.009+02:00</published><updated>2008-06-20T08:42:03.091+02:00</updated><title type='text'>Taki myk, żeby były polskie litery w Totemie</title><content type='html'>Wiele osób narzeka na brak polskich znaków przy odtwarzaniu filmów w Ubuntu 8.04. Jedni sugerują, żeby po prostu zmienić kodowanie w Totemie na CP 1250. Takie jest kodowanie większości plików z napisami.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_SdUjEZ9rpzA/SFtQotU1A6I/AAAAAAAABqI/JEPF_hLHEaE/s1600-h/synaptic.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_SdUjEZ9rpzA/SFtQotU1A6I/AAAAAAAABqI/JEPF_hLHEaE/s400/synaptic.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5213849653903426466" /&gt;&lt;/a&gt;&lt;br /&gt;Istnieje drugi sposób:&lt;br /&gt;Instalujemy pakiet "recode" w terminalu&lt;br /&gt;&lt;blockquote&gt;sudo apt-get install recode&lt;/blockquote&gt;&lt;br /&gt;lub przez Menedżer pakietów Synaptic.&lt;br /&gt;&lt;br /&gt;Nie będziemy oczywiście za każdym razem wywoływać polecenia recode z terminala, dlatego:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;System-&gt;Preferencje-&gt;Centrum Sterowania-&gt;Nautilus Actions Configuration&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Label ( nazwa ): &lt;span style="font-weight:bold;"&gt;Zmień na UTF8&lt;/span&gt;&lt;br /&gt;Tooltip ( tekst podpowiedzi ): &lt;span style="font-weight:bold;"&gt;Konwersja z CP1250 do UTF8&lt;/span&gt;&lt;br /&gt;Icon ( ikona ): według uznania, ja używam &lt;span style="font-weight:bold;"&gt;gtk-find-and-replace&lt;/span&gt;&lt;br /&gt;Action:&lt;br /&gt;Path (ścieżka): &lt;span style="font-weight:bold;"&gt;recode&lt;/span&gt;&lt;br /&gt;Parameters: &lt;span style="font-weight:bold;"&gt;CP1250..UTF-8 %M&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_SdUjEZ9rpzA/SFtQ0txFPCI/AAAAAAAABqQ/kH3JGY8A4Rg/s1600-h/nautilus.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_SdUjEZ9rpzA/SFtQ0txFPCI/AAAAAAAABqQ/kH3JGY8A4Rg/s400/nautilus.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5213849860180360226" /&gt;&lt;/a&gt;&lt;br /&gt;Conditions ( warunki ): Wybieramy czysty tekst: text/plain z rozszerzeniem *.txt dla pojedynczych plików.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_SdUjEZ9rpzA/SFtRBdtMyWI/AAAAAAAABqY/aVdT3fwFzDY/s1600-h/nautilus2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_SdUjEZ9rpzA/SFtRBdtMyWI/AAAAAAAABqY/aVdT3fwFzDY/s400/nautilus2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5213850079207410018" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Trzecia zakładka odpowiada za zakres dostępności polecenia. Ja zaznaczyłem tylko lokalne pliki.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_SdUjEZ9rpzA/SFtRJ1x61FI/AAAAAAAABqg/wa14v4fY0FA/s1600-h/nautilus3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_SdUjEZ9rpzA/SFtRJ1x61FI/AAAAAAAABqg/wa14v4fY0FA/s400/nautilus3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5213850223108609106" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Klikamy, że jest ok. Teraz możemy kliknąć prawym przyciskiem na jakiś plik z napisami i do wyboru mamy naszą nowostworzoną opcję.&lt;br /&gt;Oczywiście ten myk nie zadziała jeśli początkowe kodowanie pliku nie było CP 1250. Według tego wzoru można stworzyć dowolną nową opcję konwersji. W razie problemów &lt;span style="font-weight:bold;"&gt;man recode&lt;/span&gt; odpowie na Wasze pytania.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-3653198242485009034?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/3653198242485009034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/3653198242485009034'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2008/06/taki-myk-eby-byy-polskie-litery-w.html' title='Taki myk, żeby były polskie litery w Totemie'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_SdUjEZ9rpzA/SFtQotU1A6I/AAAAAAAABqI/JEPF_hLHEaE/s72-c/synaptic.png' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-172996211129286102.post-2742629152400383015</id><published>2008-03-14T01:11:00.003+01:00</published><updated>2008-03-14T18:41:13.249+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='politechnika'/><category scheme='http://www.blogger.com/atom/ns#' term='automatyka'/><category scheme='http://www.blogger.com/atom/ns#' term='laboratorium'/><title type='text'>Lab EiUA</title><content type='html'>&lt;br&gt;W tym tygodniu na laboratorium Elementów i Urządzeń Automatyki zaprogramowaliśmy 4 siłowniki pneumatyczne w taki sposób, że cyklicznie przepychają kulkę przez pewien przygotowany wcześniej tor. Oprócz tego, że kulka porusza się po wymyślonej przez nas trajektorii postawiliśmy sobie dodatkowo warunek cyklicznej pracy układu oraz urozmaicenia wizualnego całego procesu.&lt;br&gt; Program pisaliśmy w języku drabinkowym, który jest dla nas pewną nowością. Trochę trudno się połapać co z czym i do czego podłączyć. Ostatecznie wymyśliłem metodę opisywania układu siłowników 4 bitowym kodem. Przejście ze stanu do stanu wiąże się z odczekaniem pewnego czasu, co jest realizowane za pomocą timerów. &lt;br&gt;Brakowało nam przycisku startowego, a wpisywanie wartości do pamięci za pomocą środowiska programistycznego nie było zbyt eleganckie. Wodzu wymyślił więc sposób na zgrabną pętlę. Pierwszy timer załączamy negacją ostatniego. W ten sposób zawsze gdzieś jest 1, żeby wystartował timer. Karol za to wymyślił jak zdynamizować nasz układ. Zmierzyliśmy czas po jakim kulka przeturla się przez rynnę i zacznie spadać prawym szybem. Wtedy startuje siłownik i unosi ją do góry. Widać to w pierwszych sekundach filmu.&lt;br&gt;  &lt;br /&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/pve6oL_GmVY&amp;hl=en"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/pve6oL_GmVY&amp;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/172996211129286102-2742629152400383015?l=szkodaczasu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://szkodaczasu.blogspot.com/feeds/2742629152400383015/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=172996211129286102&amp;postID=2742629152400383015' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/2742629152400383015'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/172996211129286102/posts/default/2742629152400383015'/><link rel='alternate' type='text/html' href='http://szkodaczasu.blogspot.com/2008/03/lab-eiua.html' title='Lab EiUA'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
