comparison src/audio/mme/SDL_mmeaudio.c @ 654:e92bcf2573cb

Added audio and CD-ROM support for OSF/Tru64 (thanks Hayashi!)
author Sam Lantinga <slouken@libsdl.org>
date Tue, 22 Jul 2003 14:01:21 +0000
parents
children b1595db396a7
comparison
equal deleted inserted replaced
653:1bd056de5d1b 654:e92bcf2573cb
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 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 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22
23 /* Tru64 UNIX MME support */
24 #include "SDL_mmeaudio.h"
25
26 static BOOL inUse[NUM_BUFFERS];
27
28 /* Audio driver functions */
29 static int MME_OpenAudio(_THIS, SDL_AudioSpec *spec);
30 static void MME_WaitAudio(_THIS);
31 static Uint8 *MME_GetAudioBuf(_THIS);
32 static void MME_PlayAudio(_THIS);
33 static void MME_WaitDone(_THIS);
34 static void MME_CloseAudio(_THIS);
35
36 /* Audio driver bootstrap functions */
37 static int Audio_Available(void)
38 {
39 return(1);
40 }
41
42 static void Audio_DeleteDevice(SDL_AudioDevice *device)
43 {
44 if ( device ) {
45 if ( device->hidden ) {
46 free(device->hidden);
47 device->hidden = NULL;
48 }
49 free(device);
50 device = NULL;
51 }
52 }
53
54 static SDL_AudioDevice *Audio_CreateDevice(int devindex)
55 {
56 SDL_AudioDevice *this;
57
58 /* Initialize all variables that we clean on shutdown */
59 this = malloc(sizeof(SDL_AudioDevice));
60 if ( this ) {
61 memset(this, 0, (sizeof *this));
62 this->hidden = malloc((sizeof *this->hidden));
63 }
64 if ( (this == NULL) || (this->hidden == NULL) ) {
65 SDL_OutOfMemory();
66 if ( this ) {
67 free(this);
68 }
69 return(0);
70 }
71 memset(this->hidden, 0, (sizeof *this->hidden));
72 /* Set the function pointers */
73 this->OpenAudio = MME_OpenAudio;
74 this->WaitAudio = MME_WaitAudio;
75 this->PlayAudio = MME_PlayAudio;
76 this->GetAudioBuf = MME_GetAudioBuf;
77 this->WaitDone = MME_WaitDone;
78 this->CloseAudio = MME_CloseAudio;
79 this->free = Audio_DeleteDevice;
80
81 return this;
82 }
83
84 AudioBootStrap MMEAUDIO_bootstrap = {
85 "waveout", "Tru64 MME WaveOut",
86 Audio_Available, Audio_CreateDevice
87 };
88
89 static void SetMMerror(char *function, MMRESULT code)
90 {
91 int len;
92 char errbuf[MAXERRORLENGTH];
93
94 sprintf(errbuf, "%s: ", function);
95 len = strlen(errbuf);
96 waveOutGetErrorText(code, errbuf+len, MAXERRORLENGTH-len);
97 SDL_SetError("%s",errbuf);
98 }
99
100 static void CALLBACK MME_CALLBACK(HWAVEOUT hwo,
101 UINT uMsg,
102 DWORD dwInstance,
103 LPARAM dwParam1,
104 LPARAM dwParam2)
105 {
106 WAVEHDR *wp = (WAVEHDR *) dwParam1;
107
108 if ( uMsg == WOM_DONE )
109 inUse[wp->dwUser] = FALSE;
110 }
111
112 static int MME_OpenAudio(_THIS, SDL_AudioSpec *spec)
113 {
114 MMRESULT result;
115 int i;
116
117 mixbuf = NULL;
118
119 /* Set basic WAVE format parameters */
120 shm = mmeAllocMem(sizeof(*shm));
121 if ( shm == NULL ) {
122 SDL_SetError("Out of memory: shm");
123 return(-1);
124 }
125 shm->sound = 0;
126 shm->wFmt.wf.wFormatTag = WAVE_FORMAT_PCM;
127
128 /* Determine the audio parameters from the AudioSpec */
129 switch ( spec->format & 0xFF ) {
130 case 8:
131 /* Unsigned 8 bit audio data */
132 spec->format = AUDIO_U8;
133 shm->wFmt.wBitsPerSample = 8;
134 break;
135 case 16:
136 /* Signed 16 bit audio data */
137 spec->format = AUDIO_S16;
138 shm->wFmt.wBitsPerSample = 16;
139 break;
140 default:
141 SDL_SetError("Unsupported audio format");
142 return(-1);
143 }
144
145 shm->wFmt.wf.nChannels = spec->channels;
146 shm->wFmt.wf.nSamplesPerSec = spec->freq;
147 shm->wFmt.wf.nBlockAlign =
148 shm->wFmt.wf.nChannels * shm->wFmt.wBitsPerSample / 8;
149 shm->wFmt.wf.nAvgBytesPerSec =
150 shm->wFmt.wf.nSamplesPerSec * shm->wFmt.wf.nBlockAlign;
151
152 /* Check the buffer size -- minimum of 1/4 second (word aligned) */
153 if ( spec->samples < (spec->freq/4) )
154 spec->samples = ((spec->freq/4)+3)&~3;
155
156 /* Update the fragment size as size in bytes */
157 SDL_CalculateAudioSpec(spec);
158
159 /* Open the audio device */
160 result = waveOutOpen(&(shm->sound),
161 WAVE_MAPPER,
162 &(shm->wFmt.wf),
163 MME_CALLBACK,
164 NULL,
165 (CALLBACK_FUNCTION|WAVE_OPEN_SHAREABLE));
166 if ( result != MMSYSERR_NOERROR ) {
167 SetMMerror("waveOutOpen()", result);
168 return(-1);
169 }
170
171 /* Create the sound buffers */
172 mixbuf = (Uint8 *)mmeAllocBuffer(NUM_BUFFERS * (spec->size));
173 if ( mixbuf == NULL ) {
174 SDL_SetError("Out of memory: mixbuf");
175 return(-1);
176 }
177
178 for (i = 0; i < NUM_BUFFERS; i++) {
179 shm->wHdr[i].lpData = &mixbuf[i * (spec->size)];
180 shm->wHdr[i].dwBufferLength = spec->size;
181 shm->wHdr[i].dwFlags = 0;
182 shm->wHdr[i].dwUser = i;
183 shm->wHdr[i].dwLoops = 0; /* loop control counter */
184 shm->wHdr[i].lpNext = NULL; /* reserved for driver */
185 shm->wHdr[i].reserved = 0;
186 inUse[i] = FALSE;
187 }
188 next_buffer = 0;
189 return 0;
190 }
191
192 static void MME_WaitAudio(_THIS)
193 {
194 mmeWaitForCallbacks ();
195 mmeProcessCallbacks ();
196 }
197
198 static Uint8 *MME_GetAudioBuf(_THIS)
199 {
200 Uint8 *retval;
201
202 while ( inUse[next_buffer] )
203 ;
204
205 inUse[next_buffer] = TRUE;
206 retval = (Uint8 *)(shm->wHdr[next_buffer].lpData);
207 return retval;
208 }
209
210 static void MME_PlayAudio(_THIS)
211 {
212 /* Queue it up */
213 waveOutWrite(shm->sound, &(shm->wHdr[next_buffer]), sizeof(WAVEHDR));
214 next_buffer = (next_buffer+1)%NUM_BUFFERS;
215 }
216
217 static void MME_WaitDone(_THIS)
218 {
219 MMRESULT result;
220 int i;
221
222 if ( shm->sound ) {
223 result = waveOutReset(shm->sound);
224 if ( result != MMSYSERR_NOERROR )
225 SetMMerror("waveOutReset()", result);
226 else {
227 mmeWaitForCallbacks ();
228 mmeProcessCallbacks ();
229 }
230 }
231 }
232
233 static void MME_CloseAudio(_THIS)
234 {
235 MMRESULT result;
236
237 if ( mixbuf ) {
238 result = mmeFreeBuffer(mixbuf);
239 if (result != MMSYSERR_NOERROR )
240 SetMMerror("mmeFreeBuffer", result);
241 mixbuf = NULL;
242 }
243
244 if ( shm ) {
245 if ( shm->sound ) {
246 result = waveOutClose(shm->sound);
247 if (result != MMSYSERR_NOERROR )
248 SetMMerror("waveOutClose()", result);
249 }
250 result = mmeFreeMem(shm);
251 if (result != MMSYSERR_NOERROR )
252 SetMMerror("mmeFreeMem()", result);
253 shm = NULL;
254 }
255 }
256