虾米播放器程序失效

之前写的一个虾米播放器最近一段时间无法运行,每次运行显示Stream not seekable!直接挂断。查看了URL,发现虾米升级了服务器导致的。

因为mplayer依赖HTTP协议的accept-range头,如果服务器没设置就报错退出,我抓包分析了虾米服务器的HTTP应答,没发现accept-range,应该是这个原因。这边还有人说是mplayer的一个bug,因为不是所有服务器都严格遵守的,应该给服务器个机会嘛:)。

如果是这样的话就没法用mplayer了,得想其他办法了,初步只能用wget拖回整个专辑,然后慢慢放了-_-!!!,不过幸好mms电台不受影响,可以用mplayer放。

翻译Dewey的最后一篇游记

前篇说道Dewey的最后一篇游记追到了xiujuan,那我就试试翻译一下,说不定很有趣:),英语水平很烂,各位少安毋躁。

下文翻译自David Dewey Stories of my travels through China and the adventures I had along the way的最后一篇,[Xiujuan] Finally getting the Girl

BTW: Xiujuan我不知道真实姓名,暂时写作秀娟吧。

沙子作为礼物

到了晚上我去秀娟的宿舍去看她,但很难说服她下来见我。 我发短信告诉她我有些东西给她,但不管怎么样她说不想要。

最终过了一小时她下来了。我原以为她会怪我让她下楼来见我,但她最终跳着走到我身边并对我笑脸相迎。她说她并不知道我在这里等她,管她呢,我咳嗽着跟她讲话,并给她我从内蒙古沙漠里收集的沙子。她确实被我意想不到的礼物和我收集沙子的经历感动了。然后,她帮她的室友买了些冰淇淋就回宿舍了,但她说可以在第二天早上9点来看我,并要我帮她指导英语功课。

那天晚上我的朋友Alex从西雅图打电话给我,我和他聊了很长时间。星期天早上,我到秀娟的宿舍去接她,但我手机坏了,好像是与Alex打电话把我的手机话费用完了。所以我用宿舍楼的电话打电话给秀娟,希望他不要对直接打电话给她感到生气,因为在中国手机话费很贵,但短信费则便宜很多。

秀娟下来了,我试图用英语跟她说话,我认为应该这样,因为我今天本来应该教她英语的嘛。我试图降低语速并尽量用简单语句,但她还是无法理解我说的话并拒绝同我说英语,最后我放弃了尝试。晓娟已经学习英语9年了,但她的英语会话能力少的可怜,她英语几乎只学了读和写。

我们去教室学习,但我们不能说话,因为周围都是同样学习的学生。我建议我们去外面学习,但她不想去。她平时很喜欢去外面学习,而且今天天气很好,可能她担心去外面我的感冒会加重。我只能建议去我住的旅馆学习。

一旦到了旅馆,我们就用功的学习英语。她想通过一个高年级英语考试(译著:senior-year应该是四级英语吧),可是学习用的文章对她而言太难了,里面夹杂着许多生词和许多她不懂的复杂语法。因为她不理解所有这些语法和单词所以就更无法理解这些文章了,也就意味着她无法正确的回答这些多选题。

此外,所有晓娟要学的文章都是从西方的资料上摘抄下来的,都关于英美文化、地理、政府、政治等等。就算晓娟的英文能力再好,她也可能不能理解这些文章,因为她不熟悉这些西方的东西。比如,她不懂基督信仰、盎司、呼气测试、福利,这些都在那些文章里有所涉及。雪上加霜的是她的英文水平远远不够,理解那些文章对她来说是个噩梦。我关心的是她确实需要帮助,我会尽我所能一点一点的帮她理解每篇文章的背景。幸运的是秀娟是个超级聪明的女孩,她学的很快。我确信她如果在美国待几个月就能学会说流利的英语。

手机卡

那天晚上我试着充值手机卡,但不成功。这涉及到一些复杂的因素:我有一个非本地手机号码并且欠费了,但为了拨通手机卡充值号码,我必须手机上有卡 ,因为要漫游。我被告知必须用本机打充值电话,所以我被困住了。我买了个新的北京号码和手机卡。

