我还是Thinkpad X32的时候,一直是用tpb来关联笔记本的acpi事件。省心是省心,不过弄得我一直觉得acpi好神秘的。现在换了Asus UL30A,发现在Arch下音量调节的快捷键都不能用了,没办法,只好自己动手。
起了个acpid,到/etc/acpi
下瞟了眼,两个目录events
和actions
,一个文件handler.sh
。又翻了下里面的文件,大概明白了。
-
events
目录里面是你要捕捉的acpi事件,文件格式如下(下面的是我用来定义华硕笔记本快捷键的)要捕捉的事件,正则匹配
event=hotkey / .*
执行的脚本,用%e将事件的名字传递
action=/home/roylez/lib/acpi/asus_button.sh %e
-
actions
是默认放执行的脚本的目录,但是你不放这里也没什么影响。比如我就把脚本放自己的home了。 -
handler.sh
会捕捉其他没有被捕捉的事件,一般不需要改。
于是,我先用acpi_listen
捕捉了静音、音量减小和音量加大的acpi事件,记下来,分别是hotkey ATKD 00000032 ...
,hotkey ATKD 00000031 ...
和hotkey ATKD 00000030 ...
。
然后,我写了个叫做asus_button.sh
的脚本
#!/bin/bash
#Author: Roy L Zuo (roylzuo at gmail dot com)
#Description: 定义Asus UL30A acpi事件
script_dir=/home/roylez/bin
export DISPLAY=:0
set $*
# "hotkey ATKD 00000030 ...."
case $3 in
00000032) # mute
su roylez -c "$script_dir/change_volume toggle"
;;
00000031) # volume down
su roylez -c "$script_dir/change_volume down"
;;
00000030) # volume up
su roylez -c "$script_dir/change_volume up"
;;
0000005c) # suspend-hybrid
pm-suspend-hybrid &
;;
esac
再然后,我在我的bin目录里面放了个用来改变音量的脚本,就叫做change_volume
#!/usr/bin/env ruby
# coding: utf-8
#Author: Roy L Zuo (roylzuo at gmail dot com)
#Description: 更改音量并用notify-send做出通知
$: << File.join(ENV['HOME'], 'lib/ruby')
require "msg.rb"
class VolumeControl
def initialize
@step = 5
@notify = File.file?("/usr/bin/notify-send") ? :show_notification : nil
end
def mute_toggle
set "toggle"
end
def set(control)
`amixer sset Master #{control}`
show
end
def down
set("#{@step}%- unmute")
`aplay #{ENV['HOME']}/.sounds/MACSound/Open.wav`
end
def up
set("#{@step}%+ unmute")
`aplay #{ENV['HOME']}/.sounds/MACSound/Open.wav`
end
def show
@status = `amixer get Master`
puts @status
@notify.nil? || send(@notify)
end
private
def show_notification
volume = mute = nil
if @status =~ /Playback.*?\[(.*?)%\].*?\[(on|off)\]/m
volume = $1.to_i
mute = $2
end if volume && mute
status = case volume
when 0..33 then 'low'
when 34..66 then 'medium'
when 67..100 then 'high'
end
status = 'muted' if mute == 'off'
icon = "/usr/share/icons/Tango/scalable/status/audio-volume-#{status}.svg"
title = mute == 'off' ? "\n 扬声器已静音" : "\n 现在音量是 #{volume}%"
msg :icon => icon, :text => '' , :title => title
end
end
end
if __FILE__ == $0
require 'optparse'
vc = VolumeControl.new
case ARGV.first
when 'help'
puts "#{$0} <command>"
puts " help show this help"
puts " show display current volume info"
puts " up increase volume"
puts " down decrease volume"
puts " toggle toggle mute"
when "show"
vc.show
when "up"
vc.up
when "down"
vc.down
when "toggle"
vc.mute_toggle
end
end
里面用到了Tango的图标主题,以及苹果系统的声音主题(有兴趣的给我发信),然后就是一个叫做msg.rb
的脚本
#!/usr/bin/env ruby
# coding: utf-8
#Author: Roy L Zuo (roylzuo at gmail dot com)
#Description: 通用提醒脚本,随机选择仆人
icon_path = File.join( ENV['HOME'], '.icons')
servants = Dir.glob(File.join(icon_path, 'servants', '*.png'))
$icon = servants[rand(servants.length)]
$title = '主人,提醒您一下:'
case ARGV.length
when 1
$text = ARGV[0]
when 2
$title, $text = ARGV
when 3
$icon = File.exist?(ARGV[0]) ? ARGV[0] : \
File.exist?(File.join( icon_path , ARGV[0])) ? File.join(icon_path,ARGV[0]) : icon
$title, $text = ARGV[1..-1]
else
$title = '错误'
$text = '参数无效'
end
def msg(kwds={})
kwds = { icon:$icon, title:$title, text:$text }.merge(kwds)
kwds[:text] = %Q{<span size="12000" weight="bold">\n#{kwds[:text]}</span>}
system(%Q{DISPLAY=:0.0 notify-send -i #{kwds[:icon]} '#{kwds[:title]}' '#{kwds[:text]}'})
end
if __FILE__==$0
msg
end
最后的效果是这样的
最后说说感想
- 最难的地方是
su roylez -c
。一直没有想到acpi脚本是用root权限执行这个问题,导致notify-send的通知怎么也不能显示,su成我的用户名就好了。 - 把华硕自带的电源管理键绑成了休眠,比Fn Fx什么的方便多了。合上屏幕就是关闭屏幕,按电源管理就是休眠,按电源就是关机。
pm-suspend-hybrid
还是个半成品,目前等于suspend to memory。change-volume
脚本可以很方便的改用OSD,加一句判断什么的就成,不过我懒得动了。- tpb好难看。