医院过年

闲言碎语 — ronnie @ February 4th, 2010

老婆前两天刚刚做了个小手术,要回复一个月左右,所以我们要在医院过年了。

这也是我们新婚后的第一个春节,没想到这么特殊,要在医院过。

这最近半年,又是找工作,又是我生病,老婆生病。半年经历了太多事情,感慨良多,最大的感受就是别的一切都是扯淡,身体健康是最重要的。

老婆刚做完手术,就接到了MSRA的正式offer,老婆一下心情打好,心情好有助于恢复啊,哈哈!

在医院不能上网,我就买了个联通的3G上网卡,爬上来看看。这个卡我的手机也可以用,这样过年就不至于太无聊了。

明年去学校后,一定和老婆好好锻炼身体!

District 9

Movie, game — Tags: — ronnie @ September 13th, 2009

要说这部《District 9》这部电影,必须从District Six说起,District Six是南非开普敦第六市政区(Sixth Municipal District of Cape Town),从1867年起就这么叫了。District Six住着以前的奴隶,工人,做生意的等社会下层人士,这些人来自世界各地,各种肤色,相当国际化。二战以后,南非这个国家开始实行一种种族隔离制度,要把District Six的居民强制搬到另外一个环境极其恶劣的鸟不拉屎的地方(天朝三峡搬迁是不是这样的),给出的理由很扯淡,说这里犯罪丛生,很不安全之类,实际上还不是看上了这块地段搞房地产开发。最后搬了很多年,搬了大约6万人(听上去很少)。最后当然这样的制度倒掉了,原来District Six的居民的合法权利也得到了承认,他们现在都在陆续搬回这块土地。

话说在种族隔离制度盛行的年代,有个南非小孩Neill Blomkamp把这些都看在眼里,记在心里。16岁的时候Neill已经是南非一位专业动画师了。18岁的时候Neill举家搬到了温哥华,他就到温哥华电影学校学习。毕业以后,Neill就在温哥华当地两个特效公司担任特效师。Neill擅长制作纪录片风格、手持摄像机风格、比较现实的真实特效。同时Neill还拍一些广告之类的小短片。

虽然现在种族隔离已经远离南非,但Neill当然还记得发生在南非的这些往事。Neill拍摄了一部短片来讨论这个主题,这部短片就是《alive in joburg》。Neill应该没有想到这部短片会改变自己的职业生涯,如果没有这部短片,Neill还得在特效界和广告界混上几年吧。

话说魔戒男Peter Jackson看到这部短片以后,被片子的那种纪录片拍摄方式、手持摄像机风格吸引,拍板让Neill来做著名游戏Halo电影版的导演。这个项目成立以后,不想没钱了,项目最终搁浅。Halo没得拍,魔戒男最后和Neill决定用不够的资金把《alive in joburg》改成电影《District 9》。敲定计划以后,Neill就开始干活了,他希望指环男的特效公司Weta负责特效,可是Peter告诉他不行,因为Weta正在忙着被变态级别上帝级别的詹姆斯卡梅隆的《阿凡达》折磨,哪能抽出功夫搞这个啊,不过可以负责设计角色。Neill只好找了母校所在地温哥华的一家特效公司Image Engine来做了。话说Neill也真是胆大,自己本来就是菜鸟导演,这次只是拍自己的第一部电影,居然找来了同样没有做过一部电影特效的菜鸟特效公司Iamge Engine;不过幸好Image Engine没有搞砸(Image Engine真是伟大,因为其制作特效用了开源软件,就把自己的一些工具也开源了,别的公司可没这么好的。)。这样,就有了Neill的第一部电影,也有了一部很棒的科幻片。

《District 9》的风格与《alive in joburg》相似,还是手提摄像机的拍摄方式,纪录片的风格,这次更把电影做的像电视新闻采访。情节是《alive in joburg》的扩展与延续,当然也要顺带讽刺种族隔离了。《District 9》可以说是近几年来最出色的科幻电影了,具体点是最优秀的外星人电影,把种族隔离制度揉进电影以后,让它一反一般外星人科幻片的套路,令人耳目一新。具体的剧情我就不透漏了,感兴趣的一定不能错过。(另:影片口味略重,最好不要再吃饭后一个小时内观看;承受能力强者除外)

