Wednesday, 29 November 2006

Leadtek Winfast TV2000 XP on gentoo (part 1 - infrared remote)

The TV2000 XP is a tv/radio tuner card with a video input slot and an infrared pilot (CoolCommand). It is based on Conexant CX23880/1/2/3 PCI Video and Audio Decoder. Complete output of lspci -vv looks like this:


02:02.0 Multimedia video controller: Conexant CX23880/1/2/3 PCI Video and Audio Decoder (rev 05)
Subsystem: LeadTek Research Inc. Unknown device 6611
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
Latency: 32 (5000ns min, 13750ns max), Cache Line Size 08
Interrupt: pin A routed to IRQ 22
Region 0: Memory at fa000000 (32-bit, non-prefetchable) [size=16M]
Capabilities: [44] Vital Product Data
Capabilities: [4c] Power Management version 2
Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 PME-Enable- DSel=0 DScale=0 PME-

Linux kernel (2.6.17) contains drivers for this device in the Video For Linux section. You have to enable the following options:


Device Drivers --->
Multimedia Devices --->
<*> Video For Linux
[*] Enable Video For Linux API 1 (DEPRECATED)
[*] Enable Video For Linux API 1 compatible Layer
Video Capture Adapters --->
<M> Conexant 2388x (bt878 successor) support
<M> Conexant 2388x DMA audio support

For the infrared pilot to work you have to enable the evdev event interface:


Device Drivers  --->
Input Device Support --->
<*> Event Interface

Now recompile (make install && make modules modules_install for gentoo-sources) and reboot. After the system boots again, load the module cx8800 (modprobe cx8800). dmesg | tail -n 15 should report something similar to this:


