TechLife devBlog

Bootstrap - HTML-owe klocki Lego

Kodowanie Techblog 16 kwietnia 2012 o 22:18:55 | ☍ trackback

W lipcu narzekałem, że webdeveloperom brakuje klocków/struktur z których mogliby łatwo budować aplikacje, podobnie jak buduje się desktopowe interfejsy graficzne korzystając z różnych bibliotek zawierających zdefiniowane elementy i kontrolki. Dzisiaj spokojnie mogę powiedzieć, że HTML również doczekał tych wspaniałych czasów.

Bootstrap - przykład

Od kilku miesięcy obserwowałem rozwój projektu Bootstrap (od Twittera). Bootstrap to ogromny zbiór najczęściej stosowanych HTML-owych struktur, które zostały w bardzo estetyczny sposób ostylowane oraz dodano JavaScript do sterowania interaktywnymi elementami tj. okna modalne, taby, rozwijane menu, dymki z podpowiedziami, komunikaty i wiele innych.

Początkowo dostarczanych elementów było względnie mało. Do tego zastosowanie Bootstrapa było bardzo inwazyjne, ponieważ automatycznie stylował nam różne elementy, które niekoniecznie chcieliśmy mieć ostylowane w ten sposób. Jednak przez te kilka miesięcy odwalono kawał dobrej roboty. Liczba elementów urosła już do takiej ilości, że pozwala spokojnie budować bardzo zaawansowane aplikacje bez konieczności tworzenia własnych struktur. Zmieniła się również polityka stylowania i teraz większości elementów trzeba nadać klasę (np. tabeli należy nadać klasę table) aby skorzystać ze styli Bootstrapa.

Komponenty

Jak przystało na porządne pudełko z narzędziami, w Boostrapie znajdziemy też 12 kolumnowy CSS grid (stały lub płynny), oraz zestaw styli CSS3 służący do ładnego wyświetlania całości na różnej wielkości ekranach (Responsive design).

Grid

Korzystałem już z Bootstrapa w kilku aplikacjach i okazał się bardzo wygodny w użyciu. Bez problemu mogłem się skupić na mechanizmach zamiast na warstwie prezentacyjnej a mimo to wynikowa aplikacja była bardzo estetyczna i odznaczała się wysokim współczynnikiem eye candy. Do tego wszystkiego można dodać, że Bootstrap umożliwia wygenerowanie sobie spersonalizowanej paczki, zawierającej tylko potrzebne nam elementy a nawet przebudowany na nasze potrzeby CSS, ponieważ Boostrap generuje go korzystając z dobrodziejstw LESS.

Generator

Używa się tego tak dobrze, że całkiem prawdopodobne jest, że niedługo internet zostanie zalany podobnie wyglądającymi stronami i aplikacjami. Prosty przykład:

Przykładowa strona

Na stronie builtwithbootstrap.com można zobaczyć już całą gamę stron zbudowanych z pomocą Bootstrapa. Jest jednak światełko w tunelu. Powstała strona bootswatch.com oferująca różnorodne skórki dla elementów Bootstrapa.

Przykład skórki
Przykład skórki

Oczywiście Bootstrap to nie jedyny projekt tego typu. Warto przyjrzeć się również HTML KickStart.

Kick Start

Czasy gdy programiści tworzyli sraczkowate interfejsy oparte na tabelkach rodem z lat '90 oficjalnie uważam za zamknięte. Miłego kodowania!

Django i shortcodes

Django Kodowanie Techblog 05 lutego 2012 o 23:21:27 | ☍ trackback

Kilka miesięcy temu pytałem #django-wców na blipie o możliwość wstawiania do treści słów kluczowych, które później byłyby zamieniane na różne dziwne rzeczy. Nikt mi wtedy nie odpowiedział, więc pewnie sprawa nie jest jeszcze zbyt popularna. Ostatnio jednak znalazłem rozwiązanie mojego problemu. Słowo klucz - shortcodes.

Shortcodes to znane przede wszystkim z WordPress-a pseudo tagi, za pomocą których możemy wstawiać w dowolne miejsca w tekście różnego rodzaju obiekty. Np. wykorzystując taki kod:

[gallery id="123" size="medium"]

możemy osadzić galerię pomiędzy dwoma paragrafami tekstu. Odpowiednia aplikacja istnieje też dla Django - django-shortcodes. Instalacja jest bardzo prosta i sprowadza się do kilku kroków:


  1. do katalogu z naszym projektem kopiujemy folder shortcodes

  2. w settings.py dodajemy shortcodes do INSTALLED_APPS

  3. w szablonie, w którym chcemy użyć filtra dodajemy {% load shortcodes_filters %}

  4. do zmiennej, która zawiera nasze słowa kluczowe dodajemy filtr shortcodes np. {{ news.tresc|shortcodes|safe }}

Zmienna zawierająca słowa kluczowe nie musi być wyłącznie tekstem. Może być to HTML wyprodukowany przez jakiś edytor np. TinyMCE. Trzeba tylko pamiętać, żeby najpierw dokonać podmiany słów kluczowych a dopiero później wypluć HTML (kolejność filtrów).

Najważniejszą częścią aplikacji django-shortcodes są parsery znajdujące się w katalogu parsers (domyślnie tylko youtube)

parsers

To one zawierają definicje słów kluczowych, oraz ich parametry. Nazwa pliku parsera definiuje też nazwę słowa kluczowego.

Ok, czas na przykłady, np. YouTube (trochę zmodyfikowany):

YouTube - TinyMCE

Rezultat:

YouTube - podgląd

Napisałem też prosty parser do wstawiania mp3 z pomocą Googlowego odtwarzacza:

[mp3 adres=http://www.luzuj.com/pb/mp3/piwo.mp3]

Odtwarzacz mp3

czy parser osadzający galerię zdjęć:

[galeria numer=1]

Galeria zdjęć

Oczywiście łatwo można też modyfikować wstawiane treści za pomocą różnych parametrów np.

[youtube adres=http://youtu.be/d9NF2edxy-M szerokosc=600 wysokosc=400]

lub

[galeria numer=1 tytul=brak]

Naturalnie to tylko banalne przykłady. Jednak najważniejsze jest to, że każdy może je łatwo dostosować do swoich wymagań i wykorzystać do wstawiania ankiet, wykresów, plików, prezentacji, statystyk czy różnych innych treści, które w normalnych przypadkach wymagałyby użycia skomplikowanego (często generowanego) HTML-a, który byłby kłopotliwy dla różnych edytorów typu TinyMCE.

Generator filmowych miniaturek

Kodowanie Linux Software Techblog 11 stycznia 2012 o 21:59:22 | ☍ trackback

Często zamieszczając na stronie streszczenie jakiegoś filmu brakowało mi narzędzia, które było by w stanie zamiast zrzutu pojedynczej klatki wygenerować mi miniaturkę składającą się przynajmniej z 4 zrzutów pochodzących z różnych części filmu. W repozytorium znalazłem tylko mplayer-snapshot, ale nijak nie działało. Ponieważ potrzebowałem tylko 4 zrzuty szybko skleiłem prosty skrypt Basha wykorzystujący FFMpegThumbnailer (powinien być w każdym repo) do robienia zrzutów i montage (pakiet imagemagick) do ich klejenia.

#!/bin/sh

usage()
{
cat << EOF
usage: $0 [options] -i MOVIE-FILE

OPTIONS:
   -h       show this message
   -i       input movie file
   -o       output JPG file name
   -a       percentage or absolute time hh:mm:ss, default 20
   -b       percentage or absolute time hh:mm:ss, default 40
   -c       percentage or absolute time hh:mm:ss, default 60
   -d       percentage or absolute time hh:mm:ss, default 80
   -n       number of columns
EOF
}

FILE=
OUT=
COLUMNS=2
T1=20
T2=40
T3=60
T4=80

while getopts "hi:o:a:b:c:d:n:" OPTION
do
     case $OPTION in
         h)
             usage
             exit 1
             ;;
         i)
             FILE=$OPTARG
             OUT=${OPTARG}.jpg
             ;;
         o)
             OUT=$OPTARG
             ;;
         a)
             T1=$OPTARG
             ;;
         b)
             T2=$OPTARG
             ;;
         c)
             T3=$OPTARG
             ;;
         d)
             T4=$OPTARG
             ;;
         n)
             COLUMNS=$OPTARG
             ;;
         ?)
             usage
             exit
             ;;
     esac
done

if [[ -z $FILE ]]
then
    usage
    exit 1
else
    ffmpegthumbnailer -t $T1 -s 400 -o /tmp/thumb-1.jpg -i $FILE
    ffmpegthumbnailer -t $T2 -s 400 -o /tmp/thumb-2.jpg -i $FILE
    ffmpegthumbnailer -t $T3 -s 400 -o /tmp/thumb-3.jpg -i $FILE
    ffmpegthumbnailer -t $T4 -s 400 -o /tmp/thumb-4.jpg -i $FILE

    montage -mode concatenate -tile ${COLUMNS}x -adjoin /tmp/thumb*.jpg $OUT
    rm /tmp/thumb*.jpg
fi

Dla przykładu weźmy trailer Hobbita. Po pobraniu go na dysk i zapisaniu jako hobbit.flv wystarczy odpalić skrypt i wskazać plik:

movie-thumbnails.sh -i hobbit.flv

Skrypt powinien wypluć plik o nazwie hobbit.flv.jpg:

Jak to jednak przy generowaniu miniaturek bywa czasami zdarza się złapać jakaś niepożądana klatkę. Aby ją wymienić należy wskazać którą z czterech klatek wymieniamy (a,b,c czy d) oraz podać procentowo lub dokładnie (np. 00:03:28) czas filmu, z którego ma zostać pobrana.

Domyślnie:

a - 20%
b - 40%
c - 60%
d - 80%

Czyli jeżeli chcemy wymienić np. miniaturkę 2 na coś jaśniejszego wystarczy zrobić:

movie-thumbnails.sh -i hobbit.flv -b 27

wynik:

Używając parametru -n możemy sterować też ilością kolumn:

movie-thumbnails.sh -i hobbit.flv -n 1

movie-thumbnails.sh -i hobbit.flv -n 4

Na koniec parametrem -o sterujemy nazwą pliku wyjściowego

movie-thumbnails.sh -i hobbit.flv -o hobbit.jpg

Linki

[CSS] Pionowo czy poziomo?

Internet Kodowanie Techblog 25 listopada 2011 o 23:51:19 | ☍ trackback

Nie będzie to flame, chciałem przedstawić Wam tylko mój punk widzenia. Do chwili zatrudnienia się w Firmie byłem święcie przekonany, że jedynym słusznym formatowaniem jest formatowanie pionowe, gdzie elegancko mamy podane jak na tacy wszystkie atrybuty.

poziomo

W Firmie przyszedł czas bardzo intensywnego kodowania. Często pracowałem z dużymi arkuszami stylów, których ciągłe przewijanie stawało się bardzo niewygodne. Nierzadko trzeba było też wrócić do poprzednich projektów i szybko poprawić jakieś drobne niedociągnięcia. Dopiero wtedy uświadomiłem sobie, że w CSS-ie jest coś ważniejszego niż atrybuty i ich wartości. Najważniejszą rzeczą są selektory! Dopiero zrozumienie tej kwestii pozwoliło mi inaczej spojrzeć na elegancję poziomego formatowania.

poziomo

Rzeczą oczywistą jest to, że najpierw wyszukujemy obiekt, który chcemy zmodyfikować a następnie dodajemy mu kolor tła czy zmieniamy margines. Priorytetem jest więc szybkie odnajdywanie selektorów a później dopisanie czy odnalezienie potrzebnego atrybutu jest już dość proste, mimo że wszystkie atrybuty są w jednej linii. IMHO o wiele więcej czasu zajmuje znalezienie odpowiedniego selektora w rozciągniętym pliku niż odpowiedniego atrybutu w liniowym zapisie.

Aby jeszcze bardziej ułatwić sobie sprawę należy trzymać się prostej zasady: najpierw definiujemy box model: display, width, height, float, margin, padding (najlepiej zachować taką kolejność) a później całą resztę (position, background, color, font-size itp). Trzymając się tej zasady od razu wiemy czy szukamy atrybutu z końca czy początku linii.

Jeszcze raz poglądowo. Formatowanie pionowe - mało widać, dużo szukania

pionowo

Formatowanie poziome - szybkie odnajdywanie selektorów i (trzymając się zasady) w miarę szybkie odnajdywanie atrybutów.

poziomo

Mikro struktury HTML

Kodowanie Techblog 02 lipca 2011 o 19:16:49 | ☍ trackback

Z doświadczenia wiem, że najlepsze rozwiązania, to takie, do których doszedłem sam ewolucyjnie. Wtedy najlepiej rozumiem do czego one są i dlaczego tak a nie inaczej działają. Jest to o wiele lepsza metoda niż przyjmowanie nawyków innych osób, których sami do końca nie rozumiemy. Dlatego najczęściej nie stosuję różnych narzędzi tylko dlatego, że inni je polecają ale czekam spokojnie aż sam dojdę do punktu, w którym uznam, że dokładnie takiego narzędzia potrzebuję. Swoją drogą w ten sposób uwalniam się od stosowania przeróżnych udziwnień, które w rzeczywistości nie są przydatne / efektywne / nie do końca wiadomo w czym pomocne.