一张海报

Movie, Research, game — Tags: — ronnie @ July 26th, 2009

这是1991年《黄飞鸿》的一款被放弃的海报,不过我觉得这是最好的一款。这款海报很好的体现了当时中国社会的中西文化冲突,这也是《黄飞鸿》这部电影能摆脱纯粹动作片的地方。

其实我是想测试一下lightbox2插件。

乱记

闲言碎语 — Tags: — ronnie @ July 16th, 2009

最近实验室的事情比较忙,一直没时间更新blog,终于今天抽出点时间可以写了,却不知道写什么好,就随便涂两笔了事。

snow leopard
前两天一边写程序一边把我的leopard升级为了snow leopard,虽然是预览版,也算成熟了,我目前还没遇到太大的bug(我用的时间太短了,没遇到正常)。安装过程很顺利,本想直接用硬盘安装,但一时找不到空闲的硬盘,就只能又刻盘安装了。不过我发现我的macbook pro的光驱快挂了,不能刻DVD了。用实验室机器刻好盘直接安装就可以了,安装过程十分顺利,以前leopard的配置和数据一点没丢。这一点是我觉得mac系统最爽的地方,不用我操心备份转移恢复。用cocoa写的finder我还没看出来和以前的区别,opencl我也没用上,对我来说最大的变化就是界面了,quicktime x的界面,还有jjgod同学说的字体变化。这些还都没有最终确定,也不知正式版的雪豹会是个什么模样。

multi-thread file access
最近在写程序遇到了一个莫名其妙的bug,花了我一周时间终于搞清楚了原因。原来是我自己傻了,多线程访问一个文件,没有做好互斥。也难怪C语言中FILE的牛逼,即使别的线程已经打开了文件,FILE还是能够直接打开,进行自己的操作。

Big file access
经过这一周对死磕,发现程序的另一个bug就是对大文件的操作,这个大文件一般大于4GB。我开始用FILE后来用C++的fstream都不敌,seek文件指针的时候只能访问4GB,后来改用系统API才才搞定。对了,我的程序是64位的。

捷克签证
这两天和老婆去给她办捷克签证,本以为会很顺利,没想到确实无比麻烦。周三早上我们直接杀过去,得知周三只办长期的,我们只好回去了。周四又杀过去,发现门口已经排了十几个人了,无奈之下只好等了。没想到捷克这个破地方的签证还真难办,等了一个小时,没放进去一个人,说是一开始放进去5个人到现在一个都没出来,我心里想一个多小时,5个人啥事都办完了,怎么还没出来。最后结果是又没办到。下一次之能事下周一了,因为人家每周只有1、2、4上班,且只上半天,囧啊。我们决定周日完上就去排队,一定要办到这个破证。

这一周干了不少傻事,记在这里引以为戒,以后不能再这么无知了。

写完才想起来,雪豹的preview也有改进,就是wwdc上展示过的,PDF文字选择得到了改进。

small做关键字怎么不告诉我

Program — Tags: — ronnie @ July 6th, 2009

在windows下使用lapack遇到了个问题,编译报这样的错:

……\clapack.h(3592) : error C2144: syntax error : ‘char ‘ should be preceded by ‘) ‘
……\clapack.h(3592) : error C2144: syntax error : ‘char ‘ should be preceded by ‘; ‘
……\clapack.h(3592) : error C2143: syntax error : missing ‘; ‘ before ‘, ‘
……\clapack.h(3592) : error C2059: syntax error : ‘, ‘
……\clapack.h(3592) : error C2059: syntax error : ‘) ‘

错误内容指向这两行:

/* Subroutine */ int dlabad_(doublereal *small, doublereal *large);
/* Subroutine */ int slabad_(real *small, real *large);

