piątek, 21 października 2011

Git i (współ)praca z innymi systemami kontroli wersji

Dzisiaj będzie bardziej konkretny post. Jako, że sam nie tak dawno zmieniałem pracę, w której niestety programiści używali cvsa i nie mieli ochoty tego zmieniać (zgodnie z zasadą po co coś zmieniać skoro działa) to postanowiłem opisać jak sobie poradzić w takiej sytuacji.


Po co?
Pytanie jak najbardziej zasadne. Odpowiedź jest prosta, po to aby móc korzystać z wszystkich zalet gita nie robiąc rewolucji wśród reszty zespołu. Jakie to zalety? Jeżeli ktoś nie wie do odsyłam do link lub do link. Mnie cieszy najbardziej to, że mam całe sklonowane repo tylko dla siebie i mogę sobie commitować ile mi się podoba. Nie bez znaczenia jest też łatwość tworzenia branchy i ich niemal automatyczne mergowanie.

Krok 1 - tworzenie centralnego repozytorium gita tylko do odczytu
Na początku musimy stworzyć repozytorium, które będzie klonem tego głównego (czy to cvs czy svn). Najlepiej postawić je na maszynie, do której wszyscy będą mieli łatwy dostęp. Natomiast, co ważne to repozytorium będzie tylko ściągało zmiany z oryginalnego, nie będziemy żadnych zmian bezpośrednio do niego wrzucać!

W przypadku cvsa robimy to tak:
Przed importem należy ustawić zmienną CVSROOT w ten sposób:
$ CVSROOT=:method:user@host:/path/to/CVS/root cvs login
Później tworzymy sobie jakiś katalog, w którym będzie znajdowało się repozytorium i przechodzimy do niego. I wreszcie importujemy wszystko z cvsa:
$ git-cvsimport -p x -v -d :method:user@host:/path/to/CVS/root/someproject
method oznacza typ serwera, np. pserver. Możemy wprowadzić kilka drobnych udogodnień:
$ git config cvsimport.module someproject
$ git config cvsimport.r cvs
$ git config cvsimport.d $CVSROOT
W ten sposób przy aktualizowaniu repozytorium nie będziemy musieli prawie nic podawać.

A w svnie tak:
Na początku tworzymy sobie katalog, gdzie chcemy trzymać repozytorium i przechodzimy do niego. Później wywołujemy:
$ git-svn init svn://host/trunk/someproject
$ git-svn fetch
$ git-svn rebase

Zaznaczam w tym miejscu, że jeżeli mamy jedno repozytorium z wieloma projektami to warto zrobić kilka repozytoriów gitowych - każdy per projekt. Stąd someproject w podanych wyżej wywołaniach.

Krok 2: sklonowanie repozytorium gita
Teraz klonujemy sobie świeżo utworzone repozytorium, na którym będziemy pracować:
$ git clone /path/to/git dir

UWAGA: pracujemy tylko na branchach. Zaraz po sklonowaniu warto utworzyć sobie jakiegoś brancha aby nie pracować na branchu master. Jest to ważne przy późniejszym przerzucaniu zmian. Brancha możemy utworzyć w ten sposób:
$ git checkout -b nazwa_brancha
Utworzymy w ten sposób brancha bazującego na branchu master.

Krok 3: wrzucanie zmian
Jak już popracowaliśmy to pora na commit. Robi się go w ten sposób:
$ git add zmienione_pliki
$ git commit
Listę zmienionych plików możemy podejrzeć w ten sposób:
$ git status
Ewentualnie aby nie dodawać do commita każdego pliku z osobna możemy użyć:
$ git commit -a

Krok 4: formatowanie patcha
OK, mamy wrzucone zmiany do lokalnego repo. Jeżeli zrobiliśmy tylko jednego commita to sprawa jest banalna:
$ git format-patch -1
W ten sposób git utworzy nam plik o nazwie 0001-commit_message.patch
Jeżeli zrobiliśmy więcej commitów to mamy dwa wyjścia:
  • jeżeli chcemy mieć w oryginalnym repozytorium widoczne wszystkie commity jakie zrobiliśmy w gicie to wywołujemy:
    $ git format-patch origin..HEAD
    To polecenie utworzy nam serię patchy, każdy per commit
  • jeżeli natomiast chcemy mieć jeden zbiorczy commit to musimy sobie zmergować zmiany. W tym celu wracamy na chwilę do brancha master:
    $ git checkout master
    Tworzymy sobie tymczasowego brancha:
    $ git checkout -b merge_branch
    I mergujemy:
    $ git merge --squash nazwa_brancha_ze_zmianami
    Opcja --squash powodują złączenie wszystkich commitów w jeden.
    Commitujemy:
    $ git commit
    Po czym tworzymy patcha:
    $ git format-patch -1
    Może teraz przejść na innego brancha i usunąć ten tymczasowy:
    $ git checkout master && git branch -d merge_branch

