]> git.ipfire.org Git - thirdparty/qemu.git/blame - audio/audio_template.h
spiceaudio: port to the new audio backend api
[thirdparty/qemu.git] / audio / audio_template.h
CommitLineData
1d14ffa9
FB
1/*
2 * QEMU Audio subsystem header
3 *
4 * Copyright (c) 2005 Vassili Karpov (malc)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#ifdef DAC
571ec3d6
FB
26#define NAME "playback"
27#define HWBUF hw->mix_buf
1d14ffa9 28#define TYPE out
571ec3d6
FB
29#define HW HWVoiceOut
30#define SW SWVoiceOut
1d14ffa9 31#else
571ec3d6 32#define NAME "capture"
1d14ffa9 33#define TYPE in
571ec3d6
FB
34#define HW HWVoiceIn
35#define SW SWVoiceIn
36#define HWBUF hw->conv_buf
1d14ffa9
FB
37#endif
38
526fb058
KZ
39static void glue(audio_init_nb_voices_, TYPE)(AudioState *s,
40 struct audio_driver *drv)
c0fe3827 41{
571ec3d6
FB
42 int max_voices = glue (drv->max_voices_, TYPE);
43 int voice_size = glue (drv->voice_size_, TYPE);
c0fe3827 44
571ec3d6
FB
45 if (glue (s->nb_hw_voices_, TYPE) > max_voices) {
46 if (!max_voices) {
47#ifdef DAC
48 dolog ("Driver `%s' does not support " NAME "\n", drv->name);
49#endif
50 }
51 else {
52 dolog ("Driver `%s' does not support %d " NAME " voices, max %d\n",
53 drv->name,
54 glue (s->nb_hw_voices_, TYPE),
55 max_voices);
56 }
57 glue (s->nb_hw_voices_, TYPE) = max_voices;
c0fe3827
FB
58 }
59
470bcabd 60 if (audio_bug(__func__, !voice_size && max_voices)) {
571ec3d6
FB
61 dolog ("drv=`%s' voice_size=0 max_voices=%d\n",
62 drv->name, max_voices);
63 glue (s->nb_hw_voices_, TYPE) = 0;
64 }
65
470bcabd 66 if (audio_bug(__func__, voice_size && !max_voices)) {
571ec3d6
FB
67 dolog ("drv=`%s' voice_size=%d max_voices=0\n",
68 drv->name, voice_size);
69 }
70}
71
72static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw)
73{
ff095e52 74 g_free(hw->buf_emul);
fb7da626 75 g_free (HWBUF);
571ec3d6
FB
76 HWBUF = NULL;
77}
78
7520462b 79static bool glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw)
571ec3d6 80{
470bcabd 81 HWBUF = audio_calloc(__func__, hw->samples, sizeof(struct st_sample));
571ec3d6 82 if (!HWBUF) {
7520462b
KZ
83 dolog("Could not allocate " NAME " buffer (%zu samples)\n",
84 hw->samples);
85 return false;
c0fe3827
FB
86 }
87
7520462b 88 return true;
571ec3d6
FB
89}
90
91static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw)
92{
fb7da626 93 g_free (sw->buf);
571ec3d6
FB
94
95 if (sw->rate) {
96 st_rate_stop (sw->rate);
97 }
98
99 sw->buf = NULL;
100 sw->rate = NULL;
101}
102
103static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw)
104{
105 int samples;
106
571ec3d6 107 samples = ((int64_t) sw->hw->samples << 32) / sw->ratio;
c0fe3827 108
470bcabd 109 sw->buf = audio_calloc(__func__, samples, sizeof(struct st_sample));
571ec3d6
FB
110 if (!sw->buf) {
111 dolog ("Could not allocate buffer for `%s' (%d samples)\n",
112 SW_NAME (sw), samples);
c0fe3827
FB
113 return -1;
114 }
115
571ec3d6
FB
116#ifdef DAC
117 sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq);
118#else
119 sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq);
120#endif
121 if (!sw->rate) {
7267c094 122 g_free (sw->buf);
571ec3d6
FB
123 sw->buf = NULL;
124 return -1;
125 }
c0fe3827
FB
126 return 0;
127}
128
571ec3d6
FB
129static int glue (audio_pcm_sw_init_, TYPE) (
130 SW *sw,
131 HW *hw,
132 const char *name,
1ea879e5 133 struct audsettings *as
571ec3d6
FB
134 )
135{
136 int err;
137
d929eba5 138 audio_pcm_init_info (&sw->info, as);
571ec3d6
FB
139 sw->hw = hw;
140 sw->active = 0;
141#ifdef DAC
142 sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq;
143 sw->total_hw_samples_mixed = 0;
144 sw->empty = 1;
145#else
146 sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
147#endif
148
149#ifdef DAC
150 sw->conv = mixeng_conv
151#else
152 sw->clip = mixeng_clip
153#endif
154 [sw->info.nchannels == 2]
155 [sw->info.sign]
d929eba5 156 [sw->info.swap_endianness]
f941aa25 157 [audio_bits_to_index (sw->info.bits)];
571ec3d6 158
7267c094 159 sw->name = g_strdup (name);
571ec3d6
FB
160 err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
161 if (err) {
7267c094 162 g_free (sw->name);
571ec3d6
FB
163 sw->name = NULL;
164 }
165 return err;
166}
167
1d14ffa9
FB
168static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw)
169{
170 glue (audio_pcm_sw_free_resources_, TYPE) (sw);
fb7da626
MA
171 g_free (sw->name);
172 sw->name = NULL;
1d14ffa9
FB
173}
174
175static void glue (audio_pcm_hw_add_sw_, TYPE) (HW *hw, SW *sw)
176{
72cf2d4f 177 QLIST_INSERT_HEAD (&hw->sw_head, sw, entries);
1d14ffa9
FB
178}
179
180static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw)
181{
72cf2d4f 182 QLIST_REMOVE (sw, entries);
1d14ffa9
FB
183}
184
1a7dafce 185static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp)
1d14ffa9 186{
c0fe3827 187 HW *hw = *hwp;
526fb058 188 AudioState *s = hw->s;
1d14ffa9 189
1d14ffa9 190 if (!hw->sw_head.lh_first) {
8ead62cf
FB
191#ifdef DAC
192 audio_detach_capture (hw);
193#endif
72cf2d4f 194 QLIST_REMOVE (hw, entries);
b28fb27b 195 glue (hw->pcm_ops->fini_, TYPE) (hw);
c0fe3827
FB
196 glue (s->nb_hw_voices_, TYPE) += 1;
197 glue (audio_pcm_hw_free_resources_ ,TYPE) (hw);
7267c094 198 g_free (hw);
c0fe3827 199 *hwp = NULL;
1d14ffa9
FB
200 }
201}
202
526fb058 203static HW *glue(audio_pcm_hw_find_any_, TYPE)(AudioState *s, HW *hw)
1d14ffa9 204{
1a7dafce 205 return hw ? hw->entries.le_next : glue (s->hw_head_, TYPE).lh_first;
1d14ffa9
FB
206}
207
526fb058 208static HW *glue(audio_pcm_hw_find_any_enabled_, TYPE)(AudioState *s, HW *hw)
1d14ffa9 209{
526fb058 210 while ((hw = glue(audio_pcm_hw_find_any_, TYPE)(s, hw))) {
c0fe3827 211 if (hw->enabled) {
1d14ffa9
FB
212 return hw;
213 }
214 }
215 return NULL;
216}
217
526fb058
KZ
218static HW *glue(audio_pcm_hw_find_specific_, TYPE)(AudioState *s, HW *hw,
219 struct audsettings *as)
1d14ffa9 220{
526fb058 221 while ((hw = glue(audio_pcm_hw_find_any_, TYPE)(s, hw))) {
c0fe3827 222 if (audio_pcm_info_eq (&hw->info, as)) {
1d14ffa9
FB
223 return hw;
224 }
225 }
226 return NULL;
227}
228
526fb058
KZ
229static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
230 struct audsettings *as)
1d14ffa9
FB
231{
232 HW *hw;
571ec3d6 233 struct audio_driver *drv = s->drv;
1d14ffa9 234
571ec3d6
FB
235 if (!glue (s->nb_hw_voices_, TYPE)) {
236 return NULL;
237 }
1d14ffa9 238
470bcabd 239 if (audio_bug(__func__, !drv)) {
571ec3d6
FB
240 dolog ("No host audio driver\n");
241 return NULL;
1d14ffa9
FB
242 }
243
470bcabd 244 if (audio_bug(__func__, !drv->pcm_ops)) {
571ec3d6
FB
245 dolog ("Host audio driver without pcm_ops\n");
246 return NULL;
247 }
248
470bcabd 249 hw = audio_calloc(__func__, 1, glue(drv->voice_size_, TYPE));
571ec3d6
FB
250 if (!hw) {
251 dolog ("Can not allocate voice `%s' size %d\n",
252 drv->name, glue (drv->voice_size_, TYPE));
253 return NULL;
254 }
255
526fb058 256 hw->s = s;
571ec3d6 257 hw->pcm_ops = drv->pcm_ops;
c01b2456
MAL
258 hw->ctl_caps = drv->ctl_caps;
259
72cf2d4f 260 QLIST_INIT (&hw->sw_head);
8ead62cf 261#ifdef DAC
72cf2d4f 262 QLIST_INIT (&hw->cap_head);
8ead62cf 263#endif
5706db1d 264 if (glue (hw->pcm_ops->init_, TYPE) (hw, as, s->drv_opaque)) {
571ec3d6
FB
265 goto err0;
266 }
267
470bcabd 268 if (audio_bug(__func__, hw->samples <= 0)) {
7520462b 269 dolog("hw->samples=%zd\n", hw->samples);
571ec3d6
FB
270 goto err1;
271 }
272
273#ifdef DAC
274 hw->clip = mixeng_clip
275#else
276 hw->conv = mixeng_conv
277#endif
278 [hw->info.nchannels == 2]
279 [hw->info.sign]
d929eba5 280 [hw->info.swap_endianness]
f941aa25 281 [audio_bits_to_index (hw->info.bits)];
571ec3d6 282
7520462b 283 if (!glue(audio_pcm_hw_alloc_resources_, TYPE)(hw)) {
571ec3d6
FB
284 goto err1;
285 }
286
72cf2d4f 287 QLIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
571ec3d6 288 glue (s->nb_hw_voices_, TYPE) -= 1;
8ead62cf 289#ifdef DAC
1a7dafce 290 audio_attach_capture (hw);
8ead62cf 291#endif
571ec3d6
FB
292 return hw;
293
294 err1:
295 glue (hw->pcm_ops->fini_, TYPE) (hw);
296 err0:
7267c094 297 g_free (hw);
1d14ffa9
FB
298 return NULL;
299}
300
71830221
KZ
301AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev)
302{
303 switch (dev->driver) {
304 case AUDIODEV_DRIVER_NONE:
305 return dev->u.none.TYPE;
306 case AUDIODEV_DRIVER_ALSA:
307 return qapi_AudiodevAlsaPerDirectionOptions_base(dev->u.alsa.TYPE);
308 case AUDIODEV_DRIVER_COREAUDIO:
309 return qapi_AudiodevCoreaudioPerDirectionOptions_base(
310 dev->u.coreaudio.TYPE);
311 case AUDIODEV_DRIVER_DSOUND:
312 return dev->u.dsound.TYPE;
313 case AUDIODEV_DRIVER_OSS:
314 return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.TYPE);
315 case AUDIODEV_DRIVER_PA:
316 return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.TYPE);
317 case AUDIODEV_DRIVER_SDL:
318 return dev->u.sdl.TYPE;
319 case AUDIODEV_DRIVER_SPICE:
320 return dev->u.spice.TYPE;
321 case AUDIODEV_DRIVER_WAV:
322 return dev->u.wav.TYPE;
323
324 case AUDIODEV_DRIVER__MAX:
325 break;
326 }
327 abort();
328}
329
526fb058 330static HW *glue(audio_pcm_hw_add_, TYPE)(AudioState *s, struct audsettings *as)
1d14ffa9
FB
331{
332 HW *hw;
71830221 333 AudiodevPerDirectionOptions *pdo = glue(audio_get_pdo_, TYPE)(s->dev);
1d14ffa9 334
71830221 335 if (pdo->fixed_settings) {
526fb058 336 hw = glue(audio_pcm_hw_add_new_, TYPE)(s, as);
1d14ffa9
FB
337 if (hw) {
338 return hw;
339 }
340 }
341
526fb058 342 hw = glue(audio_pcm_hw_find_specific_, TYPE)(s, NULL, as);
1d14ffa9
FB
343 if (hw) {
344 return hw;
345 }
346
526fb058 347 hw = glue(audio_pcm_hw_add_new_, TYPE)(s, as);
1d14ffa9
FB
348 if (hw) {
349 return hw;
350 }
351
526fb058 352 return glue(audio_pcm_hw_find_any_, TYPE)(s, NULL);
1d14ffa9
FB
353}
354
526fb058
KZ
355static SW *glue(audio_pcm_create_voice_pair_, TYPE)(
356 AudioState *s,
c0fe3827 357 const char *sw_name,
1ea879e5 358 struct audsettings *as
1d14ffa9
FB
359 )
360{
361 SW *sw;
362 HW *hw;
1ea879e5 363 struct audsettings hw_as;
71830221 364 AudiodevPerDirectionOptions *pdo = glue(audio_get_pdo_, TYPE)(s->dev);
1d14ffa9 365
71830221
KZ
366 if (pdo->fixed_settings) {
367 hw_as = audiodev_to_audsettings(pdo);
c0fe3827
FB
368 }
369 else {
370 hw_as = *as;
1d14ffa9
FB
371 }
372
470bcabd 373 sw = audio_calloc(__func__, 1, sizeof(*sw));
1d14ffa9 374 if (!sw) {
e7cad338 375 dolog ("Could not allocate soft voice `%s' (%zu bytes)\n",
c0fe3827 376 sw_name ? sw_name : "unknown", sizeof (*sw));
1d14ffa9
FB
377 goto err1;
378 }
526fb058 379 sw->s = s;
1d14ffa9 380
526fb058 381 hw = glue(audio_pcm_hw_add_, TYPE)(s, &hw_as);
1d14ffa9
FB
382 if (!hw) {
383 goto err2;
384 }
385
386 glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
387
d929eba5 388 if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
1d14ffa9
FB
389 goto err3;
390 }
391
392 return sw;
393
394err3:
395 glue (audio_pcm_hw_del_sw_, TYPE) (sw);
1a7dafce 396 glue (audio_pcm_hw_gc_, TYPE) (&hw);
1d14ffa9 397err2:
7267c094 398 g_free (sw);
1d14ffa9
FB
399err1:
400 return NULL;
401}
402
1a7dafce 403static void glue (audio_close_, TYPE) (SW *sw)
c0fe3827
FB
404{
405 glue (audio_pcm_sw_fini_, TYPE) (sw);
406 glue (audio_pcm_hw_del_sw_, TYPE) (sw);
1a7dafce 407 glue (audio_pcm_hw_gc_, TYPE) (&sw->hw);
7267c094 408 g_free (sw);
c0fe3827 409}
571ec3d6 410
c0fe3827 411void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
1d14ffa9
FB
412{
413 if (sw) {
470bcabd 414 if (audio_bug(__func__, !card)) {
1a7dafce 415 dolog ("card=%p\n", card);
c0fe3827
FB
416 return;
417 }
418
1a7dafce 419 glue (audio_close_, TYPE) (sw);
1d14ffa9
FB
420 }
421}
422
423SW *glue (AUD_open_, TYPE) (
c0fe3827 424 QEMUSoundCard *card,
1d14ffa9
FB
425 SW *sw,
426 const char *name,
427 void *callback_opaque ,
cb4f03e8 428 audio_callback_fn callback_fn,
1ea879e5 429 struct audsettings *as
1d14ffa9
FB
430 )
431{
ecd97e95 432 AudioState *s = card->state;
71830221 433 AudiodevPerDirectionOptions *pdo = glue(audio_get_pdo_, TYPE)(s->dev);
1d14ffa9 434
470bcabd 435 if (audio_bug(__func__, !card || !name || !callback_fn || !as)) {
1a7dafce 436 dolog ("card=%p name=%p callback_fn=%p as=%p\n",
437 card, name, callback_fn, as);
1d14ffa9
FB
438 goto fail;
439 }
440
93b65997
SW
441 ldebug ("open %s, freq %d, nchannels %d, fmt %d\n",
442 name, as->freq, as->nchannels, as->fmt);
443
470bcabd 444 if (audio_bug(__func__, audio_validate_settings(as))) {
c0fe3827 445 audio_print_settings (as);
1d14ffa9
FB
446 goto fail;
447 }
448
470bcabd 449 if (audio_bug(__func__, !s->drv)) {
c0fe3827 450 dolog ("Can not open `%s' (no host audio driver)\n", name);
1d14ffa9
FB
451 goto fail;
452 }
453
c0fe3827 454 if (sw && audio_pcm_info_eq (&sw->info, as)) {
1d14ffa9
FB
455 return sw;
456 }
457
71830221 458 if (!pdo->fixed_settings && sw) {
c0fe3827 459 glue (AUD_close_, TYPE) (card, sw);
1d14ffa9
FB
460 sw = NULL;
461 }
462
463 if (sw) {
464 HW *hw = sw->hw;
465
466 if (!hw) {
c0fe3827
FB
467 dolog ("Internal logic error voice `%s' has no hardware store\n",
468 SW_NAME (sw));
1d14ffa9
FB
469 goto fail;
470 }
471
571ec3d6 472 glue (audio_pcm_sw_fini_, TYPE) (sw);
d929eba5 473 if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) {
1d14ffa9
FB
474 goto fail;
475 }
476 }
477 else {
526fb058 478 sw = glue(audio_pcm_create_voice_pair_, TYPE)(s, name, as);
1d14ffa9 479 if (!sw) {
c0fe3827 480 dolog ("Failed to create voice `%s'\n", name);
571ec3d6 481 return NULL;
1d14ffa9
FB
482 }
483 }
484
7cbb28ed 485 sw->card = card;
486 sw->vol = nominal_volume;
487 sw->callback.fn = callback_fn;
488 sw->callback.opaque = callback_opaque;
1d14ffa9 489
1d14ffa9 490#ifdef DEBUG_AUDIO
7cbb28ed 491 dolog ("%s\n", name);
492 audio_pcm_print_info ("hw", &sw->hw->info);
493 audio_pcm_print_info ("sw", &sw->info);
1d14ffa9 494#endif
1d14ffa9
FB
495
496 return sw;
497
498 fail:
c0fe3827 499 glue (AUD_close_, TYPE) (card, sw);
1d14ffa9
FB
500 return NULL;
501}
502
503int glue (AUD_is_active_, TYPE) (SW *sw)
504{
505 return sw ? sw->active : 0;
506}
507
508void glue (AUD_init_time_stamp_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
509{
510 if (!sw) {
511 return;
512 }
513
514 ts->old_ts = sw->hw->ts_helper;
515}
516
c0fe3827 517uint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
1d14ffa9
FB
518{
519 uint64_t delta, cur_ts, old_ts;
520
521 if (!sw) {
522 return 0;
523 }
524
525 cur_ts = sw->hw->ts_helper;
526 old_ts = ts->old_ts;
0bfcd599 527 /* dolog ("cur %" PRId64 " old %" PRId64 "\n", cur_ts, old_ts); */
1d14ffa9
FB
528
529 if (cur_ts >= old_ts) {
530 delta = cur_ts - old_ts;
531 }
532 else {
533 delta = UINT64_MAX - old_ts + cur_ts;
534 }
535
536 if (!delta) {
537 return 0;
538 }
539
4f4cc0ef 540 return muldiv64 (delta, sw->hw->info.freq, 1000000);
1d14ffa9
FB
541}
542
543#undef TYPE
544#undef HW
545#undef SW
571ec3d6
FB
546#undef HWBUF
547#undef NAME