zenilib: zenilib/jni/external/sdl/src/audio/bsd/SDL_bsdaudio.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_bsdaudio.c
Go to the documentation of this file.
1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "SDL_config.h"
22
23 #if SDL_AUDIO_DRIVER_BSD
24
25 /*
26 * Driver for native OpenBSD/NetBSD audio(4).
27 * vedge@vedge.com.ar.
28 */
29
30 #include <errno.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <sys/time.h>
34 #include <sys/ioctl.h>
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 #include <sys/audioio.h>
38
39 #include "SDL_timer.h"
40 #include "SDL_audio.h"
41 #include "../SDL_audiomem.h"
42 #include "../SDL_audio_c.h"
43 #include "../SDL_audiodev_c.h"
44 #include "SDL_bsdaudio.h"
45
46 /* Use timer for synchronization */
47 /* #define USE_TIMER_SYNC */
48
49 /* #define DEBUG_AUDIO */
50 /* #define DEBUG_AUDIO_STREAM */
51
52
53 static void
54 BSDAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
55 {
56 SDL_EnumUnixAudioDevices(iscapture, 0, NULL, addfn);
57 }
58
59
60 static void
61 BSDAUDIO_Status(_THIS)
62 {
63 #ifdef DEBUG_AUDIO
64 /* *INDENT-OFF* */
65 audio_info_t info;
66
67 if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
68 fprintf(stderr, "AUDIO_GETINFO failed.\n");
69 return;
70 }
71 fprintf(stderr, "\n"
72 "[play/record info]\n"
73 "buffer size : %d bytes\n"
74 "sample rate : %i Hz\n"
75 "channels : %i\n"
76 "precision : %i-bit\n"
77 "encoding : 0x%x\n"
78 "seek : %i\n"
79 "sample count : %i\n"
80 "EOF count : %i\n"
81 "paused : %s\n"
82 "error occured : %s\n"
83 "waiting : %s\n"
84 "active : %s\n"
85 "",
86 info.play.buffer_size,
87 info.play.sample_rate,
88 info.play.channels,
89 info.play.precision,
90 info.play.encoding,
91 info.play.seek,
92 info.play.samples,
93 info.play.eof,
94 info.play.pause ? "yes" : "no",
95 info.play.error ? "yes" : "no",
96 info.play.waiting ? "yes" : "no",
97 info.play.active ? "yes" : "no");
98
99 fprintf(stderr, "\n"
100 "[audio info]\n"
101 "monitor_gain : %i\n"
102 "hw block size : %d bytes\n"
103 "hi watermark : %i\n"
104 "lo watermark : %i\n"
105 "audio mode : %s\n"
106 "",
107 info.monitor_gain,
108 info.blocksize,
109 info.hiwat, info.lowat,
110 (info.mode == AUMODE_PLAY) ? "PLAY"
111 : (info.mode = AUMODE_RECORD) ? "RECORD"
112 : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?"));
113 /* *INDENT-ON* */
114 #endif /* DEBUG_AUDIO */
115 }
116
117
118 /* This function waits until it is possible to write a full sound buffer */
119 static void
120 BSDAUDIO_WaitDevice(_THIS)
121 {
122 #ifndef USE_BLOCKING_WRITES /* Not necessary when using blocking writes */
123 /* See if we need to use timed audio synchronization */
124 if (this->hidden->frame_ticks) {
125 /* Use timer for general audio synchronization */
126 Sint32 ticks;
127
128 ticks =
129 ((Sint32) (this->hidden->next_frame - SDL_GetTicks())) -
130 FUDGE_TICKS;
131 if (ticks > 0) {
132 SDL_Delay(ticks);
133 }
134 } else {
135 /* Use select() for audio synchronization */
136 fd_set fdset;
137 struct timeval timeout;
138
139 FD_ZERO(&fdset);
140 FD_SET(this->hidden->audio_fd, &fdset);
141 timeout.tv_sec = 10;
142 timeout.tv_usec = 0;
143 #ifdef DEBUG_AUDIO
144 fprintf(stderr, "Waiting for audio to get ready\n");
145 #endif
146 if (select(this->hidden->audio_fd + 1, NULL, &fdset, NULL, &timeout)
147 <= 0) {
148 const char *message =
149 "Audio timeout - buggy audio driver? (disabled)";
150 /* In general we should never print to the screen,
151 but in this case we have no other way of letting
152 the user know what happened.
153 */
154 fprintf(stderr, "SDL: %s\n", message);
155 this->enabled = 0;
156 /* Don't try to close - may hang */
157 this->hidden->audio_fd = -1;
158 #ifdef DEBUG_AUDIO
159 fprintf(stderr, "Done disabling audio\n");
160 #endif
161 }
162 #ifdef DEBUG_AUDIO
163 fprintf(stderr, "Ready!\n");
164 #endif
165 }
166 #endif /* !USE_BLOCKING_WRITES */
167 }
168
169 static void
170 BSDAUDIO_PlayDevice(_THIS)
171 {
172 int written, p = 0;
173
174 /* Write the audio data, checking for EAGAIN on broken audio drivers */
175 do {
176 written = write(this->hidden->audio_fd,
177 &this->hidden->mixbuf[p], this->hidden->mixlen - p);
178
179 if (written > 0)
180 p += written;
181 if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
182 /* Non recoverable error has occurred. It should be reported!!! */
183 perror("audio");
184 break;
185 }
186
187 if (p < written
188 || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) {
189 SDL_Delay(1); /* Let a little CPU time go by */
190 }
191 } while (p < written);
192
193 /* If timer synchronization is enabled, set the next write frame */
194 if (this->hidden->frame_ticks) {
195 this->hidden->next_frame += this->hidden->frame_ticks;
196 }
197
198 /* If we couldn't write, assume fatal error for now */
199 if (written < 0) {
200 this->enabled = 0;
201 }
202 #ifdef DEBUG_AUDIO
203 fprintf(stderr, "Wrote %d bytes of audio data\n", written);
204 #endif
205 }
206
207 static Uint8 *
208 BSDAUDIO_GetDeviceBuf(_THIS)
209 {
210 return (this->hidden->mixbuf);
211 }
212
213 static void
214 BSDAUDIO_CloseDevice(_THIS)
215 {
216 if (this->hidden != NULL) {
217 SDL_FreeAudioMem(this->hidden->mixbuf);
218 this->hidden->mixbuf = NULL;
219 if (this->hidden->audio_fd >= 0) {
220 close(this->hidden->audio_fd);
221 this->hidden->audio_fd = -1;
222 }
223 SDL_free(this->hidden);
224 this->hidden = NULL;
225 }
226 }
227
228 static int
229 BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
230 {
231 const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
232 SDL_AudioFormat format = 0;
233 audio_info_t info;
234
235 /* We don't care what the devname is...we'll try to open anything. */
236 /* ...but default to first name in the list... */
237 if (devname == NULL) {
238 devname = SDL_GetAudioDeviceName(0, iscapture);
239 if (devname == NULL) {
240 return SDL_SetError("No such audio device");
241 }
242 }
243
244 /* Initialize all variables that we clean on shutdown */
245 this->hidden = (struct SDL_PrivateAudioData *)
246 SDL_malloc((sizeof *this->hidden));
247 if (this->hidden == NULL) {
248 return SDL_OutOfMemory();
249 }
250 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
251
252 /* Open the audio device */
253 this->hidden->audio_fd = open(devname, flags, 0);
254 if (this->hidden->audio_fd < 0) {
255 return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
256 }
257
258 AUDIO_INITINFO(&info);
259
260 /* Calculate the final parameters for this audio specification */
261 SDL_CalculateAudioSpec(&this->spec);
262
263 /* Set to play mode */
264 info.mode = AUMODE_PLAY;
265 if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
266 BSDAUDIO_CloseDevice(this);
267 return SDL_SetError("Couldn't put device into play mode");
268 }
269
270 AUDIO_INITINFO(&info);
271 for (format = SDL_FirstAudioFormat(this->spec.format);
272 format; format = SDL_NextAudioFormat()) {
273 switch (format) {
274 case AUDIO_U8:
275 info.play.encoding = AUDIO_ENCODING_ULINEAR;
276 info.play.precision = 8;
277 break;
278 case AUDIO_S8:
279 info.play.encoding = AUDIO_ENCODING_SLINEAR;
280 info.play.precision = 8;
281 break;
282 case AUDIO_S16LSB:
283 info.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
284 info.play.precision = 16;
285 break;
286 case AUDIO_S16MSB:
287 info.play.encoding = AUDIO_ENCODING_SLINEAR_BE;
288 info.play.precision = 16;
289 break;
290 case AUDIO_U16LSB:
291 info.play.encoding = AUDIO_ENCODING_ULINEAR_LE;
292 info.play.precision = 16;
293 break;
294 case AUDIO_U16MSB:
295 info.play.encoding = AUDIO_ENCODING_ULINEAR_BE;
296 info.play.precision = 16;
297 break;
298 default:
299 continue;
300 }
301
302 if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) {
303 break;
304 }
305 }
306
307 if (!format) {
308 BSDAUDIO_CloseDevice(this);
309 return SDL_SetError("No supported encoding for 0x%x", this->spec.format);
310 }
311
312 this->spec.format = format;
313
314 AUDIO_INITINFO(&info);
315 info.play.channels = this->spec.channels;
316 if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) {
317 this->spec.channels = 1;
318 }
319 AUDIO_INITINFO(&info);
320 info.play.sample_rate = this->spec.freq;
321 info.blocksize = this->spec.size;
322 info.hiwat = 5;
323 info.lowat = 3;
324 (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
325 (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
326 this->spec.freq = info.play.sample_rate;
327 /* Allocate mixing buffer */
328 this->hidden->mixlen = this->spec.size;
329 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
330 if (this->hidden->mixbuf == NULL) {
331 BSDAUDIO_CloseDevice(this);
332 return SDL_OutOfMemory();
333 }
334 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
335
336 BSDAUDIO_Status(this);
337
338 /* We're ready to rock and roll. :-) */
339 return 0;
340 }
341
342 static int
343 BSDAUDIO_Init(SDL_AudioDriverImpl * impl)
344 {
345 /* Set the function pointers */
346 impl->DetectDevices = BSDAUDIO_DetectDevices;
347 impl->OpenDevice = BSDAUDIO_OpenDevice;
348 impl->PlayDevice = BSDAUDIO_PlayDevice;
349 impl->WaitDevice = BSDAUDIO_WaitDevice;
350 impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
351 impl->CloseDevice = BSDAUDIO_CloseDevice;
352
353 return 1; /* this audio target is available. */
354 }
355
356
357 AudioBootStrap BSD_AUDIO_bootstrap = {
358 "bsd", "BSD audio", BSDAUDIO_Init, 0
359 };
360
361 #endif /* SDL_AUDIO_DRIVER_BSD */
362
363 /* vi: set ts=4 sw=4 expandtab: */
SDL_AudioDriverImpl::CloseDevice
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:45
OPEN_FLAGS_INPUT
#define OPEN_FLAGS_INPUT
Definition: SDL_audiodev_c.h:33
SDL_FirstAudioFormat
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1226
Sint32
int32_t Sint32
A signed 32-bit integer type.
Definition: SDL_stdinc.h:141
void
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1824
message
GLsizei GLenum GLuint GLuint GLsizei GLchar * message
Definition: glew.h:2540
SDL_AddAudioDevice
void(* SDL_AddAudioDevice)(const char *name)
Definition: SDL_sysaudio.h:34
SDL_AudioDriverImpl::WaitDevice
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:41
SDL_EnumUnixAudioDevices
void SDL_EnumUnixAudioDevices(int iscapture, int classic, int(*test)(int fd), SDL_AddAudioDevice addfn)
NULL
#define NULL
Definition: ftobjs.h:61
AUDIO_U16LSB
#define AUDIO_U16LSB
Definition: SDL_audio.h:91
enabled
GLenum GLsizei const GLuint GLboolean enabled
Definition: glew.h:2538
SDL_AudioDriverImpl::GetDeviceBuf
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:43
SDL_FreeAudioMem
#define SDL_FreeAudioMem
Definition: SDL_audiomem.h:24
SDL_free
DECLSPEC void SDLCALL SDL_free(void *mem)
SDL_AudioFormat
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
SDL_AudioDriverImpl::OpenDevice
int(* OpenDevice)(_THIS, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:39
SDL_PrivateAudioData
Definition: SDL_alsa_audio.h:33
BSD_AUDIO_bootstrap
AudioBootStrap BSD_AUDIO_bootstrap
SDL_config.h
SDL_NextAudioFormat
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1238
SDL_AudioDriverImpl::PlayDevice
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:42
SDL_GetTicks
DECLSPEC Uint32 SDLCALL SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
Definition: SDL_systimer.c:44
AUDIO_U8
#define AUDIO_U8
Definition: SDL_audio.h:89
SDL_AudioDriverImpl::DetectDevices
void(* DetectDevices)(int iscapture, SDL_AddAudioDevice addfn)
Definition: SDL_sysaudio.h:38
AudioBootStrap
Definition: SDL_sysaudio.h:128
SDL_GetAudioDeviceName
DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(int index, int iscapture)
Definition: SDL_audio.c:708
OPEN_FLAGS_OUTPUT
#define OPEN_FLAGS_OUTPUT
Definition: SDL_audiodev_c.h:32
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
p
GLfloat GLfloat p
Definition: glew.h:14938
SDL_AudioDriverImpl
Definition: SDL_sysaudio.h:36
SDL_Delay
DECLSPEC void SDLCALL SDL_Delay(Uint32 ms)
Wait a specified number of milliseconds before returning.
Definition: SDL_systimer.c:70
SDL_memset
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
format
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl2ext.h:845
SDL_SetError
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
SDL_malloc
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
SDL_CalculateAudioSpec
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1247
SDL_AllocAudioMem
#define SDL_AllocAudioMem
Definition: SDL_audiomem.h:23
timeout
GLbitfield GLuint64 timeout
Definition: glew.h:5938
SDL_bsdaudio.h
FUDGE_TICKS
#define FUDGE_TICKS
Definition: SDL_artsaudio.h:49
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
flags
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
AUDIO_S16MSB
#define AUDIO_S16MSB
Definition: SDL_audio.h:94
SDL_audio.h
Uint8
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
AUDIO_S16LSB
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
types.h
SDL_timer.h
AUDIO_S8
#define AUDIO_S8
Definition: SDL_audio.h:90
AUDIO_U16MSB
#define AUDIO_U16MSB
Definition: SDL_audio.h:93