Mercurial > pidgin
annotate src/sound.c @ 134:00c1ee609648
[gaim-migrate @ 144]
Heh, whoops. Silly bug. If you only have one plugin loaded, and it's
configurable, and you unload it, the 'configure' button wouldn't deactivate,
and so you could still click on it, and it would segfault.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Wed, 19 Apr 2000 02:23:30 +0000 |
parents | e277d5f0c1dd |
children | 5d62a5d50c89 |
rev | line source |
---|---|
1 | 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> | |
63 | 30 #include <unistd.h> |
31 #include <sys/types.h> | |
32 #include <sys/stat.h> | |
1 | 33 |
34 #ifdef ESD_SOUND | |
35 #include <esd.h> | |
36 #endif | |
37 | |
38 #ifdef NAS_SOUND | |
39 #include <audio/audiolib.h> | |
40 #endif | |
41 | |
42 #include "gaim.h" | |
43 #include "sounds/BuddyArrive.h" | |
44 #include "sounds/BuddyLeave.h" | |
45 #include "sounds/Send.h" | |
46 #include "sounds/Receive.h" | |
47 | |
48 | |
49 static void play_audio(char *data, int size) | |
50 { | |
51 int fd; | |
52 | |
53 fd = open("/dev/audio", O_WRONLY | O_EXCL); | |
54 if (fd < 0) | |
55 return; | |
56 write(fd, data, size); | |
57 close(fd); | |
58 } | |
59 | |
60 static int can_play_audio() | |
61 { | |
79 | 62 struct stat stat_buf; |
63 | 63 uid_t user = getuid(); |
64 gid_t group = getgid(); | |
79 | 65 if (stat("/dev/audio", &stat_buf)) |
63 | 66 return 0; |
79 | 67 if (user == stat_buf.st_uid && stat_buf.st_mode & S_IWUSR) |
63 | 68 return 1; |
79 | 69 if (group == stat_buf.st_gid && stat_buf.st_mode & S_IWGRP) |
63 | 70 return 1; |
79 | 71 if (stat_buf.st_mode & S_IWOTH) |
63 | 72 return 1; |
73 return 0; | |
1 | 74 } |
75 | |
76 | |
77 #ifdef ESD_SOUND | |
78 /* | |
79 ** This routine converts from ulaw to 16 bit linear. | |
80 ** | |
81 ** Craig Reese: IDA/Supercomputing Research Center | |
82 ** 29 September 1989 | |
83 ** | |
84 ** References: | |
85 ** 1) CCITT Recommendation G.711 (very difficult to follow) | |
86 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards | |
87 ** for Analog-to_Digital Conversion Techniques," | |
88 ** 17 February 1987 | |
89 ** | |
90 ** Input: 8 bit ulaw sample | |
91 ** Output: signed 16 bit linear sample | |
92 ** Z-note -- this is from libaudiofile. Thanks guys! | |
93 */ | |
94 | |
95 int _af_ulaw2linear (unsigned char ulawbyte) | |
96 { | |
97 static int exp_lut[8] = {0,132,396,924,1980,4092,8316,16764}; | |
98 int sign, exponent, mantissa, sample; | |
99 | |
100 ulawbyte = ~ulawbyte; | |
101 sign = (ulawbyte & 0x80); | |
102 exponent = (ulawbyte >> 4) & 0x07; | |
103 mantissa = ulawbyte & 0x0F; | |
104 sample = exp_lut[exponent] + (mantissa << (exponent + 3)); | |
105 if (sign != 0) sample = -sample; | |
106 | |
107 return(sample); | |
108 } | |
109 | |
110 | |
111 | |
112 static int play_esd(unsigned char *data, int size) | |
113 { | |
114 int fd, i; | |
115 esd_format_t format = ESD_BITS16 | ESD_STREAM | ESD_PLAY | ESD_MONO; | |
79 | 116 guint16 *lineardata; |
1 | 117 |
118 | |
119 fd = esd_play_stream(format, 8012, NULL, "gaim"); | |
120 | |
79 | 121 if (fd < 0) { |
1 | 122 return 0; |
79 | 123 } |
124 | |
125 lineardata = g_malloc(size * 2); | |
1 | 126 |
127 for (i=0; i<size; i++) | |
128 lineardata[i] = _af_ulaw2linear(data[i]); | |
129 | |
130 write(fd, lineardata, size * 2); | |
131 | |
132 close(fd); | |
133 g_free(lineardata); | |
134 | |
135 return 1; | |
136 | |
137 } | |
138 | |
139 static int can_play_esd() | |
140 { | |
141 return 1; | |
142 } | |
143 | |
144 #endif | |
145 | |
146 #ifdef NAS_SOUND | |
147 | |
148 char nas_server[] = "localhost"; | |
149 AuServer *nas_serv = NULL; | |
150 | |
151 static AuBool | |
152 NasEventHandler(AuServer *aud, AuEvent *ev, AuEventHandlerRec *handler) | |
153 { | |
154 AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev; | |
155 | |
156 if (ev->type == AuEventTypeElementNotify) { | |
157 switch (event->kind) { | |
158 case AuElementNotifyKindState: | |
159 switch (event->cur_state) { | |
160 case AuStateStop: | |
161 _exit(0); | |
162 } | |
163 break; | |
164 } | |
165 } | |
166 return AuTrue; | |
167 } | |
168 | |
169 | |
170 static int play_nas(unsigned char *data, int size) | |
171 { | |
172 AuDeviceID device = AuNone; | |
173 AuFlowID flow; | |
174 AuElement elements[3]; | |
175 int i, n, w; | |
176 | |
177 /* look for an output device */ | |
178 for (i = 0; i < AuServerNumDevices(nas_serv); i++) { | |
179 if ((AuDeviceKind(AuServerDevice(nas_serv, i)) == | |
180 AuComponentKindPhysicalOutput) && | |
181 AuDeviceNumTracks(AuServerDevice(nas_serv, i)) == 1) { | |
182 device = AuDeviceIdentifier(AuServerDevice(nas_serv, i)); | |
183 break; | |
184 } | |
185 } | |
186 | |
187 if (device == AuNone) | |
188 return 0; | |
189 | |
190 if (!(flow = AuCreateFlow(nas_serv, NULL))) | |
191 return 0; | |
192 | |
193 | |
194 AuMakeElementImportClient(&elements[0], 8012, AuFormatULAW8, | |
195 1, AuTrue, size, size/2, 0, NULL); | |
196 AuMakeElementExportDevice(&elements[1], 0, device, 8012, | |
197 AuUnlimitedSamples, 0, NULL); | |
198 AuSetElements(nas_serv, flow, AuTrue, 2, elements, NULL); | |
199 | |
200 AuStartFlow(nas_serv, flow, NULL); | |
201 | |
202 AuWriteElement(nas_serv, flow, 0, size, data, AuTrue, NULL); | |
203 | |
204 AuRegisterEventHandler(nas_serv, AuEventHandlerIDMask, 0, flow, | |
205 NasEventHandler, NULL); | |
206 | |
207 while(1) { | |
208 AuHandleEvents(nas_serv); | |
209 } | |
210 | |
211 return 1; | |
212 } | |
213 | |
214 static int can_play_nas() | |
215 { | |
216 if ((nas_serv = AuOpenServer(NULL, 0, NULL, 0, NULL, NULL))) | |
217 return 1; | |
218 return 0; | |
219 } | |
220 | |
221 #endif | |
222 | |
133
e277d5f0c1dd
[gaim-migrate @ 143]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
108
diff
changeset
|
223 void play(unsigned char *data, int size) |
1 | 224 { |
225 int pid; | |
226 | |
227 #ifdef _WIN32 | |
228 return; | |
229 #endif | |
230 | |
231 pid = fork(); | |
232 | |
233 if (pid < 0) | |
234 return; | |
235 else if (pid == 0) { | |
236 #ifdef ESD_SOUND | |
237 /* ESD is our player of choice. Are we OK to | |
238 * go there? */ | |
239 if (can_play_esd()) { | |
240 if (play_esd(data, size)) | |
241 _exit(0); | |
242 } | |
243 #endif | |
244 | |
245 #ifdef NAS_SOUND | |
246 /* NAS is our second choice setup. */ | |
247 if (can_play_nas()) { | |
248 if (play_nas(data, size)) | |
249 _exit(0); | |
250 } | |
251 #endif | |
252 | |
253 /* Lastly, we can try just plain old /dev/audio */ | |
254 if (can_play_audio()) { | |
255 play_audio(data, size); | |
256 _exit(0); | |
257 } | |
258 } else { | |
259 gtk_timeout_add(100, (GtkFunction)clean_pid, NULL); | |
260 } | |
261 } | |
262 | |
133
e277d5f0c1dd
[gaim-migrate @ 143]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
108
diff
changeset
|
263 extern int logins_not_muted; |
108
9a544c677ab7
[gaim-migrate @ 118]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
82
diff
changeset
|
264 #ifndef USE_APPLET |
1 | 265 |
266 void play_sound(int sound) | |
267 { | |
268 | |
269 switch(sound) { | |
270 case BUDDY_ARRIVE: | |
133
e277d5f0c1dd
[gaim-migrate @ 143]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
108
diff
changeset
|
271 if ((sound_options & OPT_SOUND_LOGIN) && logins_not_muted) |
1 | 272 play(BuddyArrive, sizeof(BuddyArrive)); |
273 break; | |
274 case BUDDY_LEAVE: | |
275 if (sound_options & OPT_SOUND_LOGOUT) | |
276 play(BuddyLeave, sizeof(BuddyLeave)); | |
277 break; | |
278 case SEND: | |
279 if (sound_options & OPT_SOUND_SEND) | |
280 play(Send, sizeof(Send)); | |
281 break; | |
282 case FIRST_RECEIVE: | |
283 if (sound_options & OPT_SOUND_FIRST_RCV) | |
284 play(Receive, sizeof(Receive)); | |
285 break; | |
286 case RECEIVE: | |
287 if (sound_options & OPT_SOUND_RECV) | |
288 play(Receive, sizeof(Receive)); | |
289 break; | |
290 case AWAY: | |
291 if (sound_options & OPT_SOUND_WHEN_AWAY) | |
292 play(Receive, sizeof(Receive)); | |
293 break; | |
294 } | |
64 | 295 } |
1 | 296 |
64 | 297 #else /* USE_APPLET */ |
298 | |
82 | 299 #include <gnome.h> |
64 | 300 void play_sound(int sound) |
301 { | |
302 | |
303 switch(sound) { | |
304 case BUDDY_ARRIVE: | |
133
e277d5f0c1dd
[gaim-migrate @ 143]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
108
diff
changeset
|
305 if ((sound_options & OPT_SOUND_LOGIN) && logins_not_muted) |
64 | 306 gnome_triggers_do("", "program", "gaim_applet", "login", NULL); |
307 break; | |
308 case BUDDY_LEAVE: | |
309 if (sound_options & OPT_SOUND_LOGOUT) | |
310 gnome_triggers_do("", "program", "gaim_applet", "leave", NULL); | |
311 break; | |
312 case SEND: | |
313 if (sound_options & OPT_SOUND_SEND) | |
314 gnome_triggers_do("", "program", "gaim_applet", "send", NULL); | |
315 break; | |
316 case FIRST_RECEIVE: | |
317 if (sound_options & OPT_SOUND_FIRST_RCV) | |
318 gnome_triggers_do("", "program", "gaim_applet", "recv", NULL); | |
319 break; | |
320 case RECEIVE: | |
321 if (sound_options & OPT_SOUND_RECV) | |
322 gnome_triggers_do("", "program", "gaim_applet", "recv", NULL); | |
323 break; | |
324 case AWAY: | |
325 if (sound_options & OPT_SOUND_WHEN_AWAY) | |
326 gnome_triggers_do("", "program", "gaim_applet", "recv", NULL); | |
327 break; | |
328 } | |
1 | 329 } |
64 | 330 |
331 #endif /* USE_APPLET */ |