小松鼠嚇了一跳,有了魔法眼鏡後,這世界看起來完全不一樣了

2011年12月14日 星期三

我的小電腦們: Palm IIIc

我的第二台小電腦是 2000年買的 Palm IIIc,當時價格大約一萬多一點台幣。同時間買了我的第一台數位相機,價錢也是一萬多。那台相機讓我瞭解了兩件事情

2011年12月6日 星期二

台北捷運路線圖

台北捷運路線 (非官方,但很清楚,似乎 IE 不適用)

最近很多關於捷運的淡水線、新店線、南勢角線將要分家的新聞。
從某種角度來說,還真要給台灣的媒體一點鼓勵。不久前,我走在路上,聽到消防車一台一台的呼嘯而過,看來情況緊急。到底發生了什麼事了呢?我心理想。看來是嚴重的大火吧。身為數位科技時代的一份子,連忙拿起手機打開蘋果新聞 APP 查看即時新聞,想說能感受一下身處資訊時代的便利性。
結果頭條即時新聞是舒淇沒穿內衣
我相信這對舒淇本人來說,應該是很重要的事情。我有過幾次衣服穿反走在路上的情況,也有幾次外出時,忘記帶足內衣褲的經驗,感覺都是慌亂中帶點尷尬和不舒服。更何況是忘了穿內衣。從新聞所描述的險露股溝來看,狀況更是十分危及。新聞媒體善盡社會責任,急忙提醒舒淇小姐,這我們是可以理解的。
但問題是,雖說對舒淇本人來說很重要,對廣大的其他讀者而言,並不是那麼重要。除非他設定的讀者群是幼稚園的小朋友,那麼記得穿內褲的確是個很重要的課題,很有教育意義。
但大多數會認字的人,都會記得穿內褲,所以不成立。
二來,根據新聞所述,這是前一晚發生的事情,對舒淇本人來說,這個消息也大概也緩不濟急了。因為我想昨晚舒淇小姐洗澡的時候,應該已經發現了這個事實。
總之,我找不到任何關於失火的消息,這令我對台灣的新聞媒體相當失望。
沒想到沒過多久,台灣的新聞媒體居然會關心起攸關民眾生活上便利的問題,而且不僅沒有發生那種超過保存期限問題,而且是明年才會發生的事情。
關於這兩點,我們給予鼓勵。
但還是有幾點必須給予譴責。
我們對辦報的人,總有崇高的敬意。新聞從業人員,不但富有把關資訊的責任,更有引導輿論、啟迪民智的任務。像是梁啟超的辦新民叢報、戒嚴時的黨外雜誌、現在也有像是立報、破報的。和群眾相比,他們站在非常前面。雖然不見得是最前面,方向是否正確也見仁見智,但總有一股帶頭領隊的氣勢。雖然不見得能帶領大家到達應許之地,但至少能讓大家看到外頭的風景。
反觀現在有些主流媒體,以這次捷運分家來說,他們是跟著隊伍中後段的屁股走。我相信有一大堆的人,都可以理解所謂捷運分家的原因,知道平行轉乘和 L 形網路。這個一大堆可能是 10%、20%,甚至更多。
當然也有很多人不那麼理智。搭火車時,三不五時會碰到搭錯車、搞不清楚狀況的人,這無可厚非。很多人自知不太擅長這些,所以會跟團、跟領隊走就好了。但如果領隊自己也搞不清楚狀況,跟著亂闖一通的團員走,還高聲要團體其他人也一起走,那問題就很嚴重了。
現在也是這樣。聯合報不知道發了什麼瘋,偏頗的披露捷運分家的消息,製造莫須有的民意,創造虛幻的輿論來反對淡水線和新店線分開,搞得多愁善感的市長也跟著起舞,說捷運分家要踩煞車。
拜託,記者朋友們,如果你不是很有把握,不要危言聳聽,亂製造輿論。
網友製作的平行轉乘示意圖 :

2011年12月5日 星期一

Acer Stream Kernel on Github

https://github.com/tjwei/acer-stream-minimal-kernel

時間回到我寫 Porting custom rom to Acer Stream 的時候,由 Acer 的官方 Stream 的 kernel source 來看, Acer 的 kernel 像是從 msm-eclair_chocolate 改來的,但不確定是哪個 commit 改來的。我大致上比較了一下,看起和 msm-57e7a9f 差不多,外加一些 patch。
所以如果你只是要自行編譯 stream 的 kernel,只需抓回並解開  msm-57e7a9f,然後把 acer 的 source 覆蓋上去,然後執行
make acer-q8k-a3-dvt_defconfig && make -j12 即可。
當時 msm-eclair_chocolate 最新的 master 版本是 eea0918,我試著把 57e7a9f 和 acer 官方 kernel 的差異補回 eea0918,功能似乎完全也正常。現在放在 github 上的 fullpatch 這個 branch 上。
由於這次的成功,所以我如法泡製,修改某 msm-froyo 版本。但由於版本差異過大,無法成功開機。

2011年11月30日 星期三

我的小電腦們: Casio FX-7000GA

這一陣子很忙,空閒時間,也會被小孩哭聲切斷,所以完全沒有辦法繼續弄之前的 kindle 和修改 Acer Stream 的 kernel。當然,Blog更新的頻率銳減也是同樣的原因。
由於時間破碎,所以只能刷刷 xoom 的 3.2.2 rom,再灌上 debian 和 tightvnc,或者把 ipod mini 刷 rockbox 放黑白電影這類不太需要專注力的事情。
不過因為幫老 ipod mini 換上新生命,外加手握 kindle、xoom、ipad 2,讓我回想起之前把玩的一些小電腦們。
我的第一台小電腦應該算是這台:Casio FX 7000GA。其實因為已經不在手上,FX-7000G 的兄弟姊妹又多,長得又像,所以也不確定正確的型號。印象中應該是這台。
說來 FX-7000G 來頭可大的呢,1985 問世時,可是世界上第一台繪圖計算機。我的 7000GA 是 在 1992 以生日禮物的身份入手。不過雖說是生日禮物,由於太貴,我也出了一半費用。
回憶起來,我當時還沒有想要有手持小電腦的欲望,甚至說,根本連這種 My lovely little computer 的概念都沒有。那時有台個人電腦就很先進了。
但 FX-7000GA 是台不折不扣的小電腦,因為他可以寫程式。他的程式碼看起來像是這樣:
Ans->X
1->Y
Lbl 1
X>5=>Goto 2
XY->Y
X+1->X
Goto 1
Lbl 2
Xln X-X+ln (2pi÷X)÷2+((((1÷1188X²-1÷1680)÷X²+
           1÷1260)÷X²-1÷360)÷X²+1÷12)÷X-ln Y
當時寫了一些小程式,只記得其中有個是猜數字遊戲。忘了他的程式上的繪圖功能可以到什麼程度,但是當時應該是沒有寫什麼圖形方面的程式。
除了當時的想像力不夠之外,畢竟機器的硬體限制太大。首先是所有的輸入功能都一定都要等待使用者回應,所以動作遊戲是不可能的。
再來就是可程式化記憶體實在太小,只有 422。422M 拿到現在的 android 系統都還可以用, 422K 在當時是個人電腦等級的記憶體。FX 7000G 系列有的是 422 bytes。現在看來當然覺得小得不可思議,但當時來說,沒有只給你 422 bits 就要謝主隆恩了。
總之,當時除了寫些小程式外,計算機的功能還真的沒什麼用。雖然程式也沒寫出什麼可以用的東西。最後,只記得某次電池用完後,一直沒有換,後來年代久遠,搬遷幾次後就不知所終了。

從現在的角度來看,優點是續航力非常好,跟一般掌上型計算機一樣,用個一年兩年換次電池並不是太稀奇的事。可攜性極佳,螢幕大小不差。可玩性(可以寫程式的能力)尚可。
缺點是機乎沒有連線擴充的能力。

2011年10月19日 星期三

松鼠URL 2011-10-19

80848600
Adora Svitak: What adults can learn from kids Alison Gopnik: What do babies think? Richard Seymour: How beauty feels Pamela Meyer: How to spot a liar

2011年9月21日 星期三