Krok 5: wrzucanie zmian do oryginalnego repozytorium
Gdy mamy już patcha lub patche to przenosimy je do katalogu z checkoutem czy to cvsa czy svna. Po czym wywołujemy:
$ patch -p1 < plik_patcha
Przeglądamy sobie czy wszystko jest OK i commitujemy jak zwykle.
Jest też sposób automatyczny, którego nie polecam. Lepiej mieć nad wszystkim kontrolę. Jeżeli ktoś chce to niech poszuka informacji o git-svn dcommit lub git cvsexportcommit.

Krok 6: aktualizacja centralnego repo gita
Przechodzimy do katalogu z naszym centralnym repo gita i wywołujemy:

Dla cvsa:
$ git cvsimport -a -p -x

Dla svna:
$ git-svn fetch
$ git-svn rebase

Krok 7: aktualizacja lokalnego repo gita
W katalogu z naszym lokalnym repo wykonujemy (na każdym branchu, który chcemy zaktualizować):
$ git pull origin master
Należy pamiętać, że aby uniknąć konfliktów przy nakładaniu patcha należy zawsze przed utworzeniem brancha tymczasowego zaktualizować brancha master jak również checkout originalnego repo.

I tak w kółko :)
Wydaje się, że to dużo roboty. Powiem tak, jak już się raz to wszystko zrobi to potem nie ma jej w cale więcej niż dotychczas (oczywiście poza przerzucaniem zmian). Na przykład aktualizowanie repozytoriów można zautomatyzować jakimś prostym skryptem. Korzyści płynące z pracy z gitem są bezcenne. Naprawdę warto spróbować.

wtorek, 18 października 2011

Własność intelektualna

Ostatnio słuchając audycji o tytułowej własności intelektualnej na kontestacji przyszła mi do głowy pewna myśl. Wyobraźmy sobie, że ktoś stworzył maszynkę, która potrafi kopiować dowolne przedmioty, np. wkładamy do niej jabłko, ona sobie tam chwilę pohałasuje i w efekcie dostajemy drugie dokładnie takie samo jabłko. Teraz wyobraźmy sobie, że kupując na straganie jedno jabłko sprzedawca każe nam podpisać umowę, w której zobowiązujemy się do nie kopiowania takiego jabłka. Wydaje się, że zdrowo myślący człowiek popukał by się w czoło i pomyślał "co mi tu będzie jakiś pe**ł mówił co ja mam robić ze swoim jabłkiem" po czym poszedłby do innego sprzedawcy. W efekcie nasz kochany sprzedawca nie wiele by zarobił.

Dlaczego więc w umowach (licencjach) dot. oprogramowania powszechnie akceptujemy takie zapisy? Odpowiedź jest dość prosta. Nie dość, że istnieje prawo chroniące takie umowy to jeszcze wszędzie wokół karmią nas stwierdzeniami typu, że nie moralnym jest godzić się na kopiowanie oprogramowania bez płacenia za to. Tak naprawdę nie o zapłatę tu chodzi. Wszechobecnym argumentem są ogromne straty, które są liczone w oparciu o błędne przekonanie, że gdyby nie kopiowanie to ci wszyscy ludzie by to oprogramowanie kupili. Ale przecież programów nie można traktować na równi z produkcją, dajmy na to, noży. Tworzenie oprogramowania to nie przemysł lecz usługi. I bardziej adekwatne byłoby w moim odczuciu płacenie za wykonaną usługę, tzn. usługę napisania programu. Jasne, że wówczas cena oprogramowania byłaby dużo droższa ale i to oprogramowanie byłoby znacznie łatwiej dostępne. Powiedzmy, że jeden człowiek nie byłby w stanie kupić sobie żadnego programu ale jak zrzuci się np. gmina, miasto, firma czy inna grupa ludzi to wszyscy mogą później z niego korzystać. Tak więc i programiści więcej zarobią, a i konsumenci więcej mieć będą a do tego jeszcze wytworzy się silna konkurencja więc również jakość oprogramowania wzrośnie.

