Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.
WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.
The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce
The headers are being converted to automatically generate doxygen documentation.
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_audiodev_c.h"
38 #include "SDL_nasaudio.h"
40 /* The tag name used by artsc audio */
41 #define NAS_DRIVER_NAME "nas"
43 static struct SDL_PrivateAudioData *this2 = NULL;
45 /* Audio driver functions */
46 static int NAS_OpenAudio (_THIS, SDL_AudioSpec * spec);
47 static void NAS_WaitAudio (_THIS);
48 static void NAS_PlayAudio (_THIS);
49 static Uint8 *NAS_GetAudioBuf (_THIS);
50 static void NAS_CloseAudio (_THIS);
52 /* Audio driver bootstrap functions */
55 Audio_Available (void)
57 AuServer *aud = AuOpenServer ("", 0, NULL, 0, NULL, NULL);
66 Audio_DeleteDevice (SDL_AudioDevice * device)
68 SDL_free (device->hidden);
72 static SDL_AudioDevice *
73 Audio_CreateDevice (int devindex)
75 SDL_AudioDevice *this;
77 /* Initialize all variables that we clean on shutdown */
78 this = (SDL_AudioDevice *) SDL_malloc (sizeof (SDL_AudioDevice));
80 SDL_memset (this, 0, (sizeof *this));
81 this->hidden = (struct SDL_PrivateAudioData *)
82 SDL_malloc ((sizeof *this->hidden));
84 if ((this == NULL) || (this->hidden == NULL)) {
91 SDL_memset (this->hidden, 0, (sizeof *this->hidden));
93 /* Set the function pointers */
94 this->OpenAudio = NAS_OpenAudio;
95 this->WaitAudio = NAS_WaitAudio;
96 this->PlayAudio = NAS_PlayAudio;
97 this->GetAudioBuf = NAS_GetAudioBuf;
98 this->CloseAudio = NAS_CloseAudio;
100 this->free = Audio_DeleteDevice;
105 AudioBootStrap NAS_bootstrap = {
106 NAS_DRIVER_NAME, "Network Audio System",
107 Audio_Available, Audio_CreateDevice
110 /* This function waits until it is possible to write a full sound buffer */
112 NAS_WaitAudio (_THIS)
114 while (this->hidden->buf_free < this->hidden->mixlen) {
116 AuNextEvent (this->hidden->aud, AuTrue, &ev);
117 AuDispatchEvent (this->hidden->aud, &ev);
122 NAS_PlayAudio (_THIS)
124 while (this->hidden->mixlen > this->hidden->buf_free) { /* We think the buffer is full? Yikes! Ask the server for events,
125 in the hope that some of them is LowWater events telling us more
126 of the buffer is free now than what we think. */
128 AuNextEvent (this->hidden->aud, AuTrue, &ev);
129 AuDispatchEvent (this->hidden->aud, &ev);
131 this->hidden->buf_free -= this->hidden->mixlen;
133 /* Write the audio data */
134 AuWriteElement (this->hidden->aud, this->hidden->flow, 0,
135 this->hidden->mixlen, this->hidden->mixbuf, AuFalse,
138 this->hidden->written += this->hidden->mixlen;
141 fprintf (stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
146 NAS_GetAudioBuf (_THIS)
148 return (this->hidden->mixbuf);
152 NAS_CloseAudio (_THIS)
154 if (this->hidden->mixbuf != NULL) {
155 SDL_FreeAudioMem (this->hidden->mixbuf);
156 this->hidden->mixbuf = NULL;
158 if (this->hidden->aud) {
159 AuCloseServer (this->hidden->aud);
160 this->hidden->aud = 0;
165 sdlformat_to_auformat (unsigned int fmt)
169 return AuFormatLinearUnsigned8;
171 return AuFormatLinearSigned8;
173 return AuFormatLinearUnsigned16LSB;
175 return AuFormatLinearUnsigned16MSB;
177 return AuFormatLinearSigned16LSB;
179 return AuFormatLinearSigned16MSB;
185 event_handler (AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
188 case AuEventTypeElementNotify:
190 AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;
192 switch (event->kind) {
193 case AuElementNotifyKindLowWater:
194 if (this2->buf_free >= 0) {
195 this2->really += event->num_bytes;
196 gettimeofday (&this2->last_tv, 0);
197 this2->buf_free += event->num_bytes;
199 this2->buf_free = event->num_bytes;
202 case AuElementNotifyKindState:
203 switch (event->cur_state) {
205 if (event->reason != AuReasonUser) {
206 if (this2->buf_free >= 0) {
207 this2->really += event->num_bytes;
208 gettimeofday (&this2->last_tv, 0);
209 this2->buf_free += event->num_bytes;
211 this2->buf_free = event->num_bytes;
223 find_device (_THIS, int nch)
226 for (i = 0; i < AuServerNumDevices (this->hidden->aud); i++) {
227 if ((AuDeviceKind (AuServerDevice (this->hidden->aud, i)) ==
228 AuComponentKindPhysicalOutput) &&
229 AuDeviceNumTracks (AuServerDevice (this->hidden->aud, i)) ==
231 return AuDeviceIdentifier (AuServerDevice (this->hidden->aud, i));
238 NAS_OpenAudio (_THIS, SDL_AudioSpec * spec)
242 Uint16 test_format, format;
244 this->hidden->mixbuf = NULL;
246 /* Try for a closest match on audio format */
248 for (test_format = SDL_FirstAudioFormat (spec->format);
249 !format && test_format;) {
250 format = sdlformat_to_auformat (test_format);
252 if (format == AuNone) {
253 test_format = SDL_NextAudioFormat ();
257 SDL_SetError ("Couldn't find any hardware audio formats");
260 spec->format = test_format;
262 this->hidden->aud = AuOpenServer ("", 0, NULL, 0, NULL, NULL);
263 if (this->hidden->aud == 0) {
264 SDL_SetError ("Couldn't open connection to NAS server");
268 this->hidden->dev = find_device (this, spec->channels);
269 if ((this->hidden->dev == AuNone)
270 || (!(this->hidden->flow = AuCreateFlow (this->hidden->aud, NULL)))) {
271 AuCloseServer (this->hidden->aud);
272 this->hidden->aud = 0;
274 ("Couldn't find a fitting playback device on NAS server");
278 buffer_size = spec->freq;
279 if (buffer_size < 4096)
282 if (buffer_size > 32768)
283 buffer_size = 32768; /* So that the buffer won't get unmanageably big. */
285 /* Calculate the final parameters for this audio specification */
286 SDL_CalculateAudioSpec (spec);
288 this2 = this->hidden;
290 AuMakeElementImportClient (elms, spec->freq, format, spec->channels,
291 AuTrue, buffer_size, buffer_size / 4, 0, NULL);
292 AuMakeElementExportDevice (elms + 1, 0, this->hidden->dev, spec->freq,
293 AuUnlimitedSamples, 0, NULL);
294 AuSetElements (this->hidden->aud, this->hidden->flow, AuTrue, 2, elms,
296 AuRegisterEventHandler (this->hidden->aud, AuEventHandlerIDMask, 0,
297 this->hidden->flow, event_handler,
300 AuStartFlow (this->hidden->aud, this->hidden->flow, NULL);
302 /* Allocate mixing buffer */
303 this->hidden->mixlen = spec->size;
304 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem (this->hidden->mixlen);
305 if (this->hidden->mixbuf == NULL) {
308 SDL_memset (this->hidden->mixbuf, spec->silence, spec->size);
310 /* Get the parent process id (we're the parent of the audio thread) */
311 this->hidden->parent = getpid ();
313 /* We're ready to rock and roll. :-) */
317 /* vi: set ts=4 sw=4 expandtab: */