Porting custom rom to Acer Stream

No download available yet.
以前剛接觸 Linux 時,興沖沖的重新編譯完 kernel,往往會發生開機只出現 Li 兩個字的慘劇 (原來應該是顯示 Lilo 後跑出一堆開機訊息,但是連 Lilo 四個字母都跑不完,機器就停在那裡了。)
由於 Acer Stream 都沒人弄 rom,只好自己弄。

一開始傻傻的編譯了一份 AOSP 的 system.img,想說至少可以開機吧,沒想到頗類似當年的 Li。所有程式無法執行,gdbserver 是跑起來了,只是跑起來才發現我是用 adb shell 進去而不是 ssh,網路根本沒跑起來。
還好現在網路發達,大部分的問題網路上都找得到答案。
當然找答案也是要有點方向。

一開始經由官方版本和AOSP的 linker/bin/lib 等等的組合,外加readelf 之後發現官方版本和自己編出的 linker 的 entry point 不同。 大致上猜出是 shared library 放置的記憶體位置問題。

搜尋了一下,發現這是 android prelink 以及 VMSPLIT_2G 的問題。所以這方面把 prelink map 平移一下即可。另外我也 complie 了一份 VMSPLIT_2G=n 的 kernel。
再 來就是 RGBA8888 的問題。 Stream 的 kernel 回報不正確的解析度,而且固定為 32bit 色彩 RGBA8888。32bit 用 #define 寫死了,無法 ioctl 設定。因此把這些 #define 改了,重編成 RGB565 的格式。
最後就是 Acer 的 kernel 大概因為用 zip 壓檔的緣故,很多檔案不見了。Linux 的 kernel 中有些檔案,檔名僅僅只有大小寫不同,但卻是兩個不同的檔。碰到這種除了大小寫外完全相同的檔名,Acer 用的 zip 就會只挑其中一個放入 zip 檔中。所以只好從其他地方的 source 補回來。

這樣之後,只要選對 kernel,很多 2.2 的 custom rom 都能開機到 GUI。我試過了
AOSP (full_passion, 改 prelink map),
liquid metal 官方 2.2
liquid miui 
malez recovery (正常顯示)

基本上都沒怎麼改就能跑 GUI,不過當然硬體也都不太靈。

也試了 liquid metal 的 2.3.3 leak,不過不成功。
大概 kernel 至少要弄到 2.6.34 才行。

2011年9月17日 星期六

ClockworkMod Recovery for Acer Stream

Download here (Warning! Very experimental. Use at your own risk.)

Install:
Use fastboot (or Rom Manager?) to flash the recovery image. See ClockworkMod Recovery for more information.


Acer Stream 這隻手機,就像 Kindle DX 一樣,出來時也都算風風光光,也一度是名義上的旗艦機種,但因為銷售不理想,很快都被原廠打入冷宮,停止更新。現在完全找不到 Acer Stream 的 Custom Rom,所以,只好自力救濟一下了。由於我對 Android custom rom 幾乎毫無經驗,所以先從 Recovery image 開始。
Acer Stream 的特點:
  • image header 是 4K
  • Framebuffer 的 bits per pixel 似乎固定為 32。VSCREENINFO 傳回的 xres 和 yres 不可靠,預設是 1280x800, 但其實 lcd 的解析度是 480x800。OS_RESOLUTION 的傳回值才是對的。framebuffer 的 第二頁的起始值固定在 1280x800x4 bytes 的位置。大部分 recovery image 畫面會壞掉的原因在此。我猜大概要支援 HDMI 的緣故。
  • /data 不是 mtd@userdata 而是 mmcblk1p1 。
原本打算用 malez recovery 來改,但發現好像沒有提供 source。所以抓了野火機的 ClockworkMod Recovery Image,並且抓下 source 重新編譯 recovery。(主要的困難是 kernel.org 被駭,花了一點時間才抓到完整的 source。)
我只修改了 graphics.c ,修改的部份如下:
    if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
        perror("failed to get fb0 info");
        close(fd);
        return -1;
    }
    // should use OS_RESOLUTION ioctl to get xres
    vi.xres=480;

    bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (bits == MAP_FAILED) {
        perror("failed to mmap framebuffer");
        close(fd);
        return -1;
    }

    fb->version = sizeof(*fb);
    fb->width = vi.xres;
    fb->height = vi.yres;
    fb->stride = vi.xres;
    fb->data = bits;
    fb->format = GGL_PIXEL_FORMAT_RGBX_8888;
    memset(fb->data, 0, vi.yres * vi.xres * 4);

    fb++;

    fb->version = sizeof(*fb);
    fb->width = vi.xres;
    fb->height = vi.yres;
    fb->stride = vi.xres;
    fb->data = (void*) (((unsigned) bits) + (fi.smem_len>>1));
    fb->format = GGL_PIXEL_FORMAT_RGBX_8888;
    memset(fb->data, 0, vi.yres * vi.xres * 4);

    return fd;
}

static void get_memory_surface(GGLSurface* ms) {
  ms->version = sizeof(*ms);
  ms->width = vi.xres;
  ms->height = vi.yres;
  ms->stride = vi.xres;
  ms->data = malloc(vi.xres * vi.yres * 4);
  ms->format = GGL_PIXEL_FORMAT_RGBX_8888;
}