Konkludując, uważam, że to nie żadne państwo powinno mówić jakie umowy są moralne a jakie nie, a już tym bardziej nie powinno niczego narzucać odgórnie (jak w przypadku praw autorskich). Zresztą widać dzisiaj, że mimo odgórnego zakazu ludzie i tak kopiują na potęgę. Nie wiem jak Wam ale dla mnie jest to sygnał, że konsumenci chcą jednak czegoś innego niż chce państwo. Niech zatem rynek (czyt. konsumenci) o tym zadecyduje!

poniedziałek, 17 października 2011

Niezastąpiony, niepokonany, najlepszy

Jak już wspominałem ostatnio kontynuuję cykl o tym jak stać się lepszym programistą. Na pierwszy ogień idzie zatem Vim. Na wstępie należałoby przede wszystkim zadać sobie pytanie "po co?". Po co odchodzić od przyjemnych, intuicyjnych edytorów (ba, całych IDE) na rzecz kompletnie nieporęcznego, nieintuicyjnego i minimalistycznego (tylko z wyglądu) Vima. Odpowiedzi mógłbym udzielić całe mnóstwo ale skupię się na tych najważniejszych. Przedstawię je opisując od razu każdą z nich z osobna.

Rozpocznę od flagowej idei, która przyświecała jeszcze staremu vi czyli ergonomia i wygoda pisania. W czasach kiedy pisanie czegoś na komputerze nie należało do rzeczy najprzyjemniejszych - głównie z uwagi na szybkość komputerów - powstał edytor zwany vi. Jak wieść niesie programiści prześcigali się w jak najmniejszej ilości naciśnięć kombinacji klawiszy aby wykonać dane zadanie (notabene dzisiaj podobna inicjatywa również istnieje, więcej informacji tutaj). Twórcy vi skupili się głównie na dwóch aspektach:
  • edycja i przeglądanie tekstu musi być jak najszybsze przy jak najmniejszym udziale człowieka,
  • komendy, skróty klawiszowe powinny być zaprojektowane w sposób jak najbardziej spójny, logiczny, łatwy do zapamiętania oraz rozłożone tak aby człowiek nie musiał odrywać dłoni od klawiatury (ani wyginać nadgarstków).
Specjalnie nie napiszę co takiego wymyślili, ponieważ tego dowiesz się w trakcie nauki (do której gorąco namawiam). Warto tutaj wspomnieć, że Vim jest kompletnie od nowa przepisanym starym vi i udoskonalonym - stąd nazwa Vi IMproved (co prawda na początku brzmiała Vi IMitation, ale jak tylko twórcy przepisali 99% funkcjonalności vi to zmienili nazwę). W tym miejscu mogę jeszcze nadmienić pomniejsze zalety, które pozostały po poprzedniku takie jak bardzo małe zużycie zasobów systemowych do tego stopnia, że można z powodzeniem pracować zdalnie na słabym łączu - dodam także, że Vim jest jednym z nielicznych edytorów, które potrafą z powodzeniem pracować z plikami, które zajmują więcej miejsca niż zainstalowana ilość RAMu w komputerze.

