Skip to content

Latest commit

 

History

History
333 lines (282 loc) · 9.21 KB

SDL_netbsdaudio.c

File metadata and controls

333 lines (282 loc) · 9.21 KB
 
1
2
/*
Simple DirectMedia Layer
Jan 17, 2020
Jan 17, 2020
3
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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.
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:
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.
*/
#include "../../SDL_internal.h"
May 24, 2017
May 24, 2017
23
#if SDL_AUDIO_DRIVER_NETBSD
May 24, 2017
May 24, 2017
26
* Driver for native NetBSD audio(4).
27
28
29
30
31
32
33
34
35
36
37
38
39
40
* vedge@vedge.com.ar.
*/
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/audioio.h>
#include "SDL_timer.h"
#include "SDL_audio.h"
Aug 15, 2017
Aug 15, 2017
41
#include "../../core/unix/SDL_poll.h"
42
43
#include "../SDL_audio_c.h"
#include "../SDL_audiodev_c.h"
Jun 29, 2017
Jun 29, 2017
44
#include "SDL_netbsdaudio.h"
45
46
47
48
/* #define DEBUG_AUDIO */
static void
May 24, 2017
May 24, 2017
49
NETBSDAUDIO_DetectDevices(void)
50
51
52
53
54
55
{
SDL_EnumUnixAudioDevices(0, NULL);
}
static void
May 24, 2017
May 24, 2017
56
NETBSDAUDIO_Status(_THIS)
57
58
59
60
{
#ifdef DEBUG_AUDIO
/* *INDENT-OFF* */
audio_info_t info;
Jun 8, 2019
Jun 8, 2019
61
const struct audio_prinfo *prinfo;
62
63
64
65
66
if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
fprintf(stderr, "AUDIO_GETINFO failed.\n");
return;
}
Aug 3, 2016
Aug 3, 2016
67
Jun 8, 2019
Jun 8, 2019
68
prinfo = this->iscapture ? &info.record : &info.play;
Aug 3, 2016
Aug 3, 2016
69
70
fprintf(stderr, "\n"
Aug 3, 2016
Aug 3, 2016
71
"[%s info]\n"
72
73
74
75
76
77
78
79
80
81
82
83
84
"buffer size : %d bytes\n"
"sample rate : %i Hz\n"
"channels : %i\n"
"precision : %i-bit\n"
"encoding : 0x%x\n"
"seek : %i\n"
"sample count : %i\n"
"EOF count : %i\n"
"paused : %s\n"
"error occured : %s\n"
"waiting : %s\n"
"active : %s\n"
"",
Aug 3, 2016
Aug 3, 2016
85
86
87
88
89
90
91
92
93
94
95
96
97
this->iscapture ? "record" : "play",
prinfo->buffer_size,
prinfo->sample_rate,
prinfo->channels,
prinfo->precision,
prinfo->encoding,
prinfo->seek,
prinfo->samples,
prinfo->eof,
prinfo->pause ? "yes" : "no",
prinfo->error ? "yes" : "no",
prinfo->waiting ? "yes" : "no",
prinfo->active ? "yes" : "no");
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
fprintf(stderr, "\n"
"[audio info]\n"
"monitor_gain : %i\n"
"hw block size : %d bytes\n"
"hi watermark : %i\n"
"lo watermark : %i\n"
"audio mode : %s\n"
"",
info.monitor_gain,
info.blocksize,
info.hiwat, info.lowat,
(info.mode == AUMODE_PLAY) ? "PLAY"
: (info.mode = AUMODE_RECORD) ? "RECORD"
: (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?"));
Jun 8, 2019
Jun 8, 2019
113
114
115
116
117
118
119
120
fprintf(stderr, "\n"
"[audio spec]\n"
"format : 0x%x\n"
"size : %u\n"
"",
this->spec.format,
this->spec.size);
121
122
123
124
125
126
/* *INDENT-ON* */
#endif /* DEBUG_AUDIO */
}
static void
May 24, 2017
May 24, 2017
127
NETBSDAUDIO_PlayDevice(_THIS)
Jun 8, 2019
Jun 8, 2019
129
130
struct SDL_PrivateAudioData *h = this->hidden;
int written;
Jun 8, 2019
Jun 8, 2019
132
133
134
135
/* Write the audio data */
written = write(h->audio_fd, h->mixbuf, h->mixlen);
if (written == -1) {
/* Non recoverable error has occurred. It should be reported!!! */
136
SDL_OpenedAudioDeviceDisconnected(this);
Jun 8, 2019
Jun 8, 2019
137
138
perror("audio");
return;
Jun 8, 2019
Jun 8, 2019
140
141
142
143
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
#endif
144
145
146
}
static Uint8 *
May 24, 2017
May 24, 2017
147
NETBSDAUDIO_GetDeviceBuf(_THIS)
148
149
150
151
{
return (this->hidden->mixbuf);
}
Aug 3, 2016
Aug 3, 2016
152
153
static int
May 24, 2017
May 24, 2017
154
NETBSDAUDIO_CaptureFromDevice(_THIS, void *_buffer, int buflen)
Aug 3, 2016
Aug 3, 2016
155
156
{
Uint8 *buffer = (Uint8 *) _buffer;
Jun 8, 2019
Jun 8, 2019
157
158
159
160
161
162
163
164
int br;
br = read(this->hidden->audio_fd, buffer, buflen);
if (br == -1) {
/* Non recoverable error has occurred. It should be reported!!! */
perror("audio");
return -1;
}
Aug 3, 2016
Aug 3, 2016
165
166
#ifdef DEBUG_AUDIO
Jun 8, 2019
Jun 8, 2019
167
fprintf(stderr, "Captured %d bytes of audio data\n", br);
Aug 3, 2016
Aug 3, 2016
168
#endif
Jun 8, 2019
Jun 8, 2019
169
return 0;
Aug 3, 2016
Aug 3, 2016
170
171
172
}
static void
May 24, 2017
May 24, 2017
173
NETBSDAUDIO_FlushCapture(_THIS)
Aug 3, 2016
Aug 3, 2016
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
{
audio_info_t info;
size_t remain;
Uint8 buf[512];
if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
return; /* oh well. */
}
remain = (size_t) (info.record.samples * (SDL_AUDIO_BITSIZE(this->spec.format) / 8));
while (remain > 0) {
const size_t len = SDL_min(sizeof (buf), remain);
const int br = read(this->hidden->audio_fd, buf, len);
if (br <= 0) {
return; /* oh well. */
}
remain -= br;
}
}
May 24, 2017
May 24, 2017
195
NETBSDAUDIO_CloseDevice(_THIS)
Aug 5, 2016
Aug 5, 2016
197
198
if (this->hidden->audio_fd >= 0) {
close(this->hidden->audio_fd);
Aug 5, 2016
Aug 5, 2016
200
SDL_free(this->hidden->mixbuf);
Aug 5, 2016
Aug 5, 2016
201
SDL_free(this->hidden);
May 24, 2017
May 24, 2017
205
NETBSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
206
207
208
{
SDL_AudioFormat format = 0;
audio_info_t info;
Jun 8, 2019
Jun 8, 2019
209
struct audio_prinfo *prinfo = iscapture ? &info.record : &info.play;
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/* We don't care what the devname is...we'll try to open anything. */
/* ...but default to first name in the list... */
if (devname == NULL) {
devname = SDL_GetAudioDeviceName(0, iscapture);
if (devname == NULL) {
return SDL_SetError("No such audio device");
}
}
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
Aug 5, 2016
Aug 5, 2016
226
SDL_zerop(this->hidden);
227
228
/* Open the audio device */
Jun 8, 2019
Jun 8, 2019
229
this->hidden->audio_fd = open(devname, iscapture ? O_RDONLY : O_WRONLY);
230
231
232
233
234
235
if (this->hidden->audio_fd < 0) {
return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
}
AUDIO_INITINFO(&info);
Jun 8, 2019
Jun 8, 2019
236
prinfo->encoding = AUDIO_ENCODING_NONE;
Jun 8, 2019
Jun 8, 2019
238
for (format = SDL_FirstAudioFormat(this->spec.format); format;) {
239
240
switch (format) {
case AUDIO_U8:
Aug 3, 2016
Aug 3, 2016
241
242
prinfo->encoding = AUDIO_ENCODING_ULINEAR;
prinfo->precision = 8;
243
244
break;
case AUDIO_S8:
Aug 3, 2016
Aug 3, 2016
245
246
prinfo->encoding = AUDIO_ENCODING_SLINEAR;
prinfo->precision = 8;
247
248
break;
case AUDIO_S16LSB:
Aug 3, 2016
Aug 3, 2016
249
250
prinfo->encoding = AUDIO_ENCODING_SLINEAR_LE;
prinfo->precision = 16;
251
252
break;
case AUDIO_S16MSB:
Aug 3, 2016
Aug 3, 2016
253
254
prinfo->encoding = AUDIO_ENCODING_SLINEAR_BE;
prinfo->precision = 16;
255
256
break;
case AUDIO_U16LSB:
Aug 3, 2016
Aug 3, 2016
257
258
prinfo->encoding = AUDIO_ENCODING_ULINEAR_LE;
prinfo->precision = 16;
259
260
break;
case AUDIO_U16MSB:
Aug 3, 2016
Aug 3, 2016
261
262
prinfo->encoding = AUDIO_ENCODING_ULINEAR_BE;
prinfo->precision = 16;
Jun 8, 2019
Jun 8, 2019
265
if (prinfo->encoding != AUDIO_ENCODING_NONE) {
Jun 8, 2019
Jun 8, 2019
268
format = SDL_NextAudioFormat();
Jun 8, 2019
Jun 8, 2019
271
if (prinfo->encoding == AUDIO_ENCODING_NONE) {
272
273
274
275
276
return SDL_SetError("No supported encoding for 0x%x", this->spec.format);
}
this->spec.format = format;
Jun 8, 2019
Jun 8, 2019
277
278
279
280
/* Calculate spec parameters based on our chosen format */
SDL_CalculateAudioSpec(&this->spec);
info.mode = iscapture ? AUMODE_RECORD : AUMODE_PLAY;
281
282
283
info.blocksize = this->spec.size;
info.hiwat = 5;
info.lowat = 3;
Jun 8, 2019
Jun 8, 2019
284
285
prinfo->sample_rate = this->spec.freq;
prinfo->channels = this->spec.channels;
286
(void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
Jun 8, 2019
Jun 8, 2019
287
288
(void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
Aug 3, 2016
Aug 3, 2016
289
this->spec.freq = prinfo->sample_rate;
Jun 8, 2019
Jun 8, 2019
290
this->spec.channels = prinfo->channels;
Aug 3, 2016
Aug 3, 2016
291
292
293
294
if (!iscapture) {
/* Allocate mixing buffer */
this->hidden->mixlen = this->spec.size;
Aug 5, 2016
Aug 5, 2016
295
this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
Aug 3, 2016
Aug 3, 2016
296
297
298
299
if (this->hidden->mixbuf == NULL) {
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
May 24, 2017
May 24, 2017
302
NETBSDAUDIO_Status(this);
303
304
305
306
307
308
/* We're ready to rock and roll. :-) */
return 0;
}
static int
May 24, 2017
May 24, 2017
309
NETBSDAUDIO_Init(SDL_AudioDriverImpl * impl)
310
311
{
/* Set the function pointers */
May 24, 2017
May 24, 2017
312
313
314
315
316
317
318
impl->DetectDevices = NETBSDAUDIO_DetectDevices;
impl->OpenDevice = NETBSDAUDIO_OpenDevice;
impl->PlayDevice = NETBSDAUDIO_PlayDevice;
impl->GetDeviceBuf = NETBSDAUDIO_GetDeviceBuf;
impl->CloseDevice = NETBSDAUDIO_CloseDevice;
impl->CaptureFromDevice = NETBSDAUDIO_CaptureFromDevice;
impl->FlushCapture = NETBSDAUDIO_FlushCapture;
Aug 3, 2016
Aug 3, 2016
320
impl->HasCaptureSupport = SDL_TRUE;
321
322
323
324
325
326
impl->AllowsArbitraryDeviceNames = 1;
return 1; /* this audio target is available. */
}
May 24, 2017
May 24, 2017
327
328
AudioBootStrap NETBSDAUDIO_bootstrap = {
"netbsd", "NetBSD audio", NETBSDAUDIO_Init, 0
May 24, 2017
May 24, 2017
331
#endif /* SDL_AUDIO_DRIVER_NETBSD */
332
333
/* vi: set ts=4 sw=4 expandtab: */