雖然Mono官方不再提供 CentOS/RHEL 4.x 的 rpm 了,你還是可以自己重新 build。
在我看過 spec 檔案以後,我發現 Mono 開發團隊已經有加上對 Linux 發行套件的判斷,也就是說其實你可以直接下載 source rpm,安裝必要的函式庫之後,執行 rpmbuild –rebuild xxx.src.rpm 來 build 出 rpm。
source rpms 放在 這裡。
電影流水帳(2009/5/12~2009/5/22)
可以寫成電影流血帳嗎??會不會太血腥呢??
- 畫皮(IMDB)。這片很有意思,該有的大牌都有了。我喜歡周迅,這部片裡,她很難得的有性感的樣子甚至全裸,不過可惜就是聲音粗了點。第三個女主角是”孫儷”,女扮男裝的樣子挺俏皮,我居然沒能認出她,她曾經演過霍元甲的月慈。蠻好看的一部片,看完以後,很讓人唏噓,原來一切都是因為愛。
- The Last Templar TV miniseries(IMDB)。女主角是 1967 年生的 Mira Sorvino,開頭沒多久穿小洋裝騎馬的畫面讓人印象深刻,接下來的演出,看起來很有知性的魅力,這也難怪後來會在土耳其跟男主角野戰了。男主角跟 Mira 一起查案時,正好在守天主教的四旬齋,我以為只有佛教才有吃齋的習慣,這真的是讓我認識到了。到了片子的最後,其實是在探討信仰的問題,而寶藏其實只是偽造的耶穌福音。真正的寶藏是什麼呢?
- X-Men Origins: Wolverine(IMDB, Wikipedia),中譯:X戰警-金剛狼。嘴裡雖然說這種大片應該要去電影院看,結果還是把這個外流的版本給看完了。看完以後的心得是,這部片去電影院看會更好看!話說,金剛狼跟他老哥應該是吸血鬼吧,怎麼樣都不會死~
kernel 怎麼執行 hotplug?
因為只知道 hotplug 這關鍵字,直接以 hotplug 找,從 lib/kobject_uevent.c 裡可以看到放 “/sbin/hotplug” 的變數:uevent_helper。再往後找,可以看到 call_usermodehelper 使用了此變數。
call_usermodehelper 定義在 kmod.h 裡,是一個 static inline function。裡面則呼叫了 call_usermodehelper_setup 去設置環境,末了再呼叫 call_usermodehelper_exec 去執行。
p.s. 似乎不能在 IRQ 中斷處理常式裡去呼叫,會造成 kernel crash 掉,仔細想想,這樣有合理,因為 IRQ 中斷處理常式應該要盡早處理結束。如果是這樣,處理就比較麻煩了,可能就要利用 thread 跟 queue 來作。現階段,先不要作這個好了,雖然主動通知的功能很酷…
如何在 .Net 調用Yahoo!搜索 斷章取義 API
無心工作,剛好又看到有人問怎麼用,所以就牛刀小試一下。基本上用 WebClient 就可以搞定:
[csharp]
//
// Yahoo!搜尋『斷章取義』API http://tw.developer.yahoo.com/cas/
// Yahoo!搜尋『斷章取義』API 技術文件 http://tw.developer.yahoo.com/cas/api.php
//
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Text;
using System.Net;
namespace Yahoo {
public class CAS {
private string _GetString( byte[] bytes ) {
return Encoding.UTF8.GetString(bytes);
}
private WebClient GetWebClient() {
WebClient client = new WebClient();
// client.Proxy = new WebProxy(“localhost”, 8000);
client.Encoding = Encoding.UTF8;
return client;
}
private NameValueCollection GetParameters() {
NameValueCollection data = new NameValueCollection();
// TODO: Place your appid here.
data.Add(“appid”, “APgdNPnV34E7WQlhpBYaQvaRWPjwvd8exe094Q_r_7GWEOBFh9UDQY6vqNgZVwhc”);
return data;
}
public string WordSegmentation(string content) {
NameValueCollection data = GetParameters();
data.Add(“content”, content);
WebClient client = GetWebClient();
byte[] responseArray = client.UploadValues(“http://asia.search.yahooapis.com/cas/v1/ws”, “POST”, data);
return _GetString(responseArray);
}
public string Authenticate() {
NameValueCollection data = GetParameters();
WebClient client = GetWebClient();
byte[] responseArray = client.UploadValues(“http://asia.search.yahooapis.com/cas/v1/AuthBootUp.php”, “POST”, data);
return _GetString(responseArray);
}
public string KeywordExtraction( string content, int threshold, int maxnum ) {
NameValueCollection data = GetParameters();
data.Add(“content”, content);
data.Add(“threshold”, threshold.ToString());
data.Add(“maxnum”, maxnum.ToString());
WebClient client = GetWebClient();
byte[] responseArray = client.UploadValues(“http://asia.search.yahooapis.com/cas/v1/ke”, “POST”, data);
return _GetString(responseArray);
}
public static void Main() {
Yahoo.CAS cas = new Yahoo.CAS();
// 如果你重新申請 appid 的話,要先作 Authenticate
// Console.WriteLine( cas.Authenticate() );
Console.WriteLine( cas.WordSegmentation( “your_text” ));
Console.WriteLine( cas.KeywordExtraction( “your_text”, 30, 10));
// 得到的字串是 XML,要轉為 DataSet 的話,可以這樣作
/*
string text = cas.WordSegmentation( “your_text” );
TextReader stringReader = new StringReader(text);
DataSet dataSet1 = new DataSet();
dataSet1.ReadXml(stringReader);
// 轉好以後應會有兩個 DataTable,資料都在第二個 Table 裡,也就是 dataSet1.Tables[1]
*/
}
}
}
[/csharp]
電影流水帳(2009/5/1~2009/5/11)
要報稅了…最近看薪資單時,發現公司沒幫我預扣所得稅了…
- 愛情故事(IMDB, Wikipedia)。很清純、很淡的故事,情節有點老套,三個同窗互有情愫的故事,最後以阿Ling掛掉,Rex 試著與留學四年回來的小臻交往作終。女主角江若琳、文詠珊都很正,裡面還有看到外婆鄭佩佩,猛然想起她在唐伯虎點秋香裡的演出…,對了,片裡的江若琳有些神似Janet 謝怡芬。
- Bella(IMDB, Wikipedia),中譯:美麗.人生。帶有淡淡悲傷的故事,是足球明星的男主角因為沒注意,造成小女孩死掉,後來入獄,出獄之後為哥哥當餐廳廚師。某天,餐廳裡的某個女侍遲到,被當餐廳經理的哥哥開除,男主角想幫助她,於是展開這段故事,最後結局有些隱誨,但看得出來是女侍將孩子生了下來交由男主角撫養,並立下未來見面的約定。
Linux I2C 與 AD71471
AD71471 的 Device address 是 0x58,Linux driver 在處理這個時,其實會自行左移一位,因此,在 I2C_SLAVE_FORCE 的 ioctl 裡,應該是要傳 0x2c。這邊因為我暈頭,把 0x58>>1 算成 0x4c,導致我搞了好一陣子,直到 M 同事指正以後,才弄對。
再來,AD71471 在做讀寫時,Register address 與 data 都是 2 bytes,而 i2ctools 裡,處理 Register address 都只傳 1 byte(I2C_SMBUS),因此不適用在 AD71471 上。我把 Linux kernel i2c-core.c 裡的 code 翻出來改寫,改用 I2C_RDWR 來處理:
bool Write( uint16_t address, uint16_t value ) { int res=0; struct i2c_rdwr_ioctl_data msg_rdwr; char msgbuf0[I2C_SMBUS_BLOCK_MAX+4]; char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]; struct i2c_msg msg[1] = { { _address, 0, 4, msgbuf0 } }; uint8_t* pAddr = (uint8_t*)&address; uint8_t* pValue = (uint8_t*)&value; msg_rdwr.msgs = &msg[0]; msg_rdwr.nmsgs = 1; // write // read = 2 // 因為 little endian,所以要作調整 msgbuf0[0] = *(pAddr+1); msgbuf0[1] = *(pAddr+0); msgbuf0[2] = *(pValue+1); // (1) msgbuf0[3] = *(pValue+0); res = ioctl( _file, I2C_RDWR, &msg_rdwr ); usleep(10000); return true; } bool Read( uint16_t address, uint16_t& data ) { int res=0; struct i2c_rdwr_ioctl_data msg_rdwr; char msgbuf0[I2C_SMBUS_BLOCK_MAX+2]; char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]={0}; struct i2c_msg msg[2] = { { _address, 0, 2, msgbuf0 }, { _address, I2C_M_RD, 2, msgbuf1 } }; uint8_t* pAddr = (uint8_t*)&address; msg_rdwr.msgs = &msg[0]; msg_rdwr.nmsgs = 1; // read = 2 // 因為 little endian,所以要作調整 msgbuf0[0] = *(pAddr+1); msgbuf0[1] = *(pAddr+0); res = ioctl( _file, I2C_RDWR, &msg_rdwr ); usleep(10000); msg_rdwr.msgs = &msg[1]; msg_rdwr.nmsgs = 1; // read = 2 res = ioctl( _file, I2C_RDWR, &msg_rdwr ); #ifdef DEBUG data = msgbuf1[0] | (msgbuf1[1] << 8); return true; } int main( int argc, char* argv[] ) { int data=0; Read( 0x17, data ); printf("data=%d\n", data ); // 這邊其實不好,實際上寫 0x0052會比較清楚,這邊必須寫 0x5200,因為我在 Write() 裡有作對調,參看(1) Write( 0x00, 0x5200 ); }
GtkDrawingArea 與 gtk_widget_set_events()
GtkDrawingArea 預設是不收 button_press_event 跟 key_press_event 的,所以要使用 gtk_widget_set_events() 告訴 GtkDrawingArea 要接收才行。
這個,我是去 Google Code Search 找來的,雖然 devhelp 可以查指令,但沒有範例,還是很難猜到怎麼用。
#include <gdk/gdkkeysyms.h> // 定義按鍵值的 header static gboolean press_event( GtkWidget* widget, GdkEventButton* event, gpointer data ) { if( debug ) g_print("press_event: x=%f y=%f button=%d\n", event->x, event->y, event->button ); if( event->button==1 ) { // left } } static gboolean key_event( GtkWidget* widget, GdkEventKey* event ) { if( debug ) g_print( "event->keyval=%d event->state=%d\n", event->keyval, event->state ); switch (event->keyval) { // 省略... } return TRUE; } int main( int argc, char* argv[] ) { // 省略一萬行... g_signal_connect( drawing_area, "button_press_event", G_CALLBACK( press_event ), NULL ); g_signal_connect( drawing_area, "key_press_event", G_CALLBACK( key_event ), NULL ); // 要接收 button_press_event 跟 key_press_event 喔~ gtk_widget_set_events( drawing_area, gtk_widget_get_events(drawing_area) | GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK ); // 省略兩萬行... }
gtk 載入並顯示圖片
實際上是用 GDK+GtkDrawingArea 來畫,所以在下面的程式片斷,你會看到我宣告了 GtkDrawingArea 並且實作了 GtkDrawingArea 的 expose 事件。
GDK 支援的圖片格式很多,常見的 jpg、png、bmp 都沒問題。
static gboolean expose_event( GtkWidget* widget, GdkEventExpose* event, gpointer data ) { GError* error=NULL; int width=widget->allocation.width, height=widget->allocation.height; GdkPixbuf* buf=gdk_pixbuf_new_from_file_at_scale( "your_photo.jpg", &error ); if( buf==NULL ) g_print("load fail.\n" ); else { bufWidth = gdk_pixbuf_get_width( buf ); bufHeight = gdk_pixbuf_get_height( buf ); gdk_draw_pixbuf( widget->window, NULL, buf, 0, 0, 0, 0, (width>bufWidth?bufWidth:width), (height>bufHeight?bufHeight:height), GDK_RGB_DITHER_NORMAL, 0, 0 ); g_object_unref( buf ); } } int main( int argc, char* argv[]) { GtkWidget* drawing_area=NULL; // 省略一萬行 g_signal_connect( G_OBJECT(drawing_area), "expose_event", G_CALLBACK( expose_event ), NULL ); // 再省略兩萬行... }