cx2388x v4l2 driver version 0.0.5 loaded
ACPI: PCI Interrupt 0000:02:02.0[A] -> GSI 22 (level, low) -> IRQ 22
CORE cx88[0]: subsystem: 107d:6611, board: Leadtek Winfast 2000XP Expert [card=5,autodetected]
TV tuner 44 at 0x1fe, Radio tuner -1 at 0x1fe
cx88[0]: Leadtek Winfast 2000XP Expert config: tuner=38, eeprom[0]=0x01
input: cx88 IR (Leadtek Winfast 2000XP as /class/input/input2
cx88[0]/0: found at 0000:02:02.0, rev: 5, irq: 22, latency: 32, mmio: 0xfa000000
tuner 0-0060: All bytes are equal. It is not a TEA5767
tuner 0-0060: chip found @ 0xc0 (cx88[0])
tuner 0-0060: type set to 38 (Philips PAL/SECAM multi (FM1216ME MK3))
tda9887 0-0043: chip found @ 0x86 (cx88[0])
cx88[0]/0: registered device video0 [v4l2]
cx88[0]/0: registered device vbi0
cx88[0]/0: registered device radio0

and ls -l /dev/v4l/ should show devices radio0, vbi0 and video0, all belonging to user root and group video. Also, please note the line input: cx88 IR (Leadtek Winfast 2000XP as /class/input/input2. There should be a new event device in /dev/input/ with the same number (in this case, it will be /dev/input/event2). Unfortunately, device's name depends on the order in which devices are created by udev, and this might change. In order to find a static name of the remote, inspect the /dev/input/by-path directory. It contains device symlinks that udev created using devices' physical addresses. This is enough for a PCI card, because it will be constatant as long as the slot the card is plugged won't change. In my case, the infrared control is visible as /dev/input/by-path/pci-0000:02:03.0--event-ir.


Add cx8800 to /etc/modules.autoload/kernel-2.6 , so it will be loaded each time system starts. Now, in your /etc/make.conf, add lirc v4l v4l2 to USE flags and add a line LIRC_DEVICES="devinput". Although lirc has a driver for Leadtek Winfast TV2000 XP (named leadtek_0010), I was unable to get it to work under kernel 2.6.17 (it did not create a device node, and all attempts to use it resulted in lircd crashing and irw reporting "could not connect to socket"). Emerge lirc (and kdelirc if you want an easy way to control all KDE applications with your remote) and then execute emerge -avuDN world.


First, check if the remote works. Run lircd -d /dev/input/by-path/pci-0000:02:03.0--event-ir -n and press some buttons on the remote. Lircd should report them (although, sadly, not all keys work through the event interface). Edit /etc/conf.d/lircd and set LIRCD_OPTS="-d /dev/input/by-path/pci-0000:02:03.0--event-ir" (change the path to match your configuration). Save Leadtek Winfast TV2000 XP lirc configuration as /etc/lircd.conf. Save lirc configuration for xmms, mplayer and vlc as /etc/lircrc.


Now kill the manually started daemon and start the system one (/etc/init.d/lircd start). Add it to the runlevel (rc-update add lircd default). Start xmms/mplayer/vlc to test how your remote works. If you encounter any problems, verify that irw reports key names correctly.

Saturday, 18 November 2006

Gry są złe

Złe, niedobre i powinny być zakazane. Koniecznie. Od ponad roku żadnej dłużej niż jeden dzień na dysku nie zostawiłem, myślałem, że już mnie nie bawią... A potem trafił się Oblivion. Teoretycznie nie powinien w ogóle ruszać na moim archaicznym sprzęcie, ale trochę kombinowania (głównie za pomocą Oldblivion) i udało się uzyskać całkiem porządną jakość. A przynajmniej tak mi się wydawało.


Widok na Imperial City

PiBis odwiedził mnie i przyniósł swojego nowiutkiego laptopa. Trzeba było czymś pomęczyć nową maszynkę, wybór padł właśnie na Oblivion. I to był błąd. Zobaczyłem fale na wodzie, trawę ruszającą się pod wpływem wiatru i motyle fruwające nad kwiatami. Poległem. Jak powszechnie wiadomo, faceci są jak małe dzieci, tylko mają więcej pieniędzy. W związku z czym mam teraz nieco mniej pieniędzy (ale w granicach rozsądku, na całe szczęście) a Oblivion u mnie wygląda tak:


Widok na Imperial City

Ten sam widok chwilę później, gdy opadła mgła:


Widok na Imperial City

Pierwszy raz w grze zdarzyło mi się, że mając wejść do jakiegoś lochu, stałem 5 minut przed wejściem patrząc na zachodzące słońce. Grafika w tej grze powala, wycieczka po zapomnianej świątyni potrafi naprawdę przestraszyć: po wypalenu się ostatniej pochodni z ekwipunku, korzystając ze słabiutkiego światła rzucanego przez zaklęcie wypatrywałem kolejnej pułapki i aż podskoczyłem, gdy z za narożnika wymaszerował na mnie szkielet.


A przechodząc na temat bardziej techniczny: z mojej obsesji już się zwierzałem, tym razem jej efektem był wybór karty z pasywnym chłodzeniem.


Gigabyte GS 7600 w opakowaniu

Zabawka jest nieco krótsza od poprzedniej (którą, notabene, z bólem serca oddam w dobre ręce) i zdecydowanie chudsza.


karty graficzne od spodu
karty graficzne od góry

GV-N76G256D-RH: na pokładzie 256 MB pamięci DDR2, magistrala AGP 8x. Wynik 3DMark 2005: 3680 punktów, po minimalnym podkręceniu: 3810 punktów. GlxGears na starej karcie wyciągały do 3k FPS, na nowej 6k FPS. Co mnie lekko zaskoczyło, karta ma też osobne gniazdo zasilania. Takie czasy... Przysporzyło mi to nieco problemów - w pogoni za ciszą wymieniłem jakiś czas temu zasilacz (nowy ma wentrylator o średnicy 12 centymetrów i odpinane kable), potem obudowę (wentylatory, a jakże, 12 centymetrów, do tego zasilacz umieszczony na dole, w osobnej komorze), a teraz okazało się, że muszę przeciągnąć dodatkowy kabel zasilający. Chwilę to trwało, kabli w przejściu między jedną a drugą komorą obudowy jest dość dużo.


Plątania kabli zasilających w obudowie
Karta na swoim miejscu

Z instalacją w systemie poszło już gładko. Windows oczywiście pokrzyczał trochę, kazał się ponownie aktywować (a niech mu będzie, w końcu Politechnika funduje studentom oryginały), restartował sie 3 razy w trakcie instalowania sterowników. Gentoo podeszło do sprawy tak spokojnie, że zacząłem się obawiać, iż coś jest nie tak. Sprawdziłem, co zgłasza lspci oraz jak wygląda wynik glxgears i zostałem przyjemnie zaskoczony - sterowniki nVidii, bez żadnej ingerencji ze strony użytkownika, wykryły i obsłużyły zmienioną kartę.


Wczoraj usłyszałem upragniony od dawna komplement: szwagier wszedł do pokoju i poprosił, żebym włączył komputer. Wreszcie mogłem odpowiedzieć: "Przecież jest włączony!"

Friday, 17 November 2006

Saturday, 21 October 2006

phpBB, RSS, automatyczne logowanie i Google Reader

If you do not speak Polish, please take a look at phpBB support forums.


Dla forum phpBB powstało kilka skryptów generujących feed RSS. Ja od dłuższego czasu używam RSS Feed 2.2.4 i jestem z niego zadowolony. Problemem okazał się dopiero Google Reader. RSS Feed mod obsługuje fora wymagające specjalnych uprawnień użytkownika by je obejrzeć, ale w tym celu wymaga istnienia ciasteczka autologinu (jeśli czytamy RSS z przeglądarki) lub prosi o zalogowanie poprzez mechanizmy wbudowane w protokół HTTP. Niestety żaden czytnik online nie potrafi obsłużyć tej funkcjonalności.


Sposób na obejście tego ograniczenia podpatrzyłem na blogu Olórina - nazwa użytkownika i hasło przekazywane są w żądaniu GET, jako część URL. Oczywiście hasło nie jest wysyłane w postaci jawnej, a jako skrót (hasz). W oryginalnym skrypcie wystarczyły drobne zmiany i wszystko działa.


Przechodząc do konkretów: pobrać można patch lub zmodyfikowane pliki. Jeśli chcesz dodać jeszcze informację do FAQ dla użytkowników forum, możesz skopiować ode mnie z forum poznańskiego klubu fantastyki Ad Astra.

Tuesday, 5 September 2006

NAnt, NUnit and mono 1.1.17

The new release of mono contains various bug fixes, many of them concerning the AppDomain class, creation of application domains and communication between them. Unfortunately, those changes broke the <nunit2> task in NAnt scripts run on Linux (strangely, everything works fine on Windows). When executed, task reports an incompatible version of NUnit assembly used to compile the tests. However, when nant is run with -verbose switch, the real exception can be examined - mono is unable to load the NAnt.NUnit2Tasks.dll into the new AppDomain.


A temporary workaround is to execute the tests with the <exec> task. Start with defining a template target:



<target name="test-assembly">
<if test="${platform::is-unix()}">
<!-- nunit2 task is borked on linux with mono 1.1.17 -->
<property
name="nunit.exe"
value="${framework::get-assembly-directory(framework::get-target-framework())}/nunit-console.exe" />
<echo message="${test-assembly}" />
<exec program="${nunit.exe}" workingdir="${binaries-dir}" useruntimeengine="true">
<arg value="/nologo" />
<arg value="${test-assembly}" />
</exec>
</if>
<if test="${not platform::is-unix()}">
<nunit2 verbose="true">
<test assemblyname="${binaries-dir}/${test-assembly}" />
<formatter type="Plain" />
</nunit2>
</if>
</target>

The target still calls <nunit2> task when run on Windows, as it is faster then executing nunit-console.exe. On Linux it finds the nunit-console.exe from the appropriate framework version and uses it to execute the test. To use the template, two properties have to be set:



<target name="TestObject.test" depends="TestObject.dll">
<property name="binaries-dir" value="bin_test"/>
<property name="test-assembly" value="TestObject.dll" />
<call target="test-assembly" />
</target>

You can hardcode the binaries-dir or set it once for the entire build to avoid repeating it in every call to test-assembly.

D-Link G604T

W piątek odebrany z drugiej naprawy serwisowej. Za pierwszym razem (po dłuższej pracy zaczynał gubić pakiety, moc sygnału skakała zupełnie losowo, firewall - wylączony! - odcinał nagle połączenie itd.) - 3 tygodnie w serwisie i dostałem nowy sprzęt. Zgodnie z instrukcjami producenta zabrałem sie do instalacji nowego firmware'u i na tym sie skończyło. Instalator sie wysypał, router umarł. Druga naprawa poszła szybciej - szybciej tez access point zepsuł sie ponownie. W niedziele (niecałe dwa dni pracy!) zaczął szwankować cache DNS. Wylączylem cache - wszystko wróciło do normy, ale nieopatrznie chciałem zapisać zmiany. To wymaga restartu urządzenia... Po którym nie podniósł sie juz interfejs WiFi. Owszem, jestem w stanie go włączyć ponownie - pod warunkiem, ze wepnę sie do routera poprzez kabel ethernetowy. Wspaniale. Nie chce kolejnej naprawy, chce pieniądze z powrotem, D-Link nie nadaje sie do użytku.

Tuesday, 25 July 2006

Gdy programistom się nudzi...

Widok ogólny

syslog-ng na BA66

Efekt niezagospodarowanych 30 minut w pracy. Log systemowy, oprócz normalnego wyświetlania wiadomości na dwunastej konsoli i zapisywania do pliku, pokazuje je także na stojącym obok monitora głównego wyświetlaczu od kasy sklepowej.

Saturday, 17 June 2006

Permanent redirect

Na pewno zdarzyło Ci się kiedyś trafić na stronę z informacją w rodzaju "serwis dostępny teraz pod nowym adresem". Nierzadko data w stopce wskazuje, że przeprowadzka odbyła się już parę lat temu - a użytkownicy (znaczy - Ty) nadal trafiają pod stary adres. Traci też właściciel strony - nie dość, że musi nadal utrzymywać starą domenę strony (aby przekazać użytkownikom informację), to jeszcze wyszukiwarki wyżej oceniają starszy adres, pod niego kierując użytkowników. Nie byłoby wygodniej, gdyby użytkownicy automatycznie trafiali na nową stronę, a wyszukiwarki nie pokazywały już odnośników do starej?


Z pomocą przychodzi kod HTTP Permanent Redirect (301). Najprostsze rozwiązanie, jeśli cały serwis zmienił adres, to wpis w pliku .htaccess:


Options +FollowSymlinks
RewriteBase /
RewriteEngine On
RewriteRule ^.* http://nowy.adres.com%1 [R=permanent,L]

Powyższa regułka włącza mod_rewrite (RewriteEngine On), łapie wszystkie odwołania do strony (^.* - wyrażenie regularne), a następnie przekierowuje je ([R=permanent])na nową domenę, zachowując treść dopasowaną do wyrażenia regularnego (%1). Opcja L oznacza, że serwer ma na tej regule poprzestać zakończyć przetwarzanie pliku .htaccess. mod_rewrite pozwala na złożone przekształcenia adresu, co można wykorzystać, gdy zmieniła się struktura strony. Niestety, nie na wszystkich serwerach jest dostępny. W samym pliku .htaccess przekierowanie można też uzyskać poprzez


Redirect permanent /tutaj/byl/jakis.plik http://nowy.adres.com/jest.tutaj

natomiast w pliku php działanie przekierowania 301 można generować następującym kodem:


<?php
$var_array = explode("/",$_SERVER['REQUEST_URI']);
//print_r($var_array);
$target=$var_array[1];
$url="http://nowy.adres.com/".$target;
header("HTTP/1.1 301 Moved Permanently");
header ( "Location: $url" );
?>
<p>Strona została przeniesiona. Nowy adres:</p>
<a href="<?php echo $url; ?>"><?php echo $url; ?></a>

przy czym samo parsowanie $target trzeba dopasować do swoich potrzeb. Trzeba też pamiętać, że aby header zostało przyjęte przez przeglądarkę, serwer nie może wcześniej wysłać żadnej treści - jeśli np. przed początkiem skryptu w pliku będzie pusta linia, albo chociaż spacja, to przekierowanie nie zadziała.


Przepisywanie adresów za pomocą skryptu php sprawdza się najlepiej, gdy zmieniła się struktura strony - najłatwiej za ich pomocą poprawić adresy wymagające uaktualnienia. A w jaki sposób przekonać Apacha do obsługiwania żądań przy użyciu skryptu? Jeśli interesuje nas przepisywanie adresów z jakiegoś podfolderu, to wystarczy wykorzystać fakt, że Apache, gdy nie znajdzie żądanego adresu, zaczyna przesuwać się w górę wirtualnego drzewa plików, aż trafi na plik potrafiący obsłużyć żądanie. Np. dla http://domena.info/koza/little/beast najpierw zostanie sprawdzone koza/little/beast, potem koza/little, a na końcu koza. Wystarczy poinformować serwer, że koza jest skryptem php poprzez dodanie w .htaccess:


<Files koza>
ForceType application/x-httpd-php
</Files

Globalną obsługę żądań przez skrypt można ustawić za pomocą mod_rewrite:


RewriteRule ^.* rewriter.php [L]

dopasowując według potrzeb wyrażenie regularne.


Jak wyszukiwarki reagują na Permanent Redirect? Z mojego doświadczenia wynika, że po 2 tygodniach nowy adres traktowany jest jako równorzędny staremu, a po 4 tygodniach przejmuje już w całości jego Page Rank (stary adres nie pojawia się więcej w wynikach). Jeśli nie chcesz frustrować użytkowników, pamiętaj też, by uaktualnić linki przychodzące z innych stron - dopóki przekierowanie będzie działać, użytkownicy trafią na stronę, ale jeśli nie planujesz płacić za starą domenę w nieskończoność, wypadało by zupełnie usunąć z sieci odwołania do niej. Linki wchodzące można sprawdzić w logach serwera / statystykach (referer) lub poprzez wyszukiwarki. Tutaj niestety google kłamie bezczelnie, podając tylko małą część znanych mu linków, na szczęście Yahoo (linkdomain:domainname.com albo linksite:domainname.com) oraz MSN (link:domainname.com) zwracają pełną listę (z dokładniejszymi wynikami w Yahoo). Zostaje już tylko skontaktować się z adminem każdej z linkujących stron...

Dlatego lubię plusa

emerge -e world && echo "emerge -e world finished" | mail 48663280xxx@text.plusgsm.pl || echo "emerge failed" | mail 48663280xxx@text.plusgsm.pl

Friday, 2 June 2006

Palcówka

Porządne palcowanie wcale nie jest proste. Każdy, nawet najbardziej początkujący, jakoś sobie z nim radzi, ale jednak co profesjonalista to profesjonalista. Wielokrotnie obiecywałem sobie sumienną naukę - czasem nawet zaczynałem jakieś ćwiczenia, ale wiadomo, jak to jest - zaczyna się zgodnie z rozkładem, a potem nas ponosi i zaczyna się działać jak popadnie, byleby szybko był efekt. Faceci generalnie radzą sobie lepiej, ale to po prostu kwestia częstszych prób. Podobno nauka poprawnego palcowania jest nawet w programie liceum - niestety, mało który nauczyciel przeprowadza ten punkt programu. Większość puszcza uczniów na żywioł i tyle - dadzą sobie radę sami. A takie palcowanie z przypadku, szczególnie, gdy skupia się uwagę na wskazówkach wizualnych, jest nie do porównania z profesjonalnym - jest dużo wolniejsze, a przy tym dużo bardziej męczące.


Biorąc to wszystko pod uwagę, wziąłem się w końcu do roboty i sporządziłem sobie widoczny poniżej przyrząd do nauki palcowania. Wystarczyło trochę farbek modelarskich do zaznaczenia prawidłowego ułożenia palców. Malowanie dało jeszcze dodatkowy bonus - zakryte zostały różnorakie elementy rozpraszające normalnie uwagę.


Przyrząd do ćwiczenia palcowania

Saturday, 20 May 2006

Chwila refleksji

Nie, nie zmieniłem pomysłu na prowadzenie bloga, znów będzie o C#. Przestrzenie nazw System.Reflection i System.Reflection.Emit udostępniają zestaw bardzo interesujących klas, służących do dynamicznego analizowania i generowania kodu. Pozwala to np. stworzyć uniwersalne narzędzia, służące do serializowania dowolnych, nieznanych wcześniej typów, czy też pisanie własnych kompilatorów i analizatorów kodu.


Mechanizm refleksji, chociaż potężny, jest niestety dość powolny, w związku z tym wskazane jest uzupełnianie go dynamicznym generowaniem kodu. W ten sposób wystarczy raz tylko wykonać kosztowną analizę obiektu, a potem można korzystać z zebranych wcześniej informacji, wywołując wygenerowane za pierwszym razem metody i klasy. Oczywiście, wyprodukowany w ten sposób kod można zapisać na dysku w formie zwyczajnych assembly, do późniejszego wykonania.


Korzystanie z przestrzeni nazw System.Reflection.Emit wymaga niestety zapoznania się, chociaż pobieżnego, z CIL. Na szczęście SDK od Microsoftu zawiera dwa bardzo przydatne narzędzia. peverify.exe analizuje pliki assembly, zgłaszając wszelkie nieprawidłowości w ich strukturze, jak np. niewłaściwe nazwy obiektów, niezgodności typów, brak inicjalizacji instancji obiektów itp. Jest to istotne, ponieważ CLR bywa nadmiernie wyrozumiały dla licznych błędów, które można popełnić generując kod z pominięciem kompilatora. ildasm.exe oraz jego odpowiednik w mono, czyli monodis, pozwalają podejrzeć kod znajdujący się w plikach assembly, co z kolei umożliwia generowanie własnego kodu per analogiam. Wystarczy napisać kod w C#, skompilować, i sprawdzić, jak efekt wygląda w CIL.


Warto też pamiętać o rozszerzeniach mechanizmu refleksji, które powstała w trakcie rozwoju mono. Są to Cecil, pozwalający na inspekcję kodu bez ładowania go do środowiska CLR oraz CodeGeneration, który generuje CIL używając składni opartej na C#.


Na koniec parę ciekawostek odnośnie CLR. Na początek: interfejsy nie istnieją. CIL modeluje je za pomocą klas abstrakcyjnych. To pociąga za sobą (sic!) wielokrotne dziedziczenie. Dalej - nie istnieją też klasy. Są reprezentowane jako powiązane ze sobą struktury danych i funkcje. Każda metoda oczywiście potrzebuje wskaźnika this, który jest przekazywany do niej jako parametr numer 0 (kojarzy się z C++ ?). Pozwala to na takie operacje, jak wywołanie na obiekcie metod, których on nie posiada (poprzez wrzucenie go na stos parametrów metody innego obiektu - na szczęście, jeśli odpowiednie rzutowanie nie byłoby możliwe, wykonanie zakończy się wyjątkiem) lub uruchamianie metod instancji obiektu bez uprzedniego stworzenia go (wywołanie metody, kiedy stos nie zawiera odpowiedniego wskaźnika do obiektu - CLR zachowuje się wtedy, jakby obiekt istniał, ale wszelkie pola ustawione są na wartości domyślne dla swojego typu). Użyteczna dla wielu zastosowań może być możliwość dostępu do metod i pól prywatnych.

Friday, 12 May 2006

Zwalnianie zasobów (C#)

Jeśli dopiero co zaczynasz korzystać z platformy .Net, a wcześniej nie pisałeś w językach z automatycznym zarządzaniem pamięcią, to na pewno wcześniej czy później popełnisz ten sam błąd co ja. Wyobraź sobie, że pisana przez Ciebie klasa wykorzystuje jakieś zasoby systemowe niezarządzane przez Garbage Collector,. Jak je zwolnić? Naturalne wydaje się zrobienie tego w destruktorze, prawda? Przecież w C# ma on nawet tą samą znaną składnię, ~DummyClass(), co z tego, że nazywa się finalizer?


Haczyki są trzy. Pierwszy polega na tym, że finalizer zostanie wywołany w momencie sprzątania obiektu przez Garbage Collector, a to może stać się długo po usunięciu ostatniego do niego odwołania. Drugi - finalizer nie zostanie wywołany w ogóle, jeśli cała aplikacja jest właśnie wyłączana. Trzeci - obiekty posiadające finalizer śledzone odrębnie od nie posiadających go i usuwane z pamięci później. Całe to zachowanie wynika z faktu, że w środowisku z zarządzaną pamięcią klasyczna implementacja destruktora jest bardzo niewydajna, jeśli nie w ogóle niemożliwa.


Jak więc zwolnić takie zasoby? Należy zaimplementować interfejs IDisposable i pamiętać, by go używać, korzystając z implementujących go klas. Służy do tego specjalne słowo kluczowe using, gwarantujące, że na "opakowanym" w nie obiekcie zostanie wywołane Dispose(), niezależnie od tego,czy kod w klauzuli zakończy się normalnie czy też wyjątkiem. Używa się tego konstruktu tak:


using(DummyObject something = new DummyObject())
{
//jakiś kod, korzystający z obiektu something
}

Gdy korzystamy z obiektów implementujących IDisposable, a niemożliwe jest ujęcie ich w ramy using, należy je zwalniać w metodzie Dispose() korzystającego z nich obiektu.


I jeszcze przykładowe zastosowanie IDisposable, bo w nim też łatwo narobić błędów:


/// <summary></summary>
public class DisposableObject : IDisposable
{
#region implementacja IDisposable
/// <summary>
/// Finalizer, wywołuje Dispose,
/// <strong>nie nalezy na nim polegać!</strong>.
/// </summary>
~DisposableObject()
{
Dispose(false);
}

/// <summary>
/// Zwalnia używane zasoby. Wyrejestrowuje finalizer,
/// by niepotrzebnie nie opóźniać zwalniania pamięci.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Zwalnia używane zasoby.
/// </summary>
/// <param name="disposing">czy mamy czas na dokładne sprzątanie?</param>
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
//tutaj trafia to, co _powinniśmy_ posprzątać
}
//a tutaj to, co _musimy_ posprzątać
}
disposed = true;
}

/// <summary>Aby tylko raz zwalniac zasoby.
/// (Dispose może zostać wywołane wielokrotnie.)</summary>
protected bool disposed = false;
#endregion
}

