Mercurial > sdl-ios-xcode
comparison src/audio/pulse/SDL_pulseaudio.c @ 4211:3ce5bfddbaf6 SDL-1.2
Fixed bug #572
Please merge this patch for the PA driver in SDL.
http://0pointer.de/public/sdl-pulse-rework.patch
This patch:
- fixes buffering (i.e. reduces number of "fragments" to 2, doesn't defer
filling up of the buffer until the entire buffer ran completely empty.)
- drops $PASERVER and $PADEVICE env var support, since this is a duplication of
$PULSE_SERVER and $PULSE_SINK which the PA libs honor anyway.
This fixes the sound issues in all games I tested.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 21 Sep 2009 08:03:00 +0000 |
parents | a1b03ba2fcd0 |
children | 5b99971a27b4 |
comparison
equal
deleted
inserted
replaced
4210:8f501bbc3bf1 | 4211:3ce5bfddbaf6 |
---|---|
1 /* -*- Mode: C; c-basic-offset: 8; indent-tabs-mode: t -*- */ | |
1 /* | 2 /* |
2 SDL - Simple DirectMedia Layer | 3 SDL - Simple DirectMedia Layer |
3 Copyright (C) 1997-2009 Sam Lantinga | 4 Copyright (C) 1997-2009 Sam Lantinga |
4 | 5 |
5 This library is free software; you can redistribute it and/or | 6 This library is free software; you can redistribute it and/or |
16 License along with this library; if not, write to the Free Software | 17 License along with this library; if not, write to the Free Software |
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
18 | 19 |
19 Stéphan Kochen | 20 Stéphan Kochen |
20 stephan@kochen.nl | 21 stephan@kochen.nl |
21 | 22 |
22 Based on parts of the ALSA and ESounD output drivers. | 23 Based on parts of the ALSA and ESounD output drivers. |
23 */ | 24 */ |
24 #include "SDL_config.h" | 25 #include "SDL_config.h" |
25 | 26 |
26 /* Allow access to an PulseAudio network stream mixing buffer */ | 27 /* Allow access to an PulseAudio network stream mixing buffer */ |
76 static int (*SDL_NAME(pa_simple_drain))(pa_simple *s, int *error); | 77 static int (*SDL_NAME(pa_simple_drain))(pa_simple *s, int *error); |
77 static int (*SDL_NAME(pa_simple_write))( | 78 static int (*SDL_NAME(pa_simple_write))( |
78 pa_simple *s, | 79 pa_simple *s, |
79 const void *data, | 80 const void *data, |
80 size_t length, | 81 size_t length, |
81 int *error | 82 int *error |
82 ); | 83 ); |
83 static pa_channel_map* (*SDL_NAME(pa_channel_map_init_auto))( | 84 static pa_channel_map* (*SDL_NAME(pa_channel_map_init_auto))( |
84 pa_channel_map *m, | 85 pa_channel_map *m, |
85 unsigned channels, | 86 unsigned channels, |
86 pa_channel_map_def_t def | 87 pa_channel_map_def_t def |
87 ); | 88 ); |
88 | 89 |
89 | 90 |
90 static struct { | 91 static struct { |
91 const char *name; | 92 const char *name; |
92 void **func; | 93 void **func; |
93 } pulse_functions[] = { | 94 } pulse_functions[] = { |
156 | 157 |
157 available = 0; | 158 available = 0; |
158 if ( LoadPulseLibrary() < 0 ) { | 159 if ( LoadPulseLibrary() < 0 ) { |
159 return available; | 160 return available; |
160 } | 161 } |
161 | 162 |
162 /* Connect with a dummy format. */ | 163 /* Connect with a dummy format. */ |
163 paspec.format = PA_SAMPLE_U8; | 164 paspec.format = PA_SAMPLE_U8; |
164 paspec.rate = 11025; | 165 paspec.rate = 11025; |
165 paspec.channels = 1; | 166 paspec.channels = 1; |
166 connection = SDL_NAME(pa_simple_new)( | 167 connection = SDL_NAME(pa_simple_new)( |
167 SDL_getenv("PASERVER"), /* server */ | 168 NULL, /* server */ |
168 "Test stream", /* application name */ | 169 "Test stream", /* application name */ |
169 PA_STREAM_PLAYBACK, /* playback mode */ | 170 PA_STREAM_PLAYBACK, /* playback mode */ |
170 SDL_getenv("PADEVICE"), /* device on the server */ | 171 NULL, /* device on the server */ |
171 "Simple DirectMedia Layer", /* stream description */ | 172 "Simple DirectMedia Layer", /* stream description */ |
172 &paspec, /* sample format spec */ | 173 &paspec, /* sample format spec */ |
173 NULL, /* channel map */ | 174 NULL, /* channel map */ |
174 NULL, /* buffering attributes */ | 175 NULL, /* buffering attributes */ |
175 NULL /* error code */ | 176 NULL /* error code */ |
176 ); | 177 ); |
177 if ( connection != NULL ) { | 178 if ( connection != NULL ) { |
178 available = 1; | 179 available = 1; |
179 SDL_NAME(pa_simple_free)(connection); | 180 SDL_NAME(pa_simple_free)(connection); |
180 } | 181 } |
181 | 182 |
182 UnloadPulseLibrary(); | 183 UnloadPulseLibrary(); |
183 return(available); | 184 return(available); |
184 } | 185 } |
185 | 186 |
186 static void Audio_DeleteDevice(SDL_AudioDevice *device) | 187 static void Audio_DeleteDevice(SDL_AudioDevice *device) |
231 /* This function waits until it is possible to write a full sound buffer */ | 232 /* This function waits until it is possible to write a full sound buffer */ |
232 static void PULSE_WaitAudio(_THIS) | 233 static void PULSE_WaitAudio(_THIS) |
233 { | 234 { |
234 /* Check to see if the thread-parent process is still alive */ | 235 /* Check to see if the thread-parent process is still alive */ |
235 { static int cnt = 0; | 236 { static int cnt = 0; |
236 /* Note that this only works with thread implementations | 237 /* Note that this only works with thread implementations |
237 that use a different process id for each thread. | 238 that use a different process id for each thread. |
238 */ | 239 */ |
239 if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */ | 240 if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */ |
240 if ( kill(parent, 0) < 0 ) { | 241 if ( kill(parent, 0) < 0 ) { |
241 this->enabled = 0; | 242 this->enabled = 0; |
300 { | 301 { |
301 Uint16 test_format; | 302 Uint16 test_format; |
302 pa_sample_spec paspec; | 303 pa_sample_spec paspec; |
303 pa_buffer_attr paattr; | 304 pa_buffer_attr paattr; |
304 pa_channel_map pacmap; | 305 pa_channel_map pacmap; |
305 | 306 |
306 paspec.format = PA_SAMPLE_INVALID; | 307 paspec.format = PA_SAMPLE_INVALID; |
307 for ( test_format = SDL_FirstAudioFormat(spec->format); test_format; ) { | 308 for ( test_format = SDL_FirstAudioFormat(spec->format); test_format; ) { |
308 switch ( test_format ) { | 309 switch ( test_format ) { |
309 case AUDIO_U8: | 310 case AUDIO_U8: |
310 paspec.format = PA_SAMPLE_U8; | 311 paspec.format = PA_SAMPLE_U8; |
322 if (paspec.format == PA_SAMPLE_INVALID ) { | 323 if (paspec.format == PA_SAMPLE_INVALID ) { |
323 SDL_SetError("Couldn't find any suitable audio formats"); | 324 SDL_SetError("Couldn't find any suitable audio formats"); |
324 return(-1); | 325 return(-1); |
325 } | 326 } |
326 spec->format = test_format; | 327 spec->format = test_format; |
327 | 328 |
328 paspec.channels = spec->channels; | 329 paspec.channels = spec->channels; |
329 paspec.rate = spec->freq; | 330 paspec.rate = spec->freq; |
330 | 331 |
331 /* Calculate the final parameters for this audio specification */ | 332 /* Calculate the final parameters for this audio specification */ |
332 SDL_CalculateAudioSpec(spec); | 333 SDL_CalculateAudioSpec(spec); |
336 mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); | 337 mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); |
337 if ( mixbuf == NULL ) { | 338 if ( mixbuf == NULL ) { |
338 return(-1); | 339 return(-1); |
339 } | 340 } |
340 SDL_memset(mixbuf, spec->silence, spec->size); | 341 SDL_memset(mixbuf, spec->silence, spec->size); |
341 | 342 |
342 /* Reduced prebuffering compared to the defaults. */ | 343 /* Reduced prebuffering compared to the defaults. */ |
343 paattr.tlength = mixlen; | 344 paattr.tlength = mixlen*2; |
344 paattr.minreq = mixlen; | 345 paattr.minreq = mixlen; |
345 paattr.fragsize = mixlen; | 346 paattr.prebuf = mixlen*2; |
346 paattr.prebuf = mixlen; | 347 paattr.maxlength = mixlen*2; |
347 paattr.maxlength = mixlen * 4; | 348 |
348 | |
349 /* The SDL ALSA output hints us that we use Windows' channel mapping */ | 349 /* The SDL ALSA output hints us that we use Windows' channel mapping */ |
350 /* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */ | 350 /* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */ |
351 SDL_NAME(pa_channel_map_init_auto)( | 351 SDL_NAME(pa_channel_map_init_auto)( |
352 &pacmap, spec->channels, PA_CHANNEL_MAP_WAVEEX); | 352 &pacmap, spec->channels, PA_CHANNEL_MAP_WAVEEX); |
353 | 353 |
354 /* Connect to the PulseAudio server */ | 354 /* Connect to the PulseAudio server */ |
355 stream = SDL_NAME(pa_simple_new)( | 355 stream = SDL_NAME(pa_simple_new)( |
356 SDL_getenv("PASERVER"), /* server */ | 356 NULL, /* server */ |
357 get_progname(), /* application name */ | 357 get_progname(), /* application name */ |
358 PA_STREAM_PLAYBACK, /* playback mode */ | 358 PA_STREAM_PLAYBACK, /* playback mode */ |
359 SDL_getenv("PADEVICE"), /* device on the server */ | 359 NULL, /* device on the server */ |
360 "Simple DirectMedia Layer", /* stream description */ | 360 "Simple DirectMedia Layer", /* stream description */ |
361 &paspec, /* sample format spec */ | 361 &paspec, /* sample format spec */ |
362 &pacmap, /* channel map */ | 362 &pacmap, /* channel map */ |
363 &paattr, /* buffering attributes */ | 363 &paattr, /* buffering attributes */ |
364 NULL /* error code */ | 364 NULL /* error code */ |
369 return(-1); | 369 return(-1); |
370 } | 370 } |
371 | 371 |
372 /* Get the parent process id (we're the parent of the audio thread) */ | 372 /* Get the parent process id (we're the parent of the audio thread) */ |
373 parent = getpid(); | 373 parent = getpid(); |
374 | 374 |
375 return(0); | 375 return(0); |
376 } | 376 } |
377 |