我花了很长时间写下我的手机里的号码并放到新的卡上。我发现我买的新卡有点烂,一旦涉及到卡的flash读写将会死机。我怀疑手机店里的人利用了我作为一个无知的老外这点卖给我不想要的烂卡。应该有其他方法充值不是本地的手机卡,或许他们不想告诉我。我没时间想这些,我一门心思都在想秀娟。

现在我的手机又好了,我发了个短信给秀娟。我跟她说我病的很厉害(这些都是真的which is all too true),并告诉她应该来看我照顾我。第二早上(星期一早上)她带着给我的一包食物来看我,还带了些感冒药。接下来我们在我的旅馆房间了学习英语,最终耗费了几个小时的时间。

接下来她就到Minqi家教中文去了。她回来后我发短信给她,但她说今天晚上太晚了,不能去看我了。

月亮和火星

星期二我再次跟她一起学英语,她晚上必须去Minqi的朋友那里教中文。晚上的晚些时候,我就去了她的宿舍找她,但碰到了她的室友,她说她认识我,我却不认识她。当你是广大中国人中唯一的外国白人时,我猜很容易被记住。她说秀娟可能不在,但她上楼去看了看,不久秀娟就高兴的下来了。我带她回我的旅馆,我们拥抱并亲吻了一会儿,但秀娟不习惯跟一个男人躺在床上,所以睡不着。旅馆的房间有两张床,所以我就让她睡在旁边那张床上了。

星期三晚上秀娟发短信给我,让我去外面看月亮和火星,因为在一万年中两者之间的距离在今天是最近的。我正在睡觉,但还是起来到外面去看。她又发短信过来,问我看到月亮是否想家。我说没有,只是让我想你了。接下来她第三次发短信过来, 问我,是什么事情使我这么爱他。我误解了,以为她怀疑我对她的爱,就像她一贯如此的那样。所以我回了条短信,告诉她算了睡觉吧。令我惊奇的是,显然这使她感到不快,或许这是个好兆头。她一定是开始喜欢我了,否则她是不好这么在乎我的。

中秋节

9月11号星期四是中秋节,那晚我去了秀娟那里,我们去了外面,坐在草地上欣赏月亮,这是原本中秋节该干的事情。我们拥抱在一起谈了好一阵子话。接下来我肚子就饿了,我们去了通宵营业的小店买了些小吃。我明白今天没月饼可吃了,这原本应该中秋节吃的,但我们就是找不到月饼,月饼全都买完了。最终,过了午夜,吃月饼已经太迟了,我们回了旅馆,秀娟跟我待了一晚上。这次我们一起睡在一张床上。

第二天我们见面继续学英语,但她不想学,而且她给我带了个月饼。她在读一本她最喜欢的中国小说家的传记,里面包含了许多那个小说家写给他妻子的情书,秀娟一边看书,一边说我永远不会给她写这些情书,因为我的中文水平不够。我没法反驳她。她想回她的宿舍,并想跟我永远的分别。

当我们回到她宿舍时,我情不自禁的抱着她哭了。我猜她也对我感到难过,所以又跟我回到了旅馆房间,而不是回宿舍。但她马上要和她的朋友去听音乐会,所以我又陪她回宿舍,在那里她再次说她不属于我。我又哭了起来并跟她道别。我感到很糟糕,我意识到我必须尽量用英语跟她沟通,她可能感到她在跟一个三岁小孩约会,因为我的中文就那个水平,而且我一直都用中文跟她说话。

忘记钥匙

当我回到旅馆时,欣喜的发现秀娟忘记钥匙了。这给了我完美的再约她见面的机会。所以我用英文发了条关于钥匙的短信给她,并且用了些难懂的词汇,这样确保她无法理解。我认为这样就可以反驳她抱怨我的烂中文了。那天深夜我去她的宿舍找她,我发现她还没从音乐会回来,但很快她出现了。我告诉她我给她带来了她的钥匙。她跟她的朋友说了再见,所以我让她坐自行车后面带她转了一圈。我们坐在长凳上谈了很多事情,我告诉她所有我爱他的理由,并恳求她做我的女朋友,但这都是徒劳。

最终我们回到了旅馆房间,她又跟我度过了一个晚上。由于我的疏忽,我没把窗户关牢,房间里满是蚊子。我把蚊帐覆盖在我们身上,但我愚蠢的在黑暗中盖了一下,但蚊子早就钻进了蚊帐,早上醒来,它们都吸饱了我们的血。

