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