Po kilku dobrych latach kodowania stron coraz wyraźniej zaczynam dostrzegać co jest potrzebne do szybkiego i sprawnego budowania interfejsów www -- mikro struktury. HTML ma to do siebie, że jest dość "niskopoziomowy", dzięki czemu można za jego pomocą poskładać do kupy różne cuda. Kiedy jednak chcemy szybko zbudować interfejs składający się z często powtarzających się elementów (list, przełączników, kontrolek, pasków postępu, przycisków, komunikatów, okien dialogowych itp) odkrywamy nagle, że tak na prawdę brak nam widgetów czy kontrolek znanych z różnych środowisk graficznych. Za każdym razem budujemy je na nowo z "niskopoziomowych" klocków HTML-a zamiast po prostu wziąć i wykorzystać gotowe struktury. Coś jak np. interfejsy dla telefonów:

Android GUI

Jednym słowem chodzi mi o coś w rodzaju połączenia mikroformatów z Zen Garden. Jeżeli stworzymy odpowiednio elastyczną strukturę uzyskamy możliwość stylowania jej CSS-em na wiele różnych sposobów. Weźmy na przykład prostą listę:

<ul>
    <li>Element 1</li>
    <li>Element 2</li>
    <li>Element 3</li>
    <li>Element 4</li>
</ul>

Jeżeli zamienimy ją w uniwersalną strukturę:

<div class="vertical-list">
    <div class="outer">
        <div class="inner">
            <ul>
                <li class="first">
                    <span class="line">Element 1</span>
                </li>
                <li>
                    <span class="line">Element 2</span>
                </li>
                <li>
                    <span class="line">Element 3</span>
                </li>
                <li class="last">
                    <span class="line">Element 4</span>
                </li>
            </ul>
        </div>
    </div>
</div>

Otrzymujemy obiekt, który może uzyskać praktycznie nieskończenie wiele kształtów. Na dodatek biorąc tą samą strukturę i zmieniając nazwę klasy z vertical-list na horizontal-list możemy uzyskać listę poziomą. Oczywiście każda struktura może mieć kilka wariantów wyglądu np vertical-list-v2.

Używając takich struktur w swoim kodzie, dostosowanie ich do nowego projektu mogło by się ograniczyć wyłącznie do podłączenia innego arkusza stylującego struktury. Podobnie jak jest to rozwiązane w przypadku galerii jQuery UI.

Nie bardzo chce mi się wierzyć, że nikt przede mną jeszcze na to nie wpadł, więc jeżeli znacie jakieś podobne projekty to bardzo proszę o linki bo samemu nie udało mi się nic sensownego znaleźć.

Cywilizacja Open Source

Kodowanie Techblog 22 maja 2011 o 18:01:25 | ☍ trackback

Kiedy słyszymy Open Source nasze skojarzenia biegną w kierunku systemu Linux, przeglądarki Firefox czy też śp. pakietu OpenOffice (obecnie LibreOffice) oraz niezliczonej ilość podobnych programów, z których mniej lub bardziej świadomie korzystamy na co dzień. Open Source kojarzy się nam najczęściej z informatyką i stylem wytwarzania oprogramowania. Jednak Open Source to coś więcej niż informatyka, to styl myślenia, który powoli ale nieodwracalnie wymyka się z pola informatyki i zaczyna kiełkować w przeróżnych dziedzinach.

To co chcę przekazać w tej notce może wydać się dość niepozorne jeżeli nie znamy tła jakim jest obecny status i kształt systemu, który wytwarza nam dziś wszelkie dobra. Najlepiej zapoznać się wcześniej z filmami typu: Zeitgeist: Moving Forward czy The Light Bulb Conspiracy. Pierwszy z nich pokazuje przyczyny, które zmuszają naszą cywilizację do produkcji bubli oraz marnowania zasobów, natomiast drugi pozwala nam zobaczyć ten proces w praktyce.

Czasami, żeby zrobić krok do przodu, trzeba najpierw zrobić dwa do tyłu, porzucić rozwiązania, które zaprowadziły nas w ślepy zaułek i zaprojektować od podstaw nowe, dzięki którym trafimy na autostradę rozwoju.

Arduino

Jeżeli studiowaliście elektronikę lub informatykę na pewno na laborkach uczyliście się programować jakieś proste układy w postaci (specjalnie przygotowanych do nauki) płytek drukowanych z przeróżnymi układami elektronicznymi. Problem z tymi układami (miałem z nimi styczność w technikum i na studiach) polegał na tym, że były one:

  • dość drogie
  • do ich obsługi wymagane było specjalne dostarczane przez producenta oprogramowanie (oczywiście też drogie) i dostępne wyłącznie na Windowsa
  • dostęp do układów miałem tylko na laborkach bo ani nie miałem ochoty kupować na rok tak drogiego sprzętu, ani nie miałbym go jak uruchomić bo nie mam Windowsa

Jak widać takie praktyki w żaden sposób nie zachęcają do przybliżenia młodemu człowiekowi elektroniki. Z podobnym problemami ścierano się również w innych krajach i tym sposobem narodził się projekt Arduino.

Arduino The Documentary (2010) English HD from gnd on Vimeo.

Linki:
- Wikipedia o Arduino
- www.arduino.cc - strona domowa

Oczywiście Arduino to dopiero początek, mały klocek LEGO na bazie którego mogą powstawać nowe otwarte rozwiązania.

Open Source Ecology

Wstępem do tego projektu najlepsza będzie prelekcja Marcina Jakubowskiego wygłoszona w ramach konferencji TED.

BTW. Marcin został wyróżniony odznaką TED Fellow 2011. Jeszcze intro ze strony projektu:

Marcin odwiedził już w tym roku Polskę, do której przyjechał na zaproszenie organizatorów konferencji Cohabitat Gathering 2011. Poniżej bardzo swobodna rozmowa zarejestrowana po konferencji.

Marcin Jakubowski CHG 2011 - II from dobraidea on Vimeo.

Global Village Construction Set (GVCS) ułatwia rozpoczęcie prac w sektorze rolniczym, budowlanym oraz produkcji i może być postrzegany jako naturalnej wielkości "Zestaw Lego" narzędzi modułowych, które pozwalają stworzyć całą gospodarkę, zarówno na wiejskich terenach Missouri, w którym projekt został założony, w górach Oregon, lub w sercu Afryki. Projektując bez granic, zarówno myślowych jak i praktycznych, jesteśmy pewni że GVCS może przełamać bariery wykonalności i kosztów budowy od podstaw prawdziwej trwałej i zrównoważonej wspólnoty, oraz gospodarki funkcjonującej w oparciu o lokalne zasoby.