Jeśli nasza klasa dziedziczy z innej, już implementującej IDisposable, to wystarczy ograniczyć się do pokrycia metody protected virtual void Dispose(bool disposing), pamiętając, by wywołać w niej base:Dispose(disposing).


Na koniec ważna uwaga odnośnie kooperacji C++ i .Net. W zarządzanym C++ za pomocą składni ~DummyObject() definiuje się metodę Dispose()! Analogicznie, delete someObject oznacza wywołanie na nim metody Dispose(). Finalizer można zaimplementować poprzez !DummyObject().

Thursday, 11 May 2006

Globalna obsługa wyjątków w .Net

Mały,ale użyteczny kawałek kodu:


AppDomain.CurrentDomain.UnhandledException +=
delegate(object o, UnhandledExceptionEventArgs args)
{Console.WriteLine(args.ExceptionObject.ToString());};

Do czego to służy? Otóż zdarzenie UnhandledException wywoływane jest przy każdym nieobsłużonym przez aplikację wyjątku. Można to wykorzystać by zapisać błąd w dzienniku systemowym czy automatycznie zgłosić go obsłudze klienta / developerom. Nie można w ten sposób usunąć wyjątku - zdarzenie jest wywoływane już po 'wysypaniu' się wątku, w którym wystąpił wyjątek. Jeśli wolisz gotowe rozwiązania, polecam Unhandled Exception Manager z codeproject.

