comparison src/sound.c @ 1:2846a03bda67

[gaim-migrate @ 10] The other missing files :) committer: Tailor Script <tailor@pidgin.im>
author Rob Flynn <gaim@robflynn.com>
date Thu, 23 Mar 2000 03:13:54 +0000
parents
children 12894b62d206
comparison
equal deleted inserted replaced
0:a5ace2e037bc 1:2846a03bda67
1 /*
2 * gaim
3 *
4 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <sys/time.h>
25 #include <unistd.h>
26 #include <gtk/gtk.h>
27 #include <fcntl.h>
28 #include <sys/wait.h>
29 #include <sys/signal.h>
30
31 #ifdef ESD_SOUND
32 #include <esd.h>
33 #endif
34
35 #ifdef NAS_SOUND
36 #include <audio/audiolib.h>
37 #endif
38
39 #include "gaim.h"
40 #include "sounds/BuddyArrive.h"
41 #include "sounds/BuddyLeave.h"
42 #include "sounds/Send.h"
43 #include "sounds/Receive.h"
44
45
46 static void play_audio(char *data, int size)
47 {
48 int fd;
49
50 fd = open("/dev/audio", O_WRONLY | O_EXCL);
51 if (fd < 0)
52 return;
53 write(fd, data, size);
54 close(fd);
55 }
56
57 static int can_play_audio()
58 {
59 /* FIXME check for write access and such. */
60 return 1;
61
62 }
63
64
65 #ifdef ESD_SOUND
66 /*
67 ** This routine converts from ulaw to 16 bit linear.
68 **
69 ** Craig Reese: IDA/Supercomputing Research Center
70 ** 29 September 1989
71 **
72 ** References:
73 ** 1) CCITT Recommendation G.711 (very difficult to follow)
74 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
75 ** for Analog-to_Digital Conversion Techniques,"
76 ** 17 February 1987
77 **
78 ** Input: 8 bit ulaw sample
79 ** Output: signed 16 bit linear sample
80 ** Z-note -- this is from libaudiofile. Thanks guys!
81 */
82
83 int _af_ulaw2linear (unsigned char ulawbyte)
84 {
85 static int exp_lut[8] = {0,132,396,924,1980,4092,8316,16764};
86 int sign, exponent, mantissa, sample;
87
88 ulawbyte = ~ulawbyte;
89 sign = (ulawbyte & 0x80);
90 exponent = (ulawbyte >> 4) & 0x07;
91 mantissa = ulawbyte & 0x0F;
92 sample = exp_lut[exponent] + (mantissa << (exponent + 3));
93 if (sign != 0) sample = -sample;
94
95 return(sample);
96 }
97
98
99
100 static int play_esd(unsigned char *data, int size)
101 {
102 int fd, i;
103 esd_format_t format = ESD_BITS16 | ESD_STREAM | ESD_PLAY | ESD_MONO;
104 guint16 *lineardata = g_malloc(size * 2);
105
106
107 fd = esd_play_stream(format, 8012, NULL, "gaim");
108
109 if (fd < 0)
110 return 0;
111
112 for (i=0; i<size; i++)
113 lineardata[i] = _af_ulaw2linear(data[i]);
114
115 write(fd, lineardata, size * 2);
116
117 close(fd);
118 g_free(lineardata);
119
120 return 1;
121
122 }
123
124 static int can_play_esd()
125 {
126 return 1;
127 }
128
129 #endif
130
131 #ifdef NAS_SOUND
132
133 char nas_server[] = "localhost";
134 AuServer *nas_serv = NULL;
135
136 static AuBool
137 NasEventHandler(AuServer *aud, AuEvent *ev, AuEventHandlerRec *handler)
138 {
139 AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;
140
141 if (ev->type == AuEventTypeElementNotify) {
142 switch (event->kind) {
143 case AuElementNotifyKindState:
144 switch (event->cur_state) {
145 case AuStateStop:
146 _exit(0);
147 }
148 break;
149 }
150 }
151 return AuTrue;
152 }
153
154
155 static int play_nas(unsigned char *data, int size)
156 {
157 AuDeviceID device = AuNone;
158 AuFlowID flow;
159 AuElement elements[3];
160 int i, n, w;
161
162 /* look for an output device */
163 for (i = 0; i < AuServerNumDevices(nas_serv); i++) {
164 if ((AuDeviceKind(AuServerDevice(nas_serv, i)) ==
165 AuComponentKindPhysicalOutput) &&
166 AuDeviceNumTracks(AuServerDevice(nas_serv, i)) == 1) {
167 device = AuDeviceIdentifier(AuServerDevice(nas_serv, i));
168 break;
169 }
170 }
171
172 if (device == AuNone)
173 return 0;
174
175 if (!(flow = AuCreateFlow(nas_serv, NULL)))
176 return 0;
177
178
179 AuMakeElementImportClient(&elements[0], 8012, AuFormatULAW8,
180 1, AuTrue, size, size/2, 0, NULL);
181 AuMakeElementExportDevice(&elements[1], 0, device, 8012,
182 AuUnlimitedSamples, 0, NULL);
183 AuSetElements(nas_serv, flow, AuTrue, 2, elements, NULL);
184
185 AuStartFlow(nas_serv, flow, NULL);
186
187 AuWriteElement(nas_serv, flow, 0, size, data, AuTrue, NULL);
188
189 AuRegisterEventHandler(nas_serv, AuEventHandlerIDMask, 0, flow,
190 NasEventHandler, NULL);
191
192 while(1) {
193 AuHandleEvents(nas_serv);
194 }
195
196 return 1;
197 }
198
199 static int can_play_nas()
200 {
201 if ((nas_serv = AuOpenServer(NULL, 0, NULL, 0, NULL, NULL)))
202 return 1;
203 return 0;
204 }
205
206 #endif
207
208 static void play(unsigned char *data, int size)
209 {
210 int pid;
211
212 #ifdef _WIN32
213 return;
214 #endif
215
216 pid = fork();
217
218 if (pid < 0)
219 return;
220 else if (pid == 0) {
221 #ifdef ESD_SOUND
222 /* ESD is our player of choice. Are we OK to
223 * go there? */
224 if (can_play_esd()) {
225 if (play_esd(data, size))
226 _exit(0);
227 }
228 #endif
229
230 #ifdef NAS_SOUND
231 /* NAS is our second choice setup. */
232 if (can_play_nas()) {
233 if (play_nas(data, size))
234 _exit(0);
235 }
236 #endif
237
238 /* Lastly, we can try just plain old /dev/audio */
239 if (can_play_audio()) {
240 play_audio(data, size);
241 _exit(0);
242 }
243 } else {
244 gtk_timeout_add(100, (GtkFunction)clean_pid, NULL);
245 }
246 }
247
248
249
250 void play_sound(int sound)
251 {
252
253 switch(sound) {
254 case BUDDY_ARRIVE:
255 if (sound_options & OPT_SOUND_LOGIN)
256 play(BuddyArrive, sizeof(BuddyArrive));
257 break;
258 case BUDDY_LEAVE:
259 if (sound_options & OPT_SOUND_LOGOUT)
260 play(BuddyLeave, sizeof(BuddyLeave));
261 break;
262 case SEND:
263 if (sound_options & OPT_SOUND_SEND)
264 play(Send, sizeof(Send));
265 break;
266 case FIRST_RECEIVE:
267 if (sound_options & OPT_SOUND_FIRST_RCV)
268 play(Receive, sizeof(Receive));
269 break;
270 case RECEIVE:
271 if (sound_options & OPT_SOUND_RECV)
272 play(Receive, sizeof(Receive));
273 break;
274 case AWAY:
275 if (sound_options & OPT_SOUND_WHEN_AWAY)
276 play(Receive, sizeof(Receive));
277 break;
278 }
279
280
281 }