Cleaning out SDL_audiodev.c and related references ...
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 This driver was written by:
26 #include "SDL_config.h"
28 /* Allow access to a raw mixing buffer */
33 #include "SDL_timer.h"
34 #include "SDL_audio.h"
35 #include "../SDL_audiomem.h"
36 #include "../SDL_audio_c.h"
37 #include "SDL_nasaudio.h"
39 /* The tag name used by artsc audio */
40 #define NAS_DRIVER_NAME "nas"
42 static struct SDL_PrivateAudioData *this2 = NULL;
44 /* Audio driver functions */
45 static int NAS_OpenAudio(_THIS, SDL_AudioSpec * spec);
46 static void NAS_WaitAudio(_THIS);
47 static void NAS_PlayAudio(_THIS);
48 static Uint8 *NAS_GetAudioBuf(_THIS);
49 static void NAS_CloseAudio(_THIS);
51 /* Audio driver bootstrap functions */
56 AuServer *aud = AuOpenServer("", 0, NULL, 0, NULL, NULL);
65 Audio_DeleteDevice(SDL_AudioDevice * device)
67 SDL_free(device->hidden);
71 static SDL_AudioDevice *
72 Audio_CreateDevice(int devindex)
74 SDL_AudioDevice *this;
76 /* Initialize all variables that we clean on shutdown */
77 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
79 SDL_memset(this, 0, (sizeof *this));
80 this->hidden = (struct SDL_PrivateAudioData *)
81 SDL_malloc((sizeof *this->hidden));
83 if ((this == NULL) || (this->hidden == NULL)) {
90 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
92 /* Set the function pointers */
93 this->OpenAudio = NAS_OpenAudio;
94 this->WaitAudio = NAS_WaitAudio;
95 this->PlayAudio = NAS_PlayAudio;
96 this->GetAudioBuf = NAS_GetAudioBuf;
97 this->CloseAudio = NAS_CloseAudio;
99 this->free = Audio_DeleteDevice;
104 AudioBootStrap NAS_bootstrap = {
105 NAS_DRIVER_NAME, "Network Audio System",
106 Audio_Available, Audio_CreateDevice, 0
109 /* This function waits until it is possible to write a full sound buffer */
113 while (this->hidden->buf_free < this->hidden->mixlen) {
115 AuNextEvent(this->hidden->aud, AuTrue, &ev);
116 AuDispatchEvent(this->hidden->aud, &ev);
123 while (this->hidden->mixlen > this->hidden->buf_free) { /* We think the buffer is full? Yikes! Ask the server for events,
124 in the hope that some of them is LowWater events telling us more
125 of the buffer is free now than what we think. */
127 AuNextEvent(this->hidden->aud, AuTrue, &ev);
128 AuDispatchEvent(this->hidden->aud, &ev);
130 this->hidden->buf_free -= this->hidden->mixlen;
132 /* Write the audio data */
133 AuWriteElement(this->hidden->aud, this->hidden->flow, 0,
134 this->hidden->mixlen, this->hidden->mixbuf, AuFalse, NULL);
136 this->hidden->written += this->hidden->mixlen;
139 fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
144 NAS_GetAudioBuf(_THIS)
146 return (this->hidden->mixbuf);
150 NAS_CloseAudio(_THIS)
152 if (this->hidden->mixbuf != NULL) {
153 SDL_FreeAudioMem(this->hidden->mixbuf);
154 this->hidden->mixbuf = NULL;
156 if (this->hidden->aud) {
157 AuCloseServer(this->hidden->aud);
158 this->hidden->aud = 0;
163 sdlformat_to_auformat(unsigned int fmt)
167 return AuFormatLinearUnsigned8;
169 return AuFormatLinearSigned8;
171 return AuFormatLinearUnsigned16LSB;
173 return AuFormatLinearUnsigned16MSB;
175 return AuFormatLinearSigned16LSB;
177 return AuFormatLinearSigned16MSB;
183 event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
186 case AuEventTypeElementNotify:
188 AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;
190 switch (event->kind) {
191 case AuElementNotifyKindLowWater:
192 if (this2->buf_free >= 0) {
193 this2->really += event->num_bytes;
194 gettimeofday(&this2->last_tv, 0);
195 this2->buf_free += event->num_bytes;
197 this2->buf_free = event->num_bytes;
200 case AuElementNotifyKindState:
201 switch (event->cur_state) {
203 if (event->reason != AuReasonUser) {
204 if (this2->buf_free >= 0) {
205 this2->really += event->num_bytes;
206 gettimeofday(&this2->last_tv, 0);
207 this2->buf_free += event->num_bytes;
209 this2->buf_free = event->num_bytes;
221 find_device(_THIS, int nch)
224 for (i = 0; i < AuServerNumDevices(this->hidden->aud); i++) {
225 if ((AuDeviceKind(AuServerDevice(this->hidden->aud, i)) ==
226 AuComponentKindPhysicalOutput) &&
227 AuDeviceNumTracks(AuServerDevice(this->hidden->aud, i)) == nch) {
228 return AuDeviceIdentifier(AuServerDevice(this->hidden->aud, i));
235 NAS_OpenAudio(_THIS, SDL_AudioSpec * spec)
239 SDL_AudioFormat test_format, format;
241 this->hidden->mixbuf = NULL;
243 /* Try for a closest match on audio format */
245 for (test_format = SDL_FirstAudioFormat(spec->format);
246 !format && test_format;) {
247 format = sdlformat_to_auformat(test_format);
249 if (format == AuNone) {
250 test_format = SDL_NextAudioFormat();
254 SDL_SetError("Couldn't find any hardware audio formats");
257 spec->format = test_format;
259 this->hidden->aud = AuOpenServer("", 0, NULL, 0, NULL, NULL);
260 if (this->hidden->aud == 0) {
261 SDL_SetError("Couldn't open connection to NAS server");
265 this->hidden->dev = find_device(this, spec->channels);
266 if ((this->hidden->dev == AuNone)
267 || (!(this->hidden->flow = AuCreateFlow(this->hidden->aud, NULL)))) {
268 AuCloseServer(this->hidden->aud);
269 this->hidden->aud = 0;
270 SDL_SetError("Couldn't find a fitting playback device on NAS server");
274 buffer_size = spec->freq;
275 if (buffer_size < 4096)
278 if (buffer_size > 32768)
279 buffer_size = 32768; /* So that the buffer won't get unmanageably big. */
281 /* Calculate the final parameters for this audio specification */
282 SDL_CalculateAudioSpec(spec);
284 this2 = this->hidden;
286 AuMakeElementImportClient(elms, spec->freq, format, spec->channels,
287 AuTrue, buffer_size, buffer_size / 4, 0, NULL);
288 AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, spec->freq,
289 AuUnlimitedSamples, 0, NULL);
290 AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms,
292 AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
293 this->hidden->flow, event_handler,
296 AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);
298 /* Allocate mixing buffer */
299 this->hidden->mixlen = spec->size;
300 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
301 if (this->hidden->mixbuf == NULL) {
304 SDL_memset(this->hidden->mixbuf, spec->silence, spec->size);
306 /* Get the parent process id (we're the parent of the audio thread) */
307 this->hidden->parent = getpid();
309 /* We're ready to rock and roll. :-) */
313 /* vi: set ts=4 sw=4 expandtab: */