Friday, 21 April 2006

Sunday, 16 April 2006

Ciszej...jeszcze ciszej...nadal nie jest cicho!

Jakiś czas temu komp trafił z leża w piwnicy do mojego pokoju. I w końcu zauważyłem, jak ta bestia wyje. Już nie było mowy o zostawieniu muła na noc, bo spać się po prostu nie dało. Jakoś tak jest, że jak raz się zwróci uwagę na jedną upierdliwość, to potem nie daje ona spokoju, nawet, jeśli wcześniej była niezauważalna... Diagnoza: komputer jest za głośny.

Pierwszy winny został namierzony od razu, bo charczał jak śmiertelnie ranny zwierz. Zatrzymanie go ołówkiem dało cudowny efekt, ale było nieco ryzykowne na dłuższą metę. Wentylator z tyłu obudowy wyleciał, zastąpiony przez dwa nowe, jeden na jego miejsce, drugi z przodu kasty, na dole, żeby zasysał powietrze. Nowe wentylatorki kręcą się wolniej i ciszej, a do tego dopasowują prędkość do temperatury. No i były tanie jak barszcz ;-) (Arctic Cooling Fan PRO TC)

Temperatura spadła o 2ºC (wg lm_sensors), i jest ciszej. Dużo ciszej, ale nadal coś hałasuje... Tym razem - karta graficzna, z malutkim wiatrakiem kręcącym się w szaleńczym tempie. Skoro jest chłodniej, to można zakryć zbędne dziury w obudowie, powinno być ciszej... trochę płyty korkowej i zrobione. Efekt jest... pewien. Można też wywalić niepotrzebną stację dyskietek, zgrzytającą strasznie za każdym razem, gdy Windows sobie o niej przypomni. Hmm, co by tu... Pasywne chłodzenie za drogie, ale można kupić wentylator AC, prawie bezgłośny...

Nowa "zabawka" przyszła dziś z Allegro (sklepy komputerowe nie interesują się już posiadaczami tak archaicznego sprzętu jak mój, sniff sniff). Śrubokręt w rękę i do roboty. Arctic Cooling NV Silencer 1 już działa w moim komputerze, znów jest ciszej... teraz słychać dysk twardy, wentylator na procesorze i.... monitor. Ale głośność spadła o parę klas - sprzętu nie słychać w ogóle przy włączonej muzyce, zagłusza go cicha rozmowa. To wystarczy - do czasu ;-)

Usunięta stacja FDD
Dziura pod NV Silencer 1
Porównanie wielkości
Nagi chipset na karcie graficznej
Arctic Cooling NV Silencer 1
Zajęte dwa sloty PCI

A po głowie chodzi mi złożenie terminalu, całkowicie pozbawionego generujących dźwięk, ruchomych elementów, takich jak np. dysk czy aktywne chłodzenie...

Saturday, 15 April 2006

Krnąbrna elektronika

Godzina 10:81
Godzina 10:82

Dość intrygujący widok, napotkany kilka dni temu w poznańskim tramwaju. Mój zegarek pokazywał 11:22... Dzielny tramwajowy wyświetlacz, nie składając broni z powodu byle błędu konstruktora, wciąż odliczał czas.

Saturday, 8 April 2006

IPX and mounting Novell Netware shares on Gentoo

Start by enabling kernel support for IPX networking and NCP filesystem. For 2.6 kernels (it's simmilar on 2.4), you need to enable the following settings:

Networking -->
Networking options -->
<*> The IPX protocol
File systems -->
Network file systems -->
<*> NCP file system support (to mount NetWare volumes)
[*] Clear remove/delete inhibit when needed
[*] Use NFS namespace if available
[*] Use LONG (OS/2) namespace if available

On 2.6 kernels enabling NCP shows quite a long list of options. As I did not understand their meaning ;-) , I settled for defaults, which work just fine. You may want to enable National Language Support. I gave up on this as I was unable to find a working combination of codepage/iocharset for my local Novell server.


So, recompile (make install && make modules modules_install for gentoo-sources) and reboot. Emerge ncpfs (emerge -av ncpfs). I wanted my machine to automount the Netware share on every boot, thus I added an entry to /etc/fstab:

SERVER/user		/mnt/novell	ncpfs		uid=root,gid=disk,owner=root,passwd=pass,mode=660,volume=VOL1	0 0

Obviously, you have to replace SERVER with your local Novell servername, user with your username, VOL1 with the name of volume you wish to mount (or ommit volume=VOL1 at all to mount the entire server) and pass (in passwd=pass) with your guess_what. Of course, /mnt/novell has to exist.

There are a few caveats to keep in mind if you choose this approach. First and foremost, your password is visible to anyone who can read your fstab. This can be avoided by storing it in a config file, readable only to root (see man ncpfs for details). Second, the mount is fully accessible to anyone in the group disk (to allow only root, drop gid=disk from fstab entry).


Next, you'll want to actually connect to IPX network. I assume that it is working on the very same ethernet connection you use as eth0. Execute ipx_configure --auto_interface=on --auto_primary=on and wait a few seconds for it to settle (it backgrounds immediately, but give it some time to actually connect). Then, examine ifconfig output for lines containing IPX. Their number may vary, depending on number of IPX versions enabled on the server. If all went well, you are now able to mount your Novell share with a simple mount /mnt/novell.


Now, the init scripts. To connect to IPX on boot, add this code into /etc/conf.d/net.eth0:

postup() {
# This function could be used, for example, to register with a
# dynamic DNS service. Another possibility would be to
# send/receive mail once the interface is brought up.
result=`ipx_configure --auto_interface=on --auto_primary=on`

COUNTER=0
while [ $COUNTER -lt 30 -a `ifconfig|grep IPX|wc -l` -lt 2 ]
do
let COUNTER+=1
sleep 1
done

if [ $COUNTER -eq 30 ]
then
return 127
else
return $result
fi
}

The '2' in '-lt 2' is the number of lines, containing IPX, present in ifconfig output after the connection has settled. Change it as fit. '30' in '-lt 30' and '-eq 30' is the allowed timeout for connecting, ie. if IPX is not up after 30 seconds script reports failure.

To properly mount your NCP shares (after the network connection is initialized), gentoo has to recognize them as network filesystems. Thus, add NET_FS_LIST="ncpfs" to both /etc/conf.d/localmount and /etc/conf.d/netmount.

Monday, 3 April 2006

Dostęp do formatki z zewnętrznego wątku

W dokumentacji .Net napisane jest jednoznacznie - jedynym wątkiem, który może wykonywać jakiekolwiek operacje na formatce (System.Windows.Forms.Form) jest ten, który ją utworzył. Pozostałym wolno jedynie wywoływać metody z serii Invoke(), które z kolei zaowocują wykonaniem podanego do nich delegate w wątku formatki. A jak tego po ludzku użyć? Ano tak:


w klasie formatki

//sygnatura funkcji do wywołania z zewnątrz
delegate void SetTextDelegate(string text);
//i sama funkcja
void SetText(string text)
{
if(!InvokeRequired)//czyli wywołanie z wątku formatki
button1.Text = text;
else
Invoke(new SetTextDelegate(SetText), text);//trzeba zmienić wątek
}

natomiast użycie tego w wątku zewnętrznym to po prostu

form1.SetText((i*i).ToString());

Wersja 2.0 platformy umożliwia wykonanie tej samej operacji jeszcze prościej, mianowicie poprzez wywołanie

form1.Invoke((MethodInvoker)delegate { form1.button1.Text = (i * i).ToString(); });

Tutaj niepotrzebne są żadne dodatkowe metody w formatce, po prostu informujemy framework, że ten kawałek kodu ma być wykonany w wątku będącym właścicielem form1. Jedynym haczykiem jest rzutowanie do MethodInvoker. Jest ono konieczne, ponieważ metoda Invoke() jako parametr przyjmuje dowolny System.Delegate... który niestety sam nie jest typu delegate. Bez MethodInvoker metoda anonimowa byłaby rzutowana do System.Delegate, co skończyłoby się błędem kompilacji. A w ten sposób kompilator rozumie o co nam chodzi.

Jeśli już wykorzystywałeś wątki razem z Windows.Forms to pewnie zastanawiasz się, po co ta cała szopka, przecież można odwoływać się do formatki z innego wątku i wszystko działa? Ano działa, ale tylko na Windows XP. W tej wersji platformy .Net wprowadzono niestety zabezpiecznia przed najczęstszymi błędami związanymi z programowaniem wielowątkowym, co prowadzi do tego, iż da się na niej uruchomić kod niepoprawny, który nie zadziała np. na Windows 98 lub mono. Zresztą, w aktualnej (1.1.13.*) implementacji Windows.Forms pod tym ostatnim jest parę innych problemów - np. tworzenie formatek (całkowicie niezależnych!) w kilku różnych wątkach prowadzi do niedeterministycznego zachowania programu i częstych padów...

Sunday, 2 April 2006

Nie dla idiotów?

Komputer znajomej, kupiony okazyjnie w wiadomym sklepie, zaraz po skończeniu się okresu gwarancyjnego zaczął się zawieszać kilka-kilkanaście minut po starcie. Po stwierdzeniu, że problem nie jest związany z softem otworzyliśmy obudowę...
Spalone kondensatory
Tak, tak, spalone są wszyściutkie kondensatory na płycie głównej :-]


Inny klient, ten sam sklep. Dysk, znów po gwarancji, oddany do naprawy do małego sklepu komputerowego. Serwisant zaintrygowany, bo klient oddał do naprawy dysk jako 40GB, a nadruk oznajmia, że pojemność wynosi 80GB. Chwila sprawdzania i wszystko jasne - w dysku jedna głowica z dwóch nie działała od początku, więc został sprzedany jako o połowę mniejszy.


Nie mogę zrobić nic innego jak tylko zgodzić się z hasłem z niemieckiej reklamy Mediamarkt:

"Nie opłaca sie kraść."

Wednesday, 22 March 2006

Update - na lepsze?

Nokia PC Suite po uaktualnieniu pozbyła się niektórych elemenów składowych. Na przykład edytora midi. Żeby było śmieszniej, znaleźć wersję 6.6 (w której jeszcze zawiera Nokia Sound Converter) wcale nie jest tak prosto, z większości stron tylko najnowsze 6.7 można ściągnąć.


Samochód (nie mój, ale czasem się uda pożyczyć) po wymianie na nowy nie pozwala mi wozić plecaka na siedzeniu. Cały czas krzyczy, że pasażer nie ma pasów zapiętych. Dobrze, że przynajmniej skrzynia biegów manualna - ruszanie ze świateł na automacie nie daje żadnej satysfakcji.


Jedyny zarejestrowany dziś przeze mnie pozytywny update to program do wypełniania PITów. Wersja 2004 jest do ściągnięcia za darmo. Wersja 2005, znaczy się aktualna, dostępna tylko z Wyborczą. Albo jako update do 2004 :P


EDIT: warto jeszcze wspomnieć o usprawnieniach w Otwartym Oprogramowaniu. Ponieważ zarówno Open Office jak i KOffice wspierają formaty Open Document, więc jeśli chce się stworzyć arkusz kalkulacyjny zrozumiały dla obu programów, należy go zapisać... jako Microsoftowy xls. W specyfikacji ods brak wytycznych do zapisu funkcji, więc każdy program zapisuje je po swojemu - a cudze odczytuje jako tekst.

Saturday, 18 March 2006

The gentoo way

Wczoraj w końcu mogłem zrobić to, na co miałem od tak dawna ochotę - zmienić OS na moim stanowisku w pracy. Slackware'a miałem zdecydowanie dość, a do tego po moich ostatnich próbach "usprawnienia" system zachowywał się... różnie.


Tym razem sam instalowałem system (poprzednio stanowisko przygotowywał starszy programista), więc mogłem wybrać pasujące mi oprogramowanie. Gentoo wypuściło właśnie nowe płyty, z automatycznym instalatorem, żal nie spróbować ;-)


Gentoo LiveCD 2006.0 bez problemu uruchomiło się w trybie graficznym, z Gnome. Żadnych problemów z przeglądaniem stron spod Firefox'a, jest nawet OpenOfice, jak ktoś bardzo potrzebuje z niego korzystać mając w tle trwającą instalację. Sam graficzny instalator... pomysł dobry, wiele osób boi się Gentoo słysząc o instalacji za pomocą bash'a. Z wykonaniem nieco gorzej - musiałem sobie go odpuścić, bo nie daje sobie rady, gdy coś odbiega od standardu.


