root / audio / sdlaudio.c @ cf2c1839
History | View | Annotate | Download (10.4 kB)
1 | 85571bc7 | bellard | /*
|
---|---|---|---|
2 | 1d14ffa9 | bellard | * QEMU SDL audio driver
|
3 | 1d14ffa9 | bellard | *
|
4 | 1d14ffa9 | bellard | * Copyright (c) 2004-2005 Vassili Karpov (malc)
|
5 | 1d14ffa9 | bellard | *
|
6 | 85571bc7 | bellard | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 85571bc7 | bellard | * of this software and associated documentation files (the "Software"), to deal
|
8 | 85571bc7 | bellard | * in the Software without restriction, including without limitation the rights
|
9 | 85571bc7 | bellard | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 85571bc7 | bellard | * copies of the Software, and to permit persons to whom the Software is
|
11 | 85571bc7 | bellard | * furnished to do so, subject to the following conditions:
|
12 | 85571bc7 | bellard | *
|
13 | 85571bc7 | bellard | * The above copyright notice and this permission notice shall be included in
|
14 | 85571bc7 | bellard | * all copies or substantial portions of the Software.
|
15 | 85571bc7 | bellard | *
|
16 | 85571bc7 | bellard | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | 85571bc7 | bellard | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | 85571bc7 | bellard | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | 85571bc7 | bellard | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | 85571bc7 | bellard | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | 85571bc7 | bellard | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | 85571bc7 | bellard | * THE SOFTWARE.
|
23 | 85571bc7 | bellard | */
|
24 | 9f059eca | bellard | #include <SDL.h> |
25 | 9f059eca | bellard | #include <SDL_thread.h> |
26 | 87ecb68b | pbrook | #include "qemu-common.h" |
27 | 87ecb68b | pbrook | #include "audio.h" |
28 | 85571bc7 | bellard | |
29 | e784ba70 | ths | #ifndef _WIN32
|
30 | e784ba70 | ths | #ifdef __sun__
|
31 | e784ba70 | ths | #define _POSIX_PTHREAD_SEMANTICS 1 |
32 | c5e97233 | blueswir1 | #elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
|
33 | 9b4c14c3 | blueswir1 | #include <pthread.h> |
34 | e784ba70 | ths | #endif
|
35 | e784ba70 | ths | #include <signal.h> |
36 | e784ba70 | ths | #endif
|
37 | e784ba70 | ths | |
38 | 1d14ffa9 | bellard | #define AUDIO_CAP "sdl" |
39 | 1d14ffa9 | bellard | #include "audio_int.h" |
40 | 85571bc7 | bellard | |
41 | 1d14ffa9 | bellard | typedef struct SDLVoiceOut { |
42 | 1d14ffa9 | bellard | HWVoiceOut hw; |
43 | 1d14ffa9 | bellard | int live;
|
44 | ff541499 | malc | int rpos;
|
45 | 1d14ffa9 | bellard | int decr;
|
46 | 1d14ffa9 | bellard | } SDLVoiceOut; |
47 | 85571bc7 | bellard | |
48 | 85571bc7 | bellard | static struct { |
49 | 85571bc7 | bellard | int nb_samples;
|
50 | 85571bc7 | bellard | } conf = { |
51 | 1a40d5e2 | Juan Quintela | .nb_samples = 1024
|
52 | 85571bc7 | bellard | }; |
53 | 85571bc7 | bellard | |
54 | b1d8e52e | blueswir1 | static struct SDLAudioState { |
55 | 85571bc7 | bellard | int exit;
|
56 | 85571bc7 | bellard | SDL_mutex *mutex; |
57 | 85571bc7 | bellard | SDL_sem *sem; |
58 | 85571bc7 | bellard | int initialized;
|
59 | 85571bc7 | bellard | } glob_sdl; |
60 | 85571bc7 | bellard | typedef struct SDLAudioState SDLAudioState; |
61 | 85571bc7 | bellard | |
62 | 1d14ffa9 | bellard | static void GCC_FMT_ATTR (1, 2) sdl_logerr (const char *fmt, ...) |
63 | 85571bc7 | bellard | { |
64 | 1d14ffa9 | bellard | va_list ap; |
65 | 1d14ffa9 | bellard | |
66 | 1d14ffa9 | bellard | va_start (ap, fmt); |
67 | 1d14ffa9 | bellard | AUD_vlog (AUDIO_CAP, fmt, ap); |
68 | 1d14ffa9 | bellard | va_end (ap); |
69 | 1d14ffa9 | bellard | |
70 | 1d14ffa9 | bellard | AUD_log (AUDIO_CAP, "Reason: %s\n", SDL_GetError ());
|
71 | 85571bc7 | bellard | } |
72 | 85571bc7 | bellard | |
73 | 1d14ffa9 | bellard | static int sdl_lock (SDLAudioState *s, const char *forfn) |
74 | 85571bc7 | bellard | { |
75 | 85571bc7 | bellard | if (SDL_LockMutex (s->mutex)) {
|
76 | 1d14ffa9 | bellard | sdl_logerr ("SDL_LockMutex for %s failed\n", forfn);
|
77 | 85571bc7 | bellard | return -1; |
78 | 85571bc7 | bellard | } |
79 | 85571bc7 | bellard | return 0; |
80 | 85571bc7 | bellard | } |
81 | 85571bc7 | bellard | |
82 | 1d14ffa9 | bellard | static int sdl_unlock (SDLAudioState *s, const char *forfn) |
83 | 85571bc7 | bellard | { |
84 | 85571bc7 | bellard | if (SDL_UnlockMutex (s->mutex)) {
|
85 | 1d14ffa9 | bellard | sdl_logerr ("SDL_UnlockMutex for %s failed\n", forfn);
|
86 | 85571bc7 | bellard | return -1; |
87 | 85571bc7 | bellard | } |
88 | 85571bc7 | bellard | return 0; |
89 | 85571bc7 | bellard | } |
90 | 85571bc7 | bellard | |
91 | 1d14ffa9 | bellard | static int sdl_post (SDLAudioState *s, const char *forfn) |
92 | 85571bc7 | bellard | { |
93 | 85571bc7 | bellard | if (SDL_SemPost (s->sem)) {
|
94 | 1d14ffa9 | bellard | sdl_logerr ("SDL_SemPost for %s failed\n", forfn);
|
95 | 85571bc7 | bellard | return -1; |
96 | 85571bc7 | bellard | } |
97 | 85571bc7 | bellard | return 0; |
98 | 85571bc7 | bellard | } |
99 | 85571bc7 | bellard | |
100 | 1d14ffa9 | bellard | static int sdl_wait (SDLAudioState *s, const char *forfn) |
101 | 85571bc7 | bellard | { |
102 | 85571bc7 | bellard | if (SDL_SemWait (s->sem)) {
|
103 | 1d14ffa9 | bellard | sdl_logerr ("SDL_SemWait for %s failed\n", forfn);
|
104 | 85571bc7 | bellard | return -1; |
105 | 85571bc7 | bellard | } |
106 | 85571bc7 | bellard | return 0; |
107 | 85571bc7 | bellard | } |
108 | 85571bc7 | bellard | |
109 | 1d14ffa9 | bellard | static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn) |
110 | 85571bc7 | bellard | { |
111 | 1d14ffa9 | bellard | if (sdl_unlock (s, forfn)) {
|
112 | 85571bc7 | bellard | return -1; |
113 | 1d14ffa9 | bellard | } |
114 | 85571bc7 | bellard | |
115 | 1d14ffa9 | bellard | return sdl_post (s, forfn);
|
116 | 85571bc7 | bellard | } |
117 | 85571bc7 | bellard | |
118 | 6c557ab9 | Serge Ziryukin | static int aud_to_sdlfmt (audfmt_e fmt) |
119 | 85571bc7 | bellard | { |
120 | 85571bc7 | bellard | switch (fmt) {
|
121 | 1d14ffa9 | bellard | case AUD_FMT_S8:
|
122 | 1d14ffa9 | bellard | return AUDIO_S8;
|
123 | 1d14ffa9 | bellard | |
124 | 1d14ffa9 | bellard | case AUD_FMT_U8:
|
125 | 1d14ffa9 | bellard | return AUDIO_U8;
|
126 | 1d14ffa9 | bellard | |
127 | 1d14ffa9 | bellard | case AUD_FMT_S16:
|
128 | 1d14ffa9 | bellard | return AUDIO_S16LSB;
|
129 | 1d14ffa9 | bellard | |
130 | 1d14ffa9 | bellard | case AUD_FMT_U16:
|
131 | 1d14ffa9 | bellard | return AUDIO_U16LSB;
|
132 | 1d14ffa9 | bellard | |
133 | 85571bc7 | bellard | default:
|
134 | 1d14ffa9 | bellard | dolog ("Internal logic error: Bad audio format %d\n", fmt);
|
135 | 1d14ffa9 | bellard | #ifdef DEBUG_AUDIO
|
136 | 1d14ffa9 | bellard | abort (); |
137 | 1d14ffa9 | bellard | #endif
|
138 | 1d14ffa9 | bellard | return AUDIO_U8;
|
139 | 85571bc7 | bellard | } |
140 | 85571bc7 | bellard | } |
141 | 85571bc7 | bellard | |
142 | 1d14ffa9 | bellard | static int sdl_to_audfmt (int sdlfmt, audfmt_e *fmt, int *endianess) |
143 | 85571bc7 | bellard | { |
144 | 1d14ffa9 | bellard | switch (sdlfmt) {
|
145 | 1d14ffa9 | bellard | case AUDIO_S8:
|
146 | 1d14ffa9 | bellard | *endianess = 0;
|
147 | 1d14ffa9 | bellard | *fmt = AUD_FMT_S8; |
148 | 1d14ffa9 | bellard | break;
|
149 | 1d14ffa9 | bellard | |
150 | 1d14ffa9 | bellard | case AUDIO_U8:
|
151 | 1d14ffa9 | bellard | *endianess = 0;
|
152 | 1d14ffa9 | bellard | *fmt = AUD_FMT_U8; |
153 | 1d14ffa9 | bellard | break;
|
154 | 1d14ffa9 | bellard | |
155 | 1d14ffa9 | bellard | case AUDIO_S16LSB:
|
156 | 1d14ffa9 | bellard | *endianess = 0;
|
157 | 1d14ffa9 | bellard | *fmt = AUD_FMT_S16; |
158 | 1d14ffa9 | bellard | break;
|
159 | 1d14ffa9 | bellard | |
160 | 1d14ffa9 | bellard | case AUDIO_U16LSB:
|
161 | 1d14ffa9 | bellard | *endianess = 0;
|
162 | 1d14ffa9 | bellard | *fmt = AUD_FMT_U16; |
163 | 1d14ffa9 | bellard | break;
|
164 | 1d14ffa9 | bellard | |
165 | 1d14ffa9 | bellard | case AUDIO_S16MSB:
|
166 | 1d14ffa9 | bellard | *endianess = 1;
|
167 | 1d14ffa9 | bellard | *fmt = AUD_FMT_S16; |
168 | 1d14ffa9 | bellard | break;
|
169 | 1d14ffa9 | bellard | |
170 | 1d14ffa9 | bellard | case AUDIO_U16MSB:
|
171 | 1d14ffa9 | bellard | *endianess = 1;
|
172 | 1d14ffa9 | bellard | *fmt = AUD_FMT_U16; |
173 | 1d14ffa9 | bellard | break;
|
174 | 1d14ffa9 | bellard | |
175 | 85571bc7 | bellard | default:
|
176 | 1d14ffa9 | bellard | dolog ("Unrecognized SDL audio format %d\n", sdlfmt);
|
177 | 1d14ffa9 | bellard | return -1; |
178 | 85571bc7 | bellard | } |
179 | 1d14ffa9 | bellard | |
180 | 1d14ffa9 | bellard | return 0; |
181 | 85571bc7 | bellard | } |
182 | 85571bc7 | bellard | |
183 | 85571bc7 | bellard | static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt) |
184 | 85571bc7 | bellard | { |
185 | 85571bc7 | bellard | int status;
|
186 | e784ba70 | ths | #ifndef _WIN32
|
187 | d087bb3e | malc | int err;
|
188 | e784ba70 | ths | sigset_t new, old; |
189 | e784ba70 | ths | |
190 | e784ba70 | ths | /* Make sure potential threads created by SDL don't hog signals. */
|
191 | d087bb3e | malc | err = sigfillset (&new); |
192 | d087bb3e | malc | if (err) {
|
193 | d087bb3e | malc | dolog ("sdl_open: sigfillset failed: %s\n", strerror (errno));
|
194 | 60592edd | malc | return -1; |
195 | d087bb3e | malc | } |
196 | d087bb3e | malc | err = pthread_sigmask (SIG_BLOCK, &new, &old); |
197 | d087bb3e | malc | if (err) {
|
198 | d087bb3e | malc | dolog ("sdl_open: pthread_sigmask failed: %s\n", strerror (err));
|
199 | d087bb3e | malc | return -1; |
200 | d087bb3e | malc | } |
201 | e784ba70 | ths | #endif
|
202 | 85571bc7 | bellard | |
203 | 85571bc7 | bellard | status = SDL_OpenAudio (req, obt); |
204 | 85571bc7 | bellard | if (status) {
|
205 | 1d14ffa9 | bellard | sdl_logerr ("SDL_OpenAudio failed\n");
|
206 | 85571bc7 | bellard | } |
207 | e784ba70 | ths | |
208 | e784ba70 | ths | #ifndef _WIN32
|
209 | d087bb3e | malc | err = pthread_sigmask (SIG_SETMASK, &old, NULL);
|
210 | d087bb3e | malc | if (err) {
|
211 | d087bb3e | malc | dolog ("sdl_open: pthread_sigmask (restore) failed: %s\n",
|
212 | d087bb3e | malc | strerror (errno)); |
213 | d087bb3e | malc | /* We have failed to restore original signal mask, all bets are off,
|
214 | d087bb3e | malc | so exit the process */
|
215 | d087bb3e | malc | exit (EXIT_FAILURE); |
216 | d087bb3e | malc | } |
217 | e784ba70 | ths | #endif
|
218 | 85571bc7 | bellard | return status;
|
219 | 85571bc7 | bellard | } |
220 | 85571bc7 | bellard | |
221 | 85571bc7 | bellard | static void sdl_close (SDLAudioState *s) |
222 | 85571bc7 | bellard | { |
223 | 85571bc7 | bellard | if (s->initialized) {
|
224 | 1d14ffa9 | bellard | sdl_lock (s, "sdl_close");
|
225 | 85571bc7 | bellard | s->exit = 1;
|
226 | 1d14ffa9 | bellard | sdl_unlock_and_post (s, "sdl_close");
|
227 | 85571bc7 | bellard | SDL_PauseAudio (1);
|
228 | 85571bc7 | bellard | SDL_CloseAudio (); |
229 | 85571bc7 | bellard | s->initialized = 0;
|
230 | 85571bc7 | bellard | } |
231 | 85571bc7 | bellard | } |
232 | 85571bc7 | bellard | |
233 | 85571bc7 | bellard | static void sdl_callback (void *opaque, Uint8 *buf, int len) |
234 | 85571bc7 | bellard | { |
235 | 1d14ffa9 | bellard | SDLVoiceOut *sdl = opaque; |
236 | 85571bc7 | bellard | SDLAudioState *s = &glob_sdl; |
237 | 1d14ffa9 | bellard | HWVoiceOut *hw = &sdl->hw; |
238 | 1d14ffa9 | bellard | int samples = len >> hw->info.shift;
|
239 | 85571bc7 | bellard | |
240 | 85571bc7 | bellard | if (s->exit) {
|
241 | 85571bc7 | bellard | return;
|
242 | 85571bc7 | bellard | } |
243 | 85571bc7 | bellard | |
244 | 85571bc7 | bellard | while (samples) {
|
245 | 1d14ffa9 | bellard | int to_mix, decr;
|
246 | 85571bc7 | bellard | |
247 | ff541499 | malc | /* dolog ("in callback samples=%d\n", samples); */
|
248 | ff541499 | malc | sdl_wait (s, "sdl_callback");
|
249 | ff541499 | malc | if (s->exit) {
|
250 | ff541499 | malc | return;
|
251 | ff541499 | malc | } |
252 | ff541499 | malc | |
253 | ff541499 | malc | if (sdl_lock (s, "sdl_callback")) { |
254 | ff541499 | malc | return;
|
255 | ff541499 | malc | } |
256 | ff541499 | malc | |
257 | ff541499 | malc | if (audio_bug (AUDIO_FUNC, sdl->live < 0 || sdl->live > hw->samples)) { |
258 | ff541499 | malc | dolog ("sdl->live=%d hw->samples=%d\n",
|
259 | ff541499 | malc | sdl->live, hw->samples); |
260 | ff541499 | malc | return;
|
261 | ff541499 | malc | } |
262 | ff541499 | malc | |
263 | ff541499 | malc | if (!sdl->live) {
|
264 | ff541499 | malc | goto again;
|
265 | 1d14ffa9 | bellard | } |
266 | 85571bc7 | bellard | |
267 | ff541499 | malc | /* dolog ("in callback live=%d\n", live); */
|
268 | ff541499 | malc | to_mix = audio_MIN (samples, sdl->live); |
269 | ff541499 | malc | decr = to_mix; |
270 | ff541499 | malc | while (to_mix) {
|
271 | ff541499 | malc | int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
|
272 | ff541499 | malc | struct st_sample *src = hw->mix_buf + hw->rpos;
|
273 | ff541499 | malc | |
274 | ff541499 | malc | /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
|
275 | ff541499 | malc | hw->clip (buf, src, chunk); |
276 | ff541499 | malc | sdl->rpos = (sdl->rpos + chunk) % hw->samples; |
277 | ff541499 | malc | to_mix -= chunk; |
278 | ff541499 | malc | buf += chunk << hw->info.shift; |
279 | ff541499 | malc | } |
280 | 85571bc7 | bellard | samples -= decr; |
281 | ff541499 | malc | sdl->live -= decr; |
282 | 1d14ffa9 | bellard | sdl->decr += decr; |
283 | 85571bc7 | bellard | |
284 | ff541499 | malc | again:
|
285 | ff541499 | malc | if (sdl_unlock (s, "sdl_callback")) { |
286 | ff541499 | malc | return;
|
287 | ff541499 | malc | } |
288 | 85571bc7 | bellard | } |
289 | ff541499 | malc | /* dolog ("done len=%d\n", len); */
|
290 | 85571bc7 | bellard | } |
291 | 85571bc7 | bellard | |
292 | 1d14ffa9 | bellard | static int sdl_write_out (SWVoiceOut *sw, void *buf, int len) |
293 | 85571bc7 | bellard | { |
294 | 1d14ffa9 | bellard | return audio_pcm_sw_write (sw, buf, len);
|
295 | 1d14ffa9 | bellard | } |
296 | 1d14ffa9 | bellard | |
297 | bdff253c | malc | static int sdl_run_out (HWVoiceOut *hw, int live) |
298 | 1d14ffa9 | bellard | { |
299 | bdff253c | malc | int decr;
|
300 | 1d14ffa9 | bellard | SDLVoiceOut *sdl = (SDLVoiceOut *) hw; |
301 | 1d14ffa9 | bellard | SDLAudioState *s = &glob_sdl; |
302 | 1d14ffa9 | bellard | |
303 | 3fd7f635 | malc | if (sdl_lock (s, "sdl_run_out")) { |
304 | 1d14ffa9 | bellard | return 0; |
305 | 1d14ffa9 | bellard | } |
306 | 1d14ffa9 | bellard | |
307 | ff541499 | malc | if (sdl->decr > live) {
|
308 | ff541499 | malc | ldebug ("sdl->decr %d live %d sdl->live %d\n",
|
309 | ff541499 | malc | sdl->decr, |
310 | ff541499 | malc | live, |
311 | ff541499 | malc | sdl->live); |
312 | ff541499 | malc | } |
313 | ff541499 | malc | |
314 | ff541499 | malc | decr = audio_MIN (sdl->decr, live); |
315 | ff541499 | malc | sdl->decr -= decr; |
316 | ff541499 | malc | |
317 | ff541499 | malc | sdl->live = live - decr; |
318 | ff541499 | malc | hw->rpos = sdl->rpos; |
319 | 1d14ffa9 | bellard | |
320 | 1d14ffa9 | bellard | if (sdl->live > 0) { |
321 | 3fd7f635 | malc | sdl_unlock_and_post (s, "sdl_run_out");
|
322 | 1d14ffa9 | bellard | } |
323 | 1d14ffa9 | bellard | else {
|
324 | 3fd7f635 | malc | sdl_unlock (s, "sdl_run_out");
|
325 | 1d14ffa9 | bellard | } |
326 | 1d14ffa9 | bellard | return decr;
|
327 | 1d14ffa9 | bellard | } |
328 | 1d14ffa9 | bellard | |
329 | 1d14ffa9 | bellard | static void sdl_fini_out (HWVoiceOut *hw) |
330 | 1d14ffa9 | bellard | { |
331 | 1d14ffa9 | bellard | (void) hw;
|
332 | 1d14ffa9 | bellard | |
333 | 85571bc7 | bellard | sdl_close (&glob_sdl); |
334 | 85571bc7 | bellard | } |
335 | 85571bc7 | bellard | |
336 | 1ea879e5 | malc | static int sdl_init_out (HWVoiceOut *hw, struct audsettings *as) |
337 | 85571bc7 | bellard | { |
338 | 1d14ffa9 | bellard | SDLVoiceOut *sdl = (SDLVoiceOut *) hw; |
339 | 85571bc7 | bellard | SDLAudioState *s = &glob_sdl; |
340 | 85571bc7 | bellard | SDL_AudioSpec req, obt; |
341 | 1d14ffa9 | bellard | int endianess;
|
342 | 1d14ffa9 | bellard | int err;
|
343 | 1d14ffa9 | bellard | audfmt_e effective_fmt; |
344 | 1ea879e5 | malc | struct audsettings obt_as;
|
345 | 85571bc7 | bellard | |
346 | c0fe3827 | bellard | req.freq = as->freq; |
347 | 6c557ab9 | Serge Ziryukin | req.format = aud_to_sdlfmt (as->fmt); |
348 | c0fe3827 | bellard | req.channels = as->nchannels; |
349 | 85571bc7 | bellard | req.samples = conf.nb_samples; |
350 | 85571bc7 | bellard | req.callback = sdl_callback; |
351 | 85571bc7 | bellard | req.userdata = sdl; |
352 | 85571bc7 | bellard | |
353 | 1d14ffa9 | bellard | if (sdl_open (&req, &obt)) {
|
354 | 1d14ffa9 | bellard | return -1; |
355 | 1d14ffa9 | bellard | } |
356 | 1d14ffa9 | bellard | |
357 | 1d14ffa9 | bellard | err = sdl_to_audfmt (obt.format, &effective_fmt, &endianess); |
358 | 1d14ffa9 | bellard | if (err) {
|
359 | 1d14ffa9 | bellard | sdl_close (s); |
360 | 85571bc7 | bellard | return -1; |
361 | 1d14ffa9 | bellard | } |
362 | 85571bc7 | bellard | |
363 | c0fe3827 | bellard | obt_as.freq = obt.freq; |
364 | c0fe3827 | bellard | obt_as.nchannels = obt.channels; |
365 | c0fe3827 | bellard | obt_as.fmt = effective_fmt; |
366 | d929eba5 | bellard | obt_as.endianness = endianess; |
367 | c0fe3827 | bellard | |
368 | d929eba5 | bellard | audio_pcm_init_info (&hw->info, &obt_as); |
369 | c0fe3827 | bellard | hw->samples = obt.samples; |
370 | 85571bc7 | bellard | |
371 | 85571bc7 | bellard | s->initialized = 1;
|
372 | 85571bc7 | bellard | s->exit = 0;
|
373 | 85571bc7 | bellard | SDL_PauseAudio (0);
|
374 | 85571bc7 | bellard | return 0; |
375 | 85571bc7 | bellard | } |
376 | 85571bc7 | bellard | |
377 | 1d14ffa9 | bellard | static int sdl_ctl_out (HWVoiceOut *hw, int cmd, ...) |
378 | 85571bc7 | bellard | { |
379 | 85571bc7 | bellard | (void) hw;
|
380 | 85571bc7 | bellard | |
381 | 85571bc7 | bellard | switch (cmd) {
|
382 | 85571bc7 | bellard | case VOICE_ENABLE:
|
383 | 85571bc7 | bellard | SDL_PauseAudio (0);
|
384 | 85571bc7 | bellard | break;
|
385 | 85571bc7 | bellard | |
386 | 85571bc7 | bellard | case VOICE_DISABLE:
|
387 | 85571bc7 | bellard | SDL_PauseAudio (1);
|
388 | 85571bc7 | bellard | break;
|
389 | 85571bc7 | bellard | } |
390 | 85571bc7 | bellard | return 0; |
391 | 85571bc7 | bellard | } |
392 | 85571bc7 | bellard | |
393 | 85571bc7 | bellard | static void *sdl_audio_init (void) |
394 | 85571bc7 | bellard | { |
395 | 85571bc7 | bellard | SDLAudioState *s = &glob_sdl; |
396 | 85571bc7 | bellard | |
397 | 85571bc7 | bellard | if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
|
398 | 1d14ffa9 | bellard | sdl_logerr ("SDL failed to initialize audio subsystem\n");
|
399 | 85571bc7 | bellard | return NULL; |
400 | 85571bc7 | bellard | } |
401 | 85571bc7 | bellard | |
402 | 85571bc7 | bellard | s->mutex = SDL_CreateMutex (); |
403 | 85571bc7 | bellard | if (!s->mutex) {
|
404 | 1d14ffa9 | bellard | sdl_logerr ("Failed to create SDL mutex\n");
|
405 | 85571bc7 | bellard | SDL_QuitSubSystem (SDL_INIT_AUDIO); |
406 | 85571bc7 | bellard | return NULL; |
407 | 85571bc7 | bellard | } |
408 | 85571bc7 | bellard | |
409 | 85571bc7 | bellard | s->sem = SDL_CreateSemaphore (0);
|
410 | 85571bc7 | bellard | if (!s->sem) {
|
411 | 1d14ffa9 | bellard | sdl_logerr ("Failed to create SDL semaphore\n");
|
412 | 85571bc7 | bellard | SDL_DestroyMutex (s->mutex); |
413 | 85571bc7 | bellard | SDL_QuitSubSystem (SDL_INIT_AUDIO); |
414 | 85571bc7 | bellard | return NULL; |
415 | 85571bc7 | bellard | } |
416 | 85571bc7 | bellard | |
417 | 85571bc7 | bellard | return s;
|
418 | 85571bc7 | bellard | } |
419 | 85571bc7 | bellard | |
420 | 85571bc7 | bellard | static void sdl_audio_fini (void *opaque) |
421 | 85571bc7 | bellard | { |
422 | 85571bc7 | bellard | SDLAudioState *s = opaque; |
423 | 85571bc7 | bellard | sdl_close (s); |
424 | 85571bc7 | bellard | SDL_DestroySemaphore (s->sem); |
425 | 85571bc7 | bellard | SDL_DestroyMutex (s->mutex); |
426 | 85571bc7 | bellard | SDL_QuitSubSystem (SDL_INIT_AUDIO); |
427 | 85571bc7 | bellard | } |
428 | 85571bc7 | bellard | |
429 | 1d14ffa9 | bellard | static struct audio_option sdl_options[] = { |
430 | 98f9f48c | malc | { |
431 | 98f9f48c | malc | .name = "SAMPLES",
|
432 | 98f9f48c | malc | .tag = AUD_OPT_INT, |
433 | 98f9f48c | malc | .valp = &conf.nb_samples, |
434 | 98f9f48c | malc | .descr = "Size of SDL buffer in samples"
|
435 | 98f9f48c | malc | }, |
436 | 2700efa3 | Juan Quintela | { /* End of list */ }
|
437 | 1d14ffa9 | bellard | }; |
438 | 1d14ffa9 | bellard | |
439 | 35f4b58c | blueswir1 | static struct audio_pcm_ops sdl_pcm_ops = { |
440 | 1dd3e4d1 | Juan Quintela | .init_out = sdl_init_out, |
441 | 1dd3e4d1 | Juan Quintela | .fini_out = sdl_fini_out, |
442 | 1dd3e4d1 | Juan Quintela | .run_out = sdl_run_out, |
443 | 1dd3e4d1 | Juan Quintela | .write = sdl_write_out, |
444 | 1dd3e4d1 | Juan Quintela | .ctl_out = sdl_ctl_out, |
445 | 85571bc7 | bellard | }; |
446 | 85571bc7 | bellard | |
447 | 1d14ffa9 | bellard | struct audio_driver sdl_audio_driver = {
|
448 | bee37f32 | Juan Quintela | .name = "sdl",
|
449 | bee37f32 | Juan Quintela | .descr = "SDL http://www.libsdl.org",
|
450 | bee37f32 | Juan Quintela | .options = sdl_options, |
451 | bee37f32 | Juan Quintela | .init = sdl_audio_init, |
452 | bee37f32 | Juan Quintela | .fini = sdl_audio_fini, |
453 | bee37f32 | Juan Quintela | .pcm_ops = &sdl_pcm_ops, |
454 | bee37f32 | Juan Quintela | .can_be_default = 1,
|
455 | bee37f32 | Juan Quintela | .max_voices_out = 1,
|
456 | bee37f32 | Juan Quintela | .max_voices_in = 0,
|
457 | bee37f32 | Juan Quintela | .voice_size_out = sizeof (SDLVoiceOut),
|
458 | bee37f32 | Juan Quintela | .voice_size_in = 0
|
459 | 85571bc7 | bellard | }; |