Mercurial > sdl-ios-xcode
comparison src/audio/dart/SDL_dart.c @ 1662:782fd950bd46 SDL-1.3
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.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 28 May 2006 13:04:16 +0000 |
parents | d910939febfa |
children | 4da1ee79c9af |
comparison
equal
deleted
inserted
replaced
1661:281d3f4870e5 | 1662:782fd950bd46 |
---|---|
30 | 30 |
31 // Buffer states: | 31 // Buffer states: |
32 #define BUFFER_EMPTY 0 | 32 #define BUFFER_EMPTY 0 |
33 #define BUFFER_USED 1 | 33 #define BUFFER_USED 1 |
34 | 34 |
35 typedef struct _tMixBufferDesc { | 35 typedef struct _tMixBufferDesc |
36 int iBufferUsage; // BUFFER_EMPTY or BUFFER_USED | 36 { |
37 SDL_AudioDevice *pSDLAudioDevice; | 37 int iBufferUsage; // BUFFER_EMPTY or BUFFER_USED |
38 SDL_AudioDevice *pSDLAudioDevice; | |
38 } tMixBufferDesc, *pMixBufferDesc; | 39 } tMixBufferDesc, *pMixBufferDesc; |
39 | 40 |
40 | 41 |
41 //--------------------------------------------------------------------- | 42 //--------------------------------------------------------------------- |
42 // DARTEventFunc | 43 // DARTEventFunc |
43 // | 44 // |
44 // This function is called by DART, when an event occures, like end of | 45 // This function is called by DART, when an event occures, like end of |
45 // playback of a buffer, etc... | 46 // playback of a buffer, etc... |
46 //--------------------------------------------------------------------- | 47 //--------------------------------------------------------------------- |
47 LONG APIENTRY DARTEventFunc(ULONG ulStatus, | 48 LONG APIENTRY |
48 PMCI_MIX_BUFFER pBuffer, | 49 DARTEventFunc (ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags) |
49 ULONG ulFlags) | 50 { |
50 { | 51 if (ulFlags && MIX_WRITE_COMPLETE) { // Playback of buffer completed! |
51 if (ulFlags && MIX_WRITE_COMPLETE) | 52 |
52 { // Playback of buffer completed! | 53 // Get pointer to buffer description |
53 | 54 pMixBufferDesc pBufDesc; |
54 // Get pointer to buffer description | 55 |
55 pMixBufferDesc pBufDesc; | 56 if (pBuffer) { |
56 | 57 pBufDesc = (pMixBufferDesc) (*pBuffer).ulUserParm; |
57 if (pBuffer) | 58 |
58 { | 59 if (pBufDesc) { |
59 pBufDesc = (pMixBufferDesc) (*pBuffer).ulUserParm; | 60 SDL_AudioDevice *pSDLAudioDevice = pBufDesc->pSDLAudioDevice; |
60 | 61 // Set the buffer to be empty |
61 if (pBufDesc) | 62 pBufDesc->iBufferUsage = BUFFER_EMPTY; |
62 { | 63 // And notify DART feeder thread that it will have to work a bit. |
63 SDL_AudioDevice *pSDLAudioDevice = pBufDesc->pSDLAudioDevice; | 64 if (pSDLAudioDevice) |
64 // Set the buffer to be empty | 65 DosPostEventSem (pSDLAudioDevice->hidden-> |
65 pBufDesc->iBufferUsage = BUFFER_EMPTY; | 66 hevAudioBufferPlayed); |
66 // And notify DART feeder thread that it will have to work a bit. | 67 } |
67 if (pSDLAudioDevice) | 68 } |
68 DosPostEventSem(pSDLAudioDevice->hidden->hevAudioBufferPlayed); | 69 } |
69 } | 70 return TRUE; |
70 } | 71 } |
71 } | 72 |
72 return TRUE; | 73 |
73 } | 74 int |
74 | 75 DART_OpenAudio (_THIS, SDL_AudioSpec * spec) |
75 | 76 { |
76 int DART_OpenAudio(_THIS, SDL_AudioSpec *spec) | 77 MCI_AMP_OPEN_PARMS AmpOpenParms; |
77 { | 78 MCI_GENERIC_PARMS GenericParms; |
78 MCI_AMP_OPEN_PARMS AmpOpenParms; | 79 int iDeviceOrd = 0; // Default device to be used |
79 MCI_GENERIC_PARMS GenericParms; | 80 int bOpenShared = 1; // Try opening it shared |
80 int iDeviceOrd = 0; // Default device to be used | 81 int iBits = 16; // Default is 16 bits signed |
81 int bOpenShared = 1; // Try opening it shared | 82 int iFreq = 44100; // Default is 44KHz |
82 int iBits = 16; // Default is 16 bits signed | 83 int iChannels = 2; // Default is 2 channels (Stereo) |
83 int iFreq = 44100; // Default is 44KHz | 84 int iNumBufs = 2; // Number of audio buffers: 2 |
84 int iChannels = 2; // Default is 2 channels (Stereo) | 85 int iBufSize; |
85 int iNumBufs = 2; // Number of audio buffers: 2 | 86 int iOpenMode; |
86 int iBufSize; | 87 int iSilence; |
87 int iOpenMode; | 88 int rc; |
88 int iSilence; | 89 |
89 int rc; | 90 // First thing is to try to open a given DART device! |
90 | 91 SDL_memset (&AmpOpenParms, 0, sizeof (MCI_AMP_OPEN_PARMS)); |
91 // First thing is to try to open a given DART device! | 92 // pszDeviceType should contain the device type in low word, and device ordinal in high word! |
92 SDL_memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS)); | 93 AmpOpenParms.pszDeviceType = |
93 // pszDeviceType should contain the device type in low word, and device ordinal in high word! | 94 (PSZ) (MCI_DEVTYPE_AUDIO_AMPMIX | (iDeviceOrd << 16)); |
94 AmpOpenParms.pszDeviceType = (PSZ) (MCI_DEVTYPE_AUDIO_AMPMIX | (iDeviceOrd << 16)); | 95 |
95 | 96 iOpenMode = MCI_WAIT | MCI_OPEN_TYPE_ID; |
96 iOpenMode = MCI_WAIT | MCI_OPEN_TYPE_ID; | 97 if (bOpenShared) |
97 if (bOpenShared) iOpenMode |= MCI_OPEN_SHAREABLE; | 98 iOpenMode |= MCI_OPEN_SHAREABLE; |
98 | 99 |
99 rc = mciSendCommand( 0, MCI_OPEN, | 100 rc = mciSendCommand (0, MCI_OPEN, iOpenMode, (PVOID) & AmpOpenParms, 0); |
100 iOpenMode, | 101 if (rc != MCIERR_SUCCESS) // No audio available?? |
101 (PVOID) &AmpOpenParms, 0); | 102 return (-1); |
102 if (rc!=MCIERR_SUCCESS) // No audio available?? | 103 // Save the device ID we got from DART! |
103 return (-1); | 104 // We will use this in the next calls! |
104 // Save the device ID we got from DART! | 105 iDeviceOrd = AmpOpenParms.usDeviceID; |
105 // We will use this in the next calls! | 106 |
106 iDeviceOrd = AmpOpenParms.usDeviceID; | 107 // Determine the audio parameters from the AudioSpec |
107 | 108 switch (spec->format & 0xFF) { |
108 // Determine the audio parameters from the AudioSpec | |
109 switch ( spec->format & 0xFF ) | |
110 { | |
111 case 8: | 109 case 8: |
112 /* Unsigned 8 bit audio data */ | 110 /* Unsigned 8 bit audio data */ |
113 spec->format = AUDIO_U8; | 111 spec->format = AUDIO_U8; |
114 iSilence = 0x80; | 112 iSilence = 0x80; |
115 iBits = 8; | 113 iBits = 8; |
120 iSilence = 0x00; | 118 iSilence = 0x00; |
121 iBits = 16; | 119 iBits = 16; |
122 break; | 120 break; |
123 default: | 121 default: |
124 // Close DART, and exit with error code! | 122 // Close DART, and exit with error code! |
125 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); | 123 mciSendCommand (iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); |
126 SDL_SetError("Unsupported audio format"); | 124 SDL_SetError ("Unsupported audio format"); |
127 return(-1); | 125 return (-1); |
128 } | 126 } |
129 iFreq = spec->freq; | 127 iFreq = spec->freq; |
130 iChannels = spec->channels; | 128 iChannels = spec->channels; |
131 /* Update the fragment size as size in bytes */ | 129 /* Update the fragment size as size in bytes */ |
132 SDL_CalculateAudioSpec(spec); | 130 SDL_CalculateAudioSpec (spec); |
133 iBufSize = spec->size; | 131 iBufSize = spec->size; |
134 | 132 |
135 // Now query this device if it supports the given freq/bits/channels! | 133 // Now query this device if it supports the given freq/bits/channels! |
136 SDL_memset(&(_this->hidden->MixSetupParms), 0, sizeof(MCI_MIXSETUP_PARMS)); | 134 SDL_memset (&(_this->hidden->MixSetupParms), 0, |
137 _this->hidden->MixSetupParms.ulBitsPerSample = iBits; | 135 sizeof (MCI_MIXSETUP_PARMS)); |
138 _this->hidden->MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM; | 136 _this->hidden->MixSetupParms.ulBitsPerSample = iBits; |
139 _this->hidden->MixSetupParms.ulSamplesPerSec = iFreq; | 137 _this->hidden->MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM; |
140 _this->hidden->MixSetupParms.ulChannels = iChannels; | 138 _this->hidden->MixSetupParms.ulSamplesPerSec = iFreq; |
141 _this->hidden->MixSetupParms.ulFormatMode = MCI_PLAY; | 139 _this->hidden->MixSetupParms.ulChannels = iChannels; |
142 _this->hidden->MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO; | 140 _this->hidden->MixSetupParms.ulFormatMode = MCI_PLAY; |
143 _this->hidden->MixSetupParms.pmixEvent = DARTEventFunc; | 141 _this->hidden->MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO; |
144 rc = mciSendCommand (iDeviceOrd, MCI_MIXSETUP, | 142 _this->hidden->MixSetupParms.pmixEvent = DARTEventFunc; |
145 MCI_WAIT | MCI_MIXSETUP_QUERYMODE, | 143 rc = mciSendCommand (iDeviceOrd, MCI_MIXSETUP, |
146 &(_this->hidden->MixSetupParms), 0); | 144 MCI_WAIT | MCI_MIXSETUP_QUERYMODE, |
147 if (rc!=MCIERR_SUCCESS) | 145 &(_this->hidden->MixSetupParms), 0); |
148 { // The device cannot handle this format! | 146 if (rc != MCIERR_SUCCESS) { // The device cannot handle this format! |
149 // Close DART, and exit with error code! | 147 // Close DART, and exit with error code! |
150 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); | 148 mciSendCommand (iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); |
151 SDL_SetError("Audio device doesn't support requested audio format"); | 149 SDL_SetError ("Audio device doesn't support requested audio format"); |
152 return(-1); | 150 return (-1); |
153 } | 151 } |
154 // The device can handle this format, so initialize! | 152 // The device can handle this format, so initialize! |
155 rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP, | 153 rc = mciSendCommand (iDeviceOrd, MCI_MIXSETUP, |
156 MCI_WAIT | MCI_MIXSETUP_INIT, | 154 MCI_WAIT | MCI_MIXSETUP_INIT, |
157 &(_this->hidden->MixSetupParms), 0); | 155 &(_this->hidden->MixSetupParms), 0); |
158 if (rc!=MCIERR_SUCCESS) | 156 if (rc != MCIERR_SUCCESS) { // The device could not be opened! |
159 { // The device could not be opened! | 157 // Close DART, and exit with error code! |
160 // Close DART, and exit with error code! | 158 mciSendCommand (iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); |
161 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); | 159 SDL_SetError ("Audio device could not be set up"); |
162 SDL_SetError("Audio device could not be set up"); | 160 return (-1); |
163 return(-1); | 161 } |
164 } | 162 // Ok, the device is initialized. |
165 // Ok, the device is initialized. | 163 // Now we should allocate buffers. For this, we need a place where |
166 // Now we should allocate buffers. For this, we need a place where | 164 // the buffer descriptors will be: |
167 // the buffer descriptors will be: | 165 _this->hidden->pMixBuffers = |
168 _this->hidden->pMixBuffers = (MCI_MIX_BUFFER *) SDL_malloc(sizeof(MCI_MIX_BUFFER)*iNumBufs); | 166 (MCI_MIX_BUFFER *) SDL_malloc (sizeof (MCI_MIX_BUFFER) * iNumBufs); |
169 if (!(_this->hidden->pMixBuffers)) | 167 if (!(_this->hidden->pMixBuffers)) { // Not enough memory! |
170 { // Not enough memory! | 168 // Close DART, and exit with error code! |
171 // Close DART, and exit with error code! | 169 mciSendCommand (iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); |
172 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); | 170 SDL_SetError ("Not enough memory for audio buffer descriptors"); |
173 SDL_SetError("Not enough memory for audio buffer descriptors"); | 171 return (-1); |
174 return(-1); | 172 } |
175 } | 173 // Now that we have the place for buffer list, we can ask DART for the |
176 // Now that we have the place for buffer list, we can ask DART for the | 174 // buffers! |
177 // buffers! | 175 _this->hidden->BufferParms.ulNumBuffers = iNumBufs; // Number of buffers |
178 _this->hidden->BufferParms.ulNumBuffers = iNumBufs; // Number of buffers | 176 _this->hidden->BufferParms.ulBufferSize = iBufSize; // each with this size |
179 _this->hidden->BufferParms.ulBufferSize = iBufSize; // each with this size | 177 _this->hidden->BufferParms.pBufList = _this->hidden->pMixBuffers; // getting descriptorts into this list |
180 _this->hidden->BufferParms.pBufList = _this->hidden->pMixBuffers; // getting descriptorts into this list | 178 // Allocate buffers! |
181 // Allocate buffers! | 179 rc = mciSendCommand (iDeviceOrd, MCI_BUFFER, |
182 rc = mciSendCommand(iDeviceOrd, MCI_BUFFER, | 180 MCI_WAIT | MCI_ALLOCATE_MEMORY, |
183 MCI_WAIT | MCI_ALLOCATE_MEMORY, | 181 &(_this->hidden->BufferParms), 0); |
184 &(_this->hidden->BufferParms), 0); | 182 if ((rc != MCIERR_SUCCESS) |
185 if ((rc!=MCIERR_SUCCESS) || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers) || (_this->hidden->BufferParms.ulBufferSize==0)) | 183 || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers) |
186 { // Could not allocate memory! | 184 || (_this->hidden->BufferParms.ulBufferSize == 0)) { // Could not allocate memory! |
187 // Close DART, and exit with error code! | 185 // Close DART, and exit with error code! |
188 SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL; | 186 SDL_free (_this->hidden->pMixBuffers); |
189 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); | 187 _this->hidden->pMixBuffers = NULL; |
190 SDL_SetError("DART could not allocate buffers"); | 188 mciSendCommand (iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); |
191 return(-1); | 189 SDL_SetError ("DART could not allocate buffers"); |
192 } | 190 return (-1); |
193 // Ok, we have all the buffers allocated, let's mark them! | 191 } |
194 { | 192 // Ok, we have all the buffers allocated, let's mark them! |
193 { | |
194 int i; | |
195 for (i = 0; i < iNumBufs; i++) { | |
196 pMixBufferDesc pBufferDesc = | |
197 (pMixBufferDesc) SDL_malloc (sizeof (tMixBufferDesc));; | |
198 // Check if this buffer was really allocated by DART | |
199 if ((!(_this->hidden->pMixBuffers[i].pBuffer)) | |
200 || (!pBufferDesc)) { // Wrong buffer! | |
201 // Close DART, and exit with error code! | |
202 // Free buffer descriptions | |
203 { | |
204 int j; | |
205 for (j = 0; j < i; j++) | |
206 SDL_free ((void *) (_this->hidden->pMixBuffers[j]. | |
207 ulUserParm)); | |
208 } | |
209 // and cleanup | |
210 mciSendCommand (iDeviceOrd, MCI_BUFFER, | |
211 MCI_WAIT | MCI_DEALLOCATE_MEMORY, | |
212 &(_this->hidden->BufferParms), 0); | |
213 SDL_free (_this->hidden->pMixBuffers); | |
214 _this->hidden->pMixBuffers = NULL; | |
215 mciSendCommand (iDeviceOrd, MCI_CLOSE, MCI_WAIT, | |
216 &GenericParms, 0); | |
217 SDL_SetError ("Error at internal buffer check"); | |
218 return (-1); | |
219 } | |
220 pBufferDesc->iBufferUsage = BUFFER_EMPTY; | |
221 pBufferDesc->pSDLAudioDevice = _this; | |
222 | |
223 _this->hidden->pMixBuffers[i].ulBufferLength = | |
224 _this->hidden->BufferParms.ulBufferSize; | |
225 _this->hidden->pMixBuffers[i].ulUserParm = (ULONG) pBufferDesc; // User parameter: Description of buffer | |
226 _this->hidden->pMixBuffers[i].ulFlags = 0; // Some stuff should be flagged here for DART, like end of | |
227 // audio data, but as we will continously send | |
228 // audio data, there will be no end.:) | |
229 SDL_memset (_this->hidden->pMixBuffers[i].pBuffer, iSilence, | |
230 iBufSize); | |
231 } | |
232 } | |
233 _this->hidden->iNextFreeBuffer = 0; | |
234 _this->hidden->iLastPlayedBuf = -1; | |
235 // Create event semaphore | |
236 if (DosCreateEventSem | |
237 (NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE) != NO_ERROR) | |
238 { | |
239 // Could not create event semaphore! | |
240 { | |
241 int i; | |
242 for (i = 0; i < iNumBufs; i++) | |
243 SDL_free ((void *) (_this->hidden->pMixBuffers[i]. | |
244 ulUserParm)); | |
245 } | |
246 mciSendCommand (iDeviceOrd, MCI_BUFFER, | |
247 MCI_WAIT | MCI_DEALLOCATE_MEMORY, | |
248 &(_this->hidden->BufferParms), 0); | |
249 SDL_free (_this->hidden->pMixBuffers); | |
250 _this->hidden->pMixBuffers = NULL; | |
251 mciSendCommand (iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); | |
252 SDL_SetError ("Could not create event semaphore"); | |
253 return (-1); | |
254 } | |
255 // Store the new settings in global variables | |
256 _this->hidden->iCurrDeviceOrd = iDeviceOrd; | |
257 _this->hidden->iCurrFreq = iFreq; | |
258 _this->hidden->iCurrBits = iBits; | |
259 _this->hidden->iCurrChannels = iChannels; | |
260 _this->hidden->iCurrNumBufs = iNumBufs; | |
261 _this->hidden->iCurrBufSize = iBufSize; | |
262 | |
263 return (0); | |
264 } | |
265 | |
266 | |
267 | |
268 void | |
269 DART_ThreadInit (_THIS) | |
270 { | |
271 return; | |
272 } | |
273 | |
274 /* This function waits until it is possible to write a full sound buffer */ | |
275 void | |
276 DART_WaitAudio (_THIS) | |
277 { | |
195 int i; | 278 int i; |
196 for (i=0; i<iNumBufs; i++) | 279 pMixBufferDesc pBufDesc; |
280 ULONG ulPostCount; | |
281 | |
282 DosResetEventSem (_this->hidden->hevAudioBufferPlayed, &ulPostCount); | |
283 // If there is already an empty buffer, then return now! | |
284 for (i = 0; i < _this->hidden->iCurrNumBufs; i++) { | |
285 pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[i].ulUserParm; | |
286 if (pBufDesc->iBufferUsage == BUFFER_EMPTY) | |
287 return; | |
288 } | |
289 // If there is no empty buffer, wait for one to be empty! | |
290 DosWaitEventSem (_this->hidden->hevAudioBufferPlayed, 1000); // Wait max 1 sec!!! Important! | |
291 return; | |
292 } | |
293 | |
294 void | |
295 DART_PlayAudio (_THIS) | |
296 { | |
297 int iFreeBuf = _this->hidden->iNextFreeBuffer; | |
298 pMixBufferDesc pBufDesc; | |
299 | |
300 pBufDesc = | |
301 (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf].ulUserParm; | |
302 pBufDesc->iBufferUsage = BUFFER_USED; | |
303 // Send it to DART to be queued | |
304 _this->hidden->MixSetupParms.pmixWrite (_this->hidden->MixSetupParms. | |
305 ulMixHandle, | |
306 &(_this->hidden-> | |
307 pMixBuffers[iFreeBuf]), 1); | |
308 | |
309 _this->hidden->iLastPlayedBuf = iFreeBuf; | |
310 iFreeBuf = (iFreeBuf + 1) % _this->hidden->iCurrNumBufs; | |
311 _this->hidden->iNextFreeBuffer = iFreeBuf; | |
312 } | |
313 | |
314 Uint8 * | |
315 DART_GetAudioBuf (_THIS) | |
316 { | |
317 int iFreeBuf; | |
318 Uint8 *pResult; | |
319 pMixBufferDesc pBufDesc; | |
320 | |
321 if (_this) { | |
322 if (_this->hidden) { | |
323 iFreeBuf = _this->hidden->iNextFreeBuffer; | |
324 pBufDesc = | |
325 (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf]. | |
326 ulUserParm; | |
327 | |
328 if (pBufDesc) { | |
329 if (pBufDesc->iBufferUsage == BUFFER_EMPTY) { | |
330 pResult = _this->hidden->pMixBuffers[iFreeBuf].pBuffer; | |
331 return pResult; | |
332 } | |
333 } else | |
334 printf ("[DART_GetAudioBuf] : ERROR! pBufDesc = %p\n", | |
335 pBufDesc); | |
336 } else | |
337 printf ("[DART_GetAudioBuf] : ERROR! _this->hidden = %p\n", | |
338 _this->hidden); | |
339 } else | |
340 printf ("[DART_GetAudioBuf] : ERROR! _this = %p\n", _this); | |
341 return NULL; | |
342 } | |
343 | |
344 void | |
345 DART_WaitDone (_THIS) | |
346 { | |
347 pMixBufferDesc pBufDesc; | |
348 ULONG ulPostCount; | |
349 APIRET rc; | |
350 | |
351 pBufDesc = | |
352 (pMixBufferDesc) _this->hidden->pMixBuffers[_this->hidden-> | |
353 iLastPlayedBuf]. | |
354 ulUserParm; | |
355 rc = NO_ERROR; | |
356 while ((pBufDesc->iBufferUsage != BUFFER_EMPTY) && (rc == NO_ERROR)) { | |
357 DosResetEventSem (_this->hidden->hevAudioBufferPlayed, &ulPostCount); | |
358 rc = DosWaitEventSem (_this->hidden->hevAudioBufferPlayed, 1000); // 1 sec timeout! Important! | |
359 } | |
360 } | |
361 | |
362 void | |
363 DART_CloseAudio (_THIS) | |
364 { | |
365 MCI_GENERIC_PARMS GenericParms; | |
366 int rc; | |
367 | |
368 // Stop DART playback | |
369 rc = mciSendCommand (_this->hidden->iCurrDeviceOrd, MCI_STOP, MCI_WAIT, | |
370 &GenericParms, 0); | |
371 if (rc != MCIERR_SUCCESS) { | |
372 #ifdef SFX_DEBUG_BUILD | |
373 printf ("Could not stop DART playback!\n"); | |
374 fflush (stdout); | |
375 #endif | |
376 } | |
377 // Close event semaphore | |
378 DosCloseEventSem (_this->hidden->hevAudioBufferPlayed); | |
379 | |
380 // Free memory of buffer descriptions | |
197 { | 381 { |
198 pMixBufferDesc pBufferDesc = (pMixBufferDesc) SDL_malloc(sizeof(tMixBufferDesc));; | 382 int i; |
199 // Check if this buffer was really allocated by DART | 383 for (i = 0; i < _this->hidden->iCurrNumBufs; i++) |
200 if ((!(_this->hidden->pMixBuffers[i].pBuffer)) || (!pBufferDesc)) | 384 SDL_free ((void *) (_this->hidden->pMixBuffers[i].ulUserParm)); |
201 { // Wrong buffer! | 385 } |
202 // Close DART, and exit with error code! | 386 |
203 // Free buffer descriptions | 387 // Deallocate buffers |
204 { int j; | 388 rc = mciSendCommand (_this->hidden->iCurrDeviceOrd, MCI_BUFFER, |
205 for (j=0; j<i; j++) SDL_free((void *)(_this->hidden->pMixBuffers[j].ulUserParm)); | 389 MCI_WAIT | MCI_DEALLOCATE_MEMORY, |
206 } | 390 &(_this->hidden->BufferParms), 0); |
207 // and cleanup | 391 |
208 mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0); | 392 // Free bufferlist |
209 SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL; | 393 SDL_free (_this->hidden->pMixBuffers); |
210 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); | 394 _this->hidden->pMixBuffers = NULL; |
211 SDL_SetError("Error at internal buffer check"); | 395 |
212 return(-1); | 396 // Close dart |
213 } | 397 rc = mciSendCommand (_this->hidden->iCurrDeviceOrd, MCI_CLOSE, MCI_WAIT, |
214 pBufferDesc->iBufferUsage = BUFFER_EMPTY; | 398 &(GenericParms), 0); |
215 pBufferDesc->pSDLAudioDevice = _this; | |
216 | |
217 _this->hidden->pMixBuffers[i].ulBufferLength = _this->hidden->BufferParms.ulBufferSize; | |
218 _this->hidden->pMixBuffers[i].ulUserParm = (ULONG) pBufferDesc; // User parameter: Description of buffer | |
219 _this->hidden->pMixBuffers[i].ulFlags = 0; // Some stuff should be flagged here for DART, like end of | |
220 // audio data, but as we will continously send | |
221 // audio data, there will be no end.:) | |
222 SDL_memset(_this->hidden->pMixBuffers[i].pBuffer, iSilence, iBufSize); | |
223 } | |
224 } | |
225 _this->hidden->iNextFreeBuffer = 0; | |
226 _this->hidden->iLastPlayedBuf = -1; | |
227 // Create event semaphore | |
228 if (DosCreateEventSem(NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE)!=NO_ERROR) | |
229 { | |
230 // Could not create event semaphore! | |
231 { | |
232 int i; | |
233 for (i=0; i<iNumBufs; i++) SDL_free((void *)(_this->hidden->pMixBuffers[i].ulUserParm)); | |
234 } | |
235 mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0); | |
236 SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL; | |
237 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); | |
238 SDL_SetError("Could not create event semaphore"); | |
239 return(-1); | |
240 } | |
241 | |
242 // Store the new settings in global variables | |
243 _this->hidden->iCurrDeviceOrd = iDeviceOrd; | |
244 _this->hidden->iCurrFreq = iFreq; | |
245 _this->hidden->iCurrBits = iBits; | |
246 _this->hidden->iCurrChannels = iChannels; | |
247 _this->hidden->iCurrNumBufs = iNumBufs; | |
248 _this->hidden->iCurrBufSize = iBufSize; | |
249 | |
250 return (0); | |
251 } | |
252 | |
253 | |
254 | |
255 void DART_ThreadInit(_THIS) | |
256 { | |
257 return; | |
258 } | |
259 | |
260 /* This function waits until it is possible to write a full sound buffer */ | |
261 void DART_WaitAudio(_THIS) | |
262 { | |
263 int i; | |
264 pMixBufferDesc pBufDesc; | |
265 ULONG ulPostCount; | |
266 | |
267 DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount); | |
268 // If there is already an empty buffer, then return now! | |
269 for (i=0; i<_this->hidden->iCurrNumBufs; i++) | |
270 { | |
271 pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[i].ulUserParm; | |
272 if (pBufDesc->iBufferUsage == BUFFER_EMPTY) | |
273 return; | |
274 } | |
275 // If there is no empty buffer, wait for one to be empty! | |
276 DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // Wait max 1 sec!!! Important! | |
277 return; | |
278 } | |
279 | |
280 void DART_PlayAudio(_THIS) | |
281 { | |
282 int iFreeBuf = _this->hidden->iNextFreeBuffer; | |
283 pMixBufferDesc pBufDesc; | |
284 | |
285 pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf].ulUserParm; | |
286 pBufDesc->iBufferUsage = BUFFER_USED; | |
287 // Send it to DART to be queued | |
288 _this->hidden->MixSetupParms.pmixWrite(_this->hidden->MixSetupParms.ulMixHandle, | |
289 &(_this->hidden->pMixBuffers[iFreeBuf]), 1); | |
290 | |
291 _this->hidden->iLastPlayedBuf = iFreeBuf; | |
292 iFreeBuf = (iFreeBuf+1) % _this->hidden->iCurrNumBufs; | |
293 _this->hidden->iNextFreeBuffer = iFreeBuf; | |
294 } | |
295 | |
296 Uint8 *DART_GetAudioBuf(_THIS) | |
297 { | |
298 int iFreeBuf; | |
299 Uint8 *pResult; | |
300 pMixBufferDesc pBufDesc; | |
301 | |
302 if (_this) | |
303 { | |
304 if (_this->hidden) | |
305 { | |
306 iFreeBuf = _this->hidden->iNextFreeBuffer; | |
307 pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf].ulUserParm; | |
308 | |
309 if (pBufDesc) | |
310 { | |
311 if (pBufDesc->iBufferUsage == BUFFER_EMPTY) | |
312 { | |
313 pResult = _this->hidden->pMixBuffers[iFreeBuf].pBuffer; | |
314 return pResult; | |
315 } | |
316 } else | |
317 printf("[DART_GetAudioBuf] : ERROR! pBufDesc = %p\n", pBufDesc); | |
318 } else | |
319 printf("[DART_GetAudioBuf] : ERROR! _this->hidden = %p\n", _this->hidden); | |
320 } else | |
321 printf("[DART_GetAudioBuf] : ERROR! _this = %p\n", _this); | |
322 return NULL; | |
323 } | |
324 | |
325 void DART_WaitDone(_THIS) | |
326 { | |
327 pMixBufferDesc pBufDesc; | |
328 ULONG ulPostCount; | |
329 APIRET rc; | |
330 | |
331 pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[_this->hidden->iLastPlayedBuf].ulUserParm; | |
332 rc = NO_ERROR; | |
333 while ((pBufDesc->iBufferUsage != BUFFER_EMPTY) && (rc==NO_ERROR)) | |
334 { | |
335 DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount); | |
336 rc = DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // 1 sec timeout! Important! | |
337 } | |
338 } | |
339 | |
340 void DART_CloseAudio(_THIS) | |
341 { | |
342 MCI_GENERIC_PARMS GenericParms; | |
343 int rc; | |
344 | |
345 // Stop DART playback | |
346 rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP, MCI_WAIT, &GenericParms, 0); | |
347 if (rc!=MCIERR_SUCCESS) | |
348 { | |
349 #ifdef SFX_DEBUG_BUILD | |
350 printf("Could not stop DART playback!\n"); | |
351 fflush(stdout); | |
352 #endif | |
353 } | |
354 | |
355 // Close event semaphore | |
356 DosCloseEventSem(_this->hidden->hevAudioBufferPlayed); | |
357 | |
358 // Free memory of buffer descriptions | |
359 { | |
360 int i; | |
361 for (i=0; i<_this->hidden->iCurrNumBufs; i++) SDL_free((void *)(_this->hidden->pMixBuffers[i].ulUserParm)); | |
362 } | |
363 | |
364 // Deallocate buffers | |
365 rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0); | |
366 | |
367 // Free bufferlist | |
368 SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL; | |
369 | |
370 // Close dart | |
371 rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE, MCI_WAIT, &(GenericParms), 0); | |
372 } | 399 } |
373 | 400 |
374 /* Audio driver bootstrap functions */ | 401 /* Audio driver bootstrap functions */ |
375 | 402 |
376 int Audio_Available(void) | 403 int |
377 { | 404 Audio_Available (void) |
378 return(1); | 405 { |
379 } | 406 return (1); |
380 | 407 } |
381 void Audio_DeleteDevice(SDL_AudioDevice *device) | 408 |
382 { | 409 void |
383 SDL_free(device->hidden); | 410 Audio_DeleteDevice (SDL_AudioDevice * device) |
384 SDL_free(device); | 411 { |
385 } | 412 SDL_free (device->hidden); |
386 | 413 SDL_free (device); |
387 SDL_AudioDevice *Audio_CreateDevice(int devindex) | 414 } |
388 { | 415 |
389 SDL_AudioDevice *this; | 416 SDL_AudioDevice * |
390 | 417 Audio_CreateDevice (int devindex) |
391 /* Initialize all variables that we clean on shutdown */ | 418 { |
392 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); | 419 SDL_AudioDevice *this; |
393 if ( this ) | 420 |
394 { | 421 /* Initialize all variables that we clean on shutdown */ |
395 SDL_memset(this, 0, (sizeof *this)); | 422 this = (SDL_AudioDevice *) SDL_malloc (sizeof (SDL_AudioDevice)); |
396 this->hidden = (struct SDL_PrivateAudioData *) | 423 if (this) { |
397 SDL_malloc((sizeof *this->hidden)); | 424 SDL_memset (this, 0, (sizeof *this)); |
398 } | 425 this->hidden = (struct SDL_PrivateAudioData *) |
399 if ( (this == NULL) || (this->hidden == NULL) ) | 426 SDL_malloc ((sizeof *this->hidden)); |
400 { | 427 } |
401 SDL_OutOfMemory(); | 428 if ((this == NULL) || (this->hidden == NULL)) { |
402 if ( this ) | 429 SDL_OutOfMemory (); |
403 SDL_free(this); | 430 if (this) |
404 return(0); | 431 SDL_free (this); |
405 } | 432 return (0); |
406 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | 433 } |
407 | 434 SDL_memset (this->hidden, 0, (sizeof *this->hidden)); |
408 /* Set the function pointers */ | 435 |
409 this->OpenAudio = DART_OpenAudio; | 436 /* Set the function pointers */ |
410 this->ThreadInit = DART_ThreadInit; | 437 this->OpenAudio = DART_OpenAudio; |
411 this->WaitAudio = DART_WaitAudio; | 438 this->ThreadInit = DART_ThreadInit; |
412 this->PlayAudio = DART_PlayAudio; | 439 this->WaitAudio = DART_WaitAudio; |
413 this->GetAudioBuf = DART_GetAudioBuf; | 440 this->PlayAudio = DART_PlayAudio; |
414 this->WaitDone = DART_WaitDone; | 441 this->GetAudioBuf = DART_GetAudioBuf; |
415 this->CloseAudio = DART_CloseAudio; | 442 this->WaitDone = DART_WaitDone; |
416 | 443 this->CloseAudio = DART_CloseAudio; |
417 this->free = Audio_DeleteDevice; | 444 |
418 | 445 this->free = Audio_DeleteDevice; |
419 return this; | 446 |
447 return this; | |
420 } | 448 } |
421 | 449 |
422 AudioBootStrap DART_bootstrap = { | 450 AudioBootStrap DART_bootstrap = { |
423 "dart", "OS/2 Direct Audio RouTines (DART)", | 451 "dart", "OS/2 Direct Audio RouTines (DART)", |
424 Audio_Available, Audio_CreateDevice | 452 Audio_Available, Audio_CreateDevice |
425 }; | 453 }; |
426 | 454 |
455 /* vi: set ts=4 sw=4 expandtab: */ |