Urządzenia MTP na nie-Windows

Co to jest MTP to wie każdy, kto ma w miarę nowy odtwarzacz. Wszystkie (albo prawie wszystkie) nowe Samsungi, iRivery i Creative (żeby wymienić tylko kilka) komunikują się z komputerem przy użyciu tego protokołu. Do niedawna jedynym programem, który dobrze go obsługiwał, by Windows Media Player 10. Oczywiście, tylko na Windows. I do niedawna było to wielkim problemem, bo już nie jest. Teraz jest tylko pewnym problemem, bo do urządzeń MTP można się podłączać także z innych systemów.

Musiałem to spraktykować, bo mój nowy Samsung YP-T10 to właśnie urządzenie MTP. Podobno wgrywając koreański firmware można go przestawić w tryb UMS, ale wolałem najpierw sprawdzić metody mniej inwazyjne.

Na Macu:

  • jedyny program to XNJB, ma koszmarne GUI, ale zasadniczo działa, nie radzi sobie z niektórymi tagami ID3 i czasem nie potrafi wysłać pliku — w takiej sytuacji pomaga mu odłączenie odtwarzacza i ponowne podłączenie.

Na linuksie możliwości jest sporo więcej:

  • Amarok i Rhythmbox bez problemów gadają z urządzeniami MTP, jedyna niedogodność w przypadku tego drugiego, to możliwość wrzucania jedynie muzyki (nie wiem, jak jest z Amarokiem);
  • gnomad2 to program podobny do XNJB (właściwie to XNJB jest wzorowany na gnomad2 i wykorzystuje te same biblioteki), ale wersja, którą mam na Ubuntu 8.04, nie daje dostępu do struktury katalogów na odtwarzaczu, co uniemożliwia np. wgranie aktualizacji firmware;
  • mtpfs to obsługa systemu plików na urządzeniach MTP dla FUSE; montuje się urządzenie w dowolnym katalogu i jest dostęp do struktury systemu plików urządzenia, jedyny mankament: nie zawsze chce się odmontować, twierdząc, że device is busy; spodziewałem się jakiejś współpracy mtpfs z Nautilusem, ale niczego takiego nie stwierdziłem, w sumie dobre i to, co jest.

Jak widać, linuksiarze mają znacząco lepiej, szczególnie z powodu mtpfs/FUSE. A z innej strony: jest dla mnie całkowicie niezrozumiałe, czemu iTunes nie współpracuje z urządzeniami MTP. Szczerze mówiąc otarłem się o szok.

Robi wrażenie

Samsung SGH-F480

Wczoraj przyszedł mój nowy dotwarzacz Samsunga i o ile różni ludzie zachwycają się designem iPodów, to na mnie Samsung YP-T10 robi o wiele większe wrażenie. A że kolega z pracy wczoraj właśnie dostał swojego iPhone 3G, to z ciekawości spojrzałem na to, co Samsung może zaproponować w tej dziedzinie. Nie określiłbym siebie jako gadżeciaża, po prostu podoba mi się ten F480. :)

Upload plików w Django (po nowemu)

To jest głównie a note to self, żeby mieć to pod ręką w razie potrzeby.

Zakładając, że mam funkcję i model:

def get_userphoto_upload_path(instance, filename):
    return 'users/%s/photos/%s' % (str(instance.user_id), filename)

class UserPhoto(models.Model):
    user = models.ForeignKey(User, verbose_name=_('user'), related_name='photos')
    photo = models.ImageField(_('photo'), upload_to=get_userphoto_upload_path)
    caption = models.CharField(_('caption'), max_length=200, null=True, blank=True)

w klasie formularza metoda save() powinna zawierać kod:

def save(self, user):
    user_photo = UserPhoto(user=user)
    if 'caption' in self.cleaned_data:
        user_photo.caption = self.cleaned_data['caption']
    data = self.cleaned_data['photo']
    user_photo.photo.save(data.name, data)
    return user_photo

Zawsze zapominam, jak powinno się to robić. Może teraz będzie mi łatwiej trafić na ślad własnych dokonań. ;)

Nowe comments w Django

Dziś w Django pojawiła się zrefaktoryzowana ramówka do komentarzy. Tym razem przed aktualizacją powstrzymuje mnie comment-utils, które chroni ten piękny kawałek internetu przed spamem. Parę dni i będzie, a jak nie, to popracuję nad tym osobiście. :)

Wsparcie dla iRiver H10Jr. na Macu

