root / audio / sdlaudio.c @ 12381085
History | View | Annotate | Download (9.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 | 1d14ffa9 | bellard | int decr;
|
45 | 4839abe7 | malc | int pending;
|
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 | 1d14ffa9 | bellard | static int aud_to_sdlfmt (audfmt_e fmt, int *shift) |
119 | 85571bc7 | bellard | { |
120 | 85571bc7 | bellard | switch (fmt) {
|
121 | 1d14ffa9 | bellard | case AUD_FMT_S8:
|
122 | 1d14ffa9 | bellard | *shift = 0;
|
123 | 1d14ffa9 | bellard | return AUDIO_S8;
|
124 | 1d14ffa9 | bellard | |
125 | 1d14ffa9 | bellard | case AUD_FMT_U8:
|
126 | 1d14ffa9 | bellard | *shift = 0;
|
127 | 1d14ffa9 | bellard | return AUDIO_U8;
|
128 | 1d14ffa9 | bellard | |
129 | 1d14ffa9 | bellard | case AUD_FMT_S16:
|
130 | 1d14ffa9 | bellard | *shift = 1;
|
131 | 1d14ffa9 | bellard | return AUDIO_S16LSB;
|
132 | 1d14ffa9 | bellard | |
133 | 1d14ffa9 | bellard | case AUD_FMT_U16:
|
134 | 1d14ffa9 | bellard | *shift = 1;
|
135 | 1d14ffa9 | bellard | return AUDIO_U16LSB;
|
136 | 1d14ffa9 | bellard | |
137 | 85571bc7 | bellard | default:
|
138 | 1d14ffa9 | bellard | dolog ("Internal logic error: Bad audio format %d\n", fmt);
|
139 | 1d14ffa9 | bellard | #ifdef DEBUG_AUDIO
|
140 | 1d14ffa9 | bellard | abort (); |
141 | 1d14ffa9 | bellard | #endif
|
142 | 1d14ffa9 | bellard | return AUDIO_U8;
|
143 | 85571bc7 | bellard | } |
144 | 85571bc7 | bellard | } |
145 | 85571bc7 | bellard | |
146 | 1d14ffa9 | bellard | static int sdl_to_audfmt (int sdlfmt, audfmt_e *fmt, int *endianess) |
147 | 85571bc7 | bellard | { |
148 | 1d14ffa9 | bellard | switch (sdlfmt) {
|
149 | 1d14ffa9 | bellard | case AUDIO_S8:
|
150 | 1d14ffa9 | bellard | *endianess = 0;
|
151 | 1d14ffa9 | bellard | *fmt = AUD_FMT_S8; |
152 | 1d14ffa9 | bellard | break;
|
153 | 1d14ffa9 | bellard | |
154 | 1d14ffa9 | bellard | case AUDIO_U8:
|
155 | 1d14ffa9 | bellard | *endianess = 0;
|
156 | 1d14ffa9 | bellard | *fmt = AUD_FMT_U8; |
157 | 1d14ffa9 | bellard | break;
|
158 | 1d14ffa9 | bellard | |
159 | 1d14ffa9 | bellard | case AUDIO_S16LSB:
|
160 | 1d14ffa9 | bellard | *endianess = 0;
|
161 | 1d14ffa9 | bellard | *fmt = AUD_FMT_S16; |
162 | 1d14ffa9 | bellard | break;
|
163 | 1d14ffa9 | bellard | |
164 | 1d14ffa9 | bellard | case AUDIO_U16LSB:
|
165 | 1d14ffa9 | bellard | *endianess = 0;
|
166 | 1d14ffa9 | bellard | *fmt = AUD_FMT_U16; |
167 | 1d14ffa9 | bellard | break;
|
168 | 1d14ffa9 | bellard | |
169 | 1d14ffa9 | bellard | case AUDIO_S16MSB:
|
170 | 1d14ffa9 | bellard | *endianess = 1;
|
171 | 1d14ffa9 | bellard | *fmt = AUD_FMT_S16; |
172 | 1d14ffa9 | bellard | break;
|
173 | 1d14ffa9 | bellard | |
174 | 1d14ffa9 | bellard | case AUDIO_U16MSB:
|
175 | 1d14ffa9 | bellard | *endianess = 1;
|
176 | 1d14ffa9 | bellard | *fmt = AUD_FMT_U16; |
177 | 1d14ffa9 | bellard | break;
|
178 | 1d14ffa9 | bellard | |
179 | 85571bc7 | bellard | default:
|
180 | 1d14ffa9 | bellard | dolog ("Unrecognized SDL audio format %d\n", sdlfmt);
|
181 | 1d14ffa9 | bellard | return -1; |
182 | 85571bc7 | bellard | } |
183 | 1d14ffa9 | bellard | |
184 | 1d14ffa9 | bellard | return 0; |
185 | 85571bc7 | bellard | } |
186 | 85571bc7 | bellard | |
187 | 85571bc7 | bellard | static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt) |
188 | 85571bc7 | bellard | { |
189 | 85571bc7 | bellard | int status;
|
190 | e784ba70 | ths | #ifndef _WIN32
|
191 | e784ba70 | ths | sigset_t new, old; |
192 | e784ba70 | ths | |
193 | e784ba70 | ths | /* Make sure potential threads created by SDL don't hog signals. */
|
194 | e784ba70 | ths | sigfillset (&new); |
195 | e784ba70 | ths | pthread_sigmask (SIG_BLOCK, &new, &old); |
196 | e784ba70 | ths | #endif
|
197 | 85571bc7 | bellard | |
198 | 85571bc7 | bellard | status = SDL_OpenAudio (req, obt); |
199 | 85571bc7 | bellard | if (status) {
|
200 | 1d14ffa9 | bellard | sdl_logerr ("SDL_OpenAudio failed\n");
|
201 | 85571bc7 | bellard | } |
202 | e784ba70 | ths | |
203 | e784ba70 | ths | #ifndef _WIN32
|
204 | 660f11be | Blue Swirl | pthread_sigmask (SIG_SETMASK, &old, NULL);
|
205 | e784ba70 | ths | #endif
|
206 | 85571bc7 | bellard | return status;
|
207 | 85571bc7 | bellard | } |
208 | 85571bc7 | bellard | |
209 | 85571bc7 | bellard | static void sdl_close (SDLAudioState *s) |
210 | 85571bc7 | bellard | { |
211 | 85571bc7 | bellard | if (s->initialized) {
|
212 | 1d14ffa9 | bellard | sdl_lock (s, "sdl_close");
|
213 | 85571bc7 | bellard | s->exit = 1;
|
214 | 1d14ffa9 | bellard | sdl_unlock_and_post (s, "sdl_close");
|
215 | 85571bc7 | bellard | SDL_PauseAudio (1);
|
216 | 85571bc7 | bellard | SDL_CloseAudio (); |
217 | 85571bc7 | bellard | s->initialized = 0;
|
218 | 85571bc7 | bellard | } |
219 | 85571bc7 | bellard | } |
220 | 85571bc7 | bellard | |
221 | 85571bc7 | bellard | static void sdl_callback (void *opaque, Uint8 *buf, int len) |
222 | 85571bc7 | bellard | { |
223 | 1d14ffa9 | bellard | SDLVoiceOut *sdl = opaque; |
224 | 85571bc7 | bellard | SDLAudioState *s = &glob_sdl; |
225 | 1d14ffa9 | bellard | HWVoiceOut *hw = &sdl->hw; |
226 | 1d14ffa9 | bellard | int samples = len >> hw->info.shift;
|
227 | 85571bc7 | bellard | |
228 | 4839abe7 | malc | if (sdl_lock (s, "sdl_callback")) { |
229 | 4839abe7 | malc | return;
|
230 | 4839abe7 | malc | } |
231 | 4839abe7 | malc | |
232 | 85571bc7 | bellard | if (s->exit) {
|
233 | 85571bc7 | bellard | return;
|
234 | 85571bc7 | bellard | } |
235 | 85571bc7 | bellard | |
236 | 85571bc7 | bellard | while (samples) {
|
237 | 1d14ffa9 | bellard | int to_mix, decr;
|
238 | 85571bc7 | bellard | |
239 | 4839abe7 | malc | while (!sdl->pending) {
|
240 | 4839abe7 | malc | if (sdl_unlock (s, "sdl_callback")) { |
241 | 4839abe7 | malc | return;
|
242 | 4839abe7 | malc | } |
243 | 4839abe7 | malc | |
244 | 4839abe7 | malc | sdl_wait (s, "sdl_callback");
|
245 | 4839abe7 | malc | if (s->exit) {
|
246 | 4839abe7 | malc | return;
|
247 | 4839abe7 | malc | } |
248 | 4839abe7 | malc | |
249 | 4839abe7 | malc | if (sdl_lock (s, "sdl_callback")) { |
250 | 4839abe7 | malc | return;
|
251 | 4839abe7 | malc | } |
252 | 4839abe7 | malc | sdl->pending += sdl->live; |
253 | 4839abe7 | malc | sdl->live = 0;
|
254 | 1d14ffa9 | bellard | } |
255 | 85571bc7 | bellard | |
256 | 4839abe7 | malc | to_mix = audio_MIN (samples, sdl->pending); |
257 | 4839abe7 | malc | decr = audio_pcm_hw_clip_out (hw, buf, to_mix, 0);
|
258 | 4839abe7 | malc | buf += decr << hw->info.shift; |
259 | 85571bc7 | bellard | samples -= decr; |
260 | 1d14ffa9 | bellard | sdl->decr += decr; |
261 | 4839abe7 | malc | sdl->pending -= decr; |
262 | 4839abe7 | malc | } |
263 | 85571bc7 | bellard | |
264 | 4839abe7 | malc | if (sdl_unlock (s, "sdl_callback")) { |
265 | 4839abe7 | malc | return;
|
266 | 85571bc7 | bellard | } |
267 | 85571bc7 | bellard | } |
268 | 85571bc7 | bellard | |
269 | 1d14ffa9 | bellard | static int sdl_write_out (SWVoiceOut *sw, void *buf, int len) |
270 | 85571bc7 | bellard | { |
271 | 1d14ffa9 | bellard | return audio_pcm_sw_write (sw, buf, len);
|
272 | 1d14ffa9 | bellard | } |
273 | 1d14ffa9 | bellard | |
274 | bdff253c | malc | static int sdl_run_out (HWVoiceOut *hw, int live) |
275 | 1d14ffa9 | bellard | { |
276 | bdff253c | malc | int decr;
|
277 | 1d14ffa9 | bellard | SDLVoiceOut *sdl = (SDLVoiceOut *) hw; |
278 | 1d14ffa9 | bellard | SDLAudioState *s = &glob_sdl; |
279 | 1d14ffa9 | bellard | |
280 | 3fd7f635 | malc | if (sdl_lock (s, "sdl_run_out")) { |
281 | 1d14ffa9 | bellard | return 0; |
282 | 1d14ffa9 | bellard | } |
283 | 1d14ffa9 | bellard | |
284 | 4839abe7 | malc | sdl->live = live; |
285 | 4839abe7 | malc | decr = sdl->decr; |
286 | 4839abe7 | malc | sdl->decr = 0;
|
287 | 1d14ffa9 | bellard | |
288 | 1d14ffa9 | bellard | if (sdl->live > 0) { |
289 | 3fd7f635 | malc | sdl_unlock_and_post (s, "sdl_run_out");
|
290 | 1d14ffa9 | bellard | } |
291 | 1d14ffa9 | bellard | else {
|
292 | 3fd7f635 | malc | sdl_unlock (s, "sdl_run_out");
|
293 | 1d14ffa9 | bellard | } |
294 | 1d14ffa9 | bellard | return decr;
|
295 | 1d14ffa9 | bellard | } |
296 | 1d14ffa9 | bellard | |
297 | 1d14ffa9 | bellard | static void sdl_fini_out (HWVoiceOut *hw) |
298 | 1d14ffa9 | bellard | { |
299 | 1d14ffa9 | bellard | (void) hw;
|
300 | 1d14ffa9 | bellard | |
301 | 85571bc7 | bellard | sdl_close (&glob_sdl); |
302 | 85571bc7 | bellard | } |
303 | 85571bc7 | bellard | |
304 | 1ea879e5 | malc | static int sdl_init_out (HWVoiceOut *hw, struct audsettings *as) |
305 | 85571bc7 | bellard | { |
306 | 1d14ffa9 | bellard | SDLVoiceOut *sdl = (SDLVoiceOut *) hw; |
307 | 85571bc7 | bellard | SDLAudioState *s = &glob_sdl; |
308 | 85571bc7 | bellard | SDL_AudioSpec req, obt; |
309 | 85571bc7 | bellard | int shift;
|
310 | 1d14ffa9 | bellard | int endianess;
|
311 | 1d14ffa9 | bellard | int err;
|
312 | 1d14ffa9 | bellard | audfmt_e effective_fmt; |
313 | 1ea879e5 | malc | struct audsettings obt_as;
|
314 | 85571bc7 | bellard | |
315 | c0fe3827 | bellard | shift <<= as->nchannels == 2;
|
316 | 85571bc7 | bellard | |
317 | c0fe3827 | bellard | req.freq = as->freq; |
318 | c0fe3827 | bellard | req.format = aud_to_sdlfmt (as->fmt, &shift); |
319 | c0fe3827 | bellard | req.channels = as->nchannels; |
320 | 85571bc7 | bellard | req.samples = conf.nb_samples; |
321 | 85571bc7 | bellard | req.callback = sdl_callback; |
322 | 85571bc7 | bellard | req.userdata = sdl; |
323 | 85571bc7 | bellard | |
324 | 1d14ffa9 | bellard | if (sdl_open (&req, &obt)) {
|
325 | 1d14ffa9 | bellard | return -1; |
326 | 1d14ffa9 | bellard | } |
327 | 1d14ffa9 | bellard | |
328 | 1d14ffa9 | bellard | err = sdl_to_audfmt (obt.format, &effective_fmt, &endianess); |
329 | 1d14ffa9 | bellard | if (err) {
|
330 | 1d14ffa9 | bellard | sdl_close (s); |
331 | 85571bc7 | bellard | return -1; |
332 | 1d14ffa9 | bellard | } |
333 | 85571bc7 | bellard | |
334 | c0fe3827 | bellard | obt_as.freq = obt.freq; |
335 | c0fe3827 | bellard | obt_as.nchannels = obt.channels; |
336 | c0fe3827 | bellard | obt_as.fmt = effective_fmt; |
337 | d929eba5 | bellard | obt_as.endianness = endianess; |
338 | c0fe3827 | bellard | |
339 | d929eba5 | bellard | audio_pcm_init_info (&hw->info, &obt_as); |
340 | c0fe3827 | bellard | hw->samples = obt.samples; |
341 | 85571bc7 | bellard | |
342 | 85571bc7 | bellard | s->initialized = 1;
|
343 | 85571bc7 | bellard | s->exit = 0;
|
344 | 85571bc7 | bellard | SDL_PauseAudio (0);
|
345 | 85571bc7 | bellard | return 0; |
346 | 85571bc7 | bellard | } |
347 | 85571bc7 | bellard | |
348 | 1d14ffa9 | bellard | static int sdl_ctl_out (HWVoiceOut *hw, int cmd, ...) |
349 | 85571bc7 | bellard | { |
350 | 85571bc7 | bellard | (void) hw;
|
351 | 85571bc7 | bellard | |
352 | 85571bc7 | bellard | switch (cmd) {
|
353 | 85571bc7 | bellard | case VOICE_ENABLE:
|
354 | 85571bc7 | bellard | SDL_PauseAudio (0);
|
355 | 85571bc7 | bellard | break;
|
356 | 85571bc7 | bellard | |
357 | 85571bc7 | bellard | case VOICE_DISABLE:
|
358 | 85571bc7 | bellard | SDL_PauseAudio (1);
|
359 | 85571bc7 | bellard | break;
|
360 | 85571bc7 | bellard | } |
361 | 85571bc7 | bellard | return 0; |
362 | 85571bc7 | bellard | } |
363 | 85571bc7 | bellard | |
364 | 85571bc7 | bellard | static void *sdl_audio_init (void) |
365 | 85571bc7 | bellard | { |
366 | 85571bc7 | bellard | SDLAudioState *s = &glob_sdl; |
367 | 85571bc7 | bellard | |
368 | 85571bc7 | bellard | if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
|
369 | 1d14ffa9 | bellard | sdl_logerr ("SDL failed to initialize audio subsystem\n");
|
370 | 85571bc7 | bellard | return NULL; |
371 | 85571bc7 | bellard | } |
372 | 85571bc7 | bellard | |
373 | 85571bc7 | bellard | s->mutex = SDL_CreateMutex (); |
374 | 85571bc7 | bellard | if (!s->mutex) {
|
375 | 1d14ffa9 | bellard | sdl_logerr ("Failed to create SDL mutex\n");
|
376 | 85571bc7 | bellard | SDL_QuitSubSystem (SDL_INIT_AUDIO); |
377 | 85571bc7 | bellard | return NULL; |
378 | 85571bc7 | bellard | } |
379 | 85571bc7 | bellard | |
380 | 85571bc7 | bellard | s->sem = SDL_CreateSemaphore (0);
|
381 | 85571bc7 | bellard | if (!s->sem) {
|
382 | 1d14ffa9 | bellard | sdl_logerr ("Failed to create SDL semaphore\n");
|
383 | 85571bc7 | bellard | SDL_DestroyMutex (s->mutex); |
384 | 85571bc7 | bellard | SDL_QuitSubSystem (SDL_INIT_AUDIO); |
385 | 85571bc7 | bellard | return NULL; |
386 | 85571bc7 | bellard | } |
387 | 85571bc7 | bellard | |
388 | 85571bc7 | bellard | return s;
|
389 | 85571bc7 | bellard | } |
390 | 85571bc7 | bellard | |
391 | 85571bc7 | bellard | static void sdl_audio_fini (void *opaque) |
392 | 85571bc7 | bellard | { |
393 | 85571bc7 | bellard | SDLAudioState *s = opaque; |
394 | 85571bc7 | bellard | sdl_close (s); |
395 | 85571bc7 | bellard | SDL_DestroySemaphore (s->sem); |
396 | 85571bc7 | bellard | SDL_DestroyMutex (s->mutex); |
397 | 85571bc7 | bellard | SDL_QuitSubSystem (SDL_INIT_AUDIO); |
398 | 85571bc7 | bellard | } |
399 | 85571bc7 | bellard | |
400 | 1d14ffa9 | bellard | static struct audio_option sdl_options[] = { |
401 | 98f9f48c | malc | { |
402 | 98f9f48c | malc | .name = "SAMPLES",
|
403 | 98f9f48c | malc | .tag = AUD_OPT_INT, |
404 | 98f9f48c | malc | .valp = &conf.nb_samples, |
405 | 98f9f48c | malc | .descr = "Size of SDL buffer in samples"
|
406 | 98f9f48c | malc | }, |
407 | 2700efa3 | Juan Quintela | { /* End of list */ }
|
408 | 1d14ffa9 | bellard | }; |
409 | 1d14ffa9 | bellard | |
410 | 35f4b58c | blueswir1 | static struct audio_pcm_ops sdl_pcm_ops = { |
411 | 1dd3e4d1 | Juan Quintela | .init_out = sdl_init_out, |
412 | 1dd3e4d1 | Juan Quintela | .fini_out = sdl_fini_out, |
413 | 1dd3e4d1 | Juan Quintela | .run_out = sdl_run_out, |
414 | 1dd3e4d1 | Juan Quintela | .write = sdl_write_out, |
415 | 1dd3e4d1 | Juan Quintela | .ctl_out = sdl_ctl_out, |
416 | 85571bc7 | bellard | }; |
417 | 85571bc7 | bellard | |
418 | 1d14ffa9 | bellard | struct audio_driver sdl_audio_driver = {
|
419 | bee37f32 | Juan Quintela | .name = "sdl",
|
420 | bee37f32 | Juan Quintela | .descr = "SDL http://www.libsdl.org",
|
421 | bee37f32 | Juan Quintela | .options = sdl_options, |
422 | bee37f32 | Juan Quintela | .init = sdl_audio_init, |
423 | bee37f32 | Juan Quintela | .fini = sdl_audio_fini, |
424 | bee37f32 | Juan Quintela | .pcm_ops = &sdl_pcm_ops, |
425 | bee37f32 | Juan Quintela | .can_be_default = 1,
|
426 | bee37f32 | Juan Quintela | .max_voices_out = 1,
|
427 | bee37f32 | Juan Quintela | .max_voices_in = 0,
|
428 | bee37f32 | Juan Quintela | .voice_size_out = sizeof (SDLVoiceOut),
|
429 | bee37f32 | Juan Quintela | .voice_size_in = 0
|
430 | 85571bc7 | bellard | }; |