X Window System上のビープ音を利用して通知音を出す
かなり前に実験的に作成したものだが、使い方によっては有用なので、Mail Notificationの記事とともに紹介。
libX11を使用する小さなC言語のプログラム*1で、「XChangeKeyboardControl()関数により音の高さなどを設定し、XBell()関数によりベルを鳴らす」という処理をする。
ベル自体は、Linuxカーネルの「pcspkr」モジュールが有効になっているか、組み込みになっていないと鳴らないので注意。*2これは、Linux 2.6.23の時点では
Device Drivers ---> Input device support ---> [*] Miscellaneous devices ---> <M> PC Speaker support [CONFIG_INPUT_PCSPKR]
の場所にある。モジュールにすると、「modprobe -r pcspkr」でモジュールを削除することで鳴らなくすることもできて便利。
(2008/1/23)XOpenDisplay()関数にNULLを渡すことで関数変数DISPLAYを使用するように修正
ファイル名: notify-bell.c
/* Xのターミナルベルを使用した通知音 gcc -Wall -O2 notify-bell.c -o notify-bell -lX11 (古い環境では「-L/usr/X11R6/lib」も必要) */ #include <X11/Xlib.h> #include <unistd.h> #include <stdlib.h> #define bell_set(dpy, ctl, volume, pitch, duration) \ { \ ctl.bell_percent = volume; \ ctl.bell_pitch = pitch; \ ctl.bell_duration = duration; \ XChangeKeyboardControl (dpy, \ KBBellPercent | KBBellPitch | KBBellDuration, \ &ctl); \ } #define bell_restore(dpy, ctl, state) \ { \ ctl.bell_percent = state.bell_percent; \ ctl.bell_pitch = state.bell_pitch; \ ctl.bell_duration = state.bell_duration; \ XChangeKeyboardControl (dpy, \ KBBellPercent | KBBellPitch | KBBellDuration, \ &ctl); \ } #define bell(dpy, ctl, volume, pitch, duraton) \ { \ bell_set (dpy, ctl, volume, pitch, duraton); \ XBell (dpy, 0); \ XFlush (dpy); \ } int main (int argc, char **argv) { XKeyboardState state; XKeyboardControl ctl; Display *dpy = XOpenDisplay (NULL); XGetKeyboardControl (dpy, &state); /* 実行前の状態を記憶 */ /* 音を鳴らす */ bell (dpy, ctl, 20, 1750, 150); usleep (111111); bell (dpy, ctl, 15, 1500, 200); /* 実行前の状態に戻す */ bell_restore (dpy, ctl, state); XCloseDisplay (dpy); return EXIT_SUCCESS; }
これをビルドして${HOME}/bin/などに入れて実行する。
$ gcc -Wall -O2 notify-bell.c -o notify-bell -lX11 $ install -s notify-bell ~/bin/ $ ~/bin/notify-bell
下のソースは、同じときに実験の中で作成した、ベルで時報っぽいものを鳴らすプログラム。実用性はあまりないかも...
ファイル名: timesig.c
/* Xのターミナルベルを使用した通知音 gcc -Wall -O2 timesig.c -o timesig -lX11 (古い環境では「-L/usr/X11R6/lib」も必要) */ #include <X11/Xlib.h> #include <unistd.h> #include <stdlib.h> #define bell_set(dpy, ctl, volume, pitch, duration) \ { \ ctl.bell_percent = volume; \ ctl.bell_pitch = pitch; \ ctl.bell_duration = duration; \ XChangeKeyboardControl (dpy, \ KBBellPercent | KBBellPitch | KBBellDuration, \ &ctl); \ } #define bell_restore(dpy, ctl, state) \ { \ ctl.bell_percent = state.bell_percent; \ ctl.bell_pitch = state.bell_pitch; \ ctl.bell_duration = state.bell_duration; \ XChangeKeyboardControl (dpy, \ KBBellPercent | KBBellPitch | KBBellDuration, \ &ctl); \ } #define bell(dpy, ctl, volume, pitch, duraton) \ { \ bell_set (dpy, ctl, volume, pitch, duraton); \ XBell (dpy, 0); \ XFlush (dpy); \ } int main (int argc, char **argv) { int i; XKeyboardState state; XKeyboardControl ctl; Display *dpy = XOpenDisplay (NULL); XGetKeyboardControl (dpy, &state); /* 実行前の状態を記憶 */ /* 準備音 x 3 */ for (i = 0; i < 3; i++) { bell (dpy, ctl, 28, 666, 150); usleep (333333); bell (dpy, ctl, 25, 570, 150); usleep (666666); } /* 時報音 */ bell (dpy, ctl, 30, 875, 800); /* 実行前の状態に戻す */ bell_restore (dpy, ctl, state); XCloseDisplay (dpy); return EXIT_SUCCESS; }