Oficjalnie nie ma. Nieoficjalnie jest, w postaci biblioteki pmplib, ale skompilowanie jej pod OSX to straszliwy ból tyłka. Jak się to robi:

  1. zainstaluj z portów pakiety libid3tag, libogg i libvorbis;
  2. ściągnij źródła ze strony pmplib i rozpakuj je gdzieś, od tej pory $ROOT będzie oznaczać wypakowany katalog ze źródłami pmplib;
  3. w pliku $ROOT/lib/pmp_iriverplus3/util.c zmień wpis #include <malloc.h> na #include <sys/malloc.h> (na początku pliku);
  4. skonfiguruj używając polecenia: ./configure --disable-js --with-libiconv-prefix=/opt/local --with-id3tag-header=/opt/local/include --with-id3tag-library=/opt/local/lib --with-ogg-prefix=/opt/local --with-vorbis-prefix=/opt/local;
  5. zbuduj i zainstaluj: make && sudo make install;
  6. sprawdź czy easypmp działa.

Mnie działa, choć nie bez problemów. Pomimo odmontowania H10 przez cały czas pokazuje, że jest busy, żeby go odzyskać trzeba kilkakrotnie wyciągać z niego wtyczkę i ją wkładać (co czasem powoduje ponowne zamontowanie).

Na szczęście mój śliczny nowy Samsung YP-T10 przyjedzie do mnie już za kilka dni.

Moja muzyka od paru miesięcy

Postanowiłem dać upust mojemu upodobaniu muzycznemu i w tym miejscu zarekomendować pewnego artystę (a właściwie pewną artystkę). Otóż, kilka miesięcy temu szukając ciekawego industrialu dzięki last.fm trafiłem na Android Lust. No i zawładnęło mną na dobre... Piękny głos Shikhee, kiedy trzeba melancholijny, a kiedy trzeba drapieżny i ostry, rytm pulsujący kiedy trzeba, a kiedy trzeba połamany, kompozycje po prostu ładne. Nie chcę więcej. :)

Django po polsku gotowe na 1.0

Tytuł cokolwiek na wyrost, jak sądzę, ale mam powody do dumy. W spolszczeniu Django nie brakuje już żadnych tekstów, jedynie dwa (oba dotyczące GIS) powinny zostać przejrzane przez kogoś, kto się na tym temacie zna. Biorąc pod uwagę nadchodzący string-freeze, mogę się spodziewać, że w takim stanie dotrwamy do finalnego wydania.

Jam-ci to sprawił. Tymi recami!

Mac i Python, Python i Mac

Jak wiedzą wszyscy (albo wszyscy w mieście), Apple dostarcza jakiegoś Pythona ze swoim OSX. Mogłoby to wskazywać, że Python jest first class citizen, jeżeli chodzi o języki programowania na OSX, podobnie jak jest to w przypadku Ubuntu. A figę (chcialem napisać bardziej dosadnie, ale podobno nieletni czytają)!

Robienie aplikacji na Maka w Pythonie to droga przez mękę. Serio. PyObjC obecnie oficjalnie jest w wersji, która ledwo wspiera poprzednią wersję OSX (10.4), zresztą pisanie w tym czymś przypomina programowanie aplikacji na Win32 używając PyWin i MFC. A chyba nawet gorzej. Z normalnych ramówek GUI są oczywiście wszystkie, ale w takim przypadku bez Py2App nie ma co się do tego zabierać. Normalnie jak na Windows.

Która to konkluzja doprowadza mnie do szerzej ujmującej makowo-osxową rzeczywistość konstatacji — ogólnie Mac jest jak Windows, tylko trochę bardziej. Odczuwam taki sam brak wolności (w sensie free speech) i podobne podejście ludzi, którzy robią oprogramowanie na Maki — byle tylko zarobić i nic nie pokazać. Na linuksie może nie ma aż tak wyczesanych efektów wizualnych, może też nie wszystkie ficzery tak ładnie działają (zamknij klapę laptoka, a się uśpi, podnieś, a się obudzi — i WiFi przeżyje), ale pod względem aplikacji skierowanych na produktywność po prostu nie ma porównania. Instalujesz Ubuntu i masz dosłownie wszystko, czego potrzebujesz, a to, czego jeszcze nie masz, jest na odpalenie apt-get install.

Co doprowadza mnie do kolejnej konkluzji, że moim kolejnym prywatnym komputerem nie będzie Mac, tylko jakiś fajny normalny laptop z matrycą 13'4. Jak na przykład twoja Toshiba, Smoku...

NFA jest wielkie!

