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