Audio clean-ups

-----BEGIN PGP SIGNATURE-----
 
 iQJQBAABCgA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmkEWqwcHG1hcmNhbmRy
 ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5a4RD/49KcP8h/5+QT3nu703
 OL/c/+M0DEZCVikzbj1T+nZNlUZtto/wE1vY0/xxzoyMh/4XbUFI0b/YK8WcQyUx
 ozrWOCi6TquS1QpR62FBmDJ6QDA2KteTF8Zq/owdFj+l7VJ5F5mzcuuFCxLx1EVH
 7qOIf37Vk4r8jz42CLRTusPGQZLSvS8LbTBP62guauXlVAKVWI8k9macRSqoTBRo
 VrQO3QC/JFSqkB2jGfes8AMU+RWLYPG3ICCf0UYHH/kMik/JEL+1arx7au7oukTb
 3kp8cxGnuJzBKCvY8SLwQF3YiCotYQIjSkvAQrMYBXalPBjQIIh+vzegcF1D+xZb
 6KR4kh3oXPHtVCG2AXcxA4IuAi50jYFPn6TgDkRrUAEhsOqOxLo5bmZsqWK7L3/u
 61jLKSjLRSc+NjhwHN0YVy1ocdsLf2z1LQNHjC1TuxrgI//9fQnOE2gASb8tmJGg
 BlPYp5h6G50IEaACzlZEtudWpKRb/XyflWpHbWte0VUO9dpz/cUvO1P38CpPD1dr
 ohENb8eLn0L23M12tUABV0IoA729phBYh3Eua9uIzEVfuRVfoPCuocx6VxQked91
 SZr7X9G80Nyh5YYiMlrwpN8eDgPtKfW5JwI2wYME6clGLnf/catkqCl/qp4nQeG5
 LPZiFy5Krz+QuSq41DjcSWRD+g==
 =qTgA
 -----END PGP SIGNATURE-----

Merge tag 'audio-test-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging

Audio clean-ups

# -----BEGIN PGP SIGNATURE-----
#
# iQJQBAABCgA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmkEWqwcHG1hcmNhbmRy
# ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5a4RD/49KcP8h/5+QT3nu703
# OL/c/+M0DEZCVikzbj1T+nZNlUZtto/wE1vY0/xxzoyMh/4XbUFI0b/YK8WcQyUx
# ozrWOCi6TquS1QpR62FBmDJ6QDA2KteTF8Zq/owdFj+l7VJ5F5mzcuuFCxLx1EVH
# 7qOIf37Vk4r8jz42CLRTusPGQZLSvS8LbTBP62guauXlVAKVWI8k9macRSqoTBRo
# VrQO3QC/JFSqkB2jGfes8AMU+RWLYPG3ICCf0UYHH/kMik/JEL+1arx7au7oukTb
# 3kp8cxGnuJzBKCvY8SLwQF3YiCotYQIjSkvAQrMYBXalPBjQIIh+vzegcF1D+xZb
# 6KR4kh3oXPHtVCG2AXcxA4IuAi50jYFPn6TgDkRrUAEhsOqOxLo5bmZsqWK7L3/u
# 61jLKSjLRSc+NjhwHN0YVy1ocdsLf2z1LQNHjC1TuxrgI//9fQnOE2gASb8tmJGg
# BlPYp5h6G50IEaACzlZEtudWpKRb/XyflWpHbWte0VUO9dpz/cUvO1P38CpPD1dr
# ohENb8eLn0L23M12tUABV0IoA729phBYh3Eua9uIzEVfuRVfoPCuocx6VxQked91
# SZr7X9G80Nyh5YYiMlrwpN8eDgPtKfW5JwI2wYME6clGLnf/catkqCl/qp4nQeG5
# LPZiFy5Krz+QuSq41DjcSWRD+g==
# =qTgA
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 31 Oct 2025 07:43:56 AM CET
# gpg:                using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5
# gpg:                issuer "marcandre.lureau@redhat.com"
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [unknown]
# gpg:                 aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [unknown]
# gpg: WARNING: The key's User ID is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* tag 'audio-test-pull-request' of https://gitlab.com/marcandre.lureau/qemu: (36 commits)
  audio: deprecate HMP audio commands
  audio: Rename @endianness argument as @big_endian for clarity
  audio: Remove pointless local variables
  audio: drop needless audio_driver "descr" field
  audio: move capture API to own header
  audio: cleanup, use bool for booleans
  audio: remove dependency on spice header
  audio: move audio.h under include/qemu/
  audio/dbus: use a helper function to set the backend dbus server
  audio: remove QEMUSoundCard
  audio: rename AudioState -> AudioBackend
  audio: move internal APIs to audio_int.h
  audio/replay: fix type punning
  audio: introduce AUD_set_volume_{in,out}_lr()
  audio: remove AUDIO_HOST_ENDIANNESS
  audio: remove some needless headers
  audio: initialize card_head during object init
  audio: register and unregister vmstate with AudioState
  audio: keep vmstate handle with AudioState
  audio: drop needless error message
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2025-11-01 10:51:32 +01:00
commit c5d60e5903
79 changed files with 903 additions and 958 deletions

View file

@ -2978,6 +2978,7 @@ X: audio/paaudio.c
X: audio/sdlaudio.c
X: audio/sndioaudio.c
X: audio/spiceaudio.c
F: include/qemu/audio*.h
F: qapi/audio.json
ALSA Audio backend

View file