Stary vi to podstawa, która narzuca filozofię działania i logikę myślenia. Jednakże Vim oferuje znacznie więcej. Przede wszystkim czyni on z edytora swego rodzaju powłokę, tzn. jak z każdą powłoką komunikujemy się pewnym językiem skryptowym. Nie inaczej jest w tym przypadku, język skryptowy o którym mowa zwie się VimL (od Vim Language). Do czego on może służyć? Przede wszystkim do pisania pluginów ale nie tylko. Prostym przykładem, który mógłbym podać jest wypisanie w każdej linii kolejnej liczby (czyli prosta pętla i po sprawie) czy na przykład posortowanie zaznaczonego tekstu lub wczytanie wyjścia odpalonego programu zewnętrznego (tak, Vim potrafi odpalać programy konsolowe). W tym celu nie musimy ani zapisywać tego kodu (choć oczywiście możemy), ani go kompilować (język jest interpretowany) - wystarczy że go po prostu wpiszemy (nie chcę tutaj przedstawiać dokładnie jak to się robi, podpowiem tylko, że wygląda to podobnie jak w przypadku interaktywnych interpreterów). Na sam koniec wspomnę tylko o takich standardowych funkcjach jak zaznaczanie blokowe, wyrażenia regularne, podświetlanie składni, obsługa tagów, podpowiadanie, zintegrowana pomoc, obsługa okien, wielu schowków, buforów, możliwość definiowania prostych snippetów (właściwie abbreviation, mechanizm snippetów dostarczają pluginy) i tak można by wymieniać bez końca. Nie będę wypisywał wszystkich możliwości bo raz, że ich wszystkich nie poznałem (ciekawe czy jest to w ogóle możliwe), dwa że zajęło by to mnóstwo miejsca i trzy, że bym Cię, drogi czytelniku po prostu zanudził. Dlatego skupię się teraz na tym jak najszybciej się nie tylko nauczyć ale i pokochać Vima.

Każda dystrybucja przychodzi z programem (skryptem) o nazwie vimtutor. Po jego wykonaniu odpali nam się Vim z wczytanym samouczkiem, który należy czytać i wykonywać podane w nim ćwiczenia. Przerobienie samouczka zajmuje ok. 40 min ale należy go zrobić solidnie, tzn. jak napisane jest "nie używaj strzałek" to ich nie używaj. Naprawdę należy pozbyć się nawyków, które poznałeś do tej pory. Aby utrwalić sobie nabytą w ten sposób wiedzę używaj Vima gdzie tylko się da. Na początku będziesz pracować nieco wolniej ale później twoja produktywność wzrośnie kilkukrotnie!

Po samouczku warto poczytać pomoc, przejrzeć takie strony jak Vim Tips, poczytać parę książek (polecam "Hacking Vim"), poprzeglądać pluginy (tutaj) czy też zapisać się na listę dyskusyjną. Ale najważniejsze to po prostu go używać.

Właściwie mógłbym zakończyć ten przydługi wpis krótką sentencją używaną wśród vimowców:
Jeżeli musisz coś zrobić więcej niż dwa razy to powinieneś się zastanowić jak można to lepiej wykonać.
Jeżeli interesują Cię konkrety (co i jak zrobić, czego użyć itp.) to daj znać w komentarzu. Postaram się szybko odpowiedzieć, a jak będzie większy odzew to mogę utworzyć jakiegoś większego posta na ten temat. No to pozostaje mi tylko życzyć powodzenia!

piątek, 14 października 2011

Efektywność i jakość

Postanowiłem rozpocząć pewien cykl postów na temat jak wyróżniać się (pod względem umiejętności) wśród programistów. Genaralnie jak być jeśli nie najlepszym programistą w zespole to chociaż w ścisłej czołówce. Już na samym początku muszę obalić jeden krążący wokół mit. Nie wystarczy dużo czytać o nowych technologiach czy wzorcach ani też nie wystarczy tylko odpowiednio dużo programować. Tak naprawdę wszystko zależy od tego jak abstrakcyjnie potrafisz myśleć. Wiem, trudne słowo ale postaram się je nieco przybliżyć.

Należy zacząć od słowa abstrakcja, ponieważ nie wszyscy chyba to słowo rozumieją. Jest to jedna z najważniejszych rzeczy, gdyż jak niektórzy twierdzą, tylko ona tak naprawdę odróżnia nas od zwierząt. Zapytacie pewnie, jak to? Przecież chodzimy na dwóch nogach, mamy wyprostowaną postawę a co najważniejsze mamy jeszcze świadomość. Otóż są to rzeczy sporne bo jakby się uprzeć to i małpa czasami chodzi na dwóch nogach, a co do świadomości to nie sądzę aby człowiek miał na nią monopol. Wracając do abstrakcji, to dzięki niej możemy w ogóle cokolwiek tworzyć. Abstrakcja to inaczej oderwanie, uogólnienie. Myślenie abstrakcyjne pozwala nam więc uogólniać - wyciągać cechy wspólne, stałe, niezmienne. Po co? Po to by te rzeczy ze sobą łączyć, ulepszać, naśladować oraz tworzyć zupełnie nowe.

