/* * Logitech iTouch keyboard thingy * * Copyright (C) 2000,2001 Ville Syrjälä * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 * Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include #include #include #include #include #include /* Your preferred OSS mixer device */ #define MIXER_DEV "/dev/mixer" /* * You can customize the keycodes here. If you don't want to grab some key * set it's keycode to -1. */ enum keycodes { suspend = 223, my_home = 178, email = 236, search = 229, go = 230, mute = 160, vol_down = 174, vol_up = 176, play = 162, stop = 164, prev_track = 144, next_track = 153, logitech = 161 }; int num_keys[] = { suspend, my_home, email, search, go, mute, vol_down, vol_up, play, stop, prev_track, next_track, logitech, 0 }; void grab_keys(Display * dpy, Window root) { unsigned int i = 0; while (num_keys[i]) { if (num_keys[i] < 0) continue; #ifdef DEBUG printf("Grabbed key %d\n", num_keys[i]); #endif XGrabKey(dpy, num_keys[i++], AnyModifier, root, False, GrabModeAsync, GrabModeAsync); } } void ungrab_keys(Display * dpy, Window root) { unsigned int i = 0; while (num_keys[i]) { if (num_keys[i] < 0) continue; #ifdef DEBUG printf("Ungrabbed key %d\n", num_keys[i]); #endif XUngrabKey(dpy, num_keys[i++], AnyModifier, root); } } void run(const char *cmd,...) { const char *argv[1024]; unsigned int i; va_list args; pid_t pid; #ifdef DEBUG printf("exec: %s", cmd); #endif argv[0] = cmd; i = 1; va_start(args, cmd); do { argv[i] = va_arg(args, const char *); #ifdef DEBUG printf(" %s", argv[i]); #endif } while (argv[i++] != NULL); va_end(args); #ifdef DEBUG printf("\n"); #endif if ((pid = fork()) == 0) { if (execvp(cmd, (char *const *) argv) < 0) fprintf(stderr, "exec error - %s\n", strerror(errno)); } else if (pid == -1) fprintf(stderr, "fork error - %s\n", strerror(errno)); } void get_volume(int *l, int *r) { int fd, v, cmd, devs; fd = open(MIXER_DEV, O_RDONLY); if (fd != -1) { ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devs); if (devs & SOUND_MASK_VOLUME) cmd = SOUND_MIXER_READ_VOLUME; else if (devs & SOUND_MASK_PCM) cmd = SOUND_MIXER_READ_PCM; else { close(fd); return; } ioctl(fd, cmd, &v); *r = (v & 0xFF00) >> 8; *l = (v & 0x00FF); #ifdef DEBUG printf("get_volume: left = %d, right = %d\n", *l, *r); #endif close(fd); } else fprintf(stderr, "open error %s - %s\n", MIXER_DEV, strerror(errno)); } void set_volume(int l, int r) { int fd, v, cmd, devs; fd = open(MIXER_DEV, O_RDONLY); if (fd != -1) { ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devs); if (devs & SOUND_MASK_VOLUME) cmd = SOUND_MIXER_WRITE_VOLUME; else if (devs & SOUND_MASK_PCM) cmd = SOUND_MIXER_WRITE_PCM; else { close(fd); return; } v = (r << 8) | l; ioctl(fd, cmd, &v); #ifdef DEBUG printf("set_volume: left = %d, right = %d\n", l, r); #endif close(fd); } else fprintf(stderr, "open error %s - %s\n", MIXER_DEV, strerror(errno)); } /* * You can change the commands in this function to work with your system. */ int handle_keyevent(int keycode) { static int muted, l, r, old_l, old_r, new_l, new_r, stopped; char *www_home; char *www_search; #ifdef DEBUG printf("key release: %d\n", keycode); #endif switch (keycode) { case suspend: run("apmd", "-s", NULL); break; case my_home: www_home = getenv("WWW_HOME"); run("netscape", www_home ? www_home : "", NULL); free(www_home); break; case email: run("xterm", "-e", "pine", NULL); break; case search: www_search = getenv("WWW_SEARCH"); run("netscape", www_search ? www_search : "", NULL); free(www_search); break; case go: break; case mute: if (muted) set_volume(l, r); else { get_volume(&l, &r); set_volume(0, 0); } muted = muted ? 0 : 1; break; case vol_down: if (muted) break; get_volume(&l, &r); old_l = l; old_r = r; do { if (--l < 0) l = 0; if (--r < 0) r = 0; set_volume(l, r); get_volume(&new_l, &new_r); } while (r != 0 && l != 0 && new_l == old_l && new_r == old_r); break; case vol_up: if (muted) break; get_volume(&l, &r); old_l = l; old_r = r; do { if (++l > 100) l = 100; if (++r > 100) r = 100; set_volume(l, r); get_volume(&new_l, &new_r); } while (r != 100 && l != 100 && new_l == old_l && new_r == old_r); break; case play: if (stopped) run("xmms", "-p", NULL); else run("xmms", "-u", NULL); stopped = 0; break; case stop: run("xmms", "-s", NULL); stopped = 1; break; case prev_track: run("xmms", "-r", NULL); break; case next_track: run("xmms", "-f", NULL); break; case logitech: return 1; /* Exit program */ break; default: break; } return 0; } int main(void) { Display *dpy; Window root; XEvent event; long mask = KeyReleaseMask; int i = 0; dpy = XOpenDisplay(NULL); if (!dpy) exit(1); root = DefaultRootWindow(dpy); if (!root) { XCloseDisplay(dpy); exit(1); } grab_keys(dpy, root); while (!i) { XMaskEvent(dpy, mask, &event); i = handle_keyevent(event.xkey.keycode); } ungrab_keys(dpy, root); XCloseDisplay(dpy); return 0; }