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>
33 #include <sys/audio.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"
52 xf86OSRingBell(int loudness
, int pitch
, int duration
)
54 static short samples
[BELL_SAMPLES
];
55 static short silence
[BELL_SAMPLES
]; /* "The Sound of Silence" */
62 audio_info_t audioInfo
;
63 struct iovec iov
[IOV_MAX
];
65 double ampl
, cyclen
, phase
;
68 if ((loudness
<= 0) || (pitch
<= 0) || (duration
<= 0)) {
73 bzero(silence
, sizeof(silence
));
75 audioFD
= open(AUDIO_DEVICE
, O_WRONLY
| O_NONBLOCK
);
77 xf86Msg(X_ERROR
, "Bell: cannot open audio device \"%s\": %s\n",
78 AUDIO_DEVICE
, strerror(errno
));
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
) {
95 cyclen
= (double) freq
/ (double) BELL_RATE
;
98 for (i
= 0; i
< BELL_SAMPLES
; i
++) {
99 samples
[i
] = (short) (ampl
* sin(2.0 * M_PI
* phase
));
106 repeats
= (duration
+ (BELL_MS
/ 2)) / BELL_MS
;
107 repeats
= max(repeats
, BELL_MIN
);
109 loudness
= max(0, loudness
);
110 loudness
= min(loudness
, 100);
113 ErrorF("BELL : freq %d volume %d duration %d repeats %d\n",
114 freq
, loudness
, duration
, repeats
);
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){
126 "Bell: AUDIO_SETINFO failed on audio device \"%s\": %s\n",
127 AUDIO_DEVICE
, strerror(errno
));
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! */
153 if (errno
!= EAGAIN
) {
155 "Bell: writev failed on audio device \"%s\": %s\n",
156 AUDIO_DEVICE
, strerror(errno
));
162 i
= ((sizeof(samples
) * iovcnt
) - written
)
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
);
173 if ((written
!= -1) && (i
> 0)) {
174 iov
[iovcnt
].iov_base
= ((char *) samples
) + i
;
175 iov
[iovcnt
++].iov_len
= sizeof(samples
) - i
;