这是怎么回事,lapack的头文件有问题?不会是我无意中按到键盘了吧。仔细检查一遍,没有这些问题啊,怎么会出现这种编译错误。无奈求助google大神,发现了问题的症结:

Microsoft SDK中有个头文件叫做 RpcNdr.h,其中有一句 #define small char

知道问题原因就好办了,直接把上述声明中small改掉即可。

我的疑问就是怎么能用small这么常用的一个短语作为关键字而不告诉我呢?或者我太土不知道?

脚本下载谷歌高质量的音乐

Program — Tags: — ronnie @ June 17th, 2009

谷歌的音乐一上线,就有人搞出来脚本下载,不过他这个脚本是Python3.0的,我不太喜欢Python3.0,就将其改成了2.5的了,且我喜欢下载整张专辑,也就改成了给脚本专辑地址了,避免搜索。

#!/usr/bin/python
import sys, os, re, urllib
from HTMLParser import HTMLParser
import httplib
from subprocess import Popen
import time
 
def decode(string):
	return re.sub('&#[0-9]{5};', lambda x: unichr(int(x.group(0)[2:-1])),re.sub(' ', ' ', string))
 
def get_attr(attrs, attr):
	for key, value in attrs:
		if key == attr:
			return value
	return None
 
class SongParser(HTMLParser):
	song_list = []
	def parse(self, htm):
		self.feed(htm.read().decode("utf-8"))
		return self.song_list
 
	def handle_starttag(self, tag, attrs):
		if get_attr(attrs, "class") == "SongItem BottomBorder":
			self.song_list.append( get_attr(attrs, "id")[3:] )
 
class SongInfoParser(HTMLParser):
	# song = [ name, singer, size, format ]
	tags = {
			"td-song-name":"name",
			"td-singer":"singer",
			"td-size":"size",
			"td-format":"format"
	}
	song = {}
	attr = None
	def parse(self, htm):
		self.feed(decode(htm.read()))
		return self.song.copy()
 
	def handle_starttag(self, tag, attrs):
		if tag == "a":
			tag_href = get_attr(attrs, "href")
			if tag_href[0:7] == "/music/":
				self.song["address"] = "http://www.google.cn"+tag_href
		elif get_attr(attrs, "class") == "song-meta-data-table":
			self.attr = ''
		elif self.attr == '':
			tag_class = get_attr(attrs, "class")
			if tag_class in self.tags:
				self.attr = self.tags[tag_class]
 
	def handle_data(self, data):
		if self.attr:
			self.song[self.attr] = data
 
	def handle_endtag(self, tag):
		self.attr = ''
 
conn = httplib.HTTPConnection("www.google.cn")
 
if len(sys.argv) == 1:
	exit(0)
 
"""
query = ' '.join(sys.argv[1:])
print "send query: %s" %query
qeuery = urllib.quote(query)
conn.request("GET", "http://www.google.cn/music/search?q="+query)
result = conn.getresponse()
"""
result = urllib.urlopen(sys.argv[1])
 
#print result.read().decode("utf-8")
 
print "Get song list..."
 
p = SongParser()
song_ids = p.parse(result)
songs = []
parser = SongInfoParser()
 
for i, id in enumerate(song_ids):
	conn.request("GET", "/music/top100/musicdownload?id="+id)
	response = conn.getresponse()
	song = parser.parse(response)
	name = song["name"]
	time.sleep(1)
	print "%d\t%s\t%s\t%s\t%s" %(i, name, song["singer"],song["format"], song["size"])
	songs.append(song)
 
choice = range(len(songs))
 
for i in choice:
	song = songs[ int(i) ]
	if isinstance(song, dict):
		print "download: \t\t%s" %(song["address"])
		Popen(['wget', '-c', '-P', song["singer"], song["address"]]).wait()
conn.close()

如果你想用,可以在这里下载。

