Mercurial > sdl-ios-xcode
annotate src/audio/dart/SDL_dart.c @ 4139:568c9b3c0167 SDL-1.2
* Added configure option --enable-screensaver, to allow enabling the screensaver by default.
* Use XResetScreenSaver() instead of disabling screensaver entirely.
Full discussion summary from Erik on the SDL mailing list:
Current behaviour
=================
SDL changes the user's display power management settings without
permission from the user and without telling the user.
The interface that it uses to do so is DPMSDisable/DPMSEnable, which
should only ever be used by configuration utilities like KControl, never
by normal application programs, let alone by the libraries that they
use. Using an interface that is not at all intended for what SDL tries
to achieve means that it will not work as it should. Firstly, the power
management is completely disabled during the whole lifetime of the SDL
program, not only when it should be. Secondly, it makes SDL
non-reentrant, meaning that things will break when multiple SDL programs
are clients of the same X server simultaneously. Thirdly, no cleanup
mechanism ensures that the setting is restored if the client does not do
that (for example if it crashes).
In addition to that, this interface is broken on xorg,
[http://bugs.freedesktop.org/show_bug.cgi?id=13962], so what SDL tries
to do does not work at all on that implementation of the X Window
System. (The reason that the DPMSEnable works in KControl is that it
calls DPMSSetTimeout immediately after,
[http://websvn.kde.org/tags/KDE/3.5.9/kdebase/kcontrol/energy/energy.cpp?annotate=774532#l343]).
The problems that the current behaviour causes
==============================================
1. Information leak. When the user is away, someone might see what the
user has on the display when the user counts on the screensaver
preventing this. This does not even require physical access to the
workstation, it is enough to see it from a distance.
2. Draining battery. An SDL program that runs on a laptop will quickly
drain the battery while the user is away. The system will soon shut down
and require recharging before being usable again, while it should in
fact have consumed very little energy if the user's settings would have
been obeyed.
3. Wasting energy. Even if battery issues are not considered, energy as
such is wasted.
4. Display wear. The display may be worn out.
The problems that the current behaviour tries to solve
======================================================
1. Preventing screensaver while playing movies.
Many SDL applications are media players. They have reasons to prevent
screensavers from being activated while a movie is being played. When a
user clicks on the play button it can be interpreted as saying "play
this movie, but do not turn off the display while playing it, because I
will watch it even though I do not interact with the system".
2. Preventing screensaver when some input bypasses X.
Sometimes SDL uses input from another source than the X server, so
that the X server is bypassed. This obviously breaks the screensaver
handling. SDL tries to work around that.
3. Preventing screensaver when all input bypasses X.
There is something called Direct Graphics Access mode, where a
program takes control of both the display and the input devices from the
X server. This obviously means that the X server can not handle the
screensaver alone, since screensaver handling depends on input handling.
SDL does not do what it should to help the X server to handle the
screensaver. Nor does SDL take care of screeensaver handling itself. SDL
simply disables the screensaver completely.
How the problems should be solved
=================================
The correct way for an application program to prevent the screensaver
under X is to call XResetScreenSaver. This was recently discovered and
implemented by the mplayer developers,
[http://svn.mplayerhq.hu/mplayer?view=rev&revision=25637]. SDL needs to
wrap this in an API call (SDL_ResetScreenSaver) and implement it for the
other video targets (if they do not have a corresponding call, SDL
should do what it takes on that particular target, for example sending
fake key events).
1. When a movie is played, the player should reset the screensaver when
the animation is advanced to a new frame. The same applies to anything
similar, like slideshows.
2. When the X server is handling input, it must handle all input
(keyboards, mice, gamepads, ...). This is necessary, not only to be able
to handle the screensaver, but also so that it can send the events to
the correct (the currently active) client. If there is an input device
that the X server can not handle for some reason (such as lack of Plug
and Play capability), the program that handles the device as a
workaround must simulate what would happen if the X server would have
handled the device, by calling XResetScreenSaver when input is received
from the device.
3. When the X server is not handling the input, it depends on the
program that does to call XResetScreenSaver whenever an input event
occurs. Alternatively the program must handle the screensaver countdown
internally and call XActivateScreenSaver.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Fri, 29 Feb 2008 13:55:44 +0000 |
parents | 5b5e549382b3 |
children | a1b03ba2fcd0 |
rev | line source |
---|---|
1190 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
3 Copyright (C) 1997-2006 Sam Lantinga |
1190 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
1190 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
1190 | 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 | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
13 Lesser General Public License for more details. |
1190 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1190 | 18 |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
22 #include "SDL_config.h" |
1190 | 23 |
24 /* Allow access to a raw mixing buffer */ | |
25 | |
26 #include "SDL_timer.h" | |
27 #include "SDL_audio.h" | |
1361
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
28 #include "../SDL_audio_c.h" |
1190 | 29 #include "SDL_dart.h" |
30 | |
31 // Buffer states: | |
32 #define BUFFER_EMPTY 0 | |
33 #define BUFFER_USED 1 | |
34 | |
35 typedef struct _tMixBufferDesc { | |
36 int iBufferUsage; // BUFFER_EMPTY or BUFFER_USED | |
37 SDL_AudioDevice *pSDLAudioDevice; | |
38 } tMixBufferDesc, *pMixBufferDesc; | |
39 | |
40 | |
41 //--------------------------------------------------------------------- | |
42 // DARTEventFunc | |
43 // | |
44 // This function is called by DART, when an event occures, like end of | |
45 // playback of a buffer, etc... | |
46 //--------------------------------------------------------------------- | |
47 LONG APIENTRY DARTEventFunc(ULONG ulStatus, | |
48 PMCI_MIX_BUFFER pBuffer, | |
49 ULONG ulFlags) | |
50 { | |
51 if (ulFlags && MIX_WRITE_COMPLETE) | |
52 { // Playback of buffer completed! | |
53 | |
54 // Get pointer to buffer description | |
55 pMixBufferDesc pBufDesc; | |
56 | |
57 if (pBuffer) | |
58 { | |
59 pBufDesc = (pMixBufferDesc) (*pBuffer).ulUserParm; | |
60 | |
61 if (pBufDesc) | |
62 { | |
63 SDL_AudioDevice *pSDLAudioDevice = pBufDesc->pSDLAudioDevice; | |
64 // Set the buffer to be empty | |
65 pBufDesc->iBufferUsage = BUFFER_EMPTY; | |
66 // And notify DART feeder thread that it will have to work a bit. | |
67 if (pSDLAudioDevice) | |
68 DosPostEventSem(pSDLAudioDevice->hidden->hevAudioBufferPlayed); | |
69 } | |
70 } | |
71 } | |
72 return TRUE; | |
73 } | |
74 | |
75 | |
76 int DART_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
77 { | |
3852
5b5e549382b3
Removed some new 1.3 symbols from code backported to 1.2.
Ryan C. Gordon <icculus@icculus.org>
parents:
3851
diff
changeset
|
78 Uint16 test_format = SDL_FirstAudioFormat(spec->format); |
3851
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
79 int valid_datatype = 0; |
1190 | 80 MCI_AMP_OPEN_PARMS AmpOpenParms; |
81 MCI_GENERIC_PARMS GenericParms; | |
82 int iDeviceOrd = 0; // Default device to be used | |
83 int bOpenShared = 1; // Try opening it shared | |
84 int iBits = 16; // Default is 16 bits signed | |
85 int iFreq = 44100; // Default is 44KHz | |
86 int iChannels = 2; // Default is 2 channels (Stereo) | |
87 int iNumBufs = 2; // Number of audio buffers: 2 | |
88 int iBufSize; | |
89 int iOpenMode; | |
90 int iSilence; | |
91 int rc; | |
92 | |
93 // First thing is to try to open a given DART device! | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
94 SDL_memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS)); |
1190 | 95 // pszDeviceType should contain the device type in low word, and device ordinal in high word! |
96 AmpOpenParms.pszDeviceType = (PSZ) (MCI_DEVTYPE_AUDIO_AMPMIX | (iDeviceOrd << 16)); | |
97 | |
98 iOpenMode = MCI_WAIT | MCI_OPEN_TYPE_ID; | |
99 if (bOpenShared) iOpenMode |= MCI_OPEN_SHAREABLE; | |
100 | |
101 rc = mciSendCommand( 0, MCI_OPEN, | |
102 iOpenMode, | |
103 (PVOID) &AmpOpenParms, 0); | |
104 if (rc!=MCIERR_SUCCESS) // No audio available?? | |
105 return (-1); | |
106 // Save the device ID we got from DART! | |
107 // We will use this in the next calls! | |
108 iDeviceOrd = AmpOpenParms.usDeviceID; | |
109 | |
110 // Determine the audio parameters from the AudioSpec | |
3851
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
111 if (spec->channels > 2) |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
112 spec->channels = 2; // !!! FIXME: more than stereo support in OS/2? |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
113 |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
114 while ((!valid_datatype) && (test_format)) { |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
115 spec->format = test_format; |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
116 valid_datatype = 1; |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
117 switch (test_format) { |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
118 case AUDIO_U8: |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
119 // Unsigned 8 bit audio data |
1190 | 120 iSilence = 0x80; |
121 iBits = 8; | |
122 break; | |
3851
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
123 |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
124 case AUDIO_S16LSB: |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
125 // Signed 16 bit audio data |
1190 | 126 iSilence = 0x00; |
127 iBits = 16; | |
128 break; | |
3851
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
129 |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
130 default: |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
131 valid_datatype = 0; |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
132 test_format = SDL_NextAudioFormat(); |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
133 break; |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
134 } |
1190 | 135 } |
3851
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
136 |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
137 if (!valid_datatype) { // shouldn't happen, but just in case... |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
138 // Close DART, and exit with error code! |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
139 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
140 SDL_SetError("Unsupported audio format"); |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
141 return (-1); |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
142 } |
405a192b68e7
Backport from 1.3: most of the audio drivers can now handle data
Ryan C. Gordon <icculus@icculus.org>
parents:
1402
diff
changeset
|
143 |
1190 | 144 iFreq = spec->freq; |
145 iChannels = spec->channels; | |
146 /* Update the fragment size as size in bytes */ | |
147 SDL_CalculateAudioSpec(spec); | |
148 iBufSize = spec->size; | |
149 | |
150 // Now query this device if it supports the given freq/bits/channels! | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
151 SDL_memset(&(_this->hidden->MixSetupParms), 0, sizeof(MCI_MIXSETUP_PARMS)); |
1190 | 152 _this->hidden->MixSetupParms.ulBitsPerSample = iBits; |
153 _this->hidden->MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM; | |
154 _this->hidden->MixSetupParms.ulSamplesPerSec = iFreq; | |
155 _this->hidden->MixSetupParms.ulChannels = iChannels; | |
156 _this->hidden->MixSetupParms.ulFormatMode = MCI_PLAY; | |
157 _this->hidden->MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO; | |
158 _this->hidden->MixSetupParms.pmixEvent = DARTEventFunc; | |
159 rc = mciSendCommand (iDeviceOrd, MCI_MIXSETUP, | |
160 MCI_WAIT | MCI_MIXSETUP_QUERYMODE, | |
161 &(_this->hidden->MixSetupParms), 0); | |
162 if (rc!=MCIERR_SUCCESS) | |
163 { // The device cannot handle this format! | |
164 // Close DART, and exit with error code! | |
165 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); | |
166 SDL_SetError("Audio device doesn't support requested audio format"); | |
167 return(-1); | |
168 } | |
169 // The device can handle this format, so initialize! | |
170 rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP, | |
171 MCI_WAIT | MCI_MIXSETUP_INIT, | |
172 &(_this->hidden->MixSetupParms), 0); | |
173 if (rc!=MCIERR_SUCCESS) | |
174 { // The device could not be opened! | |
175 // Close DART, and exit with error code! | |
176 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); | |
177 SDL_SetError("Audio device could not be set up"); | |
178 return(-1); | |
179 } | |
180 // Ok, the device is initialized. | |
181 // Now we should allocate buffers. For this, we need a place where | |
182 // the buffer descriptors will be: | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
183 _this->hidden->pMixBuffers = (MCI_MIX_BUFFER *) SDL_malloc(sizeof(MCI_MIX_BUFFER)*iNumBufs); |
1190 | 184 if (!(_this->hidden->pMixBuffers)) |
185 { // Not enough memory! | |
186 // Close DART, and exit with error code! | |
187 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); | |
188 SDL_SetError("Not enough memory for audio buffer descriptors"); | |
189 return(-1); | |
190 } | |
191 // Now that we have the place for buffer list, we can ask DART for the | |
192 // buffers! | |
193 _this->hidden->BufferParms.ulNumBuffers = iNumBufs; // Number of buffers | |
194 _this->hidden->BufferParms.ulBufferSize = iBufSize; // each with this size | |
195 _this->hidden->BufferParms.pBufList = _this->hidden->pMixBuffers; // getting descriptorts into this list | |
196 // Allocate buffers! | |
197 rc = mciSendCommand(iDeviceOrd, MCI_BUFFER, | |
198 MCI_WAIT | MCI_ALLOCATE_MEMORY, | |
199 &(_this->hidden->BufferParms), 0); | |
200 if ((rc!=MCIERR_SUCCESS) || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers) || (_this->hidden->BufferParms.ulBufferSize==0)) | |
201 { // Could not allocate memory! | |
202 // Close DART, and exit with error code! | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
203 SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL; |
1190 | 204 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); |
205 SDL_SetError("DART could not allocate buffers"); | |
206 return(-1); | |
207 } | |
208 // Ok, we have all the buffers allocated, let's mark them! | |
209 { | |
210 int i; | |
211 for (i=0; i<iNumBufs; i++) | |
212 { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
213 pMixBufferDesc pBufferDesc = (pMixBufferDesc) SDL_malloc(sizeof(tMixBufferDesc));; |
1190 | 214 // Check if this buffer was really allocated by DART |
215 if ((!(_this->hidden->pMixBuffers[i].pBuffer)) || (!pBufferDesc)) | |
216 { // Wrong buffer! | |
217 // Close DART, and exit with error code! | |
218 // Free buffer descriptions | |
219 { int j; | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
220 for (j=0; j<i; j++) SDL_free((void *)(_this->hidden->pMixBuffers[j].ulUserParm)); |
1190 | 221 } |
222 // and cleanup | |
223 mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0); | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
224 SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL; |
1190 | 225 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); |
226 SDL_SetError("Error at internal buffer check"); | |
227 return(-1); | |
228 } | |
229 pBufferDesc->iBufferUsage = BUFFER_EMPTY; | |
230 pBufferDesc->pSDLAudioDevice = _this; | |
231 | |
232 _this->hidden->pMixBuffers[i].ulBufferLength = _this->hidden->BufferParms.ulBufferSize; | |
233 _this->hidden->pMixBuffers[i].ulUserParm = (ULONG) pBufferDesc; // User parameter: Description of buffer | |
234 _this->hidden->pMixBuffers[i].ulFlags = 0; // Some stuff should be flagged here for DART, like end of | |
235 // audio data, but as we will continously send | |
236 // audio data, there will be no end.:) | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
237 SDL_memset(_this->hidden->pMixBuffers[i].pBuffer, iSilence, iBufSize); |
1190 | 238 } |
239 } | |
240 _this->hidden->iNextFreeBuffer = 0; | |
241 _this->hidden->iLastPlayedBuf = -1; | |
242 // Create event semaphore | |
243 if (DosCreateEventSem(NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE)!=NO_ERROR) | |
244 { | |
245 // Could not create event semaphore! | |
246 { | |
247 int i; | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
248 for (i=0; i<iNumBufs; i++) SDL_free((void *)(_this->hidden->pMixBuffers[i].ulUserParm)); |
1190 | 249 } |
250 mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0); | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
251 SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL; |
1190 | 252 mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); |
253 SDL_SetError("Could not create event semaphore"); | |
254 return(-1); | |
255 } | |
256 | |
257 // Store the new settings in global variables | |
258 _this->hidden->iCurrDeviceOrd = iDeviceOrd; | |
259 _this->hidden->iCurrFreq = iFreq; | |
260 _this->hidden->iCurrBits = iBits; | |
261 _this->hidden->iCurrChannels = iChannels; | |
262 _this->hidden->iCurrNumBufs = iNumBufs; | |
263 _this->hidden->iCurrBufSize = iBufSize; | |
264 | |
265 return (0); | |
266 } | |
267 | |
268 | |
269 | |
270 void DART_ThreadInit(_THIS) | |
271 { | |
272 return; | |
273 } | |
274 | |
275 /* This function waits until it is possible to write a full sound buffer */ | |
276 void DART_WaitAudio(_THIS) | |
277 { | |
278 int 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 { | |
286 pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[i].ulUserParm; | |
287 if (pBufDesc->iBufferUsage == BUFFER_EMPTY) | |
288 return; | |
289 } | |
290 // If there is no empty buffer, wait for one to be empty! | |
291 DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // Wait max 1 sec!!! Important! | |
292 return; | |
293 } | |
294 | |
295 void DART_PlayAudio(_THIS) | |
296 { | |
297 int iFreeBuf = _this->hidden->iNextFreeBuffer; | |
298 pMixBufferDesc pBufDesc; | |
299 | |
300 pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf].ulUserParm; | |
301 pBufDesc->iBufferUsage = BUFFER_USED; | |
302 // Send it to DART to be queued | |
303 _this->hidden->MixSetupParms.pmixWrite(_this->hidden->MixSetupParms.ulMixHandle, | |
304 &(_this->hidden->pMixBuffers[iFreeBuf]), 1); | |
305 | |
306 _this->hidden->iLastPlayedBuf = iFreeBuf; | |
307 iFreeBuf = (iFreeBuf+1) % _this->hidden->iCurrNumBufs; | |
308 _this->hidden->iNextFreeBuffer = iFreeBuf; | |
309 } | |
310 | |
311 Uint8 *DART_GetAudioBuf(_THIS) | |
312 { | |
313 int iFreeBuf; | |
314 Uint8 *pResult; | |
315 pMixBufferDesc pBufDesc; | |
316 | |
317 if (_this) | |
318 { | |
319 if (_this->hidden) | |
320 { | |
321 iFreeBuf = _this->hidden->iNextFreeBuffer; | |
322 pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf].ulUserParm; | |
323 | |
324 if (pBufDesc) | |
325 { | |
326 if (pBufDesc->iBufferUsage == BUFFER_EMPTY) | |
327 { | |
328 pResult = _this->hidden->pMixBuffers[iFreeBuf].pBuffer; | |
329 return pResult; | |
330 } | |
331 } else | |
332 printf("[DART_GetAudioBuf] : ERROR! pBufDesc = %p\n", pBufDesc); | |
333 } else | |
334 printf("[DART_GetAudioBuf] : ERROR! _this->hidden = %p\n", _this->hidden); | |
335 } else | |
336 printf("[DART_GetAudioBuf] : ERROR! _this = %p\n", _this); | |
337 return NULL; | |
338 } | |
339 | |
340 void DART_WaitDone(_THIS) | |
341 { | |
342 pMixBufferDesc pBufDesc; | |
343 ULONG ulPostCount; | |
344 APIRET rc; | |
345 | |
346 pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[_this->hidden->iLastPlayedBuf].ulUserParm; | |
347 rc = NO_ERROR; | |
348 while ((pBufDesc->iBufferUsage != BUFFER_EMPTY) && (rc==NO_ERROR)) | |
349 { | |
350 DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount); | |
351 rc = DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // 1 sec timeout! Important! | |
352 } | |
353 } | |
354 | |
355 void DART_CloseAudio(_THIS) | |
356 { | |
357 MCI_GENERIC_PARMS GenericParms; | |
358 int rc; | |
359 | |
360 // Stop DART playback | |
361 rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP, MCI_WAIT, &GenericParms, 0); | |
362 if (rc!=MCIERR_SUCCESS) | |
363 { | |
364 #ifdef SFX_DEBUG_BUILD | |
365 printf("Could not stop DART playback!\n"); | |
366 fflush(stdout); | |
367 #endif | |
368 } | |
369 | |
370 // Close event semaphore | |
371 DosCloseEventSem(_this->hidden->hevAudioBufferPlayed); | |
372 | |
373 // Free memory of buffer descriptions | |
374 { | |
375 int i; | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
376 for (i=0; i<_this->hidden->iCurrNumBufs; i++) SDL_free((void *)(_this->hidden->pMixBuffers[i].ulUserParm)); |
1190 | 377 } |
378 | |
379 // Deallocate buffers | |
380 rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0); | |
381 | |
382 // Free bufferlist | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
383 SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL; |
1190 | 384 |
385 // Close dart | |
386 rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE, MCI_WAIT, &(GenericParms), 0); | |
387 } | |
388 | |
389 /* Audio driver bootstrap functions */ | |
390 | |
391 int Audio_Available(void) | |
392 { | |
393 return(1); | |
394 } | |
395 | |
396 void Audio_DeleteDevice(SDL_AudioDevice *device) | |
397 { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
398 SDL_free(device->hidden); |
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
399 SDL_free(device); |
1190 | 400 } |
401 | |
402 SDL_AudioDevice *Audio_CreateDevice(int devindex) | |
403 { | |
404 SDL_AudioDevice *this; | |
405 | |
406 /* Initialize all variables that we clean on shutdown */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
407 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); |
1190 | 408 if ( this ) |
409 { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
410 SDL_memset(this, 0, (sizeof *this)); |
1190 | 411 this->hidden = (struct SDL_PrivateAudioData *) |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
412 SDL_malloc((sizeof *this->hidden)); |
1190 | 413 } |
414 if ( (this == NULL) || (this->hidden == NULL) ) | |
415 { | |
416 SDL_OutOfMemory(); | |
417 if ( this ) | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
418 SDL_free(this); |
1190 | 419 return(0); |
420 } | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
421 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); |
1190 | 422 |
423 /* Set the function pointers */ | |
424 this->OpenAudio = DART_OpenAudio; | |
425 this->ThreadInit = DART_ThreadInit; | |
426 this->WaitAudio = DART_WaitAudio; | |
427 this->PlayAudio = DART_PlayAudio; | |
428 this->GetAudioBuf = DART_GetAudioBuf; | |
429 this->WaitDone = DART_WaitDone; | |
430 this->CloseAudio = DART_CloseAudio; | |
431 | |
432 this->free = Audio_DeleteDevice; | |
433 | |
434 return this; | |
435 } | |
436 | |
437 AudioBootStrap DART_bootstrap = { | |
438 "dart", "OS/2 Direct Audio RouTines (DART)", | |
439 Audio_Available, Audio_CreateDevice | |
440 }; | |
441 |