@ -26,7 +26,7 @@
#include <alsa/asoundlib.h>
#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "audio.h"
#include "qemu/audio.h"
#include "trace.h"
#pragma GCC diagnostic ignored "-Waddress"
@ -41,7 +41,7 @@ struct pollhlp {
struct pollfd *pfds;
int count;
int mask;
AudioState *s;
AudioBackend *s;
};
typedef struct ALSAVoiceOut {
@ -264,7 +264,7 @@ static int alsa_poll_in (HWVoiceIn *hw)
return alsa_poll_helper (alsa->handle, &alsa->pollhlp, POLLIN);
}
static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness)
static snd_pcm_format_t aud_to_alsafmt(AudioFormat fmt, bool big_endian)
{
switch (fmt) {
case AUDIO_FORMAT_S8:
@ -274,39 +274,19 @@ static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness)
return SND_PCM_FORMAT_U8;
case AUDIO_FORMAT_S16:
if (endianness) {
return SND_PCM_FORMAT_S16_BE;
} else {
return SND_PCM_FORMAT_S16_LE;
}
return big_endian ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE;
case AUDIO_FORMAT_U16:
if (endianness) {
return SND_PCM_FORMAT_U16_BE;
} else {
return SND_PCM_FORMAT_U16_LE;
}
return big_endian ? SND_PCM_FORMAT_U16_BE : SND_PCM_FORMAT_U16_LE;
case AUDIO_FORMAT_S32:
if (endianness) {
return SND_PCM_FORMAT_S32_BE;
} else {
return SND_PCM_FORMAT_S32_LE;
}
return big_endian ? SND_PCM_FORMAT_S32_BE : SND_PCM_FORMAT_S32_LE;
case AUDIO_FORMAT_U32:
if (endianness) {
return SND_PCM_FORMAT_U32_BE;
} else {
return SND_PCM_FORMAT_U32_LE;
}
return big_endian ? SND_PCM_FORMAT_U32_BE : SND_PCM_FORMAT_U32_LE;
case AUDIO_FORMAT_F32:
if (endianness) {
return SND_PCM_FORMAT_FLOAT_BE;
} else {
return SND_PCM_FORMAT_FLOAT_LE;
}
return big_endian ? SND_PCM_FORMAT_FLOAT_BE : SND_PCM_FORMAT_FLOAT_LE;
default:
dolog ("Internal logic error: Bad audio format %d\n", fmt);
@ -956,7 +936,6 @@ static struct audio_pcm_ops alsa_pcm_ops = {
static struct audio_driver alsa_audio_driver = {
.name = "alsa",
.descr = "ALSA http://www.alsa-project.org",
.init = alsa_audio_init,
.fini = alsa_audio_fini,
.pcm_ops = &alsa_pcm_ops,

View file

@ -23,11 +23,12 @@
*/
#include "qemu/osdep.h"
#include "audio/audio.h"
#include "audio_int.h"
#include "monitor/hmp.h"
#include "monitor/monitor.h"
#include "qapi/error.h"
#include "qobject/qdict.h"
#include "qemu/error-report.h"
static QLIST_HEAD (capture_list_head, CaptureState) capture_head;
@ -36,6 +37,8 @@ void hmp_info_capture(Monitor *mon, const QDict *qdict)
int i;
CaptureState *s;
warn_report_once("'info capture' is deprecated since v10.2, to be removed");
for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
monitor_printf(mon, "[%d]: ", i);
s->ops.info (s->opaque);
@ -48,6 +51,8 @@ void hmp_stopcapture(Monitor *mon, const QDict *qdict)
int n = qdict_get_int(qdict, "n");
CaptureState *s;
warn_report_once("'stopcapture' is deprecated since v10.2, to be removed");
for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
if (i == n) {
s->ops.destroy (s->opaque);
@ -67,7 +72,9 @@ void hmp_wavcapture(Monitor *mon, const QDict *qdict)
const char *audiodev = qdict_get_str(qdict, "audiodev");
CaptureState *s;
Error *local_err = NULL;
AudioState *as = audio_state_by_name(audiodev, &local_err);
AudioBackend *as = audio_be_by_name(audiodev, &local_err);
warn_report_once("'wavcapture' is deprecated since v10.2, to be removed");
if (!as) {
error_report_err(local_err);

View file

@ -23,9 +23,8 @@
*/
#include "qemu/osdep.h"
#include "audio.h"
#include "qemu/audio.h"
#include "migration/vmstate.h"
#include "monitor/monitor.h"
#include "qemu/timer.h"
#include "qapi/error.h"
#include "qapi/clone-visitor.h"
@ -33,7 +32,6 @@
#include "qapi/qapi-visit-audio.h"
#include "qapi/qapi-commands-audio.h"
#include "qobject/qdict.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
#include "qemu/log.h"
#include "qemu/module.h"
@ -41,7 +39,6 @@
#include "system/system.h"
#include "system/replay.h"
#include "system/runstate.h"
#include "ui/qemu-spice.h"
#include "trace.h"
#define AUDIO_CAP "audio"
@ -102,9 +99,7 @@ static audio_driver *audio_driver_lookup(const char *name)
return NULL;
}
static QTAILQ_HEAD(AudioStateHead, AudioState) audio_states =
QTAILQ_HEAD_INITIALIZER(audio_states);
static AudioState *default_audio_state;
static AudioBackend *default_audio_be;
const struct mixeng_volume nominal_volume = {
.mute = 0,
@ -279,7 +274,7 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, struct audsettings *a
&& info->is_signed == is_signed
&& info->is_float == is_float
&& info->bits == bits
&& info->swap_endianness == (as->endianness != AUDIO_HOST_ENDIANNESS);
&& info->swap_endianness == (as->endianness != HOST_BIG_ENDIAN);
}
void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
@ -325,7 +320,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
info->nchannels = as->nchannels;
info->bytes_per_frame = as->nchannels * mul;
info->bytes_per_second = info->freq * info->bytes_per_frame;
info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS);
info->swap_endianness = (as->endianness != HOST_BIG_ENDIAN);
}
void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
@ -385,7 +380,7 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
/*
* Capture
*/
static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioState *s,
static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioBackend *s,
struct audsettings *as)
{
CaptureVoiceOut *cap;
@ -410,7 +405,7 @@ static void audio_notify_capture (CaptureVoiceOut *cap, audcnotification_e cmd)
}
}
static void audio_capture_maybe_changed (CaptureVoiceOut *cap, int enabled)
static void audio_capture_maybe_changed(CaptureVoiceOut *cap, bool enabled)
{
if (cap->hw.enabled != enabled) {
audcnotification_e cmd;
@ -424,11 +419,11 @@ static void audio_recalc_and_notify_capture (CaptureVoiceOut *cap)
{
HWVoiceOut *hw = &cap->hw;
SWVoiceOut *sw;
int enabled = 0;
bool enabled = false;
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
if (sw->active) {
enabled = 1;
enabled = true;
break;
}
}
@ -465,7 +460,7 @@ static void audio_detach_capture (HWVoiceOut *hw)
static int audio_attach_capture (HWVoiceOut *hw)
{
AudioState *s = hw->s;
AudioBackend *s = hw->s;
CaptureVoiceOut *cap;
audio_detach_capture (hw);
@ -480,7 +475,7 @@ static int audio_attach_capture (HWVoiceOut *hw)
sw = &sc->sw;
sw->hw = hw_cap;
sw->info = hw->info;
sw->empty = 1;
sw->empty = true;
sw->active = hw->enabled;
sw->vol = nominal_volume;
sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq);
@ -803,7 +798,7 @@ static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info)
/*
* Timer
*/
static int audio_is_timer_needed(AudioState *s)
static int audio_is_timer_needed(AudioBackend *s)
{
HWVoiceIn *hwi = NULL;
HWVoiceOut *hwo = NULL;
@ -821,7 +816,7 @@ static int audio_is_timer_needed(AudioState *s)
return 0;
}
static void audio_reset_timer (AudioState *s)
static void audio_reset_timer(AudioBackend *s)
{
if (audio_is_timer_needed(s)) {
timer_mod_anticipate_ns(s->ts,
@ -843,7 +838,7 @@ static void audio_reset_timer (AudioState *s)
static void audio_timer (void *opaque)
{
int64_t now, diff;
AudioState *s = opaque;
AudioBackend *s = opaque;
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
diff = now - s->timer_last;
@ -916,7 +911,7 @@ int AUD_get_buffer_size_out(SWVoiceOut *sw)
return sw->hw->samples * sw->hw->info.bytes_per_frame;
}
void AUD_set_active_out (SWVoiceOut *sw, int on)
void AUD_set_active_out(SWVoiceOut *sw, bool on)
{
HWVoiceOut *hw;
@ -926,14 +921,14 @@ void AUD_set_active_out (SWVoiceOut *sw, int on)
hw = sw->hw;
if (sw->active != on) {
AudioState *s = sw->s;
AudioBackend *s = sw->s;
SWVoiceOut *temp_sw;
SWVoiceCap *sc;
if (on) {
hw->pending_disable = 0;
if (!hw->enabled) {
hw->enabled = 1;
hw->enabled = true;
if (s->vm_running) {
if (hw->pcm_ops->enable_out) {
hw->pcm_ops->enable_out(hw, true);
@ -964,7 +959,7 @@ void AUD_set_active_out (SWVoiceOut *sw, int on)
}
}
void AUD_set_active_in (SWVoiceIn *sw, int on)
void AUD_set_active_in(SWVoiceIn *sw, bool on)
{
HWVoiceIn *hw;
@ -974,12 +969,12 @@ void AUD_set_active_in (SWVoiceIn *sw, int on)
hw = sw->hw;
if (sw->active != on) {
AudioState *s = sw->s;
AudioBackend *s = sw->s;
SWVoiceIn *temp_sw;
if (on) {
if (!hw->enabled) {
hw->enabled = 1;
hw->enabled = true;
if (s->vm_running) {
if (hw->pcm_ops->enable_in) {
hw->pcm_ops->enable_in(hw, true);
@ -998,7 +993,7 @@ void AUD_set_active_in (SWVoiceIn *sw, int on)
}
if (nb_active == 1) {
hw->enabled = 0;
hw->enabled = false;
if (hw->pcm_ops->enable_in) {
hw->pcm_ops->enable_in(hw, false);
}
@ -1142,7 +1137,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live)
return clipped;
}
static void audio_run_out (AudioState *s)
static void audio_run_out(AudioBackend *s)
{
HWVoiceOut *hw = NULL;
SWVoiceOut *sw;
@ -1157,8 +1152,8 @@ static void audio_run_out (AudioState *s)
sw = hw->sw_head.lh_first;
if (hw->pending_disable) {
hw->enabled = 0;
hw->pending_disable = 0;
hw->enabled = false;
hw->pending_disable = false;
if (hw->pcm_ops->enable_out) {
hw->pcm_ops->enable_out(hw, false);
}
@ -1211,13 +1206,13 @@ static void audio_run_out (AudioState *s)
#ifdef DEBUG_OUT
dolog ("Disabling voice\n");
#endif
hw->enabled = 0;
hw->pending_disable = 0;
hw->enabled = false;
hw->pending_disable = false;
if (hw->pcm_ops->enable_out) {
hw->pcm_ops->enable_out(hw, false);
}
for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
sc->sw.active = 0;
sc->sw.active = false;
audio_recalc_and_notify_capture (sc->cap);
}
continue;
@ -1262,7 +1257,7 @@ static void audio_run_out (AudioState *s)
sw->total_hw_samples_mixed -= played;
if (!sw->total_hw_samples_mixed) {
sw->empty = 1;
sw->empty = true;
}
}
}
@ -1296,7 +1291,7 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
return conv;
}
static void audio_run_in (AudioState *s)
static void audio_run_in(AudioBackend *s)
{
HWVoiceIn *hw = NULL;
@ -1344,7 +1339,7 @@ static void audio_run_in (AudioState *s)
}
}
static void audio_run_capture (AudioState *s)
static void audio_run_capture(AudioBackend *s)
{
CaptureVoiceOut *cap;
@ -1391,7 +1386,7 @@ static void audio_run_capture (AudioState *s)
}
}
void audio_run(AudioState *s, const char *msg)
void audio_run(AudioBackend *s, const char *msg)
{
audio_run_out(s);
audio_run_in(s);
@ -1564,41 +1559,40 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size)
return total;
}
static int audio_driver_init(AudioState *s, struct audio_driver *drv,
Audiodev *dev, Error **errp)
static bool audio_driver_init(AudioBackend *s, struct audio_driver *drv,
Audiodev *dev, Error **errp)
{
Error *local_err = NULL;
s->drv_opaque = drv->init(dev, &local_err);
if (s->drv_opaque) {
if (!drv->pcm_ops->get_buffer_in) {
drv->pcm_ops->get_buffer_in = audio_generic_get_buffer_in;
drv->pcm_ops->put_buffer_in = audio_generic_put_buffer_in;
}
if (!drv->pcm_ops->get_buffer_out) {
drv->pcm_ops->get_buffer_out = audio_generic_get_buffer_out;
drv->pcm_ops->put_buffer_out = audio_generic_put_buffer_out;
}
audio_init_nb_voices_out(s, drv, 1);
audio_init_nb_voices_in(s, drv, 0);
s->drv = drv;
return 0;
} else {
if (local_err) {
error_propagate(errp, local_err);
} else {
error_setg(errp, "Could not init `%s' audio driver", drv->name);
}
return -1;
s->drv_opaque = drv->init(dev, errp);
if (!s->drv_opaque) {
return false;
}
if (!drv->pcm_ops->get_buffer_in) {
drv->pcm_ops->get_buffer_in = audio_generic_get_buffer_in;
drv->pcm_ops->put_buffer_in = audio_generic_put_buffer_in;
}
if (!drv->pcm_ops->get_buffer_out) {
drv->pcm_ops->get_buffer_out = audio_generic_get_buffer_out;
drv->pcm_ops->put_buffer_out = audio_generic_put_buffer_out;
}
audio_init_nb_voices_out(s, drv, 1);
audio_init_nb_voices_in(s, drv, 0);
s->drv = drv;
if (dev->timer_period <= 0) {
s->period_ticks = 1;
} else {
s->period_ticks = dev->timer_period * (int64_t)SCALE_US;
}
return true;
}
static void audio_vm_change_state_handler (void *opaque, bool running,
RunState state)
{
AudioState *s = opaque;
AudioBackend *s = opaque;
HWVoiceOut *hwo = NULL;
HWVoiceIn *hwi = NULL;
@ -1617,8 +1611,26 @@ static void audio_vm_change_state_handler (void *opaque, bool running,
audio_reset_timer (s);
}
static void free_audio_state(AudioState *s)
static const VMStateDescription vmstate_audio;
static void audio_be_init(Object *obj)
{
AudioBackend *s = AUDIO_BACKEND(obj);
QLIST_INIT(&s->hw_head_out);
QLIST_INIT(&s->hw_head_in);
QLIST_INIT(&s->cap_head);
s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
s->vmse = qemu_add_vm_change_state_handler(audio_vm_change_state_handler, s);
assert(s->vmse != NULL);
vmstate_register_any(NULL, &vmstate_audio, s);
}
static void audio_be_finalize(Object *obj)
{
AudioBackend *s = AUDIO_BACKEND(obj);
HWVoiceOut *hwo, *hwon;
HWVoiceIn *hwi, *hwin;
@ -1664,17 +1676,24 @@ static void free_audio_state(AudioState *s)
s->ts = NULL;
}
g_free(s);
if (s->vmse) {
qemu_del_vm_change_state_handler(s->vmse);
s->vmse = NULL;
}
vmstate_unregister(NULL, &vmstate_audio, s);
}
static Object *get_audiodevs_root(void)
{
return object_get_container("audiodevs");
}
void audio_cleanup(void)
{
default_audio_state = NULL;
while (!QTAILQ_EMPTY(&audio_states)) {
AudioState *s = QTAILQ_FIRST(&audio_states);
QTAILQ_REMOVE(&audio_states, s, list);
free_audio_state(s);
}
default_audio_be = NULL;
object_unparent(get_audiodevs_root());
}
static bool vmstate_audio_needed(void *opaque)
@ -1712,7 +1731,7 @@ void audio_create_default_audiodevs(void)
visit_type_Audiodev(v, NULL, &dev, &error_fatal);
visit_free(v);
audio_define_default(dev, &error_abort);
audio_add_default_audiodev(dev, &error_abort);
}
}
}
@ -1723,26 +1742,14 @@ void audio_create_default_audiodevs(void)
* if dev == NULL => legacy implicit initialization, return the already created
* state or create a new one
*/
static AudioState *audio_init(Audiodev *dev, Error **errp)
static AudioBackend *audio_init(Audiodev *dev, Error **errp)
{
static bool atexit_registered;
int done = 0;
const char *drvname;
VMChangeStateEntry *vmse;
AudioState *s;
AudioBackend *s;
struct audio_driver *driver;
s = g_new0(AudioState, 1);
QLIST_INIT (&s->hw_head_out);
QLIST_INIT (&s->hw_head_in);
QLIST_INIT (&s->cap_head);
if (!atexit_registered) {
atexit(audio_cleanup);
atexit_registered = true;
}
s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
s = AUDIO_BACKEND(object_new(TYPE_AUDIO_BACKEND));
if (dev) {
/* -audiodev option */
@ -1750,7 +1757,7 @@ static AudioState *audio_init(Audiodev *dev, Error **errp)
drvname = AudiodevDriver_str(dev->driver);
driver = audio_driver_lookup(drvname);
if (driver) {
done = !audio_driver_init(s, driver, dev, errp);
done = audio_driver_init(s, driver, dev, errp);
} else {
error_setg(errp, "Unknown audio driver `%s'", drvname);
}
@ -1758,7 +1765,7 @@ static AudioState *audio_init(Audiodev *dev, Error **errp)
goto out;
}
} else {
assert(!default_audio_state);
assert(!default_audio_be);
for (;;) {
AudiodevListEntry *e = QSIMPLEQ_FIRST(&default_audiodevs);
if (!e) {
@ -1770,7 +1777,7 @@ static AudioState *audio_init(Audiodev *dev, Error **errp)
g_free(e);
drvname = AudiodevDriver_str(dev->driver);
driver = audio_driver_lookup(drvname);
if (!audio_driver_init(s, driver, dev, NULL)) {
if (audio_driver_init(s, driver, dev, NULL)) {
break;
}
qapi_free_Audiodev(dev);
@ -1778,33 +1785,22 @@ static AudioState *audio_init(Audiodev *dev, Error **errp)
}
}
if (dev->timer_period <= 0) {
s->period_ticks = 1;
} else {
s->period_ticks = dev->timer_period * (int64_t)SCALE_US;
if (!object_property_try_add_child(get_audiodevs_root(), dev->id, OBJECT(s), errp)) {
goto out;
}
vmse = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
if (!vmse) {
dolog ("warning: Could not register change state handler\n"
"(Audio can continue looping even after stopping the VM)\n");
}
QTAILQ_INSERT_TAIL(&audio_states, s, list);
QLIST_INIT (&s->card_head);
vmstate_register_any(NULL, &vmstate_audio, s);
object_unref(s);
return s;
out:
free_audio_state(s);
object_unref(s);
return NULL;
}
AudioState *audio_get_default_audio_state(Error **errp)
AudioBackend *audio_get_default_audio_be(Error **errp)
{
if (!default_audio_state) {
default_audio_state = audio_init(NULL, errp);
if (!default_audio_state) {
if (!default_audio_be) {
default_audio_be = audio_init(NULL, errp);
if (!default_audio_be) {
if (!QSIMPLEQ_EMPTY(&audiodevs)) {
error_append_hint(errp, "Perhaps you wanted to use -audio or set audiodev=%s?\n",
QSIMPLEQ_FIRST(&audiodevs)->dev->id);
@ -1812,35 +1808,27 @@ AudioState *audio_get_default_audio_state(Error **errp)
}
}
return default_audio_state;
return default_audio_be;
}
bool AUD_register_card (const char *name, QEMUSoundCard *card, Error **errp)
bool AUD_backend_check(AudioBackend **be, Error **errp)
{
if (!card->state) {
card->state = audio_get_default_audio_state(errp);
if (!card->state) {
assert(be != NULL);
if (!*be) {
*be = audio_get_default_audio_be(errp);
if (!*be) {
return false;
}
}
card->name = g_strdup (name);
memset (&card->entries, 0, sizeof (card->entries));
QLIST_INSERT_HEAD(&card->state->card_head, card, entries);
return true;
}
void AUD_remove_card (QEMUSoundCard *card)
{
QLIST_REMOVE (card, entries);
g_free (card->name);
}
static struct audio_pcm_ops capture_pcm_ops;
CaptureVoiceOut *AUD_add_capture(
AudioState *s,
AudioBackend *s,
struct audsettings *as,
struct audio_capture_ops *ops,
void *cb_opaque
@ -1952,13 +1940,7 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
}
}
void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol)
{
Volume vol = { .mute = mute, .channels = 2, .vol = { lvol, rvol } };
audio_set_volume_out(sw, &vol);
}
void audio_set_volume_out(SWVoiceOut *sw, Volume *vol)
void AUD_set_volume_out(SWVoiceOut *sw, Volume *vol)
{
if (sw) {
HWVoiceOut *hw = sw->hw;
@ -1974,13 +1956,7 @@ void audio_set_volume_out(SWVoiceOut *sw, Volume *vol)
}
}
void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol)
{
Volume vol = { .mute = mute, .channels = 2, .vol = { lvol, rvol } };
audio_set_volume_in(sw, &vol);
}
void audio_set_volume_in(SWVoiceIn *sw, Volume *vol)
void AUD_set_volume_in(SWVoiceIn *sw, Volume *vol)
{
if (sw) {
HWVoiceIn *hw = sw->hw;
@ -2142,10 +2118,10 @@ void audio_parse_option(const char *opt)
visit_type_Audiodev(v, NULL, &dev, &error_fatal);
visit_free(v);
audio_define(dev);
audio_add_audiodev(dev);
}
void audio_define(Audiodev *dev)
void audio_add_audiodev(Audiodev *dev)
{
AudiodevListEntry *e;
@ -2156,7 +2132,7 @@ void audio_define(Audiodev *dev)
QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next);
}
void audio_define_default(Audiodev *dev, Error **errp)
void audio_add_default_audiodev(Audiodev *dev, Error **errp)
{
AudiodevListEntry *e;
@ -2182,7 +2158,7 @@ audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo)
.freq = pdo->frequency,
.nchannels = pdo->channels,
.fmt = pdo->format,
.endianness = AUDIO_HOST_ENDIANNESS,
.endianness = HOST_BIG_ENDIAN,
};
}
@ -2235,24 +2211,40 @@ int audio_buffer_bytes(AudiodevPerDirectionOptions *pdo,
audioformat_bytes_per_sample(as->fmt);
}
AudioState *audio_state_by_name(const char *name, Error **errp)
AudioBackend *audio_be_by_name(const char *name, Error **errp)
{
AudioState *s;
QTAILQ_FOREACH(s, &audio_states, list) {
assert(s->dev);
if (strcmp(name, s->dev->id) == 0) {
return s;
}
Object *obj = object_resolve_path_component(get_audiodevs_root(), name);
if (!obj) {
error_setg(errp, "audiodev '%s' not found", name);
return NULL;
} else {
return AUDIO_BACKEND(obj);
}
error_setg(errp, "audiodev '%s' not found", name);
return NULL;
}
const char *audio_get_id(QEMUSoundCard *card)
#ifdef CONFIG_GIO
bool audio_be_set_dbus_server(AudioBackend *be,
GDBusObjectManagerServer *server,
bool p2p,
Error **errp)
{
if (card->state) {
assert(card->state->dev);
return card->state->dev->id;
assert(be != NULL);
if (!be->drv->set_dbus_server) {
error_setg(errp, "Audiodev '%s' is not compatible with DBus", be->dev->id);
return false;
}
return be->drv->set_dbus_server(be, server, p2p, errp);
}
#endif
const char *audio_be_get_id(AudioBackend *be)
{
if (be) {
assert(be->dev);
return be->dev->id;
} else {
return "";
}
@ -2320,3 +2312,20 @@ AudiodevList *qmp_query_audiodevs(Error **errp)
}
return ret;
}
static const TypeInfo audio_be_info = {
.name = TYPE_AUDIO_BACKEND,
.parent = TYPE_OBJECT,
.instance_size = sizeof(AudioBackend),
.instance_init = audio_be_init,
.instance_finalize = audio_be_finalize,
.abstract = false, /* TODO: subclass drivers and make it abstract */
.class_size = sizeof(AudioBackendClass),
};
static void register_types(void)
{
type_register_static(&audio_be_info);
}
type_init(register_types);

View file

@ -1,185 +0,0 @@
/*
* QEMU Audio subsystem header
*
* Copyright (c) 2003-2005 Vassili Karpov (malc)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef QEMU_AUDIO_H
#define QEMU_AUDIO_H
#include "qemu/queue.h"
#include "qapi/qapi-types-audio.h"
#include "hw/qdev-properties.h"
#include "hw/qdev-properties-system.h"
typedef void (*audio_callback_fn) (void *opaque, int avail);
#if HOST_BIG_ENDIAN
#define AUDIO_HOST_ENDIANNESS 1
#else
#define AUDIO_HOST_ENDIANNESS 0
#endif
typedef struct audsettings {
int freq;
int nchannels;
AudioFormat fmt;
int endianness;
} audsettings;
audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo);
int audioformat_bytes_per_sample(AudioFormat fmt);
int audio_buffer_frames(AudiodevPerDirectionOptions *pdo,
audsettings *as, int def_usecs);
int audio_buffer_samples(AudiodevPerDirectionOptions *pdo,
audsettings *as, int def_usecs);
int audio_buffer_bytes(AudiodevPerDirectionOptions *pdo,
audsettings *as, int def_usecs);
typedef enum {
AUD_CNOTIFY_ENABLE,
AUD_CNOTIFY_DISABLE
} audcnotification_e;
struct audio_capture_ops {
void (*notify) (void *opaque, audcnotification_e cmd);
void (*capture) (void *opaque, const void *buf, int size);
void (*destroy) (void *opaque);
};
struct capture_ops {
void (*info) (void *opaque);
void (*destroy) (void *opaque);
};
typedef struct CaptureState {
void *opaque;
struct capture_ops ops;
QLIST_ENTRY (CaptureState) entries;
} CaptureState;
typedef struct SWVoiceOut SWVoiceOut;
typedef struct CaptureVoiceOut CaptureVoiceOut;
typedef struct SWVoiceIn SWVoiceIn;
typedef struct AudioState AudioState;
typedef struct QEMUSoundCard {
char *name;
AudioState *state;
QLIST_ENTRY (QEMUSoundCard) entries;
} QEMUSoundCard;
typedef struct QEMUAudioTimeStamp {
uint64_t old_ts;
} QEMUAudioTimeStamp;
void AUD_vlog (const char *cap, const char *fmt, va_list ap) G_GNUC_PRINTF(2, 0);
void AUD_log (const char *cap, const char *fmt, ...) G_GNUC_PRINTF(2, 3);
bool AUD_register_card (const char *name, QEMUSoundCard *card, Error **errp);
void AUD_remove_card (QEMUSoundCard *card);
CaptureVoiceOut *AUD_add_capture(
AudioState *s,
struct audsettings *as,
struct audio_capture_ops *ops,
void *opaque
);
void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque);
SWVoiceOut *AUD_open_out (
QEMUSoundCard *card,
SWVoiceOut *sw,
const char *name,
void *callback_opaque,
audio_callback_fn callback_fn,
struct audsettings *settings
);
void AUD_close_out (QEMUSoundCard *card, SWVoiceOut *sw);
size_t AUD_write (SWVoiceOut *sw, void *pcm_buf, size_t size);
int AUD_get_buffer_size_out (SWVoiceOut *sw);
void AUD_set_active_out (SWVoiceOut *sw, int on);
int AUD_is_active_out (SWVoiceOut *sw);
void AUD_init_time_stamp_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts);
uint64_t AUD_get_elapsed_usec_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts);
void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol);
void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol);
#define AUDIO_MAX_CHANNELS 16
typedef struct Volume {
bool mute;
int channels;
uint8_t vol[AUDIO_MAX_CHANNELS];
} Volume;
void audio_set_volume_out(SWVoiceOut *sw, Volume *vol);
void audio_set_volume_in(SWVoiceIn *sw, Volume *vol);
SWVoiceIn *AUD_open_in (
QEMUSoundCard *card,
SWVoiceIn *sw,
const char *name,
void *callback_opaque,
audio_callback_fn callback_fn,
struct audsettings *settings
);
void AUD_close_in (QEMUSoundCard *card, SWVoiceIn *sw);
size_t AUD_read (SWVoiceIn *sw, void *pcm_buf, size_t size);
void AUD_set_active_in (SWVoiceIn *sw, int on);
int AUD_is_active_in (SWVoiceIn *sw);
void AUD_init_time_stamp_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts);
uint64_t AUD_get_elapsed_usec_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts);
static inline void *advance (void *p, int incr)
{
uint8_t *d = p;
return (d + incr);
}
int wav_start_capture(AudioState *state, CaptureState *s, const char *path,
int freq, int bits, int nchannels);
void audio_cleanup(void);
void audio_sample_to_uint64(const void *samples, int pos,
uint64_t *left, uint64_t *right);
void audio_sample_from_uint64(void *samples, int pos,
uint64_t left, uint64_t right);
void audio_define(Audiodev *audio);
void audio_define_default(Audiodev *dev, Error **errp);
void audio_parse_option(const char *opt);
void audio_create_default_audiodevs(void);
void audio_init_audiodevs(void);
void audio_help(void);
AudioState *audio_state_by_name(const char *name, Error **errp);
AudioState *audio_get_default_audio_state(Error **errp);
const char *audio_get_id(QEMUSoundCard *card);
#define DEFINE_AUDIO_PROPERTIES(_s, _f) \
DEFINE_PROP_AUDIODEV("audiodev", _s, _f)
#endif /* QEMU_AUDIO_H */

View file

@ -29,12 +29,20 @@
#define FLOAT_MIXENG
/* #define RECIPROCAL */
#endif
#include "qemu/audio.h"
#include "qemu/audio-capture.h"
#include "mixeng.h"
#ifdef CONFIG_GIO
#include <gio/gio.h>
#endif
void G_GNUC_PRINTF(2, 0)
AUD_vlog(const char *cap, const char *fmt, va_list ap);
void G_GNUC_PRINTF(2, 3)
AUD_log(const char *cap, const char *fmt, ...);
struct audio_pcm_ops;
struct audio_callback {
@ -53,7 +61,7 @@ struct audio_pcm_info {
int swap_endianness;
};
typedef struct AudioState AudioState;
typedef struct AudioBackend AudioBackend;
typedef struct SWVoiceCap SWVoiceCap;
typedef struct STSampleBuffer {
@ -62,10 +70,10 @@ typedef struct STSampleBuffer {
} STSampleBuffer;
typedef struct HWVoiceOut {
AudioState *s;
int enabled;
AudioBackend *s;
bool enabled;
int poll_mode;
int pending_disable;
bool pending_disable;
struct audio_pcm_info info;
f_sample *clip;
@ -83,8 +91,8 @@ typedef struct HWVoiceOut {
} HWVoiceOut;
typedef struct HWVoiceIn {
AudioState *s;
int enabled;
AudioBackend *s;
bool enabled;
int poll_mode;
struct audio_pcm_info info;
@ -104,15 +112,14 @@ typedef struct HWVoiceIn {
} HWVoiceIn;
struct SWVoiceOut {
QEMUSoundCard *card;
AudioState *s;
AudioBackend *s;
struct audio_pcm_info info;
t_sample *conv;
STSampleBuffer resample_buf;
void *rate;
size_t total_hw_samples_mixed;
int active;
int empty;
bool active;
bool empty;
HWVoiceOut *hw;
char *name;
struct mixeng_volume vol;
@ -121,9 +128,8 @@ struct SWVoiceOut {
};
struct SWVoiceIn {
QEMUSoundCard *card;
AudioState *s;
int active;
AudioBackend *s;
bool active;
struct audio_pcm_info info;
void *rate;
size_t total_hw_samples_acquired;
@ -139,11 +145,13 @@ struct SWVoiceIn {
typedef struct audio_driver audio_driver;
struct audio_driver {
const char *name;
const char *descr;
void *(*init) (Audiodev *, Error **);
void (*fini) (void *);
#ifdef CONFIG_GIO
void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager, bool p2p);
bool (*set_dbus_server)(AudioBackend *be,
GDBusObjectManagerServer *manager,
bool p2p,
Error **errp);
#endif
struct audio_pcm_ops *pcm_ops;
int max_voices_out;
@ -187,6 +195,23 @@ struct audio_pcm_ops {
void (*volume_in)(HWVoiceIn *hw, Volume *vol);
};
audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo);
int audioformat_bytes_per_sample(AudioFormat fmt);
int audio_buffer_frames(AudiodevPerDirectionOptions *pdo,
audsettings *as, int def_usecs);
int audio_buffer_samples(AudiodevPerDirectionOptions *pdo,
audsettings *as, int def_usecs);
int audio_buffer_bytes(AudiodevPerDirectionOptions *pdo,
audsettings *as, int def_usecs);
static inline void *advance(void *p, size_t incr)
{
return (uint8_t *)p + incr;
}
int wav_start_capture(AudioBackend *state, CaptureState *s, const char *path,
int freq, int bits, int nchannels);
void audio_generic_run_buffer_in(HWVoiceIn *hw);
void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size);
void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size);
@ -216,13 +241,14 @@ struct SWVoiceCap {
QLIST_ENTRY (SWVoiceCap) entries;
};
typedef struct AudioState {
typedef struct AudioBackend {
Object parent;
struct audio_driver *drv;
Audiodev *dev;
void *drv_opaque;
QEMUTimer *ts;
QLIST_HEAD (card_listhead, QEMUSoundCard) card_head;
QLIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in;
QLIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out;
QLIST_HEAD (cap_listhead, CaptureVoiceOut) cap_head;
@ -233,9 +259,8 @@ typedef struct AudioState {
bool timer_running;
uint64_t timer_last;
QTAILQ_ENTRY(AudioState) list;
} AudioState;
VMChangeStateEntry *vmse;
} AudioBackend;
extern const struct mixeng_volume nominal_volume;
@ -248,7 +273,7 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len);
int audio_bug (const char *funcname, int cond);
void audio_run(AudioState *s, const char *msg);
void audio_run(AudioBackend *s, const char *msg);
const char *audio_application_name(void);

View file

@ -36,7 +36,7 @@
#define HWBUF hw->conv_buf
#endif
static void glue(audio_init_nb_voices_, TYPE)(AudioState *s,
static void glue(audio_init_nb_voices_, TYPE)(AudioBackend *s,
struct audio_driver *drv, int min_voices)
{
int max_voices = glue (drv->max_voices_, TYPE);
@ -166,10 +166,10 @@ static int glue (audio_pcm_sw_init_, TYPE) (
audio_pcm_init_info (&sw->info, as);
sw->hw = hw;
sw->active = 0;
sw->active = false;
#ifdef DAC
sw->total_hw_samples_mixed = 0;
sw->empty = 1;
sw->empty = true;
#endif
if (sw->info.is_float) {
@ -221,7 +221,7 @@ static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw)
static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp)
{
HW *hw = *hwp;
AudioState *s = hw->s;
AudioBackend *s = hw->s;
if (!hw->sw_head.lh_first) {
#ifdef DAC
@ -236,12 +236,12 @@ static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp)
}
}
static HW *glue(audio_pcm_hw_find_any_, TYPE)(AudioState *s, HW *hw)
static HW *glue(audio_pcm_hw_find_any_, TYPE)(AudioBackend *s, HW *hw)
{
return hw ? hw->entries.le_next : glue (s->hw_head_, TYPE).lh_first;
}
static HW *glue(audio_pcm_hw_find_any_enabled_, TYPE)(AudioState *s, HW *hw)
static HW *glue(audio_pcm_hw_find_any_enabled_, TYPE)(AudioBackend *s, HW *hw)
{
while ((hw = glue(audio_pcm_hw_find_any_, TYPE)(s, hw))) {
if (hw->enabled) {
@ -251,7 +251,7 @@ static HW *glue(audio_pcm_hw_find_any_enabled_, TYPE)(AudioState *s, HW *hw)
return NULL;
}
static HW *glue(audio_pcm_hw_find_specific_, TYPE)(AudioState *s, HW *hw,
static HW *glue(audio_pcm_hw_find_specific_, TYPE)(AudioBackend *s, HW *hw,
struct audsettings *as)
{
while ((hw = glue(audio_pcm_hw_find_any_, TYPE)(s, hw))) {
@ -262,7 +262,7 @@ static HW *glue(audio_pcm_hw_find_specific_, TYPE)(AudioState *s, HW *hw,
return NULL;
}
static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioBackend *s,
struct audsettings *as)
{
HW *hw;
@ -398,7 +398,7 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev)
abort();
}
static HW *glue(audio_pcm_hw_add_, TYPE)(AudioState *s, struct audsettings *as)
static HW *glue(audio_pcm_hw_add_, TYPE)(AudioBackend *s, struct audsettings *as)
{
HW *hw;
AudiodevPerDirectionOptions *pdo = glue(audio_get_pdo_, TYPE)(s->dev);
@ -424,7 +424,7 @@ static HW *glue(audio_pcm_hw_add_, TYPE)(AudioState *s, struct audsettings *as)
}
static SW *glue(audio_pcm_create_voice_pair_, TYPE)(
AudioState *s,
AudioBackend *s,
const char *sw_name,
struct audsettings *as
)
@ -473,11 +473,11 @@ static void glue (audio_close_, TYPE) (SW *sw)
g_free (sw);
}
void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
void glue(AUD_close_, TYPE)(AudioBackend *be, SW *sw)
{
if (sw) {
if (audio_bug(__func__, !card)) {
dolog ("card=%p\n", card);
if (audio_bug(__func__, !be)) {
dolog("backend=%p\n", be);
return;
}
@ -486,7 +486,7 @@ void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
}
SW *glue (AUD_open_, TYPE) (
QEMUSoundCard *card,
AudioBackend *be,
SW *sw,
const char *name,
void *callback_opaque ,
@ -494,16 +494,15 @@ SW *glue (AUD_open_, TYPE) (
struct audsettings *as
)
{
AudioState *s;
AudioBackend *s = be;
AudiodevPerDirectionOptions *pdo;
if (audio_bug(__func__, !card || !name || !callback_fn || !as)) {
dolog ("card=%p name=%p callback_fn=%p as=%p\n",
card, name, callback_fn, as);
if (audio_bug(__func__, !be || !name || !callback_fn || !as)) {
dolog("backend=%p name=%p callback_fn=%p as=%p\n",
be, name, callback_fn, as);
goto fail;
}
s = card->state;
pdo = glue(audio_get_pdo_, TYPE)(s->dev);
ldebug ("open %s, freq %d, nchannels %d, fmt %d\n",
@ -524,7 +523,7 @@ SW *glue (AUD_open_, TYPE) (
}
if (!pdo->fixed_settings && sw) {
glue (AUD_close_, TYPE) (card, sw);
glue(AUD_close_, TYPE)(be, sw);
sw = NULL;
}
@ -548,7 +547,6 @@ SW *glue (AUD_open_, TYPE) (
}
}
sw->card = card;
sw->vol = nominal_volume;
sw->callback.fn = callback_fn;
sw->callback.opaque = callback_opaque;
@ -562,11 +560,11 @@ SW *glue (AUD_open_, TYPE) (
return sw;
fail:
glue (AUD_close_, TYPE) (card, sw);
glue(AUD_close_, TYPE)(be, sw);
return NULL;
}
int glue (AUD_is_active_, TYPE) (SW *sw)
bool glue(AUD_is_active_, TYPE)(SW *sw)
{
return sw ? sw->active : 0;
}

View file

@ -7,7 +7,7 @@
#include <mmreg.h>
#include <mmsystem.h>
#include "audio.h"
#include "qemu/audio.h"
#include "audio_int.h"
#include "audio_win_int.h"

View file

@ -28,7 +28,7 @@
#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "audio.h"
#include "qemu/audio.h"
#define AUDIO_CAP "coreaudio"
#include "audio_int.h"
@ -664,7 +664,6 @@ static struct audio_pcm_ops coreaudio_pcm_ops = {
static struct audio_driver coreaudio_audio_driver = {
.name = "coreaudio",
.descr = "CoreAudio http://developer.apple.com/audio/coreaudio.html",
.init = coreaudio_audio_init,
.fini = coreaudio_audio_fini,
.pcm_ops = &coreaudio_pcm_ops,

View file

@ -24,9 +24,7 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qemu/host-utils.h"
#include "qemu/module.h"
#include "qemu/timer.h"
#include "qemu/dbus.h"
#ifdef G_OS_UNIX
@ -37,7 +35,7 @@
#include "ui/dbus-display1.h"
#define AUDIO_CAP "dbus"
#include "audio.h"
#include "qemu/audio.h"
#include "audio_int.h"
#include "trace.h"
@ -460,7 +458,7 @@ listener_in_vanished_cb(GDBusConnection *connection,
}
static gboolean
dbus_audio_register_listener(AudioState *s,
dbus_audio_register_listener(AudioBackend *s,
GDBusMethodInvocation *invocation,
#ifdef G_OS_UNIX
GUnixFDList *fd_list,
@ -617,7 +615,7 @@ dbus_audio_register_listener(AudioState *s,
}
static gboolean
dbus_audio_register_out_listener(AudioState *s,
dbus_audio_register_out_listener(AudioBackend *s,
GDBusMethodInvocation *invocation,
#ifdef G_OS_UNIX
GUnixFDList *fd_list,
@ -633,7 +631,7 @@ dbus_audio_register_out_listener(AudioState *s,
}
static gboolean
dbus_audio_register_in_listener(AudioState *s,
dbus_audio_register_in_listener(AudioBackend *s,
GDBusMethodInvocation *invocation,
#ifdef G_OS_UNIX
GUnixFDList *fd_list,
@ -647,8 +645,11 @@ dbus_audio_register_in_listener(AudioState *s,
arg_listener, false);
}
static void
dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server, bool p2p)
static bool
dbus_audio_set_server(AudioBackend *s,
GDBusObjectManagerServer *server,
bool p2p,
Error **errp)
{
DBusAudio *da = s->drv_opaque;
@ -671,6 +672,8 @@ dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server, bool p2p)
g_dbus_object_skeleton_add_interface(G_DBUS_OBJECT_SKELETON(da->audio),
G_DBUS_INTERFACE_SKELETON(da->iface));
g_dbus_object_manager_server_export(da->server, da->audio);
return true;
}
static struct audio_pcm_ops dbus_pcm_ops = {
@ -692,7 +695,6 @@ static struct audio_pcm_ops dbus_pcm_ops = {
static struct audio_driver dbus_audio_driver = {
.name = "dbus",
.descr = "Timer based audio exposed with DBus interface",
.init = dbus_audio_init,
.fini = dbus_audio_fini,
.set_dbus_server = dbus_audio_set_server,

View file

@ -27,12 +27,12 @@
*/
#include "qemu/osdep.h"
#include "audio.h"
#include "qemu/audio.h"
#define AUDIO_CAP "dsound"
#include "audio_int.h"
#include "qemu/host-utils.h"
#include "qemu/module.h"
#include "qapi/error.h"
#include <windows.h>
#include <mmsystem.h>
@ -64,162 +64,154 @@ typedef struct {
dsound *s;
} DSoundVoiceIn;
static void dsound_log_hresult (HRESULT hr)
static const char *dserror(HRESULT hr)
{
const char *str = "BUG";
switch (hr) {
case DS_OK:
str = "The method succeeded";
break;
return "The method succeeded";
#ifdef DS_NO_VIRTUALIZATION
case DS_NO_VIRTUALIZATION:
str = "The buffer was created, but another 3D algorithm was substituted";
break;
return "The buffer was created, but another 3D algorithm was substituted";
#endif
#ifdef DS_INCOMPLETE
case DS_INCOMPLETE:
str = "The method succeeded, but not all the optional effects were obtained";
break;
return "The method succeeded, but not all the optional effects were obtained";
#endif
#ifdef DSERR_ACCESSDENIED
case DSERR_ACCESSDENIED:
str = "The request failed because access was denied";
break;
return "The request failed because access was denied";
#endif
#ifdef DSERR_ALLOCATED
case DSERR_ALLOCATED:
str = "The request failed because resources, "
"such as a priority level, were already in use "
"by another caller";
break;
return "The request failed because resources, "
"such as a priority level, were already in use "
"by another caller";
#endif
#ifdef DSERR_ALREADYINITIALIZED
case DSERR_ALREADYINITIALIZED:
str = "The object is already initialized";
break;
return "The object is already initialized";
#endif
#ifdef DSERR_BADFORMAT
case DSERR_BADFORMAT:
str = "The specified wave format is not supported";
break;
return "The specified wave format is not supported";
#endif
#ifdef DSERR_BADSENDBUFFERGUID
case DSERR_BADSENDBUFFERGUID:
str = "The GUID specified in an audiopath file "
"does not match a valid mix-in buffer";
break;
return "The GUID specified in an audiopath file "
"does not match a valid mix-in buffer";
#endif
#ifdef DSERR_BUFFERLOST
case DSERR_BUFFERLOST:
str = "The buffer memory has been lost and must be restored";
break;
return "The buffer memory has been lost and must be restored";
#endif
#ifdef DSERR_BUFFERTOOSMALL
case DSERR_BUFFERTOOSMALL:
str = "The buffer size is not great enough to "
"enable effects processing";
break;
return "The buffer size is not great enough to "
"enable effects processing";
#endif
#ifdef DSERR_CONTROLUNAVAIL
case DSERR_CONTROLUNAVAIL:
str = "The buffer control (volume, pan, and so on) "
"requested by the caller is not available. "
"Controls must be specified when the buffer is created, "
"using the dwFlags member of DSBUFFERDESC";
break;
return "The buffer control (volume, pan, and so on) "
"requested by the caller is not available. "
"Controls must be specified when the buffer is created, "
"using the dwFlags member of DSBUFFERDESC";
#endif
#ifdef DSERR_DS8_REQUIRED
case DSERR_DS8_REQUIRED:
str = "A DirectSound object of class CLSID_DirectSound8 or later "
"is required for the requested functionality. "
"For more information, see IDirectSound8 Interface";
break;
return "A DirectSound object of class CLSID_DirectSound8 or later "
"is required for the requested functionality. "
"For more information, see IDirectSound8 Interface";
#endif
#ifdef DSERR_FXUNAVAILABLE
case DSERR_FXUNAVAILABLE:
str = "The effects requested could not be found on the system, "
"or they are in the wrong order or in the wrong location; "
"for example, an effect expected in hardware "
"was found in software";
break;
return "The effects requested could not be found on the system, "
"or they are in the wrong order or in the wrong location; "
"for example, an effect expected in hardware "
"was found in software";
#endif
#ifdef DSERR_GENERIC
case DSERR_GENERIC:
str = "An undetermined error occurred inside the DirectSound subsystem";
break;
return "An undetermined error occurred inside the DirectSound subsystem";
#endif
#ifdef DSERR_INVALIDCALL
case DSERR_INVALIDCALL:
str = "This function is not valid for the current state of this object";
break;
return "This function is not valid for the current state of this object";
#endif
#ifdef DSERR_INVALIDPARAM
case DSERR_INVALIDPARAM:
str = "An invalid parameter was passed to the returning function";
break;
return "An invalid parameter was passed to the returning function";
#endif
#ifdef DSERR_NOAGGREGATION
case DSERR_NOAGGREGATION:
str = "The object does not support aggregation";
break;
return "The object does not support aggregation";
#endif
#ifdef DSERR_NODRIVER
case DSERR_NODRIVER:
str = "No sound driver is available for use, "
"or the given GUID is not a valid DirectSound device ID";
break;
return "No sound driver is available for use, "
"or the given GUID is not a valid DirectSound device ID";
#endif
#ifdef DSERR_NOINTERFACE
case DSERR_NOINTERFACE:
str = "The requested COM interface is not available";
break;
return "The requested COM interface is not available";
#endif
#ifdef DSERR_OBJECTNOTFOUND
case DSERR_OBJECTNOTFOUND:
str = "The requested object was not found";
break;
return "The requested object was not found";
#endif
#ifdef DSERR_OTHERAPPHASPRIO
case DSERR_OTHERAPPHASPRIO:
str = "Another application has a higher priority level, "
return "Another application has a higher priority level, "
"preventing this call from succeeding";
break;
#endif
#ifdef DSERR_OUTOFMEMORY
case DSERR_OUTOFMEMORY:
str = "The DirectSound subsystem could not allocate "
return "The DirectSound subsystem could not allocate "
"sufficient memory to complete the caller's request";
break;
#endif
#ifdef DSERR_PRIOLEVELNEEDED
case DSERR_PRIOLEVELNEEDED:
str = "A cooperative level of DSSCL_PRIORITY or higher is required";
break;
return "A cooperative level of DSSCL_PRIORITY or higher is required";
#endif
#ifdef DSERR_SENDLOOP
case DSERR_SENDLOOP:
str = "A circular loop of send effects was detected";
break;
return "A circular loop of send effects was detected";
#endif
#ifdef DSERR_UNINITIALIZED
case DSERR_UNINITIALIZED:
str = "The Initialize method has not been called "
"or has not been called successfully "
"before other methods were called";
break;
return "The Initialize method has not been called "
"or has not been called successfully "
"before other methods were called";
#endif
#ifdef DSERR_UNSUPPORTED
case DSERR_UNSUPPORTED:
str = "The function called is not supported at this time";
break;
return "The function called is not supported at this time";
#endif
default:
AUD_log (AUDIO_CAP, "Reason: Unknown (HRESULT 0x%lx)\n", hr);
return;
return NULL;
}
AUD_log (AUDIO_CAP, "Reason: %s\n", str);
}
static void dserror_set(Error **errp, HRESULT hr, const char *msg)
{
const char *str = dserror(hr);
if (str) {
error_setg(errp, "%s: %s", msg, str);
} else {
error_setg(errp, "%s: Unknown (HRESULT: 0x%lx)", msg, hr);
}
}
static void dsound_log_hresult(HRESULT hr)
{
const char *str = dserror(hr);
if (str) {
AUD_log (AUDIO_CAP, "Reason: %s\n", str);
} else {
AUD_log (AUDIO_CAP, "Reason: Unknown (HRESULT: 0x%lx)\n", hr);
}
}
static void G_GNUC_PRINTF (2, 3) dsound_logerr (
@ -359,27 +351,6 @@ static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb,
dsound_unlock_out (dsb, p1, p2, blen1, blen2);
}
static int dsound_set_cooperative_level(dsound *s)
{
HRESULT hr;
HWND hwnd;
hwnd = GetDesktopWindow();
hr = IDirectSound_SetCooperativeLevel (
s->dsound,
hwnd,
DSSCL_PRIORITY
);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not set cooperative level for window %p\n",
hwnd);
return -1;
}
return 0;
}
static void dsound_enable_out(HWVoiceOut *hw, bool enable)
{
HRESULT hr;
@ -621,7 +592,6 @@ static void dsound_audio_fini (void *opaque)
static void *dsound_audio_init(Audiodev *dev, Error **errp)
{
int err;
HRESULT hr;
dsound *s = g_new0(dsound, 1);
AudiodevDsoundOptions *dso;
@ -637,8 +607,8 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp)
hr = CoInitialize (NULL);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not initialize COM\n");
g_free(s);
dserror_set(errp, hr, "Could not initialize COM");
dsound_audio_fini(s);
return NULL;
}
@ -650,20 +620,15 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp)
(void **) &s->dsound
);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not create DirectSound instance\n");
g_free(s);
dserror_set(errp, hr, "Could not create DirectSound instance");
dsound_audio_fini(s);
return NULL;
}
hr = IDirectSound_Initialize (s->dsound, NULL);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not initialize DirectSound\n");
hr = IDirectSound_Release (s->dsound);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not release DirectSound\n");
}
g_free(s);
dserror_set(errp, hr, "Could not initialize DirectSound");
dsound_audio_fini(s);
return NULL;
}
@ -675,23 +640,26 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp)
(void **) &s->dsound_capture
);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not create DirectSoundCapture instance\n");
} else {
hr = IDirectSoundCapture_Initialize (s->dsound_capture, NULL);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not initialize DirectSoundCapture\n");
hr = IDirectSoundCapture_Release (s->dsound_capture);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not release DirectSoundCapture\n");
}
s->dsound_capture = NULL;
}
dserror_set(errp, hr, "Could not create DirectSoundCapture instance");
dsound_audio_fini(s);
return NULL;
}
err = dsound_set_cooperative_level(s);
if (err) {
dsound_audio_fini (s);
hr = IDirectSoundCapture_Initialize (s->dsound_capture, NULL);
if (FAILED(hr)) {
dserror_set(errp, hr, "Could not initialize DirectSoundCapture");
dsound_audio_fini(s);
return NULL;
}
hr = IDirectSound_SetCooperativeLevel (
s->dsound,
GetDesktopWindow(),
DSSCL_PRIORITY
);
if (FAILED(hr)) {
dserror_set(errp, hr, "Could not set cooperative level");
dsound_audio_fini(s);
return NULL;
}
@ -717,7 +685,6 @@ static struct audio_pcm_ops dsound_pcm_ops = {
static struct audio_driver dsound_audio_driver = {
.name = "dsound",
.descr = "DirectSound http://wikipedia.org/wiki/DirectSound",
.init = dsound_audio_init,
.fini = dsound_audio_fini,
.pcm_ops = &dsound_pcm_ops,

View file

@ -26,7 +26,7 @@
#include "qemu/module.h"
#include "qemu/atomic.h"
#include "qemu/main-loop.h"
#include "audio.h"
#include "qemu/audio.h"
#define AUDIO_CAP "jack"
#include "audio_int.h"
@ -672,7 +672,6 @@ static struct audio_pcm_ops jack_pcm_ops = {
static struct audio_driver jack_driver = {
.name = "jack",
.descr = "JACK Audio Connection Kit Client",
.init = qjack_init,
.fini = qjack_fini,
.pcm_ops = &jack_pcm_ops,

View file

@ -1,12 +1,13 @@
system_ss.add([spice_headers, files('audio.c')])
system_ss.add(files(
'audio-hmp-cmds.c',
'audio.c',
'mixeng.c',
'noaudio.c',
'wavaudio.c',
'wavcapture.c',
))
# deprecated since v10.2, to be removed
system_ss.add(files('audio-hmp-cmds.c', 'wavcapture.c'))
system_ss.add(when: coreaudio, if_true: files('coreaudio.m'))
system_ss.add(when: dsound, if_true: files('dsoundaudio.c', 'audio_win_int.c'))

View file

@ -24,11 +24,13 @@
*/
#include "qemu/osdep.h"
#include "qemu/bswap.h"
#include "qemu/error-report.h"
#include "audio.h"
#include "qemu/audio.h"
#define AUDIO_CAP "mixeng"
#include "audio_int.h"
#ifdef FLOAT_MIXENG
#include "qemu/error-report.h"
#endif
/* 8 bit */
#define ENDIAN_CONVERSION natural
@ -402,7 +404,7 @@ f_sample *mixeng_clip_float[2][2] = {
}
};
void audio_sample_to_uint64(const void *samples, int pos,
void audio_sample_to_uint64(const st_sample *sample, int pos,
uint64_t *left, uint64_t *right)
{
#ifdef FLOAT_MIXENG
@ -410,14 +412,13 @@ void audio_sample_to_uint64(const void *samples, int pos,
"Coreaudio and floating point samples are not supported by replay yet");
abort();
#else
const struct st_sample *sample = samples;
sample += pos;
*left = sample->l;
*right = sample->r;
#endif
}
void audio_sample_from_uint64(void *samples, int pos,
void audio_sample_from_uint64(st_sample *sample, int pos,
uint64_t left, uint64_t right)
{
#ifdef FLOAT_MIXENG
@ -425,7 +426,6 @@ void audio_sample_from_uint64(void *samples, int pos,
"Coreaudio and floating point samples are not supported by replay yet");
abort();
#else
struct st_sample *sample = samples;
sample += pos;
sample->l = left;
sample->r = right;

View file

@ -33,7 +33,6 @@ struct st_sample { mixeng_real l; mixeng_real r; };
struct mixeng_volume { int mute; int64_t r; int64_t l; };
struct st_sample { int64_t l; int64_t r; };
#endif
typedef struct st_sample st_sample;
typedef void (t_sample) (struct st_sample *dst, const void *src, int samples);
typedef void (f_sample) (void *dst, const struct st_sample *src, int samples);

View file

@ -23,10 +23,8 @@
*/
#include "qemu/osdep.h"
#include "qemu/host-utils.h"
#include "qemu/module.h"
#include "audio.h"
#include "qemu/timer.h"
#include "qemu/audio.h"
#define AUDIO_CAP "noaudio"
#include "audio_int.h"
@ -131,7 +129,6 @@ static struct audio_pcm_ops no_pcm_ops = {
static struct audio_driver no_audio_driver = {
.name = "none",
.descr = "Timer based audio emulation",
.init = no_audio_init,
.fini = no_audio_fini,
.pcm_ops = &no_pcm_ops,

View file

@ -29,7 +29,7 @@
#include "qemu/module.h"
#include "qemu/host-utils.h"
#include "qapi/error.h"
#include "audio.h"
#include "qemu/audio.h"
#include "trace.h"
#define AUDIO_CAP "oss"
@ -107,13 +107,13 @@ static void oss_anal_close (int *fdp)
static void oss_helper_poll_out (void *opaque)
{
AudioState *s = opaque;
AudioBackend *s = opaque;
audio_run(s, "oss_poll_out");
}
static void oss_helper_poll_in (void *opaque)
{
AudioState *s = opaque;
AudioBackend *s = opaque;
audio_run(s, "oss_poll_in");
}
@ -131,7 +131,7 @@ static void oss_poll_in (HWVoiceIn *hw)
qemu_set_fd_handler(oss->fd, oss_helper_poll_in, NULL, hw->s);
}
static int aud_to_ossfmt (AudioFormat fmt, int endianness)
static int aud_to_ossfmt(AudioFormat fmt, bool big_endian)
{
switch (fmt) {
case AUDIO_FORMAT_S8:
@ -141,18 +141,10 @@ static int aud_to_ossfmt (AudioFormat fmt, int endianness)
return AFMT_U8;
case AUDIO_FORMAT_S16:
if (endianness) {
return AFMT_S16_BE;
} else {
return AFMT_S16_LE;
}
return big_endian ? AFMT_S16_BE : AFMT_S16_LE;
case AUDIO_FORMAT_U16:
if (endianness) {
return AFMT_U16_BE;
} else {
return AFMT_U16_LE;
}
return big_endian ? AFMT_U16_BE : AFMT_U16_LE;
default:
dolog ("Internal logic error: Bad audio format %d\n", fmt);
@ -493,10 +485,8 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as,
{
OSSVoiceOut *oss = (OSSVoiceOut *) hw;
struct oss_params req, obt;
int endianness;
int err;
int fd;
AudioFormat effective_fmt;
struct audsettings obt_as;
Audiodev *dev = drv_opaque;
AudiodevOssOptions *oopts = &dev->u.oss;
@ -511,7 +501,7 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as,
return -1;
}
err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
err = oss_to_audfmt(obt.fmt, &obt_as.fmt, &obt_as.endianness);
if (err) {
oss_anal_close (&fd);
return -1;
@ -519,8 +509,6 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as,
obt_as.freq = obt.freq;
obt_as.nchannels = obt.nchannels;
obt_as.fmt = effective_fmt;
obt_as.endianness = endianness;
audio_pcm_init_info (&hw->info, &obt_as);
oss->nfrags = obt.nfrags;
@ -628,10 +616,8 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
{
OSSVoiceIn *oss = (OSSVoiceIn *) hw;
struct oss_params req, obt;
int endianness;
int err;
int fd;
AudioFormat effective_fmt;
struct audsettings obt_as;
Audiodev *dev = drv_opaque;
@ -644,7 +630,7 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
return -1;
}
err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
err = oss_to_audfmt(obt.fmt, &obt_as.fmt, &obt_as.endianness);
if (err) {
oss_anal_close (&fd);
return -1;
@ -652,8 +638,6 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
obt_as.freq = obt.freq;
obt_as.nchannels = obt.nchannels;
obt_as.fmt = effective_fmt;
obt_as.endianness = endianness;
audio_pcm_init_info (&hw->info, &obt_as);
oss->nfrags = obt.nfrags;
@ -779,7 +763,6 @@ static struct audio_pcm_ops oss_pcm_ops = {
static struct audio_driver oss_audio_driver = {
.name = "oss",
.descr = "OSS http://www.opensound.com",
.init = oss_audio_init,
.fini = oss_audio_fini,
.pcm_ops = &oss_pcm_ops,

View file

@ -2,7 +2,7 @@
#include "qemu/osdep.h"
#include "qemu/module.h"
#include "audio.h"
#include "qemu/audio.h"
#include "qapi/error.h"
#include <pulse/pulseaudio.h>
@ -316,7 +316,7 @@ unlock_and_fail:
return 0;
}
static pa_sample_format_t audfmt_to_pa (AudioFormat afmt, int endianness)
static pa_sample_format_t audfmt_to_pa(AudioFormat afmt, bool big_endian)
{
int format;
@ -327,14 +327,14 @@ static pa_sample_format_t audfmt_to_pa (AudioFormat afmt, int endianness)
break;
case AUDIO_FORMAT_S16:
case AUDIO_FORMAT_U16:
format = endianness ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE;
format = big_endian ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE;
break;
case AUDIO_FORMAT_S32:
case AUDIO_FORMAT_U32:
format = endianness ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE;
format = big_endian ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE;
break;
case AUDIO_FORMAT_F32:
format = endianness ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE;
format = big_endian ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE;
break;
default:
dolog ("Internal logic error: Bad audio format %d\n", afmt);
@ -747,14 +747,13 @@ static void qpa_volume_in(HWVoiceIn *hw, Volume *vol)
pa_threaded_mainloop_unlock(c->mainloop);
}
static int qpa_validate_per_direction_opts(Audiodev *dev,
AudiodevPaPerDirectionOptions *pdo)
static void qpa_validate_per_direction_opts(Audiodev *dev,
AudiodevPaPerDirectionOptions *pdo)
{
if (!pdo->has_latency) {
pdo->has_latency = true;
pdo->latency = 46440;
}
return 1;
}
/* common */
@ -844,12 +843,8 @@ static void *qpa_audio_init(Audiodev *dev, Error **errp)
}
}
if (!qpa_validate_per_direction_opts(dev, popts->in)) {
return NULL;
}
if (!qpa_validate_per_direction_opts(dev, popts->out)) {
return NULL;
}
qpa_validate_per_direction_opts(dev, popts->in);
qpa_validate_per_direction_opts(dev, popts->out);
g = g_new0(paaudio, 1);
server = popts->server;
@ -927,7 +922,6 @@ static struct audio_pcm_ops qpa_pcm_ops = {
static struct audio_driver pa_audio_driver = {
.name = "pa",
.descr = "http://www.pulseaudio.org/",
.init = qpa_audio_init,
.fini = qpa_audio_fini,
.pcm_ops = &qpa_pcm_ops,

View file

@ -10,7 +10,7 @@
#include "qemu/osdep.h"
#include "qemu/module.h"
#include "audio.h"
#include "qemu/audio.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include <spa/param/audio/format-utils.h>
@ -324,7 +324,7 @@ done_unlock:
}
static int
audfmt_to_pw(AudioFormat fmt, int endianness)
audfmt_to_pw(AudioFormat fmt, bool big_endian)
{
int format;
@ -336,19 +336,19 @@ audfmt_to_pw(AudioFormat fmt, int endianness)
format = SPA_AUDIO_FORMAT_U8;
break;
case AUDIO_FORMAT_S16:
format = endianness ? SPA_AUDIO_FORMAT_S16_BE : SPA_AUDIO_FORMAT_S16_LE;
format = big_endian ? SPA_AUDIO_FORMAT_S16_BE : SPA_AUDIO_FORMAT_S16_LE;
break;
case AUDIO_FORMAT_U16:
format = endianness ? SPA_AUDIO_FORMAT_U16_BE : SPA_AUDIO_FORMAT_U16_LE;
format = big_endian ? SPA_AUDIO_FORMAT_U16_BE : SPA_AUDIO_FORMAT_U16_LE;
break;
case AUDIO_FORMAT_S32:
format = endianness ? SPA_AUDIO_FORMAT_S32_BE : SPA_AUDIO_FORMAT_S32_LE;
format = big_endian ? SPA_AUDIO_FORMAT_S32_BE : SPA_AUDIO_FORMAT_S32_LE;
break;
case AUDIO_FORMAT_U32:
format = endianness ? SPA_AUDIO_FORMAT_U32_BE : SPA_AUDIO_FORMAT_U32_LE;
format = big_endian ? SPA_AUDIO_FORMAT_U32_BE : SPA_AUDIO_FORMAT_U32_LE;
break;
case AUDIO_FORMAT_F32:
format = endianness ? SPA_AUDIO_FORMAT_F32_BE : SPA_AUDIO_FORMAT_F32_LE;
format = big_endian ? SPA_AUDIO_FORMAT_F32_BE : SPA_AUDIO_FORMAT_F32_LE;
break;
default:
dolog("Internal logic error: Bad audio format %d\n", fmt);
@ -838,7 +838,6 @@ static struct audio_pcm_ops qpw_pcm_ops = {
static struct audio_driver pw_audio_driver = {
.name = "pipewire",
.descr = "http://www.pipewire.org/",
.init = qpw_audio_init,
.fini = qpw_audio_fini,
.pcm_ops = &qpw_pcm_ops,

View file

@ -27,7 +27,7 @@
#include <SDL_thread.h>
#include "qemu/module.h"
#include "qapi/error.h"
#include "audio.h"
#include "qemu/audio.h"
#ifndef _WIN32
#ifdef __sun__
@ -338,9 +338,7 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as,
{
SDLVoiceOut *sdl = (SDLVoiceOut *)hw;
SDL_AudioSpec req, obt;
int endianness;
int err;
AudioFormat effective_fmt;
Audiodev *dev = drv_opaque;
AudiodevSdlPerDirectionOptions *spdo = dev->u.sdl.out;
struct audsettings obt_as;
@ -360,7 +358,7 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as,
return -1;
}
err = sdl_to_audfmt(obt.format, &effective_fmt, &endianness);
err = sdl_to_audfmt(obt.format, &obt_as.fmt, &obt_as.endianness);
if (err) {
sdl_close_out(sdl);
return -1;
@ -368,8 +366,6 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as,
obt_as.freq = obt.freq;
obt_as.nchannels = obt.channels;
obt_as.fmt = effective_fmt;
obt_as.endianness = endianness;
audio_pcm_init_info (&hw->info, &obt_as);
hw->samples = (spdo->has_buffer_count ? spdo->buffer_count : 4) *
@ -398,9 +394,7 @@ static int sdl_init_in(HWVoiceIn *hw, audsettings *as, void *drv_opaque)
{
SDLVoiceIn *sdl = (SDLVoiceIn *)hw;
SDL_AudioSpec req, obt;
int endianness;
int err;
AudioFormat effective_fmt;
Audiodev *dev = drv_opaque;
AudiodevSdlPerDirectionOptions *spdo = dev->u.sdl.in;
struct audsettings obt_as;
@ -420,7 +414,7 @@ static int sdl_init_in(HWVoiceIn *hw, audsettings *as, void *drv_opaque)
return -1;
}
err = sdl_to_audfmt(obt.format, &effective_fmt, &endianness);
err = sdl_to_audfmt(obt.format, &obt_as.fmt, &obt_as.endianness);
if (err) {
sdl_close_in(sdl);
return -1;
@ -428,8 +422,6 @@ static int sdl_init_in(HWVoiceIn *hw, audsettings *as, void *drv_opaque)
obt_as.freq = obt.freq;
obt_as.nchannels = obt.channels;
obt_as.fmt = effective_fmt;
obt_as.endianness = endianness;
audio_pcm_init_info(&hw->info, &obt_as);
hw->samples = (spdo->has_buffer_count ? spdo->buffer_count : 4) *
@ -490,7 +482,6 @@ static struct audio_pcm_ops sdl_pcm_ops = {
static struct audio_driver sdl_audio_driver = {
.name = "sdl",
.descr = "SDL http://www.libsdl.org",
.init = sdl_audio_init,
.fini = sdl_audio_fini,
.pcm_ops = &sdl_pcm_ops,

View file

@ -18,7 +18,7 @@
#include <poll.h>
#include <sndio.h>
#include "qemu/main-loop.h"
#include "audio.h"
#include "qemu/audio.h"
#include "trace.h"
#define AUDIO_CAP "sndio"
@ -546,7 +546,6 @@ static struct audio_pcm_ops sndio_pcm_ops = {
static struct audio_driver sndio_audio_driver = {
.name = "sndio",
.descr = "sndio https://sndio.org",
.init = sndio_audio_init,
.fini = sndio_audio_fini,
.pcm_ops = &sndio_pcm_ops,

View file

@ -26,7 +26,7 @@
#include "ui/qemu-spice.h"
#define AUDIO_CAP "spice"
#include "audio.h"
#include "qemu/audio.h"
#include "audio_int.h"
#if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3
@ -102,7 +102,7 @@ static int line_out_init(HWVoiceOut *hw, struct audsettings *as,
#endif
settings.nchannels = SPICE_INTERFACE_PLAYBACK_CHAN;
settings.fmt = AUDIO_FORMAT_S16;
settings.endianness = AUDIO_HOST_ENDIANNESS;
settings.endianness = HOST_BIG_ENDIAN;
audio_pcm_init_info (&hw->info, &settings);
hw->samples = LINE_OUT_SAMPLES;
@ -218,7 +218,7 @@ static int line_in_init(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
#endif
settings.nchannels = SPICE_INTERFACE_RECORD_CHAN;
settings.fmt = AUDIO_FORMAT_S16;
settings.endianness = AUDIO_HOST_ENDIANNESS;
settings.endianness = HOST_BIG_ENDIAN;
audio_pcm_init_info (&hw->info, &settings);
hw->samples = LINE_IN_SAMPLES;
@ -316,7 +316,6 @@ static struct audio_pcm_ops audio_callbacks = {
static struct audio_driver spice_audio_driver = {
.name = "spice",
.descr = "spice audio driver",
.init = spice_audio_init,
.fini = spice_audio_fini,
.pcm_ops = &audio_callbacks,

View file

@ -23,11 +23,8 @@
*/
#include "qemu/osdep.h"
#include "qemu/host-utils.h"
#include "qemu/module.h"
#include "qemu/timer.h"
#include "qapi/opts-visitor.h"
#include "audio.h"
#include "qemu/audio.h"
#define AUDIO_CAP "wav"
#include "audio_int.h"
@ -208,7 +205,6 @@ static struct audio_pcm_ops wav_pcm_ops = {
static struct audio_driver wav_audio_driver = {
.name = "wav",
.descr = "WAV renderer http://wikipedia.org/wiki/WAV",
.init = wav_audio_init,
.fini = wav_audio_fini,
.pcm_ops = &wav_pcm_ops,

View file

@ -1,8 +1,7 @@
#include "qemu/osdep.h"
#include "qemu/qemu-print.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "audio.h"
#include "audio_int.h"
typedef struct {
FILE *f;
@ -104,7 +103,7 @@ static struct capture_ops wav_capture_ops = {
.info = wav_capture_info
};
int wav_start_capture(AudioState *state, CaptureState *s, const char *path,
int wav_start_capture(AudioBackend *state, CaptureState *s, const char *path,
int freq, int bits, int nchannels)
{
WAVState *wav;

View file

@ -169,6 +169,26 @@ Use ``job-finalize`` instead.
This argument has always been ignored.
Human Machine Protocol (HMP) commands
-------------------------------------
``wavcapture`` (since 10.2)
''''''''''''''''''''''''''''
The ``wavcapture`` command is deprecated and will be removed in a future release.
Use ``-audiodev wav`` or your host audio system to capture audio.
``stopcapture`` (since 10.2)
''''''''''''''''''''''''''''
The ``stopcapture`` command is deprecated and will be removed in a future release.
``info`` argument ``capture`` (since 10.2)
''''''''''''''''''''''''''''''''''''''''''
The ``info capture`` command is deprecated and will be removed in a future release.
Host Architectures
------------------

View file

@ -363,18 +363,20 @@ SRST
Show host USB devices.
ERST
/* BEGIN deprecated */
{
.name = "capture",
.args_type = "",
.params = "",
.help = "show capture information",
.help = "show capture information (deprecated)",
.cmd = hmp_info_capture,
},
SRST
``info capture``
Show capture information.
Show capture information (deprecated).
ERST
/* END deprecated */
{
.name = "snapshots",

View file

@ -764,11 +764,12 @@ SRST
ERST
/* BEGIN deprecated */
{
.name = "wavcapture",
.args_type = "path:F,audiodev:s,freq:i?,bits:i?,nchannels:i?",
.params = "path audiodev [frequency [bits [channels]]]",
.help = "capture audio to a wave file (default frequency=44100 bits=16 channels=2)",
.help = "capture audio to a wave file (deprecated, default frequency=44100 bits=16 channels=2)",
.cmd = hmp_wavcapture,
},
SRST
@ -782,13 +783,15 @@ SRST
- Sample rate = 44100 Hz - CD quality
- Bits = 16
- Number of channels = 2 - Stereo
Deprecated.
ERST
{
.name = "stopcapture",
.args_type = "n:i",
.params = "capture index",
.help = "stop capture",
.help = "stop capture (deprecated)",
.cmd = hmp_stopcapture,
},
SRST
@ -797,7 +800,9 @@ SRST
info capture
Deprecated.
ERST
/* END deprecated */
{
.name = "memsave",

View file

@ -27,7 +27,7 @@
#include "hw/irq.h"
#include "hw/sd/sd.h"
#include "qom/object.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "target/arm/cpu-qom.h"
#define TYPE_INTEGRATOR_CM "integrator_core"

View file

@ -37,7 +37,7 @@
#include "qemu/cutils.h"
#include "qom/object.h"
#include "hw/net/mv88w8618_eth.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "qemu/error-report.h"
#include "target/arm/cpu-qom.h"

View file

@ -30,7 +30,7 @@
#include "hw/irq.h"
#include "hw/i2c/arm_sbcon_i2c.h"
#include "hw/sd/sd.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "target/arm/cpu-qom.h"
#define SMP_BOOT_ADDR 0xe0000000

View file

@ -26,7 +26,7 @@
#include "hw/char/pl011.h"
#include "hw/sd/sd.h"
#include "qom/object.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "target/arm/cpu-qom.h"
#include "qemu/log.h"

View file

@ -45,7 +45,7 @@
#include "hw/sd/sd.h"
#include "qobject/qlist.h"
#include "qom/object.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "target/arm/cpu-qom.h"
#define VEXPRESS_BOARD_ID 0x8e0

View file

@ -26,7 +26,7 @@
#include "system/device_tree.h"
#include "qom/object.h"
#include "net/can_emu.h"
#include "audio/audio.h"
#include "qemu/audio.h"
struct XlnxZCU102 {
MachineState parent_obj;

View file

@ -18,8 +18,8 @@
*/
#include "qemu/osdep.h"
#include "hw/audio/soundhw.h"
#include "audio/audio.h"
#include "hw/audio/model.h"
#include "qemu/audio.h"
#include "hw/pci/pci_device.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
@ -120,7 +120,7 @@ typedef struct AC97BusMasterRegs {
struct AC97LinkState {
PCIDevice dev;
QEMUSoundCard card;
AudioBackend *audio_be;
uint32_t glob_cnt;
uint32_t glob_sta;
uint32_t cas;
@ -320,7 +320,7 @@ static void open_voice(AC97LinkState *s, int index, int freq)
switch (index) {
case PI_INDEX:
s->voice_pi = AUD_open_in(
&s->card,
s->audio_be,
s->voice_pi,
"ac97.pi",
s,
@ -331,7 +331,7 @@ static void open_voice(AC97LinkState *s, int index, int freq)
case PO_INDEX:
s->voice_po = AUD_open_out(
&s->card,
s->audio_be,
s->voice_po,
"ac97.po",
s,
@ -342,7 +342,7 @@ static void open_voice(AC97LinkState *s, int index, int freq)
case MC_INDEX:
s->voice_mc = AUD_open_in(
&s->card,
s->audio_be,
s->voice_mc,
"ac97.mc",
s,
@ -355,17 +355,17 @@ static void open_voice(AC97LinkState *s, int index, int freq)
s->invalid_freq[index] = freq;
switch (index) {
case PI_INDEX:
AUD_close_in(&s->card, s->voice_pi);
AUD_close_in(s->audio_be, s->voice_pi);
s->voice_pi = NULL;
break;
case PO_INDEX:
AUD_close_out(&s->card, s->voice_po);
AUD_close_out(s->audio_be, s->voice_po);
s->voice_po = NULL;
break;
case MC_INDEX:
AUD_close_in(&s->card, s->voice_mc);
AUD_close_in(s->audio_be, s->voice_mc);
s->voice_mc = NULL;
break;
}
@ -416,7 +416,7 @@ static void update_combined_volume_out(AC97LinkState *s)
lvol = (lvol * plvol) / 255;
rvol = (rvol * prvol) / 255;
AUD_set_volume_out(s->voice_po, mute, lvol, rvol);
AUD_set_volume_out_lr(s->voice_po, mute, lvol, rvol);
}
static void update_volume_in(AC97LinkState *s)
@ -427,7 +427,7 @@ static void update_volume_in(AC97LinkState *s)
get_volume(mixer_load(s, AC97_Record_Gain_Mute), 0x0f, 0,
&mute, &lvol, &rvol);
AUD_set_volume_in(s->voice_pi, mute, lvol, rvol);
AUD_set_volume_in_lr(s->voice_pi, mute, lvol, rvol);
}
static void set_volume(AC97LinkState *s, int index, uint32_t val)
@ -1275,7 +1275,7 @@ static void ac97_realize(PCIDevice *dev, Error **errp)
AC97LinkState *s = AC97(dev);
uint8_t *c = s->dev.config;
if (!AUD_register_card ("ac97", &s->card, errp)) {
if (!AUD_backend_check (&s->audio_be, errp)) {
return;
}
@ -1320,14 +1320,13 @@ static void ac97_exit(PCIDevice *dev)
{
AC97LinkState *s = AC97(dev);
AUD_close_in(&s->card, s->voice_pi);
AUD_close_out(&s->card, s->voice_po);
AUD_close_in(&s->card, s->voice_mc);
AUD_remove_card(&s->card);
AUD_close_in(s->audio_be, s->voice_pi);
AUD_close_out(s->audio_be, s->voice_po);
AUD_close_in(s->audio_be, s->voice_mc);
}
static const Property ac97_properties[] = {
DEFINE_AUDIO_PROPERTIES(AC97LinkState, card),
DEFINE_AUDIO_PROPERTIES(AC97LinkState, audio_be),
};
static void ac97_class_init(ObjectClass *klass, const void *data)
@ -1362,8 +1361,7 @@ static const TypeInfo ac97_info = {
static void ac97_register_types(void)
{
type_register_static(&ac97_info);
deprecated_register_soundhw("ac97", "Intel 82801AA AC97 Audio",
0, TYPE_AC97);
audio_register_model("ac97", "Intel 82801AA AC97 Audio", TYPE_AC97);
}
type_init(ac97_register_types)

View file

@ -25,8 +25,8 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/module.h"
#include "hw/audio/soundhw.h"
#include "audio/audio.h"
#include "hw/audio/model.h"
#include "qemu/audio.h"
#include "hw/isa/isa.h"
#include "hw/qdev-properties.h"
#include "qemu/error-report.h"
@ -57,7 +57,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(AdlibState, ADLIB)
struct AdlibState {
ISADevice parent_obj;
QEMUSoundCard card;
AudioBackend *audio_be;
uint32_t freq;
uint32_t port;
int ticking[2];
@ -240,7 +240,6 @@ static void Adlib_fini (AdlibState *s)
s->active = 0;
s->enabled = 0;
AUD_remove_card (&s->card);
}
static MemoryRegionPortio adlib_portio_list[] = {
@ -255,7 +254,7 @@ static void adlib_realizefn (DeviceState *dev, Error **errp)
AdlibState *s = ADLIB(dev);
struct audsettings as;
if (!AUD_register_card ("adlib", &s->card, errp)) {
if (!AUD_backend_check(&s->audio_be, errp)) {
return;
}
@ -272,10 +271,10 @@ static void adlib_realizefn (DeviceState *dev, Error **errp)
as.freq = s->freq;
as.nchannels = SHIFT;
as.fmt = AUDIO_FORMAT_S16;
as.endianness = AUDIO_HOST_ENDIANNESS;
as.endianness = HOST_BIG_ENDIAN;
s->voice = AUD_open_out (
&s->card,
s->audio_be,
s->voice,
"adlib",
s,
@ -298,7 +297,7 @@ static void adlib_realizefn (DeviceState *dev, Error **errp)
}
static const Property adlib_properties[] = {
DEFINE_AUDIO_PROPERTIES(AdlibState, card),
DEFINE_AUDIO_PROPERTIES(AdlibState, audio_be),
DEFINE_PROP_UINT32 ("iobase", AdlibState, port, 0x220),
DEFINE_PROP_UINT32 ("freq", AdlibState, freq, 44100),
};
@ -323,7 +322,7 @@ static const TypeInfo adlib_info = {
static void adlib_register_types (void)
{
type_register_static (&adlib_info);
deprecated_register_soundhw("adlib", ADLIB_DESC, 1, TYPE_ADLIB);
audio_register_model("adlib", ADLIB_DESC, TYPE_ADLIB);
}
type_init (adlib_register_types)

View file

@ -15,7 +15,7 @@
#include "qapi/error.h"
#include "hw/sysbus.h"
#include "hw/irq.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "hw/audio/asc.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
@ -489,7 +489,7 @@ static void asc_write(void *opaque, hwaddr addr, uint64_t value,
{
int vol = (value & 0xe0);
AUD_set_volume_out(s->voice, 0, vol, vol);
AUD_set_volume_out_lr(s->voice, 0, vol, vol);
break;
}
}
@ -634,8 +634,6 @@ static void asc_unrealize(DeviceState *dev)
g_free(s->mixbuf);
g_free(s->silentbuf);
AUD_remove_card(&s->card);
}
static void asc_realize(DeviceState *dev, Error **errp)
@ -643,19 +641,18 @@ static void asc_realize(DeviceState *dev, Error **errp)
ASCState *s = ASC(dev);
struct audsettings as;
if (!AUD_register_card("Apple Sound Chip", &s->card, errp)) {
if (!AUD_backend_check(&s->audio_be, errp)) {
return;
}
as.freq = ASC_FREQ;
as.nchannels = 2;
as.fmt = AUDIO_FORMAT_U8;
as.endianness = AUDIO_HOST_ENDIANNESS;
as.endianness = HOST_BIG_ENDIAN;
s->voice = AUD_open_out(&s->card, s->voice, "asc.out", s, asc_out_cb,
s->voice = AUD_open_out(s->audio_be, s->voice, "asc.out", s, asc_out_cb,
&as);
if (!s->voice) {
AUD_remove_card(&s->card);
error_setg(errp, "Initializing audio stream failed");
return;
}
@ -702,7 +699,7 @@ static void asc_init(Object *obj)
}
static const Property asc_properties[] = {
DEFINE_AUDIO_PROPERTIES(ASCState, card),
DEFINE_AUDIO_PROPERTIES(ASCState, audio_be),
DEFINE_PROP_UINT8("asctype", ASCState, type, ASC_TYPE_ASC),
};

View file

@ -23,8 +23,8 @@
*/
#include "qemu/osdep.h"
#include "hw/audio/soundhw.h"
#include "audio/audio.h"
#include "hw/audio/model.h"
#include "qemu/audio.h"
#include "hw/irq.h"
#include "hw/isa/isa.h"
#include "hw/qdev-properties.h"
@ -69,7 +69,7 @@ DECLARE_INSTANCE_CHECKER(CSState, CS4231A,
struct CSState {
ISADevice dev;
QEMUSoundCard card;
AudioBackend *audio_be;
MemoryRegion ioports;
qemu_irq pic;
uint32_t regs[CS_REGS];
@ -305,7 +305,7 @@ static void cs_reset_voices (CSState *s, uint32_t val)
s->tab = ALawDecompressTable;
x_law:
as.fmt = AUDIO_FORMAT_S16;
as.endianness = AUDIO_HOST_ENDIANNESS;
as.endianness = HOST_BIG_ENDIAN;
s->shift = as.nchannels == 2;
break;
@ -328,7 +328,7 @@ static void cs_reset_voices (CSState *s, uint32_t val)
}
s->voice = AUD_open_out (
&s->card,
s->audio_be,
s->voice,
"cs4231a",
s,
@ -678,7 +678,7 @@ static void cs4231a_realizefn (DeviceState *dev, Error **errp)
return;
}
if (!AUD_register_card ("cs4231a", &s->card, errp)) {
if (!AUD_backend_check(&s->audio_be, errp)) {
return;
}
@ -694,7 +694,7 @@ static void cs4231a_realizefn (DeviceState *dev, Error **errp)
}
static const Property cs4231a_properties[] = {
DEFINE_AUDIO_PROPERTIES(CSState, card),
DEFINE_AUDIO_PROPERTIES(CSState, audio_be),
DEFINE_PROP_UINT32 ("iobase", CSState, port, 0x534),
DEFINE_PROP_UINT32 ("irq", CSState, irq, 9),
DEFINE_PROP_UINT32 ("dma", CSState, dma, 3),
@ -723,7 +723,7 @@ static const TypeInfo cs4231a_info = {
static void cs4231a_register_types (void)
{
type_register_static (&cs4231a_info);
deprecated_register_soundhw("cs4231a", "CS4231A", 1, TYPE_CS4231A);
audio_register_model("cs4231a", "CS4231A", TYPE_CS4231A);
}
type_init (cs4231a_register_types)

View file

@ -26,8 +26,8 @@
#define VERBOSE_ES1370 0
#include "qemu/osdep.h"
#include "hw/audio/soundhw.h"
#include "audio/audio.h"
#include "hw/audio/model.h"
#include "qemu/audio.h"
#include "hw/pci/pci_device.h"
#include "migration/vmstate.h"
#include "qemu/cutils.h"
@ -258,7 +258,7 @@ struct chan {
struct ES1370State {
PCIDevice dev;
QEMUSoundCard card;
AudioBackend *audio_be;
MemoryRegion io;
struct chan chan[NB_CHANNELS];
SWVoiceOut *dac_voice[2];
@ -330,10 +330,10 @@ static void es1370_reset (ES1370State *s)
d->scount = 0;
d->leftover = 0;
if (i == ADC_CHANNEL) {
AUD_close_in (&s->card, s->adc_voice);
AUD_close_in(s->audio_be, s->adc_voice);
s->adc_voice = NULL;
} else {
AUD_close_out (&s->card, s->dac_voice[i]);
AUD_close_out(s->audio_be, s->dac_voice[i]);
s->dac_voice[i] = NULL;
}
}
@ -412,7 +412,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl)
if (i == ADC_CHANNEL) {
s->adc_voice =
AUD_open_in (
&s->card,
s->audio_be,
s->adc_voice,
"es1370.adc",
s,
@ -422,7 +422,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl)
} else {
s->dac_voice[i] =
AUD_open_out (
&s->card,
s->audio_be,
s->dac_voice[i],
i ? "es1370.dac2" : "es1370.dac1",
s,
@ -784,12 +784,12 @@ static int es1370_post_load (void *opaque, int version_id)
for (i = 0; i < NB_CHANNELS; ++i) {
if (i == ADC_CHANNEL) {
if (s->adc_voice) {
AUD_close_in (&s->card, s->adc_voice);
AUD_close_in(s->audio_be, s->adc_voice);
s->adc_voice = NULL;
}
} else {
if (s->dac_voice[i]) {
AUD_close_out (&s->card, s->dac_voice[i]);
AUD_close_out(s->audio_be, s->dac_voice[i]);
s->dac_voice[i] = NULL;
}
}
@ -833,7 +833,7 @@ static void es1370_realize(PCIDevice *dev, Error **errp)
ES1370State *s = ES1370(dev);
uint8_t *c = s->dev.config;
if (!AUD_register_card ("es1370", &s->card, errp)) {
if (!AUD_backend_check(&s->audio_be, errp)) {
return;
}
@ -861,15 +861,14 @@ static void es1370_exit(PCIDevice *dev)
int i;
for (i = 0; i < 2; ++i) {
AUD_close_out(&s->card, s->dac_voice[i]);
AUD_close_out(s->audio_be, s->dac_voice[i]);
}
AUD_close_in(&s->card, s->adc_voice);
AUD_remove_card(&s->card);
AUD_close_in(s->audio_be, s->adc_voice);
}
static const Property es1370_properties[] = {
DEFINE_AUDIO_PROPERTIES(ES1370State, card),
DEFINE_AUDIO_PROPERTIES(ES1370State, audio_be),
};
static void es1370_class_init(ObjectClass *klass, const void *data)
@ -905,8 +904,7 @@ static const TypeInfo es1370_info = {
static void es1370_register_types (void)
{
type_register_static (&es1370_info);
deprecated_register_soundhw("es1370", "ENSONIQ AudioPCI ES1370",
0, TYPE_ES1370);
audio_register_model("es1370", "ENSONIQ AudioPCI ES1370", TYPE_ES1370);
}
type_init (es1370_register_types)

View file

@ -25,8 +25,8 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/module.h"
#include "hw/audio/soundhw.h"
#include "audio/audio.h"
#include "hw/audio/model.h"
#include "qemu/audio.h"
#include "hw/irq.h"
#include "hw/isa/isa.h"
#include "hw/qdev-properties.h"
@ -49,7 +49,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(GUSState, GUS)
struct GUSState {
ISADevice dev;
GUSEmuState emu;
QEMUSoundCard card;
AudioBackend *audio_be;
uint32_t freq;
uint32_t port;
int pos, left, shift, irqs;
@ -242,7 +242,7 @@ static void gus_realizefn (DeviceState *dev, Error **errp)
IsaDmaClass *k;
struct audsettings as;
if (!AUD_register_card ("gus", &s->card, errp)) {
if (!AUD_backend_check(&s->audio_be, errp)) {
return;
}
@ -255,10 +255,10 @@ static void gus_realizefn (DeviceState *dev, Error **errp)
as.freq = s->freq;
as.nchannels = 2;
as.fmt = AUDIO_FORMAT_S16;
as.endianness = AUDIO_HOST_ENDIANNESS;
as.endianness = HOST_BIG_ENDIAN;
s->voice = AUD_open_out (
&s->card,
s->audio_be,
NULL,
"gus",
s,
@ -267,7 +267,6 @@ static void gus_realizefn (DeviceState *dev, Error **errp)
);
if (!s->voice) {
AUD_remove_card (&s->card);
error_setg(errp, "No voice");
return;
}
@ -292,7 +291,7 @@ static void gus_realizefn (DeviceState *dev, Error **errp)
}
static const Property gus_properties[] = {
DEFINE_AUDIO_PROPERTIES(GUSState, card),
DEFINE_AUDIO_PROPERTIES(GUSState, audio_be),
DEFINE_PROP_UINT32 ("freq", GUSState, freq, 44100),
DEFINE_PROP_UINT32 ("iobase", GUSState, port, 0x240),
DEFINE_PROP_UINT32 ("irq", GUSState, emu.gusirq, 7),
@ -320,7 +319,7 @@ static const TypeInfo gus_info = {
static void gus_register_types (void)
{
type_register_static (&gus_info);
deprecated_register_soundhw("gus", "Gravis Ultrasound GF1", 1, TYPE_GUS);
audio_register_model("gus", "Gravis Ultrasound GF1", TYPE_GUS);
}
type_init (gus_register_types)

View file

@ -25,7 +25,7 @@
#include "qemu/host-utils.h"
#include "qemu/module.h"
#include "intel-hda-defs.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "trace.h"
#include "qom/object.h"
@ -178,7 +178,7 @@ struct HDAAudioState {
HDACodecDevice hda;
const char *name;
QEMUSoundCard card;
AudioBackend *audio_be;
const desc_codec *desc;
HDAAudioStream st[4];
bool running_compat[16];
@ -466,9 +466,9 @@ static void hda_audio_set_amp(HDAAudioStream *st)
return;
}
if (st->output) {
AUD_set_volume_out(st->voice.out, muted, left, right);
AUD_set_volume_out_lr(st->voice.out, muted, left, right);
} else {
AUD_set_volume_in(st->voice.in, muted, left, right);
AUD_set_volume_in_lr(st->voice.in, muted, left, right);
}
}
@ -491,7 +491,7 @@ static void hda_audio_setup(HDAAudioStream *st)
} else {
cb = hda_audio_compat_output_cb;
}
st->voice.out = AUD_open_out(&st->state->card, st->voice.out,
st->voice.out = AUD_open_out(st->state->audio_be, st->voice.out,
st->node->name, st, cb, &st->as);
} else {
if (use_timer) {
@ -500,7 +500,7 @@ static void hda_audio_setup(HDAAudioStream *st)
} else {
cb = hda_audio_compat_input_cb;
}
st->voice.in = AUD_open_in(&st->state->card, st->voice.in,
st->voice.in = AUD_open_in(st->state->audio_be, st->voice.in,
st->node->name, st, cb, &st->as);
}
}
@ -696,7 +696,7 @@ static void hda_audio_init(HDACodecDevice *hda,
const desc_param *param;
uint32_t i, type;
if (!AUD_register_card("hda", &a->card, errp)) {
if (!AUD_backend_check(&a->audio_be, errp)) {
return;
}
@ -754,12 +754,11 @@ static void hda_audio_exit(HDACodecDevice *hda)
}
timer_free(st->buft);
if (st->output) {
AUD_close_out(&a->card, st->voice.out);
AUD_close_out(a->audio_be, st->voice.out);
} else {
AUD_close_in(&a->card, st->voice.in);
AUD_close_in(a->audio_be, st->voice.in);
}
}
AUD_remove_card(&a->card);
}
static int hda_audio_post_load(void *opaque, int version)
@ -858,7 +857,7 @@ static const VMStateDescription vmstate_hda_audio = {
};
static const Property hda_audio_properties[] = {
DEFINE_AUDIO_PROPERTIES(HDAAudioState, card),
DEFINE_AUDIO_PROPERTIES(HDAAudioState, audio_be),
DEFINE_PROP_UINT32("debug", HDAAudioState, debug, 0),
DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer, true),
DEFINE_PROP_BOOL("use-timer", HDAAudioState, use_timer, true),

View file

@ -21,16 +21,16 @@
#include "hw/pci/pci.h"
#include "hw/qdev-properties.h"
#include "hw/pci/msi.h"
#include "monitor/qdev.h"
#include "qemu/timer.h"
#include "qemu/bitops.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "qemu/error-report.h"
#include "hw/audio/soundhw.h"
#include "hw/audio/model.h"
#include "intel-hda.h"
#include "migration/vmstate.h"
#include "intel-hda-defs.h"
#include "system/dma.h"
#include "qobject/qdict.h"
#include "qapi/error.h"
#include "qom/object.h"
@ -1303,18 +1303,20 @@ static const TypeInfo hda_codec_device_type_info = {
* create intel hda controller with codec attached to it,
* so '-soundhw hda' works.
*/
static int intel_hda_and_codec_init(PCIBus *bus, const char *audiodev)
static void intel_hda_and_codec_init(const char *audiodev)
{
DeviceState *controller;
g_autoptr(QDict) props = qdict_new();
DeviceState *intel_hda, *codec;
BusState *hdabus;
DeviceState *codec;
controller = DEVICE(pci_create_simple(bus, -1, "intel-hda"));
hdabus = QLIST_FIRST(&controller->child_bus);
qdict_put_str(props, "driver", "intel-hda");
intel_hda = qdev_device_add_from_qdict(props, false, &error_fatal);
hdabus = QLIST_FIRST(&intel_hda->child_bus);
codec = qdev_new("hda-duplex");
qdev_prop_set_string(codec, "audiodev", audiodev);
qdev_realize_and_unref(codec, hdabus, &error_fatal);
return 0;
object_unref(intel_hda);
}
static void intel_hda_register_types(void)
@ -1324,7 +1326,7 @@ static void intel_hda_register_types(void)
type_register_static(&intel_hda_info_ich6);
type_register_static(&intel_hda_info_ich9);
type_register_static(&hda_codec_device_type_info);
pci_register_soundhw("hda", "Intel HD Audio", intel_hda_and_codec_init);
audio_register_model_with_cb("hda", "Intel HD Audio", intel_hda_and_codec_init);
}
type_init(intel_hda_register_types)

View file

@ -15,7 +15,7 @@
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "lm4549.h"
#include "migration/vmstate.h"
@ -190,7 +190,7 @@ void lm4549_write(lm4549_state *s,
as.endianness = 0;
s->voice = AUD_open_out(
&s->card,
s->audio_be,
s->voice,
"lm4549.out",
s,
@ -260,7 +260,7 @@ static int lm4549_post_load(void *opaque, int version_id)
as.endianness = 0;
s->voice = AUD_open_out(
&s->card,
s->audio_be,
s->voice,
"lm4549.out",
s,
@ -282,7 +282,7 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque,
struct audsettings as;
/* Register an audio card */
if (!AUD_register_card("lm4549", &s->card, errp)) {
if (!AUD_backend_check(&s->audio_be, errp)) {
return;
}
@ -300,7 +300,7 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque,
as.endianness = 0;
s->voice = AUD_open_out(
&s->card,
s->audio_be,
s->voice,
"lm4549.out",
s,
@ -308,7 +308,7 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque,
&as
);
AUD_set_volume_out(s->voice, 0, 255, 255);
AUD_set_volume_out_lr(s->voice, 0, 255, 255);
s->voice_is_active = 0;

View file

@ -12,7 +12,7 @@
#ifndef HW_LM4549_H
#define HW_LM4549_H
#include "audio/audio.h"
#include "qemu/audio.h"
#include "exec/hwaddr.h"
typedef void (*lm4549_callback)(void *opaque);
@ -21,7 +21,7 @@ typedef void (*lm4549_callback)(void *opaque);
typedef struct {
QEMUSoundCard card;
AudioBackend *audio_be;
SWVoiceOut *voice;
uint32_t voice_is_active;

View file

@ -16,7 +16,7 @@
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "hw/audio/wm8750.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "qapi/error.h"
#include "qemu/module.h"
#include "qom/object.h"

View file

@ -1,4 +1,4 @@
system_ss.add(files('soundhw.c'))
system_ss.add(files('model.c'))
system_ss.add(when: 'CONFIG_AC97', if_true: files('ac97.c'))
system_ss.add(when: 'CONFIG_ADLIB', if_true: files('fmopl.c', 'adlib.c'))
system_ss.add(when: 'CONFIG_ASC', if_true: files('asc.c'))

View file

@ -22,56 +22,50 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
#include "qemu/option.h"
#include "qemu/help_option.h"
#include "hw/qdev-core.h"
#include "monitor/qdev.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "qom/object.h"
#include "hw/qdev-properties.h"
#include "hw/isa/isa.h"
#include "hw/pci/pci.h"
#include "hw/audio/soundhw.h"
#include "hw/audio/model.h"
struct soundhw {
struct audio_model {
const char *name;
const char *descr;
const char *typename;
int isa;
int (*init_pci) (PCIBus *bus, const char *audiodev);
void (*init)(const char *audiodev);
};
static struct soundhw soundhw[9];
static int soundhw_count;
static struct audio_model audio_models[9];
static int audio_models_count;
void pci_register_soundhw(const char *name, const char *descr,
int (*init_pci)(PCIBus *bus, const char *audiodev))
void audio_register_model_with_cb(const char *name, const char *descr,
void (*init_audio_model)(const char *audiodev))
{
assert(soundhw_count < ARRAY_SIZE(soundhw) - 1);
soundhw[soundhw_count].name = name;
soundhw[soundhw_count].descr = descr;
soundhw[soundhw_count].isa = 0;
soundhw[soundhw_count].init_pci = init_pci;
soundhw_count++;
assert(audio_models_count < ARRAY_SIZE(audio_models) - 1);
audio_models[audio_models_count].name = name;
audio_models[audio_models_count].descr = descr;
audio_models[audio_models_count].init = init_audio_model;
audio_models_count++;
}
void deprecated_register_soundhw(const char *name, const char *descr,
int isa, const char *typename)
void audio_register_model(const char *name, const char *descr,
const char *typename)
{
assert(soundhw_count < ARRAY_SIZE(soundhw) - 1);
soundhw[soundhw_count].name = name;
soundhw[soundhw_count].descr = descr;
soundhw[soundhw_count].isa = isa;
soundhw[soundhw_count].typename = typename;
soundhw_count++;
assert(audio_models_count < ARRAY_SIZE(audio_models) - 1);
audio_models[audio_models_count].name = name;
audio_models[audio_models_count].descr = descr;
audio_models[audio_models_count].typename = typename;
audio_models_count++;
}
void audio_print_available_models(void)
{
struct soundhw *c;
struct audio_model *c;
if (soundhw_count) {
if (audio_models_count) {
printf("Valid audio device model names:\n");
for (c = soundhw; c->name; ++c) {
for (c = audio_models; c->name; ++c) {
printf("%-11s %s\n", c->name, c->descr);
}
} else {
@ -80,19 +74,19 @@ void audio_print_available_models(void)
}
}
static struct soundhw *selected = NULL;
static struct audio_model *selected;
static const char *audiodev_id;
void select_soundhw(const char *name, const char *audiodev)
void audio_set_model(const char *name, const char *audiodev)
{
struct soundhw *c;
struct audio_model *c;
if (selected) {
error_report("only one -audio option is allowed");
exit(1);
}
for (c = soundhw; c->name; ++c) {
for (c = audio_models; c->name; ++c) {
if (g_str_equal(c->name, name)) {
selected = c;
audiodev_id = audiodev;
@ -107,36 +101,20 @@ void select_soundhw(const char *name, const char *audiodev)
}
}
void soundhw_init(void)
void audio_model_init(void)
{
struct soundhw *c = selected;
ISABus *isa_bus = (ISABus *) object_resolve_path_type("", TYPE_ISA_BUS, NULL);
PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL);
BusState *bus;
struct audio_model *c = selected;
if (!c) {
return;
}
if (c->isa) {
if (!isa_bus) {
error_report("ISA bus not available for %s", c->name);
exit(1);
}
bus = BUS(isa_bus);
} else {
if (!pci_bus) {
error_report("PCI bus not available for %s", c->name);
exit(1);
}
bus = BUS(pci_bus);
}
if (c->typename) {
DeviceState *dev = qdev_new(c->typename);
BusState *bus = qdev_find_default_bus(DEVICE_GET_CLASS(dev), &error_fatal);
qdev_prop_set_string(dev, "audiodev", audiodev_id);
qdev_realize_and_unref(dev, bus, &error_fatal);
} else {
assert(!c->isa);
c->init_pci(pci_bus, audiodev_id);
c->init(audiodev_id);
}
}

View file

@ -24,8 +24,8 @@
#include "qemu/osdep.h"
#include "hw/isa/isa.h"
#include "hw/audio/soundhw.h"
#include "audio/audio.h"
#include "hw/audio/model.h"
#include "qemu/audio.h"
#include "qemu/module.h"
#include "qemu/timer.h"
#include "qemu/error-report.h"
@ -49,7 +49,7 @@ struct PCSpkState {
MemoryRegion ioport;
uint32_t iobase;
uint8_t sample_buf[PCSPK_BUF_LEN];
QEMUSoundCard card;
AudioBackend *audio_be;
SWVoiceOut *voice;
PITCommonState *pit;
unsigned int pit_count;
@ -123,7 +123,7 @@ static int pcspk_audio_init(PCSpkState *s)
return 0;
}
s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as);
s->voice = AUD_open_out(s->audio_be, s->voice, s_spk, s, pcspk_callback, &as);
if (!s->voice) {
error_report("pcspk: Could not open voice");
return -1;
@ -196,8 +196,9 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp)
isa_register_ioport(isadev, &s->ioport, s->iobase);
if (s->card.state && AUD_register_card(s_spk, &s->card, errp)) {
if (s->audio_be && AUD_backend_check(&s->audio_be, errp)) {
pcspk_audio_init(s);
return;
}
}
@ -221,7 +222,7 @@ static const VMStateDescription vmstate_spk = {
};
static const Property pcspk_properties[] = {
DEFINE_AUDIO_PROPERTIES(PCSpkState, card),
DEFINE_AUDIO_PROPERTIES(PCSpkState, audio_be),
DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, 0x61),
DEFINE_PROP_BOOL("migrate", PCSpkState, migrate, true),
DEFINE_PROP_LINK("pit", PCSpkState, pit, TYPE_PIT_COMMON, PITCommonState *),

View file

@ -626,7 +626,7 @@ static const VMStateDescription vmstate_pl041 = {
};
static const Property pl041_device_properties[] = {
DEFINE_AUDIO_PROPERTIES(PL041State, codec.card),
DEFINE_AUDIO_PROPERTIES(PL041State, codec.audio_be),
/* Non-compact FIFO depth property */
DEFINE_PROP_UINT32("nc_fifo_depth", PL041State, fifo_depth,
DEFAULT_FIFO_DEPTH),

View file

@ -23,8 +23,8 @@
*/
#include "qemu/osdep.h"
#include "hw/audio/soundhw.h"
#include "audio/audio.h"
#include "hw/audio/model.h"
#include "qemu/audio.h"
#include "hw/irq.h"
#include "hw/isa/isa.h"
#include "hw/qdev-properties.h"
@ -54,7 +54,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(SB16State, SB16)
struct SB16State {
ISADevice parent_obj;
QEMUSoundCard card;
AudioBackend *audio_be;
qemu_irq pic;
uint32_t irq;
uint32_t dma;
@ -216,7 +216,7 @@ static void continue_dma8 (SB16State *s)
as.endianness = 0;
s->voice = AUD_open_out (
&s->card,
s->audio_be,
s->voice,
"sb16",
s,
@ -379,7 +379,7 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
as.endianness = 0;
s->voice = AUD_open_out (
&s->card,
s->audio_be,
s->voice,
"sb16",
s,
@ -880,7 +880,7 @@ static void legacy_reset (SB16State *s)
as.endianness = 0;
s->voice = AUD_open_out (
&s->card,
s->audio_be,
s->voice,
"sb16",
s,
@ -1287,7 +1287,7 @@ static int sb16_post_load (void *opaque, int version_id)
SB16State *s = opaque;
if (s->voice) {
AUD_close_out (&s->card, s->voice);
AUD_close_out(s->audio_be, s->voice);
s->voice = NULL;
}
@ -1303,7 +1303,7 @@ static int sb16_post_load (void *opaque, int version_id)
as.endianness = 0;
s->voice = AUD_open_out (
&s->card,
s->audio_be,
s->voice,
"sb16",
s,
@ -1401,7 +1401,7 @@ static void sb16_realizefn (DeviceState *dev, Error **errp)
SB16State *s = SB16 (dev);
IsaDmaClass *k;
if (!AUD_register_card ("sb16", &s->card, errp)) {
if (!AUD_backend_check(&s->audio_be, errp)) {
return;
}
@ -1440,7 +1440,7 @@ static void sb16_realizefn (DeviceState *dev, Error **errp)
}
static const Property sb16_properties[] = {
DEFINE_AUDIO_PROPERTIES(SB16State, card),
DEFINE_AUDIO_PROPERTIES(SB16State, audio_be),
DEFINE_PROP_UINT32 ("version", SB16State, ver, 0x0405), /* 4.5 */
DEFINE_PROP_UINT32 ("iobase", SB16State, port, 0x220),
DEFINE_PROP_UINT32 ("irq", SB16State, irq, 5),
@ -1470,8 +1470,7 @@ static const TypeInfo sb16_info = {
static void sb16_register_types (void)
{
type_register_static (&sb16_info);
deprecated_register_soundhw("sb16", "Creative Sound Blaster 16",
1, TYPE_SB16);
audio_register_model("sb16", "Creative Sound Blaster 16", TYPE_SB16);
}
type_init (sb16_register_types)

View file

@ -53,7 +53,7 @@ static void codec_volume_set_out(ViaAC97State *s)
rvol /= 255;
mute = CODEC_REG(s, AC97_Master_Volume_Mute) >> MUTE_SHIFT;
mute |= CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> MUTE_SHIFT;
AUD_set_volume_out(s->vo, mute, lvol, rvol);
AUD_set_volume_out_lr(s->vo, mute, lvol, rvol);
}
static void codec_reset(ViaAC97State *s)
@ -239,7 +239,7 @@ static void open_voice_out(ViaAC97State *s)
.fmt = s->aur.type & BIT(5) ? AUDIO_FORMAT_S16 : AUDIO_FORMAT_S8,
.endianness = 0,
};
s->vo = AUD_open_out(&s->card, s->vo, "via-ac97.out", s, out_cb, &as);
s->vo = AUD_open_out(s->audio_be, s->vo, "via-ac97.out", s, out_cb, &as);
}
static uint64_t sgd_read(void *opaque, hwaddr addr, unsigned size)
@ -426,7 +426,7 @@ static void via_ac97_realize(PCIDevice *pci_dev, Error **errp)
ViaAC97State *s = VIA_AC97(pci_dev);
Object *o = OBJECT(s);
if (!AUD_register_card ("via-ac97", &s->card, errp)) {
if (!AUD_backend_check(&s->audio_be, errp)) {
return;
}
@ -455,12 +455,11 @@ static void via_ac97_exit(PCIDevice *dev)
{
ViaAC97State *s = VIA_AC97(dev);
AUD_close_out(&s->card, s->vo);
AUD_remove_card(&s->card);
AUD_close_out(s->audio_be, s->vo);
}
static const Property via_ac97_properties[] = {
DEFINE_AUDIO_PROPERTIES(ViaAC97State, card),
DEFINE_AUDIO_PROPERTIES(ViaAC97State, audio_be),
};
static void via_ac97_class_init(ObjectClass *klass, const void *data)

View file

@ -11,7 +11,7 @@
#include "qemu/osdep.h"
#include "qom/object.h"
#include "qapi/error.h"
#include "hw/audio/soundhw.h"
#include "hw/audio/model.h"
#include "hw/virtio/virtio-pci.h"
#include "hw/audio/virtio-snd.h"
@ -71,24 +71,10 @@ static const VirtioPCIDeviceTypeInfo virtio_snd_pci_info = {
.class_init = virtio_snd_pci_class_init,
};
/* Create a Virtio Sound PCI device, so '-audio driver,model=virtio' works. */
static int virtio_snd_pci_init(PCIBus *bus, const char *audiodev)
{
DeviceState *vdev = NULL;
VirtIOSoundPCI *dev = NULL;
vdev = qdev_new(TYPE_VIRTIO_SND_PCI);
assert(vdev);
dev = VIRTIO_SND_PCI(vdev);
qdev_prop_set_string(DEVICE(&dev->vdev), "audiodev", audiodev);
qdev_realize_and_unref(vdev, BUS(bus), &error_fatal);
return 0;
}
static void virtio_snd_pci_register(void)
{
virtio_pci_types_register(&virtio_snd_pci_info);
pci_register_soundhw("virtio", "Virtio Sound", virtio_snd_pci_init);
audio_register_model("virtio", "Virtio Sound", TYPE_VIRTIO_SND_PCI);
}
type_init(virtio_snd_pci_register);

View file

@ -78,7 +78,7 @@ static const VMStateDescription vmstate_virtio_snd = {
};
static const Property virtio_snd_properties[] = {
DEFINE_AUDIO_PROPERTIES(VirtIOSound, card),
DEFINE_AUDIO_PROPERTIES(VirtIOSound, audio_be),
DEFINE_PROP_UINT32("jacks", VirtIOSound, snd_conf.jacks,
VIRTIO_SOUND_JACK_DEFAULT),
DEFINE_PROP_UINT32("streams", VirtIOSound, snd_conf.streams,
@ -391,10 +391,10 @@ static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream)
if (stream) {
virtio_snd_pcm_flush(stream);
if (stream->info.direction == VIRTIO_SND_D_OUTPUT) {
AUD_close_out(&stream->pcm->snd->card, stream->voice.out);
AUD_close_out(stream->pcm->snd->audio_be, stream->voice.out);
stream->voice.out = NULL;
} else if (stream->info.direction == VIRTIO_SND_D_INPUT) {
AUD_close_in(&stream->pcm->snd->card, stream->voice.in);
AUD_close_in(stream->pcm->snd->audio_be, stream->voice.in);
stream->voice.in = NULL;
}
}
@ -457,21 +457,21 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id)
stream->as = as;
if (stream->info.direction == VIRTIO_SND_D_OUTPUT) {
stream->voice.out = AUD_open_out(&s->card,
stream->voice.out = AUD_open_out(s->audio_be,
stream->voice.out,
"virtio-sound.out",
stream,
virtio_snd_pcm_out_cb,
&as);
AUD_set_volume_out(stream->voice.out, 0, 255, 255);
AUD_set_volume_out_lr(stream->voice.out, 0, 255, 255);
} else {
stream->voice.in = AUD_open_in(&s->card,
stream->voice.in = AUD_open_in(s->audio_be,
stream->voice.in,
"virtio-sound.in",
stream,
virtio_snd_pcm_in_cb,
&as);
AUD_set_volume_in(stream->voice.in, 0, 255, 255);
AUD_set_volume_in_lr(stream->voice.in, 0, 255, 255);
}
return cpu_to_le32(VIRTIO_SND_S_OK);
@ -1053,7 +1053,7 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
return;
}
if (!AUD_register_card("virtio-sound", &vsnd->card, errp)) {
if (!AUD_backend_check(&vsnd->audio_be, errp)) {
return;
}
@ -1330,7 +1330,6 @@ static void virtio_snd_unrealize(DeviceState *dev)
g_free(vsnd->pcm);
vsnd->pcm = NULL;
}
AUD_remove_card(&vsnd->card);
qemu_mutex_destroy(&vsnd->cmdq_mutex);
virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_CONTROL]);
virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_EVENT]);

View file

@ -12,7 +12,7 @@
#include "migration/vmstate.h"
#include "qemu/module.h"
#include "hw/audio/wm8750.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "qom/object.h"
#define IN_PORT_N 3
@ -34,7 +34,7 @@ struct WM8750State {
uint8_t i2c_data[2];
int i2c_len;
QEMUSoundCard card;
AudioBackend *audio_be;
SWVoiceIn *adc_voice[IN_PORT_N];
SWVoiceOut *dac_voice[OUT_PORT_N];
int enable;
@ -145,30 +145,30 @@ static void wm8750_vol_update(WM8750State *s)
{
/* FIXME: multiply all volumes by s->invol[2], s->invol[3] */
AUD_set_volume_in(s->adc_voice[0], s->mute,
AUD_set_volume_in_lr(s->adc_voice[0], s->mute,
s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]),
s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]));
AUD_set_volume_in(s->adc_voice[1], s->mute,
AUD_set_volume_in_lr(s->adc_voice[1], s->mute,
s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]),
s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]));
AUD_set_volume_in(s->adc_voice[2], s->mute,
AUD_set_volume_in_lr(s->adc_voice[2], s->mute,
s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]),
s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]));
/* FIXME: multiply all volumes by s->outvol[0], s->outvol[1] */
/* Speaker: LOUT2VOL ROUT2VOL */
AUD_set_volume_out(s->dac_voice[0], s->mute,
AUD_set_volume_out_lr(s->dac_voice[0], s->mute,
s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[4]),
s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[5]));
/* Headphone: LOUT1VOL ROUT1VOL */
AUD_set_volume_out(s->dac_voice[1], s->mute,
AUD_set_volume_out_lr(s->dac_voice[1], s->mute,
s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[2]),
s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[3]));
/* MONOOUT: MONOVOL MONOVOL */
AUD_set_volume_out(s->dac_voice[2], s->mute,
AUD_set_volume_out_lr(s->dac_voice[2], s->mute,
s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[6]),
s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[6]));
}
@ -188,12 +188,12 @@ static void wm8750_set_format(WM8750State *s)
for (i = 0; i < IN_PORT_N; i ++)
if (s->adc_voice[i]) {
AUD_close_in(&s->card, s->adc_voice[i]);
AUD_close_in(s->audio_be, s->adc_voice[i]);
s->adc_voice[i] = NULL;
}
for (i = 0; i < OUT_PORT_N; i ++)
if (s->dac_voice[i]) {
AUD_close_out(&s->card, s->dac_voice[i]);
AUD_close_out(s->audio_be, s->dac_voice[i]);
s->dac_voice[i] = NULL;
}
@ -206,11 +206,11 @@ static void wm8750_set_format(WM8750State *s)
in_fmt.freq = s->adc_hz;
in_fmt.fmt = AUDIO_FORMAT_S16;
s->adc_voice[0] = AUD_open_in(&s->card, s->adc_voice[0],
s->adc_voice[0] = AUD_open_in(s->audio_be, s->adc_voice[0],
CODEC ".input1", s, wm8750_audio_in_cb, &in_fmt);
s->adc_voice[1] = AUD_open_in(&s->card, s->adc_voice[1],
s->adc_voice[1] = AUD_open_in(s->audio_be, s->adc_voice[1],
CODEC ".input2", s, wm8750_audio_in_cb, &in_fmt);
s->adc_voice[2] = AUD_open_in(&s->card, s->adc_voice[2],
s->adc_voice[2] = AUD_open_in(s->audio_be, s->adc_voice[2],
CODEC ".input3", s, wm8750_audio_in_cb, &in_fmt);
/* Setup output */
@ -219,12 +219,12 @@ static void wm8750_set_format(WM8750State *s)
out_fmt.freq = s->dac_hz;
out_fmt.fmt = AUDIO_FORMAT_S16;
s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0],
s->dac_voice[0] = AUD_open_out(s->audio_be, s->dac_voice[0],
CODEC ".speaker", s, wm8750_audio_out_cb, &out_fmt);
s->dac_voice[1] = AUD_open_out(&s->card, s->dac_voice[1],
s->dac_voice[1] = AUD_open_out(s->audio_be, s->dac_voice[1],
CODEC ".headphone", s, wm8750_audio_out_cb, &out_fmt);
/* MONOMIX is also in stereo for simplicity */
s->dac_voice[2] = AUD_open_out(&s->card, s->dac_voice[2],
s->dac_voice[2] = AUD_open_out(s->audio_be, s->dac_voice[2],
CODEC ".monomix", s, wm8750_audio_out_cb, &out_fmt);
/* no sense emulating OUT3 which is a mix of other outputs */
@ -624,7 +624,7 @@ static void wm8750_realize(DeviceState *dev, Error **errp)
{
WM8750State *s = WM8750(dev);
if (!AUD_register_card(CODEC, &s->card, errp)) {
if (!AUD_backend_check(&s->audio_be, errp)) {
return;
}
@ -637,7 +637,6 @@ static void wm8750_fini(I2CSlave *i2c)
WM8750State *s = WM8750(i2c);
wm8750_reset(I2C_SLAVE(s));
AUD_remove_card(&s->card);
g_free(s);
}
#endif
@ -707,7 +706,7 @@ void wm8750_set_bclk_in(void *opaque, int new_hz)
}
static const Property wm8750_properties[] = {
DEFINE_AUDIO_PROPERTIES(WM8750State, card),
DEFINE_AUDIO_PROPERTIES(WM8750State, audio_be),
};
static void wm8750_class_init(ObjectClass *klass, const void *data)

View file

@ -36,7 +36,7 @@
#include "hw/virtio/virtio-net.h"
#include "hw/virtio/virtio-iommu.h"
#include "hw/acpi/generic_event_device.h"
#include "audio/audio.h"
#include "qemu/audio.h"
GlobalProperty hw_compat_10_1[] = {
{ TYPE_ACPI_GED, "x-has-hest-addr", "false" },
@ -760,7 +760,7 @@ static void machine_set_audiodev(Object *obj, const char *value,
{
MachineState *ms = MACHINE(obj);
if (!audio_state_by_name(value, errp)) {
if (!audio_be_by_name(value, errp)) {
return;
}

View file

@ -27,7 +27,7 @@
#include "qemu/error-report.h"
#include "qdev-prop-internal.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "chardev/char-fe.h"
#include "system/block-backend.h"
#include "system/blockdev.h"
@ -487,28 +487,27 @@ static void get_audiodev(Object *obj, Visitor *v, const char* name,
void *opaque, Error **errp)
{
const Property *prop = opaque;
QEMUSoundCard *card = object_field_prop_ptr(obj, prop);
char *p = g_strdup(audio_get_id(card));
AudioBackend **be = object_field_prop_ptr(obj, prop);
g_autofree char *id = g_strdup(audio_be_get_id(*be));
visit_type_str(v, name, &p, errp);
g_free(p);
visit_type_str(v, name, (char **)&id, errp);
}
static void set_audiodev(Object *obj, Visitor *v, const char* name,
void *opaque, Error **errp)
{
const Property *prop = opaque;
QEMUSoundCard *card = object_field_prop_ptr(obj, prop);
AudioState *state;
AudioBackend **be = object_field_prop_ptr(obj, prop);
AudioBackend *state;
g_autofree char *str = NULL;
if (!visit_type_str(v, name, &str, errp)) {
return;
}
state = audio_state_by_name(str, errp);
state = audio_be_by_name(str, errp);
if (state) {
card->state = state;
*be = state;
}
}

View file

@ -1306,7 +1306,7 @@ static void xlnx_dp_realize(DeviceState *dev, Error **errp)
DisplaySurface *surface;
struct audsettings as;
if (!AUD_register_card("xlnx_dp.audio", &s->aud_card, errp)) {
if (!AUD_backend_check(&s->audio_be, errp)) {
return;
}
@ -1328,13 +1328,13 @@ static void xlnx_dp_realize(DeviceState *dev, Error **errp)
as.fmt = AUDIO_FORMAT_S16;
as.endianness = 0;
s->amixer_output_stream = AUD_open_out(&s->aud_card,
s->amixer_output_stream = AUD_open_out(s->audio_be,
s->amixer_output_stream,
"xlnx_dp.audio.out",
s,
xlnx_dp_audio_callback,
&as);
AUD_set_volume_out(s->amixer_output_stream, 0, 255, 255);
AUD_set_volume_out_lr(s->amixer_output_stream, 0, 255, 255);
xlnx_dp_audio_activate(s);
s->vblank = ptimer_init(vblank_hit, s, DP_VBLANK_PTIMER_POLICY);
ptimer_transaction_begin(s->vblank);
@ -1392,7 +1392,7 @@ static void xlnx_dp_reset(DeviceState *dev)
}
static const Property xlnx_dp_device_properties[] = {
DEFINE_AUDIO_PROPERTIES(XlnxDPState, aud_card),
DEFINE_AUDIO_PROPERTIES(XlnxDPState, audio_be),
};
static void xlnx_dp_class_init(ObjectClass *oc, const void *data)

View file

@ -46,7 +46,7 @@
#include "trace.h"
#include "elf.h"
#include "qemu/units.h"
#include "audio/audio.h"
#include "qemu/audio.h"
/* SMP is not enabled, for now */
#define MAX_CPUS 1

View file

@ -35,7 +35,7 @@
#include "hw/usb.h"
#include "migration/vmstate.h"
#include "desc.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "qom/object.h"
static void usb_audio_reinit(USBDevice *dev, unsigned channels);
@ -635,7 +635,7 @@ static uint8_t *streambuf_get(struct streambuf *buf, size_t *len)
struct USBAudioState {
/* qemu interfaces */
USBDevice dev;
QEMUSoundCard card;
AudioBackend *audio_be;
/* state */
struct {
@ -805,7 +805,7 @@ static int usb_audio_set_control(USBAudioState *s, uint8_t attrib,
}
fprintf(stderr, "\n");
}
audio_set_volume_out(s->out.voice, &s->out.vol);
AUD_set_volume_out(s->out.voice, &s->out.vol);
}
return ret;
@ -931,8 +931,7 @@ static void usb_audio_unrealize(USBDevice *dev)
}
usb_audio_set_output_altset(s, ALTSET_OFF);
AUD_close_out(&s->card, s->out.voice);
AUD_remove_card(&s->card);
AUD_close_out(s->audio_be, s->out.voice);
streambuf_fini(&s->out.buf);
}
@ -942,7 +941,7 @@ static void usb_audio_realize(USBDevice *dev, Error **errp)
USBAudioState *s = USB_AUDIO(dev);
int i;
if (!AUD_register_card(TYPE_USB_AUDIO, &s->card, errp)) {
if (!AUD_backend_check(&s->audio_be, errp)) {
return;
}
@ -979,9 +978,9 @@ static void usb_audio_reinit(USBDevice *dev, unsigned channels)
s->out.as.endianness = 0;
streambuf_init(&s->out.buf, s->buffer, s->out.channels);
s->out.voice = AUD_open_out(&s->card, s->out.voice, TYPE_USB_AUDIO,
s->out.voice = AUD_open_out(s->audio_be, s->out.voice, TYPE_USB_AUDIO,
s, output_callback, &s->out.as);
audio_set_volume_out(s->out.voice, &s->out.vol);
AUD_set_volume_out(s->out.voice, &s->out.vol);
AUD_set_active_out(s->out.voice, 0);
}
@ -991,7 +990,7 @@ static const VMStateDescription vmstate_usb_audio = {
};
static const Property usb_audio_properties[] = {
DEFINE_AUDIO_PROPERTIES(USBAudioState, card),
DEFINE_AUDIO_PROPERTIES(USBAudioState, audio_be),
DEFINE_PROP_UINT32("debug", USBAudioState, debug, 0),
DEFINE_PROP_UINT32("buffer", USBAudioState, buffer_user, 0),
DEFINE_PROP_BOOL("multi", USBAudioState, multi, false),

View file

@ -14,7 +14,7 @@
#define HW_AUDIO_ASC_H
#include "hw/sysbus.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#define ASC_FREQ 22257
@ -61,7 +61,7 @@ struct ASCState {
MemoryRegion mem_regs;
MemoryRegion mem_extregs;
QEMUSoundCard card;
AudioBackend *audio_be;
SWVoiceOut *voice;
uint8_t *mixbuf;
int samples;

14
include/hw/audio/model.h Normal file
View file

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef HW_AUDIO_MODEL_H
#define HW_AUDIO_MODEL_H
void audio_register_model_with_cb(const char *name, const char *descr,
void (*init_audio_model)(const char *audiodev));
void audio_register_model(const char *name, const char *descr,
const char *typename);
void audio_model_init(void);
void audio_print_available_models(void);
void audio_set_model(const char *name, const char *audiodev);
#endif

View file

@ -1,13 +0,0 @@
#ifndef HW_SOUNDHW_H
#define HW_SOUNDHW_H
void pci_register_soundhw(const char *name, const char *descr,
int (*init_pci)(PCIBus *bus, const char *audiodev));
void deprecated_register_soundhw(const char *name, const char *descr,
int isa, const char *typename);
void soundhw_init(void);
void audio_print_available_models(void);
void select_soundhw(const char *name, const char *audiodev);
#endif

View file

@ -17,7 +17,7 @@
#define QEMU_VIRTIO_SOUND_H
#include "hw/virtio/virtio.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "standard-headers/linux/virtio_ids.h"
#include "standard-headers/linux/virtio_snd.h"
@ -216,7 +216,7 @@ struct VirtIOSound {
VirtQueue *queues[VIRTIO_SND_VQ_MAX];
uint64_t features;
VirtIOSoundPCM *pcm;
QEMUSoundCard card;
AudioBackend *audio_be;
VMChangeStateEntry *vmstate;
virtio_snd_config snd_conf;
QemuMutex cmdq_mutex;

View file

@ -33,7 +33,7 @@
#include "qemu/fifo8.h"
#include "qemu/units.h"
#include "hw/dma/xlnx_dpdma.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "qom/object.h"
#include "hw/ptimer.h"
@ -84,7 +84,7 @@ struct XlnxDPState {
struct PixmanPlane v_plane;
struct PixmanPlane bout_plane;
QEMUSoundCard aud_card;
AudioBackend *audio_be;
SWVoiceOut *amixer_output_stream;
int16_t audio_buffer_0[AUD_CHBUF_MAX_DEPTH];
int16_t audio_buffer_1[AUD_CHBUF_MAX_DEPTH];

View file

@ -2,7 +2,7 @@
#define HW_VT82C686_H
#include "hw/pci/pci_device.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#define TYPE_VT82C686B_ISA "vt82c686b-isa"
#define TYPE_VT82C686B_USB_UHCI "vt82c686b-usb-uhci"
@ -24,7 +24,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(ViaAC97State, VIA_AC97);
struct ViaAC97State {
PCIDevice dev;
QEMUSoundCard card;
AudioBackend *audio_be;
MemoryRegion sgd;
MemoryRegion fm;
MemoryRegion midi;

View file

@ -87,7 +87,7 @@ extern const PropertyInfo qdev_prop_virtio_gpu_output_list;
.set_default = true)
#define DEFINE_PROP_AUDIODEV(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, qdev_prop_audiodev, QEMUSoundCard)
DEFINE_PROP(_n, _s, _f, qdev_prop_audiodev, AudioBackend *)
#define DEFINE_PROP_UUID_NODEFAULT(_name, _state, _field) \
DEFINE_PROP(_name, _state, _field, qdev_prop_uuid, QemuUUID)

View file

@ -1,6 +1,8 @@
#ifndef MONITOR_QDEV_H
#define MONITOR_QDEV_H
#include "hw/qdev-core.h"
/*** monitor commands ***/
void hmp_info_qtree(Monitor *mon, const QDict *qdict);
@ -11,6 +13,7 @@ int qdev_device_help(QemuOpts *opts);
DeviceState *qdev_device_add(QemuOpts *opts, Error **errp);
DeviceState *qdev_device_add_from_qdict(const QDict *opts,
bool from_json, Error **errp);
BusState *qdev_find_default_bus(DeviceClass *dc, Error **errp);
/**
* qdev_set_id: parent the device and set its id if provided.

View file

@ -0,0 +1,43 @@
/*
* QEMU Audio subsystem
*
* SPDX-License-Identifier: MIT
*/
#ifndef QEMU_AUDIO_CAPTURE_H
#define QEMU_AUDIO_CAPTURE_H
#include "audio.h"
typedef struct CaptureVoiceOut CaptureVoiceOut;
typedef enum {
AUD_CNOTIFY_ENABLE,
AUD_CNOTIFY_DISABLE
} audcnotification_e;
struct audio_capture_ops {
void (*notify) (void *opaque, audcnotification_e cmd);
void (*capture) (void *opaque, const void *buf, int size);
void (*destroy) (void *opaque);
};
struct capture_ops {
void (*info) (void *opaque);
void (*destroy) (void *opaque);
};
typedef struct CaptureState {
void *opaque;
struct capture_ops ops;
QLIST_ENTRY(CaptureState) entries;
} CaptureState;
CaptureVoiceOut *AUD_add_capture(
AudioBackend *be,
struct audsettings *as,
struct audio_capture_ops *ops,
void *opaque
);
void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque);
#endif /* QEMU_AUDIO_CAPTURE_H */

150
include/qemu/audio.h Normal file
View file

@ -0,0 +1,150 @@
/*
* QEMU Audio subsystem header
*
* Copyright (c) 2003-2005 Vassili Karpov (malc)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef QEMU_AUDIO_H
#define QEMU_AUDIO_H
#include "qemu/queue.h"
#include "qapi/qapi-types-audio.h"
#include "hw/qdev-properties-system.h"
#ifdef CONFIG_GIO
#include "gio/gio.h"
#endif
typedef void (*audio_callback_fn) (void *opaque, int avail);
typedef struct audsettings {
int freq;
int nchannels;
AudioFormat fmt;
int endianness;
} audsettings;
typedef struct SWVoiceOut SWVoiceOut;
typedef struct SWVoiceIn SWVoiceIn;
struct AudioBackendClass {
ObjectClass parent_class;
};
typedef struct AudioBackend AudioBackend;
typedef struct QEMUAudioTimeStamp {
uint64_t old_ts;
} QEMUAudioTimeStamp;
bool AUD_backend_check(AudioBackend **be, Error **errp);
SWVoiceOut *AUD_open_out (
AudioBackend *be,
SWVoiceOut *sw,
const char *name,
void *callback_opaque,
audio_callback_fn callback_fn,
struct audsettings *settings
);
void AUD_close_out (AudioBackend *be, SWVoiceOut *sw);
size_t AUD_write (SWVoiceOut *sw, void *pcm_buf, size_t size);
int AUD_get_buffer_size_out (SWVoiceOut *sw);
void AUD_set_active_out(SWVoiceOut *sw, bool on);
bool AUD_is_active_out(SWVoiceOut *sw);
void AUD_init_time_stamp_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts);
uint64_t AUD_get_elapsed_usec_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts);
#define AUDIO_MAX_CHANNELS 16
typedef struct Volume {
bool mute;
int channels;
uint8_t vol[AUDIO_MAX_CHANNELS];
} Volume;
void AUD_set_volume_out(SWVoiceOut *sw, Volume *vol);
void AUD_set_volume_in(SWVoiceIn *sw, Volume *vol);
static inline void
AUD_set_volume_out_lr(SWVoiceOut *sw, bool mut, uint8_t lvol, uint8_t rvol) {
AUD_set_volume_out(sw, &(Volume) {
.mute = mut, .channels = 2, .vol = { lvol, rvol }
});
}
static inline void
AUD_set_volume_in_lr(SWVoiceIn *sw, bool mut, uint8_t lvol, uint8_t rvol) {
AUD_set_volume_in(sw, &(Volume) {
.mute = mut, .channels = 2, .vol = { lvol, rvol }
});
}
SWVoiceIn *AUD_open_in(
AudioBackend *be,
SWVoiceIn *sw,
const char *name,
void *callback_opaque,
audio_callback_fn callback_fn,
struct audsettings *settings
);
void AUD_close_in(AudioBackend *be, SWVoiceIn *sw);
size_t AUD_read (SWVoiceIn *sw, void *pcm_buf, size_t size);
void AUD_set_active_in(SWVoiceIn *sw, bool on);
bool AUD_is_active_in(SWVoiceIn *sw);
void AUD_init_time_stamp_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts);
uint64_t AUD_get_elapsed_usec_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts);
void audio_cleanup(void);
typedef struct st_sample st_sample;
void audio_sample_to_uint64(const st_sample *sample, int pos,
uint64_t *left, uint64_t *right);
void audio_sample_from_uint64(st_sample *sample, int pos,
uint64_t left, uint64_t right);
void audio_add_audiodev(Audiodev *audio);
void audio_add_default_audiodev(Audiodev *dev, Error **errp);
void audio_parse_option(const char *opt);
void audio_create_default_audiodevs(void);
void audio_init_audiodevs(void);
void audio_help(void);
AudioBackend *audio_be_by_name(const char *name, Error **errp);
AudioBackend *audio_get_default_audio_be(Error **errp);
const char *audio_be_get_id(AudioBackend *be);
#ifdef CONFIG_GIO
bool audio_be_set_dbus_server(AudioBackend *be,
GDBusObjectManagerServer *server,
bool p2p,
Error **errp);
#endif
#define DEFINE_AUDIO_PROPERTIES(_s, _f) \
DEFINE_PROP_AUDIODEV("audiodev", _s, _f)
#define TYPE_AUDIO_BACKEND "audio-backend"
OBJECT_DECLARE_TYPE(AudioBackend, AudioBackendClass, AUDIO_BACKEND)
#endif /* QEMU_AUDIO_H */

View file

@ -16,6 +16,7 @@
#include "qapi/qapi-types-run-state.h"
#include "qapi/qapi-types-ui.h"
#include "block/aio.h"
#include "qemu/audio.h"
/* replay clock kinds */
enum ReplayClockKind {
@ -165,7 +166,7 @@ void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
/*! Saves/restores number of played samples of audio out operation. */
void replay_audio_out(size_t *played);
/*! Saves/restores recorded samples of audio in operation. */
void replay_audio_in(size_t *recorded, void *samples, size_t *wpos, size_t size);
void replay_audio_in(size_t *recorded, st_sample *samples, size_t *wpos, size_t size);
/* VM state operations */

View file

@ -1730,6 +1730,7 @@ const char *object_property_get_type(Object *obj, const char *name, Error **errp
}
static const char *const root_containers[] = {
"audiodevs",
"chardevs",
"objects",
"backend"

View file

@ -13,7 +13,7 @@
#include "qemu/error-report.h"
#include "system/replay.h"
#include "replay-internal.h"
#include "audio/audio.h"
#include "qemu/audio.h"
void replay_audio_out(size_t *played)
{
@ -35,7 +35,7 @@ void replay_audio_out(size_t *played)
}
}
void replay_audio_in(size_t *recorded, void *samples, size_t *wpos, size_t size)
void replay_audio_in(size_t *recorded, st_sample *samples, size_t *wpos, size_t size)
{
int pos;
uint64_t left, right;

View file

@ -15,7 +15,7 @@ void replay_input_sync_event(void)
void replay_add_blocker(const char *feature)
{
}
void replay_audio_in(size_t *recorded, void *samples, size_t *wpos, size_t size)
void replay_audio_in(size_t *recorded, st_sample *samples, size_t *wpos, size_t size)
{
}
void replay_audio_out(size_t *played)

View file

@ -264,8 +264,8 @@ def test_initial_includes():
#define SILENT_ES1370
#include "qemu/osdep.h"
#include "hw/audio/soundhw.h"
#include "audio/audio.h"
#include "hw/audio/model.h"
#include "qemu/audio.h"
#include "hw/pci/pci.h"
#include "migration/vmstate.h"
#include "qemu/module.h"

View file

@ -621,6 +621,25 @@ const char *qdev_set_id(DeviceState *dev, char *id, Error **errp)
return prop->name;
}
BusState *qdev_find_default_bus(DeviceClass *dc, Error **errp)
{
BusState *bus = NULL;
assert(dc->bus_type != NULL);
bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
if (!bus) {
error_setg(errp, "No '%s' bus found for device '%s'",
dc->bus_type, object_class_get_name(OBJECT_CLASS(dc)));
return NULL;
}
if (qbus_is_full(bus)) {
error_setg(errp, "A '%s' bus was found but is full", dc->bus_type);
return NULL;
}
return bus;
}
DeviceState *qdev_device_add_from_qdict(const QDict *opts,
bool from_json, Error **errp)
{
@ -657,10 +676,8 @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts,
return NULL;
}
} else if (dc->bus_type != NULL) {
bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
if (!bus || qbus_is_full(bus)) {
error_setg(errp, "No '%s' bus found for device '%s'",
dc->bus_type, driver);
bus = qdev_find_default_bus(dc, errp);
if (!bus) {
return NULL;
}
}

View file

@ -23,7 +23,7 @@
*/
#include "qemu/osdep.h"
#include "audio/audio.h"
#include "qemu/audio.h"
#include "block/block.h"
#include "block/export.h"
#include "chardev/char.h"

View file

@ -86,8 +86,8 @@
#include "migration/snapshot.h"
#include "system/tpm.h"
#include "system/dma.h"
#include "hw/audio/soundhw.h"
#include "audio/audio.h"
#include "hw/audio/model.h"
#include "qemu/audio.h"
#include "system/cpus.h"
#include "system/cpu-timers.h"
#include "exec/icount.h"
@ -2265,7 +2265,7 @@ static void qemu_record_config_group(const char *group, QDict *dict,
Audiodev *dev = NULL;
Visitor *v = qobject_input_visitor_new_keyval(QOBJECT(dict));
if (visit_type_Audiodev(v, NULL, &dev, errp)) {
audio_define(dev);
audio_add_audiodev(dev);
}
visit_free(v);
@ -2732,7 +2732,7 @@ static void qemu_create_cli_devices(void)
{
DeviceOption *opt;
soundhw_init();
audio_model_init();
qemu_opts_foreach(qemu_find_opts("fw_cfg"),
parse_fw_cfg, fw_cfg_find(), &error_fatal);
@ -3087,11 +3087,11 @@ void qemu_init(int argc, char **argv)
visit_type_Audiodev(v, NULL, &dev, &error_fatal);
visit_free(v);
if (model) {
audio_define(dev);
select_soundhw(model, dev->id);
audio_add_audiodev(dev);
audio_set_model(model, dev->id);
g_free(model);
} else {
audio_define_default(dev, &error_fatal);
audio_add_default_audiodev(dev, &error_fatal);
}
break;
}

View file

@ -34,8 +34,7 @@
#include "ui/egl-helpers.h"
#include "ui/egl-context.h"
#endif
#include "audio/audio.h"
#include "audio/audio_int.h"
#include "qemu/audio.h"
#include "qapi/error.h"
#include "trace.h"
@ -220,16 +219,10 @@ dbus_display_complete(UserCreatable *uc, Error **errp)
}
if (dd->audiodev && *dd->audiodev) {
AudioState *audio_state = audio_state_by_name(dd->audiodev, errp);
if (!audio_state) {
AudioBackend *audio_be = audio_be_by_name(dd->audiodev, errp);
if (!audio_be || !audio_be_set_dbus_server(audio_be, dd->server, dd->p2p, errp)) {
return;
}
if (!g_str_equal(audio_state->drv->name, "dbus")) {
error_setg(errp, "Audiodev '%s' is not compatible with DBus",
dd->audiodev);
return;
}
audio_state->drv->set_dbus_server(audio_state, dd->server, dd->p2p);
}
consoles = g_array_new(FALSE, FALSE, sizeof(guint32));

View file

@ -1276,7 +1276,7 @@ static void audio_add(VncState *vs)
ops.destroy = audio_capture_destroy;
ops.capture = audio_capture;
vs->audio_cap = AUD_add_capture(vs->vd->audio_state, &vs->as, &ops, vs);
vs->audio_cap = AUD_add_capture(vs->vd->audio_be, &vs->as, &ops, vs);
if (!vs->audio_cap) {
error_report("Failed to add audio capture");
}
@ -2193,7 +2193,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
send_ext_key_event_ack(vs);
break;
case VNC_ENCODING_AUDIO:
if (vs->vd->audio_state) {
if (vs->vd->audio_be) {
vnc_set_feature(vs, VNC_FEATURE_AUDIO);
send_ext_audio_ack(vs);
}
@ -4236,12 +4236,12 @@ void vnc_display_open(const char *id, Error **errp)
audiodev = qemu_opt_get(opts, "audiodev");
if (audiodev) {
vd->audio_state = audio_state_by_name(audiodev, errp);
if (!vd->audio_state) {
vd->audio_be = audio_be_by_name(audiodev, errp);
if (!vd->audio_be) {
goto fail;
}
} else {
vd->audio_state = audio_get_default_audio_state(NULL);
vd->audio_be = audio_get_default_audio_be(NULL);
}
device_id = qemu_opt_get(opts, "display");

View file

@ -31,7 +31,7 @@
#include "qemu/thread.h"
#include "ui/clipboard.h"
#include "ui/console.h"
#include "audio/audio.h"
#include "qemu/audio-capture.h"
#include "qemu/bitmap.h"
#include "crypto/tlssession.h"
#include "qemu/buffer.h"
@ -184,7 +184,7 @@ struct VncDisplay
VncDisplaySASL sasl;
#endif
AudioState *audio_state;
AudioBackend *audio_be;
VMChangeStateEntry *vmstate_handler_entry;
};