Tak jak pisałem na początku, niektórym projekt może się to wydać dość niepozorny. W końcu stworzono tylko niezbyt estetycznie wyglądający traktor czy zgniatarkę do ziemi. Bardziej zainteresowało by to pewnie rolnika niż przeciętną osobę techniczną. Jednak cały sens projektu ukryty jest w jego filozofii, czyli filozofii Open Source. Weźcie pod uwagę np. fakt, że dopiero ostatnio producenci telefonów komórkowych zdecydowali się produkować zgodne ze sobą ładowarki (sic!). Przez Wykop przetaczają się teraz notki o tym, jak to producenci drukarek oszukują nas za pomocą tuszy. Tych problemów (pokazanych też w The Light Bulb Conspiracy ) jest całe mnóstwo. Nie wyrwiemy się z nich dopóki nie przestawimy swoich schematów myślenia na tory Open Source.

Tak więc parafrazując jest to mały traktor dla człowieka ale wielki dla ludzkości. Poza tym traktor to dopiero początek. Kilka dni temu pojawiły się pierwsze testy stołu do cięcia. Przypomnę, że jednym z jego głównych założeń jest samoreplikacja podobnie jak w przypadku słynnej drukarki 3D RepRap. Na liście projektów do stworzenia czekają jeszcze takie rzeczy jak: drukarka 3D, skaner 3D, 50kW turbina wiatrowa, automobil czy ciężarówka.

Nie sposób o tym wszystkim opowiedzieć, dlatego zachęcam do zapoznania się z różnymi zaułkami strony projektu.

Linki:
- opensourceecology.org - strona projektu

PS. Od jakiegoś czasu ilość moich notek technicznych jest zastępowana przez notki nietechniczne dodawane na moim drugim blogu poświęconym zagadnieniom alternatywnym. Jeżeli kogoś interesuje taka tematyka to zapraszam. Co do notek technicznych to chyba będę musiał zamieszczać je w bardziej skróconej formie, bo na zebranie materiałów i skompilowanie z nich jakiegoś tekstu mam coraz mniej czasu, czego skutek najczęściej jest taki, że pomysł na notkę umiera na etapie pomysłu.

Django: usuwanie cache'u generowanego przez szablon

Django Kodowanie Techblog 25 marca 2011 o 23:58:16 | ☍ trackback

Sytuacja jest następująca: 1989 rok, Kijów. Piękna ukraińska jesień. Czterech urodzonych morderców, uzbrojonych po zęby, a ja sam, jeden, z moim wiernym kałachem... mamy jakiś kawałek szablonu, którego wygenerowanie kosztuje nas sporo zasobów np. wiele zapytań do bazy. Cache'ujemy więc w szablonie wygenerowany HTML aby ulżyć serwerowi. Np. tak:

{% load cache %}

{% cache 604800 statystyki %}
   jakiś super zasobożerny w generowaniu kod HTML
{% endcache %}

Wszystko działa ładnie. Cache wygasa co tydzień (604800 sekund) i wszystko gra. Problem pojawia się jednak, kiedy wygenerowany kod zależy bezpośrednio od jakiegoś obiektu lub obiektów. Kiedy dany obiekt jest modyfikowany chcielibyśmy usunąć cache generowany przez szablon. Rozwiązanie wydaje się być dość logiczne:

from django.core.cache import cache

cache.delete('statystyki')

Niestety powyższy kod robi nic. Template tag tworzy cache generując klucz:

args = md5_constructor(u':'.join([urlquote(resolve_variable(var, context)) for var in self.vary_on]))
cache_key = 'template.cache.%s.%s' % (self.fragment_name, args.hexdigest())

Jak widzimy schemat jest następujący:
template.cache.KLUCZ-Z-SZABLONU.ZAKODOWANE_ARGUMENTY

Jeżeli nie używaliście argumentów w szablonie przy stworzeniu klucza cache'u (czyli nie zrobiliście np. czegoś takiego: {% cache 604800 statystyki request.user %}) to Wasza lista argumentów będzie pusta. Suma MD5 z pustego stringa zawsze wynosi tyle samo, więc dla cache'u tworzonego bez argumentów klucz jest stały i wygląda tak:

cache.delete('template.cache.statystyki.d41d8cd98f00b204e9800998ecf8427e')

<oklaski />

Django i zduplikowane wartości kluczy

Django Kodowanie 24 stycznia 2011 o 21:38:59 | ☍ trackback

Django przy współpracy z Postgresem odstawiło dzisiaj niezłą scenę. Galeria na stabilnie działającej od ponad roku stronie nagle wysypała się przy dodawaniu kolejnych zdjęć, pod pretekstem podwójnych wartości kluczy w tabeli przechowującej pliki galerii.

IntegrityError: duplicate key value violates unique constraint "galeria_plik_pkey"

No więc sprawdzam.

SELECT max(id) FROM galeria_plik;
1573
SELECT nextval('galeria_plik_id_seq'::regclass) FROM galeria_plik;
1526

Great Scott! WTF? Ktoś zakłócił kontinuum! Nie mam pojęcia jak stabilnie działający PostgreSQL mógł nagle tak machnąć się w numeracji... Jeżeli traficie na coś podobnego nie pozostaje nic innego jak zresetowanie indeksu tabeli z właściwym numerem, jaki powinien posiadać kolejny wiersz.

ALTER SEQUENCE galeria_plik_id_seq RESTART with 1574;

I powinno działać. Komuś zdarzyło się coś podobnego?

PS. Python jednak ryje beret. Dzisiaj ułożyłem takie oto zapytanie:

FROM galeria_plik SELECT max(id);

Flash player i pseudo-strumień MP4

Kodowanie Linux Software Techblog 10 stycznia 2011 o 19:07:34 | ☍ trackback

Co jakiś czas przychodzi mi osadzać na stronach pliki FLV z jakimś Flashowym playerem. Oczywiście nie ma z tym żadnego problemu, jednak obecnie nadciąga moda na pliki MP4 kodowane przez h264. Flash od wersji 9 umożliwia odtwarzanie tego typu plików jednak jest ale. Żeby Flash zaśpiewał jak mu MP4 zagra, potrzebuje wyciągnąć z niego metadane (w tym cały indeks zawartości pliku) czyli tzw. obszar Moov Atom. Problem w tym, że większość enkoderów beztrosko umieszcza metadane na końcu pliku MP4.

