Cos sie konczy, cos zaczyna.

Revision, revision... i po revision.
Zakończył się pewien etap z życiu - domknąłem rozdziały związane z demosceną i emulacją. Brak czasu i zmiana priorytetów życiowych wymusiły takie "drastyczne" ruchy.
A więc po kolei:
- Cenotaph - Demo na GBC ( większość kodu jest mojego autorstwa) zajęło 4 miejsce w oldskool demo competition
Nagranie "live" z party:
- 4K Seminar - 15th Anniversary of MAME project ( start okolo 17 minuty )
Polacy nie gesi

Skąd ten tytuł ? Pochodzi z publikacji Piotr Rypsona "Nie gęsi. Polskie projektowanie graficzne 1919–1949". Jest to bardzo dobre opracowanie polskiej szkoły graficznej z lat 20,30 i 40 ubiegłego wieku. Znaleźć można w niej dziesiątki przeróżnych ilustracji, reklam czy nawet druków urzędowych! Dokładniejszą recenzję wrzucę niedługo do działu Po godzinach.
Revision 2012
Już za miesiąc Revison 2012 w Saarbruecken. Jak na razie ponad 500 zgłoszeń z całej Europy ( i nie tylko ). Samemu (a raczej z resztą ( Gilligan, Vodka, Wiklund ) ludzi z "reaktywowanego" po 12 latach Dual Crew Shining ) pracuję nad czymś do wystawienia w Oldksool Demo Compo. Zobaczymy czy coś z tego wyjdzie. Prawdopodobnie także projekt BEZDEN będzie miał swoje 5 minut
Poza tym - o wiele ciekawsza chyba sprawa - poprowadzę jedno z seminariów. W zasadzie będzie to krótki tzw Lightning Talk na temat (15 lecia) projektu MAME :
15 Years of MAME
Labour of love or chore? The truth behind the development of Multiple Arcade Machine Emulator.
What has been done and where are things headed? A look at the core design, past, present, and future of the MAME project.
Szczegółowe informacje ( godzina (prawdopodobnie niedziela, 14.00 ), numer sali konferencyjnej ) powinny niedługo znaleźć się tutaj:
#if czy #ifdef ?
Czego używać #if czy #ifdef ?
Ciekawe i bardzo proste rozwiązanie znalazłem na stronie Kayamona .
Definiujemy makra:
#define ON 2- #define OFF 1- #define USING(x) ( (x 0) == 2 )
Przykład użycia:
#define BIG_ENDIAN ON #if USING( BIG_ENDIAN ) // nasz kod #endif
Jakie są zalety takiego rozwiązania ? Wymusza na nas określenie parametru. Gdy o tym zapomnimy - program nie skompiluje się. Ominie nas ( wątpliwa ) przyjemność używania domyślnych wartości.
Perfekcyjne (?) kolory.
Od jakiegoś już czasu poszukiwałem dobrego zestawu kolorów do wykorzystania w GUI. Na sieci można znaleźć sporo dobrych ( i tych gorszych ) rad. W końcu trafiłem na SOLARIZED . Znajomy i miły dla oka zestaw. Planuję użyć go w jednym z projektów open source - barwy są stonowane i dobrze ze sobą współgrają.
(Free)glut – reshape.
Po kilku małych zmianach w kodzie multiplatformowego projektu ( iOS, Android, Win) wykorzystującego OpenGL ( oraz - tylko w wersji Win - freeglut ) doszło do dziwnego zdarzenia. Aplikacja przestała (podczas zmiany rozmiaru okna) wywoływać reshape callback zainstalowany funkcją glutReshapeFunc() . Projekt skompilowany z wykorzystaniem glut (a nie freeglut) działa bez problemu. Niestety, bez freeglut się nie obejdzie. Najprostsze rozwiązanie to obejście problemu - "ręczny" odczyt wymiarów okna i wywoływanie funkcji reshape. Co prawda nie jesteśmy w stanie reagować na wszystkie zmiany rozmiaru okna, ale podpięcie wywołań reshape pod główny timer aplikacji ( 30fps ) zdaje egzamin:
int w = glutGet(GLUT_WINDOW_WIDTH); int h = glutGet(GLUT_WINDOW_HEIGHT); reshape ( w, h );
Placement New.
Czym jest Placement New ? Jest to wersja operatora new, która pozwala na utworzenie obiektu we wcześniej zaallokowanym obszarze pamięci. Jeśli mamy własny system allokacji pamięci i nie chcemy przeładowywać operatorów new, delete i delete[] dla każdej z klas - najprościej użyć Placement New. Jedyny minus to konieczność ręcznego wywołania destruktora i pamiętanie o zwolnieniu zaallokowanej wcześniej pamięci ( podobnie jak przy new /delete
). Mały przykład użycia:
cTest * tmp = new ( myCustomAlloc( sizeof (cTest) ) ) cTest; .... tmp->~cTest(); myCustomFree( tmp ); tmp = NULL;
Lion + OpenOffice + Resume = ?
Jak wiadomo, jedną z nowych cech OS X Lion jest "resume". Po restarcie systemu, aplikacja zostaje przywrócona do stanu sprzed zamknięcia. "Wracają" wszystkie zamknięte okna i dane.
Niestety, u mnie wystąpił mały problem z Open Office (który to pakiet jest naprawdę mocno zabugowany) . Po restarcie aplikacji pojawił się (systemowy?) requester z opcjami do wyboru: przywrócenie stanu poprzedniego lub restart. Niestety. OO nie reagowało na wybór żadnej z nich i z uporem maniaka wyświetlało okno ponownie. Co prawda dało się odpalić Writera w tle, ale menu główne nie reagowało na nic.
Najprostsze rozwiązanie - usunięcie odpowiednich plików (z findera lub terminala). Dane te znajdują się w ~Library/Saved Application State w podkatalogach łatwo identyfikowalnych z daną aplikacją. Dla OO wszystko siedzi w org.openoffice.script.savedState. Wystarczy usunąć katalog wraz z zawartością - i po problemie.
Android Market – certyfikaty
Po kilku poprawkach do aplikacji i ponownym szyfrowaniu ( sign + align ) .apk nie chciał się zainstalować na urządzeniu - Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]. Sam proces "szyfrowania" nie zmienił się od poprzedniej wersji :
Sign:
jarsigner -verbose -digestalg SHA1 -sigalg MD5withRSA -keystore mykeys.keystore -signedjar test-signed.apk tes-unsigned.apk mykeys.keystore
Align:
zipalign -v 4 test-signed.apk test.apk
Upload:
adb install test.apk
I .. Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES].
Po weryfikacji za pomocą:
jarsigner -verify -verbose -certs test-signed.apk
pojawiło się kilka problemów z certyfikatem - każdy z plików zgłaszał [CertPath not validated: null] .
Plus podsumowanie:
Warning: This jar contains entries whose certificate chain is not validated.
Po przeszukaniu sieci i kilku testach okazało się, że android (a w szczególności market i narzędzia do podpisywania .apk) nie lubi się z JDK > 1.7 . Niestety miałem zainstalowany JDK 1.7.0.0 . Po doinstalowaniu 1.6.0.2i skorzystaniu ze starszej wersji jarsignera - wszystko wróciło do normy.
Instalacja .apk na karcie SD.
W nowej wersji aplikacji klient zdecydował się na umożliwienie instalacji na zewnętrznym nośniku - karcie SD. Sam proces jest szczegółowo opisany na stronie google . Z wcześniejszych założeń wynikało, że aplikacja powinna działać na różnych wersja systemu Android - począwszy od 1.6 (czyli Api Level 4). Jak do tej pory ustawinia minimalnej wersji OS-a (czyli android:minSdkVersion w AndroidManifest.xml ) pokrywały się z wersją OS pod która SDK budował kod wynikowy ( target w default.properties ). By umożliwić instalację na zewnętrznym nośniku, trzeba jednak użyc w AndroidManifest.xml tagów wprowadzonych dopiero w Api Level 8 (Android 2.2) - czyli ustawić target na "android-8". Atrybut android:minSdkVersion pozostaje bez zmian. Podczas kompilacji dostajemy co prawda ostrzeżenie o niższej wersji SDK niż zadeklarowany "target" kompilacji, ale - dopóki nie korzystamy w naszym kodzie z żadnych funkcji API wyższego niż Level 4 - możemy je zignorować.
Do AndroidManifest.xml musimy także dodać atrybut android:installLocation oraz ustawic jego wartość na auto lub preferExternal. Wybrałem opcję pierwszą - system sam decyduje gdzie zainstalować aplikację ( wybór zależy m.in . od ilości wolnego miejsca w internal storage), poza tym użytkownik sam może zadecydować czy (i kiedy) przenieść aplikację na kartę SD czy pozostawić ją w pamięci telefonu. Odpowiednia opcja kopiowania dostępna jest w ustawieniach (oczywiście jeśli używamy Androida >= 2.2 ).