Jak ma się to do programowania? Cóż, abstrakcje w programowaniu to przede wszystkim typy danych. Tworzymy je po to aby ułatwiać sobie pracę, np:
  • skracać ilość kodu potrzebnego do napisania,
  • dbać o poprawność programu,
  • ułatwiać sobie dzięki nim późniejsze modyfikacje.
Oczywiście są też największym źródłem problemów. Począwszy od języków dynamicznych gdzie praktycznie nie mamy możliwości wymuszenia prawidłowego korzystania z nich po chociażby (niewłaściwe) rzutowania w innych językach.

Co cechuje dobrego programistę? Dobry programista przede wszystkim myśli typami. Można porównać to trochę do Matrixa gdzie jeden z bohaterów nie widział już tych wszystkich liczb i znaków na ekranie ale same kobiety i mężczyzn. Co to oznacza w praktyce? Np. pisząc tekst nie widzimy znaków - widzimy słowa, zdania paragrafy, linie itp. Czytając kod nie widzimy do, while, for, function, mov rax, 0xff ale widzimy pętle, funkcje, obiekty, instrukcje. Tworząc kod widzimy interakcje i powiązania między typami. Jeżeli w ten sposób funkcjonujesz to nie irytuje Cię poprawianie błędów, nie nudzisz się przy rysowaniu UMLi, z chęcią przeglądasz cudzy kod. Tak, to wszystko sprawia Ci ogromną przyjemność. Nie wystarczy więc być geekiem aby być dobrym programistą (choć większość programistów nawet geekami nie jest). Oprócz wiedzy jak działa komputer (czyli znajomości systemów operacyjnych, sieci, imperatywnych języków programowania i assemblera ) trzeba jeszcze umieć i być nieźle wprawionym w myśleniu abstrakcyjnym.

Jak więc się wprawić? Oto kilka rad:
  • Do pisania używaj vima - nauczysz się nie tylko jak szybko pisać i edytować tekst ale także widzieć obiekty w tekście i na nich działać. Szybko oznacza tu naprawdę szybko (o wiele szybciej niż chociażby w jakimś Visual Studio). Korzystanie z vima przypomina programowanie, np. wydajesz instrukcje (naciskając odpowiedni ciąg kombinacji klawiszy) usunięcia wszystkiego od miejsca, w którym znajduje się kursor do drugiego wystąpienia litery f.
  • Dokumenty twórz w LaTeXu - wówczas będziesz widział w tekście strony, rozdziały, różnego rodzaju bloki. Nauczysz się widzieć dokument patrząc na jego źródło. Ponadto twoje dokumenty będą wyglądały nieziemsko w porównaniu do tych z różnych pakietów office.
  • Naucz się kilku języków deklaratywnych (z rodziny funkcyjnych i logicznych) - tam praktycznie programuje się samymi typami.
  • Wreszcie staraj się używać jak najbardziej niskopoziomowych narzędzi, pisz skrypty, debuguj w gdb itp. - te narzędzia są znacznie szybsze od graficznych. Mam tu namyśli czas jaki Ty spędzisz nad zrobieniem czegoś, oczywiście gdy już się wprawisz. Zaoszczędzisz sporo czasu oraz wiele się nauczysz.

Myślę, że w kolejnych postach opiszę pokrótce powyższe punkty. Mam nadzieję, że zmotywuje to chociaż niektórych do pracy nad sobą :)

czwartek, 13 października 2011

XMonad i XMobar na wielu monitorach

Ostatnio dostałem w robocie drugi monitor. Nic nadzwyczajnego, ot takie zwykłe BenQ 22". Jako, że wszędzie, gdzie tylko jest taka możliwość używam XMonada jako menadżera okien więc i tym razem postanowiłem zobaczyć jak sobie radzi z wieloma monitorami. Muszę przyznać, że jest jeszcze lepiej (!) niż na jednym monitorze w przeciwieństwie do innych menadżerów jak Gnome czy KDE, gdzie działa to fatalnie (nigdy nie wiem, na którym monitorze wyświetli się okno i takie tam).

Oczywiście wszystko działa out of the box ale nie spodobała mi się jedna rzecz. Otóż mój wspaniały panel (XMobar) wyświetlał się tylko na jednym monitorze. Niestety nie znalazłem w sieci żadnego poradnika jak zrobić aby wyświetlał się na dwóch więc jakby ktoś też tego potrzebował to zamieszczam poniżej instrukcję jak to zrobić (jako, że znam Haskella to nie było to dla mnie wielkim problemem).