下载完了以后用mutagen自带工具mid3iconv可以转换mp3的tag编码,不过这里有个小问题,就是对于谷歌高质量音乐有一点不爽,谷歌音乐都是自带歌词的,这个工具不能转换歌词,我就改了改,让他可以该歌词编码了,这样iTunes等只支持unicode的就没问题了,ipod touch/iphone中也可以真长看到歌词了。其实主要就是改了很小一点,原来mid3iconv只是修改T开头的tag,我加上了对歌词所在的”USLT”tag的处理就OK了,代码如下:

#!/usr/bin/python
 
import os
import sys
import locale
 
from optparse import OptionParser
 
VERSION = (0, 1)
 
def isascii(string):
    return not string or min(string) < '\x127'
 
class ID3OptionParser(OptionParser):
    def __init__(self):
        mutagen_version = ".".join(map(str, mutagen.version))
        my_version = ".".join(map(str, VERSION))
        version = "mid3iconv %s\nUses Mutagen %s" % (
            my_version, mutagen_version)
        return OptionParser.__init__(
            self, version=version,
            usage="%prog [OPTION] [FILE]...",
            description=("Mutagen-based replacement the id3iconv utility, "
                         "which converts ID3 tags from legacy encodings "
                         "to Unicode and stores them using the ID3v2 format."))
 
    def format_help(self, *args, **kwargs):
        text = OptionParser.format_help(self, *args, **kwargs)
        return text + "\nFiles are updated in-place, so use --dry-run first.\n"
 
def update(options, filenames):
    encoding = options.encoding or locale.getpreferredencoding()
    verbose = options.verbose
    noupdate = options.noupdate
    force_v1 = options.force_v1
    remove_v1 = options.remove_v1
 
    def conv(uni):
        return uni.encode('iso-8859-1').decode(encoding)
 
    for filename in filenames:
        if verbose != "quiet":
            print "Updating", filename
 
        if has_id3v1(filename) and not noupdate and force_v1:
            mutagen.id3.delete(filename, False, True)
 
        try: id3 = mutagen.id3.ID3(filename)
        except mutagen.id3.ID3NoHeaderError:
            if verbose != "quiet":
                print "No ID3 header found; skipping..."
            continue
        except Exception, err:
            if verbose != "quiet":
                print str(err)
            continue
 
        for tag in filter(lambda t: t.startswith("T"), id3):
            frame = id3[tag]
            if isinstance(frame, mutagen.id3.TimeStampTextFrame): # non-unicode fields
                continue
 
            try:
                text = map(conv, frame.text)
            except (UnicodeError, LookupError):
                continue
            else:
                frame.text = text
                if min(map(isascii, text)):
                    frame.encoding = 3
                else:
                    frame.encoding = 1
 
        print "Process USLT"
        for tag in filter(lambda t: t.startswith("U"), id3):
            frame = id3[tag]
            if isinstance(frame, mutagen.id3.TimeStampTextFrame): # non-unicode fields
                continue
            if frame.encoding == 1:
				continue
 
            text=frame.text
            text = text.encode('iso-8859-1').decode(encoding)
 
            frame.text = text
            if min(map(isascii, text)):
                frame.encoding = 3
            else:
                frame.encoding = 1
 
        enc = locale.getpreferredencoding()
        if verbose == "debug":
            print id3.pprint().encode(enc, "replace")
 
        if not noupdate:
            if remove_v1: id3.save(filename, v1=False)
            else: id3.save(filename)
 
def has_id3v1(filename):
    f = open(filename, 'rb+')
    try: f.seek(-128, 2)
    except IOError: pass
    else: return (f.read(3) == "TAG")
 
