Mercurial > hg > xemacs-beta
annotate src/sunplay.c @ 5518:3cc7470ea71c
gnuclient: if TMPDIR was set and connect failed, try again with /tmp
2011-06-03 Aidan Kehoe <kehoea@parhasard.net>
* gnuslib.c (connect_to_unix_server):
Retry with /tmp as a directory in which to search for Unix sockets
if an attempt to connect with some other directory failed (which
may be because gnuclient and gnuserv don't share an environment
value for TMPDIR, or because gnuserv was compiled with USE_TMPDIR
turned off).
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Fri, 03 Jun 2011 18:40:57 +0100 |
parents | 6f2158fa75ed |
children |
rev | line source |
---|---|
428 | 1 /* play.c - play a sound file on the speaker |
2 ** | |
3 ** Copyright (C) 1989 by Jef Poskanzer. | |
4 ** | |
5 ** Modified 24-May-91 by Jamie Zawinski (for Lucid Emacs). | |
6 ** Modified 17-Dec-92 by Jamie Zawinski (largely rewritten for SunOS 4.1.3). | |
7 ** | |
8 ** Permission to use, copy, modify, and distribute this software and its | |
9 ** documentation for any purpose and without fee is hereby granted, provided | |
10 ** that the above copyright notice appear in all copies and that both that | |
11 ** copyright notice and this permission notice appear in supporting | |
12 ** documentation. This software is provided "as is" without express or | |
13 ** implied warranty. | |
14 */ | |
15 | |
16 /* Synched up with: Not in FSF. */ | |
17 | |
563 | 18 /* This file Mule-ized by Ben Wing, 5-15-01. */ |
428 | 19 |
563 | 20 #include <config.h> |
21 #include "lisp.h" | |
22 #include "sound.h" | |
428 | 23 |
563 | 24 #include "sysdep.h" |
25 #include "sysfile.h" | |
26 #include "syssignal.h" | |
428 | 27 |
28 #include <multimedia/libaudio.h> | |
29 #include <multimedia/audio_device.h> | |
30 | |
31 static SIGTYPE (*sighup_handler) (int sig); | |
32 static SIGTYPE (*sigint_handler) (int sig); | |
33 static SIGTYPE sighandler (int sig); | |
34 | |
35 static int audio_fd; | |
36 | |
37 #define audio_open() open ("/dev/audio", (O_WRONLY | O_NONBLOCK), 0) | |
38 | |
442 | 39 static int initialized_device_p; |
428 | 40 static int reset_volume_p, reset_device_p; |
41 static double old_volume; | |
42 static Audio_hdr dev_hdr; | |
43 | |
44 static int | |
2367 | 45 init_device (int volume, Binbyte *data, int fd, |
428 | 46 unsigned int *header_length) |
47 { | |
48 Audio_hdr file_hdr; | |
49 | |
50 reset_volume_p = 0; | |
51 reset_device_p = 0; | |
52 | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
53 assert (!(data && fd)); /* one or the other */ |
428 | 54 |
55 if (AUDIO_SUCCESS != audio_get_play_config (audio_fd, &dev_hdr)) | |
56 { | |
563 | 57 sound_perror ("Not a valid audio device"); |
428 | 58 return 1; |
59 } | |
60 | |
61 if (AUDIO_SUCCESS != (data | |
62 ? audio_decode_filehdr (data, &file_hdr, header_length) | |
63 : audio_read_filehdr (fd, &file_hdr, 0, 0))) | |
64 { | |
65 if (data) | |
563 | 66 sound_perror ("invalid audio data"); |
428 | 67 else |
563 | 68 sound_perror ("invalid audio file"); |
428 | 69 return 1; |
70 } | |
71 | |
72 audio_flush_play (audio_fd); | |
73 | |
442 | 74 if (!initialized_device_p || (0 != audio_cmp_hdr (&dev_hdr, &file_hdr))) |
428 | 75 { |
76 Audio_hdr new_hdr; | |
77 new_hdr = file_hdr; | |
78 reset_device_p = 1; | |
442 | 79 initialized_device_p = 1; |
428 | 80 if (AUDIO_SUCCESS != audio_set_play_config (audio_fd, &new_hdr)) |
81 { | |
563 | 82 Extbyte buf1 [100], buf2 [100], buf3 [250]; |
428 | 83 audio_enc_to_str (&file_hdr, buf1); |
84 audio_enc_to_str (&new_hdr, buf2); | |
85 sprintf (buf3, "wanted %s, got %s", buf1, buf2); | |
563 | 86 sound_warn (buf3); |
428 | 87 return 1; |
88 } | |
89 } | |
90 | |
91 if (volume < 0 || volume > 100) | |
92 { | |
563 | 93 Extbyte buf [255]; |
428 | 94 sprintf (buf, "volume must be between 0 and 100 (not %d)", volume); |
563 | 95 sound_warn (buf); |
428 | 96 return 1; |
97 } | |
98 { | |
99 /* set the volume; scale it to 0.0 - 1.0 */ | |
100 double V = (volume / 100.0); | |
101 audio_get_play_gain (audio_fd, &old_volume); | |
102 reset_volume_p = 1; | |
103 audio_set_play_gain (audio_fd, &V); | |
104 } | |
105 | |
106 return 0; | |
107 } | |
108 | |
109 | |
110 static void | |
111 reset_device (int wait_p) | |
112 { | |
113 if (wait_p) | |
114 audio_drain (audio_fd, 1); | |
115 else | |
116 audio_flush_play (audio_fd); | |
117 if (reset_device_p) | |
118 audio_set_play_config (audio_fd, &dev_hdr); | |
119 if (reset_volume_p) | |
120 audio_set_play_gain (audio_fd, &old_volume); | |
121 } | |
122 | |
123 | |
124 void | |
563 | 125 play_sound_file (Extbyte *sound_file, int volume) |
428 | 126 { |
127 int rrtn, wrtn; | |
2367 | 128 Binbyte buf [255]; |
428 | 129 int file_fd; |
130 | |
131 audio_fd = audio_open (); | |
132 | |
133 if (audio_fd < 0) | |
134 { | |
563 | 135 sound_perror ("open /dev/audio"); |
428 | 136 return; |
137 } | |
138 | |
139 /* where to find the proto for signal()... */ | |
613 | 140 sighup_handler = (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGHUP, sighandler); |
141 sigint_handler = (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGINT, sighandler); | |
428 | 142 |
143 file_fd = open (sound_file, O_RDONLY, 0); | |
144 if (file_fd < 0) | |
145 { | |
563 | 146 sound_perror (sound_file); |
428 | 147 goto END_OF_PLAY; |
148 } | |
149 | |
2367 | 150 if (init_device (volume, (Binbyte *) 0, file_fd, (unsigned int *) 0)) |
428 | 151 goto END_OF_PLAY; |
152 | |
153 while (1) | |
154 { | |
2367 | 155 rrtn = read (file_fd, (CBinbyte *) buf, sizeof (buf)); |
428 | 156 if (rrtn < 0) |
157 { | |
563 | 158 sound_perror ("read"); |
428 | 159 goto END_OF_PLAY; |
160 } | |
161 if (rrtn == 0) | |
162 break; | |
163 | |
164 while (1) | |
165 { | |
2367 | 166 wrtn = write (audio_fd, (CBinbyte *) buf, rrtn); |
428 | 167 if (wrtn < 0) |
168 { | |
563 | 169 sound_perror ("write"); |
428 | 170 goto END_OF_PLAY; |
171 } | |
172 if (wrtn != 0) | |
173 break; | |
174 | |
175 if (AUDIO_ERR_INTERRUPTED == audio_drain (audio_fd, 1)) | |
176 goto END_OF_PLAY; | |
177 } | |
178 if (wrtn != rrtn) | |
179 { | |
563 | 180 Extbyte warn_buf [255]; |
428 | 181 sprintf (warn_buf, "play: rrtn = %d, wrtn = %d", rrtn, wrtn); |
563 | 182 sound_warn (warn_buf); |
428 | 183 goto END_OF_PLAY; |
184 } | |
185 } | |
186 | |
187 END_OF_PLAY: | |
188 | |
189 if (file_fd > 0) | |
190 close (file_fd); | |
191 | |
192 if (audio_fd > 0) | |
193 { | |
194 reset_device (1); | |
195 close (audio_fd); | |
196 } | |
197 | |
613 | 198 EMACS_SIGNAL (SIGHUP, sighup_handler); |
199 EMACS_SIGNAL (SIGINT, sigint_handler); | |
428 | 200 } |
201 | |
202 | |
442 | 203 int |
2367 | 204 play_sound_data (Binbyte *data, int length, int volume) |
428 | 205 { |
206 int wrtn, start = 0; | |
207 unsigned int ilen; | |
442 | 208 int result = 0; |
428 | 209 |
210 audio_fd = -1; | |
211 | |
442 | 212 if (length == 0) return 0; |
428 | 213 |
214 /* this is just to get a better error message */ | |
2367 | 215 if (strncmp (".snd\0", (CBinbyte *) data, 4)) |
428 | 216 { |
563 | 217 sound_warn ("Not valid audio data (bad magic number)"); |
428 | 218 goto END_OF_PLAY; |
219 } | |
220 if (length <= sizeof (Audio_hdr)) | |
221 { | |
563 | 222 sound_warn ("Not valid audio data (too short)"); |
428 | 223 goto END_OF_PLAY; |
224 } | |
225 | |
226 audio_fd = audio_open (); | |
227 if (audio_fd < 0) | |
442 | 228 return 0; |
428 | 229 |
230 /* where to find the proto for signal()... */ | |
613 | 231 sighup_handler = (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGHUP, sighandler); |
232 sigint_handler = (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGINT, sighandler); | |
428 | 233 |
234 if (init_device (volume, data, 0, &ilen)) | |
235 goto END_OF_PLAY; | |
236 | |
237 data += (ilen<<2); | |
238 length -= (ilen<<2); | |
239 if (length <= 1) | |
240 goto END_OF_PLAY; | |
241 | |
242 while (1) | |
243 { | |
2367 | 244 wrtn = write (audio_fd, (CBinbyte *) (data+start), length-start); |
428 | 245 if (wrtn < 0) |
246 { | |
563 | 247 sound_perror ("write"); |
428 | 248 goto END_OF_PLAY; |
249 } | |
250 if (wrtn != 0) | |
251 { | |
252 start += wrtn; | |
253 break; | |
254 } | |
255 if (AUDIO_ERR_INTERRUPTED == audio_drain (audio_fd, 1)) | |
256 goto END_OF_PLAY; | |
257 } | |
258 if (wrtn != length) | |
259 { | |
563 | 260 Extbyte buf [255]; |
428 | 261 sprintf (buf, "play: rrtn = %d, wrtn = %d", length, wrtn); |
563 | 262 sound_warn (buf); |
428 | 263 goto END_OF_PLAY; |
264 } | |
265 | |
442 | 266 result = 1; |
267 | |
428 | 268 END_OF_PLAY: |
269 | |
270 if (audio_fd > 0) | |
271 { | |
272 reset_device (1); | |
273 close (audio_fd); | |
274 } | |
275 | |
613 | 276 EMACS_SIGNAL (SIGHUP, sighup_handler); |
277 EMACS_SIGNAL (SIGINT, sigint_handler); | |
442 | 278 |
279 return result; | |
428 | 280 } |
281 | |
282 /* #### sigcontext doesn't exist in Solaris. This should be updated | |
283 to be correct for Solaris. */ | |
442 | 284 static SIGTYPE |
428 | 285 sighandler (int sig) |
286 { | |
287 if (audio_fd > 0) | |
288 { | |
289 reset_device (0); | |
290 close (audio_fd); | |
291 } | |
292 if (sig == SIGHUP && sighup_handler) | |
293 sighup_handler (sig); | |
294 else if (sig == SIGINT && sigint_handler) | |
295 sigint_handler (sig); | |
296 else | |
297 exit (1); | |
298 } |