Rezultatem tej złotej myśli technologicznej jest to, że plik MP4 musi zostać w całości pobrany, zanim jakiś Flash player go zdoła otworzyć. Z małymi plikami to nie problem, jednak kazanie użytkownikowi czekać na pobranie 200 MB pliku, zamiast oglądać go w trakcie ściągania jak w przypadku plików FLV, to powrót do epoki, w której to strony zdobione były tagami <marquee>.

Wyjścia innego nie ma jak złapać za uszy metadane i przeciągnąć je na początek pliku. Na szczęście FFMPEG dostastarcza do tego celu gotowy skrypt o nazwie qt-faststart. Jego użycie raczej nie przysporzy nikogo o ból głowy.

qt-faststart in.mp4 out.mp4

Dla !linuksiarzy pozostaje skorzystanie z aplikacji dla Adobe AIR, lub przygarnięcie klasy dla PHP5.

Snippety dla webdevelopera

Kodowanie Linux Techblog 13 maja 2010 o 19:24:46 | ☍ trackback

Od czasu publikacji poprzedniej porcji snippetów dla mojego ulubionego edytora Geany minęło okrągłe 2 lata i 6 dni. Przez ten czas snippety uległy ewolucji (wykorzystuję je codziennie) jak również nowsze wersje Geany pozwoliły na umieszczenie w snippecie więcej niż jednej pozycji kursora.

Z racji tego, że pracuję jako webdesigner/programista/administrator oprócz zestawu HTML-a dodałem również kilka skrótów dla CSS-a oraz szczyptę udogodnień dla Django (głównie modele i szablony). Scaliłem również inne dostępne dla Geany snippety m.in. dla PHP, Pythona, LaTeX-a i Tlc oczywiście (z informacjami o ich autorach). Prawdę mówiąc, miałem nadzieję, że w ten sposób będzie można uporządkować dodatki na stronie Geany, tak aby do pobrania był jeden plik a z boku zbiorowa informacja o autorach, no ale z autorami strony trochę trudno się dogadać. Już nawet dorwałem ich bezpośrednio na IRC-u ale widocznie godzina była za późna i już mało kontaktowali.

W każdym razie dzięki Dropboksowi plik będzie teraz leżał zawsze w tym samym miejscu i w razie czego będzie na bieżąco aktualizowany, ponieważ mam go podpiętego bezpośrednio pod edytor.

snippets.conf

W szybki sposób można je pobrać tak:

$ wget http://dl.dropbox.com/u/668529/conf/snippets.conf -O ~/.config/geany/snippets.conf

Tradycyjnie dołączam mały przegląd. Oczywiście tylko pobieżnie.

Autorzy snippetów:

  • PHP - Atanas Beloborodov
  • Python - inspirowane snippetami z Gedita
  • LaTeX - Frank Lanitz
  • Tlc - Witek Mozga

Sumowanie statystyk Google Analytics

Kodowanie Python Techblog 20 listopada 2009 o 23:30:37 | ☍ trackback

Zawsze mnie ciekawiło jaki jest ruch na naszym firmowym serwerze ale nie chciałem obciążać maszyny dodatkowym oprogramowaniem, które by to zliczało. Zwłaszcza że każda hostowana przez nas strona jest podpięta pod Google Analytics. Nie znalazłem jednak sposobu aby w panelu statystyk wyświetlić sumę odwiedzin z kilku kont. Na szczęście Analytics podobnie jak większość usług Googla ma swoje API. Wystarczyło więc zaprząc do pracy Pythona oraz bibliotekę gdata.

Użytkownikom ArchLinuksa polecam paczkę python-gdata-svn

yaourt -S python-gdata-svn

Skrypt jest dość prosty i działa w konsoli:

#!/usr/bin/python

import datetime
import sys

import gdata.analytics
import gdata.analytics.service


def main(argv):

    GOOGLE_ANALYTICS_LOGIN = 'TWOJE@KONTO'
    GOOGLE_ANALYTICS_PASSWORD = 'TAJNE_HASLO'

    if len(argv) > 1:
        d = argv[1].split('-')
        data = datetime.date(int(d[0]), int(d[1]), int(d[2]))
    else:
        data = datetime.datetime.now()

    print "\ndata: %d-%d-%d" % (data.year, data.month, data.day)
    print "\nodw\tods\tdomena"
    print "--------------------------"

    dc = gdata.analytics.service.AnalyticsDataService()
    dc.ClientLogin(GOOGLE_ANALYTICS_LOGIN, GOOGLE_ANALYTICS_PASSWORD, account_type='GOOGLE')
    a = dc.GetAccountList()

    odwiedziny, odslony = [], []

    for b in a.entry:
        tid = b.id.text.replace('http://www.google.com/analytics/feeds/accounts/','')
        query = dc.GetData(
            ids=tid, 
            start_date='%.4d-%.2d-%.2d' % (data.year, data.month, data.day), 
            end_date='%.4d-%.2d-%.2d' % (data.year, data.month, data.day), 
            metrics='ga:visitors,ga:pageviews',
            dimensions='ga:day'
        )
        odw = int(query.entry[0].visitors.value)
        ods = int(query.entry[0].pageviews.value)
        odwiedziny.append(odw)
        odslony.append(ods)
        print "\033[1;31m%d\t%d\033[0m\t\033[33m%s\033[0m" % (odw, ods, b.title.text)

    print "--------------------------"
    print "%d\t%d\tRazem" % (sum(odwiedziny),sum(odslony))


if __name__ == "__main__":
    sys.exit(main(sys.argv))

Jeżeli wywoła się go bez parametrów wówczas pokaże statystyki dla dnia dzisiejszego. Można też podać mu jako parametr datę, np:

python stats.py 2012-12-21

Przykładowy wynik działania wygląda tak:
Przykład działania

Definiowanie własnych atrybutów w HTML-u

Kodowanie Techblog 05 listopada 2009 o 23:31:00 | ☍ trackback

Obecnie w czasach interfejsów napędzanych JavaScriptem coraz widoczniejszy staje się problem składowania danych w HTML-u. Prosty przykład: mamy generowany formularz, który chcemy zweryfikować za pomocą JavaScriptu. Przy generowaniu formularza posiadamy dla każdego pola zmienną mówiącą nam o tym czy to pole jest wymagane czy nie. I tu pojawia się problem, jak oznaczyć np. inputa jako pole wymagane? Struktura formularza nie daje nam miejsca na składowanie takich danych. Można kombinować z wrzuceniem jakiegoś słowa kluczowego do id. np:

id="required"

No ale id musi być niepowtarzalne, więc może klasa...

class="required"

