First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / os-support / solaris / sun_bell.c
blob29ecd730008817ca28c3d9a5f9f7a533bebf03bf
1 /* Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved.
3 * Permission is hereby granted, free of charge, to any person obtaining a
4 * copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, and/or sell copies of the Software, and to permit persons
8 * to whom the Software is furnished to do so, provided that the above
9 * copyright notice(s) and this permission notice appear in all copies of
10 * the Software and that both the above copyright notice(s) and this
11 * permission notice appear in supporting documentation.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
16 * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
17 * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
18 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
19 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Except as contained in this notice, the name of a copyright holder
24 * shall not be used in advertising or otherwise to promote the sale, use
25 * or other dealings in this Software without prior written authorization
26 * of the copyright holder.
29 #ifdef HAVE_XORG_CONFIG_H
30 #include <xorg-config.h>
31 #endif
33 #include <sys/audio.h>
34 #include <sys/uio.h>
35 #include <limits.h>
36 #include <math.h>
37 #include <poll.h>
39 #include "xf86.h"
40 #include "xf86Priv.h"
41 #include "xf86_OSlib.h"
43 #define BELL_RATE 48000 /* Samples per second */
44 #define BELL_HZ 50 /* Fraction of a second i.e. 1/x */
45 #define BELL_MS (1000/BELL_HZ) /* MS */
46 #define BELL_SAMPLES (BELL_RATE / BELL_HZ)
47 #define BELL_MIN 3 /* Min # of repeats */
49 #define AUDIO_DEVICE "/dev/audio"
51 _X_EXPORT void
52 xf86OSRingBell(int loudness, int pitch, int duration)
54 static short samples[BELL_SAMPLES];
55 static short silence[BELL_SAMPLES]; /* "The Sound of Silence" */
56 static int lastFreq;
57 int cnt;
58 int i;
59 int written;
60 int repeats;
61 int freq;
62 audio_info_t audioInfo;
63 struct iovec iov[IOV_MAX];
64 int iovcnt;
65 double ampl, cyclen, phase;
66 int audioFD;
68 if ((loudness <= 0) || (pitch <= 0) || (duration <= 0)) {
69 return;
72 lastFreq = 0;
73 bzero(silence, sizeof(silence));
75 audioFD = open(AUDIO_DEVICE, O_WRONLY | O_NONBLOCK);
76 if (audioFD == -1) {
77 xf86Msg(X_ERROR, "Bell: cannot open audio device \"%s\": %s\n",
78 AUDIO_DEVICE, strerror(errno));
79 return;
82 freq = pitch;
83 freq = min(freq, (BELL_RATE / 2) - 1);
84 freq = max(freq, 2 * BELL_HZ);
87 * Ensure full waves per buffer
89 freq -= freq % BELL_HZ;
91 if (freq != lastFreq) {
92 lastFreq = freq;
93 ampl = 16384.0;
95 cyclen = (double) freq / (double) BELL_RATE;
96 phase = 0.0;
98 for (i = 0; i < BELL_SAMPLES; i++) {
99 samples[i] = (short) (ampl * sin(2.0 * M_PI * phase));
100 phase += cyclen;
101 if (phase >= 1.0)
102 phase -= 1.0;
106 repeats = (duration + (BELL_MS / 2)) / BELL_MS;
107 repeats = max(repeats, BELL_MIN);
109 loudness = max(0, loudness);
110 loudness = min(loudness, 100);
112 #ifdef DEBUG
113 ErrorF("BELL : freq %d volume %d duration %d repeats %d\n",
114 freq, loudness, duration, repeats);
115 #endif
117 AUDIO_INITINFO(&audioInfo);
118 audioInfo.play.encoding = AUDIO_ENCODING_LINEAR;
119 audioInfo.play.sample_rate = BELL_RATE;
120 audioInfo.play.channels = 2;
121 audioInfo.play.precision = 16;
122 audioInfo.play.gain = min(AUDIO_MAX_GAIN, AUDIO_MAX_GAIN * loudness / 100);
124 if (ioctl(audioFD, AUDIO_SETINFO, &audioInfo) < 0){
125 xf86Msg(X_ERROR,
126 "Bell: AUDIO_SETINFO failed on audio device \"%s\": %s\n",
127 AUDIO_DEVICE, strerror(errno));
128 close(audioFD);
129 return;
132 iovcnt = 0;
134 for (cnt = 0; cnt <= repeats; cnt++) {
135 iov[iovcnt].iov_base = (char *) samples;
136 iov[iovcnt++].iov_len = sizeof(samples);
137 if (cnt == repeats) {
138 /* Insert a bit of silence so that multiple beeps are distinct and
139 * not compressed into a single tone.
141 iov[iovcnt].iov_base = (char *) silence;
142 iov[iovcnt++].iov_len = sizeof(silence);
144 if ((iovcnt >= IOV_MAX) || (cnt == repeats)) {
145 written = writev(audioFD, iov, iovcnt);
147 if ((written < ((int)(sizeof(samples) * iovcnt)))) {
148 /* audio buffer was full! */
150 int naptime;
152 if (written == -1) {
153 if (errno != EAGAIN) {
154 xf86Msg(X_ERROR,
155 "Bell: writev failed on audio device \"%s\": %s\n",
156 AUDIO_DEVICE, strerror(errno));
157 close(audioFD);
158 return;
160 i = iovcnt;
161 } else {
162 i = ((sizeof(samples) * iovcnt) - written)
163 / sizeof(samples);
165 cnt -= i;
167 /* sleep a little to allow audio buffer to drain */
168 naptime = BELL_MS * i;
169 poll(NULL, 0, naptime);
171 i = ((sizeof(samples) * iovcnt) - written) % sizeof(samples);
172 iovcnt = 0;
173 if ((written != -1) && (i > 0)) {
174 iov[iovcnt].iov_base = ((char *) samples) + i;
175 iov[iovcnt++].iov_len = sizeof(samples) - i;
177 } else {
178 iovcnt = 0;
183 close(audioFD);
184 return;