给男孩的信

接下来的晚上,我给秀娟买了朵玫瑰,去她宿舍找她。可是她宿舍那里有大群人,有些男生在给所有女生唱歌。秀娟拒绝下楼见我,我发了很多不同的短信给她,并固执的等了她三个小时。最终一些女孩在阳台上跟我说话,并扔给我个折成纸飞机的信,信是用荧光笔写的,而且用的是英文:

嗨, 小子:

中国女孩可不吃这套的,你今晚最好回去睡觉了。

事实上这幢楼内的所有女孩对你所做的都很感动,但是继续待在这儿确实不是个好办法,听懂了吗?

或许你可以慢慢来,给她些时间来接受你。

祝你好运 : )

这封信写的很好, 但这不适用与秀娟。我了解她,我知道如果我做了些貌似很傻的事,比如说整晚站在外面等她下来,她会很感动的。我知道她爱我,但她在试探我,确信我是否忠于她。

我对晓娟让我在外面整整等了3个小时感到恼火,所以我回去了。她答应第二天带我去吃早餐,并跟我一起学习英语。我发了条短信给她,她第二天早上开手机时应该会看到,在这条短信中我说她辜负了我的心,我决定忘了她。

最后一天

第二天早上,她早早的用短信叫醒了我,她对我前天晚上发的短信感到生气。我道了歉,我们在吃早餐时见了面。那束玫瑰现在看起来有点破败不堪了,但我不管怎么样还是给了她。她并不想要,但我坚持着让她拿着,她被感动到了。我告诉了她等她3小时的事情,她原本希望我会生气,但我告诉她我爱她以至于能原谅她所有事情。那确实是真的,我太爱她了,以至于见到她的瞬间我就忘了所有她对我的伤害。我了解秀娟,她喜欢听这些话,确实是这样的。这天接下来的时间里她对我难以置信的好,她用双手牵着我的手去逛街。在我在中国的最后24小时里,她紧紧的跟着我。

我那天晚上只睡了一个小时,因为必须起来打包准备我的行李。我们临晨4点离开旅馆直奔机场,到机场时发现太早了,她在大庭广众之下毫无羞涩的吻了我,这至少在北京很少见。不幸的是她还没答应做我女朋友,但我一旦回美国就会打电话或者写信、email给她做她的思想工作。

我进入检票区后,秀娟在后面很远的站着看我。她给我的手机发了些温暖的短信,接下来我就登机了,我对我们的未来很有希望。

回到美国

飞机轻松的到了东京,我坐在一个靠窗的位置,那里可以看到所有下面的小船和很多漂亮的云,韩国的大城市,日本的工厂、公园、高尔夫球场、高速公路、房子。在从东京飞西雅图的航班上我座位不靠窗,但飞机靠门的方向上有个座位没人,因为那个人在飞机起飞前没有出现。这恰好是个很好的座位,远离747巨大的机翼。因此,在坐之前我问航班服务员是否可以坐那里,她同意了。我很高兴找了个靠窗的位子。一旦飞过了太平洋,在西雅图着陆之前,我飞过了San Juan Islands, Dungeness spit, Sequim, Port Townsend和华盛顿大学,我看得很清楚。

回美国三个月后,我最终说服了晓娟当我的女朋友。再一个月后我的学习申请被北京师范大学接受,我将在2004年2月2号回北京。

2004年10月更新: 我现在生活在中国浙江省杭州市,晓娟现在已经是杭州这里的高中中文老师了,而且我和我的好朋友开了个公司,ChinaForge.com有限公司。感谢ChinaForge赞助这个网站,谢谢晓娟,作为这个世界上最特别的女孩,也是最好的中文老师。

读老外游记意外收获

我对老外之类游中国之类的游记很有兴趣,在龙腾网上发现这么一篇游记杜大威游中国,看起来Dewey还是比较单纯的人。到了第二篇游记,Dewey已经显示显露出对xiujuan的暗恋了-_-!!!。读到最后,对他和xiujuan的旅游我到不太关心了,我最关心的是他俩以后的事情,毕竟这个游记大概写于2003年(根据这里判断),xiujuan好像还是大二或大三的学生。