def main(argv):
    parser = ID3OptionParser()
    parser.add_option(
        "-e", "--encoding", metavar="ENCODING", action="store",
        type="string", dest="encoding",
        help=("Specify original tag encoding (default is %s)" %(
        locale.getpreferredencoding())))
    parser.add_option(
        "-p", "--dry-run", action="store_true", dest="noupdate",
        help="Do not actually modify files")
    parser.add_option(
        "--force-v1", action="store_true", dest="force_v1",
        help="Use an ID3v1 tag even if an ID3v2 tag is present")
    parser.add_option(
        "--remove-v1", action="store_true", dest="remove_v1",
        help="Remove v1 tag after processing the files")
    parser.add_option(
        "-q", "--quiet", action="store_const", dest="verbose",
        const="quiet", help="Only output errors")
    parser.add_option(
        "-d", "--debug", action="store_const", dest="verbose",
        const="debug", help="Output updated tags")
 
    for i, arg in enumerate(sys.argv):
        if arg == "-v1": sys.argv[i] = "--force-v1"
        elif arg == "-removev1": sys.argv[i] = "--remove-v1"
 
    (options, args) = parser.parse_args(argv[1:])
 
    if args:
        update(options, args)
    else:
        parser.print_help()
 
if __name__ == "__main__":
    try: import mutagen, mutagen.id3
    except ImportError:
        # Run out of tools/
        sys.path.append(os.path.abspath("../"))
        import mutagen, mutagen.id3
    main(sys.argv)

可以到这里下载。

记住这个或许有点用

闲言碎语 — ronnie @ June 8th, 2009

天朝成都市发生了一起惨不忍睹的公交车着火事件,27名乘客被烧死,还有18命生命垂危。姑且不管火灾是怎么发生的,先来说说发生火灾了怎么办吧。

那辆公交车是传说中的空调车,全部封闭,只有两个门可以打开。发生火灾以后,电子门就打不开了,整个车就此完全封闭。我就很奇怪,为什么没有人打碎玻璃呢,一方面可能车里面都乱了套,另一方面或许是没有使用恰当的方法去敲玻璃。公交车上面使用的是钢化玻璃,这种玻璃现在随处可见,大楼门窗,车窗等处都有使用。先把普通玻璃切割成需要的尺寸,然后加热软化,接着突然冷却,这样就形成了钢化玻璃,这种玻璃表面形成了均匀的压应力,内部形成张应力,简单说就是特别抗压了,不容易碎。如果想要去敲碎钢化玻璃还是很难的,除非你足够牛逼,上肢能够产生足够的冲击力。不过它有个弱点,就是边缘和角上特别容易碎,因为这里张应力最大,所以要想敲碎钢化玻璃,从四角下手是最明智的选择。这些都有依据,来源于伟大的wiki

… The glass is most susceptible to breakage due to damage to the edge of the glass where the tensile stress is the greatest, but shattering can also occur in the event of a hard impact in the middle of the glass pane or if the impact is concentrated (for example, striking the glass with a point)…

好了,大家记住这一点,指不定您乘坐的哪路公交或地铁着火了呢,天朝很危险,还是武装自己为妙。

My Posterior cruciate ligament tears

闲言碎语 — ronnie @ June 3rd, 2009

我的后十字韧带断了,到底是怎么回事呢,看看右边的图就明白了。这个伤是我在两星期前踢球的时候受的,当时是我带球的时候,被对方队员从后面踢到膝盖,然后我就重重摔倒了。就在我摔倒的时候,一阵疼痛从左腿传来,我立刻就站不起来了。过了几秒钟,痛苦有所减轻,我以为只是一般轻伤,就没在意继续比赛了,虽然后面我也没有再怎么跑,我觉得这也是我伤势加重的原因。等踢完比赛以后,我当时觉得应该没事了,就吃饭,休息,去实验室了。可是到了实验室我坐了一会,想站起来的时候就发现,我已经站不起了。左腿不能伸直,也不能太弯曲。根本不敢用力,否则就是巨痛。

