Revision c0fe3827 audio/audio_template.h
b/audio/audio_template.h | ||
---|---|---|
32 | 32 |
#define SW glue (SWVoice, In) |
33 | 33 |
#endif |
34 | 34 |
|
35 |
static int glue (audio_pcm_hw_init_, TYPE) ( |
|
36 |
HW *hw, |
|
37 |
audsettings_t *as |
|
38 |
) |
|
39 |
{ |
|
40 |
glue (audio_pcm_hw_free_resources_, TYPE) (hw); |
|
41 |
|
|
42 |
if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) { |
|
43 |
return -1; |
|
44 |
} |
|
45 |
|
|
46 |
if (audio_bug (AUDIO_FUNC, hw->samples <= 0)) { |
|
47 |
dolog ("hw->samples=%d\n", hw->samples); |
|
48 |
return -1; |
|
49 |
} |
|
50 |
|
|
51 |
LIST_INIT (&hw->sw_head); |
|
52 |
#ifdef DAC |
|
53 |
hw->clip = |
|
54 |
mixeng_clip |
|
55 |
#else |
|
56 |
hw->conv = |
|
57 |
mixeng_conv |
|
58 |
#endif |
|
59 |
[hw->info.nchannels == 2] |
|
60 |
[hw->info.sign] |
|
61 |
[hw->info.swap_endian] |
|
62 |
[hw->info.bits == 16]; |
|
63 |
|
|
64 |
if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) { |
|
65 |
glue (hw->pcm_ops->fini_, TYPE) (hw); |
|
66 |
return -1; |
|
67 |
} |
|
68 |
|
|
69 |
return 0; |
|
70 |
} |
|
71 |
|
|
35 | 72 |
static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw) |
36 | 73 |
{ |
37 | 74 |
glue (audio_pcm_sw_free_resources_, TYPE) (sw); |
... | ... | |
51 | 88 |
LIST_REMOVE (sw, entries); |
52 | 89 |
} |
53 | 90 |
|
54 |
static void glue (audio_pcm_hw_fini_, TYPE) (HW *hw)
|
|
91 |
static void glue (audio_pcm_hw_gc_, TYPE) (AudioState *s, HW **hwp)
|
|
55 | 92 |
{ |
56 |
if (hw->active) { |
|
57 |
glue (audio_pcm_hw_free_resources_ ,TYPE) (hw); |
|
58 |
glue (hw->pcm_ops->fini_, TYPE) (hw); |
|
59 |
memset (hw, 0, glue (audio_state.drv->voice_size_, TYPE)); |
|
60 |
} |
|
61 |
} |
|
93 |
HW *hw = *hwp; |
|
62 | 94 |
|
63 |
static void glue (audio_pcm_hw_gc_, TYPE) (HW *hw) |
|
64 |
{ |
|
65 | 95 |
if (!hw->sw_head.lh_first) { |
66 |
glue (audio_pcm_hw_fini_, TYPE) (hw); |
|
96 |
LIST_REMOVE (hw, entries); |
|
97 |
glue (s->nb_hw_voices_, TYPE) += 1; |
|
98 |
glue (audio_pcm_hw_free_resources_ ,TYPE) (hw); |
|
99 |
glue (hw->pcm_ops->fini_, TYPE) (hw); |
|
100 |
qemu_free (hw); |
|
101 |
*hwp = NULL; |
|
67 | 102 |
} |
68 | 103 |
} |
69 | 104 |
|
70 |
static HW *glue (audio_pcm_hw_find_any_, TYPE) (HW *hw) |
|
105 |
static HW *glue (audio_pcm_hw_find_any_, TYPE) (AudioState *s, HW *hw)
|
|
71 | 106 |
{ |
72 |
return hw ? hw->entries.le_next : glue (hw_head_, TYPE).lh_first; |
|
107 |
return hw ? hw->entries.le_next : s->glue (hw_head_, TYPE).lh_first;
|
|
73 | 108 |
} |
74 | 109 |
|
75 |
static HW *glue (audio_pcm_hw_find_any_active_, TYPE) (HW *hw)
|
|
110 |
static HW *glue (audio_pcm_hw_find_any_enabled_, TYPE) (AudioState *s, HW *hw)
|
|
76 | 111 |
{ |
77 |
while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) { |
|
78 |
if (hw->active) {
|
|
112 |
while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (s, hw))) {
|
|
113 |
if (hw->enabled) {
|
|
79 | 114 |
return hw; |
80 | 115 |
} |
81 | 116 |
} |
82 | 117 |
return NULL; |
83 | 118 |
} |
84 | 119 |
|
85 |
static HW *glue (audio_pcm_hw_find_any_active_enabled_, TYPE) (HW *hw)
|
|
120 |
static HW *glue (audio_pcm_hw_find_any_passive_, TYPE) (AudioState *s)
|
|
86 | 121 |
{ |
87 |
while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) { |
|
88 |
if (hw->active && hw->enabled) { |
|
89 |
return hw; |
|
122 |
if (glue (s->nb_hw_voices_, TYPE)) { |
|
123 |
struct audio_driver *drv = s->drv; |
|
124 |
|
|
125 |
if (audio_bug (AUDIO_FUNC, !drv)) { |
|
126 |
dolog ("No host audio driver\n"); |
|
127 |
return NULL; |
|
90 | 128 |
} |
91 |
} |
|
92 |
return NULL; |
|
93 |
} |
|
94 | 129 |
|
95 |
static HW *glue (audio_pcm_hw_find_any_passive_, TYPE) (HW *hw) |
|
96 |
{ |
|
97 |
while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) { |
|
98 |
if (!hw->active) { |
|
99 |
return hw; |
|
130 |
HW *hw = audio_calloc (AUDIO_FUNC, 1, glue (drv->voice_size_, TYPE)); |
|
131 |
if (!hw) { |
|
132 |
dolog ("Can not allocate voice `%s' size %d\n", |
|
133 |
drv->name, glue (drv->voice_size_, TYPE)); |
|
100 | 134 |
} |
135 |
|
|
136 |
LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries); |
|
137 |
glue (s->nb_hw_voices_, TYPE) -= 1; |
|
138 |
return hw; |
|
101 | 139 |
} |
140 |
|
|
102 | 141 |
return NULL; |
103 | 142 |
} |
104 | 143 |
|
105 | 144 |
static HW *glue (audio_pcm_hw_find_specific_, TYPE) ( |
145 |
AudioState *s, |
|
106 | 146 |
HW *hw, |
107 |
int freq, |
|
108 |
int nchannels, |
|
109 |
audfmt_e fmt |
|
147 |
audsettings_t *as |
|
110 | 148 |
) |
111 | 149 |
{ |
112 |
while ((hw = glue (audio_pcm_hw_find_any_active_, TYPE) (hw))) {
|
|
113 |
if (audio_pcm_info_eq (&hw->info, freq, nchannels, fmt)) {
|
|
150 |
while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (s, hw))) {
|
|
151 |
if (audio_pcm_info_eq (&hw->info, as)) {
|
|
114 | 152 |
return hw; |
115 | 153 |
} |
116 | 154 |
} |
117 | 155 |
return NULL; |
118 | 156 |
} |
119 | 157 |
|
120 |
static HW *glue (audio_pcm_hw_add_new_, TYPE) ( |
|
121 |
int freq, |
|
122 |
int nchannels, |
|
123 |
audfmt_e fmt |
|
124 |
) |
|
158 |
static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as) |
|
125 | 159 |
{ |
126 | 160 |
HW *hw; |
127 | 161 |
|
128 |
hw = glue (audio_pcm_hw_find_any_passive_, TYPE) (NULL);
|
|
162 |
hw = glue (audio_pcm_hw_find_any_passive_, TYPE) (s);
|
|
129 | 163 |
if (hw) { |
130 |
hw->pcm_ops = audio_state.drv->pcm_ops;
|
|
164 |
hw->pcm_ops = s->drv->pcm_ops;
|
|
131 | 165 |
if (!hw->pcm_ops) { |
132 | 166 |
return NULL; |
133 | 167 |
} |
134 | 168 |
|
135 |
if (glue (audio_pcm_hw_init_, TYPE) (hw, freq, nchannels, fmt)) {
|
|
136 |
glue (audio_pcm_hw_gc_, TYPE) (hw); |
|
169 |
if (glue (audio_pcm_hw_init_, TYPE) (hw, as)) {
|
|
170 |
glue (audio_pcm_hw_gc_, TYPE) (s, &hw);
|
|
137 | 171 |
return NULL; |
138 | 172 |
} |
139 | 173 |
else { |
... | ... | |
144 | 178 |
return NULL; |
145 | 179 |
} |
146 | 180 |
|
147 |
static HW *glue (audio_pcm_hw_add_, TYPE) ( |
|
148 |
int freq, |
|
149 |
int nchannels, |
|
150 |
audfmt_e fmt |
|
151 |
) |
|
181 |
static HW *glue (audio_pcm_hw_add_, TYPE) (AudioState *s, audsettings_t *as) |
|
152 | 182 |
{ |
153 | 183 |
HW *hw; |
154 | 184 |
|
155 |
if (glue (audio_state.greedy_, TYPE)) {
|
|
156 |
hw = glue (audio_pcm_hw_add_new_, TYPE) (freq, nchannels, fmt);
|
|
185 |
if (glue (conf.fixed_, TYPE).enabled && glue (conf.fixed_, TYPE).greedy) {
|
|
186 |
hw = glue (audio_pcm_hw_add_new_, TYPE) (s, as);
|
|
157 | 187 |
if (hw) { |
158 | 188 |
return hw; |
159 | 189 |
} |
160 | 190 |
} |
161 | 191 |
|
162 |
hw = glue (audio_pcm_hw_find_specific_, TYPE) (NULL, freq, nchannels, fmt);
|
|
192 |
hw = glue (audio_pcm_hw_find_specific_, TYPE) (s, NULL, as);
|
|
163 | 193 |
if (hw) { |
164 | 194 |
return hw; |
165 | 195 |
} |
166 | 196 |
|
167 |
hw = glue (audio_pcm_hw_add_new_, TYPE) (freq, nchannels, fmt);
|
|
197 |
hw = glue (audio_pcm_hw_add_new_, TYPE) (s, as);
|
|
168 | 198 |
if (hw) { |
169 | 199 |
return hw; |
170 | 200 |
} |
171 | 201 |
|
172 |
return glue (audio_pcm_hw_find_any_active_, TYPE) (NULL);
|
|
202 |
return glue (audio_pcm_hw_find_any_, TYPE) (s, NULL);
|
|
173 | 203 |
} |
174 | 204 |
|
175 | 205 |
static SW *glue (audio_pcm_create_voice_pair_, TYPE) ( |
176 |
const char *name, |
|
177 |
int freq, |
|
178 |
int nchannels, |
|
179 |
audfmt_e fmt |
|
206 |
AudioState *s, |
|
207 |
const char *sw_name, |
|
208 |
audsettings_t *as |
|
180 | 209 |
) |
181 | 210 |
{ |
182 | 211 |
SW *sw; |
183 | 212 |
HW *hw; |
184 |
int hw_freq = freq; |
|
185 |
int hw_nchannels = nchannels; |
|
186 |
int hw_fmt = fmt; |
|
213 |
audsettings_t hw_as; |
|
187 | 214 |
|
188 |
if (glue (audio_state.fixed_settings_, TYPE)) { |
|
189 |
hw_freq = glue (audio_state.fixed_freq_, TYPE); |
|
190 |
hw_nchannels = glue (audio_state.fixed_channels_, TYPE); |
|
191 |
hw_fmt = glue (audio_state.fixed_fmt_, TYPE); |
|
215 |
if (glue (conf.fixed_, TYPE).enabled) { |
|
216 |
hw_as = glue (conf.fixed_, TYPE).settings; |
|
217 |
} |
|
218 |
else { |
|
219 |
hw_as = *as; |
|
192 | 220 |
} |
193 | 221 |
|
194 |
sw = qemu_mallocz (sizeof (*sw));
|
|
222 |
sw = audio_calloc (AUDIO_FUNC, 1, sizeof (*sw));
|
|
195 | 223 |
if (!sw) { |
224 |
dolog ("Could not allocate soft voice `%s' (%d bytes)\n", |
|
225 |
sw_name ? sw_name : "unknown", sizeof (*sw)); |
|
196 | 226 |
goto err1; |
197 | 227 |
} |
198 | 228 |
|
199 |
hw = glue (audio_pcm_hw_add_, TYPE) (hw_freq, hw_nchannels, hw_fmt);
|
|
229 |
hw = glue (audio_pcm_hw_add_, TYPE) (s, &hw_as);
|
|
200 | 230 |
if (!hw) { |
201 | 231 |
goto err2; |
202 | 232 |
} |
203 | 233 |
|
204 | 234 |
glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw); |
205 | 235 |
|
206 |
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, freq, nchannels, fmt)) {
|
|
236 |
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
|
|
207 | 237 |
goto err3; |
208 | 238 |
} |
209 | 239 |
|
... | ... | |
211 | 241 |
|
212 | 242 |
err3: |
213 | 243 |
glue (audio_pcm_hw_del_sw_, TYPE) (sw); |
214 |
glue (audio_pcm_hw_gc_, TYPE) (hw); |
|
244 |
glue (audio_pcm_hw_gc_, TYPE) (s, &hw);
|
|
215 | 245 |
err2: |
216 | 246 |
qemu_free (sw); |
217 | 247 |
err1: |
218 | 248 |
return NULL; |
219 | 249 |
} |
220 | 250 |
|
221 |
void glue (AUD_close_, TYPE) (SW *sw) |
|
251 |
static void glue (audio_close_, TYPE) (AudioState *s, SW *sw) |
|
252 |
{ |
|
253 |
glue (audio_pcm_sw_fini_, TYPE) (sw); |
|
254 |
glue (audio_pcm_hw_del_sw_, TYPE) (sw); |
|
255 |
glue (audio_pcm_hw_gc_, TYPE) (s, &sw->hw); |
|
256 |
qemu_free (sw); |
|
257 |
} |
|
258 |
void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw) |
|
222 | 259 |
{ |
223 | 260 |
if (sw) { |
224 |
glue (audio_pcm_sw_fini_, TYPE) (sw); |
|
225 |
glue (audio_pcm_hw_del_sw_, TYPE) (sw); |
|
226 |
glue (audio_pcm_hw_gc_, TYPE) (sw->hw); |
|
227 |
qemu_free (sw); |
|
261 |
if (audio_bug (AUDIO_FUNC, !card || !card->audio)) { |
|
262 |
dolog ("card=%p card->audio=%p\n", |
|
263 |
card, card ? card->audio : NULL); |
|
264 |
return; |
|
265 |
} |
|
266 |
|
|
267 |
glue (audio_close_, TYPE) (card->audio, sw); |
|
228 | 268 |
} |
229 | 269 |
} |
230 | 270 |
|
231 | 271 |
SW *glue (AUD_open_, TYPE) ( |
272 |
QEMUSoundCard *card, |
|
232 | 273 |
SW *sw, |
233 | 274 |
const char *name, |
234 | 275 |
void *callback_opaque , |
235 | 276 |
audio_callback_fn_t callback_fn, |
236 |
int freq, |
|
237 |
int nchannels, |
|
238 |
audfmt_e fmt |
|
277 |
audsettings_t *as |
|
239 | 278 |
) |
240 | 279 |
{ |
280 |
AudioState *s; |
|
241 | 281 |
#ifdef DAC |
242 | 282 |
int live = 0; |
243 | 283 |
SW *old_sw = NULL; |
244 | 284 |
#endif |
245 | 285 |
|
246 |
if (!callback_fn) { |
|
247 |
dolog ("No callback specifed for voice `%s'\n", name); |
|
286 |
ldebug ("open %s, freq %d, nchannels %d, fmt %d\n", |
|
287 |
name, as->freq, as->nchannels, as->fmt); |
|
288 |
|
|
289 |
if (audio_bug (AUDIO_FUNC, |
|
290 |
!card || !card->audio || !name || !callback_fn || !as)) { |
|
291 |
dolog ("card=%p card->audio=%p name=%p callback_fn=%p as=%p\n", |
|
292 |
card, card ? card->audio : NULL, name, callback_fn, as); |
|
248 | 293 |
goto fail; |
249 | 294 |
} |
250 | 295 |
|
251 |
if (nchannels != 1 && nchannels != 2) { |
|
252 |
dolog ("Bogus channel count %d for voice `%s'\n", nchannels, name); |
|
296 |
s = card->audio; |
|
297 |
|
|
298 |
if (audio_bug (AUDIO_FUNC, audio_validate_settigs (as))) { |
|
299 |
audio_print_settings (as); |
|
253 | 300 |
goto fail; |
254 | 301 |
} |
255 | 302 |
|
256 |
if (!audio_state.drv) {
|
|
257 |
dolog ("No audio driver defined\n");
|
|
303 |
if (audio_bug (AUDIO_FUNC, !s->drv)) {
|
|
304 |
dolog ("Can not open `%s' (no host audio driver)\n", name);
|
|
258 | 305 |
goto fail; |
259 | 306 |
} |
260 | 307 |
|
261 |
if (sw && audio_pcm_info_eq (&sw->info, freq, nchannels, fmt)) {
|
|
308 |
if (sw && audio_pcm_info_eq (&sw->info, as)) {
|
|
262 | 309 |
return sw; |
263 | 310 |
} |
264 | 311 |
|
265 | 312 |
#ifdef DAC |
266 |
if (audio_state.plive && sw && (!sw->active && !sw->empty)) {
|
|
313 |
if (conf.plive && sw && (!sw->active && !sw->empty)) {
|
|
267 | 314 |
live = sw->total_hw_samples_mixed; |
268 | 315 |
|
269 | 316 |
#ifdef DEBUG_PLIVE |
270 |
dolog ("Replacing voice %s with %d live samples\n", sw->name, live);
|
|
317 |
dolog ("Replacing voice %s with %d live samples\n", SW_NAME (sw), live);
|
|
271 | 318 |
dolog ("Old %s freq %d, bits %d, channels %d\n", |
272 |
sw->name, sw->info.freq, sw->info.bits, sw->info.nchannels);
|
|
319 |
SW_NAME (sw), sw->info.freq, sw->info.bits, sw->info.nchannels);
|
|
273 | 320 |
dolog ("New %s freq %d, bits %d, channels %d\n", |
274 |
name, freq, (fmt == AUD_FMT_S16 || fmt == AUD_FMT_U16) ? 16 : 8, |
|
321 |
name, |
|
322 |
freq, |
|
323 |
(fmt == AUD_FMT_S16 || fmt == AUD_FMT_U16) ? 16 : 8, |
|
275 | 324 |
nchannels); |
276 | 325 |
#endif |
277 | 326 |
|
... | ... | |
283 | 332 |
} |
284 | 333 |
#endif |
285 | 334 |
|
286 |
if (!glue (audio_state.fixed_settings_, TYPE) && sw) {
|
|
287 |
glue (AUD_close_, TYPE) (sw); |
|
335 |
if (!glue (conf.fixed_, TYPE).enabled && sw) {
|
|
336 |
glue (AUD_close_, TYPE) (card, sw);
|
|
288 | 337 |
sw = NULL; |
289 | 338 |
} |
290 | 339 |
|
... | ... | |
292 | 341 |
HW *hw = sw->hw; |
293 | 342 |
|
294 | 343 |
if (!hw) { |
295 |
dolog ("Internal logic error voice %s has no hardware store\n",
|
|
296 |
name);
|
|
344 |
dolog ("Internal logic error voice `%s' has no hardware store\n",
|
|
345 |
SW_NAME (sw));
|
|
297 | 346 |
goto fail; |
298 | 347 |
} |
299 | 348 |
|
300 |
if (glue (audio_pcm_sw_init_, TYPE) ( |
|
301 |
sw, |
|
302 |
hw, |
|
303 |
name, |
|
304 |
freq, |
|
305 |
nchannels, |
|
306 |
fmt |
|
307 |
)) { |
|
349 |
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) { |
|
308 | 350 |
goto fail; |
309 | 351 |
} |
310 | 352 |
} |
311 | 353 |
else { |
312 |
sw = glue (audio_pcm_create_voice_pair_, TYPE) ( |
|
313 |
name, |
|
314 |
freq, |
|
315 |
nchannels, |
|
316 |
fmt); |
|
354 |
sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as); |
|
317 | 355 |
if (!sw) { |
318 |
dolog ("Failed to create voice %s\n", name);
|
|
356 |
dolog ("Failed to create voice `%s'\n", name);
|
|
319 | 357 |
goto fail; |
320 | 358 |
} |
321 | 359 |
} |
... | ... | |
349 | 387 |
return sw; |
350 | 388 |
|
351 | 389 |
fail: |
352 |
glue (AUD_close_, TYPE) (sw); |
|
390 |
glue (AUD_close_, TYPE) (card, sw);
|
|
353 | 391 |
return NULL; |
354 | 392 |
} |
355 | 393 |
|
... | ... | |
367 | 405 |
ts->old_ts = sw->hw->ts_helper; |
368 | 406 |
} |
369 | 407 |
|
370 |
uint64_t glue (AUD_time_stamp_get_elapsed_usec_, TYPE) ( |
|
371 |
SW *sw, |
|
372 |
QEMUAudioTimeStamp *ts |
|
373 |
) |
|
408 |
uint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts) |
|
374 | 409 |
{ |
375 | 410 |
uint64_t delta, cur_ts, old_ts; |
376 | 411 |
|
Also available in: Unified diff