Może, ale w sumie mam już tam kilka innych klas

class="specjalne kontrast required"

A więc czy klasa to na pewno dobre miejsce? Jasne że nie, klasa jest dla styli. No więc jak? Trzeba stworzyć własny atrybut! Niby jasne, ale przecież validator nie uznaje własnych atrybutów...

Otóż uznaje. Trzeba je tylko zadeklarować w definicji dokumentu - DTD (Document Type Definition). Załóżmy że chcemy wzbogacić nasz input w atrybut required. Wystarczy więc taka konstrukcja DTD:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" 
[
  <!ATTLIST input required CDATA #IMPLIED>
]>

Ta dekladacja zezwala atrybutowi required posiadać dowolną wartość znakową. Jeżeli chcielibyśmy ograniczyć wartość jedynie do dwóch pozycji wystarczy zastosować coś takiego:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" 
[
  <!ATTLIST input required (true|false) #IMPLIED>
]>

Ogólny schemat jest taki:

ATTLIST element atrybut typ opcjnonalnyStatus

No i gotowe. Teraz możemy zaprząc JavaScript do podjęcia odpowiednich działań na podstawie struktury dokumentu. Czyli np. w jQuery:

$('input[required='true']').PrzypilnujInteresu();

Prosto czysto i funkcjonalnie.

Materiał źródłowy:
http://www.alistapart.com/articles/customdtd/

PS. Remember remember the fifth of november...

GooglePreview dla Google Chrome

Internet Kodowanie Techblog 28 października 2009 o 22:56:02 | ☍ trackback

Google preview to moja ulubiona wtyczka rozszerzenie dla Firefoksa, bez której wyniki wyszukiwania w Googlu po prostu nie wyglądają. Wstawia ona obok każdej pozycji miniaturkę strony, a ponieważ człowiek myśli obrazami więc o wiele szybciej można namierzyć szukaną witrynę. Niestety w przeglądarce Google Chrome (która ostatnio stała się moją podstawową przeglądarką) nic takiego nie istnieje. Istnieje już jednak system rozszerzeń (chociaż ukryty) oraz podstawowa dokumentacja, więc postanowiłem sam zapchać lukę.

Na początek przyda się nam developerska wersja Chroma (nie wiem czy wersja stabilna posiada tą funkcjonalność, jeżeli tak to niech mnie ktoś poprawi). Dla użytkowników ArchLinuksa polecam paczkę z AUR - google-chrome-dev.

yaourt -S google-chrome-dev

Aby uruchomić ukryty jeszcze mechanizm obsługi rozszerzeń należy uruchomić przeglądarkę z parametrem -–enable-extensions.

google-chrome -–enable-extensions

Teraz wystarczy już tylko pobrać przygotowane przeze mnie rozszerzenie i potwierdzić chęć instalacji

ChromePreview 0.38

Od tej chwili możemy się już cieszyć pięknymi miniaturkami

wyniki wyszukiwania

O ile wszystko dobrze poskładałem to rozszerzenie powinno się samo aktualizować (w razie W). Jeżeli ktoś jest zainteresowany bebechami to dołączam pliki:

Listę zainstalowanych rozszerzeń znajdziecie wstukując do paska adresu chrome://extensions/

EDIT: rozszerzenie znajdziecie w otwartej dzisiaj bazie rozszerzeń pod adresem https://chrome.google.com/extensions/detail/behjpjkdajdecgkkamhaplpkcbkceaie

Django – personalizacja settings.py

Django Kodowanie Techblog 28 czerwca 2009 o 11:17:04 | ☍ trackback

Jak każdy djangowic dobrze wie plik settings.py przechowuje wszelkie ustawienia aplikacji począwszy od nazwy strony a na listach middleware'u czy liście zainstalowanych aplikacji skończywszy. Ponieważ zawiera on wszelkie ustawienia, musi być inny dla developera a inny dla serwera produkcyjnego (np. z powodu tego, że developer ma DEBUG=True).

Pierwszą możliwością rozwiązania tego problemu jest ignorowanie pliku settings.py przez repozytorium kodu, tak aby różne zawartości tego pliku nie powodowały konfliktów. Wadą takiego rozwiązania jest potrzeba ręcznego edytowania tego pliku na serwerze kiedy np. dodajemy nową aplikację do INSTALLED_APPS. Moje repozytorium aktualizuje stronę na serwerze po każdym commicie, więc ręczna edycja settings.py jest męcząca.

Drugą możliwością jest stworzenie osobnych ustawień dla serwera i osobnych dla developera. Django umożliwia uruchomienie serwera z podaniem pliku ustawień jako parametr:

python manage.py runserver --settings=settings-developer.py

Wszystko wydaje się być ok. Jeżeli coś zmieniamy to dokonujemy zmiany w settings.py, settings-developer.py i po commitcie wszystko gra. Czasami jednak przy testowaniu różnych rzeczy w pliku developera można zapomnieć o settings.py i po commicie znowu strona jest rozwalona. Poza tym nie każdy developer korzysta z tych samych ustawień. Jeden używa Django Debug Toolbar inny ColorSQLMiddleware więc trzeba by zrobić tyle settings-xxx ilu developerów. A później przy zmianie czegoś globalnego edytować wszystkie...

Ostatecznym rozwiązaniem okazało się przeciążenie pliku settings.py przez ponowną deklarację zmiennych lub rozszerzenie już istniejących wartości. Jak to zrobić?

  1. Tworzymy plik, który będzie przetrzymywał nasze lokalne ustawienia, np. settings-local.py
  2. Na końcu pliku settings.py dodajemy kod:
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
execfile('%s/settings-local.py' % BASE_DIR)

Teraz w pliku settings-local.py możemy ponownie zadeklarować zmienne które mają zostać przeciążone lub rozszerzyć zadeklarowane już w settings.py listy. Np. kiedy jeden z developerów chce użyć Django Debug Toolbar dodaje do settings-local.py taki kod:

MIDDLEWARE_CLASSES += (
	'debug_toolbar.middleware.DebugToolbarMiddleware',
)

INSTALLED_APPS += (
	'debug_toolbar',
)

DEBUG_TOOLBAR_PANELS = (
	'debug_toolbar.panels.sql.SQLDebugPanel',
	'debug_toolbar.panels.headers.HeaderDebugPanel',
	'debug_toolbar.panels.cache.CacheDebugPanel',
	'debug_toolbar.panels.profiler.ProfilerDebugPanel',
	'debug_toolbar.panels.request_vars.RequestVarsDebugPanel',
	'debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel',
	'debug_toolbar.panels.templates.TemplatesDebugPanel',
	# If you are using the profiler panel you don't need the timer
	# 'debug_toolbar.panels.timer.TimerDebugPanel',
)