A maszyna w firmie nieco odbiega. Tak właściwie, to miał to chyba być serwer Oracle'a, ale potrzeby był desktop dla pracownika i jakoś tak wyszło.... :-D Pentium Prescott HT jest procesorem zupełnie normalnym (chociaż długo trwało, zanim Slack dał się przekonać do tego HT - ale pod nim nawet całej pamięci - 1GB - nie dało się wykorzystać, bo były problemy z włączeniem HIGHMEM). Nieco mniej normalny jest brak karty dźwiękowej i dwie karty graficzne, z tego jedna na PCI (on-board jest Radeon 7200, na PCI - nie PCI Express - Radeon 9200 - bo ten pierwszy, to się podobno do pracy nie nadaje :P ). Kontroler SCSI Adaptec AIC-7902 z dwoma napędami jest najciekawszym elementem konfiguracji. Pod Slackiem wykorzystywany był z niego jeden dysk.


Zaczęło się od uruchomienia macierzy dyskowej: RAID1 na /boot, RAID0 na / i dwie niezależne partycje na swap. Na Gentoo Wiki proces jest przystępnie opisany. Całość ruszyła, dała się zamontować, wystartował automatyczny instalator (jeszcze byłem dobrej myśli), pokrzyczał, że nie może sam zamontować dysków, zaczął działać... Najpierw okazało się, że instalacja jest błyskawiczna (podobno 7.5 minuty) tylko dla domyślnych ustawień. Jeśli ktoś chce np. KDE zamiast Gnome, będzie musiał poczekać dłużej... Chwilę później instalator pogubił się całkowicie i odmówił dalszej pracy.


No nic, trzeba było zatem wrócić do ręcznej działalności. Spod X'ów szło to o tyle wygodniej, że można mieć na jednym ekranie dwie konsole i jeszcze dokumentacja się zmieści, i google jak czegoś potrzeba.


Nareszcie widać możliwości tego sprzętu. Prędkość odczytu z dysku, zmierzona za pomocą hdparm, to 66MBps. Z macierzy - 125MBps. Jak na stację roboczą - monstrum :-D . Zostało mi jeszcze skonfigurowanie X'ów. Ech, gdyby tak dostać drugi monitor...

Tuesday, 14 March 2006

iRiver T10 - epilog

Nieco ponad miesiąc temu narzekałem na odtwarzacz iRiver T10. Nie dało się go używać jako normalnej pamięci masowej USB, wymagał do komunikacji z komputerem Windows Media Player'a 10. Wspominałem też, że taka sytuacja przeszkadza wielu osób. Część z nich była na tyle zdesperowana, by zaryzykować rozwalenie zabawki za kilkaset złotych. No i są efekty.

Powstała strona (już nie istnieje) opisująca dokładnie proces konwersji T10 do trybu pracy urządzenia pamięci masowej (czyli - wpinasz w port i możesz przegrywać pliki, na każdym systemie operacyjnym obsługującym USB). Cała operacja wymaga nieco kombinowania, zalecam też trzymać się dokładnie instrukcji. Na stronie widać np. informację o dwóch nieudanych konwersjach, a w ich szczegółach można doczytać, że wynikały one właśnie z niezastosowania się do przepisu (firmware hybrydowy w wersji Non-Pure wgrany do odtwarzacza Pure, czyli bez radia).

Po zakończonej konwersji odtwarzacz identyfikuje się jako australijski, z radiem ;-) , które niestety nie działa (brak dźwięku - nic zresztą dziwnego, skoro w środku nie ma chipa za nie odpowiedzialnego). Nie powoduje natomiast żadnych problemów - to ważne, bo w T20 próba użycia radia na odtwarzaczu Pure (czyli bez odpowiedniego chipa) skończyła się zniszceniem playera. Cała reszta opcji działa stabilnie. Dodatkowym plusem jest usunięcie ograniczenia głośności - teraz już nikt nie zabroni mi niszczyć sobie słuchu :-P. Warto też zaznaczyć, że update'y firmware'u iRiver wypuszcza szybciej dla wersji UMS.

Moje osobiste wrażenie, nie poparte dokładnymi testami - transfer danych w trybie UMS odbywa się szybciej niż wcześniej przez MTP. Odtwarzacz wreszcie nie zrywa połączenia z komputerem.

UPDATE: porówanie prędkości iAudio 5 i iRiver T10 UMS. iRiver jest pojemniejszy o 30MB, ale prawie dwukrotnie wolniejszy! [niestety, darmowy hosting zżarł screenshota]

UPDATE 2: iRiver udostępnia oficjalnie narzędzia do konwersji MTP<->UMS.

Friday, 3 February 2006

Singleton w C#

Chyba najczęściej stosowany wzorzec projektowy. Bardzo często też implementowany błędnie - większość przykładów dostępnych w sieci nie bierze zupełnie pod uwagę wielowątkowości. Przykład na MSDN też nie jest idealny. Dobra, najpierw działający kod:


/// <summary></summary>
public sealed class Singleton
{
#region Singleton
/// <summary>ukryty konstruktor</summary>
private Singleton()
{}

/// <value>Dostep do instancji singletona</value>
public static Singleton Instance
{ get { return InstaceHolder.instance; } }

/// <summary>klasa wewnętrzna przechowująca instancję</summary>
class InstaceHolder
{
/// <summary>konstruktor statyczny,
/// by kompilator NIE oznaczyl klasy jako BeforeFieldInit</summary>
static InstaceHolder() {}

/// <summary>instancja singletona</summary>
internal static readonly Singleton instance = new Singleton();
}
#endregion
}

I po kolei, o co w tym chodzi. Sama klasa oznaczona jako sealed, czyli nie można z niej dziedziczyć. Nie chcemy, by ktos stworzył klasę potomną, która będzie pozwalała na utworzenie wielu instancji. Funkcjonalność zbliżoną do polimorfizmu może nam łatwo dostarczyć np. wzorzec State.


Konstruktor prywatny, żeby nikt nam "na boku" nie utworzył instancji klasy.


Własność publiczna Instance - jedyny dostęp do singletona. Metody niestatyczne będzie się w nim wywoływać przez Singleton.Instance.MojaMetoda();


Klasa wewnętrza pozwala nam na leniwe, czyli opóźnione utworzenie instancji. Dopiero pierwsze odwołanie do Singleton.Instance utworzy obiekt. Kostruktor statyczny w InstanceHolder wymusza na kompilatorze, by nie oznaczał klasy jako BeforeFieldInit. To znaczy, że pola statyczne zostaną zainicjowane dopiero przy pierwszym odwołaniu do klasy (dostęp do statycznego pola/metody lub utworzenie instancji), a nie "na zapas". Uwaga - chodzi o pola/metody klasy InstanceHolder, dostęp do statycznych pól czy metod Singletona nie spowoduje zainicjalizowania go.


Inicjalizacja singletona powinna trafić do prywatnego konstruktora, a nie statycznego. W ogóle - ze statycznymi konstruktorami lepiej ostrożnie. InstanceHolder.instance mógłbym zainicjalizować w static InstaceHolder(), ne? Haczyk znajduje się w specyfikacji języka C#.

The static constructor for a class executes at most once in a given application domain.

Najwyżej raz oznacza, że może nie zostać wykonany ani razu. Tak się dzieje np. w niektórych wersjach Mono.



Kod pochodzi z yoda.arachsys.com



UPDATE: na MSDN znalazłem poprawny i elegancki kod singletona, z innym podejściem niż pokazane powyżej.

Monday, 30 January 2006

Kanji, katakana etc.

Z zupełnie nieznanych dla mnie przyczyn, spora część moich najbliższych znajomych zanieczyszcza swoje przemyślenia dużą ilością znaczków spoza alfabetu łacińskiego. Jeszcze żeby ograniczali się do względnie małej (kilkadziesiąt glifów, jeśli się nie mylę) katakany. Ale jest pełen przekrój przez alfabety japońskie, znaki chińskie, niedługo pewnie ktoś zacznie dla sportu pisać po koreańsku…


Na pytanie jakiej czcionki potrzebuję, by nie widzieć wielokrotnych '?' w tekście ich stron otrzymałem standardową odpowiedź WFM. No tak, jak komuś system instalował informatyk w Chinach, to nie ma problemu z chińskimi czcionkami. Potem pojawiła się propozycja, abym z 'Panelu Sterowania -> Opcje Regionalne -> Języki' doinstalował obsługę języków wschodnioazjatyckich… Miałem mały problem - pod KDE nie ma Panelu Sterowania ;-) . A w Windows taka instalka waży dodatkowe 230MB. I u mnie, z nieznanych mi przyczyn, nie działa.