Dziś w pracy miałem robotę głównie poszukiwawczą — było kilka rzeczy, których nie wiadomo było jak zrobić, choć wiadomo było, że się da. Na przykład na początek: jak w adminie Django wyświetlić obrazek na formularzu edycji obiektu, zamiast zwykłego linku do niego, jak to jest domyślnie? Na szczęście wiedziałem jak się to robi, więc nie miałem zbyt trudnego zadania na początek.

W nowym Django (czyli beta-1 lub nowszym) w adminie jest to o tyle proste, że dla każdego indywidualnego pola formularza można przypisać odpowiedni widget, czyli reprezentację w HTML. Wystarczyło utworzyć sobie odpowiednią klasę dla takiego widgetu:

class AdminImageWidget(forms.FileInput):
    
    """
    Widget do wyświetlania obrazka w adminie (change form)
    """
    
    def render(self, name, value, attrs=None):
        output = []
        file_name = str(value)
        if value and hasattr(value, 'url'):
            output.append('<img src="%(url)s" alt="image" /><br />' % {'url': value.url})
            output.append('%s ' % _('Change:'))
        output.append(super(AdminImageWidget, self).render(name, value, attrs))
        return mark_safe(u''.join(output))

i następnie użyć jej w klasie administracyjnej dla modelu:

class MovieImageAdmin(admin.ModelAdmin):
    list_display = ('movie', 'width', 'height', 'shot_at')
    search_fields = ['movie__title']
    save_on_top = True
    list_filter = ('movie', 'width')
    
    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name == 'image':
            kwargs['widget'] = AdminImageWidget
        return db_field.formfield(**kwargs)

Metoda formfield_for_dbfield jest wywoływana dla każdego pola formularza i w tym przypadku sprawdzeniu podlega nazwa pola, ale można równie dobrze sprawdzić jego typ lub inny atrybut, aby dopasować właściwy widget. W ten sposób można także dostosować wyświetlanie plików video czy reprezentację dla plików dźwiękowych.

No dobrze, to było proste i nie zajęło mi całego dnia. Ale następna robota nie była już taka oczywista. Kolega chciał, żeby główne okno aplikacji administracyjnej (to, co jest pod / w adminie) dostało kilka dodatkowych zmiennych w kontekście. W starszym Django (sprzed newforms-admin) nie byłoby to możliwe bez patchowania samego Django (co nie jest kłopotliwe, jeżeli używa się Virtualenv, ale zawsze jest uciążliwe), ale teraz dostaliśmy wszystkie potrzebne narzędzia.

Jak wiadomo, za sterowanie aplikacją administracyjną odpowiada obiekt klasy AdminSite, który jest o tyle fajny, że jest najzwyklejszym obiektem najzwyklejszej klasy. Klasy, którą oczywiście można nadpisać. Jak to może wyglądać? Na przykład tak:

class AdminSite(admin.AdminSite):
    
    def index(self, request, extra_context=None):
        if extra_context is None:
            extra_context = {}
        ctx = {
            'my_item': u'my_value',
        }
        extra_context.update(ctx)
        return super(AdminSite, self).index(request, extra_context)

Nieprzyjemy aspekt używania obiektu site własnej klasy AdminSite jest taki, że nie działa funkcja autodiscover() i wszystkie klasy administracyjne trzeba rejestrować własnoręcznie w tym samym miejscu, gdzie znajduje się obiekt klasy AdminSite. Ale to chyba stosunkowo mała niedogodność w porównaniu z dostarczoną mocą.

Prawie, prawie

Django jest coraz bliżej mitycznego "1.0" — właśnie wyszło 1.0-alpha-2, w którym dostaliśmy zrefaktorowane pola FileField i pochodne (czyli również ImageField), przebudowę przeszedł także podsystem sygnałów.

To tak gwoli kronikarskiej ścisłości, bo to są rzeczy, które albo wymagały ode mnie przepisania kawałka kodu, albo długo na nie czekałem.

Sztorm? Nie zauważyłem

Podobno na Bałtyku szalał sztorm. Lelewizja o tym trąbiła. Ja zauważyłem tylko deszcz co chwilę i wiatr, który urywa głowy. Poza tym żadnych atrakcji. A ja myślałem, że sztorm to coś, co zapada w pamięć, jak halny w Tatrach.

Wyjeżdżając na wakacje nie zapomnij komputera

Jak się okazuje, Polska pełna jest niezabezpieczonych sieci WiFi. Wystarczy włączyć komputer, a kilka natychmiast się znajdzie. A jak nie, to trzeba przesiąć się o jedną-dwie ławki dalej.

Technikalia

  • XP-Dev.com: Free Subversion Hosting
  • A Django joint.
  • Python powered