Mercurial > sdl-ios-xcode
annotate src/audio/dsp/SDL_dspaudio.c @ 563:04dcaf3da918
Massive Quartz input enhancements from Darrell Walisser. His email:
Enclosed is a patch that addresses the following:
--Various minor cleanups.
Removed dead/obsolete code, made some style cleanups
--Mouse Events
Now keep track of what button(s) were pressed so we know when to send
the mouse up event. This fixes the case where the mouse is dragged
outside of the game window and released (in which case we want to send
the mouse up event even though the mouse is outside the game window).
--Input Grabbing
Here is my take on the grabbing situation, which is the basis for the
new implementation.
There are 3 grab states, ungrabbed (UG), visible (VG), and invisible
(IG). Both VG and IG keep the mouse constrained to the window and
produce relative motion events. In VG the cursor is visible (duh), in
IG it is not. In VG, absolute motion events also work.
There are 6 actions that can affect grabbing:
1. Set Fullscreen/Window (F/W). In fullscreen, a visible grab should do
nothing. However, a fullscreen visible grab can be treated just like a
windowed visible grab, which is what I have done to help simplify
things.
2. Cursor hide/show (H/S). If the cursor is hidden when grabbing, the
grab is an invisible grab. If the cursor is visible, the grab should
just constrain the mouse to the window.
3. Input grab/ungrab(G/U). If grabbed, the cursor should be confined to
the window as should the keyboard input. On Mac OS X, the keyboard
input is implicitly grabbed by confining the cursor, except for
command-tab which can switch away from the application. Should the
window come to the foreground if the application is deactivated and
grab input is called? This isn't necessary in this implementation
because the grab state will be asserted upon activation.
Using my notation, these are all the cases that need to be handled
(state + action = new state).
UG+U = UG
UG+G = VG or IG, if cursor is visible or not
UG+H = UG
UG+S = UG
VG+U = UG
VG+G = VG
VG+H = IG
VG+S = VG
IG+U = UG
IG+G = IG
IG+H = IG
IG+S = VG
The cases that result in the same state can be ignored in the code,
which cuts it down to just 5 cases.
Another issue is what happens when the app loses/gains input focus from
deactivate/activate or iconify/deiconify. I think that if input focus
is ever lost (outside of SDL's control), the grab state should be
suspended and the cursor should become visible and active again. When
regained, the cursor should reappear in its original location and/or
grab state. This way, when reactivating the cursor is still in the same
position as before so apps shouldn't get confused when the next motion
event comes in. This is what I've done in this patch.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Fri, 27 Dec 2002 20:52:41 +0000 |
parents | 30935e76acb5 |
children | b8d311d90021 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
297
f6ffac90895c
Updated copyright information for 2002
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
248
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* Allow access to a raw mixing buffer */ | |
29 | |
30 #include <stdlib.h> | |
31 #include <stdio.h> | |
32 #include <string.h> | |
33 #include <errno.h> | |
34 #include <unistd.h> | |
35 #include <fcntl.h> | |
36 #include <signal.h> | |
37 #include <sys/time.h> | |
38 #include <sys/ioctl.h> | |
39 #include <sys/stat.h> | |
94
ae6e6b73333f
Cleaned up the OpenBSD port, thanks to Peter Valchev
Sam Lantinga <slouken@lokigames.com>
parents:
93
diff
changeset
|
40 #ifdef OSS_USE_SOUNDCARD_H |
ae6e6b73333f
Cleaned up the OpenBSD port, thanks to Peter Valchev
Sam Lantinga <slouken@lokigames.com>
parents:
93
diff
changeset
|
41 /* This is installed on some systems */ |
ae6e6b73333f
Cleaned up the OpenBSD port, thanks to Peter Valchev
Sam Lantinga <slouken@lokigames.com>
parents:
93
diff
changeset
|
42 #include <soundcard.h> |
ae6e6b73333f
Cleaned up the OpenBSD port, thanks to Peter Valchev
Sam Lantinga <slouken@lokigames.com>
parents:
93
diff
changeset
|
43 #else |
ae6e6b73333f
Cleaned up the OpenBSD port, thanks to Peter Valchev
Sam Lantinga <slouken@lokigames.com>
parents:
93
diff
changeset
|
44 /* This is recommended by OSS */ |
0 | 45 #include <sys/soundcard.h> |
94
ae6e6b73333f
Cleaned up the OpenBSD port, thanks to Peter Valchev
Sam Lantinga <slouken@lokigames.com>
parents:
93
diff
changeset
|
46 #endif |
0 | 47 |
48 #include "SDL_audio.h" | |
49 #include "SDL_error.h" | |
50 #include "SDL_audiomem.h" | |
51 #include "SDL_audio_c.h" | |
52 #include "SDL_timer.h" | |
53 #include "SDL_audiodev_c.h" | |
54 #include "SDL_dspaudio.h" | |
55 | |
56 /* The tag name used by DSP audio */ | |
57 #define DSP_DRIVER_NAME "dsp" | |
58 | |
59 /* Open the audio device for playback, and don't block if busy */ | |
97
c7bcdece4845
Revert to old non-blocking writes (if it ain't broke, don't fix it)
Sam Lantinga <slouken@lokigames.com>
parents:
96
diff
changeset
|
60 /*#define USE_BLOCKING_WRITES*/ |
0 | 61 #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) |
62 | |
63 /* Audio driver functions */ | |
64 static int DSP_OpenAudio(_THIS, SDL_AudioSpec *spec); | |
65 static void DSP_WaitAudio(_THIS); | |
66 static void DSP_PlayAudio(_THIS); | |
67 static Uint8 *DSP_GetAudioBuf(_THIS); | |
68 static void DSP_CloseAudio(_THIS); | |
69 | |
70 /* Audio driver bootstrap functions */ | |
71 | |
72 static int Audio_Available(void) | |
73 { | |
74 int fd; | |
75 int available; | |
76 | |
77 available = 0; | |
78 fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); | |
79 if ( fd >= 0 ) { | |
80 available = 1; | |
81 close(fd); | |
82 } | |
83 return(available); | |
84 } | |
85 | |
86 static void Audio_DeleteDevice(SDL_AudioDevice *device) | |
87 { | |
88 free(device->hidden); | |
89 free(device); | |
90 } | |
91 | |
92 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | |
93 { | |
94 SDL_AudioDevice *this; | |
95 | |
96 /* Initialize all variables that we clean on shutdown */ | |
97 this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice)); | |
98 if ( this ) { | |
99 memset(this, 0, (sizeof *this)); | |
100 this->hidden = (struct SDL_PrivateAudioData *) | |
101 malloc((sizeof *this->hidden)); | |
102 } | |
103 if ( (this == NULL) || (this->hidden == NULL) ) { | |
104 SDL_OutOfMemory(); | |
105 if ( this ) { | |
106 free(this); | |
107 } | |
108 return(0); | |
109 } | |
110 memset(this->hidden, 0, (sizeof *this->hidden)); | |
111 audio_fd = -1; | |
112 | |
113 /* Set the function pointers */ | |
114 this->OpenAudio = DSP_OpenAudio; | |
115 this->WaitAudio = DSP_WaitAudio; | |
116 this->PlayAudio = DSP_PlayAudio; | |
117 this->GetAudioBuf = DSP_GetAudioBuf; | |
118 this->CloseAudio = DSP_CloseAudio; | |
119 | |
120 this->free = Audio_DeleteDevice; | |
121 | |
122 return this; | |
123 } | |
124 | |
125 AudioBootStrap DSP_bootstrap = { | |
126 DSP_DRIVER_NAME, "OSS /dev/dsp standard audio", | |
127 Audio_Available, Audio_CreateDevice | |
128 }; | |
129 | |
130 /* This function waits until it is possible to write a full sound buffer */ | |
131 static void DSP_WaitAudio(_THIS) | |
132 { | |
133 /* Check to see if the thread-parent process is still alive */ | |
134 { static int cnt = 0; | |
135 /* Note that this only works with thread implementations | |
136 that use a different process id for each thread. | |
137 */ | |
138 if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */ | |
139 if ( kill(parent, 0) < 0 ) { | |
140 this->enabled = 0; | |
141 } | |
142 } | |
143 } | |
144 | |
93
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
145 #ifndef USE_BLOCKING_WRITES /* Not necessary when using blocking writes */ |
0 | 146 /* See if we need to use timed audio synchronization */ |
147 if ( frame_ticks ) { | |
148 /* Use timer for general audio synchronization */ | |
149 Sint32 ticks; | |
150 | |
151 ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; | |
152 if ( ticks > 0 ) { | |
153 SDL_Delay(ticks); | |
154 } | |
155 } else { | |
156 /* Use select() for audio synchronization */ | |
93
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
157 fd_set fdset; |
0 | 158 struct timeval timeout; |
93
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
159 |
0 | 160 FD_ZERO(&fdset); |
161 FD_SET(audio_fd, &fdset); | |
162 timeout.tv_sec = 10; | |
163 timeout.tv_usec = 0; | |
164 #ifdef DEBUG_AUDIO | |
165 fprintf(stderr, "Waiting for audio to get ready\n"); | |
166 #endif | |
167 if ( select(audio_fd+1, NULL, &fdset, NULL, &timeout) <= 0 ) { | |
168 const char *message = | |
169 "Audio timeout - buggy audio driver? (disabled)"; | |
170 /* In general we should never print to the screen, | |
171 but in this case we have no other way of letting | |
172 the user know what happened. | |
173 */ | |
174 fprintf(stderr, "SDL: %s\n", message); | |
175 this->enabled = 0; | |
176 /* Don't try to close - may hang */ | |
177 audio_fd = -1; | |
178 #ifdef DEBUG_AUDIO | |
179 fprintf(stderr, "Done disabling audio\n"); | |
180 #endif | |
181 } | |
182 #ifdef DEBUG_AUDIO | |
183 fprintf(stderr, "Ready!\n"); | |
184 #endif | |
185 } | |
186 #endif /* !USE_BLOCKING_WRITES */ | |
187 } | |
188 | |
189 static void DSP_PlayAudio(_THIS) | |
190 { | |
93
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
191 int written, p=0; |
0 | 192 |
193 /* Write the audio data, checking for EAGAIN on broken audio drivers */ | |
194 do { | |
93
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
195 written = write(audio_fd, &mixbuf[p], mixlen-p); |
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
196 if (written>0) |
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
197 p += written; |
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
198 if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) |
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
199 { |
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
200 /* Non recoverable error has occurred. It should be reported!!! */ |
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
201 perror("audio"); |
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
202 break; |
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
203 } |
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
204 |
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
205 if ( p < written || ((written < 0) && ((errno == 0) || (errno == EAGAIN))) ) { |
0 | 206 SDL_Delay(1); /* Let a little CPU time go by */ |
207 } | |
93
fc774f445e10
Applied Hannu's fix and switched to blocking writes .. seems to work?
Sam Lantinga <slouken@lokigames.com>
parents:
35
diff
changeset
|
208 } while ( p < written ); |
0 | 209 |
210 /* If timer synchronization is enabled, set the next write frame */ | |
211 if ( frame_ticks ) { | |
212 next_frame += frame_ticks; | |
213 } | |
214 | |
215 /* If we couldn't write, assume fatal error for now */ | |
216 if ( written < 0 ) { | |
217 this->enabled = 0; | |
218 } | |
219 #ifdef DEBUG_AUDIO | |
220 fprintf(stderr, "Wrote %d bytes of audio data\n", written); | |
221 #endif | |
222 } | |
223 | |
224 static Uint8 *DSP_GetAudioBuf(_THIS) | |
225 { | |
226 return(mixbuf); | |
227 } | |
228 | |
229 static void DSP_CloseAudio(_THIS) | |
230 { | |
231 if ( mixbuf != NULL ) { | |
232 SDL_FreeAudioMem(mixbuf); | |
233 mixbuf = NULL; | |
234 } | |
235 if ( audio_fd >= 0 ) { | |
248
8e47ebb7bced
Reset the device before closing it - fixes a hang with some audio drivers
Sam Lantinga <slouken@libsdl.org>
parents:
97
diff
changeset
|
236 int value; |
8e47ebb7bced
Reset the device before closing it - fixes a hang with some audio drivers
Sam Lantinga <slouken@libsdl.org>
parents:
97
diff
changeset
|
237 ioctl(audio_fd, SNDCTL_DSP_RESET, &value); |
0 | 238 close(audio_fd); |
239 audio_fd = -1; | |
240 } | |
241 } | |
242 | |
243 static int DSP_ReopenAudio(_THIS, const char *audiodev, int format, | |
244 SDL_AudioSpec *spec) | |
245 { | |
246 int frag_spec; | |
247 int value; | |
248 | |
249 /* Close and then reopen the audio device */ | |
250 close(audio_fd); | |
251 audio_fd = open(audiodev, O_WRONLY, 0); | |
252 if ( audio_fd < 0 ) { | |
253 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); | |
254 return(-1); | |
255 } | |
256 | |
257 /* Calculate the final parameters for this audio specification */ | |
258 SDL_CalculateAudioSpec(spec); | |
259 | |
260 /* Determine the power of two of the fragment size */ | |
261 for ( frag_spec = 0; (0x01<<frag_spec) < spec->size; ++frag_spec ); | |
262 if ( (0x01<<frag_spec) != spec->size ) { | |
263 SDL_SetError("Fragment size must be a power of two"); | |
264 return(-1); | |
265 } | |
266 frag_spec |= 0x00020000; /* two fragments, for low latency */ | |
267 | |
268 /* Set the audio buffering parameters */ | |
269 #ifdef DEBUG_AUDIO | |
270 fprintf(stderr, "Requesting %d fragments of size %d\n", | |
271 (frag_spec >> 16), 1<<(frag_spec&0xFFFF)); | |
272 #endif | |
273 if ( ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0 ) { | |
274 fprintf(stderr, "Warning: Couldn't set audio fragment size\n"); | |
275 } | |
276 #ifdef DEBUG_AUDIO | |
277 { audio_buf_info info; | |
278 ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info); | |
279 fprintf(stderr, "fragments = %d\n", info.fragments); | |
280 fprintf(stderr, "fragstotal = %d\n", info.fragstotal); | |
281 fprintf(stderr, "fragsize = %d\n", info.fragsize); | |
282 fprintf(stderr, "bytes = %d\n", info.bytes); | |
283 } | |
284 #endif | |
285 | |
286 /* Set the audio format */ | |
287 value = format; | |
288 if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || | |
289 (value != format) ) { | |
290 SDL_SetError("Couldn't set audio format"); | |
291 return(-1); | |
292 } | |
293 | |
294 /* Set the number of channels of output */ | |
295 value = spec->channels; | |
296 #ifdef SNDCTL_DSP_CHANNELS | |
297 if ( ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0 ) { | |
298 #endif | |
299 value = (spec->channels > 1); | |
300 ioctl(audio_fd, SNDCTL_DSP_STEREO, &value); | |
301 value = (value ? 2 : 1); | |
302 #ifdef SNDCTL_DSP_CHANNELS | |
303 } | |
304 #endif | |
305 if ( value != spec->channels ) { | |
306 SDL_SetError("Couldn't set audio channels"); | |
307 return(-1); | |
308 } | |
309 | |
310 /* Set the DSP frequency */ | |
311 value = spec->freq; | |
312 if ( ioctl(audio_fd, SOUND_PCM_WRITE_RATE, &value) < 0 ) { | |
313 SDL_SetError("Couldn't set audio frequency"); | |
314 return(-1); | |
315 } | |
316 spec->freq = value; | |
317 | |
318 /* We successfully re-opened the audio */ | |
319 return(0); | |
320 } | |
321 | |
322 static int DSP_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
323 { | |
324 char audiodev[1024]; | |
325 int format; | |
326 int value; | |
327 Uint16 test_format; | |
328 | |
329 /* Reset the timer synchronization flag */ | |
330 frame_ticks = 0.0; | |
331 | |
332 /* Open the audio device */ | |
333 audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); | |
334 if ( audio_fd < 0 ) { | |
335 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); | |
336 return(-1); | |
337 } | |
338 mixbuf = NULL; | |
339 | |
96
799bea5504e2
Fixed blocking open bug when using blocking audio writes
Sam Lantinga <slouken@lokigames.com>
parents:
94
diff
changeset
|
340 #ifdef USE_BLOCKING_WRITES |
799bea5504e2
Fixed blocking open bug when using blocking audio writes
Sam Lantinga <slouken@lokigames.com>
parents:
94
diff
changeset
|
341 /* Make the file descriptor use blocking writes with fcntl() */ |
799bea5504e2
Fixed blocking open bug when using blocking audio writes
Sam Lantinga <slouken@lokigames.com>
parents:
94
diff
changeset
|
342 { long flags; |
799bea5504e2
Fixed blocking open bug when using blocking audio writes
Sam Lantinga <slouken@lokigames.com>
parents:
94
diff
changeset
|
343 flags = fcntl(audio_fd, F_GETFL); |
799bea5504e2
Fixed blocking open bug when using blocking audio writes
Sam Lantinga <slouken@lokigames.com>
parents:
94
diff
changeset
|
344 flags &= ~O_NONBLOCK; |
799bea5504e2
Fixed blocking open bug when using blocking audio writes
Sam Lantinga <slouken@lokigames.com>
parents:
94
diff
changeset
|
345 if ( fcntl(audio_fd, F_SETFL, flags) < 0 ) { |
799bea5504e2
Fixed blocking open bug when using blocking audio writes
Sam Lantinga <slouken@lokigames.com>
parents:
94
diff
changeset
|
346 SDL_SetError("Couldn't set audio blocking mode"); |
799bea5504e2
Fixed blocking open bug when using blocking audio writes
Sam Lantinga <slouken@lokigames.com>
parents:
94
diff
changeset
|
347 return(-1); |
799bea5504e2
Fixed blocking open bug when using blocking audio writes
Sam Lantinga <slouken@lokigames.com>
parents:
94
diff
changeset
|
348 } |
799bea5504e2
Fixed blocking open bug when using blocking audio writes
Sam Lantinga <slouken@lokigames.com>
parents:
94
diff
changeset
|
349 } |
799bea5504e2
Fixed blocking open bug when using blocking audio writes
Sam Lantinga <slouken@lokigames.com>
parents:
94
diff
changeset
|
350 #endif |
799bea5504e2
Fixed blocking open bug when using blocking audio writes
Sam Lantinga <slouken@lokigames.com>
parents:
94
diff
changeset
|
351 |
0 | 352 /* Get a list of supported hardware formats */ |
353 if ( ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0 ) { | |
354 SDL_SetError("Couldn't get audio format list"); | |
355 return(-1); | |
356 } | |
357 | |
358 /* Try for a closest match on audio format */ | |
359 format = 0; | |
360 for ( test_format = SDL_FirstAudioFormat(spec->format); | |
361 ! format && test_format; ) { | |
362 #ifdef DEBUG_AUDIO | |
363 fprintf(stderr, "Trying format 0x%4.4x\n", test_format); | |
364 #endif | |
365 switch ( test_format ) { | |
366 case AUDIO_U8: | |
367 if ( value & AFMT_U8 ) { | |
368 format = AFMT_U8; | |
369 } | |
370 break; | |
371 case AUDIO_S8: | |
372 if ( value & AFMT_S8 ) { | |
373 format = AFMT_S8; | |
374 } | |
375 break; | |
376 case AUDIO_S16LSB: | |
377 if ( value & AFMT_S16_LE ) { | |
378 format = AFMT_S16_LE; | |
379 } | |
380 break; | |
381 case AUDIO_S16MSB: | |
382 if ( value & AFMT_S16_BE ) { | |
383 format = AFMT_S16_BE; | |
384 } | |
385 break; | |
386 case AUDIO_U16LSB: | |
387 if ( value & AFMT_U16_LE ) { | |
388 format = AFMT_U16_LE; | |
389 } | |
390 break; | |
391 case AUDIO_U16MSB: | |
392 if ( value & AFMT_U16_BE ) { | |
393 format = AFMT_U16_BE; | |
394 } | |
395 break; | |
396 default: | |
354
30935e76acb5
Updated ALSA audio support for ALSA 0.9
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
397 format = 0; |
0 | 398 break; |
399 } | |
400 if ( ! format ) { | |
401 test_format = SDL_NextAudioFormat(); | |
402 } | |
403 } | |
404 if ( format == 0 ) { | |
405 SDL_SetError("Couldn't find any hardware audio formats"); | |
406 return(-1); | |
407 } | |
408 spec->format = test_format; | |
409 | |
410 /* Set the audio format */ | |
411 value = format; | |
412 if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || | |
413 (value != format) ) { | |
414 SDL_SetError("Couldn't set audio format"); | |
415 return(-1); | |
416 } | |
417 | |
418 /* Set the number of channels of output */ | |
419 value = spec->channels; | |
420 #ifdef SNDCTL_DSP_CHANNELS | |
421 if ( ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0 ) { | |
422 #endif | |
423 value = (spec->channels > 1); | |
424 ioctl(audio_fd, SNDCTL_DSP_STEREO, &value); | |
425 value = (value ? 2 : 1); | |
426 #ifdef SNDCTL_DSP_CHANNELS | |
427 } | |
428 #endif | |
429 spec->channels = value; | |
430 | |
431 /* Because some drivers don't allow setting the buffer size | |
432 after setting the format, we must re-open the audio device | |
433 once we know what format and channels are supported | |
434 */ | |
435 if ( DSP_ReopenAudio(this, audiodev, format, spec) < 0 ) { | |
436 /* Error is set by DSP_ReopenAudio() */ | |
437 return(-1); | |
438 } | |
439 | |
440 /* Allocate mixing buffer */ | |
441 mixlen = spec->size; | |
442 mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); | |
443 if ( mixbuf == NULL ) { | |
444 return(-1); | |
445 } | |
446 memset(mixbuf, spec->silence, spec->size); | |
447 | |
448 #ifndef USE_BLOCKING_WRITES | |
449 /* Check to see if we need to use select() workaround */ | |
450 { char *workaround; | |
451 workaround = getenv("SDL_DSP_NOSELECT"); | |
452 if ( workaround ) { | |
453 frame_ticks = (float)(spec->samples*1000)/spec->freq; | |
454 next_frame = SDL_GetTicks()+frame_ticks; | |
455 } | |
456 } | |
457 #endif /* !USE_BLOCKING_WRITES */ | |
458 | |
459 /* Get the parent process id (we're the parent of the audio thread) */ | |
460 parent = getpid(); | |
461 | |
462 /* We're ready to rock and roll. :-) */ | |
463 return(0); | |
464 } |