Plik settings-local.py wywalamy z repozytorium i w ten sposób otrzymujemy elastyczny mechanizm współdzielenia wartości globalnych przy jednoczesnej personalizacji ustawień lokalnych.

Narzędzia do pracy grupowej poszukiwane

Internet Kodowanie 04 czerwca 2009 o 15:40:21 | ☍ trackback

Obecnie pracuję jako programista aplikacji internetowych w małym zespole. Realizujemy kilka projektów w miesiącu i dość trudno jest zapanować nad wszystkimi zadaniami, które trzeba wykonać. W przypadku większych projektów korzystamy z Trac'a, jednak do mniejszych nie nadaje się on za dobrze ponieważ trzeba dla każdego projektu tworzyć nową instancję i nie ma jak zrobić zbiorczego zestawienia. Rozglądałem się więc za jakimś kompleksowym rozwiązaniem, które dawałoby możliwość ogarnięcia kilku projektów wraz ze śledzeniem repozytoriów Subversion.

Powstało już wiele serwisów oferujących podobną funkcjonalność. Wśród najbardziej znanych wymienić można:

Główną wadą pierwszych trzech rozwiązań jest to, że nie można ich hostować na własnym serwerze a jedynie wykupuje się konto na serwerze producenta. Collabtive jest co prawda aplikacją na licencji GNU GPL i można postawić to u siebie, ale z kolei zupełnie nie obsługuje repozytoriów kodu.

I tutaj pytanie do Was. Czego Wy używacie w pracy? Być może jest jakiś fajny projekt który przeoczyłem.

PS. Swoją drogą to dziwne, że nikt jeszcze czegoś podobnego w Django nie zrobił.

Python i jQuery czyli pyquery

Kodowanie Python Techblog 04 maja 2009 o 15:51:57 | ☍ trackback

Ostatnio wpadł mi w ręce bardzo ciekawy moduł Pythona, który śmiało można określić jako jQuery po stronie serwera. Jeżeli potrzebowaliście kiedyś wyciągnąć jakieś dane z kodu HTML-a i denerwowała was zabawa z parsowaniem kodu za pomocą sgmllib czy innego tego typu wynalazku, to wasze cierpienia właśnie się skończyły.

Jak to działa?

Na początek pobierzemy zawartość jakieś strony, z której chcemy wyciągnąć dane. Ja posłużę się stroną antyweb.pl, ponieważ jest całkiem przystępnie zakodowana.

from pyquery import PyQuery as pq
import urllib

html = urllib.urlopen("http://antyweb.pl").read()
html = pq(html)

Teraz wystarczy już zadecydować co chcemy wyciągnąć i po prostu to zrobić :-) Np. informacje o autorze

print  html("#f li.frt").text()

Wynik:

Witaj, nazywam sie Grzegorz Marczak i jestem autorem tego bloga. Piszę tutaj o serwisach spolecznosciowych, nowych technologiach i nowych trendach w internecie.

Wyciągnięcie wszystkich kategorii

for a in html("li.categories a"):
	print a.text

Wynik:

antytydzień Biała flaga
Ciekawe strony
google
Świat
Miniblog
Mobilnie
Moje przemyślenia
Off topic
polska
Pytamy.pl
Startups
To mnie drażni.
Uncategorized
W trakcie tworzenia
wywiady

Wyszukanie najczęściej komentowanego wpisu ze strony głównej

max_comments = 0
title = ''
for a in html("ul.clnn li.l a"):
	try:
		# liczba komentarzy
		comments = int(a.text.split(" ")[1])
		if max_comments < comments:
			max_comments = comments
			# nazwa wpisu
			title = a.values()[1].replace("Komentarze do wpisu ",'')
	except:
		pass
		
print "Najwiecej komentarzy: %s" % max_comments
print "Wpis: %s" % title

Wynik:

Najwiecej komentarzy: 32
Wpis: Interia mówi, tak kupujemy ruch (bo inni też tak robią)

Więcej

To oczywiście tylko mała próbka możliwości. pyquery pozwala również na manipulację stylami (addClass, toggleClass, removeClass, attr, css) czy samą strukturą danych (append, prepend, prependTo, insertAfter, remove, replaceWith itd.). Jeżeli posiadamy moduł WebOb możemy też zaprzęgnąć do pracy Ajax.

Po więcej informacji zapraszam na stronę projektu pyquery.

Joggerowy gadżet na pulpit

ArchLinux Kodowanie Linux Python Techblog 05 września 2008 o 00:38:40 | ☍ trackback

Ostatnio rozglądałem się za tutorialem do budowy prostego gadżetu w Pythonie, który siedział by sobie na przezroczystym tle na moim pulpicie. Gadżety Screenlets czy gDesklets działają różnie, zazwyczaj niestabilnie albo, któryś (akurat przydatny) całkowicie się nie odpala. Poza tym potrzebowałem coś maksymalnie prostego a nie całej platformy dla gadżetów.

Wpadłem więc dziś na pomysł wykorzystania Tildy jako ładnego kontenera. W zasadzie to do pełni szczęścia potrzebne były dwie paczki: tilda i python-feedparser. Znajdziecie je w każdej dystrybucji. Dla archowców:

# pacman -S tilda python-feedparser

Tildę najlepiej skonfigurować następująco:

W sekcji Command w polu Custom Command umieszczamy adres skryptu, ale o tym za chwilę.

Teraz czas na Pythona. Wystarczy sworzyć malutki skrypt o takiej treści:

#! /usr/bin/env python

import feedparser
import time
import os, sys

# nieskonczona petla
while 1:
	# pobierz RSS
	feed = feedparser.parse("http://jogger.pl/rss/")
	# wyczysc ekran
	sys.stdout.write(os.popen('clear').read())
	# dla kazdego wpisu
	for note in feed['entries']:
		# wypisz tytul
		print "- %s" % note['title']
	print "\nhttp://jogger.pl/"
	# odczekaj 60 sekund
	time.sleep(60)

Skrypt wystarczy zapisać np. jako jogger.py i wpisać ścieżkę do niego w polu Custom Command. W moim przypadku jest to:

python /home/tomek/go/python/jogger.py

I to by było na tyle. Po ponownym uruchomieniu Tildy powinniśmy mieć ładny przegląd wydarzeń na joggerze odświeżany co 60 sekund. Gdy coś nas zainteresuje wystarczy przytrzymać ctrl i kliknąć link do joggera.

