Thinkpad 的键盘上有一些特殊地按键如音量控制等,在 Linux 下可以通过 tpb 这个工具利用起来,tpb 可以识别这些按键并执行一系列地操作,例如调用某个脚本或者用 xosd 在屏幕上显示(音量、亮度等)一个状态。不过我新装的这个 Arch Linux 的 tpb 在 Thinkpad X200 下工作不太正常,于是用了另一个办法来解决,使用很浮云地 notify-osd 加上自制的脚本来实现相同的目的。
以下是废话:
最近频繁地背着笔记本往来于 ZJG 和 YQ 两个校区,原来那个 Thinkpad R60e 不仅非常重,而且散热量非常大,看到毕业结算的时候学校退了一些学费,于是加上自己攒的一些钱买了一个 Thinkpad X200 ,顿时感觉好轻呀! 😀
X200 预装了 Windows Vista Home Basic 这个非常鸡肋的系统,一开始我想着好歹还是正版,还是留着吧,可是用了一下发现又卡又烦人,发现 Vista 竟然比我记忆中的要难用这么多啊,再想至少保留一个备份吧,可是用系统自带的工具折腾了好久都没有成功,一怒之下就全盘 erase 了装成 Linux 了。-.-bb
当时拿到 R60e 的时候是立即装了 Debian ,这次是装的 Arch Linux ,都是整个硬盘全部 erase ,所以隐藏分区也没有了,那个万能地 ThinkVantage 键之后拿来做什么还是慢慢想吧,Thinkpad 要是改回以前那样送光盘多好。
以下是正文:
装好系统之后配置声音的时候选择了 ALSA ,其实装好 alsa 相关的包然后运行 alsaconf
就有声音了,不过键盘上的音量控制按钮很奇怪,可以静音,但是却没法调整声音,似乎和之前的 R60e 不一样,这个不是 hardware mixer ,而是 software mixer ,在网上搜索了许多方法设置都不可以,tpb 的配置文件里面倒是有选项是选择可以使用 software mixer 的,但是依然没有效果,尝试各种配置之后得到的结果如果不是没有变化的话,就是更差了。所以最后我决定直接绑定按键用命令来调整音量。
不过整个声音系统似乎本身也比较奇怪,用 amixer 或者 alsamixer 设置 mute 之后音乐还是照常正常播放的,所以要 mute 似乎只有保存一下当前的音量,然后把音量设置为 0 ,在 unmute 的时候则读入之前保存的音量。不过,即使采取了这个办法,也还有一个问题:静音按钮无法捕获。
这真是非常奇怪的事,因为我之前确实捕获到这个按钮,并且在 xev 里查到了它的 keysym 是 XF86AudioMute ,但是后来却怎么都捕获不到了,不过 tpb 却是可以识别到,所以我确信那个按钮还没有坏。因为之前在尝试解决的时候用了各种配置,所以应该是某个配置导致的吧。经过各种尝试,才终于发现了原来要在系统启动的时候内核参数加上 acpi_osi="Linux"
(就是加在 /boot/grub/menu.lst
文件的 kernel
那一行)参数才能识别出这个按键来。不过网上有说加上了这个参数之后调整音量就正常了,可惜我的 tpb 还是无法工作,并且(不确定是不是哪个步骤的配置又影响到了)其他部分也变得不太好用了,比如亮度调整的时候如果连续的按键的话,几次调整的状态会重叠显示在屏幕上。所以我决定彻底放弃 tpb 了。
其实自己绑定按键执行相应的命令也还是挺方便的。我用的窗口管理器是 Openbox ,首先运行 xev ,按下对应的键,从输出中找到对应的 keysym ,比如 XF86AudioRaiseVolume ,然后在 ~/.config/openbox.rc.xml
的 keyboard 一节加上这样的配置:
<keybind key="XF86AudioRaiseVolume"> <action name="Execute"> <execute>amixer set Master 2+</execute> </action> </keybind> |
然后重新加载一下配置文件就可以了。而静音的话,可以写一个脚本来先保存当前音量。不过,这样虽然可以调整音量,但是只是盲按,没有一点具体的反馈(比如什么时候已经达到最大音量了)还是不太方便。
但是要在屏幕上显示那样的东西,我还是只想到 xosd 或者 dzen2 ,dzen2 似乎比较难控制一点,关键是两次按键是会以两个独立的脚本运行起来的,而 xosd 似乎主要是提供了可编程的 API ,可执行文件就是 osd_cat ,可以在屏幕上显示一个文件的内容,不过其实也可以做,比如用一个比较大的字体显示
Volume: |||||-----
其实也就相当直观了,tpb 画出来的图也就是差不多这个样子而已。只是这个方案很快就又被否决了,问题还是出在重复按键上,如果我连续按几下的话,几次显示的东西就重叠在一起了,根本不具有可用性。就在我都决定要放弃实时显示,只在静音或者音量达到最大、最小时用 libnotify 发一个提示消息的时候,不小心找到了 notify-osd 这个东西。似乎是 Ubuntu 社区开发出来的东西,看起来相当浮云,在 Arch 仓库里暂时还没有,不过在 AUR 上又相应的包。用这个东西代替那个很土的 notification-daemon 就可以实现实时显示了。
notify-osd 使用的是 notification-daemon 同一个接口,所以也只要通过 notify-send 来发送提醒就可以了,它的弹出提示有淡入淡出效果并且是半透明的(当然,需要开启了 Composite 的支持),并且还有许多很先进的地方,比如显示一个状态条,正好用于音量的显示,并且它还能合并多次 notify ,也就是说我连续按下几次调整音量的话,它会直接更新原来的那个 notify bubble ,而不是弹出一个新的 bubble 。
好了,废话说完了,下面开始动工!首先是 notify-osd ,如果装好了 yaourt ,只需要运行
yaourt notify-osd
然后按照提示选择,就会自动下载并编译、安装好了,如果之前已经安装了 notification-daemon
,则先卸载之。重新启动一下 X 即可生效,不过,Openbox 没有 composite 的支持,notify-osd 不能半透明,这个可以使用 xcompmgr
来辅助,不过我不需要阴影和淡入淡出,所以直接运行 xcompmgr ,把下面这一行加入到 ~/.config/openbox/autostart.sh
中即可:
xcompmgr & |
这里顺便提一个问题,我一开始运行 xcompmgr 的时候屏幕疯狂地输出类似如下的错误:
error 168 request 153 minor 8 serial 1919 error 168 request 153 minor 8 serial 2131 error 168 request 153 minor 8 serial 2239 error 168 request 153 minor 8 serial 2347 error 168 request 153 minor 8 serial 2455 error 168 request 153 minor 8 serial 2563
查了一下原来是应为我使用 xloadimage 来设置桌面壁纸的缘故,它的某个不规范的行为(没有将 _XSETROOT_ID
设置为一个有效的 pixmap )让 xcompmgr 郁闷了,改用 feh 来设置壁纸之后就 OK 了。事实上我在很久很久前 Debian 中就遇到了这个问题,只是当时怎么都没有想到会是桌面壁纸的问题。 -.-bb
然后是控制音量并显示提示的脚本,控制音量使用 amixer ,静音按照之前的方法将音量保存在 ~/.thinkpad-volume
文件中。另外,我还彻底抛弃了 tpb ,把亮度调节也加入到脚本中来,只是和音量调节不一样的是,亮度调节按下 Fn+Home
和 Fn+End
就可以实现了,脚本里只要读出调节后的值再用 notify-osd 显示出来就可以了。脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | #!/usr/bin/python # processing of thinkpad multi-media key import sys import re import os if len(sys.argv) < 2: print "Usage:" print " %s cmd" % sys.argv[0] print "" print " Available commands:" print " - vol-up" print " - vol-down" print " - mute" print " - brightness" sys.exit(1) cmd = sys.argv[1] ######################################## # Configurations ######################################## MIXER = "Master" VOLSTEP = 2 VOLTMP = os.path.expanduser('~/.thinkpad-volume') BRFILE = '/proc/acpi/video/VID/LCD0/brightness' ######################################## # Utility routines ######################################## def get_volume(): info = os.popen('amixer get %s' % MIXER).read() limit = re.search(r'Limits: Playback 0 - (\d+)', info).group(1) vol = re.search(r'Front Left: Playback (\d+)', info).group(1) return (int(vol), int(limit)) def notify_percentage(subject, value, limit): percentage = value * 100 / limit if percentage < 30: icon = 'low' elif percentage > 70: icon = 'high' else: icon = 'medium' os.system('notify-send "%s" ' % subject + '-i notification-%s-%s ' % (subject, icon) + '-h int:value:%d ' % percentage + '-h string:x-canonical-private-synchronous:') def adjust_volume(adjustment): curr_volume, limit = get_volume() dest_volume = curr_volume+adjustment if dest_volume < 0: dest_volume = 0 if dest_volume > limit: dest_volume = limit os.system("amixer set %s %d unmute" % (MIXER, dest_volume)) notify_percentage('audio-volume', dest_volume, limit) def toggle_mute(): curr_volume, limit = get_volume() if curr_volume == 0: try: orig_volume = int(open(VOLTMP).read()) except: orig_volume = limit/2 os.system("amixer set %s %d unmute" % (MIXER, orig_volume)) notify_percentage('audio-volume', orig_volume, limit) else: open(VOLTMP, 'w').write('%d' % curr_volume) os.system("amixer set %s 0 unmute" % MIXER) os.system('notify-send "Volume" ' + '-i notification-audio-volume-muted ' + '-h int:value:0 ' + '-h string:x-canonical-private-synchronous:') def get_brightness(): info = open(BRFILE).readlines() limit = int(info[0].split()[-1]) curr = int(info[1].split()[-1]) return (curr, limit) def adjust_brightness(): # brightness is adjusted from hardware, we just show # notification curr, limit = get_brightness() notify_percentage('display-brightness', curr, limit) ######################################## # Main routine ######################################## if cmd == 'vol-up': adjust_volume(VOLSTEP) elif cmd == 'vol-down': adjust_volume(-VOLSTEP) elif cmd == 'mute': toggle_mute() elif cmd == 'brightness': adjust_brightness() |
然后在 Openbox 中把各个按键绑定到这个脚本上:
<!-- multimedia keys --> <keybind key="XF86AudioMute"> <action name="Execute"> <execute>/home/pluskid/bin/thinkpad-mmkey.py mute</execute> </action> </keybind> <keybind key="XF86AudioRaiseVolume"> <action name="Execute"> <execute>/home/pluskid/bin/thinkpad-mmkey.py vol-up</execute> </action> </keybind> <keybind key="XF86AudioLowerVolume"> <action name="Execute"> <execute>/home/pluskid/bin/thinkpad-mmkey.py vol-down</execute> </action> </keybind> <keybind key="XF86MonBrightnessUp"> <action name="Execute"> <execute>/home/pluskid/bin/thinkpad-mmkey.py brightness</execute> </action> </keybind> <keybind key="XF86MonBrightnessDown"> <action name="Execute"> <execute>/home/pluskid/bin/thinkpad-mmkey.py brightness</execute> </action> </keybind> |
这下就可以有很浮云的实时提醒了! 😀
最后再说几句废话,X200 还是很不错的,不过 ESC 键那里的壳似乎有一点松,所以按的时候会啪啪地响,莫非是交给联想之后做工变得粗糙了? -,-bb 装 Linux 除了音量控制搞得有点崩溃之外,基本没有遇到问题,我还是比较喜欢 R60e 那样的 hardware mixer 。无线应该也没有问题,只是(不知道是不是考试的原因)最近一两周紫金港的无线网络完全瘫痪了,没法测试。宽屏分辨率也完全没有问题,装好 xf86-video-intel
之后甚至不需要生成 xorg.conf 就可以很正常地跑起 X 来(不过我还是启动不起 compiz ,一运行 fusion-icon ,X 就退出了,没有任何错误信息)。小红点支持也很好,甚至比 Windows 下还好用,Windows 下如果启用了小红点的滚屏功能的话,中键的很多功能都不能用了,比如在 Firefox 里用来在新标签中打开链接、关闭标签页等,然而在 Linux 下却可以两者兼得,不得不说小红点是我最喜欢的 Thinkpad 的设计。最后就是休眠了,似乎这些方面 Linux 还得持续改进才行,我一看到网上超级复杂的文档就开始退缩了。总的来说还是相当不错的!下面 show 一张截屏吧,Openbox + conky + tint2 :
先推荐一个小黑的网站: http://www.thinkwiki.org
说几点你可能会乎略的问题:
0) 相关内核模块是CONFIG_THINKPAD_ACPI, 不过arch好像默认m了所有模块所以不是问题. 另外还有一个包叫thinkpad smapi (tpctl.sf.net)
1) 电池充电的上下限, 这个对延长电池寿命很有用. 有0)之后, 相关文件在/sys/devices/platform/smapi/BAT0/start(stop)_charge_thresh. 以battery搜索thinkwiki有更详细的帖子
2) 硬盘门事件..
http://www.thinkwiki.org/wiki/Problem_with_hard_drive_clicking
3) 电源管理. 可以考虑用laptop-mode-tools包.
另外挂起/休眠我用的是tuxonice的kernel, 配套的用户工具是hibernate-script
Fn热键绑定我用的是acpid (e.g., Fn-F4 suspend to ram, Fn-F12 suspend to disk, etc). 在某些型号下可能需要
cat /sys/devices/platform/thinkpad_acpi/hotkey_all_mask > /sys/devices/platform/thinkpad_acpi/hotkey_mask
来unmask所有Fn组合 (软件作者不推荐:D)
更广义的热键绑定我用actkbd, e.g., 长按mute键mute, 短按则切换mute/unmute, etc. 我因为要用到tablet面板上的按键, 所以普通的肩膀定功能都单薄了点. 以前写的一个帖子(要翻墙):
http://zeekish.wordpress.com/2009/03/26/actkbd/
先打这些, 吃早饭去了
果然Linuxer都是相当折腾呢!
自从内核的一个版本,我这里Fn+x调整屏幕亮度就不工作了,不过似乎我平时不需要调亮度,音量似乎也没有特别频繁地要用快捷键调整的需要 -.-b 虽然 xev 都可以捕获到这些键,但是懒得设置执行程序了。
notify-osd看起来很pp,考完试就换成它。顺便我也来折腾下这些快捷键…
那张壁纸我以前也用过,很喜欢 :p
x200的屏幕实在太小,不喜欢。
我用的是x61,但是那个右掌托发热的问题实在没法解决(我把BIOS里能关的选项都关了,系统设置上,又是延长系统写入脏页时间,又是调整电源管理策略…最终发觉温度还是比windows下要高3-4度),如果还要一直用无线,会非常的痛苦。编译一个emacs,CPU温度可以上95-98度… 如果要跑kvm,qemu,bochs或者xen(vmware要好一点),那简直…太心疼我的笔记本了。
虽然居无定所,用笔记本搬家方便,但是我已经决定了:下一台电脑,一定买台式的…
@galilette
多谢这些建议呢!用了电池设置和电源管理的东西,不过休眠还是不行,用 TuxOnIce 的 kernel ,由于一开始把 swap 分区只分了 256M ,又不想调整分区,就用休眠到文件的办法,也不知道是 ext4 文件系统的问题还是磁盘驱动的问题,不能成功从休眠中恢复。于是以后再考虑这个问题了,其实要用到休眠的时候好像也不多。
ps: 那个是你的 blog 啊? 🙂
关于休眠碰到的问题, 具体可能要看一下log文件了, 我这边是 /var/log/hibernate.log. 我能想到的几种可能:
1) 在设置SuspendDevice时你可能用了file:/dev/sda:0x0000, 你可以把file改成swap试试 (但后面还是跟文件而不是swap分区)。 我最早装的时候用file会corrupt the swap file, 可能是tuxonice的bug,不知道现在修复没有
2) 可能是因为initrd的问题,arch好像只是把ext4编译成模块的样子,tuxonice未必能及时载入文件系统模块。这个可能需要看一下tuxonice里关于initrd的文档。我在gentoo上是把这种启动相关的模块都编译进内核的,省掉一些麻烦
挂起到硬盘还是蛮方便的, 有点像一个universal session manager
那个blog我就是记录一点机器设置的问题,年纪大了全记脑子里记不住了
@galilette
/var/log/hibernate.log 倒是挺正常的,不过 dmesg 有些错误,像这个样子:
我想要么就是文件系统要么就是磁盘驱动的问题吧,后来我改成 swap 分区了(只是先用小的分区试一下),结果是另一个错误:
但是感觉是差不多的,而且这次是直接连 suspend 都不成功的。
不过
modprobe scsi
是失败的,这个感觉应该已经被直接编译进内核了,而不是以模块的形式存在了吧?真奇怪。有没有做过这一步?
http://wiki.archlinux.org/index.php/Tuxonice#Recreating_the_initramfs
还有就是你第二个错误里为啥是hda不是sda呢?
我给我爸的台机装了arch, 其他都不错, yaourt很好很强大, 就是感觉内核弄起来不及自己编译来得直接
@galilette
应该是 sda ,在 dmesg 里的,我没有保存日志,就看了昨天的浏览器搜索记录,我搜索的时候去掉了具体的 partition ,所以刚才打错了。
那一步确实做过了,我还尝试把 resume 这个 hook 放到 filesystem 后面也不行,按理说如果连 filesystem 都已经起来了,磁盘和文件系统应该都已经初始化好了啊。
确实 yaourt 装内核的时候都不知道哪里可以有机会修改内核配置。
@pluskid
恩,应该是修改 PKGBUILD 文件里把
make menuconfig
一行注释掉就可以配置内核编译选项了。 🙂http://aur.archlinux.org/packages.php?ID=15224
第一条bug不知道跟你的有没有关系
btw gentoo上tuxonice还停留在2.6.29, 所以你说的问题也可能是patchset和.30不完全匹配有关. tuxonice官方还没有.30的稳定版发布
@galilette
也许是呢,没有验证过,不过想起来 yaourt 下载的其中一个 patch 的 md5sum 和 PKGBUILD 中列的不一样,我当时忽略掉了这个问题,应为 patch 倒是能正常打上的。现在这个样子,好像 Arch 里 2.6.30 的 kernel 也才刚启用不久,还是等一段时间再来看看好了。
米男阿!
arch下小红点还不错,默认的灵敏度比xp的高点,xp下我调了下,跟arch差不多了。中键也不错,但不能左右滚动,现在已经习惯用ctrl + w关闭标签,ctrl + 左键 在新标签打开链接了。
arch下的风扇呼呼作响。x200的字体好小,xp下我把dpi调到了110来用,但某些程序的界面变形了,而arch下dpi可以调到250,字体和界面都自适应变得,这个好。据说vista下dpi和linux的类似,xp的不行。
@pluskid
如果不考虑休眠时的界面,个人觉得tuxonice已经非常鸡肋了。现在不管是ibm T43还是hp nc6400中我都是用pm-suspend/pm-hibernate来待机与休眠,无需其他设置,非常的方便。pm-utils应该算是系统的核心包了,arch应该也是带了的吧(俺用gentoo)。
@transtone
Arch 确实也有那个包,不过我的 swap 分区分得太小了,需要能支持 suspend to file 的支持才行。
昨天刚入手x200。。。。
就差这个浮云了。。。嘿嘿
然后发现只要启动gnome-settings-daemon就好了。。。-,-
看来ubuntu下了很多功夫啊。。。。
@Mike
恩,gnome-daemon 会处理音量调节,但是亮度好像没有。而且我现在好像如果没有先锁定就把盖子合上,然后过一段时间再打开的话就一直黑屏,得强行重启或者远程重启,不知道是不是它自动休眠却休眠失败了,真是……
@pluskid
应该是gnome-power-manager管亮度的。最开始我没启动gnome-settings-daemon的时候就没有声音,启动了它,有屏幕亮度。。。。
我的x200是7457a46,suspend和hibernate都没有任何问题啊。。。难道是ubuntu用了一些神奇的驱动?@_@
@Mike
不一定是驱动吧,估计是打过 kernel patch 什么的或者有一些额外的配置文件,只是也许自己弄的话搞起来毕竟麻烦,但是如果用 Gnome 的话,它应该自动搞定了一些东西了,如果用 Ubuntu 下的 Gnome 的话,应该有更多的东西被自动搞定了,像休眠什么的。
@Mike
不管怎么说,我不太喜欢它这种 soft mixer ,感觉还是那种硬件控制声音的好用一些。
osd_cat 可以直接显示“|||—“,用–barmode参数
试试看:
我的OSD_Volumn.sh:
#!/bin/sh
# get volumn value from system
volumn_percent=$(amixer get Master | grep –color=never Mono: | sed -e s/” Mono: Playback [0-9]* \[“// -e s/”%.*”//)
# show it by percentage
killall osd_cat
osd_cat –pos=bottom –align=center –color=green –shadow=3 –delay=1 –barmode=percentage –percentage=$volumn_percent &
然后加到.xbindkeys中就可以了:
“amixer sset Master 1-;~/.myscript/OSD_Volumn.sh”
m:0x10 + c:122
Mod2 + XF86AudioLowerVolume