Po pierwsze musimy utworzyć dwie instancje XMobara ze wskazaniem, na którym monitorze ma się uruchomić. W tym celu edytujemy nasz xmonad.hs i dorzucamy do funkcji main takie 2 linijki:
xmproc <- spawnPipe "xmobar -x 0"
xmpro2 <- spawnPipe "xmobar -x 1 ~/.xmobarrc2"
Parametr x oznacza numer monitora zaczynając od 0. Ja akurat potrzebowałem aby każdy panel wyglądał nieco inaczej (głównie ze względu na program trayer, który ma się znaleźć tylko na jednym monitorze) więc druga instancja uruchamia się z innym plikiem konfiguracyjnym (.xmobarrc2). W drugim kroku musimy powiedzieć menadżerowi aby wysyłał takie same dane do dwóch paneli. Edytujemy więc w xmonad.hs funkcję logHook:
xmonad $ defaultConfig
                { manageHook = manageDocks <+> manageHook defaultConfig
                , layoutHook = avoidStruts $ smartBorders $ tabbed shrinkText myTabConfig ||| layoutHook defaultConfig
                , logHook = dynamicLogWithPP $ xmobarPP
                        { ppOutput = \s -> do
                              hPutStrLn xmproc s
                              hPutStrLn xmpro2 s
                        , ppTitle = xmobarColor "green" "" . shorten 150
                        }              
                , modMask = mod4Mask
                , terminal = "gnome-terminal"
                , keys = \c -> myKeys c `M.union` keys defaultConfig c
                }
Interesuje nas linijka przy logHook a dokładnie ppOutput. Nie ma tam nic nadzwyczajnego, po prostu przekazujemy dane do obydwu instancji XMobara. I to właściwie wszystko. Mój cały config do XMonada dostępny jest tutaj. A do XMobarów kolejno tutaj i tutaj.

środa, 12 października 2011

Philips SAA7130 pod linuxem

Dla odmiany po poprzednim poście napiszę coś technicznego jak na prawdziwego informatyka przystało. Nie tak dawno kupiłem sobie tani tuner tv (ok. 50 zł) oparty na chipset'cie philips saa7130. Jak tylko tuner doszedł pocztą postanowiłem go od razu wypróbować. Zamontowałem kartę w moim itx'ie, na którym miałem postawione ubuntu. Odpalam, system wykrył co prawda kartę prawidłowo ale w tvtime nie miałem ani obrazu ani dźwięku. Okazało się, że linux załadował odpowiedni sterownik ale nie ustawił odpowiedniego modelu karty i tunera. Niestety na liście kart i tunerów nie ma mojego modelu, gdyż producentem tej karty jest jakaś mała firma jak to zwykle bywa w przypadku wykorzystywania tanich chipsetów. Jeżeli ktoś ma podobną kartę, z którą nie może dojść do ładu to poniżej przedstawiam rozwiązanie jak sobie radzić z tego typu kartami pod linuxem.

Na wstępie powinniśmy się zaopatrzyć w program tvtime i tvtime-scanner. Pod ubuntu najłatwiej w ten sposób:
$ sudo apt-get install tvtime

Teraz tworzymy prosty skrypt, który będzie testował różne ustawienia modeli kart i tunerów automatycznie. W tym celu tworzymy plik, np. o nazwie skrypt.sh:
#!/bin/bash

echo -e "Program started\n" > out
for i in {52..152} ; do
    for g in 0 1 26 ; do
        echo "Card: $i, Tuner: $g"
        rmmod -w saa7134_alsa saa7134_dvb saa7134_empress saa7134
        `modprobe saa7134 card=$i tuner=$g`
        timeout -9 120 tvtime-scanner 2>&1 | while read f ; do
            if [[ $f =~ "Znaleziono kana" ]] ; then
                exit 2; //found!!
            fi

            if [[ $f =~ "Nie znaleziono tunera" ]] ; then
                exit 3; //No tuner found!
            fi
        done

        echo "code = $?";
        if [ $? -eq 2 ] ; then
            echo -e "Found Card = $i, Tuner = $g\n" >> out
        fi
    done
