Mercurial > sdl-ios-xcode
comparison src/audio/pulseaudio/SDL_pulseaudio.c @ 3672:878d8adf2fde
Merged r4210:5510 from branches/SDL-1.2/src/audio/pulse: PulseAudio updates.
This pulls all the PulseAudio reworking that was done for 1.2.14 into 1.3.
Fixes Bugzilla #801.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sun, 17 Jan 2010 06:14:04 +0000 |
parents | b21348d47cab |
children | c9d5bd1b4e18 |
comparison
equal
deleted
inserted
replaced
3671:0d6f520c0eb9 | 3672:878d8adf2fde |
---|---|
35 #include <signal.h> | 35 #include <signal.h> |
36 #endif | 36 #endif |
37 #include <unistd.h> | 37 #include <unistd.h> |
38 #include <sys/types.h> | 38 #include <sys/types.h> |
39 #include <errno.h> | 39 #include <errno.h> |
40 #include <pulse/pulseaudio.h> | |
40 #include <pulse/simple.h> | 41 #include <pulse/simple.h> |
41 | 42 |
42 #include "SDL_timer.h" | 43 #include "SDL_timer.h" |
43 #include "SDL_audio.h" | 44 #include "SDL_audio.h" |
44 #include "../SDL_audiomem.h" | 45 #include "../SDL_audiomem.h" |
54 | 55 |
55 /* The tag name used by pulse audio */ | 56 /* The tag name used by pulse audio */ |
56 #define PULSEAUDIO_DRIVER_NAME "pulseaudio" | 57 #define PULSEAUDIO_DRIVER_NAME "pulseaudio" |
57 | 58 |
58 #ifdef SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC | 59 #ifdef SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC |
60 | |
61 #if (PA_API_VERSION < 12) | |
62 /** Return non-zero if the passed state is one of the connected states */ | |
63 static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x) { | |
64 return | |
65 x == PA_CONTEXT_CONNECTING || | |
66 x == PA_CONTEXT_AUTHORIZING || | |
67 x == PA_CONTEXT_SETTING_NAME || | |
68 x == PA_CONTEXT_READY; | |
69 } | |
70 /** Return non-zero if the passed state is one of the connected states */ | |
71 static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) { | |
72 return | |
73 x == PA_STREAM_CREATING || | |
74 x == PA_STREAM_READY; | |
75 } | |
76 #endif /* pulseaudio <= 0.9.10 */ | |
59 | 77 |
60 static const char *pulse_library = SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC; | 78 static const char *pulse_library = SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC; |
61 static void *pulse_handle = NULL; | 79 static void *pulse_handle = NULL; |
62 | 80 |
63 /* !!! FIXME: I hate this SDL_NAME clutter...it makes everything so messy! */ | 81 /* !!! FIXME: I hate this SDL_NAME clutter...it makes everything so messy! */ |
69 const pa_sample_spec * ss, | 87 const pa_sample_spec * ss, |
70 const pa_channel_map * map, | 88 const pa_channel_map * map, |
71 const pa_buffer_attr * attr, | 89 const pa_buffer_attr * attr, |
72 int *error); | 90 int *error); |
73 static void (*SDL_NAME(pa_simple_free)) (pa_simple * s); | 91 static void (*SDL_NAME(pa_simple_free)) (pa_simple * s); |
74 static int (*SDL_NAME(pa_simple_drain)) (pa_simple * s, int *error); | |
75 static int (*SDL_NAME(pa_simple_write)) (pa_simple * s, | |
76 const void *data, | |
77 size_t length, int *error); | |
78 static pa_channel_map *(*SDL_NAME(pa_channel_map_init_auto)) (pa_channel_map * | 92 static pa_channel_map *(*SDL_NAME(pa_channel_map_init_auto)) (pa_channel_map * |
79 m, | 93 m, |
80 unsigned | 94 unsigned |
81 channels, | 95 channels, |
82 pa_channel_map_def_t | 96 pa_channel_map_def_t |
83 def); | 97 def); |
84 static const char *(*SDL_NAME(pa_strerror)) (int error); | 98 static const char *(*SDL_NAME(pa_strerror)) (int error); |
99 static pa_mainloop * (*SDL_NAME(pa_mainloop_new))(void); | |
100 static pa_mainloop_api * (*SDL_NAME(pa_mainloop_get_api))(pa_mainloop *m); | |
101 static int (*SDL_NAME(pa_mainloop_iterate))(pa_mainloop *m, int block, int *retval); | |
102 static void (*SDL_NAME(pa_mainloop_free))(pa_mainloop *m); | |
103 | |
104 static pa_operation_state_t (*SDL_NAME(pa_operation_get_state))(pa_operation *o); | |
105 static void (*SDL_NAME(pa_operation_cancel))(pa_operation *o); | |
106 static void (*SDL_NAME(pa_operation_unref))(pa_operation *o); | |
107 | |
108 static pa_context * (*SDL_NAME(pa_context_new))( | |
109 pa_mainloop_api *m, const char *name); | |
110 static int (*SDL_NAME(pa_context_connect))( | |
111 pa_context *c, const char *server, | |
112 pa_context_flags_t flags, const pa_spawn_api *api); | |
113 static pa_context_state_t (*SDL_NAME(pa_context_get_state))(pa_context *c); | |
114 static void (*SDL_NAME(pa_context_disconnect))(pa_context *c); | |
115 static void (*SDL_NAME(pa_context_unref))(pa_context *c); | |
116 | |
117 static pa_stream * (*SDL_NAME(pa_stream_new))(pa_context *c, | |
118 const char *name, const pa_sample_spec *ss, const pa_channel_map *map); | |
119 static int (*SDL_NAME(pa_stream_connect_playback))(pa_stream *s, const char *dev, | |
120 const pa_buffer_attr *attr, pa_stream_flags_t flags, | |
121 pa_cvolume *volume, pa_stream *sync_stream); | |
122 static pa_stream_state_t (*SDL_NAME(pa_stream_get_state))(pa_stream *s); | |
123 static size_t (*SDL_NAME(pa_stream_writable_size))(pa_stream *s); | |
124 static int (*SDL_NAME(pa_stream_write))(pa_stream *s, const void *data, size_t nbytes, | |
125 pa_free_cb_t free_cb, int64_t offset, pa_seek_mode_t seek); | |
126 static pa_operation * (*SDL_NAME(pa_stream_drain))(pa_stream *s, | |
127 pa_stream_success_cb_t cb, void *userdata); | |
128 static int (*SDL_NAME(pa_stream_disconnect))(pa_stream *s); | |
129 static void (*SDL_NAME(pa_stream_unref))(pa_stream *s); | |
85 | 130 |
86 | 131 |
87 #define SDL_PULSEAUDIO_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) } | 132 #define SDL_PULSEAUDIO_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) } |
88 static struct | 133 static struct |
89 { | 134 { |
91 void **func; | 136 void **func; |
92 } pulse_functions[] = { | 137 } pulse_functions[] = { |
93 /* *INDENT-OFF* */ | 138 /* *INDENT-OFF* */ |
94 SDL_PULSEAUDIO_SYM(pa_simple_new), | 139 SDL_PULSEAUDIO_SYM(pa_simple_new), |
95 SDL_PULSEAUDIO_SYM(pa_simple_free), | 140 SDL_PULSEAUDIO_SYM(pa_simple_free), |
96 SDL_PULSEAUDIO_SYM(pa_simple_drain), | 141 SDL_PULSEAUDIO_SYM(pa_mainloop_new), |
97 SDL_PULSEAUDIO_SYM(pa_simple_write), | 142 SDL_PULSEAUDIO_SYM(pa_mainloop_get_api), |
143 SDL_PULSEAUDIO_SYM(pa_mainloop_iterate), | |
144 SDL_PULSEAUDIO_SYM(pa_mainloop_free), | |
145 SDL_PULSEAUDIO_SYM(pa_operation_get_state), | |
146 SDL_PULSEAUDIO_SYM(pa_operation_cancel), | |
147 SDL_PULSEAUDIO_SYM(pa_operation_unref), | |
148 SDL_PULSEAUDIO_SYM(pa_context_new), | |
149 SDL_PULSEAUDIO_SYM(pa_context_connect), | |
150 SDL_PULSEAUDIO_SYM(pa_context_get_state), | |
151 SDL_PULSEAUDIO_SYM(pa_context_disconnect), | |
152 SDL_PULSEAUDIO_SYM(pa_context_unref), | |
153 SDL_PULSEAUDIO_SYM(pa_stream_new), | |
154 SDL_PULSEAUDIO_SYM(pa_stream_connect_playback), | |
155 SDL_PULSEAUDIO_SYM(pa_stream_get_state), | |
156 SDL_PULSEAUDIO_SYM(pa_stream_writable_size), | |
157 SDL_PULSEAUDIO_SYM(pa_stream_write), | |
158 SDL_PULSEAUDIO_SYM(pa_stream_drain), | |
159 SDL_PULSEAUDIO_SYM(pa_stream_disconnect), | |
160 SDL_PULSEAUDIO_SYM(pa_stream_unref), | |
98 SDL_PULSEAUDIO_SYM(pa_channel_map_init_auto), | 161 SDL_PULSEAUDIO_SYM(pa_channel_map_init_auto), |
99 SDL_PULSEAUDIO_SYM(pa_strerror), | 162 SDL_PULSEAUDIO_SYM(pa_strerror), |
100 /* *INDENT-ON* */ | 163 /* *INDENT-ON* */ |
101 }; | 164 }; |
102 | 165 |
153 | 216 |
154 /* This function waits until it is possible to write a full sound buffer */ | 217 /* This function waits until it is possible to write a full sound buffer */ |
155 static void | 218 static void |
156 PULSEAUDIO_WaitDevice(_THIS) | 219 PULSEAUDIO_WaitDevice(_THIS) |
157 { | 220 { |
158 Sint32 ticks; | 221 while(1) { |
159 | 222 if (SDL_NAME(pa_context_get_state)(this->hidden->context) != PA_CONTEXT_READY || |
160 /* Check to see if the thread-parent process is still alive */ | 223 SDL_NAME(pa_stream_get_state)(this->hidden->stream) != PA_STREAM_READY || |
161 { | 224 SDL_NAME(pa_mainloop_iterate)(this->hidden->mainloop, 1, NULL) < 0) { |
162 static int cnt = 0; | 225 this->enabled = 0; |
163 /* Note that this only works with thread implementations | 226 return; |
164 that use a different process id for each thread. | 227 } |
165 */ | 228 if (SDL_NAME(pa_stream_writable_size)(this->hidden->stream) >= this->hidden->mixlen) { |
166 /* Check every 10 loops */ | 229 return; |
167 if (this->hidden->parent && (((++cnt) % 10) == 0)) { | 230 } |
168 if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) { | |
169 this->enabled = 0; | |
170 } | |
171 } | |
172 } | |
173 | |
174 /* Use timer for general audio synchronization */ | |
175 ticks = | |
176 ((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS; | |
177 if (ticks > 0) { | |
178 SDL_Delay(ticks); | |
179 } | 231 } |
180 } | 232 } |
181 | 233 |
182 static void | 234 static void |
183 PULSEAUDIO_PlayDevice(_THIS) | 235 PULSEAUDIO_PlayDevice(_THIS) |
184 { | 236 { |
185 /* Write the audio data */ | 237 /* Write the audio data */ |
186 if (SDL_NAME(pa_simple_write) (this->hidden->stream, this->hidden->mixbuf, | 238 if (SDL_NAME(pa_stream_write) (this->hidden->stream, this->hidden->mixbuf, |
187 this->hidden->mixlen, NULL) != 0) { | 239 this->hidden->mixlen, NULL, 0LL, |
240 PA_SEEK_RELATIVE) < 0) { | |
188 this->enabled = 0; | 241 this->enabled = 0; |
189 } | 242 } |
190 } | 243 } |
191 | 244 |
192 static void | 245 static void |
246 stream_drain_complete(pa_stream *s, int success, void *userdata) | |
247 { | |
248 /* no-op for pa_stream_drain() to use for callback. */ | |
249 } | |
250 | |
251 static void | |
193 PULSEAUDIO_WaitDone(_THIS) | 252 PULSEAUDIO_WaitDone(_THIS) |
194 { | 253 { |
195 SDL_NAME(pa_simple_drain) (this->hidden->stream, NULL); | 254 pa_operation *o; |
196 } | 255 |
256 o = SDL_NAME(pa_stream_drain)(this->hidden->stream, stream_drain_complete, NULL); | |
257 if (!o) { | |
258 return; | |
259 } | |
260 | |
261 while (SDL_NAME(pa_operation_get_state)(o) != PA_OPERATION_DONE) { | |
262 if (SDL_NAME(pa_context_get_state)(this->hidden->context) != PA_CONTEXT_READY || | |
263 SDL_NAME(pa_stream_get_state)(this->hidden->stream) != PA_STREAM_READY || | |
264 SDL_NAME(pa_mainloop_iterate)(this->hidden->mainloop, 1, NULL) < 0) { | |
265 SDL_NAME(pa_operation_cancel)(o); | |
266 break; | |
267 } | |
268 } | |
269 | |
270 SDL_NAME(pa_operation_unref)(o); | |
271 } | |
272 | |
197 | 273 |
198 | 274 |
199 static Uint8 * | 275 static Uint8 * |
200 PULSEAUDIO_GetDeviceBuf(_THIS) | 276 PULSEAUDIO_GetDeviceBuf(_THIS) |
201 { | 277 { |
210 if (this->hidden->mixbuf != NULL) { | 286 if (this->hidden->mixbuf != NULL) { |
211 SDL_FreeAudioMem(this->hidden->mixbuf); | 287 SDL_FreeAudioMem(this->hidden->mixbuf); |
212 this->hidden->mixbuf = NULL; | 288 this->hidden->mixbuf = NULL; |
213 } | 289 } |
214 if (this->hidden->stream) { | 290 if (this->hidden->stream) { |
215 SDL_NAME(pa_simple_drain) (this->hidden->stream, NULL); | 291 SDL_NAME(pa_stream_disconnect)(this->hidden->stream); |
216 SDL_NAME(pa_simple_free) (this->hidden->stream); | 292 SDL_NAME(pa_stream_unref)(this->hidden->stream); |
217 this->hidden->stream = NULL; | 293 this->hidden->stream = NULL; |
294 } | |
295 if (this->hidden->context != NULL) { | |
296 SDL_NAME(pa_context_disconnect)(this->hidden->context); | |
297 SDL_NAME(pa_context_unref)(this->hidden->context); | |
298 this->hidden->context = NULL; | |
299 } | |
300 if (this->hidden->mainloop != NULL) { | |
301 SDL_NAME(pa_mainloop_free)(this->hidden->mainloop); | |
302 this->hidden->mainloop = NULL; | |
218 } | 303 } |
219 SDL_free(this->hidden); | 304 SDL_free(this->hidden); |
220 this->hidden = NULL; | 305 this->hidden = NULL; |
221 } | 306 } |
222 } | 307 } |
225 /* !!! FIXME: this could probably be expanded. */ | 310 /* !!! FIXME: this could probably be expanded. */ |
226 /* Try to get the name of the program */ | 311 /* Try to get the name of the program */ |
227 static char * | 312 static char * |
228 get_progname(void) | 313 get_progname(void) |
229 { | 314 { |
315 #ifdef __LINUX__ | |
230 char *progname = NULL; | 316 char *progname = NULL; |
231 #ifdef __LINUX__ | |
232 FILE *fp; | 317 FILE *fp; |
233 static char temp[BUFSIZ]; | 318 static char temp[BUFSIZ]; |
234 | 319 |
235 SDL_snprintf(temp, SDL_arraysize(temp), "/proc/%d/cmdline", getpid()); | 320 SDL_snprintf(temp, SDL_arraysize(temp), "/proc/%d/cmdline", getpid()); |
236 fp = fopen(temp, "r"); | 321 fp = fopen(temp, "r"); |
243 progname = progname + 1; | 328 progname = progname + 1; |
244 } | 329 } |
245 } | 330 } |
246 fclose(fp); | 331 fclose(fp); |
247 } | 332 } |
333 return(progname); | |
334 #elif defined(__NetBSD__) | |
335 return getprogname(); | |
336 #else | |
337 return("unknown"); | |
248 #endif | 338 #endif |
249 return (progname); | |
250 } | 339 } |
251 | 340 |
252 | 341 |
253 static int | 342 static int |
254 PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) | 343 PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) |
255 { | 344 { |
256 Uint16 test_format = 0; | 345 Uint16 test_format = 0; |
257 pa_sample_spec paspec; | 346 pa_sample_spec paspec; |
258 pa_buffer_attr paattr; | 347 pa_buffer_attr paattr; |
259 pa_channel_map pacmap; | 348 pa_channel_map pacmap; |
260 int err = 0; | 349 pa_stream_flags_t flags = 0; |
350 int state = 0; | |
261 | 351 |
262 /* Initialize all variables that we clean on shutdown */ | 352 /* Initialize all variables that we clean on shutdown */ |
263 this->hidden = (struct SDL_PrivateAudioData *) | 353 this->hidden = (struct SDL_PrivateAudioData *) |
264 SDL_malloc((sizeof *this->hidden)); | 354 SDL_malloc((sizeof *this->hidden)); |
265 if (this->hidden == NULL) { | 355 if (this->hidden == NULL) { |
300 return 0; | 390 return 0; |
301 } | 391 } |
302 this->spec.format = test_format; | 392 this->spec.format = test_format; |
303 | 393 |
304 /* Calculate the final parameters for this audio specification */ | 394 /* Calculate the final parameters for this audio specification */ |
395 #ifdef PA_STREAM_ADJUST_LATENCY | |
396 this->spec.samples /= 2; /* Mix in smaller chunck to avoid underruns */ | |
397 #endif | |
305 SDL_CalculateAudioSpec(&this->spec); | 398 SDL_CalculateAudioSpec(&this->spec); |
306 | 399 |
307 /* Allocate mixing buffer */ | 400 /* Allocate mixing buffer */ |
308 this->hidden->mixlen = this->spec.size; | 401 this->hidden->mixlen = this->spec.size; |
309 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); | 402 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); |
316 | 409 |
317 paspec.channels = this->spec.channels; | 410 paspec.channels = this->spec.channels; |
318 paspec.rate = this->spec.freq; | 411 paspec.rate = this->spec.freq; |
319 | 412 |
320 /* Reduced prebuffering compared to the defaults. */ | 413 /* Reduced prebuffering compared to the defaults. */ |
321 paattr.tlength = this->hidden->mixlen; | 414 #ifdef PA_STREAM_ADJUST_LATENCY |
415 paattr.tlength = this->hidden->mixlen * 4; /* 2x original requested bufsize */ | |
416 paattr.prebuf = -1; | |
417 paattr.maxlength = -1; | |
418 /* -1 can lead to pa_stream_writable_size() >= this->hidden->mixlen never being true */ | |
322 paattr.minreq = this->hidden->mixlen; | 419 paattr.minreq = this->hidden->mixlen; |
323 paattr.fragsize = this->hidden->mixlen; | 420 flags = PA_STREAM_ADJUST_LATENCY; |
324 paattr.prebuf = this->hidden->mixlen; | 421 #else |
325 paattr.maxlength = this->hidden->mixlen * 4; | 422 paattr.tlength = this->hidden->mixlen*2; |
423 paattr.prebuf = this->hidden->mixlen*2; | |
424 paattr.maxlength = this->hidden->mixlen*2; | |
425 paattr.minreq = this->hidden->mixlen; | |
426 #endif | |
326 | 427 |
327 /* The SDL ALSA output hints us that we use Windows' channel mapping */ | 428 /* The SDL ALSA output hints us that we use Windows' channel mapping */ |
328 /* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */ | 429 /* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */ |
329 SDL_NAME(pa_channel_map_init_auto) (&pacmap, this->spec.channels, | 430 SDL_NAME(pa_channel_map_init_auto) (&pacmap, this->spec.channels, |
330 PA_CHANNEL_MAP_WAVEEX); | 431 PA_CHANNEL_MAP_WAVEEX); |
331 | 432 |
433 /* Set up a new main loop */ | |
434 if (!(this->hidden->mainloop = SDL_NAME(pa_mainloop_new)())) { | |
435 PULSEAUDIO_CloseDevice(this); | |
436 SDL_SetError("pa_mainloop_new() failed"); | |
437 return 0; | |
438 } | |
439 | |
440 this->hidden->mainloop_api = SDL_NAME(pa_mainloop_get_api)(this->hidden->mainloop); | |
441 if (!(this->hidden->context = SDL_NAME(pa_context_new)(this->hidden->mainloop_api, get_progname()))) { | |
442 PULSEAUDIO_CloseDevice(this); | |
443 SDL_SetError("pa_context_new() failed"); | |
444 return 0; | |
445 } | |
446 | |
332 /* Connect to the PulseAudio server */ | 447 /* Connect to the PulseAudio server */ |
333 this->hidden->stream = SDL_NAME(pa_simple_new) (SDL_getenv("PASERVER"), /* server */ | 448 if (SDL_NAME(pa_context_connect)(this->hidden->context, NULL, 0, NULL) < 0) { |
334 get_progname(), /* application name */ | 449 PULSEAUDIO_CloseDevice(this); |
335 PA_STREAM_PLAYBACK, /* playback mode */ | 450 SDL_SetError("Could not setup connection to PulseAudio"); |
336 SDL_getenv("PADEVICE"), /* device on the server */ | 451 return 0; |
337 "Simple DirectMedia Layer", /* stream description */ | 452 } |
338 &paspec, /* sample format spec */ | 453 |
339 &pacmap, /* channel map */ | 454 do { |
340 &paattr, /* buffering attributes */ | 455 if (SDL_NAME(pa_mainloop_iterate)(this->hidden->mainloop, 1, NULL) < 0) { |
341 &err /* error code */ | 456 PULSEAUDIO_CloseDevice(this); |
457 SDL_SetError("pa_mainloop_iterate() failed"); | |
458 return 0; | |
459 } | |
460 state = SDL_NAME(pa_context_get_state)(this->hidden->context); | |
461 if (!PA_CONTEXT_IS_GOOD(state)) { | |
462 PULSEAUDIO_CloseDevice(this); | |
463 SDL_SetError("Could not connect to PulseAudio"); | |
464 return 0; | |
465 } | |
466 } while (state != PA_CONTEXT_READY); | |
467 | |
468 this->hidden->stream = SDL_NAME(pa_stream_new)( | |
469 this->hidden->context, | |
470 "Simple DirectMedia Layer", /* stream description */ | |
471 &paspec, /* sample format spec */ | |
472 &pacmap /* channel map */ | |
342 ); | 473 ); |
343 | 474 |
344 if (this->hidden->stream == NULL) { | 475 if (this->hidden->stream == NULL) { |
345 PULSEAUDIO_CloseDevice(this); | 476 PULSEAUDIO_CloseDevice(this); |
346 SDL_SetError("Could not connect to PulseAudio: %s", | 477 SDL_SetError("Could not set up PulseAudio stream"); |
347 SDL_NAME(pa_strerror(err))); | 478 return 0; |
348 return 0; | 479 } |
349 } | 480 |
350 | 481 if (SDL_NAME(pa_stream_connect_playback)(this->hidden->stream, NULL, &paattr, flags, |
351 /* Get the parent process id (we're the parent of the audio thread) */ | 482 NULL, NULL) < 0) { |
352 this->hidden->parent = getpid(); | 483 PULSEAUDIO_CloseDevice(this); |
484 SDL_SetError("Could not connect PulseAudio stream"); | |
485 return 0; | |
486 } | |
487 | |
488 do { | |
489 if (SDL_NAME(pa_mainloop_iterate)(this->hidden->mainloop, 1, NULL) < 0) { | |
490 PULSEAUDIO_CloseDevice(this); | |
491 SDL_SetError("pa_mainloop_iterate() failed"); | |
492 return 0; | |
493 } | |
494 state = SDL_NAME(pa_stream_get_state)(this->hidden->stream); | |
495 if (!PA_STREAM_IS_GOOD(state)) { | |
496 PULSEAUDIO_CloseDevice(this); | |
497 SDL_SetError("Could not create to PulseAudio stream"); | |
498 return 0; | |
499 } | |
500 } while (state != PA_STREAM_READY); | |
353 | 501 |
354 /* We're ready to rock and roll. :-) */ | 502 /* We're ready to rock and roll. :-) */ |
355 return 1; | 503 return 1; |
356 } | 504 } |
357 | 505 |