2008年12月19日星期五

在 Windows 使用主动模式的 FTP 客户端时遇到的一个问题

最近在测试一个软件时,需要用在 Windows 主动模式的 FTP 客户端,发现当客户端打开数据端口来让服务器连接的时候,服务器却死活连不上,而客户端也会一直等在那边。后来通过不同的方法,查看日志啦,抓包啦,杀进程啦,google 啦,最终确定是 Windows 的 ALG 服务的 FTP 插件把客户端发的 PORT 命令做了 NAT 变换,于是修改注册表以禁之。世界清静了。

附注册表键值:
HKEY_LOCAL_MACHINE\Software\Microsoft\ALG\ISV
这个底下的那个键的值改成 Disable 就行了。

2008年5月14日星期三

关于字符集,字符编码以及那些与之相关的麻烦东西

几个概念:

locale,与那些日期和时间,钱币等之类东西的输出格式有关。
codepage,指的是底层的文件系统实际存储时所用的字符编码方案。
iocharset,指的是文件系统提供给操作系统的接口所用的字符编码方案。

而在/etc/fstab配置文件中的utf8选项,意思应该是iocharset=utf8,嗯,未经证实。

至于字符集,如果你用utf8编码,那字符集就是unicode,用GBK的话,那就是GBK自己的字符集。我至今还没听说过有单独指定字符集的方法,欢迎拍砖。

Linux桌面实用工具

第一个就是大名鼎鼎的jump-or-exec,貌似我的代码是从不知道那个地方抄来的,作者莫怪。


#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

int
main(int argc, char* argv[])
{
if (argc < 3) {
fprintf(stderr, "Usage: %s resource_name start_command\n\n", argv[0]);
fprintf(stderr, "resource_name: the window's X resource name.\n");
fprintf(stderr, "start_command: the command to start a new window.\n");
return 0;
}

const char *res_class = argv[1];
printf("The inputed resource name is %s.\n", res_class);

Display *display = XOpenDisplay(NULL);
if (!display) {
fprintf(stderr, "This program should be run within X environment.\n");
return 1;
}
Window root = DefaultRootWindow(display);
Window *windows = NULL;
unsigned long win_num, i = 0;
Atom actual_return_type;
int actual_format_return;
unsigned long bytes;
XGetWindowProperty(display,
root,
XInternAtom(display, "_NET_CLIENT_LIST", False),
0,
1024,
False,
XA_WINDOW,
&actual_return_type,
&actual_format_return,
&win_num,
&bytes,
(unsigned char**) &windows);
printf("Found %d windows.\n", win_num);

for (; i < win_num; ++i) {
XClassHint hint;
memset(&hint, 0, sizeof(hint));
XGetClassHint(display, windows[i], &hint);
printf("%s\n", hint.res_class);
if (hint.res_class) {
if (strcasecmp(res_class, hint.res_class) == 0) {
printf("Found!!!\n");
XMapRaised(display, windows[i]);
XCloseDisplay(display);
return 0;
}
}
}

/* Reach here means the window with the name was not found. */
system(argv[2]);

if (windows)
XFree(windows);
return 0;
}


用法:

$ jump-or-exec gecko firefox

其中第一个参数为窗口的class名称,可用xprop命令查看,记得是WM_CLASS属性中的第二个字符串;第二个参数为启动该程序的命令。

第二个工具就是用来控制当前窗口的透明度的,当然前提就是你的WM要支持真透明。比如我用的Xfce4,再用之前就要先开启设置->窗口管理器调整->混合设置->允许混合显示。另外你用的xorg也要支持,并且在你的xorg.conf文件中要有这么一段:


Section "Extensions"
Option "Composite" "true"
EndSection


代码如下:

#include <X11/Xlib.h>
#include <X11/Xlibint.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#define OPACITY 0xffff

int
main(int argc, char* argv[])
{
if (argc < 2) {
fprintf(stderr, "Usage: %s step\n\n", argv[0]);
fprintf(stderr, "step: to in(de)crease opacity of current window.\n");
fprintf(stderr, " Maybe negative.\n");
return 0;
}

int step = atoi(argv[1]);

Display *display = XOpenDisplay(NULL);
if (!display) {
fprintf(stderr, "This program should be run within X environment.\n");
return 1;
}

Atom opacity_atom = XInternAtom(display, "_NET_WM_WINDOW_OPACITY", 0);

Atom actual;
int result, format;
unsigned long n, left;
unsigned char *data;

result = XGetWindowProperty(display, DefaultRootWindow(display),
XInternAtom(display, "_NET_ACTIVE_WINDOW", 0),
0L, 1L, False, XA_WINDOW, &actual, &format,
&n, &left, &data);
if (result != Success || !n || !data)
return 0;
Window active = *((Window *)data);
XClassHint hint;
memset(&hint, 0, sizeof(XClassHint));
XGetClassHint(display, active, &hint);
printf("resource name: %s\n", hint.res_name);

result = XGetWindowProperty(display, active, opacity_atom,
0L, 1L, False, XA_CARDINAL, &actual, &format,
&n, &left, &data);
int opacity = OPACITY;
if (result == Success && n && data) {
CARD32 value;
memcpy(&value, data, sizeof(CARD32));
XFree(data);
opacity = value >> 16;
printf("opacity: %d\n", opacity);
}
opacity += OPACITY * step / 100;
if (opacity < 0)
opacity = 0;
if (opacity > OPACITY)
opacity = OPACITY;
CARD32 value32 = opacity << 16 | opacity;
XChangeProperty(display, active, opacity_atom, XA_CARDINAL,
32, PropModeReplace, (unsigned char *)&value32, 1);

XSync(display, False);

return 0;
}


用法:

$ opacity -20

参数的意思是透明度的调整数值,-20就是“不透明度”-20啦。呃,当初没意识到这个问题,算了。

这两个程序在编译时别忘了加上xlib的编译参数,不知道的话就用pkg-config吧。

嗯,它们的优点就是独立于你所用的WM,配合上xbindkeys这个小软件的话就更加完美了。

嗯,就酱。

我的iPod Shuffle以及回放增益

说实话,我不确定我的iPod Shuffle是否支持我的播放软件给mp3文件打的回放增益标签,好像有的是Lame标签,有的是APE标签,还有的是id3v2标签?搞不懂啦。貌似还会有反效果,大的愈大,小的愈小,看来是跟那些软件产生了沟通问题?不管了,暴力解决之。

我的解决方案需要Lame以及WaveGain两个软件。没听说过?Google去。

$ lame --decode a.mp3 a.wav
$ lame --scale `wavegain -p -x a.wav` a.wav a.mp3


另,用Lame重新编码之后其id3v2标签就没了,需要的话请自行重新添加。我用的是mutagen。

嗯,我真是个吃饱了撑着的人。

2008年5月7日星期三

Boehm-GC 与 Glib 的集成

要迫使 Glib 也使用 Boehm-GC 貌似很简单,在你的 main() 函数的开头加入如下一段代码即可:

GMemVTable mem;

setenv("G_SLICE", "always-malloc", 1);
GC_INIT();
memset(&mem, 0, sizeof(GMemVTable));
mem.malloc = GC_MALLOC;
mem.realloc = GC_REALLOC;
mem.free = GC_FREE;
g_mem_set_vtable(&mem);

具体什么意思就去查文档吧,懒得敲了。

不过这样貌似不能处理 GObject 的 ref 和 unref ?还是要手动的吧。

就这样。