Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
351 lines (297 loc) · 9.09 KB

SDL_esdaudio.c

File metadata and controls

351 lines (297 loc) · 9.09 KB
 
Apr 26, 2001
Apr 26, 2001
1
/*
Apr 8, 2011
Apr 8, 2011
2
3
Simple DirectMedia Layer
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
Apr 26, 2001
Apr 26, 2001
4
Apr 8, 2011
Apr 8, 2011
5
6
7
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Apr 26, 2001
Apr 26, 2001
8
Apr 8, 2011
Apr 8, 2011
9
10
11
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
Apr 26, 2001
Apr 26, 2001
12
Apr 8, 2011
Apr 8, 2011
13
14
15
16
17
18
19
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Apr 26, 2001
Apr 26, 2001
20
*/
Feb 21, 2006
Feb 21, 2006
21
#include "SDL_config.h"
Apr 26, 2001
Apr 26, 2001
22
23
24
/* Allow access to an ESD network stream mixing buffer */
Mar 31, 2006
Mar 31, 2006
25
26
27
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
Apr 26, 2001
Apr 26, 2001
28
29
30
#include <errno.h>
#include <esd.h>
Feb 10, 2006
Feb 10, 2006
31
#include "SDL_timer.h"
Apr 26, 2001
Apr 26, 2001
32
#include "SDL_audio.h"
Feb 16, 2006
Feb 16, 2006
33
34
#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
Apr 26, 2001
Apr 26, 2001
35
36
#include "SDL_esdaudio.h"
Feb 16, 2006
Feb 16, 2006
37
#ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC
Mar 6, 2002
Mar 6, 2002
38
39
40
41
42
43
#include "SDL_name.h"
#include "SDL_loadso.h"
#else
#define SDL_NAME(X) X
#endif
Apr 26, 2001
Apr 26, 2001
44
45
46
/* The tag name used by ESD audio */
#define ESD_DRIVER_NAME "esd"
Feb 16, 2006
Feb 16, 2006
47
#ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC
Mar 6, 2002
Mar 6, 2002
48
Feb 16, 2006
Feb 16, 2006
49
static const char *esd_library = SDL_AUDIO_DRIVER_ESD_DYNAMIC;
Mar 6, 2002
Mar 6, 2002
50
51
static void *esd_handle = NULL;
Jul 10, 2006
Jul 10, 2006
52
53
54
55
static int (*SDL_NAME(esd_open_sound)) (const char *host);
static int (*SDL_NAME(esd_close)) (int esd);
static int (*SDL_NAME(esd_play_stream)) (esd_format_t format, int rate,
const char *host, const char *name);
Oct 17, 2006
Oct 17, 2006
56
57
#define SDL_ESD_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
Jul 10, 2006
Jul 10, 2006
58
59
60
61
static struct
{
const char *name;
void **func;
Jun 3, 2009
Jun 3, 2009
62
63
64
65
66
} const esd_functions[] = {
SDL_ESD_SYM(esd_open_sound),
SDL_ESD_SYM(esd_close), SDL_ESD_SYM(esd_play_stream),
};
Oct 17, 2006
Oct 17, 2006
67
#undef SDL_ESD_SYM
Mar 6, 2002
Mar 6, 2002
68
Jul 10, 2006
Jul 10, 2006
69
70
static void
UnloadESDLibrary()
Mar 6, 2002
Mar 6, 2002
71
{
Oct 17, 2006
Oct 17, 2006
72
if (esd_handle != NULL) {
Jul 10, 2006
Jul 10, 2006
73
74
75
SDL_UnloadObject(esd_handle);
esd_handle = NULL;
}
Mar 6, 2002
Mar 6, 2002
76
77
}
Jul 10, 2006
Jul 10, 2006
78
79
static int
LoadESDLibrary(void)
Mar 6, 2002
Mar 6, 2002
80
{
Jul 10, 2006
Jul 10, 2006
81
82
int i, retval = -1;
Oct 17, 2006
Oct 17, 2006
83
84
85
86
87
88
89
90
91
92
93
94
if (esd_handle == NULL) {
esd_handle = SDL_LoadObject(esd_library);
if (esd_handle) {
retval = 0;
for (i = 0; i < SDL_arraysize(esd_functions); ++i) {
*esd_functions[i].func =
SDL_LoadFunction(esd_handle, esd_functions[i].name);
if (!*esd_functions[i].func) {
retval = -1;
UnloadESDLibrary();
break;
}
Jul 10, 2006
Jul 10, 2006
95
96
97
98
}
}
}
return retval;
Mar 6, 2002
Mar 6, 2002
99
100
101
102
}
#else
Jul 10, 2006
Jul 10, 2006
103
104
static void
UnloadESDLibrary()
Mar 6, 2002
Mar 6, 2002
105
{
Jul 10, 2006
Jul 10, 2006
106
return;
Mar 6, 2002
Mar 6, 2002
107
108
}
Jul 10, 2006
Jul 10, 2006
109
110
static int
LoadESDLibrary(void)
Mar 6, 2002
Mar 6, 2002
111
{
Jul 10, 2006
Jul 10, 2006
112
return 0;
Mar 6, 2002
Mar 6, 2002
113
114
}
Feb 16, 2006
Feb 16, 2006
115
#endif /* SDL_AUDIO_DRIVER_ESD_DYNAMIC */
Mar 6, 2002
Mar 6, 2002
116
Apr 26, 2001
Apr 26, 2001
117
118
/* This function waits until it is possible to write a full sound buffer */
Jul 10, 2006
Jul 10, 2006
119
static void
Oct 17, 2006
Oct 17, 2006
120
ESD_WaitDevice(_THIS)
Apr 26, 2001
Apr 26, 2001
121
{
Jul 10, 2006
Jul 10, 2006
122
123
124
125
126
127
128
129
Sint32 ticks;
/* Check to see if the thread-parent process is still alive */
{
static int cnt = 0;
/* Note that this only works with thread implementations
that use a different process id for each thread.
*/
Oct 17, 2006
Oct 17, 2006
130
131
/* Check every 10 loops */
if (this->hidden->parent && (((++cnt) % 10) == 0)) {
Feb 17, 2009
Feb 17, 2009
132
if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
Jul 10, 2006
Jul 10, 2006
133
134
135
136
137
138
this->enabled = 0;
}
}
}
/* Use timer for general audio synchronization */
Oct 28, 2006
Oct 28, 2006
139
140
ticks =
((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS;
Jul 10, 2006
Jul 10, 2006
141
142
143
if (ticks > 0) {
SDL_Delay(ticks);
}
Apr 26, 2001
Apr 26, 2001
144
145
}
Jul 10, 2006
Jul 10, 2006
146
static void
Oct 17, 2006
Oct 17, 2006
147
ESD_PlayDevice(_THIS)
Apr 26, 2001
Apr 26, 2001
148
{
Oct 17, 2006
Oct 17, 2006
149
int written = 0;
Jul 10, 2006
Jul 10, 2006
150
151
152
/* Write the audio data, checking for EAGAIN on broken audio drivers */
do {
Oct 17, 2006
Oct 17, 2006
153
written = write(this->hidden->audio_fd,
Oct 28, 2006
Oct 28, 2006
154
this->hidden->mixbuf, this->hidden->mixlen);
Jul 10, 2006
Jul 10, 2006
155
156
157
if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) {
SDL_Delay(1); /* Let a little CPU time go by */
}
Aug 27, 2008
Aug 27, 2008
158
159
} while ((written < 0) &&
((errno == 0) || (errno == EAGAIN) || (errno == EINTR)));
Jul 10, 2006
Jul 10, 2006
160
161
/* Set the next write frame */
Oct 17, 2006
Oct 17, 2006
162
this->hidden->next_frame += this->hidden->frame_ticks;
Jul 10, 2006
Jul 10, 2006
163
164
165
166
167
/* If we couldn't write, assume fatal error for now */
if (written < 0) {
this->enabled = 0;
}
Apr 26, 2001
Apr 26, 2001
168
169
}
Jul 10, 2006
Jul 10, 2006
170
static Uint8 *
Oct 17, 2006
Oct 17, 2006
171
ESD_GetDeviceBuf(_THIS)
Apr 26, 2001
Apr 26, 2001
172
{
Oct 17, 2006
Oct 17, 2006
173
return (this->hidden->mixbuf);
Apr 26, 2001
Apr 26, 2001
174
175
}
Jul 10, 2006
Jul 10, 2006
176
static void
Oct 17, 2006
Oct 17, 2006
177
ESD_CloseDevice(_THIS)
Apr 26, 2001
Apr 26, 2001
178
{
Oct 17, 2006
Oct 17, 2006
179
180
181
182
183
184
185
186
187
188
189
190
if (this->hidden != NULL) {
if (this->hidden->mixbuf != NULL) {
SDL_FreeAudioMem(this->hidden->mixbuf);
this->hidden->mixbuf = NULL;
}
if (this->hidden->audio_fd >= 0) {
SDL_NAME(esd_close) (this->hidden->audio_fd);
this->hidden->audio_fd = -1;
}
SDL_free(this->hidden);
this->hidden = NULL;
Jul 10, 2006
Jul 10, 2006
191
}
Apr 26, 2001
Apr 26, 2001
192
193
194
}
/* Try to get the name of the program */
Jul 10, 2006
Jul 10, 2006
195
196
static char *
get_progname(void)
Apr 26, 2001
Apr 26, 2001
197
{
Jul 10, 2006
Jul 10, 2006
198
char *progname = NULL;
Feb 21, 2006
Feb 21, 2006
199
#ifdef __LINUX__
Jul 10, 2006
Jul 10, 2006
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
FILE *fp;
static char temp[BUFSIZ];
SDL_snprintf(temp, SDL_arraysize(temp), "/proc/%d/cmdline", getpid());
fp = fopen(temp, "r");
if (fp != NULL) {
if (fgets(temp, sizeof(temp) - 1, fp)) {
progname = SDL_strrchr(temp, '/');
if (progname == NULL) {
progname = temp;
} else {
progname = progname + 1;
}
}
fclose(fp);
}
Apr 26, 2001
Apr 26, 2001
216
#endif
Jul 10, 2006
Jul 10, 2006
217
return (progname);
Apr 26, 2001
Apr 26, 2001
218
219
}
Oct 17, 2006
Oct 17, 2006
220
Jul 10, 2006
Jul 10, 2006
221
static int
Oct 17, 2006
Oct 17, 2006
222
ESD_OpenDevice(_THIS, const char *devname, int iscapture)
Apr 26, 2001
Apr 26, 2001
223
{
Oct 17, 2006
Oct 17, 2006
224
225
226
227
228
229
esd_format_t format = (ESD_STREAM | ESD_PLAY);
SDL_AudioFormat test_format = 0;
int found = 0;
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
Oct 28, 2006
Oct 28, 2006
230
SDL_malloc((sizeof *this->hidden));
Oct 17, 2006
Oct 17, 2006
231
232
233
234
235
236
if (this->hidden == NULL) {
SDL_OutOfMemory();
return 0;
}
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
this->hidden->audio_fd = -1;
Jul 10, 2006
Jul 10, 2006
237
238
/* Convert audio spec to the ESD audio format */
Oct 17, 2006
Oct 17, 2006
239
240
241
242
243
244
245
246
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format);
!found && test_format; test_format = SDL_NextAudioFormat()) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
found = 1;
switch (test_format) {
Oct 28, 2006
Oct 28, 2006
247
248
249
250
251
252
253
254
255
case AUDIO_U8:
format |= ESD_BITS8;
break;
case AUDIO_S16SYS:
format |= ESD_BITS16;
break;
default:
found = 0;
break;
Oct 17, 2006
Oct 17, 2006
256
}
Jul 10, 2006
Jul 10, 2006
257
}
Oct 17, 2006
Oct 17, 2006
258
259
260
261
262
263
264
265
if (!found) {
ESD_CloseDevice(this);
SDL_SetError("Couldn't find any hardware audio formats");
return 0;
}
if (this->spec.channels == 1) {
Jul 10, 2006
Jul 10, 2006
266
267
268
269
format |= ESD_MONO;
} else {
format |= ESD_STEREO;
}
Apr 26, 2001
Apr 26, 2001
270
#if 0
Oct 28, 2006
Oct 28, 2006
271
this->spec.samples = ESD_BUF_SIZE; /* Darn, no way to change this yet */
Apr 26, 2001
Apr 26, 2001
272
273
#endif
Jul 10, 2006
Jul 10, 2006
274
/* Open a connection to the ESD audio server */
Oct 17, 2006
Oct 17, 2006
275
this->hidden->audio_fd =
Oct 28, 2006
Oct 28, 2006
276
277
SDL_NAME(esd_play_stream) (format, this->spec.freq, NULL,
get_progname());
Oct 17, 2006
Oct 17, 2006
278
279
280
if (this->hidden->audio_fd < 0) {
ESD_CloseDevice(this);
Jul 10, 2006
Jul 10, 2006
281
SDL_SetError("Couldn't open ESD connection");
Oct 17, 2006
Oct 17, 2006
282
return 0;
Jul 10, 2006
Jul 10, 2006
283
284
285
}
/* Calculate the final parameters for this audio specification */
Oct 17, 2006
Oct 17, 2006
286
SDL_CalculateAudioSpec(&this->spec);
Oct 28, 2006
Oct 28, 2006
287
288
this->hidden->frame_ticks =
(float) (this->spec.samples * 1000) / this->spec.freq;
Oct 17, 2006
Oct 17, 2006
289
this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks;
Jul 10, 2006
Jul 10, 2006
290
291
/* Allocate mixing buffer */
Oct 17, 2006
Oct 17, 2006
292
293
294
295
296
297
this->hidden->mixlen = this->spec.size;
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
ESD_CloseDevice(this);
SDL_OutOfMemory();
return 0;
Jul 10, 2006
Jul 10, 2006
298
}
Oct 17, 2006
Oct 17, 2006
299
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
Jul 10, 2006
Jul 10, 2006
300
301
/* Get the parent process id (we're the parent of the audio thread) */
Oct 17, 2006
Oct 17, 2006
302
this->hidden->parent = getpid();
Jul 10, 2006
Jul 10, 2006
303
304
/* We're ready to rock and roll. :-) */
Oct 17, 2006
Oct 17, 2006
305
306
307
308
309
310
311
312
313
314
return 1;
}
static void
ESD_Deinitialize(void)
{
UnloadESDLibrary();
}
static int
Oct 28, 2006
Oct 28, 2006
315
ESD_Init(SDL_AudioDriverImpl * impl)
Oct 17, 2006
Oct 17, 2006
316
317
318
319
320
321
322
{
if (LoadESDLibrary() < 0) {
return 0;
} else {
int connection = 0;
/* Don't start ESD if it's not running */
Dec 16, 2009
Dec 16, 2009
323
SDL_setenv("ESD_NO_SPAWN", "1", 0);
Oct 17, 2006
Oct 17, 2006
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
connection = SDL_NAME(esd_open_sound) (NULL);
if (connection < 0) {
UnloadESDLibrary();
SDL_SetError("ESD: esd_open_sound failed (no audio server?)");
return 0;
}
SDL_NAME(esd_close) (connection);
}
/* Set the function pointers */
impl->OpenDevice = ESD_OpenDevice;
impl->PlayDevice = ESD_PlayDevice;
impl->WaitDevice = ESD_WaitDevice;
impl->GetDeviceBuf = ESD_GetDeviceBuf;
impl->CloseDevice = ESD_CloseDevice;
impl->Deinitialize = ESD_Deinitialize;
impl->OnlyHasDefaultOutputDevice = 1;
Jan 26, 2010
Jan 26, 2010
343
return 1; /* this audio target is available. */
Apr 26, 2001
Apr 26, 2001
344
}
Jul 10, 2006
Jul 10, 2006
345
Oct 17, 2006
Oct 17, 2006
346
347
348
349
350
AudioBootStrap ESD_bootstrap = {
ESD_DRIVER_NAME, "Enlightened Sound Daemon", ESD_Init, 0
};
Jul 10, 2006
Jul 10, 2006
351
/* vi: set ts=4 sw=4 expandtab: */