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

Latest commit

 

History

History
292 lines (251 loc) · 8.58 KB

SDL_nasaudio.c

File metadata and controls

292 lines (251 loc) · 8.58 KB
 
Apr 26, 2001
Apr 26, 2001
1
2
/*
SDL - Simple DirectMedia Layer
Feb 1, 2006
Feb 1, 2006
3
Copyright (C) 1997-2006 Sam Lantinga
Apr 26, 2001
Apr 26, 2001
4
5
This library is free software; you can redistribute it and/or
Feb 1, 2006
Feb 1, 2006
6
modify it under the terms of the GNU Lesser General Public
Apr 26, 2001
Apr 26, 2001
7
License as published by the Free Software Foundation; either
Feb 1, 2006
Feb 1, 2006
8
version 2.1 of the License, or (at your option) any later version.
Apr 26, 2001
Apr 26, 2001
9
10
11
12
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Feb 1, 2006
Feb 1, 2006
13
Lesser General Public License for more details.
Apr 26, 2001
Apr 26, 2001
14
Feb 1, 2006
Feb 1, 2006
15
16
17
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Apr 26, 2001
Apr 26, 2001
18
19
Sam Lantinga
Dec 14, 2001
Dec 14, 2001
20
slouken@libsdl.org
Apr 26, 2001
Apr 26, 2001
21
22
23
24
25
This driver was written by:
Erik Inge Bolsø
knan@mo.himolde.no
*/
Feb 21, 2006
Feb 21, 2006
26
#include "SDL_config.h"
Apr 26, 2001
Apr 26, 2001
27
28
29
30
31
32
/* Allow access to a raw mixing buffer */
#include <signal.h>
#include <unistd.h>
Feb 10, 2006
Feb 10, 2006
33
#include "SDL_timer.h"
Apr 26, 2001
Apr 26, 2001
34
#include "SDL_audio.h"
Feb 16, 2006
Feb 16, 2006
35
36
#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
Apr 26, 2001
Apr 26, 2001
37
38
#include "SDL_nasaudio.h"
Oct 7, 2006
Oct 7, 2006
39
/* The tag name used by nas audio */
Apr 26, 2001
Apr 26, 2001
40
41
42
43
#define NAS_DRIVER_NAME "nas"
static struct SDL_PrivateAudioData *this2 = NULL;
Oct 7, 2006
Oct 7, 2006
44
/* !!! FIXME: dynamic loading? */
Apr 26, 2001
Apr 26, 2001
45
Jul 10, 2006
Jul 10, 2006
46
static int
Oct 7, 2006
Oct 7, 2006
47
NAS_Available(void)
Apr 26, 2001
Apr 26, 2001
48
{
Jul 10, 2006
Jul 10, 2006
49
50
51
AuServer *aud = AuOpenServer("", 0, NULL, 0, NULL, NULL);
if (!aud)
return 0;
Apr 26, 2001
Apr 26, 2001
52
Jul 10, 2006
Jul 10, 2006
53
54
AuCloseServer(aud);
return 1;
Apr 26, 2001
Apr 26, 2001
55
56
57
}
/* This function waits until it is possible to write a full sound buffer */
Jul 10, 2006
Jul 10, 2006
58
static void
Oct 7, 2006
Oct 7, 2006
59
NAS_WaitDevice(_THIS)
Apr 26, 2001
Apr 26, 2001
60
{
Jul 10, 2006
Jul 10, 2006
61
62
63
64
65
while (this->hidden->buf_free < this->hidden->mixlen) {
AuEvent ev;
AuNextEvent(this->hidden->aud, AuTrue, &ev);
AuDispatchEvent(this->hidden->aud, &ev);
}
Apr 26, 2001
Apr 26, 2001
66
67
}
Jul 10, 2006
Jul 10, 2006
68
static void
Oct 7, 2006
Oct 7, 2006
69
NAS_PlayDevice(_THIS)
Apr 26, 2001
Apr 26, 2001
70
{
Oct 7, 2006
Oct 7, 2006
71
72
73
74
75
76
while (this->hidden->mixlen > this->hidden->buf_free) {
/*
* We think the buffer is full? Yikes! Ask the server for events,
* in the hope that some of them is LowWater events telling us more
* of the buffer is free now than what we think.
*/
Jul 10, 2006
Jul 10, 2006
77
78
79
80
81
82
83
84
85
86
87
88
AuEvent ev;
AuNextEvent(this->hidden->aud, AuTrue, &ev);
AuDispatchEvent(this->hidden->aud, &ev);
}
this->hidden->buf_free -= this->hidden->mixlen;
/* Write the audio data */
AuWriteElement(this->hidden->aud, this->hidden->flow, 0,
this->hidden->mixlen, this->hidden->mixbuf, AuFalse, NULL);
this->hidden->written += this->hidden->mixlen;
Apr 26, 2001
Apr 26, 2001
89
#ifdef DEBUG_AUDIO
Jul 10, 2006
Jul 10, 2006
90
fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
Apr 26, 2001
Apr 26, 2001
91
92
93
#endif
}
Jul 10, 2006
Jul 10, 2006
94
static Uint8 *
Oct 7, 2006
Oct 7, 2006
95
NAS_GetDeviceBuf(_THIS)
Apr 26, 2001
Apr 26, 2001
96
{
Jul 10, 2006
Jul 10, 2006
97
return (this->hidden->mixbuf);
Apr 26, 2001
Apr 26, 2001
98
99
}
Jul 10, 2006
Jul 10, 2006
100
static void
Oct 7, 2006
Oct 7, 2006
101
NAS_CloseDevice(_THIS)
Apr 26, 2001
Apr 26, 2001
102
{
Oct 7, 2006
Oct 7, 2006
103
104
105
106
107
108
109
110
111
112
113
if (this->hidden != NULL) {
if (this->hidden->mixbuf != NULL) {
SDL_FreeAudioMem(this->hidden->mixbuf);
this->hidden->mixbuf = NULL;
}
if (this->hidden->aud) {
AuCloseServer(this->hidden->aud);
this->hidden->aud = 0;
}
SDL_free(this->hidden);
this->hidden = NULL;
Jul 10, 2006
Jul 10, 2006
114
}
Apr 26, 2001
Apr 26, 2001
115
116
}
Jul 10, 2006
Jul 10, 2006
117
118
static unsigned char
sdlformat_to_auformat(unsigned int fmt)
Apr 26, 2001
Apr 26, 2001
119
{
Jul 10, 2006
Jul 10, 2006
120
switch (fmt) {
Apr 26, 2001
Apr 26, 2001
121
case AUDIO_U8:
Jul 10, 2006
Jul 10, 2006
122
return AuFormatLinearUnsigned8;
Apr 26, 2001
Apr 26, 2001
123
case AUDIO_S8:
Jul 10, 2006
Jul 10, 2006
124
return AuFormatLinearSigned8;
Apr 26, 2001
Apr 26, 2001
125
case AUDIO_U16LSB:
Jul 10, 2006
Jul 10, 2006
126
return AuFormatLinearUnsigned16LSB;
Apr 26, 2001
Apr 26, 2001
127
case AUDIO_U16MSB:
Jul 10, 2006
Jul 10, 2006
128
return AuFormatLinearUnsigned16MSB;
Apr 26, 2001
Apr 26, 2001
129
case AUDIO_S16LSB:
Jul 10, 2006
Jul 10, 2006
130
return AuFormatLinearSigned16LSB;
Apr 26, 2001
Apr 26, 2001
131
case AUDIO_S16MSB:
Jul 10, 2006
Jul 10, 2006
132
return AuFormatLinearSigned16MSB;
Apr 26, 2001
Apr 26, 2001
133
}
Jul 10, 2006
Jul 10, 2006
134
return AuNone;
Apr 26, 2001
Apr 26, 2001
135
136
137
}
static AuBool
Jul 10, 2006
Jul 10, 2006
138
event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
Apr 26, 2001
Apr 26, 2001
139
{
Jul 10, 2006
Jul 10, 2006
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
switch (ev->type) {
case AuEventTypeElementNotify:
{
AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;
switch (event->kind) {
case AuElementNotifyKindLowWater:
if (this2->buf_free >= 0) {
this2->really += event->num_bytes;
gettimeofday(&this2->last_tv, 0);
this2->buf_free += event->num_bytes;
} else {
this2->buf_free = event->num_bytes;
}
break;
case AuElementNotifyKindState:
switch (event->cur_state) {
case AuStatePause:
if (event->reason != AuReasonUser) {
if (this2->buf_free >= 0) {
this2->really += event->num_bytes;
gettimeofday(&this2->last_tv, 0);
this2->buf_free += event->num_bytes;
} else {
this2->buf_free = event->num_bytes;
}
}
break;
}
}
}
}
return AuTrue;
Apr 26, 2001
Apr 26, 2001
173
174
175
176
177
}
static AuDeviceID
find_device(_THIS, int nch)
{
Jul 10, 2006
Jul 10, 2006
178
179
180
181
182
183
184
185
186
int i;
for (i = 0; i < AuServerNumDevices(this->hidden->aud); i++) {
if ((AuDeviceKind(AuServerDevice(this->hidden->aud, i)) ==
AuComponentKindPhysicalOutput) &&
AuDeviceNumTracks(AuServerDevice(this->hidden->aud, i)) == nch) {
return AuDeviceIdentifier(AuServerDevice(this->hidden->aud, i));
}
}
return AuNone;
Apr 26, 2001
Apr 26, 2001
187
188
}
Jul 10, 2006
Jul 10, 2006
189
static int
Oct 7, 2006
Oct 7, 2006
190
NAS_OpenDevice(_THIS, const char *devname, int iscapture)
Apr 26, 2001
Apr 26, 2001
191
{
Jul 10, 2006
Jul 10, 2006
192
193
AuElement elms[3];
int buffer_size;
Aug 24, 2006
Aug 24, 2006
194
SDL_AudioFormat test_format, format;
Jul 10, 2006
Jul 10, 2006
195
Oct 7, 2006
Oct 7, 2006
196
197
198
199
200
201
202
203
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
SDL_OutOfMemory();
return 0;
}
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
Jul 10, 2006
Jul 10, 2006
204
205
206
/* Try for a closest match on audio format */
format = 0;
Oct 7, 2006
Oct 7, 2006
207
for (test_format = SDL_FirstAudioFormat(this->spec.format);
Jul 10, 2006
Jul 10, 2006
208
209
210
211
212
213
214
!format && test_format;) {
format = sdlformat_to_auformat(test_format);
if (format == AuNone) {
test_format = SDL_NextAudioFormat();
}
}
if (format == 0) {
Oct 7, 2006
Oct 7, 2006
215
216
217
NAS_CloseDevice(this);
SDL_SetError("NAS: Couldn't find any hardware audio formats");
return 0;
Jul 10, 2006
Jul 10, 2006
218
}
Oct 7, 2006
Oct 7, 2006
219
this->spec.format = test_format;
Jul 10, 2006
Jul 10, 2006
220
221
222
this->hidden->aud = AuOpenServer("", 0, NULL, 0, NULL, NULL);
if (this->hidden->aud == 0) {
Oct 7, 2006
Oct 7, 2006
223
224
225
NAS_CloseDevice(this);
SDL_SetError("NAS: Couldn't open connection to NAS server");
return 0;
Jul 10, 2006
Jul 10, 2006
226
227
}
Oct 7, 2006
Oct 7, 2006
228
this->hidden->dev = find_device(this, this->spec.channels);
Jul 10, 2006
Jul 10, 2006
229
230
if ((this->hidden->dev == AuNone)
|| (!(this->hidden->flow = AuCreateFlow(this->hidden->aud, NULL)))) {
Oct 7, 2006
Oct 7, 2006
231
232
233
NAS_CloseDevice(this);
SDL_SetError("NAS: Couldn't find a fitting device on NAS server");
return 0;
Jul 10, 2006
Jul 10, 2006
234
235
}
Oct 7, 2006
Oct 7, 2006
236
buffer_size = this->spec.freq;
Jul 10, 2006
Jul 10, 2006
237
238
239
240
241
242
243
if (buffer_size < 4096)
buffer_size = 4096;
if (buffer_size > 32768)
buffer_size = 32768; /* So that the buffer won't get unmanageably big. */
/* Calculate the final parameters for this audio specification */
Oct 7, 2006
Oct 7, 2006
244
SDL_CalculateAudioSpec(&this->spec);
Jul 10, 2006
Jul 10, 2006
245
246
247
this2 = this->hidden;
Oct 7, 2006
Oct 7, 2006
248
AuMakeElementImportClient(elms,this->spec.freq,format,this->spec.channels,
Jul 10, 2006
Jul 10, 2006
249
AuTrue, buffer_size, buffer_size / 4, 0, NULL);
Oct 7, 2006
Oct 7, 2006
250
AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq,
Jul 10, 2006
Jul 10, 2006
251
AuUnlimitedSamples, 0, NULL);
Oct 7, 2006
Oct 7, 2006
252
AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms, NULL);
Jul 10, 2006
Jul 10, 2006
253
254
255
256
257
258
259
AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
this->hidden->flow, event_handler,
(AuPointer) NULL);
AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);
/* Allocate mixing buffer */
Oct 7, 2006
Oct 7, 2006
260
this->hidden->mixlen = this->spec.size;
Jul 10, 2006
Jul 10, 2006
261
262
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
Oct 7, 2006
Oct 7, 2006
263
264
NAS_CloseDevice(this);
SDL_OutOfMemory();
Jul 10, 2006
Jul 10, 2006
265
266
return (-1);
}
Oct 7, 2006
Oct 7, 2006
267
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
Jul 10, 2006
Jul 10, 2006
268
269
/* We're ready to rock and roll. :-) */
Oct 7, 2006
Oct 7, 2006
270
return 1;
Apr 26, 2001
Apr 26, 2001
271
}
Jul 10, 2006
Jul 10, 2006
272
Oct 7, 2006
Oct 7, 2006
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
static int
NAS_Init(SDL_AudioDriverImpl *impl)
{
/* Set the function pointers */
impl->OpenDevice = NAS_OpenDevice;
impl->PlayDevice = NAS_PlayDevice;
impl->WaitDevice = NAS_WaitDevice;
impl->GetDeviceBuf = NAS_GetDeviceBuf;
impl->CloseDevice = NAS_CloseDevice;
impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: is this true? */
return 1;
}
AudioBootStrap NAS_bootstrap = {
NAS_DRIVER_NAME, "Network Audio System",
NAS_Available, NAS_Init, 0
};
Jul 10, 2006
Jul 10, 2006
292
/* vi: set ts=4 sw=4 expandtab: */