RiverCopier

iRiver T10Jestem w posiadaniu odtwarzacza iRiver T10. Nabyłem go ze względu na dobrą jakość dźwięku, możliwość odtwarzania plików Ogg Vorbis i długi czas pracy na baterii. Zasadniczą wadą, jaka dała się we znaki po pewnym czasie użytkowania, okazał się brak sortowania playlisty. Utwory odtwarzane są w takiej kolejności, w jakiej trafiły do pamięci urządzenia. Okazuje się, że nawet po zripowaniu płyty pliki wynikowe są rozrzucone po dysku i podczas kopiowania nie jest zachowana ich kolejność. Prawdopodobnie dałoby się rozwiązać problem za pomocą jakiegoś menedżera plików lub odtwarzacza audio, który pozwoliłby posortować pliki i przenieść je na urządzenie. Postanowiłem jednak spróbować napisać własny program, ucząc się przy okazji Pythona i PyGTK. W końcu tak wiele osób twierdzi, że gdy się nie ma jakiegoś programu na Linuksa, to przecież można go sobie napisać, korzystając chociażby z bogactwa języków skryptowych.

Prace rozpocząłem ponad półtora miesiąca temu i co kilka dni dopisywałem trochę kodu, wprowadzałem poprawki i usprawnienia. Koniec końców otrzymałem aplikację, która spełnia moje wymagania, choć dla kogoś innego może okazać się kłopotliwa w obsłudze. Niemniej jestem zadowolony z efektu, a także z tego, że zapoznałem się bliżej z Gitem, Pythonem i tworzeniem interfejsów graficznych z użyciem Glade i PyGTK. Sam Python okazał się przyjaznym językiem, za to PyGTK przysporzyło mi wiele problemów. Myślę, że warto je opisać, by pomóc innym, a także zachęcić do upartego pokonywania trudności.

RiverCopier v.0.1beta

Pierwszym z problemów był wzorzec projektowy Model-Widok-Kontroler (MVC), stosowany w GTK. Trochę czasu zajęło mi zrozumienie, że wyświetlanie listy plików za pomocą widgetu gtk.TreeView oznacza też zaprzyjaźnienie się z modelem danych gtk.ListStore, którym zresztą też nie operuje się tak łatwo, jakby się chciało.

O wiele bardziej kłopotliwa była jednak obsługa wątków. Zapewnienie płynności działania GUI podczas operacji takich jak kopiowanie plików wymagało zastosowania wątków. Umieściłem zatem pętle odpowiedzialne za czasochłonne operacje w oddzielnych wątkach generowanych za pomocą konstrukcji:

threading.Thread(target=funkcja).start()

Zaowocowało to jednak mnóstwem błędów, pojawiających się w trudnych do określenia warunkach. Na szczęście pomogło wykorzystanie funkcji gobject.idle_add() do wywoływania wszelkich akcji związanych z GUI, np.:

gobject.idle_add(self.copyWindow.hide)

Funkcja ta odkłada daną akcję „na później”, gdy system będzie mógł ją obsłużyć.

Kolejnym źródłem dziwnych błędów były funkcje sortujące pliki. Sortowanie jest przeprowadzane automatycznie podczas dodawania kolejnego elementu do gtk.ListStore. Samo dodawanie za pomocą metody append() jest bardzo proste, okazało się jednak, że próby sortowania są podejmowane nie tylko bezpośrednio po dodaniu całego nowego wiersza do listy, ale przy każdej zmianie kolumny. Dochodziło więc do sytuacji, gdy na liście była pozycja typu numer ścieżki bez tytułu utworu i nazwy pliku, a program próbował już dokonywać sortowania, nie czekając na wpisanie pełnych informacji o pliku. Tu rozwiązanie było bardzo proste: wystarczyło wyłączać sortowanie przed zmianą zawartości listy, a włączać po niej, np.:

self.model.set_sort_column_id(-2,gtk.SORT_ASCENDING)
self.model.clear()
self.model.append("pole1","pole2","pole3")
self.model.set_sort_column_id(1,gtk.SORT_ASCENDING)

Równie kłopotliwy, co listy, okazał się pasek stanu. Dodawałem do niego pola tekstowe gtk.Label za pomocą metody pack_start(), nie mogłem jednak uzyskać ich wyrównania do lewej strony, gdyż znaczną część paska stanu od lewej strony zajmowała dziwna pusta przestrzeń. Debugowanie wykazało, że jest tam umieszczany jakiś domyślny element (zapewne do wyświetlania tekstu ze stosu), który, na szczęście, można schować:

self.statusBar.get_children()[0].hide()

Podczas korzystania z RiverCopiera wyszło też na jaw wiele źródeł potencjalnych problemów, jakie mogą pojawić się na skutek wprowadzania nieprawidłowych ścieżek, błędów dostępu itp. Starałem się je wszystkie obsłużyć.

Osoby zainteresowane wykorzystaniem programu lub lekturą kodu, zapraszam do pobierania tarballa z mojego wiki. Znajdziecie tam także opis, jak wymusić automatyczne włączanie RiverCopiera po podłączeniu odtwarzacza do komputera.

Komentarzy: 2 do „RiverCopier“

  1. Lanx komentuje:

    Trzeba bylo najpierw troche pogooglowac :)
    http://fatsort.berlios.de/

  2. vmario komentuje:

    Ale czy fatsort posortuje po tagach (w szczególności: po numerze ścieżki na płycie), czy tylko po nazwie pliku? Poza tym z RiverCopierem chyba jest nieco wygodniej ;)

Dodawanie komentarzy

XHTML: Możesz używać tagów: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">