diff options
author | Daniel Stone <daniel@fooishbar.org> | 2006-11-01 23:10:26 +0200 |
---|---|---|
committer | Daniel Stone <daniels@endtroducing.fooishbar.org> | 2006-11-01 23:10:26 +0200 |
commit | 81728558a044fdde0e1d63da7b6314755f77296e (patch) | |
tree | 94e8bb0559aee194216164ee10b09446ca1570a0 | |
parent | 3df454719f9cbf6a046cb7458019ec621b3b42ee (diff) |
input: add non-keyboard bell ringing function
Add a generic 'ring the bell' function (console bell on Linux and BSD,
/dev/audio on Solaris), and add DDX functions for this. Make this the
core keyboard's bell.
Port Xvfb and Xnest to this.
Port XFree86 to this, with OS-specific hooks for Linux, BSD, and Solaris
taken from foo_io.c in the old layer.
-rw-r--r-- | dix/devices.c | 6 | ||||
-rw-r--r-- | hw/vfb/InitInput.c | 4 | ||||
-rw-r--r-- | hw/xfree86/common/xf86Events.c | 5 | ||||
-rw-r--r-- | hw/xfree86/os-support/bsd/Makefile.am | 1 | ||||
-rw-r--r-- | hw/xfree86/os-support/bsd/bsd_bell.c | 81 | ||||
-rw-r--r-- | hw/xfree86/os-support/linux/Makefile.am | 2 | ||||
-rw-r--r-- | hw/xfree86/os-support/linux/lnx_bell.c | 43 | ||||
-rw-r--r-- | hw/xfree86/os-support/solaris/Makefile.am | 2 | ||||
-rw-r--r-- | hw/xfree86/os-support/solaris/sun_bell.c | 184 | ||||
-rw-r--r-- | hw/xfree86/os-support/xf86_OSproc.h | 1 | ||||
-rw-r--r-- | hw/xnest/Keyboard.c | 6 | ||||
-rw-r--r-- | include/input.h | 6 |
12 files changed, 335 insertions, 6 deletions
diff --git a/dix/devices.c b/dix/devices.c index a554f2f79..aa0486219 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -211,9 +211,11 @@ ActivateDevice(DeviceIntPtr dev) } static void -CoreKeyboardBell(int volume, DeviceIntPtr pDev, pointer ctrl, int something) +CoreKeyboardBell(int volume, DeviceIntPtr pDev, pointer arg, int something) { - return; + KeybdCtrl *ctrl = arg; + + DDXRingBell(volume, ctrl->bell_pitch, ctrl->bell_duration); } static void diff --git a/hw/vfb/InitInput.c b/hw/vfb/InitInput.c index 9cb1c02cb..99cf56c70 100644 --- a/hw/vfb/InitInput.c +++ b/hw/vfb/InitInput.c @@ -55,6 +55,10 @@ ProcessInputEvents() miPointerUpdate(); } +void DDXRingBell(int volume, int pitch, int duration) +{ +} + #define VFB_MIN_KEY 8 #define VFB_MAX_KEY 255 KeySym map[MAP_LENGTH * LK201_GLYPHS_PER_KEY]; diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c index 3df201aa7..4a9f36926 100644 --- a/hw/xfree86/common/xf86Events.c +++ b/hw/xfree86/common/xf86Events.c @@ -1128,6 +1128,11 @@ xf86ReloadInputDevs(int sig) return; } +_X_EXPORT void +DDXRingBell(int volume, int pitch, int duration) { + xf86OSRingBell(volume, pitch, duration); +} + #ifdef WSCONS_SUPPORT /* XXX Currently XKB is mandatory. */ diff --git a/hw/xfree86/os-support/bsd/Makefile.am b/hw/xfree86/os-support/bsd/Makefile.am index 0a0bcab3e..e456328df 100644 --- a/hw/xfree86/os-support/bsd/Makefile.am +++ b/hw/xfree86/os-support/bsd/Makefile.am @@ -63,6 +63,7 @@ libbsd_la_SOURCES = \ bsd_VTsw.c \ bsd_init.c \ bsd_mouse.c \ + bsd_bell.c \ $(ARCH_SOURCES) \ $(AGP_SOURCES) \ $(APM_SOURCES) \ diff --git a/hw/xfree86/os-support/bsd/bsd_bell.c b/hw/xfree86/os-support/bsd/bsd_bell.c new file mode 100644 index 000000000..60c2ffc8b --- /dev/null +++ b/hw/xfree86/os-support/bsd/bsd_bell.c @@ -0,0 +1,81 @@ +/* + * Copyright 1992 by Rich Murphey <Rich@Rice.edu> + * Copyright 1993 by David Dawes <dawes@xfree86.org> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of Rich Murphey and David Dawes + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Rich Murphey and + * David Dawes make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * RICH MURPHEY AND DAVID DAWES DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID DAWES BE LIABLE FOR + * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <termios.h> + +#include "xf86.h" +#include "xf86Priv.h" + +#ifdef WSCONS_SUPPORT +#define KBD_FD(i) ((i).kbdFd != -1 ? (i).kbdFd : (i).consoleFd) +#endif + +_X_EXPORT void +xf86OSRingBell(int loudness, int pitch, int duration) +{ +#ifdef WSCONS_SUPPORT + struct wskbd_bell_data wsb; +#endif + + if (loudness && pitch) + { +#ifdef PCCONS_SUPPORT + int data[2]; +#endif + + switch (xf86Info.consType) { + +#ifdef PCCONS_SUPPORT + case PCCONS: + data[0] = pitch; + data[1] = (duration * loudness) / 50; + ioctl(xf86Info.consoleFd, CONSOLE_X_BELL, data); + break; +#endif +#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) + case SYSCONS: + case PCVT: + ioctl(xf86Info.consoleFd, KDMKTONE, + ((1193190 / pitch) & 0xffff) | + (((unsigned long)duration*loudness/50)<<16)); + break; +#endif +#if defined (WSCONS_SUPPORT) + case WSCONS: + wsb.which = WSKBD_BELL_DOALL; + wsb.pitch = pitch; + wsb.period = duration; + wsb.volume = loudness; + ioctl(KBD_FD(xf86Info), WSKBDIO_COMPLEXBELL, + &wsb); + break; +#endif + } + } +} diff --git a/hw/xfree86/os-support/linux/Makefile.am b/hw/xfree86/os-support/linux/Makefile.am index fc4243b26..673a4e128 100644 --- a/hw/xfree86/os-support/linux/Makefile.am +++ b/hw/xfree86/os-support/linux/Makefile.am @@ -20,7 +20,7 @@ XORG_CFLAGS += -DHAVE_APM endif liblinux_la_SOURCES = lnx_init.c lnx_video.c lnx_mouse.c \ - lnx_pci.c lnx_agp.c lnx_kmod.c \ + lnx_pci.c lnx_agp.c lnx_kmod.c lnx_bell.c \ $(srcdir)/../shared/bios_mmap.c \ $(srcdir)/../shared/VTsw_usl.c \ $(srcdir)/../shared/posix_tty.c \ diff --git a/hw/xfree86/os-support/linux/lnx_bell.c b/hw/xfree86/os-support/linux/lnx_bell.c new file mode 100644 index 000000000..6ef881bf7 --- /dev/null +++ b/hw/xfree86/os-support/linux/lnx_bell.c @@ -0,0 +1,43 @@ +/* + * Copyright © 2006 Daniel Stone + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and that + * both that this copyright notice and this permission notice appear in + * supporting electronic documentation. + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR AUTHORS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Daniel Stone <daniel@fooishbar.org> + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <sys/ioctl.h> +#include <linux/kd.h> + +#include "xf86.h" +#include "xf86Priv.h" + +_X_EXPORT void +xf86OSRingBell(int loudness, int pitch, int duration) +{ + if (xf86Info.consoleFd == -1 || !pitch || !loudness) + return; + + ioctl(xf86Info.consoleFd, KDMKTONE, + ((1193190 / pitch) & 0xffff) | + (((unsigned long)duration * loudness / 50) << 16)); +} diff --git a/hw/xfree86/os-support/solaris/Makefile.am b/hw/xfree86/os-support/solaris/Makefile.am index 9c8607918..291c329ea 100644 --- a/hw/xfree86/os-support/solaris/Makefile.am +++ b/hw/xfree86/os-support/solaris/Makefile.am @@ -19,7 +19,7 @@ solaris-$(SOLARIS_INOUT_ARCH).il: solaris-${SOLARIS_INOUT_ARCH}.S noinst_LTLIBRARIES = libsolaris.la libsolaris_la_SOURCES = sun_bios.c sun_init.c \ - sun_mouse.c sun_vid.c $(AGP_SRC) \ + sun_mouse.c sun_vid.c sun_bell.c $(AGP_SRC) \ $(srcdir)/../shared/libc_wrapper.c \ $(srcdir)/../shared/kmod_noop.c $(srcdir)/../shared/pm_noop.c \ $(srcdir)/../shared/posix_tty.c $(srcdir)/../shared/sigiostubs.c \ diff --git a/hw/xfree86/os-support/solaris/sun_bell.c b/hw/xfree86/os-support/solaris/sun_bell.c new file mode 100644 index 000000000..369103f7b --- /dev/null +++ b/hw/xfree86/os-support/solaris/sun_bell.c @@ -0,0 +1,184 @@ +/* Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons + * to whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * of the copyright holder. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <sys/audio.h> +#include <sys/uio.h> +#include <limits.h> +#include <math.h> +#include <poll.h> + +#include "xf86.h" +#include "xf86Priv.h" + +#define BELL_RATE 48000 /* Samples per second */ +#define BELL_HZ 50 /* Fraction of a second i.e. 1/x */ +#define BELL_MS (1000/BELL_HZ) /* MS */ +#define BELL_SAMPLES (BELL_RATE / BELL_HZ) +#define BELL_MIN 3 /* Min # of repeats */ + +#define AUDIO_DEVICE "/dev/audio" + +_X_EXPORT int +xf86OSRingBell(int loudness, int pitch, int duration) +{ + static short samples[BELL_SAMPLES]; + static short silence[BELL_SAMPLES]; /* "The Sound of Silence" */ + static int lastFreq; + int cnt; + int i; + int written; + int repeats; + int freq; + audio_info_t audioInfo; + struct iovec iov[IOV_MAX]; + int iovcnt; + double ampl, cyclen, phase; + int audioFD; + + if ((loudness <= 0) || (pitch <= 0) || (duration <= 0)) { + return 0; + } + + lastFreq = 0; + bzero(silence, sizeof(silence)); + + audioFD = open(AUDIO_DEVICE, O_WRONLY | O_NONBLOCK); + if (audioFD == -1) { + xf86Msg(X_ERROR, "Bell: cannot open audio device \"%s\": %s\n", + AUDIO_DEVICE, strerror(errno)); + return -1; + } + + freq = pitch; + freq = min(freq, (BELL_RATE / 2) - 1); + freq = max(freq, 2 * BELL_HZ); + + /* + * Ensure full waves per buffer + */ + freq -= freq % BELL_HZ; + + if (freq != lastFreq) { + lastFreq = freq; + ampl = 16384.0; + + cyclen = (double) freq / (double) BELL_RATE; + phase = 0.0; + + for (i = 0; i < BELL_SAMPLES; i++) { + samples[i] = (short) (ampl * sin(2.0 * M_PI * phase)); + phase += cyclen; + if (phase >= 1.0) + phase -= 1.0; + } + } + + repeats = (duration + (BELL_MS / 2)) / BELL_MS; + repeats = max(repeats, BELL_MIN); + + loudness = max(0, loudness); + loudness = min(loudness, 100); + +#ifdef DEBUG + ErrorF("BELL : freq %d volume %d duration %d repeats %d\n", + freq, loudness, duration, repeats); +#endif + + AUDIO_INITINFO(&audioInfo); + audioInfo.play.encoding = AUDIO_ENCODING_LINEAR; + audioInfo.play.sample_rate = BELL_RATE; + audioInfo.play.channels = 2; + audioInfo.play.precision = 16; + audioInfo.play.gain = min(AUDIO_MAX_GAIN, AUDIO_MAX_GAIN * loudness / 100); + + if (ioctl(audioFD, AUDIO_SETINFO, &audioInfo) < 0){ + xf86Msg(X_ERROR, + "Bell: AUDIO_SETINFO failed on audio device \"%s\": %s\n", + AUDIO_DEVICE, strerror(errno)); + close(audioFD); + return -1; + } + + iovcnt = 0; + + for (cnt = 0; cnt <= repeats; cnt++) { + iov[iovcnt].iov_base = (char *) samples; + iov[iovcnt++].iov_len = sizeof(samples); + if (cnt == repeats) { + /* Insert a bit of silence so that multiple beeps are distinct and + * not compressed into a single tone. + */ + iov[iovcnt].iov_base = (char *) silence; + iov[iovcnt++].iov_len = sizeof(silence); + } + if ((iovcnt >= IOV_MAX) || (cnt == repeats)) { + written = writev(audioFD, iov, iovcnt); + + if ((written < ((int)(sizeof(samples) * iovcnt)))) { + /* audio buffer was full! */ + + int naptime; + + if (written == -1) { + if (errno != EAGAIN) { + xf86Msg(X_ERROR, + "Bell: writev failed on audio device \"%s\": %s\n", + AUDIO_DEVICE, strerror(errno)); + close(audioFD); + return -1; + } + i = iovcnt; + } else { + i = ((sizeof(samples) * iovcnt) - written) + / sizeof(samples); + } + cnt -= i; + + /* sleep a little to allow audio buffer to drain */ + naptime = BELL_MS * i; + poll(NULL, 0, naptime); + + i = ((sizeof(samples) * iovcnt) - written) % sizeof(samples); + iovcnt = 0; + if ((written != -1) && (i > 0)) { + iov[iovcnt].iov_base = ((char *) samples) + i; + iov[iovcnt++].iov_len = sizeof(samples) - i; + } + } else { + iovcnt = 0; + } + } + } + + close(audioFD); + return 0; +} diff --git a/hw/xfree86/os-support/xf86_OSproc.h b/hw/xfree86/os-support/xf86_OSproc.h index c987d755a..0311b8193 100644 --- a/hw/xfree86/os-support/xf86_OSproc.h +++ b/hw/xfree86/os-support/xf86_OSproc.h @@ -174,6 +174,7 @@ extern int xf86GetSerialModemState(int fd); extern int xf86SerialModemSetBits(int fd, int bits); extern int xf86SerialModemClearBits(int fd, int bits); extern int xf86LoadKernelModule(const char *pathname); +extern void xf86RingBell(int volume, int pitch, int duration); /* AGP GART interface */ diff --git a/hw/xnest/Keyboard.c b/hw/xnest/Keyboard.c index 26a5ed3fb..0dacae70b 100644 --- a/hw/xnest/Keyboard.c +++ b/hw/xnest/Keyboard.c @@ -94,6 +94,12 @@ xnestBell(int volume, DeviceIntPtr pDev, pointer ctrl, int cls) } void +DDXRingBell(int volume, int pitch, int duration) +{ + XBell(xnestDisplay, volume); +} + +void xnestChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl) { #if 0 diff --git a/include/input.h b/include/input.h index 3fe694474..f2fe6d137 100644 --- a/include/input.h +++ b/include/input.h @@ -441,7 +441,9 @@ extern DeviceIntPtr LookupDeviceIntRec( extern int NewInputDeviceRequest( InputOption *options); -extern DeviceIntPtr LookupDeviceIntRec( - CARD8 deviceid); +extern void DDXRingBell( + int volume, + int pitch, + int duration); #endif /* INPUT_H */ |