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:
commit
c5d60e5903
79 changed files with 903 additions and 958 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
321
audio/audio.c
321
audio/audio.c
|
|
@ -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);
|
||||
|
|
|
|||
185
audio/audio.h
185
audio/audio.h
|
|
@ -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 */
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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'))
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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'))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 *),
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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
14
include/hw/audio/model.h
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
43
include/qemu/audio-capture.h
Normal file
43
include/qemu/audio-capture.h
Normal 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
150
include/qemu/audio.h
Normal 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 */
|
||||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
14
system/vl.c
14
system/vl.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
13
ui/dbus.c
13
ui/dbus.c
|
|
@ -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));
|
||||
|
|
|
|||
10
ui/vnc.c
10
ui/vnc.c
|
|
@ -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");
|
||||
|
|
|
|||
4
ui/vnc.h
4
ui/vnc.h
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue