Mercurial > sdl-ios-xcode
comparison src/audio/esd/SDL_esdaudio.c @ 1662:782fd950bd46 SDL-1.3
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.
WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.
The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce
The headers are being converted to automatically generate doxygen documentation.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 28 May 2006 13:04:16 +0000 |
parents | 9f836cec0521 |
children | 4da1ee79c9af |
comparison
equal
deleted
inserted
replaced
1661:281d3f4870e5 | 1662:782fd950bd46 |
---|---|
45 | 45 |
46 /* The tag name used by ESD audio */ | 46 /* The tag name used by ESD audio */ |
47 #define ESD_DRIVER_NAME "esd" | 47 #define ESD_DRIVER_NAME "esd" |
48 | 48 |
49 /* Audio driver functions */ | 49 /* Audio driver functions */ |
50 static int ESD_OpenAudio(_THIS, SDL_AudioSpec *spec); | 50 static int ESD_OpenAudio (_THIS, SDL_AudioSpec * spec); |
51 static void ESD_WaitAudio(_THIS); | 51 static void ESD_WaitAudio (_THIS); |
52 static void ESD_PlayAudio(_THIS); | 52 static void ESD_PlayAudio (_THIS); |
53 static Uint8 *ESD_GetAudioBuf(_THIS); | 53 static Uint8 *ESD_GetAudioBuf (_THIS); |
54 static void ESD_CloseAudio(_THIS); | 54 static void ESD_CloseAudio (_THIS); |
55 | 55 |
56 #ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC | 56 #ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC |
57 | 57 |
58 static const char *esd_library = SDL_AUDIO_DRIVER_ESD_DYNAMIC; | 58 static const char *esd_library = SDL_AUDIO_DRIVER_ESD_DYNAMIC; |
59 static void *esd_handle = NULL; | 59 static void *esd_handle = NULL; |
60 static int esd_loaded = 0; | 60 static int esd_loaded = 0; |
61 | 61 |
62 static int (*SDL_NAME(esd_open_sound))( const char *host ); | 62 static int (*SDL_NAME (esd_open_sound)) (const char *host); |
63 static int (*SDL_NAME(esd_close))( int esd ); | 63 static int (*SDL_NAME (esd_close)) (int esd); |
64 static int (*SDL_NAME(esd_play_stream))( esd_format_t format, int rate, | 64 static int (*SDL_NAME (esd_play_stream)) (esd_format_t format, int rate, |
65 const char *host, const char *name ); | 65 const char *host, const char *name); |
66 static struct { | 66 static struct |
67 const char *name; | 67 { |
68 void **func; | 68 const char *name; |
69 void **func; | |
69 } esd_functions[] = { | 70 } esd_functions[] = { |
70 { "esd_open_sound", (void **)&SDL_NAME(esd_open_sound) }, | 71 { |
71 { "esd_close", (void **)&SDL_NAME(esd_close) }, | 72 "esd_open_sound", (void **) &SDL_NAME (esd_open_sound)}, { |
72 { "esd_play_stream", (void **)&SDL_NAME(esd_play_stream) }, | 73 "esd_close", (void **) &SDL_NAME (esd_close)}, { |
74 "esd_play_stream", (void **) &SDL_NAME (esd_play_stream)},}; | |
75 | |
76 static void | |
77 UnloadESDLibrary () | |
78 { | |
79 if (esd_loaded) { | |
80 SDL_UnloadObject (esd_handle); | |
81 esd_handle = NULL; | |
82 esd_loaded = 0; | |
83 } | |
84 } | |
85 | |
86 static int | |
87 LoadESDLibrary (void) | |
88 { | |
89 int i, retval = -1; | |
90 | |
91 esd_handle = SDL_LoadObject (esd_library); | |
92 if (esd_handle) { | |
93 esd_loaded = 1; | |
94 retval = 0; | |
95 for (i = 0; i < SDL_arraysize (esd_functions); ++i) { | |
96 *esd_functions[i].func = | |
97 SDL_LoadFunction (esd_handle, esd_functions[i].name); | |
98 if (!*esd_functions[i].func) { | |
99 retval = -1; | |
100 UnloadESDLibrary (); | |
101 break; | |
102 } | |
103 } | |
104 } | |
105 return retval; | |
106 } | |
107 | |
108 #else | |
109 | |
110 static void | |
111 UnloadESDLibrary () | |
112 { | |
113 return; | |
114 } | |
115 | |
116 static int | |
117 LoadESDLibrary (void) | |
118 { | |
119 return 0; | |
120 } | |
121 | |
122 #endif /* SDL_AUDIO_DRIVER_ESD_DYNAMIC */ | |
123 | |
124 /* Audio driver bootstrap functions */ | |
125 | |
126 static int | |
127 Audio_Available (void) | |
128 { | |
129 int connection; | |
130 int available; | |
131 | |
132 available = 0; | |
133 if (LoadESDLibrary () < 0) { | |
134 return available; | |
135 } | |
136 connection = SDL_NAME (esd_open_sound) (NULL); | |
137 if (connection >= 0) { | |
138 available = 1; | |
139 SDL_NAME (esd_close) (connection); | |
140 } | |
141 UnloadESDLibrary (); | |
142 return (available); | |
143 } | |
144 | |
145 static void | |
146 Audio_DeleteDevice (SDL_AudioDevice * device) | |
147 { | |
148 SDL_free (device->hidden); | |
149 SDL_free (device); | |
150 UnloadESDLibrary (); | |
151 } | |
152 | |
153 static SDL_AudioDevice * | |
154 Audio_CreateDevice (int devindex) | |
155 { | |
156 SDL_AudioDevice *this; | |
157 | |
158 /* Initialize all variables that we clean on shutdown */ | |
159 LoadESDLibrary (); | |
160 this = (SDL_AudioDevice *) SDL_malloc (sizeof (SDL_AudioDevice)); | |
161 if (this) { | |
162 SDL_memset (this, 0, (sizeof *this)); | |
163 this->hidden = (struct SDL_PrivateAudioData *) | |
164 SDL_malloc ((sizeof *this->hidden)); | |
165 } | |
166 if ((this == NULL) || (this->hidden == NULL)) { | |
167 SDL_OutOfMemory (); | |
168 if (this) { | |
169 SDL_free (this); | |
170 } | |
171 return (0); | |
172 } | |
173 SDL_memset (this->hidden, 0, (sizeof *this->hidden)); | |
174 audio_fd = -1; | |
175 | |
176 /* Set the function pointers */ | |
177 this->OpenAudio = ESD_OpenAudio; | |
178 this->WaitAudio = ESD_WaitAudio; | |
179 this->PlayAudio = ESD_PlayAudio; | |
180 this->GetAudioBuf = ESD_GetAudioBuf; | |
181 this->CloseAudio = ESD_CloseAudio; | |
182 | |
183 this->free = Audio_DeleteDevice; | |
184 | |
185 return this; | |
186 } | |
187 | |
188 AudioBootStrap ESD_bootstrap = { | |
189 ESD_DRIVER_NAME, "Enlightened Sound Daemon", | |
190 Audio_Available, Audio_CreateDevice | |
73 }; | 191 }; |
74 | 192 |
75 static void UnloadESDLibrary() | |
76 { | |
77 if ( esd_loaded ) { | |
78 SDL_UnloadObject(esd_handle); | |
79 esd_handle = NULL; | |
80 esd_loaded = 0; | |
81 } | |
82 } | |
83 | |
84 static int LoadESDLibrary(void) | |
85 { | |
86 int i, retval = -1; | |
87 | |
88 esd_handle = SDL_LoadObject(esd_library); | |
89 if ( esd_handle ) { | |
90 esd_loaded = 1; | |
91 retval = 0; | |
92 for ( i=0; i<SDL_arraysize(esd_functions); ++i ) { | |
93 *esd_functions[i].func = SDL_LoadFunction(esd_handle, esd_functions[i].name); | |
94 if ( !*esd_functions[i].func ) { | |
95 retval = -1; | |
96 UnloadESDLibrary(); | |
97 break; | |
98 } | |
99 } | |
100 } | |
101 return retval; | |
102 } | |
103 | |
104 #else | |
105 | |
106 static void UnloadESDLibrary() | |
107 { | |
108 return; | |
109 } | |
110 | |
111 static int LoadESDLibrary(void) | |
112 { | |
113 return 0; | |
114 } | |
115 | |
116 #endif /* SDL_AUDIO_DRIVER_ESD_DYNAMIC */ | |
117 | |
118 /* Audio driver bootstrap functions */ | |
119 | |
120 static int Audio_Available(void) | |
121 { | |
122 int connection; | |
123 int available; | |
124 | |
125 available = 0; | |
126 if ( LoadESDLibrary() < 0 ) { | |
127 return available; | |
128 } | |
129 connection = SDL_NAME(esd_open_sound)(NULL); | |
130 if ( connection >= 0 ) { | |
131 available = 1; | |
132 SDL_NAME(esd_close)(connection); | |
133 } | |
134 UnloadESDLibrary(); | |
135 return(available); | |
136 } | |
137 | |
138 static void Audio_DeleteDevice(SDL_AudioDevice *device) | |
139 { | |
140 SDL_free(device->hidden); | |
141 SDL_free(device); | |
142 UnloadESDLibrary(); | |
143 } | |
144 | |
145 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | |
146 { | |
147 SDL_AudioDevice *this; | |
148 | |
149 /* Initialize all variables that we clean on shutdown */ | |
150 LoadESDLibrary(); | |
151 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); | |
152 if ( this ) { | |
153 SDL_memset(this, 0, (sizeof *this)); | |
154 this->hidden = (struct SDL_PrivateAudioData *) | |
155 SDL_malloc((sizeof *this->hidden)); | |
156 } | |
157 if ( (this == NULL) || (this->hidden == NULL) ) { | |
158 SDL_OutOfMemory(); | |
159 if ( this ) { | |
160 SDL_free(this); | |
161 } | |
162 return(0); | |
163 } | |
164 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | |
165 audio_fd = -1; | |
166 | |
167 /* Set the function pointers */ | |
168 this->OpenAudio = ESD_OpenAudio; | |
169 this->WaitAudio = ESD_WaitAudio; | |
170 this->PlayAudio = ESD_PlayAudio; | |
171 this->GetAudioBuf = ESD_GetAudioBuf; | |
172 this->CloseAudio = ESD_CloseAudio; | |
173 | |
174 this->free = Audio_DeleteDevice; | |
175 | |
176 return this; | |
177 } | |
178 | |
179 AudioBootStrap ESD_bootstrap = { | |
180 ESD_DRIVER_NAME, "Enlightened Sound Daemon", | |
181 Audio_Available, Audio_CreateDevice | |
182 }; | |
183 | |
184 /* This function waits until it is possible to write a full sound buffer */ | 193 /* This function waits until it is possible to write a full sound buffer */ |
185 static void ESD_WaitAudio(_THIS) | 194 static void |
186 { | 195 ESD_WaitAudio (_THIS) |
187 Sint32 ticks; | 196 { |
188 | 197 Sint32 ticks; |
189 /* Check to see if the thread-parent process is still alive */ | 198 |
190 { static int cnt = 0; | 199 /* Check to see if the thread-parent process is still alive */ |
191 /* Note that this only works with thread implementations | 200 { |
192 that use a different process id for each thread. | 201 static int cnt = 0; |
193 */ | 202 /* Note that this only works with thread implementations |
194 if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */ | 203 that use a different process id for each thread. |
195 if ( kill(parent, 0) < 0 ) { | 204 */ |
196 this->enabled = 0; | 205 if (parent && (((++cnt) % 10) == 0)) { /* Check every 10 loops */ |
197 } | 206 if (kill (parent, 0) < 0) { |
198 } | 207 this->enabled = 0; |
199 } | 208 } |
200 | 209 } |
201 /* Use timer for general audio synchronization */ | 210 } |
202 ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; | 211 |
203 if ( ticks > 0 ) { | 212 /* Use timer for general audio synchronization */ |
204 SDL_Delay(ticks); | 213 ticks = ((Sint32) (next_frame - SDL_GetTicks ())) - FUDGE_TICKS; |
205 } | 214 if (ticks > 0) { |
206 } | 215 SDL_Delay (ticks); |
207 | 216 } |
208 static void ESD_PlayAudio(_THIS) | 217 } |
209 { | 218 |
210 int written; | 219 static void |
211 | 220 ESD_PlayAudio (_THIS) |
212 /* Write the audio data, checking for EAGAIN on broken audio drivers */ | 221 { |
213 do { | 222 int written; |
214 written = write(audio_fd, mixbuf, mixlen); | 223 |
215 if ( (written < 0) && ((errno == 0) || (errno == EAGAIN)) ) { | 224 /* Write the audio data, checking for EAGAIN on broken audio drivers */ |
216 SDL_Delay(1); /* Let a little CPU time go by */ | 225 do { |
217 } | 226 written = write (audio_fd, mixbuf, mixlen); |
218 } while ( (written < 0) && | 227 if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) { |
219 ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)) ); | 228 SDL_Delay (1); /* Let a little CPU time go by */ |
220 | 229 } |
221 /* Set the next write frame */ | 230 } |
222 next_frame += frame_ticks; | 231 while ((written < 0) && |
223 | 232 ((errno == 0) || (errno == EAGAIN) || (errno == EINTR))); |
224 /* If we couldn't write, assume fatal error for now */ | 233 |
225 if ( written < 0 ) { | 234 /* Set the next write frame */ |
226 this->enabled = 0; | 235 next_frame += frame_ticks; |
227 } | 236 |
228 } | 237 /* If we couldn't write, assume fatal error for now */ |
229 | 238 if (written < 0) { |
230 static Uint8 *ESD_GetAudioBuf(_THIS) | 239 this->enabled = 0; |
231 { | 240 } |
232 return(mixbuf); | 241 } |
233 } | 242 |
234 | 243 static Uint8 * |
235 static void ESD_CloseAudio(_THIS) | 244 ESD_GetAudioBuf (_THIS) |
236 { | 245 { |
237 if ( mixbuf != NULL ) { | 246 return (mixbuf); |
238 SDL_FreeAudioMem(mixbuf); | 247 } |
239 mixbuf = NULL; | 248 |
240 } | 249 static void |
241 if ( audio_fd >= 0 ) { | 250 ESD_CloseAudio (_THIS) |
242 SDL_NAME(esd_close)(audio_fd); | 251 { |
243 audio_fd = -1; | 252 if (mixbuf != NULL) { |
244 } | 253 SDL_FreeAudioMem (mixbuf); |
254 mixbuf = NULL; | |
255 } | |
256 if (audio_fd >= 0) { | |
257 SDL_NAME (esd_close) (audio_fd); | |
258 audio_fd = -1; | |
259 } | |
245 } | 260 } |
246 | 261 |
247 /* Try to get the name of the program */ | 262 /* Try to get the name of the program */ |
248 static char *get_progname(void) | 263 static char * |
249 { | 264 get_progname (void) |
250 char *progname = NULL; | 265 { |
266 char *progname = NULL; | |
251 #ifdef __LINUX__ | 267 #ifdef __LINUX__ |
252 FILE *fp; | 268 FILE *fp; |
253 static char temp[BUFSIZ]; | 269 static char temp[BUFSIZ]; |
254 | 270 |
255 SDL_snprintf(temp, SDL_arraysize(temp), "/proc/%d/cmdline", getpid()); | 271 SDL_snprintf (temp, SDL_arraysize (temp), "/proc/%d/cmdline", getpid ()); |
256 fp = fopen(temp, "r"); | 272 fp = fopen (temp, "r"); |
257 if ( fp != NULL ) { | 273 if (fp != NULL) { |
258 if ( fgets(temp, sizeof(temp)-1, fp) ) { | 274 if (fgets (temp, sizeof (temp) - 1, fp)) { |
259 progname = SDL_strrchr(temp, '/'); | 275 progname = SDL_strrchr (temp, '/'); |
260 if ( progname == NULL ) { | 276 if (progname == NULL) { |
261 progname = temp; | 277 progname = temp; |
262 } else { | 278 } else { |
263 progname = progname+1; | 279 progname = progname + 1; |
264 } | 280 } |
265 } | 281 } |
266 fclose(fp); | 282 fclose (fp); |
267 } | 283 } |
268 #endif | 284 #endif |
269 return(progname); | 285 return (progname); |
270 } | 286 } |
271 | 287 |
272 static int ESD_OpenAudio(_THIS, SDL_AudioSpec *spec) | 288 static int |
273 { | 289 ESD_OpenAudio (_THIS, SDL_AudioSpec * spec) |
274 esd_format_t format; | 290 { |
275 | 291 esd_format_t format; |
276 /* Convert audio spec to the ESD audio format */ | 292 |
277 format = (ESD_STREAM | ESD_PLAY); | 293 /* Convert audio spec to the ESD audio format */ |
278 switch ( spec->format & 0xFF ) { | 294 format = (ESD_STREAM | ESD_PLAY); |
279 case 8: | 295 switch (spec->format & 0xFF) { |
280 format |= ESD_BITS8; | 296 case 8: |
281 break; | 297 format |= ESD_BITS8; |
282 case 16: | 298 break; |
283 format |= ESD_BITS16; | 299 case 16: |
284 break; | 300 format |= ESD_BITS16; |
285 default: | 301 break; |
286 SDL_SetError("Unsupported ESD audio format"); | 302 default: |
287 return(-1); | 303 SDL_SetError ("Unsupported ESD audio format"); |
288 } | 304 return (-1); |
289 if ( spec->channels == 1 ) { | 305 } |
290 format |= ESD_MONO; | 306 if (spec->channels == 1) { |
291 } else { | 307 format |= ESD_MONO; |
292 format |= ESD_STEREO; | 308 } else { |
293 } | 309 format |= ESD_STEREO; |
310 } | |
294 #if 0 | 311 #if 0 |
295 spec->samples = ESD_BUF_SIZE; /* Darn, no way to change this yet */ | 312 spec->samples = ESD_BUF_SIZE; /* Darn, no way to change this yet */ |
296 #endif | 313 #endif |
297 | 314 |
298 /* Open a connection to the ESD audio server */ | 315 /* Open a connection to the ESD audio server */ |
299 audio_fd = SDL_NAME(esd_play_stream)(format, spec->freq, NULL, get_progname()); | 316 audio_fd = |
300 if ( audio_fd < 0 ) { | 317 SDL_NAME (esd_play_stream) (format, spec->freq, NULL, |
301 SDL_SetError("Couldn't open ESD connection"); | 318 get_progname ()); |
302 return(-1); | 319 if (audio_fd < 0) { |
303 } | 320 SDL_SetError ("Couldn't open ESD connection"); |
304 | 321 return (-1); |
305 /* Calculate the final parameters for this audio specification */ | 322 } |
306 SDL_CalculateAudioSpec(spec); | 323 |
307 frame_ticks = (float)(spec->samples*1000)/spec->freq; | 324 /* Calculate the final parameters for this audio specification */ |
308 next_frame = SDL_GetTicks()+frame_ticks; | 325 SDL_CalculateAudioSpec (spec); |
309 | 326 frame_ticks = (float) (spec->samples * 1000) / spec->freq; |
310 /* Allocate mixing buffer */ | 327 next_frame = SDL_GetTicks () + frame_ticks; |
311 mixlen = spec->size; | 328 |
312 mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); | 329 /* Allocate mixing buffer */ |
313 if ( mixbuf == NULL ) { | 330 mixlen = spec->size; |
314 return(-1); | 331 mixbuf = (Uint8 *) SDL_AllocAudioMem (mixlen); |
315 } | 332 if (mixbuf == NULL) { |
316 SDL_memset(mixbuf, spec->silence, spec->size); | 333 return (-1); |
317 | 334 } |
318 /* Get the parent process id (we're the parent of the audio thread) */ | 335 SDL_memset (mixbuf, spec->silence, spec->size); |
319 parent = getpid(); | 336 |
320 | 337 /* Get the parent process id (we're the parent of the audio thread) */ |
321 /* We're ready to rock and roll. :-) */ | 338 parent = getpid (); |
322 return(0); | 339 |
323 } | 340 /* We're ready to rock and roll. :-) */ |
341 return (0); | |
342 } | |
343 | |
344 /* vi: set ts=4 sw=4 expandtab: */ |