root / audio / sdlaudio.c @ 298e01b6
History | View | Annotate | Download (10.1 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 | e784ba70 | ths | #endif
|
33 | e784ba70 | ths | #include <signal.h> |
34 | e784ba70 | ths | #endif
|
35 | e784ba70 | ths | |
36 | 1d14ffa9 | bellard | #define AUDIO_CAP "sdl" |
37 | 1d14ffa9 | bellard | #include "audio_int.h" |
38 | 85571bc7 | bellard | |
39 | 1d14ffa9 | bellard | typedef struct SDLVoiceOut { |
40 | 1d14ffa9 | bellard | HWVoiceOut hw; |
41 | 1d14ffa9 | bellard | int live;
|
42 | 1d14ffa9 | bellard | int rpos;
|
43 | 1d14ffa9 | bellard | int decr;
|
44 | 1d14ffa9 | bellard | } SDLVoiceOut; |
45 | 85571bc7 | bellard | |
46 | 85571bc7 | bellard | static struct { |
47 | 85571bc7 | bellard | int nb_samples;
|
48 | 85571bc7 | bellard | } conf = { |
49 | 85571bc7 | bellard | 1024
|
50 | 85571bc7 | bellard | }; |
51 | 85571bc7 | bellard | |
52 | 85571bc7 | bellard | struct SDLAudioState {
|
53 | 85571bc7 | bellard | int exit;
|
54 | 85571bc7 | bellard | SDL_mutex *mutex; |
55 | 85571bc7 | bellard | SDL_sem *sem; |
56 | 85571bc7 | bellard | int initialized;
|
57 | 85571bc7 | bellard | } glob_sdl; |
58 | 85571bc7 | bellard | typedef struct SDLAudioState SDLAudioState; |
59 | 85571bc7 | bellard | |
60 | 1d14ffa9 | bellard | static void GCC_FMT_ATTR (1, 2) sdl_logerr (const char *fmt, ...) |
61 | 85571bc7 | bellard | { |
62 | 1d14ffa9 | bellard | va_list ap; |
63 | 1d14ffa9 | bellard | |
64 | 1d14ffa9 | bellard | va_start (ap, fmt); |
65 | 1d14ffa9 | bellard | AUD_vlog (AUDIO_CAP, fmt, ap); |
66 | 1d14ffa9 | bellard | va_end (ap); |
67 | 1d14ffa9 | bellard | |
68 | 1d14ffa9 | bellard | AUD_log (AUDIO_CAP, "Reason: %s\n", SDL_GetError ());
|
69 | 85571bc7 | bellard | } |
70 | 85571bc7 | bellard | |
71 | 1d14ffa9 | bellard | static int sdl_lock (SDLAudioState *s, const char *forfn) |
72 | 85571bc7 | bellard | { |
73 | 85571bc7 | bellard | if (SDL_LockMutex (s->mutex)) {
|
74 | 1d14ffa9 | bellard | sdl_logerr ("SDL_LockMutex for %s failed\n", forfn);
|
75 | 85571bc7 | bellard | return -1; |
76 | 85571bc7 | bellard | } |
77 | 85571bc7 | bellard | return 0; |
78 | 85571bc7 | bellard | } |
79 | 85571bc7 | bellard | |
80 | 1d14ffa9 | bellard | static int sdl_unlock (SDLAudioState *s, const char *forfn) |
81 | 85571bc7 | bellard | { |
82 | 85571bc7 | bellard | if (SDL_UnlockMutex (s->mutex)) {
|
83 | 1d14ffa9 | bellard | sdl_logerr ("SDL_UnlockMutex for %s failed\n", forfn);
|
84 | 85571bc7 | bellard | return -1; |
85 | 85571bc7 | bellard | } |
86 | 85571bc7 | bellard | return 0; |
87 | 85571bc7 | bellard | } |
88 | 85571bc7 | bellard | |
89 | 1d14ffa9 | bellard | static int sdl_post (SDLAudioState *s, const char *forfn) |
90 | 85571bc7 | bellard | { |
91 | 85571bc7 | bellard | if (SDL_SemPost (s->sem)) {
|
92 | 1d14ffa9 | bellard | sdl_logerr ("SDL_SemPost for %s failed\n", forfn);
|
93 | 85571bc7 | bellard | return -1; |
94 | 85571bc7 | bellard | } |
95 | 85571bc7 | bellard | return 0; |
96 | 85571bc7 | bellard | } |
97 | 85571bc7 | bellard | |
98 | 1d14ffa9 | bellard | static int sdl_wait (SDLAudioState *s, const char *forfn) |
99 | 85571bc7 | bellard | { |
100 | 85571bc7 | bellard | if (SDL_SemWait (s->sem)) {
|
101 | 1d14ffa9 | bellard | sdl_logerr ("SDL_SemWait for %s failed\n", forfn);
|
102 | 85571bc7 | bellard | return -1; |
103 | 85571bc7 | bellard | } |
104 | 85571bc7 | bellard | return 0; |
105 | 85571bc7 | bellard | } |
106 | 85571bc7 | bellard | |
107 | 1d14ffa9 | bellard | static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn) |
108 | 85571bc7 | bellard | { |
109 | 1d14ffa9 | bellard | if (sdl_unlock (s, forfn)) {
|
110 | 85571bc7 | bellard | return -1; |
111 | 1d14ffa9 | bellard | } |
112 | 85571bc7 | bellard | |
113 | 1d14ffa9 | bellard | return sdl_post (s, forfn);
|
114 | 85571bc7 | bellard | } |
115 | 85571bc7 | bellard | |
116 | 1d14ffa9 | bellard | static int aud_to_sdlfmt (audfmt_e fmt, int *shift) |
117 | 85571bc7 | bellard | { |
118 | 85571bc7 | bellard | switch (fmt) {
|
119 | 1d14ffa9 | bellard | case AUD_FMT_S8:
|
120 | 1d14ffa9 | bellard | *shift = 0;
|
121 | 1d14ffa9 | bellard | return AUDIO_S8;
|
122 | 1d14ffa9 | bellard | |
123 | 1d14ffa9 | bellard | case AUD_FMT_U8:
|
124 | 1d14ffa9 | bellard | *shift = 0;
|
125 | 1d14ffa9 | bellard | return AUDIO_U8;
|
126 | 1d14ffa9 | bellard | |
127 | 1d14ffa9 | bellard | case AUD_FMT_S16:
|
128 | 1d14ffa9 | bellard | *shift = 1;
|
129 | 1d14ffa9 | bellard | return AUDIO_S16LSB;
|
130 | 1d14ffa9 | bellard | |
131 | 1d14ffa9 | bellard | case AUD_FMT_U16:
|
132 | 1d14ffa9 | bellard | *shift = 1;
|
133 | 1d14ffa9 | bellard | return AUDIO_U16LSB;
|
134 | 1d14ffa9 | bellard | |
135 | 85571bc7 | bellard | default:
|
136 | 1d14ffa9 | bellard | dolog ("Internal logic error: Bad audio format %d\n", fmt);
|
137 | 1d14ffa9 | bellard | #ifdef DEBUG_AUDIO
|
138 | 1d14ffa9 | bellard | abort (); |
139 | 1d14ffa9 | bellard | #endif
|
140 | 1d14ffa9 | bellard | return AUDIO_U8;
|
141 | 85571bc7 | bellard | } |
142 | 85571bc7 | bellard | } |
143 | 85571bc7 | bellard | |
144 | 1d14ffa9 | bellard | static int sdl_to_audfmt (int sdlfmt, audfmt_e *fmt, int *endianess) |
145 | 85571bc7 | bellard | { |
146 | 1d14ffa9 | bellard | switch (sdlfmt) {
|
147 | 1d14ffa9 | bellard | case AUDIO_S8:
|
148 | 1d14ffa9 | bellard | *endianess = 0;
|
149 | 1d14ffa9 | bellard | *fmt = AUD_FMT_S8; |
150 | 1d14ffa9 | bellard | break;
|
151 | 1d14ffa9 | bellard | |
152 | 1d14ffa9 | bellard | case AUDIO_U8:
|
153 | 1d14ffa9 | bellard | *endianess = 0;
|
154 | 1d14ffa9 | bellard | *fmt = AUD_FMT_U8; |
155 | 1d14ffa9 | bellard | break;
|
156 | 1d14ffa9 | bellard | |
157 | 1d14ffa9 | bellard | case AUDIO_S16LSB:
|
158 | 1d14ffa9 | bellard | *endianess = 0;
|
159 | 1d14ffa9 | bellard | *fmt = AUD_FMT_S16; |
160 | 1d14ffa9 | bellard | break;
|
161 | 1d14ffa9 | bellard | |
162 | 1d14ffa9 | bellard | case AUDIO_U16LSB:
|
163 | 1d14ffa9 | bellard | *endianess = 0;
|
164 | 1d14ffa9 | bellard | *fmt = AUD_FMT_U16; |
165 | 1d14ffa9 | bellard | break;
|
166 | 1d14ffa9 | bellard | |
167 | 1d14ffa9 | bellard | case AUDIO_S16MSB:
|
168 | 1d14ffa9 | bellard | *endianess = 1;
|
169 | 1d14ffa9 | bellard | *fmt = AUD_FMT_S16; |
170 | 1d14ffa9 | bellard | break;
|
171 | 1d14ffa9 | bellard | |
172 | 1d14ffa9 | bellard | case AUDIO_U16MSB:
|
173 | 1d14ffa9 | bellard | *endianess = 1;
|
174 | 1d14ffa9 | bellard | *fmt = AUD_FMT_U16; |
175 | 1d14ffa9 | bellard | break;
|
176 | 1d14ffa9 | bellard | |
177 | 85571bc7 | bellard | default:
|
178 | 1d14ffa9 | bellard | dolog ("Unrecognized SDL audio format %d\n", sdlfmt);
|
179 | 1d14ffa9 | bellard | return -1; |
180 | 85571bc7 | bellard | } |
181 | 1d14ffa9 | bellard | |
182 | 1d14ffa9 | bellard | return 0; |
183 | 85571bc7 | bellard | } |
184 | 85571bc7 | bellard | |
185 | 85571bc7 | bellard | static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt) |
186 | 85571bc7 | bellard | { |
187 | 85571bc7 | bellard | int status;
|
188 | e784ba70 | ths | #ifndef _WIN32
|
189 | e784ba70 | ths | sigset_t new, old; |
190 | e784ba70 | ths | |
191 | e784ba70 | ths | /* Make sure potential threads created by SDL don't hog signals. */
|
192 | e784ba70 | ths | sigfillset (&new); |
193 | e784ba70 | ths | pthread_sigmask (SIG_BLOCK, &new, &old); |
194 | e784ba70 | ths | #endif
|
195 | 85571bc7 | bellard | |
196 | 85571bc7 | bellard | status = SDL_OpenAudio (req, obt); |
197 | 85571bc7 | bellard | if (status) {
|
198 | 1d14ffa9 | bellard | sdl_logerr ("SDL_OpenAudio failed\n");
|
199 | 85571bc7 | bellard | } |
200 | e784ba70 | ths | |
201 | e784ba70 | ths | #ifndef _WIN32
|
202 | e784ba70 | ths | pthread_sigmask (SIG_SETMASK, &old, 0);
|
203 | e784ba70 | ths | #endif
|
204 | 85571bc7 | bellard | return status;
|
205 | 85571bc7 | bellard | } |
206 | 85571bc7 | bellard | |
207 | 85571bc7 | bellard | static void sdl_close (SDLAudioState *s) |
208 | 85571bc7 | bellard | { |
209 | 85571bc7 | bellard | if (s->initialized) {
|
210 | 1d14ffa9 | bellard | sdl_lock (s, "sdl_close");
|
211 | 85571bc7 | bellard | s->exit = 1;
|
212 | 1d14ffa9 | bellard | sdl_unlock_and_post (s, "sdl_close");
|
213 | 85571bc7 | bellard | SDL_PauseAudio (1);
|
214 | 85571bc7 | bellard | SDL_CloseAudio (); |
215 | 85571bc7 | bellard | s->initialized = 0;
|
216 | 85571bc7 | bellard | } |
217 | 85571bc7 | bellard | } |
218 | 85571bc7 | bellard | |
219 | 85571bc7 | bellard | static void sdl_callback (void *opaque, Uint8 *buf, int len) |
220 | 85571bc7 | bellard | { |
221 | 1d14ffa9 | bellard | SDLVoiceOut *sdl = opaque; |
222 | 85571bc7 | bellard | SDLAudioState *s = &glob_sdl; |
223 | 1d14ffa9 | bellard | HWVoiceOut *hw = &sdl->hw; |
224 | 1d14ffa9 | bellard | int samples = len >> hw->info.shift;
|
225 | 85571bc7 | bellard | |
226 | 85571bc7 | bellard | if (s->exit) {
|
227 | 85571bc7 | bellard | return;
|
228 | 85571bc7 | bellard | } |
229 | 85571bc7 | bellard | |
230 | 85571bc7 | bellard | while (samples) {
|
231 | 1d14ffa9 | bellard | int to_mix, decr;
|
232 | 85571bc7 | bellard | |
233 | 85571bc7 | bellard | /* dolog ("in callback samples=%d\n", samples); */
|
234 | 1d14ffa9 | bellard | sdl_wait (s, "sdl_callback");
|
235 | 85571bc7 | bellard | if (s->exit) {
|
236 | 85571bc7 | bellard | return;
|
237 | 85571bc7 | bellard | } |
238 | 85571bc7 | bellard | |
239 | 1d14ffa9 | bellard | if (sdl_lock (s, "sdl_callback")) { |
240 | 1d14ffa9 | bellard | return;
|
241 | 1d14ffa9 | bellard | } |
242 | 1d14ffa9 | bellard | |
243 | 1d14ffa9 | bellard | if (audio_bug (AUDIO_FUNC, sdl->live < 0 || sdl->live > hw->samples)) { |
244 | 1d14ffa9 | bellard | dolog ("sdl->live=%d hw->samples=%d\n",
|
245 | 1d14ffa9 | bellard | sdl->live, hw->samples); |
246 | 1d14ffa9 | bellard | return;
|
247 | 1d14ffa9 | bellard | } |
248 | 1d14ffa9 | bellard | |
249 | 1d14ffa9 | bellard | if (!sdl->live) {
|
250 | 85571bc7 | bellard | goto again;
|
251 | 1d14ffa9 | bellard | } |
252 | 85571bc7 | bellard | |
253 | 85571bc7 | bellard | /* dolog ("in callback live=%d\n", live); */
|
254 | 1d14ffa9 | bellard | to_mix = audio_MIN (samples, sdl->live); |
255 | 85571bc7 | bellard | decr = to_mix; |
256 | 85571bc7 | bellard | while (to_mix) {
|
257 | 85571bc7 | bellard | int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
|
258 | 85571bc7 | bellard | st_sample_t *src = hw->mix_buf + hw->rpos; |
259 | 85571bc7 | bellard | |
260 | 85571bc7 | bellard | /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
|
261 | 85571bc7 | bellard | hw->clip (buf, src, chunk); |
262 | 1d14ffa9 | bellard | sdl->rpos = (sdl->rpos + chunk) % hw->samples; |
263 | 85571bc7 | bellard | to_mix -= chunk; |
264 | 1d14ffa9 | bellard | buf += chunk << hw->info.shift; |
265 | 85571bc7 | bellard | } |
266 | 85571bc7 | bellard | samples -= decr; |
267 | 1d14ffa9 | bellard | sdl->live -= decr; |
268 | 1d14ffa9 | bellard | sdl->decr += decr; |
269 | 85571bc7 | bellard | |
270 | 85571bc7 | bellard | again:
|
271 | 1d14ffa9 | bellard | if (sdl_unlock (s, "sdl_callback")) { |
272 | 1d14ffa9 | bellard | return;
|
273 | 1d14ffa9 | bellard | } |
274 | 85571bc7 | bellard | } |
275 | 85571bc7 | bellard | /* dolog ("done len=%d\n", len); */
|
276 | 85571bc7 | bellard | } |
277 | 85571bc7 | bellard | |
278 | 1d14ffa9 | bellard | static int sdl_write_out (SWVoiceOut *sw, void *buf, int len) |
279 | 85571bc7 | bellard | { |
280 | 1d14ffa9 | bellard | return audio_pcm_sw_write (sw, buf, len);
|
281 | 1d14ffa9 | bellard | } |
282 | 1d14ffa9 | bellard | |
283 | 1d14ffa9 | bellard | static int sdl_run_out (HWVoiceOut *hw) |
284 | 1d14ffa9 | bellard | { |
285 | 1d14ffa9 | bellard | int decr, live;
|
286 | 1d14ffa9 | bellard | SDLVoiceOut *sdl = (SDLVoiceOut *) hw; |
287 | 1d14ffa9 | bellard | SDLAudioState *s = &glob_sdl; |
288 | 1d14ffa9 | bellard | |
289 | 1d14ffa9 | bellard | if (sdl_lock (s, "sdl_callback")) { |
290 | 1d14ffa9 | bellard | return 0; |
291 | 1d14ffa9 | bellard | } |
292 | 1d14ffa9 | bellard | |
293 | 1d14ffa9 | bellard | live = audio_pcm_hw_get_live_out (hw); |
294 | 1d14ffa9 | bellard | |
295 | 1d14ffa9 | bellard | if (sdl->decr > live) {
|
296 | 1d14ffa9 | bellard | ldebug ("sdl->decr %d live %d sdl->live %d\n",
|
297 | 1d14ffa9 | bellard | sdl->decr, |
298 | 1d14ffa9 | bellard | live, |
299 | 1d14ffa9 | bellard | sdl->live); |
300 | 1d14ffa9 | bellard | } |
301 | 1d14ffa9 | bellard | |
302 | 1d14ffa9 | bellard | decr = audio_MIN (sdl->decr, live); |
303 | 1d14ffa9 | bellard | sdl->decr -= decr; |
304 | 1d14ffa9 | bellard | |
305 | 1d14ffa9 | bellard | sdl->live = live - decr; |
306 | 1d14ffa9 | bellard | hw->rpos = sdl->rpos; |
307 | 1d14ffa9 | bellard | |
308 | 1d14ffa9 | bellard | if (sdl->live > 0) { |
309 | 1d14ffa9 | bellard | sdl_unlock_and_post (s, "sdl_callback");
|
310 | 1d14ffa9 | bellard | } |
311 | 1d14ffa9 | bellard | else {
|
312 | 1d14ffa9 | bellard | sdl_unlock (s, "sdl_callback");
|
313 | 1d14ffa9 | bellard | } |
314 | 1d14ffa9 | bellard | return decr;
|
315 | 1d14ffa9 | bellard | } |
316 | 1d14ffa9 | bellard | |
317 | 1d14ffa9 | bellard | static void sdl_fini_out (HWVoiceOut *hw) |
318 | 1d14ffa9 | bellard | { |
319 | 1d14ffa9 | bellard | (void) hw;
|
320 | 1d14ffa9 | bellard | |
321 | 85571bc7 | bellard | sdl_close (&glob_sdl); |
322 | 85571bc7 | bellard | } |
323 | 85571bc7 | bellard | |
324 | c0fe3827 | bellard | static int sdl_init_out (HWVoiceOut *hw, audsettings_t *as) |
325 | 85571bc7 | bellard | { |
326 | 1d14ffa9 | bellard | SDLVoiceOut *sdl = (SDLVoiceOut *) hw; |
327 | 85571bc7 | bellard | SDLAudioState *s = &glob_sdl; |
328 | 85571bc7 | bellard | SDL_AudioSpec req, obt; |
329 | 85571bc7 | bellard | int shift;
|
330 | 1d14ffa9 | bellard | int endianess;
|
331 | 1d14ffa9 | bellard | int err;
|
332 | 1d14ffa9 | bellard | audfmt_e effective_fmt; |
333 | c0fe3827 | bellard | audsettings_t obt_as; |
334 | 85571bc7 | bellard | |
335 | c0fe3827 | bellard | shift <<= as->nchannels == 2;
|
336 | 85571bc7 | bellard | |
337 | c0fe3827 | bellard | req.freq = as->freq; |
338 | c0fe3827 | bellard | req.format = aud_to_sdlfmt (as->fmt, &shift); |
339 | c0fe3827 | bellard | req.channels = as->nchannels; |
340 | 85571bc7 | bellard | req.samples = conf.nb_samples; |
341 | 85571bc7 | bellard | req.callback = sdl_callback; |
342 | 85571bc7 | bellard | req.userdata = sdl; |
343 | 85571bc7 | bellard | |
344 | 1d14ffa9 | bellard | if (sdl_open (&req, &obt)) {
|
345 | 1d14ffa9 | bellard | return -1; |
346 | 1d14ffa9 | bellard | } |
347 | 1d14ffa9 | bellard | |
348 | 1d14ffa9 | bellard | err = sdl_to_audfmt (obt.format, &effective_fmt, &endianess); |
349 | 1d14ffa9 | bellard | if (err) {
|
350 | 1d14ffa9 | bellard | sdl_close (s); |
351 | 85571bc7 | bellard | return -1; |
352 | 1d14ffa9 | bellard | } |
353 | 85571bc7 | bellard | |
354 | c0fe3827 | bellard | obt_as.freq = obt.freq; |
355 | c0fe3827 | bellard | obt_as.nchannels = obt.channels; |
356 | c0fe3827 | bellard | obt_as.fmt = effective_fmt; |
357 | d929eba5 | bellard | obt_as.endianness = endianess; |
358 | c0fe3827 | bellard | |
359 | d929eba5 | bellard | audio_pcm_init_info (&hw->info, &obt_as); |
360 | c0fe3827 | bellard | hw->samples = obt.samples; |
361 | 85571bc7 | bellard | |
362 | 85571bc7 | bellard | s->initialized = 1;
|
363 | 85571bc7 | bellard | s->exit = 0;
|
364 | 85571bc7 | bellard | SDL_PauseAudio (0);
|
365 | 85571bc7 | bellard | return 0; |
366 | 85571bc7 | bellard | } |
367 | 85571bc7 | bellard | |
368 | 1d14ffa9 | bellard | static int sdl_ctl_out (HWVoiceOut *hw, int cmd, ...) |
369 | 85571bc7 | bellard | { |
370 | 85571bc7 | bellard | (void) hw;
|
371 | 85571bc7 | bellard | |
372 | 85571bc7 | bellard | switch (cmd) {
|
373 | 85571bc7 | bellard | case VOICE_ENABLE:
|
374 | 85571bc7 | bellard | SDL_PauseAudio (0);
|
375 | 85571bc7 | bellard | break;
|
376 | 85571bc7 | bellard | |
377 | 85571bc7 | bellard | case VOICE_DISABLE:
|
378 | 85571bc7 | bellard | SDL_PauseAudio (1);
|
379 | 85571bc7 | bellard | break;
|
380 | 85571bc7 | bellard | } |
381 | 85571bc7 | bellard | return 0; |
382 | 85571bc7 | bellard | } |
383 | 85571bc7 | bellard | |
384 | 85571bc7 | bellard | static void *sdl_audio_init (void) |
385 | 85571bc7 | bellard | { |
386 | 85571bc7 | bellard | SDLAudioState *s = &glob_sdl; |
387 | 85571bc7 | bellard | |
388 | 85571bc7 | bellard | if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
|
389 | 1d14ffa9 | bellard | sdl_logerr ("SDL failed to initialize audio subsystem\n");
|
390 | 85571bc7 | bellard | return NULL; |
391 | 85571bc7 | bellard | } |
392 | 85571bc7 | bellard | |
393 | 85571bc7 | bellard | s->mutex = SDL_CreateMutex (); |
394 | 85571bc7 | bellard | if (!s->mutex) {
|
395 | 1d14ffa9 | bellard | sdl_logerr ("Failed to create SDL mutex\n");
|
396 | 85571bc7 | bellard | SDL_QuitSubSystem (SDL_INIT_AUDIO); |
397 | 85571bc7 | bellard | return NULL; |
398 | 85571bc7 | bellard | } |
399 | 85571bc7 | bellard | |
400 | 85571bc7 | bellard | s->sem = SDL_CreateSemaphore (0);
|
401 | 85571bc7 | bellard | if (!s->sem) {
|
402 | 1d14ffa9 | bellard | sdl_logerr ("Failed to create SDL semaphore\n");
|
403 | 85571bc7 | bellard | SDL_DestroyMutex (s->mutex); |
404 | 85571bc7 | bellard | SDL_QuitSubSystem (SDL_INIT_AUDIO); |
405 | 85571bc7 | bellard | return NULL; |
406 | 85571bc7 | bellard | } |
407 | 85571bc7 | bellard | |
408 | 85571bc7 | bellard | return s;
|
409 | 85571bc7 | bellard | } |
410 | 85571bc7 | bellard | |
411 | 85571bc7 | bellard | static void sdl_audio_fini (void *opaque) |
412 | 85571bc7 | bellard | { |
413 | 85571bc7 | bellard | SDLAudioState *s = opaque; |
414 | 85571bc7 | bellard | sdl_close (s); |
415 | 85571bc7 | bellard | SDL_DestroySemaphore (s->sem); |
416 | 85571bc7 | bellard | SDL_DestroyMutex (s->mutex); |
417 | 85571bc7 | bellard | SDL_QuitSubSystem (SDL_INIT_AUDIO); |
418 | 85571bc7 | bellard | } |
419 | 85571bc7 | bellard | |
420 | 1d14ffa9 | bellard | static struct audio_option sdl_options[] = { |
421 | 1d14ffa9 | bellard | {"SAMPLES", AUD_OPT_INT, &conf.nb_samples,
|
422 | 1d14ffa9 | bellard | "Size of SDL buffer in samples", NULL, 0}, |
423 | 1d14ffa9 | bellard | {NULL, 0, NULL, NULL, NULL, 0} |
424 | 1d14ffa9 | bellard | }; |
425 | 1d14ffa9 | bellard | |
426 | 1d14ffa9 | bellard | static struct audio_pcm_ops sdl_pcm_ops = { |
427 | 1d14ffa9 | bellard | sdl_init_out, |
428 | 1d14ffa9 | bellard | sdl_fini_out, |
429 | 1d14ffa9 | bellard | sdl_run_out, |
430 | 1d14ffa9 | bellard | sdl_write_out, |
431 | 1d14ffa9 | bellard | sdl_ctl_out, |
432 | 1d14ffa9 | bellard | |
433 | 1d14ffa9 | bellard | NULL,
|
434 | 1d14ffa9 | bellard | NULL,
|
435 | 1d14ffa9 | bellard | NULL,
|
436 | 1d14ffa9 | bellard | NULL,
|
437 | 1d14ffa9 | bellard | NULL
|
438 | 85571bc7 | bellard | }; |
439 | 85571bc7 | bellard | |
440 | 1d14ffa9 | bellard | struct audio_driver sdl_audio_driver = {
|
441 | 1d14ffa9 | bellard | INIT_FIELD (name = ) "sdl",
|
442 | 1d14ffa9 | bellard | INIT_FIELD (descr = ) "SDL http://www.libsdl.org",
|
443 | 1d14ffa9 | bellard | INIT_FIELD (options = ) sdl_options, |
444 | 1d14ffa9 | bellard | INIT_FIELD (init = ) sdl_audio_init, |
445 | 1d14ffa9 | bellard | INIT_FIELD (fini = ) sdl_audio_fini, |
446 | 1d14ffa9 | bellard | INIT_FIELD (pcm_ops = ) &sdl_pcm_ops, |
447 | 1d14ffa9 | bellard | INIT_FIELD (can_be_default = ) 1,
|
448 | 1d14ffa9 | bellard | INIT_FIELD (max_voices_out = ) 1,
|
449 | 1d14ffa9 | bellard | INIT_FIELD (max_voices_in = ) 0,
|
450 | 1d14ffa9 | bellard | INIT_FIELD (voice_size_out = ) sizeof (SDLVoiceOut),
|
451 | 1d14ffa9 | bellard | INIT_FIELD (voice_size_in = ) 0
|
452 | 85571bc7 | bellard | }; |