SDL 2.0
SDL_netbsdaudio.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 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_internal.h"
22
23#if SDL_AUDIO_DRIVER_NETBSD
24
25/*
26 * Driver for native 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 "../../core/unix/SDL_poll.h"
42#include "../SDL_audio_c.h"
43#include "../SDL_audiodev_c.h"
44#include "SDL_netbsdaudio.h"
45
46/* #define DEBUG_AUDIO */
47
48static void
49NETBSDAUDIO_DetectDevices(void)
50{
52}
53
54
55static void
56NETBSDAUDIO_Status(_THIS)
57{
58#ifdef DEBUG_AUDIO
59 /* *INDENT-OFF* */
60 audio_info_t info;
61 const struct audio_prinfo *prinfo;
62
63 if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
64 fprintf(stderr, "AUDIO_GETINFO failed.\n");
65 return;
66 }
67
68 prinfo = this->iscapture ? &info.record : &info.play;
69
70 fprintf(stderr, "\n"
71 "[%s info]\n"
72 "buffer size : %d bytes\n"
73 "sample rate : %i Hz\n"
74 "channels : %i\n"
75 "precision : %i-bit\n"
76 "encoding : 0x%x\n"
77 "seek : %i\n"
78 "sample count : %i\n"
79 "EOF count : %i\n"
80 "paused : %s\n"
81 "error occured : %s\n"
82 "waiting : %s\n"
83 "active : %s\n"
84 "",
85 this->iscapture ? "record" : "play",
86 prinfo->buffer_size,
87 prinfo->sample_rate,
88 prinfo->channels,
89 prinfo->precision,
90 prinfo->encoding,
91 prinfo->seek,
92 prinfo->samples,
93 prinfo->eof,
94 prinfo->pause ? "yes" : "no",
95 prinfo->error ? "yes" : "no",
96 prinfo->waiting ? "yes" : "no",
97 prinfo->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
114 fprintf(stderr, "\n"
115 "[audio spec]\n"
116 "format : 0x%x\n"
117 "size : %u\n"
118 "",
119 this->spec.format,
120 this->spec.size);
121 /* *INDENT-ON* */
122#endif /* DEBUG_AUDIO */
123}
124
125
126static void
127NETBSDAUDIO_PlayDevice(_THIS)
128{
129 struct SDL_PrivateAudioData *h = this->hidden;
130 int written;
131
132 /* Write the audio data */
133 written = write(h->audio_fd, h->mixbuf, h->mixlen);
134 if (written == -1) {
135 /* Non recoverable error has occurred. It should be reported!!! */
137 perror("audio");
138 return;
139 }
140
141#ifdef DEBUG_AUDIO
142 fprintf(stderr, "Wrote %d bytes of audio data\n", written);
143#endif
144}
145
146static Uint8 *
147NETBSDAUDIO_GetDeviceBuf(_THIS)
148{
149 return (this->hidden->mixbuf);
150}
151
152
153static int
154NETBSDAUDIO_CaptureFromDevice(_THIS, void *_buffer, int buflen)
155{
156 Uint8 *buffer = (Uint8 *) _buffer;
157 int br;
158
159 br = read(this->hidden->audio_fd, buffer, buflen);
160 if (br == -1) {
161 /* Non recoverable error has occurred. It should be reported!!! */
162 perror("audio");
163 return -1;
164 }
165
166#ifdef DEBUG_AUDIO
167 fprintf(stderr, "Captured %d bytes of audio data\n", br);
168#endif
169 return 0;
170}
171
172static void
173NETBSDAUDIO_FlushCapture(_THIS)
174{
175 audio_info_t info;
176 size_t remain;
177 Uint8 buf[512];
178
179 if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
180 return; /* oh well. */
181 }
182
183 remain = (size_t) (info.record.samples * (SDL_AUDIO_BITSIZE(this->spec.format) / 8));
184 while (remain > 0) {
185 const size_t len = SDL_min(sizeof (buf), remain);
186 const int br = read(this->hidden->audio_fd, buf, len);
187 if (br <= 0) {
188 return; /* oh well. */
189 }
190 remain -= br;
191 }
192}
193
194static void
195NETBSDAUDIO_CloseDevice(_THIS)
196{
197 if (this->hidden->audio_fd >= 0) {
198 close(this->hidden->audio_fd);
199 }
200 SDL_free(this->hidden->mixbuf);
201 SDL_free(this->hidden);
202}
203
204static int
205NETBSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
206{
208 audio_info_t info;
209 struct audio_prinfo *prinfo = iscapture ? &info.record : &info.play;
210
211 /* We don't care what the devname is...we'll try to open anything. */
212 /* ...but default to first name in the list... */
213 if (devname == NULL) {
214 devname = SDL_GetAudioDeviceName(0, iscapture);
215 if (devname == NULL) {
216 return SDL_SetError("No such audio device");
217 }
218 }
219
220 /* Initialize all variables that we clean on shutdown */
221 this->hidden = (struct SDL_PrivateAudioData *)
222 SDL_malloc((sizeof *this->hidden));
223 if (this->hidden == NULL) {
224 return SDL_OutOfMemory();
225 }
226 SDL_zerop(this->hidden);
227
228 /* Open the audio device */
229 this->hidden->audio_fd = open(devname, iscapture ? O_RDONLY : O_WRONLY);
230 if (this->hidden->audio_fd < 0) {
231 return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
232 }
233
234 AUDIO_INITINFO(&info);
235
236 prinfo->encoding = AUDIO_ENCODING_NONE;
237
238 for (format = SDL_FirstAudioFormat(this->spec.format); format;) {
239 switch (format) {
240 case AUDIO_U8:
241 prinfo->encoding = AUDIO_ENCODING_ULINEAR;
242 prinfo->precision = 8;
243 break;
244 case AUDIO_S8:
245 prinfo->encoding = AUDIO_ENCODING_SLINEAR;
246 prinfo->precision = 8;
247 break;
248 case AUDIO_S16LSB:
249 prinfo->encoding = AUDIO_ENCODING_SLINEAR_LE;
250 prinfo->precision = 16;
251 break;
252 case AUDIO_S16MSB:
253 prinfo->encoding = AUDIO_ENCODING_SLINEAR_BE;
254 prinfo->precision = 16;
255 break;
256 case AUDIO_U16LSB:
257 prinfo->encoding = AUDIO_ENCODING_ULINEAR_LE;
258 prinfo->precision = 16;
259 break;
260 case AUDIO_U16MSB:
261 prinfo->encoding = AUDIO_ENCODING_ULINEAR_BE;
262 prinfo->precision = 16;
263 break;
264 }
265 if (prinfo->encoding != AUDIO_ENCODING_NONE) {
266 break;
267 }
269 }
270
271 if (prinfo->encoding == AUDIO_ENCODING_NONE) {
272 return SDL_SetError("No supported encoding for 0x%x", this->spec.format);
273 }
274
275 this->spec.format = format;
276
277 /* Calculate spec parameters based on our chosen format */
279
280 info.mode = iscapture ? AUMODE_RECORD : AUMODE_PLAY;
281 info.blocksize = this->spec.size;
282 info.hiwat = 5;
283 info.lowat = 3;
284 prinfo->sample_rate = this->spec.freq;
285 prinfo->channels = this->spec.channels;
286 (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
287
288 (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
289 this->spec.freq = prinfo->sample_rate;
290 this->spec.channels = prinfo->channels;
291
292 if (!iscapture) {
293 /* Allocate mixing buffer */
294 this->hidden->mixlen = this->spec.size;
295 this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
296 if (this->hidden->mixbuf == NULL) {
297 return SDL_OutOfMemory();
298 }
299 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
300 }
301
302 NETBSDAUDIO_Status(this);
303
304 /* We're ready to rock and roll. :-) */
305 return 0;
306}
307
308static int
309NETBSDAUDIO_Init(SDL_AudioDriverImpl * impl)
310{
311 /* Set the function pointers */
312 impl->DetectDevices = NETBSDAUDIO_DetectDevices;
313 impl->OpenDevice = NETBSDAUDIO_OpenDevice;
314 impl->PlayDevice = NETBSDAUDIO_PlayDevice;
315 impl->GetDeviceBuf = NETBSDAUDIO_GetDeviceBuf;
316 impl->CloseDevice = NETBSDAUDIO_CloseDevice;
317 impl->CaptureFromDevice = NETBSDAUDIO_CaptureFromDevice;
318 impl->FlushCapture = NETBSDAUDIO_FlushCapture;
319
322
323 return 1; /* this audio target is available. */
324}
325
326
328 "netbsd", "NetBSD audio", NETBSDAUDIO_Init, 0
329};
330
331#endif /* SDL_AUDIO_DRIVER_NETBSD */
332
333/* vi: set ts=4 sw=4 expandtab: */
#define _THIS
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1668
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1647
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
Definition: SDL_audio.c:486
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1659
#define AUDIO_U16LSB
Definition: SDL_audio.h:91
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
#define AUDIO_S16MSB
Definition: SDL_audio.h:94
#define AUDIO_U16MSB
Definition: SDL_audio.h:93
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
#define AUDIO_U8
Definition: SDL_audio.h:89
#define AUDIO_S8
Definition: SDL_audio.h:90
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
void SDL_EnumUnixAudioDevices(const int classic, int(*test)(int))
unsigned int size_t
#define SDL_SetError
#define SDL_memset
#define SDL_GetAudioDeviceName
#define SDL_malloc
#define SDL_free
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
GLenum GLsizei len
GLuint buffer
GLenum GLuint GLenum GLsizei const GLchar * buf
GLfloat GLfloat GLfloat GLfloat h
@ SDL_TRUE
Definition: SDL_stdinc.h:164
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
uint8_t Uint8
Definition: SDL_stdinc.h:179
AudioBootStrap NETBSDAUDIO_bootstrap
#define NULL
Definition: begin_code.h:167
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
SDL_AudioSpec spec
Definition: loopwave.c:31
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:73
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:78
void(* FlushCapture)(_THIS)
Definition: SDL_sysaudio.h:76
void(* DetectDevices)(void)
Definition: SDL_sysaudio.h:67
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
Definition: SDL_sysaudio.h:75
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:68
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:74
Uint32 size
Definition: SDL_audio.h:186
Uint8 channels
Definition: SDL_audio.h:182
SDL_AudioFormat format
Definition: SDL_audio.h:181