Na szczęscie Microsoft przygotował czcionkę Arial Unicode, dołączaną do Windows XP oraz Office'a 2000. Zaraz, u mnie znów jej nie ma. W legalnym Windows... chyba zbyt mocno "zoptymalizowałem" płytę instalacyjną. Dla podobnie zagubionych, którym Arial Unicode prawnie się należy, podpowiedź: plik nazywa się arialuni.ttf, waży ok. 23MB, i jest łatwy do znalezienia w sieci. Czcionka zawiera glify dla całej tablicy Unicode, pełen zestaw znaków chińskich, japońskich, koreańskich etc. Zainstalować i zapomnieć.


Jeśli używasz linux'a, pewnie nie będziesz kupować Windows XP tylko by dostać czcionki. Alternatywy OS pod gentoo pojawią się w systemie po wykonaniu polecenia


emerge media-fonts/kochi-substitute media-fonts/arphicfonts media-fonts/baekmuk-fonts

Pierwsza czcionka to znaki japońskie, druga chińskie a trzecia koreańskie. [info znalezione na Gentoo Forums]

Saturday, 28 January 2006

Microsoft - Plays For Sure?

Kupiłem w piątek czwarty odtwarzacz mp3. Pierwszy, jeszcze przed letnimi wakacjami, był Creative MuVo V200 512MB . Wybrany, ponieważ:

  • Creative ma reputację firmy znającej się na dźwięku komputerowym
  • flash (mały, lekki, dłużej działa na bateriach, jak spadnie nic mu się nie stanie, nie szkodzi mu bieganie/podskakiwanie/jazda na rowerze)
  • wpina się jako pendrive do dowolnego komputera z USB

Creative po dwóch miesiącach zaczął się wieszać. Odtwarzał, nagle przestawał, nie reagował na nic i pomagał mu tylko format. Serwis nic nie wymyślił, dostałem pieniądze z powrotem. Na całe szczęście. Shin'a MuVo, kupiony miesiąc wcześniej, działa, ale ze względu na nieprzemyślaną konstrukcję wtyczki USB - trzeba go było skleić taśmą, bo po prostu się rozpadł.

Kolejny zakup był przemyślany dokładniej. Do Creative'a nie miałem większych zastrzeżeń, ale po przebiciu się przez sporo recenzji na różnych stronach - wybór padł na iAudio. Snobizm trochę ;-) , ale iAudio i iRiver wszędzie chwalone są za najlepszą jakość dźwięku wśród odtwarzaczy. Oczywiście, kryteria stare nadal obowiązywały, a że pieniędzy miałem nieco więcej, zdecydowałem się na iAudio 5 1GB. Dodatkowo, nagrywając dźwięk (mikrofon "zbiera" jak porządny dyktafon) potrafi go w czasie rzeczywistym kompresować do mp3. Zastanawiałem się też nad iAudio U2 1GB, z tą samą elektroniką, ale akumulatorem wewnętrznym (odtwarzacz jest dzięki temu mniejszy), jednak przeważyła wygoda - wychodząc z domu mogę zabrać ze sobą dodatkowe baterie i wymienić, kiedy stare się wyczerpią. A odtwarza na jednej baterii jakieś 20 godzin.

Na gwiazdkę brat chciał tez odtwarzacz. Dostał taki sam, wersja 512MB. No i jeszcze siostra...

Siostra wymyśliła sobie czerwony. Koniecznie, żaden inny, nie metaliczny czerwony, wiśniowy, koniecznie musi być czerwony. Ugh... iRiver T10 512MB spodobał się. Wczoraj odebrałem go w sklepie, przyniosłem do domu... Działa. Dźwięk jak to iRiver - jakość bardzo dobra, nieco lepiej niż moje iAudio - ale to kwestia słuchawek, na takich samych - jakość jak dla mnie identyczna. Zdecydowanie lepsza, niż z wieży stojącej w pokoju ;-) Jest jeden haczyk, dla mojej siostry (na razie) niezauważalny.

iRiver T10 ze znaczkiem "Microsoft Plays For Sure" wymaga Windows Media Player'a 10. Koniec. Nie da się go podpiąć do komputera z Windows 98, nie ma mowy o żadnym Linuksie czy MacOS (chociaż podobno jakiś soft do obsługi aparatów fotograficznych potrafi wgrać na niego pliki). Nie jest też widoczny jako dysk, tylko jako MTP Device. Można, niby, wgrywać muzykę przez Explorer'a - ale nie np. Total Commander'em, bo nie odtwarzacz nie jest rozpoznawany jako napęd! Co więcej - jedyną zalecaną metoda wgrywania muzyki jest przenoszenie jej poprzez WMP 10. I to nie żart, mp3 wgrywane inaczej potrafią np. skakać przy odtwarzaniu czy się zacinać.

Jest wersja T10 oznaczana jako UMS, widoczna po wpięciu jako normalny napęd. Niestety, do kupienia tylko w Korei i okolicach. Na forum Mystic River jest sporo tematów z pytaniami o możliwość podmiany firmware'u wersji MTP na UMS. Jak na razie bez efektów.

Konkluzje? Unikać jak ognia odtwarzaczy z logo "Microsoft Plays For Sure". Ponieważ na pewno NIE działają bez Windows Media Player 10.

PlaysForSure logo

Thursday, 26 January 2006

Access Point

Planuję wyprowadzkę komputera z jego leża w piwnicy na górę, do mieszkania. Problem w tym, że o ile rodzinka nie miała nic przeciwko wierceniu dziur wielkości kciuka w ścianach w piwnicy (musiała przejść wtyczka RJ-11 :-) ), to raczej nie zgodzą się na robienie takich dziur w mieszkaniu, przez dwa piętra. No cóż, skoro nie można położyć przewodów, pozostaje łączność bezprzewodowa :-]

Zacząłem od sprawdzenia na pożyczonym sprzęcie, czy będzie wszystko działać na potrzebną mi odległość. Styka. Krok kolejny: do sklepu, wybrać jakiś sensowny AP z modemem DSL. I tutaj pojawił się problem. W interesującym mnie przedziale cenowym wybór jest dość spory - jak dla mnie zbyt spory ;-)

Po wstępnym przesiewie zostały

Wszystkie w tej samej cenie (380 złotych brutto), właściwe te same możliwości. D-Link polecany przez znajomego, który już ma sprzęt tej firmy. Linksys ma z kolei bardzo dobre recenzje w sklepie komputronika, i ku niemu bym się skłaniał. Edimax, dla mnie zupełny noname, interesujący jest ze względu na obsługę standardu 802.11g+, czyli transfer (teoretycznie) rzędu 108Mbps oraz WPA oprócz złamanego już WEP. I masz babo placek. Co do cholery wybrać?

Po fakcie: niestety, kupiłem D-Link'a G604T

Wednesday, 25 January 2006

Toshiba Satellite 2140 - tam i z powrotem

Znajoma narzekała ostatnio na problemy z laptopem. Że hałasuje, grzeje się i wygląda, jakby miał wybuchnąć. Na słuch - rozwalone chłodzenie? Dziś po zajęciach miałem ją odwiedzić i obejrzeć. Zabrałem mój uniwersalny śrubokręt™ i byłem gotów. Całe szczęście, że podczepił się jeszcze PiBis, zaopatrzony w zestaw wkrętaków zegarmistrzowskich, wielgachnym śrubokrętem wiele bym nie zdziałał. Ale na usprawiedliwienie - pozwala zrobić wszystko przy kompie stacjonarnym. Moja wina, że laptopy takie małe?