OK,按奈不住好奇心寻到了Dewey的游记博客,总共15篇游记,龙腾上只翻译了两篇,所有的游记英文在这里。Dewey与xiujuan分开后独自旅游了很多地方,这些我暂时没工夫看,最最关键的是最后一篇[Xiujuan] Finally getting the Girl。看来Dewey最终抱得美人归了:),有空我试试翻译这篇,我看的很有意思,有点感动。

Dewey的游记博客有点旧了,无意中有找到了比较新的日常博客,从中我知道Dewey在杭州与朋友合伙创业开公司(好熟悉啊),好像是做模具外包的,xiujuan也来到了杭州做了老师。2006年他俩结婚了,这中间有很多波折,你可以自己去看那些博文。我想现在结婚压力都这么大,何况是老外呢,文化差异、工作、手续问题,特别是xiujuan父母有点反对(他们想至少也的嫁个有房有车的小伙吧-_-!!!),但最后他俩熬过来了,皆大欢喜,end story :)。

BTW: Dewey是美国西雅图人,xiujuan是湖州人,他俩的照片去Dewey博客里找吧:),我是不是太八卦了啊-_-!!!。

令人困惑的单位:kB和KiB

ubuntu 12.04目前ls -l 默认是1024为单位的KiB、MiB和GiB(显示K、M、G):

SIZE may be (or may be an integer optionally followed by) one of fol‐lowing: KB 1000, K 1024, MB 10001000, M 10241024, and so on for G, T, P, E, Z, Y.

而且有个选项–si可以显示以1000为单位的,-s显示文件占的块数(4KiB)。

但是我亲自试了一下,发现ls显示大小的小数部分貌似不是正常的四舍五入。--!!! 终于发现规律了,不是四舍五入,而是精确到位数后再加一,把剩下的小数进一,确保不小于原来大小(可以大,但不能小--!!!)。

例如:

$ls -l
-rw-rw-r--  1 xx xx  604066417  xx xx xx OpenWrt-xxx
$ll
-rw-rw-r--  1 xx xx  577M  xx xx xx OpenWrt-xxx

所以直接就进位了:

604066417 byte = 576.0826272964478 MiB = 577MiB

听说ubuntu 13.04要调整成1000为单位的KB、MB、GB。

http://forum.ubuntu.org.cn/viewtopic.php?f=49&t=401481

http://askubuntu.com/questions/465/is-it-true-that-ubuntu-will-no-longer-measure-file-size-unit-as-byte-megabyte

https://wiki.ubuntu.com/UnitsPolicy

http://en.wikipedia.org/wiki/Mebibyte

mini2440上实现网络电台播放

上次说到要实现一个无线鼠标控制的网络电台播放程序(远程控制:)),今天有空就实现了。主要的难点就是读取鼠标数据,昨天花了一天时间看了linux kernel的driver/input/mousedev.c源代码,看懂了数据格式和控制原理,就很简单了:)。

鼠标的设备文件是/dev/input/mice,默认读取的是PS2数据,分3个字节,分别是3个按键、X、Y坐标。不过要注意的是XY坐标都是相对坐标(不超过127,有符号),如果要获得滚轮数据需要打开im扩展,直接向mice写数据串{ 0xf3, 200, 0xf3, 100, 0xf3, 80 }就行了,这个在mousedev.c写的很清楚了,PS2格式参考看这里

解决了鼠标控制,具体播放就开个进程放mplayer,把所有电台URL放在playlist里就行了,mplayer支持从标准输入的按键控制,0和9控制音量,<和>对应前进和后退,p是暂停。进程间通信就用pipe,不过建pipe,绑定stdin有点麻烦,有现成的API做了这些了,popen和pclose就可以搞定这些。最后用鼠标左键前翻,右键后翻,中键暂停,滚轮控制音量。

Talk is cheap, show me the code: github

// @author: lbzhung
// @brief:  just a network radio player and control by mouse.
//          using mplayer as backend, left button previous, right button forward and middle button pause.
// @see  linux kernel drivers/input/mousedev.c
//       http://www.computer-engineering.org/ps2mouse/
//       
#include <cstdio>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>

typedef unsigned char BYTE;

