Mercurial > sdl-ios-xcode
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 |