1 /* Copyright (c) 2004-2005, Oracle and/or its affiliates. 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 "Software"),
5 * to deal in the Software without restriction, including without limitation
6 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 * and/or sell copies of the Software, and to permit persons to whom the
8 * Software is furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice (including the next
11 * paragraph) shall be included in all copies or substantial portions of the
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
23 #ifdef HAVE_XORG_CONFIG_H
24 #include <xorg-config.h>
27 #include <sys/audio.h>
35 #include "xf86_OSlib.h"
37 #define BELL_RATE 48000 /* Samples per second */
38 #define BELL_HZ 50 /* Fraction of a second i.e. 1/x */
39 #define BELL_MS (1000/BELL_HZ) /* MS */
40 #define BELL_SAMPLES (BELL_RATE / BELL_HZ)
41 #define BELL_MIN 3 /* Min # of repeats */
43 #define AUDIO_DEVICE "/dev/audio"
46 xf86OSRingBell(int loudness
, int pitch
, int duration
)
48 static short samples
[BELL_SAMPLES
];
49 static short silence
[BELL_SAMPLES
]; /* "The Sound of Silence" */
56 audio_info_t audioInfo
;
57 struct iovec iov
[IOV_MAX
];
59 double ampl
, cyclen
, phase
;
62 if ((loudness
<= 0) || (pitch
<= 0) || (duration
<= 0)) {
67 memset(silence
, 0, sizeof(silence
));
69 audioFD
= open(AUDIO_DEVICE
, O_WRONLY
| O_NONBLOCK
);
71 xf86Msg(X_ERROR
, "Bell: cannot open audio device \"%s\": %s\n",
72 AUDIO_DEVICE
, strerror(errno
));
77 freq
= min(freq
, (BELL_RATE
/ 2) - 1);
78 freq
= max(freq
, 2 * BELL_HZ
);
81 * Ensure full waves per buffer
83 freq
-= freq
% BELL_HZ
;
85 if (freq
!= lastFreq
) {
89 cyclen
= (double) freq
/ (double) BELL_RATE
;
92 for (i
= 0; i
< BELL_SAMPLES
; i
++) {
93 samples
[i
] = (short) (ampl
* sin(2.0 * M_PI
* phase
));
100 repeats
= (duration
+ (BELL_MS
/ 2)) / BELL_MS
;
101 repeats
= max(repeats
, BELL_MIN
);
103 loudness
= max(0, loudness
);
104 loudness
= min(loudness
, 100);
107 ErrorF("BELL : freq %d volume %d duration %d repeats %d\n",
108 freq
, loudness
, duration
, repeats
);
111 AUDIO_INITINFO(&audioInfo
);
112 audioInfo
.play
.encoding
= AUDIO_ENCODING_LINEAR
;
113 audioInfo
.play
.sample_rate
= BELL_RATE
;
114 audioInfo
.play
.channels
= 2;
115 audioInfo
.play
.precision
= 16;
116 audioInfo
.play
.gain
= min(AUDIO_MAX_GAIN
, AUDIO_MAX_GAIN
* loudness
/ 100);
118 if (ioctl(audioFD
, AUDIO_SETINFO
, &audioInfo
) < 0) {
120 "Bell: AUDIO_SETINFO failed on audio device \"%s\": %s\n",
121 AUDIO_DEVICE
, strerror(errno
));
128 for (cnt
= 0; cnt
<= repeats
; cnt
++) {
129 if (cnt
== repeats
) {
130 /* Insert a bit of silence so that multiple beeps are distinct and
131 * not compressed into a single tone.
133 iov
[iovcnt
].iov_base
= (char *) silence
;
134 iov
[iovcnt
++].iov_len
= sizeof(silence
);
137 iov
[iovcnt
].iov_base
= (char *) samples
;
138 iov
[iovcnt
++].iov_len
= sizeof(samples
);
140 if ((iovcnt
>= IOV_MAX
) || (cnt
== repeats
)) {
141 written
= writev(audioFD
, iov
, iovcnt
);
143 if ((written
< ((int) (sizeof(samples
) * iovcnt
)))) {
144 /* audio buffer was full! */
149 if (errno
!= EAGAIN
) {
151 "Bell: writev failed on audio device \"%s\": %s\n",
152 AUDIO_DEVICE
, strerror(errno
));
159 i
= ((sizeof(samples
) * iovcnt
) - written
)
164 /* sleep a little to allow audio buffer to drain */
165 naptime
= BELL_MS
* i
;
166 poll(NULL
, 0, naptime
);
168 i
= ((sizeof(samples
) * iovcnt
) - written
) % sizeof(samples
);
170 if ((written
!= -1) && (i
> 0)) {
171 iov
[iovcnt
].iov_base
= ((char *) samples
) + i
;
172 iov
[iovcnt
++].iov_len
= sizeof(samples
) - i
;