Mercurial > sdl-ios-xcode
comparison src/audio/alsa/SDL_alsa_audio.c @ 1895:c121d94672cb
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 10 Jul 2006 21:04:37 +0000 |
parents | d7c9d7f42881 |
children | 3b4ce57c6215 |
comparison
equal
deleted
inserted
replaced
1894:c69cee13dd76 | 1895:c121d94672cb |
---|---|
22 #include "SDL_config.h" | 22 #include "SDL_config.h" |
23 | 23 |
24 /* Allow access to a raw mixing buffer */ | 24 /* Allow access to a raw mixing buffer */ |
25 | 25 |
26 #include <sys/types.h> | 26 #include <sys/types.h> |
27 #include <signal.h> /* For kill() */ | 27 #include <signal.h> /* For kill() */ |
28 | 28 |
29 #include "SDL_timer.h" | 29 #include "SDL_timer.h" |
30 #include "SDL_audio.h" | 30 #include "SDL_audio.h" |
31 #include "../SDL_audiomem.h" | 31 #include "../SDL_audiomem.h" |
32 #include "../SDL_audio_c.h" | 32 #include "../SDL_audio_c.h" |
46 | 46 |
47 /* The default ALSA audio driver */ | 47 /* The default ALSA audio driver */ |
48 #define DEFAULT_DEVICE "default" | 48 #define DEFAULT_DEVICE "default" |
49 | 49 |
50 /* Audio driver functions */ | 50 /* Audio driver functions */ |
51 static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec); | 51 static int ALSA_OpenAudio(_THIS, SDL_AudioSpec * spec); |
52 static void ALSA_WaitAudio(_THIS); | 52 static void ALSA_WaitAudio(_THIS); |
53 static void ALSA_PlayAudio(_THIS); | 53 static void ALSA_PlayAudio(_THIS); |
54 static Uint8 *ALSA_GetAudioBuf(_THIS); | 54 static Uint8 *ALSA_GetAudioBuf(_THIS); |
55 static void ALSA_CloseAudio(_THIS); | 55 static void ALSA_CloseAudio(_THIS); |
56 | 56 |
58 | 58 |
59 static const char *alsa_library = SDL_AUDIO_DRIVER_ALSA_DYNAMIC; | 59 static const char *alsa_library = SDL_AUDIO_DRIVER_ALSA_DYNAMIC; |
60 static void *alsa_handle = NULL; | 60 static void *alsa_handle = NULL; |
61 static int alsa_loaded = 0; | 61 static int alsa_loaded = 0; |
62 | 62 |
63 static int (*SDL_snd_pcm_open)(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode); | 63 static int (*SDL_snd_pcm_open) (snd_pcm_t ** pcm, const char *name, |
64 static int (*SDL_NAME(snd_pcm_open))(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode); | 64 snd_pcm_stream_t stream, int mode); |
65 static int (*SDL_NAME(snd_pcm_close))(snd_pcm_t *pcm); | 65 static int (*SDL_NAME(snd_pcm_open)) (snd_pcm_t ** pcm, const char *name, |
66 static snd_pcm_sframes_t (*SDL_NAME(snd_pcm_writei))(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size); | 66 snd_pcm_stream_t stream, int mode); |
67 static int (*SDL_NAME(snd_pcm_resume))(snd_pcm_t *pcm); | 67 static int (*SDL_NAME(snd_pcm_close)) (snd_pcm_t * pcm); |
68 static int (*SDL_NAME(snd_pcm_prepare))(snd_pcm_t *pcm); | 68 static snd_pcm_sframes_t(*SDL_NAME(snd_pcm_writei)) (snd_pcm_t * pcm, |
69 static int (*SDL_NAME(snd_pcm_drain))(snd_pcm_t *pcm); | 69 const void *buffer, |
70 static const char *(*SDL_NAME(snd_strerror))(int errnum); | 70 snd_pcm_uframes_t size); |
71 static size_t (*SDL_NAME(snd_pcm_hw_params_sizeof))(void); | 71 static int (*SDL_NAME(snd_pcm_resume)) (snd_pcm_t * pcm); |
72 static size_t (*SDL_NAME(snd_pcm_sw_params_sizeof))(void); | 72 static int (*SDL_NAME(snd_pcm_prepare)) (snd_pcm_t * pcm); |
73 static int (*SDL_NAME(snd_pcm_hw_params_any))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); | 73 static int (*SDL_NAME(snd_pcm_drain)) (snd_pcm_t * pcm); |
74 static int (*SDL_NAME(snd_pcm_hw_params_set_access))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access); | 74 static const char *(*SDL_NAME(snd_strerror)) (int errnum); |
75 static int (*SDL_NAME(snd_pcm_hw_params_set_format))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val); | 75 static size_t(*SDL_NAME(snd_pcm_hw_params_sizeof)) (void); |
76 static int (*SDL_NAME(snd_pcm_hw_params_set_channels))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val); | 76 static size_t(*SDL_NAME(snd_pcm_sw_params_sizeof)) (void); |
77 static int (*SDL_NAME(snd_pcm_hw_params_get_channels))(const snd_pcm_hw_params_t *params); | 77 static int (*SDL_NAME(snd_pcm_hw_params_any)) (snd_pcm_t * pcm, |
78 static unsigned int (*SDL_NAME(snd_pcm_hw_params_set_rate_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int *dir); | 78 snd_pcm_hw_params_t * params); |
79 static snd_pcm_uframes_t (*SDL_NAME(snd_pcm_hw_params_set_period_size_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val, int *dir); | 79 static int (*SDL_NAME(snd_pcm_hw_params_set_access)) (snd_pcm_t * pcm, |
80 static snd_pcm_sframes_t (*SDL_NAME(snd_pcm_hw_params_get_period_size))(const snd_pcm_hw_params_t *params); | 80 snd_pcm_hw_params_t * |
81 static unsigned int (*SDL_NAME(snd_pcm_hw_params_set_periods_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int *dir); | 81 params, |
82 static int (*SDL_NAME(snd_pcm_hw_params_get_periods))(snd_pcm_hw_params_t *params); | 82 snd_pcm_access_t |
83 static int (*SDL_NAME(snd_pcm_hw_params))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); | 83 access); |
84 static int (*SDL_NAME(snd_pcm_hw_params_set_format)) (snd_pcm_t * pcm, | |
85 snd_pcm_hw_params_t * | |
86 params, | |
87 snd_pcm_format_t val); | |
88 static int (*SDL_NAME(snd_pcm_hw_params_set_channels)) (snd_pcm_t * pcm, | |
89 snd_pcm_hw_params_t * | |
90 params, | |
91 unsigned int val); | |
92 static int (*SDL_NAME(snd_pcm_hw_params_get_channels)) (const | |
93 snd_pcm_hw_params_t * | |
94 params); | |
95 static unsigned int | |
96 (*SDL_NAME(snd_pcm_hw_params_set_rate_near)) (snd_pcm_t * | |
97 pcm, | |
98 snd_pcm_hw_params_t | |
99 * params, | |
100 unsigned int val, int *dir); | |
101 static snd_pcm_uframes_t | |
102 (*SDL_NAME(snd_pcm_hw_params_set_period_size_near)) (snd_pcm_t * pcm, | |
103 snd_pcm_hw_params_t | |
104 * params, | |
105 snd_pcm_uframes_t | |
106 val, int *dir); | |
107 static snd_pcm_sframes_t | |
108 (*SDL_NAME(snd_pcm_hw_params_get_period_size)) (const | |
109 snd_pcm_hw_params_t | |
110 * params); | |
111 static unsigned int | |
112 (*SDL_NAME(snd_pcm_hw_params_set_periods_near)) (snd_pcm_t * pcm, | |
113 snd_pcm_hw_params_t | |
114 * params, | |
115 unsigned int val, | |
116 int *dir); | |
117 static int (*SDL_NAME(snd_pcm_hw_params_get_periods)) (snd_pcm_hw_params_t * | |
118 params); | |
119 static int (*SDL_NAME(snd_pcm_hw_params)) (snd_pcm_t * pcm, | |
120 snd_pcm_hw_params_t * params); | |
84 /* | 121 /* |
85 */ | 122 */ |
86 static int (*SDL_NAME(snd_pcm_sw_params_current))(snd_pcm_t *pcm, snd_pcm_sw_params_t *swparams); | 123 static int (*SDL_NAME(snd_pcm_sw_params_current)) (snd_pcm_t * pcm, |
87 static int (*SDL_NAME(snd_pcm_sw_params_set_start_threshold))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val); | 124 snd_pcm_sw_params_t * |
88 static int (*SDL_NAME(snd_pcm_sw_params_set_avail_min))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val); | 125 swparams); |
89 static int (*SDL_NAME(snd_pcm_sw_params))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params); | 126 static int (*SDL_NAME(snd_pcm_sw_params_set_start_threshold)) (snd_pcm_t * |
90 static int (*SDL_NAME(snd_pcm_nonblock))(snd_pcm_t *pcm, int nonblock); | 127 pcm, |
128 snd_pcm_sw_params_t | |
129 * params, | |
130 snd_pcm_uframes_t | |
131 val); | |
132 static int (*SDL_NAME(snd_pcm_sw_params_set_avail_min)) (snd_pcm_t * pcm, | |
133 snd_pcm_sw_params_t | |
134 * params, | |
135 snd_pcm_uframes_t | |
136 val); | |
137 static int (*SDL_NAME(snd_pcm_sw_params)) (snd_pcm_t * pcm, | |
138 snd_pcm_sw_params_t * params); | |
139 static int (*SDL_NAME(snd_pcm_nonblock)) (snd_pcm_t * pcm, int nonblock); | |
91 #define snd_pcm_hw_params_sizeof SDL_NAME(snd_pcm_hw_params_sizeof) | 140 #define snd_pcm_hw_params_sizeof SDL_NAME(snd_pcm_hw_params_sizeof) |
92 #define snd_pcm_sw_params_sizeof SDL_NAME(snd_pcm_sw_params_sizeof) | 141 #define snd_pcm_sw_params_sizeof SDL_NAME(snd_pcm_sw_params_sizeof) |
93 | 142 |
94 /* cast funcs to char* first, to please GCC's strict aliasing rules. */ | 143 /* cast funcs to char* first, to please GCC's strict aliasing rules. */ |
95 static struct { | 144 static struct |
96 const char *name; | 145 { |
97 void **func; | 146 const char *name; |
147 void **func; | |
98 } alsa_functions[] = { | 148 } alsa_functions[] = { |
99 { "snd_pcm_open", (void**)(char*)&SDL_NAME(snd_pcm_open) }, | 149 { |
100 { "snd_pcm_close", (void**)(char*)&SDL_NAME(snd_pcm_close) }, | 150 "snd_pcm_open", (void **) (char *) &SDL_NAME(snd_pcm_open)}, { |
101 { "snd_pcm_writei", (void**)(char*)&SDL_NAME(snd_pcm_writei) }, | 151 "snd_pcm_close", (void **) (char *) &SDL_NAME(snd_pcm_close)}, { |
102 { "snd_pcm_resume", (void**)(char*)&SDL_NAME(snd_pcm_resume) }, | 152 "snd_pcm_writei", (void **) (char *) &SDL_NAME(snd_pcm_writei)}, { |
103 { "snd_pcm_prepare", (void**)(char*)&SDL_NAME(snd_pcm_prepare) }, | 153 "snd_pcm_resume", (void **) (char *) &SDL_NAME(snd_pcm_resume)}, { |
104 { "snd_pcm_drain", (void**)(char*)&SDL_NAME(snd_pcm_drain) }, | 154 "snd_pcm_prepare", (void **) (char *) &SDL_NAME(snd_pcm_prepare)}, { |
105 { "snd_strerror", (void**)(char*)&SDL_NAME(snd_strerror) }, | 155 "snd_pcm_drain", (void **) (char *) &SDL_NAME(snd_pcm_drain)}, { |
106 { "snd_pcm_hw_params_sizeof", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_sizeof) }, | 156 "snd_strerror", (void **) (char *) &SDL_NAME(snd_strerror)}, { |
107 { "snd_pcm_sw_params_sizeof", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_sizeof) }, | 157 "snd_pcm_hw_params_sizeof", |
108 { "snd_pcm_hw_params_any", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_any) }, | 158 (void **) (char *) &SDL_NAME(snd_pcm_hw_params_sizeof)}, { |
109 { "snd_pcm_hw_params_set_access", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_access) }, | 159 "snd_pcm_sw_params_sizeof", |
110 { "snd_pcm_hw_params_set_format", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_format) }, | 160 (void **) (char *) &SDL_NAME(snd_pcm_sw_params_sizeof)}, { |
111 { "snd_pcm_hw_params_set_channels", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_channels) }, | 161 "snd_pcm_hw_params_any", |
112 { "snd_pcm_hw_params_get_channels", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_channels) }, | 162 (void **) (char *) &SDL_NAME(snd_pcm_hw_params_any)}, { |
113 { "snd_pcm_hw_params_set_rate_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_rate_near) }, | 163 "snd_pcm_hw_params_set_access", |
114 { "snd_pcm_hw_params_set_period_size_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_period_size_near) }, | 164 (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_access)}, { |
115 { "snd_pcm_hw_params_get_period_size", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_period_size) }, | 165 "snd_pcm_hw_params_set_format", |
116 { "snd_pcm_hw_params_set_periods_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_periods_near) }, | 166 (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_format)}, { |
117 { "snd_pcm_hw_params_get_periods", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_periods) }, | 167 "snd_pcm_hw_params_set_channels", |
118 { "snd_pcm_hw_params", (void**)(char*)&SDL_NAME(snd_pcm_hw_params) }, | 168 (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_channels)}, { |
119 { "snd_pcm_sw_params_current", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_current) }, | 169 "snd_pcm_hw_params_get_channels", |
120 { "snd_pcm_sw_params_set_start_threshold", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_set_start_threshold) }, | 170 (void **) (char *) &SDL_NAME(snd_pcm_hw_params_get_channels)}, { |
121 { "snd_pcm_sw_params_set_avail_min", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_set_avail_min) }, | 171 "snd_pcm_hw_params_set_rate_near", |
122 { "snd_pcm_sw_params", (void**)(char*)&SDL_NAME(snd_pcm_sw_params) }, | 172 (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_rate_near)}, { |
123 { "snd_pcm_nonblock", (void**)(char*)&SDL_NAME(snd_pcm_nonblock) }, | 173 "snd_pcm_hw_params_set_period_size_near", (void **) (char *) |
124 }; | 174 &SDL_NAME(snd_pcm_hw_params_set_period_size_near)}, { |
125 | 175 "snd_pcm_hw_params_get_period_size", |
126 static void UnloadALSALibrary(void) { | 176 (void **) (char *) &SDL_NAME(snd_pcm_hw_params_get_period_size)}, |
127 if (alsa_loaded) { | 177 { |
178 "snd_pcm_hw_params_set_periods_near", (void **) (char *) | |
179 &SDL_NAME(snd_pcm_hw_params_set_periods_near)}, { | |
180 "snd_pcm_hw_params_get_periods", | |
181 (void **) (char *) &SDL_NAME(snd_pcm_hw_params_get_periods)}, { | |
182 "snd_pcm_hw_params", (void **) (char *) &SDL_NAME(snd_pcm_hw_params)}, { | |
183 "snd_pcm_sw_params_current", | |
184 (void **) (char *) &SDL_NAME(snd_pcm_sw_params_current)}, { | |
185 "snd_pcm_sw_params_set_start_threshold", (void **) (char *) | |
186 &SDL_NAME(snd_pcm_sw_params_set_start_threshold)}, { | |
187 "snd_pcm_sw_params_set_avail_min", | |
188 (void **) (char *) &SDL_NAME(snd_pcm_sw_params_set_avail_min)}, { | |
189 "snd_pcm_sw_params", (void **) (char *) &SDL_NAME(snd_pcm_sw_params)}, { | |
190 "snd_pcm_nonblock", (void **) (char *) &SDL_NAME(snd_pcm_nonblock)},}; | |
191 | |
192 static void | |
193 UnloadALSALibrary(void) | |
194 { | |
195 if (alsa_loaded) { | |
128 /* SDL_UnloadObject(alsa_handle);*/ | 196 /* SDL_UnloadObject(alsa_handle);*/ |
129 dlclose(alsa_handle); | 197 dlclose(alsa_handle); |
130 alsa_handle = NULL; | 198 alsa_handle = NULL; |
131 alsa_loaded = 0; | 199 alsa_loaded = 0; |
132 } | 200 } |
133 } | 201 } |
134 | 202 |
135 static int LoadALSALibrary(void) { | 203 static int |
136 int i, retval = -1; | 204 LoadALSALibrary(void) |
205 { | |
206 int i, retval = -1; | |
137 | 207 |
138 /* alsa_handle = SDL_LoadObject(alsa_library);*/ | 208 /* alsa_handle = SDL_LoadObject(alsa_library);*/ |
139 alsa_handle = dlopen(alsa_library,RTLD_NOW); | 209 alsa_handle = dlopen(alsa_library, RTLD_NOW); |
140 if (alsa_handle) { | 210 if (alsa_handle) { |
141 alsa_loaded = 1; | 211 alsa_loaded = 1; |
142 retval = 0; | 212 retval = 0; |
143 for (i = 0; i < SDL_arraysize(alsa_functions); i++) { | 213 for (i = 0; i < SDL_arraysize(alsa_functions); i++) { |
144 /* *alsa_functions[i].func = SDL_LoadFunction(alsa_handle,alsa_functions[i].name);*/ | 214 /* *alsa_functions[i].func = SDL_LoadFunction(alsa_handle,alsa_functions[i].name);*/ |
145 #if HAVE_DLVSYM | 215 #if HAVE_DLVSYM |
146 *alsa_functions[i].func = dlvsym(alsa_handle,alsa_functions[i].name,"ALSA_0.9"); | 216 *alsa_functions[i].func = |
147 if (!*alsa_functions[i].func) | 217 dlvsym(alsa_handle, alsa_functions[i].name, "ALSA_0.9"); |
218 if (!*alsa_functions[i].func) | |
148 #endif | 219 #endif |
149 *alsa_functions[i].func = dlsym(alsa_handle,alsa_functions[i].name); | 220 *alsa_functions[i].func = |
150 if (!*alsa_functions[i].func) { | 221 dlsym(alsa_handle, alsa_functions[i].name); |
151 retval = -1; | 222 if (!*alsa_functions[i].func) { |
152 UnloadALSALibrary(); | 223 retval = -1; |
153 break; | 224 UnloadALSALibrary(); |
154 } | 225 break; |
155 } | 226 } |
156 } | 227 } |
157 return retval; | 228 } |
229 return retval; | |
158 } | 230 } |
159 | 231 |
160 #else | 232 #else |
161 | 233 |
162 static void UnloadALSALibrary(void) { | 234 static void |
163 return; | 235 UnloadALSALibrary(void) |
164 } | 236 { |
165 | 237 return; |
166 static int LoadALSALibrary(void) { | 238 } |
167 return 0; | 239 |
240 static int | |
241 LoadALSALibrary(void) | |
242 { | |
243 return 0; | |
168 } | 244 } |
169 | 245 |
170 #endif /* SDL_AUDIO_DRIVER_ALSA_DYNAMIC */ | 246 #endif /* SDL_AUDIO_DRIVER_ALSA_DYNAMIC */ |
171 | 247 |
172 static const char *get_audio_device(int channels) | 248 static const char * |
173 { | 249 get_audio_device(int channels) |
174 const char *device; | 250 { |
175 | 251 const char *device; |
176 device = SDL_getenv("AUDIODEV"); /* Is there a standard variable name? */ | 252 |
177 if ( device == NULL ) { | 253 device = SDL_getenv("AUDIODEV"); /* Is there a standard variable name? */ |
178 if (channels == 6) device = "surround51"; | 254 if (device == NULL) { |
179 else if (channels == 4) device = "surround40"; | 255 if (channels == 6) |
180 else device = DEFAULT_DEVICE; | 256 device = "surround51"; |
181 } | 257 else if (channels == 4) |
182 return device; | 258 device = "surround40"; |
259 else | |
260 device = DEFAULT_DEVICE; | |
261 } | |
262 return device; | |
183 } | 263 } |
184 | 264 |
185 /* Audio driver bootstrap functions */ | 265 /* Audio driver bootstrap functions */ |
186 | 266 |
187 static int Audio_Available(void) | 267 static int |
188 { | 268 Audio_Available(void) |
189 int available; | 269 { |
190 int status; | 270 int available; |
191 snd_pcm_t *handle; | 271 int status; |
192 | 272 snd_pcm_t *handle; |
193 available = 0; | 273 |
194 if (LoadALSALibrary() < 0) { | 274 available = 0; |
195 return available; | 275 if (LoadALSALibrary() < 0) { |
196 } | 276 return available; |
197 status = SDL_NAME(snd_pcm_open)(&handle, get_audio_device(2), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); | 277 } |
198 if ( status >= 0 ) { | 278 status = |
199 available = 1; | 279 SDL_NAME(snd_pcm_open) (&handle, get_audio_device(2), |
200 SDL_NAME(snd_pcm_close)(handle); | 280 SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); |
201 } | 281 if (status >= 0) { |
202 UnloadALSALibrary(); | 282 available = 1; |
203 return(available); | 283 SDL_NAME(snd_pcm_close) (handle); |
204 } | 284 } |
205 | 285 UnloadALSALibrary(); |
206 static void Audio_DeleteDevice(SDL_AudioDevice *device) | 286 return (available); |
207 { | 287 } |
208 SDL_free(device->hidden); | 288 |
209 SDL_free(device); | 289 static void |
210 UnloadALSALibrary(); | 290 Audio_DeleteDevice(SDL_AudioDevice * device) |
211 } | 291 { |
212 | 292 SDL_free(device->hidden); |
213 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | 293 SDL_free(device); |
214 { | 294 UnloadALSALibrary(); |
215 SDL_AudioDevice *this; | 295 } |
216 | 296 |
217 /* Initialize all variables that we clean on shutdown */ | 297 static SDL_AudioDevice * |
218 LoadALSALibrary(); | 298 Audio_CreateDevice(int devindex) |
219 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); | 299 { |
220 if ( this ) { | 300 SDL_AudioDevice *this; |
221 SDL_memset(this, 0, (sizeof *this)); | 301 |
222 this->hidden = (struct SDL_PrivateAudioData *) | 302 /* Initialize all variables that we clean on shutdown */ |
223 SDL_malloc((sizeof *this->hidden)); | 303 LoadALSALibrary(); |
224 } | 304 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); |
225 if ( (this == NULL) || (this->hidden == NULL) ) { | 305 if (this) { |
226 SDL_OutOfMemory(); | 306 SDL_memset(this, 0, (sizeof *this)); |
227 if ( this ) { | 307 this->hidden = (struct SDL_PrivateAudioData *) |
228 SDL_free(this); | 308 SDL_malloc((sizeof *this->hidden)); |
229 } | 309 } |
230 return(0); | 310 if ((this == NULL) || (this->hidden == NULL)) { |
231 } | 311 SDL_OutOfMemory(); |
232 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | 312 if (this) { |
233 | 313 SDL_free(this); |
234 /* Set the function pointers */ | 314 } |
235 this->OpenAudio = ALSA_OpenAudio; | 315 return (0); |
236 this->WaitAudio = ALSA_WaitAudio; | 316 } |
237 this->PlayAudio = ALSA_PlayAudio; | 317 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); |
238 this->GetAudioBuf = ALSA_GetAudioBuf; | 318 |
239 this->CloseAudio = ALSA_CloseAudio; | 319 /* Set the function pointers */ |
240 | 320 this->OpenAudio = ALSA_OpenAudio; |
241 this->free = Audio_DeleteDevice; | 321 this->WaitAudio = ALSA_WaitAudio; |
242 | 322 this->PlayAudio = ALSA_PlayAudio; |
243 return this; | 323 this->GetAudioBuf = ALSA_GetAudioBuf; |
324 this->CloseAudio = ALSA_CloseAudio; | |
325 | |
326 this->free = Audio_DeleteDevice; | |
327 | |
328 return this; | |
244 } | 329 } |
245 | 330 |
246 AudioBootStrap ALSA_bootstrap = { | 331 AudioBootStrap ALSA_bootstrap = { |
247 DRIVER_NAME, "ALSA 0.9 PCM audio", | 332 DRIVER_NAME, "ALSA 0.9 PCM audio", |
248 Audio_Available, Audio_CreateDevice | 333 Audio_Available, Audio_CreateDevice |
249 }; | 334 }; |
250 | 335 |
251 /* This function waits until it is possible to write a full sound buffer */ | 336 /* This function waits until it is possible to write a full sound buffer */ |
252 static void ALSA_WaitAudio(_THIS) | 337 static void |
253 { | 338 ALSA_WaitAudio(_THIS) |
254 /* Check to see if the thread-parent process is still alive */ | 339 { |
255 { static int cnt = 0; | 340 /* Check to see if the thread-parent process is still alive */ |
256 /* Note that this only works with thread implementations | 341 { |
257 that use a different process id for each thread. | 342 static int cnt = 0; |
258 */ | 343 /* Note that this only works with thread implementations |
259 if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */ | 344 that use a different process id for each thread. |
260 if ( kill(parent, 0) < 0 ) { | 345 */ |
261 this->enabled = 0; | 346 if (parent && (((++cnt) % 10) == 0)) { /* Check every 10 loops */ |
262 } | 347 if (kill(parent, 0) < 0) { |
263 } | 348 this->enabled = 0; |
264 } | 349 } |
350 } | |
351 } | |
265 } | 352 } |
266 | 353 |
267 | 354 |
268 /* | 355 /* |
269 * http://bugzilla.libsdl.org/show_bug.cgi?id=110 | 356 * http://bugzilla.libsdl.org/show_bug.cgi?id=110 |
278 T tmp; \ | 365 T tmp; \ |
279 tmp = ptr[2]; ptr[2] = ptr[4]; ptr[4] = tmp; \ | 366 tmp = ptr[2]; ptr[2] = ptr[4]; ptr[4] = tmp; \ |
280 tmp = ptr[3]; ptr[3] = ptr[5]; ptr[5] = tmp; \ | 367 tmp = ptr[3]; ptr[3] = ptr[5]; ptr[5] = tmp; \ |
281 } | 368 } |
282 | 369 |
283 static __inline__ void swizzle_alsa_channels_6_64bit(_THIS) { SWIZ6(Uint64); } | 370 static __inline__ void |
284 static __inline__ void swizzle_alsa_channels_6_32bit(_THIS) { SWIZ6(Uint32); } | 371 swizzle_alsa_channels_6_64bit(_THIS) |
285 static __inline__ void swizzle_alsa_channels_6_16bit(_THIS) { SWIZ6(Uint16); } | 372 { |
286 static __inline__ void swizzle_alsa_channels_6_8bit(_THIS) { SWIZ6(Uint8); } | 373 SWIZ6(Uint64); |
374 } | |
375 static __inline__ void | |
376 swizzle_alsa_channels_6_32bit(_THIS) | |
377 { | |
378 SWIZ6(Uint32); | |
379 } | |
380 static __inline__ void | |
381 swizzle_alsa_channels_6_16bit(_THIS) | |
382 { | |
383 SWIZ6(Uint16); | |
384 } | |
385 static __inline__ void | |
386 swizzle_alsa_channels_6_8bit(_THIS) | |
387 { | |
388 SWIZ6(Uint8); | |
389 } | |
287 | 390 |
288 #undef SWIZ6 | 391 #undef SWIZ6 |
289 | 392 |
290 | 393 |
291 /* | 394 /* |
292 * Called right before feeding this->mixbuf to the hardware. Swizzle channels | 395 * Called right before feeding this->mixbuf to the hardware. Swizzle channels |
293 * from Windows/Mac order to the format alsalib will want. | 396 * from Windows/Mac order to the format alsalib will want. |
294 */ | 397 */ |
295 static __inline__ void swizzle_alsa_channels(_THIS) | 398 static __inline__ void |
399 swizzle_alsa_channels(_THIS) | |
296 { | 400 { |
297 if (this->spec.channels == 6) { | 401 if (this->spec.channels == 6) { |
298 const Uint16 fmtsize = (this->spec.format & 0xFF); /* bits/channel. */ | 402 const Uint16 fmtsize = (this->spec.format & 0xFF); /* bits/channel. */ |
299 if (fmtsize == 16) | 403 if (fmtsize == 16) |
300 swizzle_alsa_channels_6_16bit(this); | 404 swizzle_alsa_channels_6_16bit(this); |
301 else if (fmtsize == 8) | 405 else if (fmtsize == 8) |
302 swizzle_alsa_channels_6_8bit(this); | 406 swizzle_alsa_channels_6_8bit(this); |
303 else if (fmtsize == 32) | 407 else if (fmtsize == 32) |
308 | 412 |
309 /* !!! FIXME: update this for 7.1 if needed, later. */ | 413 /* !!! FIXME: update this for 7.1 if needed, later. */ |
310 } | 414 } |
311 | 415 |
312 | 416 |
313 static void ALSA_PlayAudio(_THIS) | 417 static void |
314 { | 418 ALSA_PlayAudio(_THIS) |
315 int status; | 419 { |
316 int sample_len; | 420 int status; |
317 signed short *sample_buf; | 421 int sample_len; |
318 | 422 signed short *sample_buf; |
319 swizzle_alsa_channels(this); | 423 |
320 | 424 swizzle_alsa_channels(this); |
321 sample_len = this->spec.samples; | 425 |
322 sample_buf = (signed short *)mixbuf; | 426 sample_len = this->spec.samples; |
323 | 427 sample_buf = (signed short *) mixbuf; |
324 while ( sample_len > 0 ) { | 428 |
325 status = SDL_NAME(snd_pcm_writei)(pcm_handle, sample_buf, sample_len); | 429 while (sample_len > 0) { |
326 if ( status < 0 ) { | 430 status = |
327 if ( status == -EAGAIN ) { | 431 SDL_NAME(snd_pcm_writei) (pcm_handle, sample_buf, sample_len); |
328 SDL_Delay(1); | 432 if (status < 0) { |
329 continue; | 433 if (status == -EAGAIN) { |
330 } | 434 SDL_Delay(1); |
331 if ( status == -ESTRPIPE ) { | 435 continue; |
332 do { | 436 } |
333 SDL_Delay(1); | 437 if (status == -ESTRPIPE) { |
334 status = SDL_NAME(snd_pcm_resume)(pcm_handle); | 438 do { |
335 } while ( status == -EAGAIN ); | 439 SDL_Delay(1); |
336 } | 440 status = SDL_NAME(snd_pcm_resume) (pcm_handle); |
337 if ( status < 0 ) { | 441 } while (status == -EAGAIN); |
338 status = SDL_NAME(snd_pcm_prepare)(pcm_handle); | 442 } |
339 } | 443 if (status < 0) { |
340 if ( status < 0 ) { | 444 status = SDL_NAME(snd_pcm_prepare) (pcm_handle); |
341 /* Hmm, not much we can do - abort */ | 445 } |
342 this->enabled = 0; | 446 if (status < 0) { |
343 return; | 447 /* Hmm, not much we can do - abort */ |
344 } | 448 this->enabled = 0; |
345 continue; | 449 return; |
346 } | 450 } |
347 sample_buf += status * this->spec.channels; | 451 continue; |
348 sample_len -= status; | 452 } |
349 } | 453 sample_buf += status * this->spec.channels; |
350 } | 454 sample_len -= status; |
351 | 455 } |
352 static Uint8 *ALSA_GetAudioBuf(_THIS) | 456 } |
353 { | 457 |
354 return(mixbuf); | 458 static Uint8 * |
355 } | 459 ALSA_GetAudioBuf(_THIS) |
356 | 460 { |
357 static void ALSA_CloseAudio(_THIS) | 461 return (mixbuf); |
358 { | 462 } |
359 if ( mixbuf != NULL ) { | 463 |
360 SDL_FreeAudioMem(mixbuf); | 464 static void |
361 mixbuf = NULL; | 465 ALSA_CloseAudio(_THIS) |
362 } | 466 { |
363 if ( pcm_handle ) { | 467 if (mixbuf != NULL) { |
364 SDL_NAME(snd_pcm_drain)(pcm_handle); | 468 SDL_FreeAudioMem(mixbuf); |
365 SDL_NAME(snd_pcm_close)(pcm_handle); | 469 mixbuf = NULL; |
366 pcm_handle = NULL; | 470 } |
367 } | 471 if (pcm_handle) { |
368 } | 472 SDL_NAME(snd_pcm_drain) (pcm_handle); |
369 | 473 SDL_NAME(snd_pcm_close) (pcm_handle); |
370 static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec) | 474 pcm_handle = NULL; |
371 { | 475 } |
372 int status; | 476 } |
373 snd_pcm_hw_params_t *hwparams; | 477 |
374 snd_pcm_sw_params_t *swparams; | 478 static int |
375 snd_pcm_format_t format; | 479 ALSA_OpenAudio(_THIS, SDL_AudioSpec * spec) |
376 snd_pcm_uframes_t frames; | 480 { |
377 Uint16 test_format; | 481 int status; |
378 | 482 snd_pcm_hw_params_t *hwparams; |
379 /* Open the audio device */ | 483 snd_pcm_sw_params_t *swparams; |
380 /* Name of device should depend on # channels in spec */ | 484 snd_pcm_format_t format; |
381 status = SDL_NAME(snd_pcm_open)(&pcm_handle, get_audio_device(spec->channels), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); | 485 snd_pcm_uframes_t frames; |
382 | 486 Uint16 test_format; |
383 if ( status < 0 ) { | 487 |
384 SDL_SetError("Couldn't open audio device: %s", SDL_NAME(snd_strerror)(status)); | 488 /* Open the audio device */ |
385 return(-1); | 489 /* Name of device should depend on # channels in spec */ |
386 } | 490 status = |
387 | 491 SDL_NAME(snd_pcm_open) (&pcm_handle, |
388 /* Figure out what the hardware is capable of */ | 492 get_audio_device(spec->channels), |
389 snd_pcm_hw_params_alloca(&hwparams); | 493 SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); |
390 status = SDL_NAME(snd_pcm_hw_params_any)(pcm_handle, hwparams); | 494 |
391 if ( status < 0 ) { | 495 if (status < 0) { |
392 SDL_SetError("Couldn't get hardware config: %s", SDL_NAME(snd_strerror)(status)); | 496 SDL_SetError("Couldn't open audio device: %s", |
393 ALSA_CloseAudio(this); | 497 SDL_NAME(snd_strerror) (status)); |
394 return(-1); | 498 return (-1); |
395 } | 499 } |
396 | 500 |
397 /* SDL only uses interleaved sample output */ | 501 /* Figure out what the hardware is capable of */ |
398 status = SDL_NAME(snd_pcm_hw_params_set_access)(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); | 502 snd_pcm_hw_params_alloca(&hwparams); |
399 if ( status < 0 ) { | 503 status = SDL_NAME(snd_pcm_hw_params_any) (pcm_handle, hwparams); |
400 SDL_SetError("Couldn't set interleaved access: %s", SDL_NAME(snd_strerror)(status)); | 504 if (status < 0) { |
401 ALSA_CloseAudio(this); | 505 SDL_SetError("Couldn't get hardware config: %s", |
402 return(-1); | 506 SDL_NAME(snd_strerror) (status)); |
403 } | 507 ALSA_CloseAudio(this); |
404 | 508 return (-1); |
405 /* Try for a closest match on audio format */ | 509 } |
406 status = -1; | 510 |
407 for ( test_format = SDL_FirstAudioFormat(spec->format); | 511 /* SDL only uses interleaved sample output */ |
408 test_format && (status < 0); ) { | 512 status = |
409 switch ( test_format ) { | 513 SDL_NAME(snd_pcm_hw_params_set_access) (pcm_handle, hwparams, |
410 case AUDIO_U8: | 514 SND_PCM_ACCESS_RW_INTERLEAVED); |
411 format = SND_PCM_FORMAT_U8; | 515 if (status < 0) { |
412 break; | 516 SDL_SetError("Couldn't set interleaved access: %s", |
413 case AUDIO_S8: | 517 SDL_NAME(snd_strerror) (status)); |
414 format = SND_PCM_FORMAT_S8; | 518 ALSA_CloseAudio(this); |
415 break; | 519 return (-1); |
416 case AUDIO_S16LSB: | 520 } |
417 format = SND_PCM_FORMAT_S16_LE; | 521 |
418 break; | 522 /* Try for a closest match on audio format */ |
419 case AUDIO_S16MSB: | 523 status = -1; |
420 format = SND_PCM_FORMAT_S16_BE; | 524 for (test_format = SDL_FirstAudioFormat(spec->format); |
421 break; | 525 test_format && (status < 0);) { |
422 case AUDIO_U16LSB: | 526 switch (test_format) { |
423 format = SND_PCM_FORMAT_U16_LE; | 527 case AUDIO_U8: |
424 break; | 528 format = SND_PCM_FORMAT_U8; |
425 case AUDIO_U16MSB: | 529 break; |
426 format = SND_PCM_FORMAT_U16_BE; | 530 case AUDIO_S8: |
427 break; | 531 format = SND_PCM_FORMAT_S8; |
428 default: | 532 break; |
429 format = 0; | 533 case AUDIO_S16LSB: |
430 break; | 534 format = SND_PCM_FORMAT_S16_LE; |
431 } | 535 break; |
432 if ( format != 0 ) { | 536 case AUDIO_S16MSB: |
433 status = SDL_NAME(snd_pcm_hw_params_set_format)(pcm_handle, hwparams, format); | 537 format = SND_PCM_FORMAT_S16_BE; |
434 } | 538 break; |
435 if ( status < 0 ) { | 539 case AUDIO_U16LSB: |
436 test_format = SDL_NextAudioFormat(); | 540 format = SND_PCM_FORMAT_U16_LE; |
437 } | 541 break; |
438 } | 542 case AUDIO_U16MSB: |
439 if ( status < 0 ) { | 543 format = SND_PCM_FORMAT_U16_BE; |
440 SDL_SetError("Couldn't find any hardware audio formats"); | 544 break; |
441 ALSA_CloseAudio(this); | 545 default: |
442 return(-1); | 546 format = 0; |
443 } | 547 break; |
444 spec->format = test_format; | 548 } |
445 | 549 if (format != 0) { |
446 /* Set the number of channels */ | 550 status = |
447 status = SDL_NAME(snd_pcm_hw_params_set_channels)(pcm_handle, hwparams, spec->channels); | 551 SDL_NAME(snd_pcm_hw_params_set_format) (pcm_handle, |
448 if ( status < 0 ) { | 552 hwparams, format); |
449 status = SDL_NAME(snd_pcm_hw_params_get_channels)(hwparams); | 553 } |
450 if ( (status <= 0) || (status > 2) ) { | 554 if (status < 0) { |
451 SDL_SetError("Couldn't set audio channels"); | 555 test_format = SDL_NextAudioFormat(); |
452 ALSA_CloseAudio(this); | 556 } |
453 return(-1); | 557 } |
454 } | 558 if (status < 0) { |
455 spec->channels = status; | 559 SDL_SetError("Couldn't find any hardware audio formats"); |
456 } | 560 ALSA_CloseAudio(this); |
457 | 561 return (-1); |
458 /* Set the audio rate */ | 562 } |
459 status = SDL_NAME(snd_pcm_hw_params_set_rate_near)(pcm_handle, hwparams, spec->freq, NULL); | 563 spec->format = test_format; |
460 if ( status < 0 ) { | 564 |
461 SDL_SetError("Couldn't set audio frequency: %s", SDL_NAME(snd_strerror)(status)); | 565 /* Set the number of channels */ |
462 ALSA_CloseAudio(this); | 566 status = |
463 return(-1); | 567 SDL_NAME(snd_pcm_hw_params_set_channels) (pcm_handle, hwparams, |
464 } | 568 spec->channels); |
465 spec->freq = status; | 569 if (status < 0) { |
466 | 570 status = SDL_NAME(snd_pcm_hw_params_get_channels) (hwparams); |
467 /* Set the buffer size, in samples */ | 571 if ((status <= 0) || (status > 2)) { |
468 frames = spec->samples; | 572 SDL_SetError("Couldn't set audio channels"); |
469 frames = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, frames, NULL); | 573 ALSA_CloseAudio(this); |
470 spec->samples = frames; | 574 return (-1); |
471 SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, 2, NULL); | 575 } |
472 | 576 spec->channels = status; |
473 /* "set" the hardware with the desired parameters */ | 577 } |
474 status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams); | 578 |
475 if ( status < 0 ) { | 579 /* Set the audio rate */ |
476 SDL_SetError("Couldn't set hardware audio parameters: %s", SDL_NAME(snd_strerror)(status)); | 580 status = |
477 ALSA_CloseAudio(this); | 581 SDL_NAME(snd_pcm_hw_params_set_rate_near) (pcm_handle, hwparams, |
478 return(-1); | 582 spec->freq, NULL); |
479 } | 583 if (status < 0) { |
584 SDL_SetError("Couldn't set audio frequency: %s", | |
585 SDL_NAME(snd_strerror) (status)); | |
586 ALSA_CloseAudio(this); | |
587 return (-1); | |
588 } | |
589 spec->freq = status; | |
590 | |
591 /* Set the buffer size, in samples */ | |
592 frames = spec->samples; | |
593 frames = | |
594 SDL_NAME(snd_pcm_hw_params_set_period_size_near) (pcm_handle, | |
595 hwparams, frames, | |
596 NULL); | |
597 spec->samples = frames; | |
598 SDL_NAME(snd_pcm_hw_params_set_periods_near) (pcm_handle, hwparams, 2, | |
599 NULL); | |
600 | |
601 /* "set" the hardware with the desired parameters */ | |
602 status = SDL_NAME(snd_pcm_hw_params) (pcm_handle, hwparams); | |
603 if (status < 0) { | |
604 SDL_SetError("Couldn't set hardware audio parameters: %s", | |
605 SDL_NAME(snd_strerror) (status)); | |
606 ALSA_CloseAudio(this); | |
607 return (-1); | |
608 } | |
480 | 609 |
481 /* This is useful for debugging... */ | 610 /* This is useful for debugging... */ |
482 /* | 611 /* |
483 { snd_pcm_sframes_t bufsize; int fragments; | 612 { snd_pcm_sframes_t bufsize; int fragments; |
484 bufsize = SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams); | 613 bufsize = SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams); |
486 | 615 |
487 fprintf(stderr, "ALSA: bufsize = %ld, fragments = %d\n", bufsize, fragments); | 616 fprintf(stderr, "ALSA: bufsize = %ld, fragments = %d\n", bufsize, fragments); |
488 } | 617 } |
489 */ | 618 */ |
490 | 619 |
491 /* Set the software parameters */ | 620 /* Set the software parameters */ |
492 snd_pcm_sw_params_alloca(&swparams); | 621 snd_pcm_sw_params_alloca(&swparams); |
493 status = SDL_NAME(snd_pcm_sw_params_current)(pcm_handle, swparams); | 622 status = SDL_NAME(snd_pcm_sw_params_current) (pcm_handle, swparams); |
494 if ( status < 0 ) { | 623 if (status < 0) { |
495 SDL_SetError("Couldn't get software config: %s", SDL_NAME(snd_strerror)(status)); | 624 SDL_SetError("Couldn't get software config: %s", |
496 ALSA_CloseAudio(this); | 625 SDL_NAME(snd_strerror) (status)); |
497 return(-1); | 626 ALSA_CloseAudio(this); |
498 } | 627 return (-1); |
499 status = SDL_NAME(snd_pcm_sw_params_set_start_threshold)(pcm_handle, swparams, 0); | 628 } |
500 if ( status < 0 ) { | 629 status = |
501 SDL_SetError("Couldn't set start threshold: %s", SDL_NAME(snd_strerror)(status)); | 630 SDL_NAME(snd_pcm_sw_params_set_start_threshold) (pcm_handle, |
502 ALSA_CloseAudio(this); | 631 swparams, 0); |
503 return(-1); | 632 if (status < 0) { |
504 } | 633 SDL_SetError("Couldn't set start threshold: %s", |
505 status = SDL_NAME(snd_pcm_sw_params_set_avail_min)(pcm_handle, swparams, frames); | 634 SDL_NAME(snd_strerror) (status)); |
506 if ( status < 0 ) { | 635 ALSA_CloseAudio(this); |
507 SDL_SetError("Couldn't set avail min: %s", SDL_NAME(snd_strerror)(status)); | 636 return (-1); |
508 ALSA_CloseAudio(this); | 637 } |
509 return(-1); | 638 status = |
510 } | 639 SDL_NAME(snd_pcm_sw_params_set_avail_min) (pcm_handle, swparams, |
511 status = SDL_NAME(snd_pcm_sw_params)(pcm_handle, swparams); | 640 frames); |
512 if ( status < 0 ) { | 641 if (status < 0) { |
513 SDL_SetError("Couldn't set software audio parameters: %s", SDL_NAME(snd_strerror)(status)); | 642 SDL_SetError("Couldn't set avail min: %s", |
514 ALSA_CloseAudio(this); | 643 SDL_NAME(snd_strerror) (status)); |
515 return(-1); | 644 ALSA_CloseAudio(this); |
516 } | 645 return (-1); |
517 | 646 } |
518 /* Calculate the final parameters for this audio specification */ | 647 status = SDL_NAME(snd_pcm_sw_params) (pcm_handle, swparams); |
519 SDL_CalculateAudioSpec(spec); | 648 if (status < 0) { |
520 | 649 SDL_SetError("Couldn't set software audio parameters: %s", |
521 /* Allocate mixing buffer */ | 650 SDL_NAME(snd_strerror) (status)); |
522 mixlen = spec->size; | 651 ALSA_CloseAudio(this); |
523 mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); | 652 return (-1); |
524 if ( mixbuf == NULL ) { | 653 } |
525 ALSA_CloseAudio(this); | 654 |
526 return(-1); | 655 /* Calculate the final parameters for this audio specification */ |
527 } | 656 SDL_CalculateAudioSpec(spec); |
528 SDL_memset(mixbuf, spec->silence, spec->size); | 657 |
529 | 658 /* Allocate mixing buffer */ |
530 /* Get the parent process id (we're the parent of the audio thread) */ | 659 mixlen = spec->size; |
531 parent = getpid(); | 660 mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen); |
532 | 661 if (mixbuf == NULL) { |
533 /* Switch to blocking mode for playback */ | 662 ALSA_CloseAudio(this); |
534 SDL_NAME(snd_pcm_nonblock)(pcm_handle, 0); | 663 return (-1); |
535 | 664 } |
536 /* We're ready to rock and roll. :-) */ | 665 SDL_memset(mixbuf, spec->silence, spec->size); |
537 return(0); | 666 |
538 } | 667 /* Get the parent process id (we're the parent of the audio thread) */ |
668 parent = getpid(); | |
669 | |
670 /* Switch to blocking mode for playback */ | |
671 SDL_NAME(snd_pcm_nonblock) (pcm_handle, 0); | |
672 | |
673 /* We're ready to rock and roll. :-) */ | |
674 return (0); | |
675 } | |
676 | |
677 /* vi: set ts=4 sw=4 expandtab: */ |