#pragma pack(1)
struct imps2_data
{
    BYTE btn_left:1;
    BYTE btn_right:1;
    BYTE btn_middle:1;
    BYTE NONE:1;
    BYTE x_sign:1;  // x offset sign
    BYTE y_sign:1;  // y offset sign
    BYTE x_overflow:1; // x offset is overflow
    BYTE y_overflow:1; // y offset is overflow

    // x/y movement offset relative to its position
    signed char x;
    signed char y;
    signed char z;
};
#pragma pack()

int main(int argc, char *argv[])
{
    BYTE mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
    int mice_fd = open("/dev/input/mice", O_RDWR|O_NONBLOCK);
    if (mice_fd == -1)
    {
        fprintf(stderr, "Open mice fail");
        return 1;
    }

    // set mice mode, so can read rolling wheels
    int nRet = write(mice_fd, mousedev_imps_seq, sizeof(mousedev_imps_seq));
    if (nRet < 0)
    {
        fprintf(stderr, "set mice imps2 fail\n");
        return 1;
    }


    FILE *stream = popen("mplayer -quiet -softvol -softvol-max 300 -playlist channel.txt", "w");
    if (stream == NULL || stream < 0)
    {
        fprintf(stderr, "popen mplayer fail\n");
        return 1;
    }

    while (true)
    {
        fd_set fdset;
        //struct timeval tv;
        //tv.tv_sec = 0;
        //tv.tv_usec = 200000;

        FD_ZERO(&fdset);
        FD_SET(mice_fd, &fdset);

        int ret = select(mice_fd+1, &fdset, NULL, NULL, NULL);
        if (ret < 0)
        {
            fprintf(stderr, "select return error\n");
            return 1;
        }
        else
        {
            if (FD_ISSET(mice_fd, &fdset))
            {
                imps2_data data;
                while (true)
                {
                    int nLen = read(mice_fd, &data, sizeof(data));
                    if (nLen == 0)
                    {
                        fprintf(stderr, "End of file \n");
                        return 1;
                    }
                    else if (nLen == -1)
                    {
                        if (errno != EAGAIN)
                        {
                            fprintf(stderr, "read fail\n");
                            return 1;
                        }
                        break;
                    }
                    else
                    {
                        // nLen = 1 is ack
                        if (nLen == sizeof(data))
                        {
                            //printf("nLen:%d, left:%d right:%d middle:%d X:%d Y:%d Z:%d\n",
                            //        nLen, data.btn_left, data.btn_right, data.btn_middle, data.x, data.y, data.z);
                            if (data.btn_left)
                            {
                                if (data.btn_right)
                                {
                                    // OK quit
                                    close(mice_fd);

                                    fprintf(stream, "q");
                                    fflush(stream);

                                    // wait process exit
                                    pclose(stream);
                                    return 0;
                                }

                                // preivous
                                fprintf(stream, "<");
                                fflush(stream);
                            }
                            else if (data.btn_right)
                            {
                                // forword
                                fprintf(stream, ">");
                                fflush(stream);
                            }
                            else if (data.btn_middle)
                            {
                                // pause
                                fprintf(stream, "p");
                                fflush(stream);
                            }
                            else if (data.z != 0)
                            {
                                if (data.z > 0)
                                {
                                    // rolling down
                                    fprintf(stream, "9");
                                    fflush(stream);
                                }
                                else
                                {
                                    // rolling up
                                    fprintf(stream, "0");
                                    fflush(stream);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    return 0;
}

Linux pipe读写问题

之前的那个mplayer播放mms电台需要一个控制接口,mplayer只支持控制台输入命令,所以要控制mplayer只能用管道控制标准输入stdin。为了灵活就用FIFO文件作为mplayer的输入端。

mkfifo radio_pipe
cat radio_pipe | mplayer mms://xxx
echo -n p > radio_pipe

这里有个问题是cat radio_pipe读到文件EOF会退出,导致mplayer退出,所以每次只能控制一次:(。

前几天看mini2440附带的led-player程序,突然意识到可以自己写个pipe_read程序忽略文件EOF,这样就解决了mplayer的控制。记得之前写TCP程序时知道read返回0说明到文件EOF了,TCP就代表关闭了。我只要忽略掉read返回0的状态就行了(之后证明大错特错-_-!!!),错误是因为select认为文件EOF是读信号,除非你退出否则一直触发。最后的解决方法是这一句

int null_pipe_write_rd = open(pstrPipe, O_WRONLY | O_NONBLOCK);

再打开一个不操作的pipe读fd,这样才不至返回文件EOF,具体原因不是很明白:(,不过达到了我要的效果:)。

mkfifo radio_pipe
./pipe_read radio_pipe | mplayer mms://xxx
echo -n p > radio_pipe

这样就不会退出了,不过就如我们CEO说的一句话:解决了一个问题,往往带来了其他问题,这样pipe_read永远也不会退出了,尽管mplayer已经退出了-_-!!!。

Talk is cheap, show me the code:

#include <cstdio>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>

void usage(const char *pstrProgram)
{
    printf("Usage:\n"
           "  %s pipefile\n", pstrProgram);
}


int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        usage(argv[0]);
        return 1;
    }

    bool bExit = false;
    const char *pstrPipe = argv[1];

    int pipe_rd = open(pstrPipe, O_RDONLY | O_NONBLOCK);
    if (pipe_rd == -1)
    {
        fprintf(stderr, "open pipe fail\n");
        return 1;
    }

    int null_pipe_write_rd = open(pstrPipe, O_WRONLY | O_NONBLOCK);

    while (!bExit)
    {
        fd_set fdset;
        //struct timeval tv;

        FD_ZERO(&fdset);
        FD_SET(pipe_rd, &fdset);

        int ret = select(pipe_rd+1, &fdset, NULL, NULL, NULL);

        if (ret < 0)
        {
            fprintf(stderr, "select return error\n");
            return 1;
        }
        else
        {
            if (FD_ISSET(pipe_rd, &fdset))
            {
                char buffer[128];
                while (true)
                {
                    int nLen = read(pipe_rd, buffer, sizeof(buffer));
                    if (nLen == 0)
                    {
                        fprintf(stderr, "End of file\n");
                        break;
                    }
                    else if (nLen == -1)
                    {
                        if (errno == EAGAIN)
                        {
                            fprintf(stderr, "nonblocking read fail\n");
                        }
                        else
                        {
                            fprintf(stderr, "read fail\n");
                            return 1;
                        }
                        break;
                    }
                    else
                    {
                        // write stdout
                        int ret = write(STDOUT_FILENO, buffer, nLen);
                        if (ret == -1 && errno != EAGAIN)
                        {
                            fprintf(stderr, "write fail\n");
                            return 1;
                        }
                    }
                }
            }
        }
    }

    return 0;
}

mplayer在线收音机

最近搬家后一直苦于没有电视看(想念以前的IPTV,看不完的电影和电视:)),所以我一直想在mini2440板子上做一个在线收音机弥补一下,正好有个音响空着。一开始用的方案是这里

wget -q -O -http://example.com/mystream | madplay -Q --no-tty-control-

可惜的是只支持mp3类型的广播(这个只有国外的shoutcast,而且貌似都是私人的,中文的很少,只听到台湾一哥们几年前的录音-_-!!!)。madplay里面是MAD定点解码库只支持mp3之类的,要想播放mms需要微软的解码库,这个估计没戏。而国内的网络电台清一色的mms,没办法继续找。

好不容易找到mplayer,花了大力气交叉编译好,发现居然有15M--!!!。好吧,随便找个中国之声的电台测试,在板子上接上音响,发现效果很好,以后吃饭时候听广播就靠它了。现在的问题是播放只能远程登陆到mini2440上启动mplayer,下一步是做到远程控制。初步的方案是用无线鼠标HID控制,切换电台和控制声音(之前还想到过用人声音控制,例如拍手切换电台,这个估计不现实吧--!!!)。

这里记几个mplayer的命令:q退出,9和0控制声音,p Pause。

BTW:最近这段时间天天加班,这个要什么时候能弄完啊!!!,之前想写的FTP服务器还没写呢:(

转战tmux

一时兴起觉得用tmux配合vim打造一个工作平台,这样应该很酷吧:)。因为用的是Ubuntu系统,它有一个tmux的包装软件,叫Byobu(日语的屏风),简单试用了一下觉的没必要多次一举,所以直接就安装了tmux。

tmux这东西差不多是screen加上了切屏功能(pane),应该有的detach和attach都有。既然用tmux就应该用它的pane了,否则window跟screen一样。

最使我纠结的是怎么绑定pane切换而不与VIM的windows切换冲突,而且必须尽可能方面。其实最方便的直接C-H/J/K/L搞定,但VIM已经占用了,最后只好用C-A H/J/K/L多按了个扩展键-_-!!!。

下面的配置参考了网上的例子,不过挑选合适的状态栏颜色花费了我很多时间,tmux的颜色很古怪,最后只好当前的反转颜色算了。而且说实话调到后来,我自己都怀疑是否有必要花打力气去配置tmux,毕竟大部分时间都在用VIM。

# base settings
set -g default-terminal "screen-256color"
#set -g display-time 3000
set -g escape-time 0
set -g base-index 1
set -g pane-base-index 1

# bind key
unbind-key -n C-a
set -g prefix ^A
set -g prefix2 ^A
bind a send-prefix

unbind '"'
bind - splitw -v -p 30
unbind %
bind \ splitw -h -p 30

setw -g mode-keys vi
#setw -g automatic-rename off

unbind h
unbind j
unbind k
unbind l
bind  h select-pane -L
bind  j select-pane -D
bind  k select-pane -U
bind  l select-pane -R
#bind  C-a      last-window # last window
bind  C-a      last-pane # last window

unbind [
unbind ]
bind [ swap-pane -U
bind ] swap-pane -D

# reload config (prefix r)
bind r source ~/.tmux.conf \; display "Configuration reloaded!"

# misc
unbind-key x
#bind x killw # kill windows (prefix x)
bind x killp # kill pane (prefix x)

# statusbar
set -g status-justify centre
set -g status-bg  black
set -g status-fg  white

setw -g window-status-current-bg black
setw -g window-status-current-fg white
setw -g window-status-current-attr "reverse"
#setw -g window-status-current-format "[#I:#W#F]"
setw -g window-status-current-format "#I:#W#F"

set -g status-left "#[default]» #[fg=colour187]#S #[default]• #[fg=colour187]W#I P#P#[default]"
set -g status-left-attr bright
set -g status-left-length 20
set -g status-right "#H #[default]• %H:%M"
set -g status-right-attr bright
set -g status-right-length 80

参考:

http://linuxtoy.org/archives/from-screen-to-tmux.html

http://blog.xeonxu.info/blog/2012/11/04/shi-yong-tmuxgai-jin-zhong-duan-ti-yan/

Google Reader被关闭了

今天早上在同事车上用手机看Hacker News,头条竟然是”Google Reader shutting down”,在公司电脑上登录立马证实了消息。对我这样习惯上网等于上Google Reader的人,这个让人接受不了了-_-!!!。

回顾用Google Reader也两三年了,博客订阅数也达到了160了,其中的酸甜苦辣自有一番滋味在其中。可以说是Google Reader扩展了我的视野,让我在现在微博横行的世界中看到了博客的可贵之处,感谢各位辛苦写博客的博主。话说还有几个月,希望能找到替代品,以此纪念伴我左右的Google Reader君, R.I.P。

天线电磁辐射

最近在搞射频方面的工作,发现普通RFID读头RF的输出功率最高可达到32.5dBm(1.7W),天线增益假如是6dBi,线路损耗为2dBm的话,最终天线表面的等效辐射功率达32.5+6-2=36.5dBm(等效功率接近4W-_-!!!,这个功率就比较危险了,国标是33dBm和功率密度2W/平方米),也就是说要达到国标RF的最大输出功率要设置33-9+1=25dBm才可以,为安全其间尽量设小点:)。

说几点想到的:

  1. 就算不考虑天线也有最高也有1.7W,这个相比普通路由器的几个毫瓦高了1000倍。
  2. 尽量离天线越远越好。
  3. 不知生活中各种电磁辐射(手机、无线路由、电脑等等)对人体的影响,看到美国FCC的相关电磁对人体的报告,但没细看。
  4. 想起之前看新闻看到美国有些人患有电磁辐射过敏,没办法只能住在山洞里-_-!!!。
  5. 看了电磁炉其实也是用电磁感应加热金属,只不过大部分能量被金属吸收变成了热能,如果质量不好的话对周围的辐射也比较大吧。

最近睡眠不足,早点睡觉吧:(。

天线增益:http://baike.soso.com/v406959.htm