done
echo -e "Program ended\n" >> out
Linie 4 i 5 oznaczają numery kart i tunerów, które będziemy sprawdzać. Ja wpisałem akurat te wartości, które na liście kart (link) i tunerów (link) nazwami najbardziej odpowiadały mojej karcie. Kolejna ważna linijka 9 decyduje o czasie poszukiwania sygnału. Otóż tvtime-scanner skanuje całe pasmo w poszukiwaniu programów. Trwa to bardzo długo więc jakbyśmy mieli za każdym razem przeszukiwać całe pasmo to sprawdzenie wszystkich kombinacji kart i tunerów zajęłoby nam z miesiąc czasu. Dlatego też programem timeout ustawiamy limit długości trwania skanowania - w moim przypadku 120 sekund wystarczy, gdyż pierwszy program mam zaraz na początku pasma.

W kolejnym kroku zmieniamy uprawnienia do skryptu na wykonywalne:
$ chmod a+x skrypt.sh

I uruchamiamy go jako root:
$ sudo ./skrypt.sh

Skrypt będzie się wykonywał dość długo (parę godzin) więc warto go zostawić na noc. Gdy skrypt zakończy działanie przeglądamy plik o nazwie out, który się utworzył. Będzie on wyglądał mniej więcej tak:

Card: 49, Tuner: 0
ERROR: Removing 'saa7134_dvb': No such file or directory
ERROR: Removing 'saa7134_empress': No such file or directory
code = 3
Card: 49, Tuner: 1
ERROR: Removing 'saa7134_dvb': No such file or directory
ERROR: Removing 'saa7134_empress': No such file or directory
code = 3
Card: 49, Tuner: 26
ERROR: Removing 'saa7134_dvb': No such file or directory
ERROR: Removing 'saa7134_empress': No such file or directory
code = 3
Card: 50, Tuner: 0
ERROR: Removing 'saa7134_dvb': No such file or directory
ERROR: Removing 'saa7134_empress': No such file or directory
code = 0
Card: 50, Tuner: 1
ERROR: Removing 'saa7134_empress': No such file or directory
code = 2
Card: 50, Tuner: 26
ERROR: Removing 'saa7134_empress': No such file or directory
code = 2
Card: 51, Tuner: 0
ERROR: Removing 'saa7134_empress': No such file or directory
Killed
FATAL: Error running install command for saa7134
code = 0
Card: 51, Tuner: 1
ERROR: Removing 'saa7134_alsa': No such file or directory
ERROR: Removing 'saa7134_dvb': No such file or directory
ERROR: Removing 'saa7134_empress': No such file or directory
ERROR: Removing 'saa7134': Device or resource busy

Interesują nas właściwie tylko te linijki, które zawierają code = 2. Oznacza to, że złapano sygnał na tych ustawieniach sterownika więc praktycznie mamy zagwarantowany obraz. No to odczytujemy numer karty i tunera i wywołujemy (z roota):
$ rmmod -w saa7134_alsa saa7134_dvb saa7134_empress saa7134
$ modprobe saa7134 card=numer_karty tuner=numer_tunera

To, że mamy zagwarantowany obraz nie oznacza, że będziemy mieli dźwięk. Z dźwiękiem na tych kartach jest tak, że jest on analogowy (nie ma żadnego urządzenia w rodzaju karty dźwiękowej) więc należy bezpośrednio podłączyć kabelkiem wyjście audio na karcie do wejścia liniowego na karcie dźwiękowej. Niestety to nie wystarczy. Karty te mają dwa źródła dźwięku. Jednym jest sygnał z wejścia antenowego oczywiście a drugim sygnał z wejścia audio (na karcie są dwa złącza audio-in oraz audio-out). To powoduje, że sterownik musi umieć się pomiędzy nimi przełączać. Dlatego odpalamy tvtime (już z użytkownika) i patrzymy czy mamy obraz i dźwięk. Jak nie mamy to bierzemy następną parę karty i tunera z pliku gdzie code = 2 i powtarzamy powyższy krok aż do skutku. Jak już znajdziemy odpowiednie ustawienia to możemy je wpisać na stałe aby ustawiały się przy starcie systemu. W tym celu w pliku /etc/modules dopisujemy na końcu:
saa7134 card=numer_karty tuner=numer_tunera