第二天我去校医院检查,有一位大夫直接告诉我说:“没事,你回去休息几天就好了”。我当时就想这个大夫肯定害了不少人,我不能被他害了。我就要求他给我转院,去北医三院看。他说不能做主,给我换了个大夫,这位大夫看出了问题的严重性,马上让我转院了。第三天早上,我就早早(大概早上5点)起来去排队挂号,幸好取得早,挂到了一个比较靠前的号。三院的一位大夫为我检查后说,我的韧带断了,让我去拍核磁共振。我当时就愣了,韧带断了,我都没想到这么严重。拍核磁的人太多了,我只能拍到一周后。我就买了个夹板回去带着,等了一周,才拍到核磁共振,最终结果就是左膝后十字韧带断裂(Posterior cruciate ligament tears),有检查报告单为证。

center

我以后的职业生涯就算是完了,我宣布挂靴。希望我一年以后能够完全康复。

How to write a full screen cocoa progam

Cocoa, Program — Tags: — ronnie @ May 31st, 2009

最近正好要写一个全屏的cocoa程序,所以就研究了一些用cocoa怎么写全屏的程序。

说起来全屏程序很简单,就是首先要拿到你要全屏的显示设备的ID,然后获取这个设备。接着建立一个无边界的窗口,将其大小设置为屏幕的大小,然后显示就可以了,这个窗口里面可以显示你需要的任何东东,包括按钮,滚动条等等,不过一般全屏要么显示图片,要么显示视频,再就是3D程序,所以也不会放上很丑的这些按钮什么的。

首先是获得显示设备的ID,你可以使用

CGDisplayErr CGGetActiveDisplayList (
   CGDisplayCount maxDisplays,
   CGDirectDisplayID *activeDspys,
   CGDisplayCount *dspyCnt
);

去获得所有的可用的显示设备,然后用设备ID调用函数

CGDisplayErr CGDisplayCapture (
   CGDirectDisplayID display
);

去获得这个设备。接着,我们建立一个无边界的窗口:

- (id)initWithContentRect:(NSRect)contentRect 
styleMask:(NSUInteger)windowStyle 
backing:(NSBackingStoreType)bufferingType 
defer:(BOOL)deferCreation 
screen:(NSScreen *)screen

其中参数windowStyle设置为NSBorderlessWindowMask就是无边界窗口,screen要设置成为屏幕大小。我的程序里面完整的调用如下:

[[YLFullScreenWindow alloc] initWithContentRect:screenRect 
styleMask:NSBorderlessWindowMask 
backing:NSBackingStoreBuffered 
defer:NO 
screen:[NSScreen mainScreen]];

然后显示这个窗口就可以了。
我的程序中之所以使用YLFullScreenWindow,是因为要想全屏窗口响应鼠标事件,必须自己重载NSWindow这个类,重写一下函数- (BOOL)canBecomeKeyWindow,使其总是返回YES:

- (BOOL)canBecomeKeyWindow
{
	return YES;
}

好了,全屏程序就这样建立了。

无题

闲言碎语 — ronnie @ May 16th, 2009

最近一段时间忙项目,也没时间写东西。前两天刚忙完,只顾休息了,也没上来写。好不容易今天才有时间来写点东西。

读书:最近读了清华老教授何兆武的回忆录,书名是《上学记》。从他的回忆中能感到他对西南联大那段时期自由民主的学校氛围的怀念,他解释说那段时间除了那么多学术牛人的原因就是自由,他强调搞学术就是要自由。的确是这样,如果教授不能教自己喜欢交的,学生不能学自己喜欢学的,学术研究当然会停滞不前。那段时期的教授还真的都是大家学者,专心学术,同时心里还有一个民主自由的梦想为之奋斗。看看当今校园中大部分所谓教授,有哪些是专心学术,敢称自己为大家,哪个不为了项目资金使劲剥削学生。同时何先生的回忆也改变了我对那段时期的认识。虽然那时中国处于战乱年代,但远没有今天封闭,大家真的可以有各种思想,各种信仰。那时的北京也很发达了,可以看到好莱坞大片哦。

电影:今天看了《star trek》,总体还算可以,特效也不错,但没有什么新意。就算是为延续了近40年的星际迷航传奇一个开始吧。不过还是不如《star wars》来的好。

Next Page »
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.
(c) 2010 To Be A Brave One | powered by WordPress with Barecity