mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
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:
@@ -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
|
||||
|
||||
+8
-29
@@ -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);
|
||||
|
||||
+165
-156
File diff suppressed because it is too large
Load Diff
-185
@@ -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 */
|
||||
+46
-21
@@ -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);
|
||||
|
||||
|
||||
+21
-23
@@ -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"
|
||||
|
||||
|
||||
+1
-2
@@ -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,
|
||||
|
||||
+11
-9
@@ -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,
|
||||
|
||||
+91
-124
@@ -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,
|
||||
|
||||
+1
-2
@@ -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,
|
||||
|
||||
+4
-3
@@ -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'))
|
||||
|
||||
|
||||
+6
-6
@@ -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);
|
||||
|
||||
+1
-4
@@ -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,
|
||||
|
||||
+8
-25
@@ -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,
|
||||
|
||||
+9
-15
@@ -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,
|
||||
|
||||
+7
-8
@@ -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,
|
||||
|
||||
+3
-12
@@ -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,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user