Jakby komuś się nie chciało tego wszystkiego robić to może od razu sprawdzić moje ustawienia - karta 126 i tuner 1. Miłej zabawy!

O powodach i godności

Człowiek z natury jest leniwy (a może tylko programiści) i jak już zaczyna coś robić to dopiero wtedy kiedy solidnie zaczyna go coś irytować. Mówi się nawet, że najwięcej pieniędzy jest tam gdzie ludzie narzekają. Co by nie mówić musi to być prawdą przynajmniej w moim przypadku. W życiu denerwowało i nadal denerwuje wiele rzeczy ale ostatnia kampania wyborcza wprawiła mnie w nadzwyczaj nieprzyjemny stan. Oczywiście nie jedna kampania już była wcześniej i nie tylko w tej jednej kampanii człowiek nie mógł włączyć telewizji, radia czy przeczytać gazety bez wszechobecnych twarzy i jakże wymownych sentencji. Najczęściej pojawiającym się słowem tej kampanii (przynajmniej tym, które mnie wyprowadzało z błogiego stanu ignorancji) była godność i to w różnych formach: godna płaca, godne życie, bla bla bla. Niezrozumiałość tego słowa przez polityków wcale mnie nie dziwi i nawet to nagminne powtarzanie tych bzdur nie popchnęło mnie do napisania tego postu. Popchnęła mnie natomiast wiara w te słowa przez bądź co bądź bliskie mi osoby. Szukałem w internecie jakiejś sensownej definicji i niestety nie znalazłem więc postanowiłem przedstawić swoją.

Po pierwsze nie ma czegoś takiego jak godna płaca. Te słowa w żaden sposób się ze sobą nie łączą. Godność (a także i honor) jest bezpośrednio związana z innym bardzo ważnym słowem: wolność. Godność bowiem tracimy wówczas, gdy zyskujemy korzyści na odbieraniu wolności innych ludzi (oczywiście bez ich zgody). Pozwolę sobie przytoczyć w tym miejscu dobry przykład podany przez pana Janusza Korwin-Mikkego. Otóż człowiek, który zarabia 100zł i przymiera głodem może żyć godnie w przeciwieństwie do tego, który ma się dobrze a nie zarabia i bierze zasiłek socjalny od państwa. Dlaczego? Ponieważ ten pierwszy żyje z tego co sam zarobi, żyje na tyle na ile potrafi i swoje życie zawdzięcza tylko sobie. Ten drugi natomiast korzysta z pieniędzy brutalnie zabranych innym ludziom (w większości tym biednym, którzy zarabiają za dużo aby móc dostawać zasiłek). Godnie to znaczy żyć za swoje!


Politycy nie tylko kłamią odnośnie godności ale również upadlają ludzi. Jeżeli ktoś wmawia mi, że nie żyję godnie i nakłania mnie do brania zasiłku bo wówczas będę żył godnie a do tego szczyci się jeszcze tym, że te zasiłki podniesie to jest to dokładnie upodlenie ludzi!

A gdzie tu związek z wolnością? Jeżeli ktoś jeszcze tego jeszcze nie widzi to wyjaśnię to konkretnie. Zabieranie pieniędzy ludziom pod przymusem jest zabieraniem wolności, korzystanie z kradzionych pieniędzy czy innych kradzionych rzeczy jest niemoralne bo wówczas to Ty, drogi czytelniku, stajesz na szczycie tej piramidy. Innymi słowy to Ty jesteś zleceniodawcą ergo również Ty godzisz w wolność innych ludzi.

Wiem co powie na to większość ludzi. Powiedzą, że jak tu żyć godnie jak ci wredni bogaci kapitaliści ciągle obniżają im pensje a z czegoś trzeba wyżywić swoje rodziny. Twierdzić będą, że "bogacą się kosztem biednych ludzi". Otóż w normalnym wolnym świecie bogatym zostać można tylko w jeden sposób, po prostu robiąc coś dla innych. Na tym polega praca. Ludzie mają różne cele, różne ambicje, ideały, marzenia ale aby je spełniać potrzebują różnych rzeczy. Cała sztuka polega na tym aby dawać ludziom to czego oni potrzebują a w zamian dostając potrzebne nam rzeczy (np. pieniądze). Zatem ludzie nie bogacą się kosztem innych lecz pracując na rzecz innych. Jest to najlepszy sposób na godne życie.