Oczywiście może to być dowolny kanał RSS/Atom czy coś zupełnie innego np. statystyki obciążenia naszego serwera. Żadnych tam Googlowych gadżetów z tysiącem funkcji. Prosto łatwo i przyjemnie.

Rozpoznawanie gestów za pomocą kamery

Kodowanie Projekty Python Techblog 07 czerwca 2008 o 13:06:30 | ☍ trackback

Od dawna chciałem już zrobić coś związanego z kamerą. W tym semestrze nadarzyła się okazja i zaproponowaliśmy prowadzącemu własny temat projektu z przedmiotu o nazwie „struktury systemów informatycznych”. Naszym zamierzeniem było stworzenie programu, który działałby podobnie jak gesty wykonywane myszą w Firefoksie tyle, że rolę myszki odegrać miała kamera. Założenia wstępne: platforma – Linux, język – Python.

Najwięcej problemów sprawiła nam sama kamera, a dokładniej to zbieranie i przetwarzanie jej obrazu.

Na początku zabraliśmy się za testowanie reacTIVision, które w zasadzie jest oprogramowaniem dla ekranów wielodotykowych. ReacTIVision ma swoją bibliotekę 89 symboli, które potrafi rozpoznać określając ich numer id, pozycję x-y, kąt nachylenia a nawet przyśpieszenie.

Symbole wyglądają tak:

Kamera widziała to tak:

A reacTIVision tak:

Działo to całkiem sprawnie. Jeżeli wykonaliśmy szybszy ruch markerem, a dokładniej przyśpieszenie markera przekroczyło pewną granicę, wówczas rozpoczynał się rysować gest. Wadą jednak tego rozwiązania były markery. Jeżeli nie miało się markera to program był bezużyteczny. Trzeba było więc go zastąpić czymś co ma każdy, np. ręką :-)

Do łapania obrazu z kamery tym razem wykorzystaliśmy moduł Pythona pyvideograb. Znaleźliśmy nawet bardzo przydatny skrypt, który wykrywał punkty ruchu w obrazie poprzez porównywanie dwóch sąsiednich klatek. Co prawda autorzy zaznaczyli, że działa tylko pod Windowsem z uwagi na moduł do przychwytywania obrazu z kamery, ale ten łatwo można było podmienić.

Teraz wystarczyło wrzucić wszystko do Pygame’a i już pierwsze efekty były widoczne.

Program wykrywał ruch i potrafił określić współrzędne punktu ruchu, co w przypadku poruszającej się większej powierzchni oznaczało jej środek.

Po naciśnięciu spacji możemy już wykonywać gest.

Następny etap to sieć neuronowa a dokładniej sieć Hopfielda. Dzięki niej jesteśmy w stanie rozpoznać, czy wykonany gest zgadza się z jednym z 4 wzorców. Jeżeli tak, wykonywane jest przypisane do niego polecenie.

W konsoli wygląda to tak:

W tej chwili program ma wprowadzone 4 wzorce (plik: patterns.txt)

Przypisane do nich działania można łatwo edytować (interfejs.py)

Jeżeli ktoś miał by ochotę się tym pobawić lub zrobić z tym coś więcej to proszę bardzo.

Gesty v0.001 na licencji GNU GPL

Projekt – 4.5, radość ze zrealizowanego pomysłu – bezcenna ;-)

Współautorzy:
– Marek Knaga
Jarosław Miazga

UPDATE: ponieważ strona projektu pyvideograb od jakiegoś czasu jest martwa zamieszczam spakowany moduł pyvideograb.tar.gz

Pacman i kategorie z portage

ArchLinux Gentoo Kodowanie Linux Pacnet Projekty Python 24 lutego 2008 o 01:21:39 | ☍ trackback

Moje ostatnie narzekania na organizację repozytorium w Archu nie dawały mi spokoju. Dzisiaj z pomocą fixxxera (właściwie to tylko przerobiłem jego skrypt ;) powstał skrypt, który po otrzymaniu nazwy pakietu pokazuje nam do jakiej kategorii jest on przypisany w repozytoriach Gentoo.

Składania jest prosta:

$ python portage.py gajim
net-im

Oczywiście bez dwóch zdań będą jakieś niezgodności

$ python portage.py pacman
games-arcade

Ale na ogół skrypt powinien działać dobrze. Czyli pierwszy krok do kategoryzacji Archa zrobiony. Teraz tylko powkładać pakiety w kategorie, zrobić GUI i można podbijać świat ;-)

Jamendo Tray Icon Player

Internet Kodowanie Linux Python Techblog 12 stycznia 2008 o 00:38:40 | ☍ trackback

Ostatnio zaczynam mieć dość webowych aplikacji. Oglądanie wszystkiego w przeglądarce nie zawsze jest wygodne, no i nie zawsze szybkie zważywszy na ilość rozszerzeń jakie wcieliłem do Firefox-a. Czasami też wyłączam okno przeglądarki zapominając, że w któreś z zakładek siedzi coś co np. odtwarza muzykę z Jamendo. Do webaplikacji Googla używam już od jakiegoś czasu Prisma. Działa to lepiej ale nadal nie jest to /to coś/ czego szukam. Jeżeli mogę staram się używać aplikacji natywnych np. Gmail via Thunderbird (przez IMAP) czy Google Calendar via Lightning (rozszerzenie do Trunderbird-a). Aplikacje webowe mają jednak bardzo dobrą cechę – są mobilne. Nie mając naszych ulubionych aplikacji pod ręką i tak zawsze się do nich dostaniemy choćby przez tfu IE tfu.

Dzisiaj trochę bawiłem się PyGTK wynikiem czego wykombinowałem mały skrypt. Sam się zdziwiłem jak można łatwo ubierać strony w jakieś natywne GUI. Poniższy skrypt jest zwykłym oknem przeglądarki opartej na gtkmozembed tyle, że potrafi schować się do ikonki w zasobniku systemowym dzięki czemu świetnie sprawuje się już jako odtwarzacz moich ulubionych utworów z Jamendo.

Przy pierwszym uruchomieniu należy się zalogować w serwisie (nowej wersji serwisu), a przy następnych od razu ładowany będzie ichniejszy player.

Skrypt: jtip.py

Odpalamy standardowo jak na pythona przystało:

$ python jtip.py

Oczywiście skrypt łatwo wykorzystać do obsługi innej strony.

BTW: Kiedy ktoś zrobi wtyczkę do QuodLibet obsługującą Jamendo ?

BTW2: Jak spowodować aby klikanie na krzyżyk chowało aplikację do ikonki w zasobniku? W moich próbach okno niby udało mi się ukryć nie wyłączając aplikacji, ale dźwięk się urywał a po kliknięciu na ikonkę w zasobniku przywracało się gołe okno.