static void set_active_framebuffer(unsigned n)
{
    if (n > 1) return;
    vi.yoffset = n * vi.yres;
    if (ioctl(gr_fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
        printf("active fb swap failed %d\n", n);
    }
}

void gr_flip(void)
{
    GGLContext *gl = gr_context;

    /* swap front and back buffers */
    gr_active_fb = (gr_active_fb + 1) & 1;

    /* copy data from the in-memory surface to the buffer we're about
     * to make active. */
    memcpy(gr_framebuffer[gr_active_fb].data, gr_mem_surface.data,
           vi.xres * vi.yres * 4);

    /* inform the display driver */
    set_active_framebuffer(gr_active_fb);
}

賽德克‧巴萊 太陽旗

熱血‧巴萊
雖然電影並未特別標榜或宣傳揚熱血,但最真實的熱血在這部影片中被呈現出來了。
而且是赤裸真實,未經多餘烹煮的原始熱血。由於太生了,所以會讓很多吃慣七分熟熱血的人,難以下嚥。是那種真的會流血、拋頭顱的後所灑的熱血。
不老騎士很熱血吧,因為看正常人看到他們騎車的英姿,都會很怕他們不能繼續老下去。荒野大飆客(Wild Hogs)雖然也是一樣長途騎車來奪回青春,但是光是騎騎車感覺就沒那麼熱血,直到他們生命受到威脅時,不顧危險的奮戰,才開始讓人覺得熱血。
所以難怪台灣熱血界第一品牌九把刀的名言是「人生就是不停的戰鬥」(或報仇)。因為熱血這種情緒本來就源自於不是你流血、就是我流血、大家多少都會留點血的狩獵搏鬥。賽德克巴萊中很忠實的呈現了這種情緒的原始風情,就像電影中的真實場景一樣。
我們現代男人骨子裡也還留有一樣的血液,只是用比較「文明」的方式包裝著。或者更貼切的說,因為文明的關係,只能用比較迂迴的方式來「模擬」原始的熱血。比方「蔣為文黃春明事件」,看似有點脫序離譜,其實不過是男人在爭奪以及守護自己的如天邊彩虹般的虛擬獵場--台灣文學論述權。我舉這個例子並不是因為他們特別野蠻,而是因為他們特別文明(作家以及教授)。無數的現代男人在馬路上、職場上、球場上、遊戲中、電視前(觀看運動比賽或者政治),不自覺的依照原始獵人的本能,在更複雜難解的文明森林裡,爭奪虛幻的虛擬獵場。而現實世界中的真實獵場早己集中於少數資本家及獨裁者手中。
賽德克人在電影中,遇上了從真實獵場到文明虛擬獵場的過渡期。在真實獵場裡驍勇善戰的獵人們,在文明的虛擬獵場中卻成了被宰制的輸家。影片中藉由花岡兄弟為代表的模範番,說明了接受文明的狩獵規則也是一條充滿不公平與忍耐的漫長道路。實質的獵場是註定失去了,雖說還能靠著勝利者的施捨苟活(或者說像狗一樣活著,「連獵犬都看不起」),但這是以彩虹另一端的虛擬獵場作為代價所換來的(「二十年後就不是賽德克了」)。由此,不難理解影片中至少要保住彩虹那端獵場的想法。
廢刀令及西南戰爭時的日本武士是如此,哪天外星人來佔領地球,讓你驚覺到所謂天經地義的社會規範(或「普世價值」)原來並非真實獵場時,你也會有做出相同舉動的衝動來保護僅剩的虛幻獵場(假如你還有熱血的話)。
電影中也藉由老一輩的頭目級人物、花岡一輩有家室和事業者、年輕一輩想成家者、巴萬這樣的小孩等四個不同階段的男人,來描述不同的熱血。相當細膩。

歌舞過多?
片中的歌曲和舞蹈也傳達出動人而豐富的情感,也對於劇中人物的情感做出了闡釋。當然也可以選擇用內心戲、旁白、字幕或台灣長壽劇常見的自言自語的方式呈現劇中人物的心裡轉折和想法。能用微妙的內心戲表達自然最好,但觀眾你摸著良心自問自己看穿人心善解人意的讀心術真的很強嗎?所以用其他方式傳達會比較有效而且有效率。本片用歌舞相當的適當,但也許還是部份人會接收不到。

出草不文明?
這是事實,至少從現代的角度來看,的確不文明。
不過對科幻類作品有一定視聽量的人,對於這種程度的文化差異應該是司空見慣。因為像 Star Trek 這種等級作品的常見的把戲,就是對於外星文明的文化差異來個為拍新戲強說愁。
舉個天元突破裡的例子。一個村莊裡出來了新生兒,大家卻歡喜中帶有憂愁。因為村子中的規矩是,總人數不能超過兩百人(?)。 所以多了兩個人,就要抽兩個號碼,處死這兩人。結果抽到兩個可愛的小朋友(又沒有像飢餓遊戲裡可以自告奮勇取代的規則)。結果外來的主角群當然無法接受,覺得太慘忍。但其實由於與外界封閉,村莊所能生產的資源,只足夠兩百人生存。只要多出一人,整個生態圈會崩潰。為了救兩個人,會讓 202 個人都死掉。
看似野蠻的習俗,其實自有道理。
從另一個角度來看出草,不也是在有限的資源下,讓最強的生命留下,達到適者生存的演化目的,讓整個種族更強?
我們現在強用科技留下原本無法生存於自然中的生命,是否是反演化?是否會導致整個人類族群滅亡?其實也很難說。
現實生活中要真心接受文化差異很難,但至少在電影中看看,應該還沒那麼難跨越,也才能接受影片傳達的情感。

2011年9月13日 星期二

朋友悖論與先承認你就是你朋友


今天在報紙上看到一段話:
伴侶盟的調查不只問受訪者自己的同居經驗,也問其親友的同居經驗,發現兩者有相當大的落差。套句鄉民的術語,這是所謂「你承認你就是你朋友吧」的現象:網路上許多敏感話題的提問,往往發文者會以替朋友上來問的方式,以避免自己「曝光」或「出櫃」的窘境,而實際上問的乃是自己本身的困擾。美國研究同居最重要的學者,前人口學會會長Larry Bumpass教授當年開始到日本做調查,也發現日本人不願意說自己在同居,但卻有極高比例報告親友在同居。同居伴侶所覺知到台灣社會對他們的不友善,有這個鄉民世界的對比可見一斑。  --- 同居伴侶權益 立法保障       2011-09-13     中國時報     【李瑞中】
 讓我聯想到朋友悖論。 簡單的說,就是就是平均來說,你的朋友數量會比你朋友少。這樣說有一點繞口令。或者這樣講好了,平均來說,每個人交往過的對象,會比他交往對象的(平均)交往次數少。
所以說,當你興致一來,將你過去所有交過女友調查一番,把她們交往過的男友次數平均一下,發現遠比你交過的女友多,或者把你 facebook 上所有好友的好友數平均一下,發現自己似乎人緣不佳,請不要太灰心,因為這只是簡單的數學事實,圖論上、統計上的簡單定理。不代表你有低於平均值的人緣。也許這就是人比人會氣死人的理由之一。
回到報紙上的那段話。受訪者自己的同居經驗和親友的同居經驗有落差,會不會也是受到相似因素的影響?不見得完全是因為話題敏感的原因?
因為即使每個人都完全誠實,你也很可能會得到受訪者平均的交往過的對象有 5人,但是問其親友(包含前男女友)的交往對象數量,卻有 10 人,這種現象。
而同居關係和親友數量是否互相會影響?似乎也很難排除。

2011年9月12日 星期一

幾個關於 Kindle 3 firmware on Kindle DXG 的 Hack

之前由 Yifan Lu 發布的 Kindle 3.X updater 實現了讓 Kindle DXG/2 也能使用 Kindle 3.x 的 firmware。這應該是很多人的願望,對一般使用者而言,也遠比我之前的 kindle 3 Open Source on DXG 實用。
但是有三個問題:

2011年9月1日 星期四

WebKit for Kindle DX binary files

下面的 tar ball是一套可以在 kindle dx 執行的 directfb, gtk+, webkit 環境:
WebKitGtkKindleDXG.tar.xz
使用方式
  1. jailbreak, ssh 到你的 kindle DXG (2.5.8 版本)
  2.  解開 tar ball,放到一個 loop file system 下,然後 mount 到 /usr/local
  3. mount -o bind /usr/local/root /var/tmp/root
  4. 執行 /usr/local/bin/gwebkit 即可,會打開一個 html 檔。
  5. shift+方向鍵控制游標。Sym 是 Tab。Menu 可以跳到 URL 輸入框。
  6. Alt-x  離開,Alt-a Alt-z Zoom in, out。Alt-l 刷新螢幕。
  7. 雖然可以使用免費的 3G 網路,但是由於怕違反 Amazon 的使用規範,所以預設關閉,只能手動啟動,
  8. 沒有內附中文輸入法,但是許多的 gtk+ 的輸入法 module 都可以用。scim 不能用的原因有兩個,stdc++ 的版本,我編譯的 DirectFB 只允許單一程式。我自己是寫了個 chewing 的 gtk+ im-module,但是還不完整,沒有附在裡面。
  9. 其他一些程式,也可以試試看,如 gtk-demo, leafpad, gqview, vte, gtkterm2 等。
  10. 基本上是使用 kindle 3 source code,修改過的 source 在 /usr/local/src 。
(更新*****)
GitHub Project: https://github.com/tjwei/WebKitGtkKindleDXG

2011年8月21日 星期日

WebKit Kindle DX backport

Kindle DX 的 netfront 瀏覽器雖然堪用,但是很多網頁讀不出來。
比方說我的部落格首頁就會出現記憶體不足的訊息,網頁呈現的效果雖然似乎挺清爽乾淨,但是 DX 螢幕有 824x1200 的解析度,足以顯示完整的網頁。
整體來看,還是 kindle 3 的瀏覽器較佳。一個作法是直接讓 DX 執行 kindle 3 的作業系統。非常神奇的是,居然沒有什麼問題。但既然 kindle 基於 open source,也釋出了修改過的程式碼,所以我試著將 kindle 3 的 webkit 移植到 dx 上。
初步的結果如下:

還不是很完整,但至少能在 google 裡打個搜尋,顯示一些網頁。
過程是 Directfb -> Gtk+ -> WebKit
  • 編譯環境; scratchbox
    • toolchain 用的是 glibc2.5 2007q1。雖然說 libstdc++ 和 kindle dx 的不相容,但 2006q3 太舊了,很難編譯。而且 gtk+ 用的是 C 而不是 C++,webkit 雖然用 C++ 但是沒有用到 libstdc++ 而是自帶的程式庫,所以問題不大。這點從android 極為貧乏的 C++ runtime 可見端倪。因為顯然同樣是 WebKit based 的 Android web browser 不需要完整的 libstdc++。所以 glibc2.5 的 toolchain 應該都可以。
    • 在 amd64 的 linux 下使用 scratchbox i386 binary, kernel 要增加 vdso32=0 的參數,不然會有 Inconsistency detected by ld.so: rtld.c: 1192: dl_main: Assertion `(void *) ph->p_vaddr ==  的錯誤
    • 我的 cputransp 跑不起來,所以我自己編譯了一個 static linked x64 qemu-arm。然後寫了一個 wrapper 來吃 binfmt 餵進來  --sbox 的參數。除了 pthread 外,似乎沒什麼問題。跑 configure 時,一些 pthread 的測試程式會停不下來,也許是 qemu 的問題。當碰到這個問題的時候,都是手動修改 configure.in 裡面的測試程式,讓他直接通過。
  • 我在 /mnt/us 上弄了個 200mb 的 ext3 loop filesystem,mount 到 /usr/local 上。之後只要 設好 ld.so 或者設定 LD_LIBRARY_PATH=/usr/local/lib 即可,不會影響原系統。
  • 編譯 DirectFB
    • 用的是 kindle 3 的 source。設定 --prefix=/usr/local,gfxdriver=none
    • 編譯所需的 jepg 和 libpng 時,設定 --prefix=/usr。libpng 需要 1.2 版的。我當初一時不察,用了 libpng 1.4 ,所以修改了一點 DirectFB 的程式碼解決 libpng 1.2 的相容問題,還要額外的安裝 libpng 1.4 到 /usr/local
    • 編譯上沒有什麼問題,然後把 /usr/local copy 到 kindle 完成安裝上。可以利用 ssh+tar 或者 ssh mount 來複製檔案。
    •  kindle 的 eink framebuffer 是 4bit 灰階,無法被 directFB 直接支援,所以只好當成 indirect fb 來使用。如果你在這裡花上零點五秒來想想該怎麼解決這個問題,你會發現 amazon 的 lab126 想的解法和你一樣。他用了一個 LUT8 (8bit indexed color) 的 virtual framebuffer 來假裝是真正的 frame buffer,然後就能順利建構 DirectFB 。接下來只要設法讓 virtual frame buffer 和真正的 frame buffer 來互通有無即可。lab126 用的是 call back 的方式讓使用者程式自行決定如何處理。雖然從程式碼來看, lab126 取得 frame buffer address 的方式似乎有點不保險。
    • kindle 3 的 eink 比 DX 多了好幾種 update eink screen 的方式。
    • lab126 版的 DirectfB 基本上有考慮到 DX 的按鍵,除了一個 keymap 的檔案。所以要修改這個檔案,不然之後有些按鍵會出問題。我順便把 Sym 鍵設成 Tab。
    • 要用 no-vt 模式執行。可將 no-vt 加入 ~/.directfbrc 裡面。 
  • 編譯 GTK+
    • 編譯基本上沒有太大的問題,但是很繁雜。有些 kindle 3 source 沒有 autogen.sh 或者 configure 時,就 aclocal && autoconf && automake。還不行,就抓一份相同版本的正版 source ,然後把 lab126 版 copy 過去。
    • DX 的 glib 太舊了,要弄個新版的到 /usr/local 裡。在 scratchbox 中,我也順便把新版的 glib 裝到 /usr/ 下,之後編譯會比較輕鬆。
    • 雖然沒什麼道理,但 gtk-doc 似乎不裝到 /usr/ 下,automake 就抓不太到。雖然常常 configure 時可以關掉 gtk-doc,但有時需要 autogen 的時候, 不裝個  gtk-doc 就過不了關。autogen 應該是設計來簡化問題的,而不是用來增加問題的。 
    • automake 版本要用 SBOX_DEFAULT_AUTOMAKE 設定到 1.9。不然會有 tar-ustar 錯誤。
    •  直接編譯完,執行 gtk-demo 會出現像是 這裡的情形。我的作法是在 gdk_init 裡面加上自己的 kindle dirty rect callback ,把更動過得方塊更新到 eink screen 上。這樣, gtk-demo 就能正常顯示。
    • 如果前面 directfb 的 keymap 沒改好,會發生 gtk-demo 裡面上下鍵無法使用的狀況。
    • 我遇到了 字體都變成方格這個問題。google 查詢到,似乎某些 pango + cairo 的組合會發生這種情形,所以我將 pango 和 cairo 換成稍微新一點的版本。lab126 有更動 cairo 程式碼,不過看起來只是 hack 某些 font 資訊的問題,不是什麼致命的問題,所以我直接使用無修正板。
    • 我設定了 gtkrc-2.0 ,讓字體大一點,也設定了 fontconfig 來使用 /usr/java/lib/fonts 中相對應的字型。
    • 除了 gtk-demo,我試了 leafpad,gtkterm, gqview。 leafpad 和 gtkterm 都能正確編譯執行,但是視窗要修改或者設定成大一點,最好是全螢幕。原因是 gtk游標會在螢幕正中間,如果 gtk 程式的視窗太小,會因為鼠標沒有在視窗上而抓不到 keyboard focus。這大概是 directfb的 wm 的特性。gqview 也可執行和操作,但是似乎圖形顯示有問題。gtkterm 需要 vte,編譯 vte 時,需要 termcap。雖然用 ncurses 取代 termcap 也行,但是 ncurses 我編不起來,也懶得弄。除了 gtkterm 外,vte 本身應該也能跑。和 kindle 上其他的 terminal 程式相比,vte based terminal 的一大優點是可以顯示正確顯示 utf8 中文。LXDE 的 gpicview 雖然標榜純 gtk,但其實有用到 X11。光是 gdkx.h 也就罷了,其中有用到 X11 的檔案,所以無法直接編譯。gedit 因為需要 gtksourceview 一堆的,看起來太複雜了,就沒有真的弄起來。
  • WebKit
    • 查看 kindle 3 的 source code 裡的 Changelog,到 2009年5月18日,所以下載了 webkit r43841。
    • 解開後將 kindle 3 裡面修改過的 source 複製並且覆蓋過去。
    • 修改 configure.ac,讓 directfb 變成 default。因為 build-webkit 似乎沒有這個選項。
    • 執行 WebKitTools/Script/build-webkit --gtk,我選擇關掉 xslt還有一些不需要的選項。
    • make 過程會出現錯誤,因為一些 .h 檔沒有放對位置。可以修改 GNUMakefile 或者 source,或把 .h ln -s 到適當地位置。總之,依個人喜好,讓他編譯過去就是了。
    • 還有一些錯誤是 kindle profiling 相關的,我直接刪除相關的部份。
    • GtkPerf 的 link 會出問題,要把 .libs/libWebcore.a 連進去。
    • make install 後把 /usr/local copy 到 kindle 就行了。
    • 編出來的 GtkLauncher 可以執行,但是 kindle 的 proxy 需要特別的 x-fsn http header,所以暫時還不能上網。可以嘗試用 GtkLauncher 瀏覽 kindle 裡面的 local 檔案,要用完整檔名。如果發現只看到 html 的 source code,那是因為沒有 mime data。將你電腦裡面的 /usr/share/mime copy 去 kindle 即可。
    • 這個版本的 webkit settings 沒有支援 user-agent 修改,也沒有支援 proxy,更沒有支援客製化的 http header,所以修改程式碼送出適當的 header,和使用 proxy。
    • 修改被 lab126 修改過的 GtkLauncher 程式碼,讓 urlbar 顯示出來。
    • urlbar 可以輸入,但是 google 搜尋框無法輸入文字。經 google 查詢後,發現是 ICU 問題。我用的是 ICU 3.6,在 scratchbox 中無法順利編譯,因為 pkgdata 無法執行。我修改 makefile,讓 pkgdata 能順利執行,完成 make。但是顯然我漏了什麼。依照這裡的方式,重新編譯。這時,輸入框就能輸入了。
    • 我不曉得如何用鍵盤完整的操作,GtkLauncher,即使打開 caret browsing,也不知道怎麼操作,介面還需要修改。中文輸入法也還沒整合進去。 

2011年8月15日 星期一

Kindle DX 的酷音中文輸入法 (2)

(上接 Kindle DX 的酷音中文輸入法
(更新** GitHub 專案 https://github.com/tjwei/KindleChewing )
檔案 Source and Binary 在此 目前預設是使用許氏鍵盤,可用 Sym 切換漢語拼音。我沒有包入普通的注音鍵盤,因為 kindle 上面數字鍵比較不好打,而且鍵盤上沒有標注音符號。普通的注音輸入法,沒有特別不能用的理由,但雖然 alt-q alt-w 的方式,可以正確輸入 1,2 等等數字,但 . < ; - 這些鍵不能直接輸入,所以還是有些音打不出來,需要用其它鍵代替。
更新:
  • 修改 post key event 的方式,讓一些 kindlet 也能使用。
  • 簡單的處理了螢幕旋轉的狀況。
原理說明:
  1. khk.jar 是一個假的 msp.jar。msp.jar 就是 kindle 裡面的採地雷/五子棋小遊戲。Kindle 會在使用者介面啟動時,載入 msp.g 這個 class。msp 大致上還能猜出跟 Mine Sweeper 之間的關聯,但是一個 class 叫 g 就有點怪。不過這是由於 kindle 的程式碼被弄亂過得原因。總之,這個是寫死的。這個 class 不能叫做 msp.h, msp.g2, msp.gg, msp2.g,就只能叫做 msp.g,不然 kindle 主程式不會主動過來招呼你的,因為跟你不熟。當然你也可以假裝成為其他 kindle 認識的人,比方說像是 browser, pictureviewer, pdfreader, mobireader 之類的,甚至是 home,但比較起來,採地雷看起來最人畜無害,所以選擇假扮 msp。
  2. 假扮 msp 的方式參考 http://www.mobileread.com/forums/showthread.php?t=61093 ,但只有精神上類似,因為 kindle 內部改了很多。不用完全模仿 msp 的格式,任何 class 都行。只要記得把 meta info 包進去就行了。反正重點只是要讓 kindle 呼叫 g() 這個constructor。名稱叫 khk 的原因是要搶在 msp.jar 之前載入,先搶先贏。如果你叫做 msp2.jar,就只能繼續玩踩地雷了。不過這算是不太保險的 hack。因為沒有人保證 khk.jar 一定會在 msp.jar 前面載入。完全只是因為 kindle 啟動 script 裡面的 booklet/*.jar 造成 cvm 的 command option 中, khk 會比 msp 前面。
  3. khk 可用,msp 就不能用了。當然,其實可以修改 msp 程式碼,讓 msp.g 載入我們的程式碼之後,繼續他原來的功能。但這樣就失去這種方式的意義了。這個輸入法的優點就是不用修改主程式碼。
  4. 這版的 khk 用到了 AppContextBridge 這個(隱藏?)功能。不然我不知道怎麼送 keyEvent 到 kinlet 中。
  5. im 參考了 launchpad kiterm 。不過修改了很多地方,可能只剩下(沒用到的) daemonize,還有 screen 和 pixop。
  6. khk 是用 eclipse 然後包進所有的 kindle jar 用 cdc 1.0 模式編譯。
  7. im 是用 scratchbox 編譯。kindle dx 的 libstdc++ 分常舊,雖然網路上面常常看到推薦的 toolchain 是 scratchbox-toolchain-cs2007q3-glibc2.5-*,但裡面的 libstdc++.so 是 6.0.9,而 kindle 是 6.0.8,不要看這 8 和 9 差不多,這可能會造成一些 c++ 的程式發生 version `GLIBCXX_3.4.9' not found 錯誤。所以我用 scratchbox-toolchain-arm-linux-2006q3。如果不用 c++ 的話,似乎是沒什麼問題。用 c++ 也不見得總是會有問題。
  8. 原本想試試看加入 google 語音輸入,但錄了辦天才發現 dx 沒有辦法錄音。kindle 3 才行。不過錄音的時候,也不會產生錯誤訊息,只是沒有聲音而已。 原則上,khk 配合 curl, 和 flac 即可達到語音輸入的功能。kindle 內的 busybox wget 似乎無法送出客製化 header,不然連 curl 也不需要。
  9. freetype的用法 是參考 freetype 的教程和這篇
  10. DBus 的使用方式是參考這篇。 雖然 glib 裡面有 dbus 支援,但是 kindle dx 的 glib 太舊,所以只好用 C API了。
CanBeFound 的 kindle 3 的中文輸入法 的比較:
  1. CanBeFound 的方式是修改 SymbolPopup 的方式來處理。這是一個好的方法。事實上,我的第一個想法也是如此,畢竟 symbol popup 是 kindle 裡面長得最像輸入法的東西,其實這也是我之前弄磚 kindle 的原因。 慘的是磚了之後才發現已經有人完成這個想法。
  2. 我的方式的最大優點是,source 可以公開。因為完全不用修改 kindle 的程式碼。 
  3. 第二個優點是使用 D-Bus 做訊息溝通。所以其他程式只要寫個 D-Bus 處理器就能使用。而且對於 kindle framework 的依賴可能比較小一點。
  4. kindle 裡面的程式,可以選擇輸入時不使用 symbol popup。這時,symbol popup based 方式就無效。比方 kindle 的 home 介面,你可以直接叫出酷音輸入文字,然後搜尋框就會跑出來。Sym 鍵則是要在搜尋框出來後,才能叫出 SymbolPopup。
  5. 但除此之外,都是 CanBeFound 使用 SymbolPopup 的方式比較直接比較好。
  6. 大部分輸入文字的地方,如果程式師不特地亂搞,照規矩來,其實都可以叫出 SymbolPopup。所以第 4 點沒有太大意義。
  7. SymbolPopup 可以很容易編譯。msp 比較麻煩一點。其實也可以把 DBus 處理的部份讓 SymbolPopup  來啟動。但主要的考量是能否公開程式碼的問題。
  8. 使用 SymbolPopup 的優點是簡潔。kindle 裡面的 eventqueue 不只一條,至少 msp.g 能抓到的那條,無法處理 kindlet 的訊息。所以我必須要用到 AppContextBridge 來跨越 context 送訊息。看起來似乎不太腳踏實地,也增加了對於 kindle framework 的依賴。而 SymbolPopup 的好處是,程式需要符號輸入時,會自己去把你叫出來,這就不用擔心什麼 context, thread group 什麼的問題了。
  9. SymbolPopup 因為在 Kindle 的框架內,所以不用擔心旋轉顯示的問題,也能在適當的位置顯示。我的外掛的方式,因為有個內奸在裡面,所以某種程度上也能整合的不錯,但比較累。
  10. CanBeFound 的輸入法可以在 browser 內輸入,但是我的 dx 沒辦法。我想應該是 browser 的問題。因為我也有讓 symbol popup 輸入中文字的測試程式,但是在 dx 的 browser 裡面,只有符號能輸入,中文不行。不過問題是我的外掛輸入法在 dx 的 browser 裡,連英文也無法輸入,這點我就不太清楚為什麼了。

2011年8月10日 星期三

Kindle DX 的酷音中文輸入法


這是一個基於酷音輸入法的 kindle DXG 2.5.8 的中文輸入法。檔案 Source and Binary 在此
目前預設是使用許氏鍵盤,詳細的原理與使用方式之後再詳述。
(和 這個 kindle 3 的中文輸入法原理不同,各有優缺點)

使用方式:

  1. ssh 進 kindle
  2.  mntroot rw 然後將 khk.jar 放到 /opt/amazon/ebook/booklet 下。
  3. 將 mnt/us/chewing 下的 .so 和輸入法資料檔放到  /mnt/us/chewing
  4. 將 im 執行檔放在任何地方都可。
  5. /etc/init.d/framework restart
  6. 執行 LD_LIBRARY_PATH=/mnt/us/chewing ./im
  7. alt-shift-space 可叫出輸入法,sym 切換許氏/漢語拼音 。Aa 切換中英文。
 Bug:
  1. 瀏覽器裡面無法使用,應該是 kindle dx 的瀏覽器 netfront3 的問題。不過搜尋列可以使用。
  2. 我還沒有處理螢幕旋轉,所以螢幕選轉後,要 alt-shift-space 兩次叫出輸入視窗。
  3. 閱讀器裡面直接輸入中文不會跳出搜尋窗,不過先用英文按出搜尋窗之後,就能輸入中文。

(下接: Kindle DX 的酷音中文輸入法 (2))

2011年7月13日 星期三

OpenNI + F# 3d mesh Test


修改之前的程式,將 points cloud 改成簡單的 mesh,配合 image texture。效果似乎好點。
程式碼中用到 F# powerpack 的 PSeq 和 Array.Parallel,簡單的利用平行處理加速。
執行檔和 source 下載
執行時需要 .Net 4.0
OpenNI (只要 binary 和 Hardware binary)
Sensor Kinect Driver

2011年7月12日 星期二

用 F# 和 Kinect +OpenNI 產生 Point Cloud

這和前一篇 用 F# 和 Kinect SDK 產生 Point Cloud 是幾乎一樣的程式,只不過改用 OpenNI 而不是用 Kinect SDK beta。 OpenNI 支援將色彩和深度資訊重合,所以出來的結果比之前手工亂搞的正確得多。但是似乎沒有 Kinect SDK 的 ready callback 機制,所以用 background worker 取代。
OpenNI 似乎也不支援 80x60 的解析度。

2011年7月11日 星期一

用 F# 和 Kinect SDK 產生 Point Cloud


本文附的 F# 程式碼,是用 Kinect SDK 來產生 "points cloud"。
程式的效果如影片。
過程中的一些紀錄:
  • 因為之前的 visual studio 2010 過了試用期限,所以我有一段時間沒用 F#, 稍有一點生疏,但這問題不大。問題是我沒有寫過 .net 上的 GUI 程式,更別說是 3D 繪圖了,所以花了一點時間在網路上找範例。 F# 的 GUI 參考資料似乎不是很多,很多似乎也不太靈。
  • Kinect SDK 和 driver 簡單好用,骨架判斷似乎比之前 OpenNI 容易(沒有打錯字,這不是用來判斷股價的軟體),在狹小空間(像是大多數寫程式的地方)就能辨認出骨架。
  • 根據 Wikipedia,Kinect 的 depth sensor 橫向角度 57度,垂直角度 43度。
  • 網路查詢結果,System.Media3D 似乎無法直接畫出「點」,沒辦法做出 point cloud。所以用 squares cloud 或者 cubes cloud 來代替。
  • 我的筆記型電腦 GPU 太差,最多只能跑 80x60 的 cubes cloud。所以影片中解析度很差。
  • 設法將 Video Image 和 Depth Image 組合,發現不吻合。理論上應該要用 Color in Depth Space 或者 Depth in Color Space 的參數來設定 Kinect,但是網路上查詢的結果是, Kinect SDK Beta 還不支援這些。
  • 也許應該改用 OpenNI,但是程式碼已經寫了一半了,繼續用手工的方是將色彩和深度組合。
  • 色彩和深度的圖形居然是鏡像(x軸方向相反)?應該是我哪裡搞錯了。
  • 由於沒有硬體規格,解析度太低也很難實驗,所以用觀察和嘗試錯誤法很粗糙的將色彩資訊以及深度資訊勉強組合在一起。
  • 之後改用 OpenNI 試試看。

2011年7月7日 星期四

用 kindle 顯示 LyX 的 PDF Preview

  •  環境為 Win 7 32bit, LyX 1.6.9,  Python 2.7, Cygwin, Kindle DX
  • Kindle DX 安裝 usbNetwork hack
  • Cygwin 安裝 openSSH
  • 將 ssh 環境設定成無密碼登入 kindle,要在 kindle 的 usbnet/etc 下設定 authorized_keys
  • 將下面的 python 程式用 py2exe 或者 cx_freeze 包裝成 exe 檔
  • 在 LyX 裡面,將 Tools -> Preferences -> File Handling -> File Format 下的 pdf (pdflatex) 的 viewer 由 pdfview 改成我們的 exe 檔的路徑。
  • 如此就完成了,LyX 的 preview 會自動傳送到 kindle,然後自動更新書目。

2011年6月27日 星期一

我的 Kindle DX 復活了

自從買了 Kindle DXG 後,使用率一直很高。不過說來也是我不小心,後來發生了一件慘劇。
原本有些小構想,決定要改寫 Kindle 裡面的一些 java 程式。
於是,我將 /opt/amazon 備份了一份成為 /opt/amazon2,然後將使用者介面停止。
一開始的計畫將修改的版本放入 /opt/amazon2 內,然後copy 並修改相關的 script裡面的 path。這樣,我就有一份可以修改的使用這介面,不會影響原本的系統。
由於都是 user mode 的東西,想來應該很安全,即使 script 失敗,最多就是程式終止罷了。
為了怕有些地方 path 沒改到,執行了原本的 /opt/amazon 裡的程式,所以我又將 /opt/amazon 改成 /opt/amazon0,執行 /opt/amazon2 的版本試試看。
結果執行新的 script ,失敗了,這不意外,因為難免會漏掉一些地方沒改到。
意外的是,機器非常迅速的重新開機。
這只能怪我沒有事先注意到這個起始使用這介面的 script 有個當掉會自動重開機的保護機制。由於只是一瞬間的事,我來不及將 /opt/amazon0 改回,所以機器就磚了。
總之,錯在於我過於大意,沒有將 usbnetwork 設為開機自動啟動。
上網搜尋了一下,找到所謂的進入 recovery mode的方式:按住電源 30 秒,然後長按 Home。
然後我就讓他回復了原廠設定。可惜回復原廠設定不包含讓 /opt/amazon 回復。
Recovery mode 可以讓你用 usb 傳入更新檔,然後更新。可惜這個階段的更新檔的格式和普通那種 font hack 之類從使用者介面選單更新的那種不同,update maker 還不支援。
想說送廠維修曠日費時,而且因為是自己 hack 的結果,所以難免有點心虛。所以就想自力救濟。
依照這個網頁的說明,拆解了 kindle 的塑膠頭蓋。沒有 iPad 拆解工具,所以就用一字起,指甲和卡片完成工作。
這張圖的最上端中間,j9 那個區域,有四塊明顯的方形金屬片,用這個區域來連 serial console。所以需要 USB to TTL 裝置,電壓需要 3.3v版本。四個金屬片由左至右分別為,3.3v, TX, RX, GND,所以要依序連上 USB to TTL 端的 3.3v RX TX GND(我其實不太懂,但就我的印像是 TX<->RX)。
理論上來說,應該要焊上去比較牢靠,但是我的銲錫和電烙鐵不知塵封何處,而且我之前只是拿來焊接舞台魔術道具的一些電線,所以其實技術非常糟糕。或者應該要做個像是這樣的接頭,但同樣我也沒有工具。
所以我剪開一條壞掉的網路線,抽出幾條短電線,然後在卡紙上用針穿了四個孔,把導線頭穿過針孔,然後膠帶貼好,用剪刀把導線頭剪齊,作成了這樣的接頭

這樣的接頭當然十分不穩,所以要一隻手用點力去讓導線頭和 kindle 上的金屬板接觸。更不幸的是,由於擺設方向的問題,我必需要用右手做這件事。也就是說,鍵盤、滑鼠、重開 kindle 的動作必須由左手來負責。
經過一點練習後,終於能成功的讓 hyperterm 連到 kindle 的開機畫面。
不過發現 login 時,會問密碼。
網路上搜尋了一下,發現真的要連進 shell ,要使用先進入  uboot 互動環境。
進入的方式是在 reboot 後第一時間按下 enter(也許是任意鍵,不過反正 enter 也是任意鍵)。
按的時間不對的話,會進入 developer mode,那是壞得更嚴重的時候才需要的。
在 uboot 下輸入
uboot> setenv bootargs $(bootargs_base) root=/dev/mmcblk0p1 rw init=/bin/sh
uboot> bootm 0xa0060000
這兩行指令就可以進入 shell 了。當然,由於我只有左手能工作,所以那兩行我是先 copy 起來,讓鬥在 hypterterm 裡面貼上。
經過漫長的努力後,終於看到睽違已久的 #  shell 命令列提示符號,不用再 root ,也不用再 remount ,不過 PATH 沒有設定,所以輸入完整的 /bin/mv 把 /opt/amazon0 改回 /opt/amazon。
然後 shutdown now, reboot 都無效,只好按電源紐重新啟動。其實有點緊張,不過很順利的重新開機。
唯一的遺憾是之前在 recovery mode 時,似乎把下載的藏書以及 font hack 等等都刪除了。不過amazon 的帳號資料還在,所以跟 amazon 買的書都還會在。

2011年6月25日 星期六

將 Python 3.2 的 keyword 換成 中文

這是一個用到 ctypes 的 hack,將 python 3.2 的一些 Keyword 換成中文,然後可以用中文寫程式。
Source

50 行純 python code 做中文手寫


用 50 行 python 3.2 source code 實作中文手寫辨識的核心,外加訓練也是五十行以內,演算法同 Zinnia。完整 Source Code

2011年5月21日 星期六

松鼠URL 2011-5-21

安全的幻影
Bruce Schneier: The security mirage


由於演化的關係,動物對於什麼是安全、什麼是危險有相當敏銳而正確的直覺。所以不需要理論、模型這一堆東西幫忙。人類其實也是....假如我們還生活在石器時代的話。其中一個和古時候的差別就是大眾傳播媒體。人類有一個很實用的經驗法則(或稱捷思)叫做可利用性法則(availability heuristic),簡單的說,就是如果你很熟、很快就能聯想起來的東西,應該就是比較重要的東西。比方說你常常聽說村子裡面有人被老虎吃掉,但是很少聽說有人被兔子吃掉,那老虎就比較危險一點。但是大眾媒體把一切都搞砸了。新聞顧名思義,就是報導罕見的事情。車禍天天發生、天天死人,沒什麼稀奇的,飛機比較少出問題,所以才會大幅報導。但是因為媒體從早報到晚,混淆了我們的可利用性法則,混淆了我們的直覺。
吃路邊或者速食可能比手機的電磁波危險的多。把 511 當成只是另外一天的人,遠比贊同王老師大地震說的人多,至少一開始是這樣的。但是媒體只會報導稀奇、不正常的事情。普通我們聽到王老師的講法,只會當成瘋子,根本不會去理會,但經過電視、報紙連續幾天的連環轟炸,混淆了我們的直覺,即使理智上你還是知道這完全是無稽之談,但你的「可利用性法則」會強迫你把這當成一件事情。

嬰兒的語言天才
Patricia Kuhl: The linguistic genius of babies


一歲前的嬰兒正在建立語言模型,重點是,對於嬰兒的語言學習,電視不但無法取代真人互動,而且是跟本完全沒有用。要有真人互動才拿打開嬰兒學習語言的開關。

笑容的隱藏能力
Ron Gutman: The hidden power of smiling


裡面提到,笑得越開懷的人,將來成就也會越高、壽命也會越長。乍看之下,似乎是個誤謬:因為健康較好、成就較高的人自然會笑得比較燦爛一點。
不過裡面用科學分析了笑容的反饋效應,告訴我們笑容會在腦中帶來快樂感,超過巧克力和金錢所能帶來的效應。
另外笑容也有感染力,能夠讓人心情平靜快樂。
之前結婚時,負責辦婚宴的小姐臉上總是掛著略帶誇張的笑容。可以說是有點「職業」,但我覺得是好的那種。因為大多數人結婚都是第一次,即使結婚很多次的人,也至少有一次是第一次。第一次做一件事時,有點緊張或者慌忙是自然的。穩定的笑容能夠有效的紓解不安。

如何綁鞋帶
Terry Moore: How to tie your shoes


五十歲的大叔終於發現自己(和多數人)以前鞋帶都沒有綁對。

Sean Carroll: Distant time and the hint of a multiverse

為什麼有時間這個東西?

2011年5月15日 星期日

Python: 下載 youtube 上的台灣電視節目

在坐月子中心,老婆想追一下之前連續劇的進度。月子中心裡的網路有限制,用 p2p 軟體不但佔用頻寬,而且不太可行的。雖然 cattail 在 android 上推出 台灣連續劇 app,但沒帶 hdmi 線,而且用我之前寫的 acer stream hdmi test,解析度不夠。雖說如此,既然影片已經在 youtube 上了,就有辦法看得到。
簡單看了一下,發現影片資料庫的網址。下載了 drama.db 後,用 sqlite database browser 檢視一下後,簡單寫個 python script 來生成 m3u8 檔。 現在的 VLC 已經能直接播放像是 http://youtube.com/watch?v=XXXXX 的 URL 。所以生成的 m3u8 也的卻能播放,不過由於網路速度太慢,播放斷斷續續的,無法盡如人意。所以乾脆寫個程式來下載 youtube 的影片。雖然 youtube-dl 很成熟,但用殺牛的大刀來切雞肉,有點太大材小用了,況且放入自己的程式碼中,還要花點時間讀程式碼。Youtube 的 HTML 碼改過不少,網路上一下也搜尋不到怎麼解析來源 flv 或者 mp4 的方式,所以乾脆就直接看 HTML source,配合上 regexp 來擷取影片 URL,也可以選擇自己想要的解析度。
雖然也可以配合 vlc 的 python binding 來播放,但是下載並且產生 m3u8 檔已經符合我的需求。
程式在 windows 7 下的 python 2.6 及 Ubuntu 的 python 2.7 測試過。在不同的機器下,除了一開始的幾個 path 外,也許檔名(drama_m3u8 和 fn)和 sys.argv[1]   的 encoding 也可能因為系統而不同也需要更改。
****
 2011-09-27補充
該資料庫已經不再繼續更新
*******

最後寫出的 python script 如下:

# -*- coding: utf8 -*-
import sqlite3
import re
import urllib
import sys
import time
import locale

DB_FILENAME=r'./drama.db'
OUT_DIR=ur'./'
PREF_FMTS=["35","34","5"] # youtube format: flv 480, flv 360, flv 240

def best_url(fmt_dict):
    k=filter(fmt_dict.has_key, PREF_FMTS)
    return fmt_dict[k[0]] if k else None

def try_to(f, n=1, message="do the work"):
    for i in range(n):
        try:
            return f()
        except:
            print "failed to %s (#%d)"%(message,i)
    return None

def get_fmts(v):
    url="http://youtube.com/watch?v=%s"%v
    read_url=lambda :urllib.urlopen(url).read()
    parse_fmt=lambda s: (s[0],urllib.unquote(s[1].decode('unicode_escape'))
                                     .replace(r'\/','/'))
    try:
        s=re.compile('"fmt_url_map": "([^"]*)"')\
            .search(try_to(read_url, 10, "read %s"%url))
        return dict(parse_fmt(x.split("|")) for x in s.group(1).split(","))
    except:
        print "failed to parse formats"
        return {}

def get_episodes(drama_name, ep_list=None, part_list=None):
    pbar=lambda p,k,t:"#"*int(p/2+0.5)+"."*(50-int(p/2+0.5))\
          +" %5.1f%% %6.1fKB/s %3d:%02d\r"%(p,k,t/60,t%60)
    def report():
        sec0=time.time()
        return lambda n, bs, size: sys.stdout.write(
                     pbar(min(n*bs*100.0/size,100.0),
                          n*bs/1024.0/max(1.0,time.time()-sec0),
                          int(time.time()-sec0)))
    conn=sqlite3.connect(DB_FILENAME)
    c=conn.cursor()
    query='''select pltitle, plvids from playlisttable
                                    where pltitle like ?
                                    order by plds'''
    c.execute(query, (u"%%%s%%"%drama_name,))
    enum_eps=((i+1,row) for i,row in enumerate(c) 
                        if not ep_list or i+1 in ep_list)
    for ep,row in enum_eps:
        print "[ep=%d]"%ep, row[0]
        drama_m3u8=OUT_DIR+ur'%s.m3u8'%row[0]
        vids=row[1].split(",")
        allparts=range(len(vids))
        vidnames=[row[0]+u" (%d).flv"%i for i in allparts]
        open(drama_m3u8,"w").write(u"\n".join(vidnames).encode("utf-8")+"\n")
        pl=set(allparts)&set(part_list) if part_list else allparts
        for part in pl:
            fn=OUT_DIR+vidnames[part]
            print fn
            url=best_url(get_fmts(vids[part]))
            if not url:
                continue
            if try_to(lambda :
              urllib.urlretrieve(url, fn, report()), 3, "get %s"%url):
                print "\nDone"
            else:
                print "\nFailed"
    conn.close()
    
if __name__ == "__main__":
    enc=locale.getpreferredencoding()
    try:
        drama_name=sys.argv[1].decode(enc) if len(sys.argv)>1 else u"犀利人妻"
        ep_list=map(int,sys.argv[2].split(",")) if len(sys.argv)>2 else None
        part_list=map(int,sys.argv[3].split(",")) if len(sys.argv)>3 else None
    except:
        print """Usage: tvshow_download showname [ep_list [part_list]]
Example: tvshow_download 犀利人妻 3,4,5  #download episode 3,4,5
         tvshow_download 犀利人妻        #donwload all episodes
         tvshow_download 犀利人妻 13 0,1 #download part 0,1 of episode 13
""".encode(enc)
    print "args:",drama_name, ep_list, part_list
    get_episodes(drama_name, ep_list, part_list)

2011年5月7日 星期六

Android 上的 midi

Android 2.2 上的 midi播放不太好聽,至少我的 acer stream 是如此。Android 系統採用 sonivox 的 EAS 來軟體合成 midi 音樂的,而且是使用 wavetable。但使用的wavetable格式不是比較常見的 SoundFont 而是 DLS。DLS 其實也是標準,而且 Windows 就內建有 gm.dls。 EAS預設的 wavetable 寫死在程式碼裡面,而且似乎就是 gm.dls。抓下 android 的 source 之後,就能編譯裡面的 eas_main.c 使用,來測試軟體合成的功能。
不過實際嘗試後發現無法使用,原因是 PlayFile 有點小 bug,要在
    file.fd = 0;
後面加上
    file.length=0;
    file.offset=0;
就行了。
接下來就是想嘗試改用比較好的 dls 檔,看看音色會不會改善一點點。雖然不期待改善太多,因為 android 中的 EAS 只能使用 22khz 的 sample rate。首先嘗試的是 windows 中的 gm.dls。可以用 EAS_LoadDLSCollection 順利載入,不過音色完全沒有改變。
想說換換其他的 DLS 檔看看,但是網路上不太容易找到 DLS 檔,找了很久只找到 dlsbyxg.dls, fury.dls, 還有兩種 ff8.dls。
很可惜,這幾個 dls 都無法在 EAS 中順利載入,分別會有不同的錯誤傳回碼。
沒有在詳細追錯誤的來源了,看來要改變計畫,直接編譯 fluidsynth 或 timidity++ 看看好了。如果能成功的話,再看看能不能做個 EAS 的介面讓 android 的 media player 直接取用?

2011年4月22日 星期五

與 Python shell-like pipe 類似的東西

多年前寫了一個 python shell like pipe (minipipe),主要是可以讓 python 有像是
ls|wc
ls|tail(n=5)|sort
cat/"*.py"|grep("def")
grep("pipe")/"*.py"/"/usr/include/*.h"
grep("^a","aaa\nbbb\nccc\nabc".splitlines(), open("text","rb"))
這樣的語法。
最近看到一個極為類似的東西,Pipe: Infix syntax for Python
我的 minipipe 其實比較複雜一點,原因是
  • 為了能直接打 ls 就能在 interactive shell 中直接顯示結果,也可以寫成 ls|wc 而不是 ls()|wc
  • 多了 /"*.py" 這樣的運算
  • 能和吃 iterator 的普統函數直接作用(也就沒有加上 @pipecmd decorator 的)。原因在於minipie 的傳回值都是 pipe object  (PipeCmd),即使碰到普通函數,會自動把魔法傳下去。
 類似的還有 python-pipeline/ 這個。
以相似度來說,我的 minipipe 和 ASPN Recipe: Shell-like data processing 其實原理和用法上都有差異。 Recipe 中的 cat, ls 等等,是個別的 class。而 minipie 主要的概念是 class 包函數(這個概念是 OO 語言中的常見方式),運算的傳回值都是
Pipe: infix 用法和原理類似 minipipe 。差異是,他傳回的值是 iterator 而不是 pipe object。好處就是,傳回值預期的類型。缺點是,一旦變成普通物件,就失去魔法了。他的 | 就是另外一種 function call 的語法,一些語言一樣 function calling語法 (haskell 太久沒用忘了, F# 是 |>) 。
python-pipeline 程式碼比較複雜,不過看起來用法差不多,原理沒仔細看。
回頭看了一下自己以前寫的程式碼,看起來還是很醜。

2011年4月21日 星期四

語錄 2011-4-21

 "Any sufficiently advanced financial instrument is indistinguishable from fraud." ---(來源
「高興就又跑又跳,悲傷就又哭又喊,那是上野動物園猴子幹的事。流行歌詞,笑在臉上,哭在心裡。說出心裡相反的言語,做出心裡相反的臉色,這才叫人哪。」--- 小津安二郎
"The use of condoms is acceptable in exceptional circumstances" --- 教宗 Benedict XVI
比方說想要用水球攻擊異教徒,但手邊剛好沒有氣球時,在這種情形下,因為情況緊急且特殊,可以特別通融,允許用保險套來代替氣球。
"All that is necessary for the triumph of evil is that good men do nothing."  --- Edmund Burke
Or when good men start doing evil things.
"The secret to creativity is knowing how to hide your sources."  ---愛因斯坦
怪不得現在的新聞都好像連續劇一樣。
"An eye for an eye makes the whole world blind."   --- 甘地
也許全世界都沒有眼睛反而好,小混混(或者狗)會因為你用眼睛看他, 就覺得你不尊重他、挑釁他,暴力爭端因此而產生。
"Whatever you do will be insignificant, but it is very important that you do it."  --- 甘地
 "Creativity is allowing yourself to make mistakes. Art is knowing which ones to keep." --- Scott Adam
"Decisions are made by people who have time, not people who have talent."   --- Scott Adam

「人之所以不幸,是因為他不知道他是幸福的;僅僅是這個原因。這就是一切,一切!誰要是明白了這一點,他此時此刻馬上就會變得幸福起來。 」 ---  費奧多爾·米哈伊洛維奇·杜斯妥也夫斯基

「我有一個計畫,就是做一個瘋子。讓人們去狂怒,讓他們來醫治。」 ---  費奧多爾·米哈伊洛維奇·杜斯妥也夫斯基
「人人需求同一,人人都是一個樣,誰若感覺不同,誰就進瘋人院。」  ---尼采
「抗議和無理取鬧的猜疑,或有嘲弄癖好的人是健康的。那些無聊件接受所有事物的人,是有病的。」  --- 尼采
“The true man wants two things: danger and play. For that reason he wants woman, as the most dangerous plaything.” --- 尼采
「在這個世界上,總有一條除了你以外,別人無法走的路。途中千萬別詢問路究竟通向何方,只顧走下去吧!  」  --- 尼采
「最後的旅程,也許很苦,也許孤單,但那是你自己的選擇,你必須自己一個人,獨自把它走完……你必須把自己選擇的路走完,你才能找出自己的道」  --- 孫曉,英雄志 論述正道
「一些人統治是由於他們願意統治;另一些人統治是因為他們不願意被人統治---對於他們來說,統治不過是兩害中之輕者」 --- 尼采
「我秦仲海只要想到一件事,夜里便會偷偷地笑,哪怕多刺十個字,再斷一條腿,我也感到值得!那便是秦仲海此生不必跪人!好好想吧!你們這幫人書讀得再多、武功練得再高,這輩子還是得跪人!不過求一口飯吃,頭便要按得那麼低,你們甘心麼?大家一樣是人,那幫賊只不過投胎投得​​好了,便能高高在上,頤指氣使,你滿腹經綸,一身武功,卻要日也怕、夜也怕,忍氣吞聲,這種人生便如在豬堆裡打滾,縱使富貴滿門,卻又有何滋味!來!學我吧,志氣點,將那一把怒火燒起來,打打殺殺一樣可以度日,誰能奈何你呢?」 --- 孫曉, 英雄志中論述造反的理由