SDL-1.2.14
[sdl_omap.git] / src / audio / dmedia / SDL_irixaudio.c
CommitLineData
e14743d1 1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
4
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.
9
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.
14
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
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24/* Allow access to a raw mixing buffer (For IRIX 6.5 and higher) */
25/* patch for IRIX 5 by Georg Schwarz 18/07/2004 */
26
27#include "SDL_timer.h"
28#include "SDL_audio.h"
29#include "../SDL_audiomem.h"
30#include "../SDL_audio_c.h"
31#include "SDL_irixaudio.h"
32
33
34#ifndef AL_RESOURCE /* as a test whether we use the old IRIX audio libraries */
35#define OLD_IRIX_AUDIO
36#define alClosePort(x) ALcloseport(x)
37#define alFreeConfig(x) ALfreeconfig(x)
38#define alGetFillable(x) ALgetfillable(x)
39#define alNewConfig() ALnewconfig()
40#define alOpenPort(x,y,z) ALopenport(x,y,z)
41#define alSetChannels(x,y) ALsetchannels(x,y)
42#define alSetQueueSize(x,y) ALsetqueuesize(x,y)
43#define alSetSampFmt(x,y) ALsetsampfmt(x,y)
44#define alSetWidth(x,y) ALsetwidth(x,y)
45#endif
46
47/* Audio driver functions */
48static int AL_OpenAudio(_THIS, SDL_AudioSpec *spec);
49static void AL_WaitAudio(_THIS);
50static void AL_PlayAudio(_THIS);
51static Uint8 *AL_GetAudioBuf(_THIS);
52static void AL_CloseAudio(_THIS);
53
54/* Audio driver bootstrap functions */
55
56static int Audio_Available(void)
57{
58 return 1;
59}
60
61static void Audio_DeleteDevice(SDL_AudioDevice *device)
62{
63 SDL_free(device->hidden);
64 SDL_free(device);
65}
66
67static SDL_AudioDevice *Audio_CreateDevice(int devindex)
68{
69 SDL_AudioDevice *this;
70
71 /* Initialize all variables that we clean on shutdown */
72 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice));
73 if ( this ) {
74 SDL_memset(this, 0, (sizeof *this));
75 this->hidden = (struct SDL_PrivateAudioData *)
76 SDL_malloc((sizeof *this->hidden));
77 }
78 if ( (this == NULL) || (this->hidden == NULL) ) {
79 SDL_OutOfMemory();
80 if ( this ) {
81 SDL_free(this);
82 }
83 return(0);
84 }
85 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
86
87 /* Set the function pointers */
88 this->OpenAudio = AL_OpenAudio;
89 this->WaitAudio = AL_WaitAudio;
90 this->PlayAudio = AL_PlayAudio;
91 this->GetAudioBuf = AL_GetAudioBuf;
92 this->CloseAudio = AL_CloseAudio;
93
94 this->free = Audio_DeleteDevice;
95
96 return this;
97}
98
99AudioBootStrap DMEDIA_bootstrap = {
100 "AL", "IRIX DMedia audio",
101 Audio_Available, Audio_CreateDevice
102};
103
104
105void static AL_WaitAudio(_THIS)
106{
107 Sint32 timeleft;
108
109 timeleft = this->spec.samples - alGetFillable(audio_port);
110 if ( timeleft > 0 ) {
111 timeleft /= (this->spec.freq/1000);
112 SDL_Delay((Uint32)timeleft);
113 }
114}
115
116static void AL_PlayAudio(_THIS)
117{
118 /* Write the audio data out */
119 if ( alWriteFrames(audio_port, mixbuf, this->spec.samples) < 0 ) {
120 /* Assume fatal error, for now */
121 this->enabled = 0;
122 }
123}
124
125static Uint8 *AL_GetAudioBuf(_THIS)
126{
127 return(mixbuf);
128}
129
130static void AL_CloseAudio(_THIS)
131{
132 if ( mixbuf != NULL ) {
133 SDL_FreeAudioMem(mixbuf);
134 mixbuf = NULL;
135 }
136 if ( audio_port != NULL ) {
137 alClosePort(audio_port);
138 audio_port = NULL;
139 }
140}
141
142static int AL_OpenAudio(_THIS, SDL_AudioSpec * spec)
143{
144 Uint16 test_format = SDL_FirstAudioFormat(spec->format);
145 long width = 0;
146 long fmt = 0;
147 int valid = 0;
148
149#ifdef OLD_IRIX_AUDIO
150 {
151 long audio_param[2];
152 audio_param[0] = AL_OUTPUT_RATE;
153 audio_param[1] = spec->freq;
154 valid = (ALsetparams(AL_DEFAULT_DEVICE, audio_param, 2) < 0);
155 }
156#else
157 {
158 ALpv audio_param;
159 audio_param.param = AL_RATE;
160 audio_param.value.i = spec->freq;
161 valid = (alSetParams(AL_DEFAULT_OUTPUT, &audio_param, 1) < 0);
162 }
163#endif
164
165 while ((!valid) && (test_format)) {
166 valid = 1;
167 spec->format = test_format;
168
169 switch (test_format) {
170 case AUDIO_S8:
171 width = AL_SAMPLE_8;
172 fmt = AL_SAMPFMT_TWOSCOMP;
173 break;
174
175 case AUDIO_S16SYS:
176 width = AL_SAMPLE_16;
177 fmt = AL_SAMPFMT_TWOSCOMP;
178 break;
179
180 default:
181 valid = 0;
182 test_format = SDL_NextAudioFormat();
183 break;
184 }
185
186 if (valid) {
187 ALconfig audio_config = alNewConfig();
188 valid = 0;
189 if (audio_config) {
190 if (alSetChannels(audio_config, spec->channels) < 0) {
191 if (spec->channels > 2) { /* can't handle > stereo? */
192 spec->channels = 2; /* try again below. */
193 }
194 }
195
196 if ((alSetSampFmt(audio_config, fmt) >= 0) &&
197 ((!width) || (alSetWidth(audio_config, width) >= 0)) &&
198 (alSetQueueSize(audio_config, spec->samples * 2) >= 0) &&
199 (alSetChannels(audio_config, spec->channels) >= 0)) {
200
201 audio_port = alOpenPort("SDL audio", "w", audio_config);
202 if (audio_port == NULL) {
203 /* docs say AL_BAD_CHANNELS happens here, too. */
204 int err = oserror();
205 if (err == AL_BAD_CHANNELS) {
206 spec->channels = 2;
207 alSetChannels(audio_config, spec->channels);
208 audio_port = alOpenPort("SDL audio", "w",
209 audio_config);
210 }
211 }
212
213 if (audio_port != NULL) {
214 valid = 1;
215 }
216 }
217
218 alFreeConfig(audio_config);
219 }
220 }
221 }
222
223 if (!valid) {
224 SDL_SetError("Unsupported audio format");
225 return (-1);
226 }
227
228 /* Update the fragment size as size in bytes */
229 SDL_CalculateAudioSpec(spec);
230
231 /* Allocate mixing buffer */
232 mixbuf = (Uint8 *) SDL_AllocAudioMem(spec->size);
233 if (mixbuf == NULL) {
234 SDL_OutOfMemory();
235 return (-1);
236 }
237 SDL_memset(mixbuf, spec->silence, spec->size);
238
239 /* We're ready to rock and roll. :-) */
240 return (0);
241}
242