Na miejscu - Toshiba nie hałasuje. Oczywiście, przyszedł serwis ;-) to wszystko działa. Ale nie odpuściliśmy, żaden z nas jeszcze laptopa nie rozkręcał, mieliśmy taką okazję przepuścić? Po wykręceniu wszystkich widocznych (i nie - 4 były chowane pod akumulatorem) śrubek obudowa nadal nie dawała się otworzyć. Ja poszedłem zasięgnąć rady wyroczni, PiBis kombinbował. Był szybszy - ostatnie dwie śrubki okazały się ukryte pod płytką z przyciskiem 'Power'. Potem nastąpiła chwila wahania - czy po odczepieniu kabli łączących monitor/klawiaturę z resztą wnętrzności damy radę je zmonotowac ponownie? Zaryzykowaliśmy, płyta główna na wierzchu. Jeszcze tylko wymontować elegancki heatpipe i wentylator dał się wyjąć do czyszczenia. Wtedy w końcu ktoś zasugerował, że gdyby od początku robić zdjęcia, to potem byłoby łatwiej złożyć całość z powrotem :-] No, mądry Polak po szkodzie. Całe szczęście, że w Satellite każdy slot na śrubkę był elegancko opisany - bardzo dobry pomysł. Ale przynajmniej mamy dokumentację techniczną jak złożyć Toshibę Satellite 2140 z części :-D


Wymontowany monitor
Wymontowany monitor


Obudowa od spodu
Obudowa od spodu


Wszystkie wykręcone śrubki
Wszystkie wykręcone śrubki


Płyta główna bez wentylatora
Płyta główna bez wentylatora


Klawiatura, monitor, wentylator i heatpipe
Klawiatura, monitor, wentylator i heatpipe


Precyzyjne narzędzie każdego zegarmistrza
Precyzyjne narzędzie każdego zegarmistrza


Przedmuchiwanie wentylatora za pomocą odkurzacza
Przedmuchiwanie wentylatora za pomocą odkurzacza


Wentylator wraca na miejsce
Wentylator wraca na miejsce


Osłonka na CPU...
Osłonka na CPU...


Jeszcze tylko klawiatura
Jeszcze tylko klawiatura


Już wszystko podłączone
Już wszystko podłączone


Cztery połączenia, których się baliśmy
Cztery połączenia, których się baliśmy


Przed skręceniem warto sprawdzić, czy wszystko działa
Przed skręceniem warto sprawdzić, czy wszystko działa


To są właśnie te ukryte mocowania
To są właśnie te ukryte mocowania


A tak się je odczepia
A tak się je odczepia


Wkręcenie ostatniej śrubki
Wkręcenie ostatniej śrubki


Obudowa montowana jest 20 śrubkami!
Obudowa montowana jest 20 śrubkami!


Jeśli ktoś wie, co to za złącze, proszę o info...
Jeśli ktoś wie, co to za złącze, proszę o info...


I już po wszystkim.
I już po wszystkim.

Monday, 23 January 2006

Mmmm... upgrades.

Drobne poprawki na joggu. Po kolei:



  • Google Analytics, z hack'ami wziętymi od hao i riddle. Nareszcie koniec z moim pięknym inaczej licznikiem własnej roboty.

  • Feed RSS z newsami przez FeedBurner. Dalej w duchu zbierania statystyk. Korzystających z feed'a tutaj lub na uch0 proszę o uaktualnienie odnośników.

  • Ludzkie czcionki, w końcu miałem dość nieczytelnej Book Antiqua. Którą bardzo lubię - ale na papierze.


Za jakiś czas mam zamiar zrobić nowy layout, ten nie najlepiej świadczy o moich umiejętnościach :-/ No ale to po egzaminie inżynierskim.

Tuesday, 17 January 2006

Jabber od google wychodzi w świat

Googlowe serwery XMPP w końcu otwierają się na świat. Ruszyło s2s. Czyli z konta na google można - w końcu - porozmiawiać z ok. 10 milionami innych użytkowników jabbera. Jak zalogować się na konto na gmail z Konnekta? Potrzebny jest mały przekręt ;-) pomysłu Olórina. A zatem: uruchom "notepad %WINDIR%\system32\drivers\etc\hosts" i dodaj do pliku linijkę "216.239.37.125 gmail.com". kJabbera należy skonfigurować tak:

gmail i Konnekt

Uaktualnienie: google ustawiło na serwerze odpowiedź DNS SRV, używane do mapowania nazwy użytkownika na adres serwera. W skrócie: hack nie jest potrzebny, wystarczy ustawić to co na screenie :-)

Saturday, 14 January 2006

Pandora.com

Pandora, bardzo fajne "radio" internetowe, potrafiące się uczyć naszych preferencji i inteligentnie sugerujące nowości. Zabawka polecona wczoraj przez siję, dziś pokazała jeszcze jedną miłą cechę.



Konnekt nagle zaalarmował mnie, że katalog %temp% mocno się rozrósł... Otóż Pandora wspaniałomyślnie zachowuje nam wszystkie odtworzone piosenki na dysku. Dokładniej, to w folderze %temp% powstaje podkatalog plugtmp-x (x to liczba), a w nim kolejne pliki access-x. Wystarczy dorzucić im rozszerzenie .mp3 i ... słuchać :P

Thursday, 12 January 2006

Automatyczne numerowanie build'ów w Visual Studio 2003/2005

Jeśli przesiadłeś się z produktów Borlanda, pewnie dziwi Cię brak tej prostej możliwości. W Builderze wystarczyło zaznaczyć jednego checkbox'a i — voila! — każdy kolejny build programu miał podbity numer wersji.


Visual Studio nie oferuje takiej opcji. Może dlatego, że w głównej dla niego platformie - .Net - wystarczy wpisanie * zamiast części numeru wersji, by kompilator sam go uzupełniał? Problem jest ze zwykłymi binarkami, dla których numer wersji ustawiany jest na podstawie pliku *.rc .


Rozwiązanie jest kilkuetapowe. Najpierw trzeba dodać do projektu plik .rc, jeśli jeszcze takiego nie ma (panel 'Solution Explorer', RMB na projekcie, 'Add->New Item', 'Resource File'), po dodaniu utworzyć numer wersji (panel 'Resource View', RMB, 'Add->Resource', 'Version'). Kiedy projekt już posiada odpowiedni plik zasobów, należy otworzyć go w edytorze tekstowym (panel 'Solution Explorer', RMB na pliku *.rc, 'View code') i podmienić kod

VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "041504b0"
BEGIN
VALUE "FileDescription", "dxfgdfgd Application"
VALUE "FileVersion", "1, 0, 0, 1"
VALUE "InternalName", "dxfgdfgd"
VALUE "LegalCopyright", "Copyright (C) 2006"
VALUE "OriginalFilename", "dxfgdfgd.exe"
VALUE "ProductName", " dxfgdfgd Application"
VALUE "ProductVersion", "1, 0, 0, 1"
END
END
BLOCK "VarFileInfo"

na

VS_VERSION_INFO VERSIONINFO
FILEVERSION FILEVER
PRODUCTVERSION PRODUCTVER
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
#include "VersionNo.h"
BEGIN
BLOCK "041504b0"
BEGIN
VALUE "FileDescription", "dxfgdfgd Application"
VALUE "FileVersion", STRFILEVER
VALUE "InternalName", "dxfgdfgd"
VALUE "LegalCopyright", "Copyright (C) 2006"
VALUE "OriginalFilename", "dxfgdfgd.exe"
VALUE "ProductName", " dxfgdfgd Application"
VALUE "ProductVersion", STRPRODUCTVER
END
END
BLOCK "VarFileInfo"

Teraz do projektu trzeba dodać plik VersionNo.h (panel 'Solution Explorer', RMB na projekcie, 'Add->New Item', 'Code->Header File'), w którym zdefiniowane będą użyte przed chwilą stałe. Powinien się w nim znaleźć następujący kod:

#define FILEVER  1,0,0,00001
#define PRODUCTVER 1,0,0,00001
#define STRFILEVER "1, 0, 0, 00001\0"
#define STRPRODUCTVER "1, 0, 0, 00001\0"

Ostatnim krokiem jest skłonienie IDE do uaktualniania tej informacji po każdym zbudowaniu projektu. W tym celu albo piszesz własny skrypt/program/cokolwiek, albo używasz mojego Autoincrement. Plik należy umieścić w katalogu projektu i włączyć w opcjach uruchomienie go każdorazowo po zbudowaniu projektu ('Project->Properties','Configuration->Build Events->Post-build Event', w 'Command line' należy wpisać 'Autoincrement.exe VersionNo.h'). Uff, koniec. Pamiętaj, by wybrać odpowienią konfigurację ustawiając 'Build Events'.