audio: fixes and cleanups.

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJcd7MsAAoJEEy22O7T6HE4vsQQAIWS7+gx/zaxoMwoZ0BcPA7T
 TaoROz911srx9XUgQkbZHrYL7k5MSbcU2muwB/S8fGP3KodEZKzDWp7sjewi0yB+
 v8emLhfKVy7aWVIiyyLuSvd0nA0Z38ovNuwOFdAOw4Yd496bhDpKp7qIV9oS7qUB
 xBH46U0mtMVMeCeTH+1CrT+/5ETPNvO0D51VN3Fs+8HL+rYenb8OzTAcxyTANFbb
 CrYf7O/ilEflf0S67yotuPkKILvmOhK9VIC+8keThsPBneUr/KbqvpBKivgGDJy+
 YBa5xhzraysLTNwLL+sLnRPprSsltUYf4GcI+WKiRr92KdCgDomFW/abPQDJtAZ9
 TgsZFBzZ+/FkUz0FtNpfI4anFAQDyfA1qVtpkk1uUMfZCcxaBaPcu8NzHIl62HfE
 l7Mr2AQAm5NqGXEdy4Xu4ZMqkIj3T0JOx5sULyfVgMZIwLSrjjRNB/GwGV23ZTPv
 NfXIPIwxANG2T9SRhPgmCZtQXY7qNlLR97I87ZgKQ7dzod1J4O0Tk+qt0wpHt6o3
 kpOgehtWZRFNGuT1zA6fVUJX942Rcps2lKvY+7hv47HhUgoTl7c0uRnBtcZgerD2
 wOldGeRuS67iy7Pjj2/Ih8lV8Brprb54t7CFrZ259uUlYKJQV4zd9tDdpNLN+bTT
 7UXq+vM3er0Rfw7LvAzz
 =RC1S
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kraxel/tags/audio-20190228-pull-request' into staging

audio: fixes and cleanups.

# gpg: Signature made Thu 28 Feb 2019 10:08:44 GMT
# gpg:                using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/audio-20190228-pull-request:
  audio/sdlaudio: Simplify the sdl_callback function
  audio/sdlaudio: Remove the semaphore code
  audio: don't build alsa and sdl by default on linux
  audio: Do not check for audio_calloc failure
  audio: Use g_strdup_printf instead of manual building a string

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-02-28 16:11:18 +00:00
commit 21ee7686d7
3 changed files with 34 additions and 227 deletions

View File

@ -454,9 +454,7 @@ static void audio_print_options (const char *prefix,
static void audio_process_options (const char *prefix, static void audio_process_options (const char *prefix,
struct audio_option *opt) struct audio_option *opt)
{ {
char *optname; gchar *prefix_upper;
const char qemu_prefix[] = "QEMU_";
size_t preflen, optlen;
if (audio_bug(__func__, !prefix)) { if (audio_bug(__func__, !prefix)) {
dolog ("prefix = NULL\n"); dolog ("prefix = NULL\n");
@ -468,10 +466,10 @@ static void audio_process_options (const char *prefix,
return; return;
} }
preflen = strlen (prefix); prefix_upper = g_utf8_strup(prefix, -1);
for (; opt->name; opt++) { for (; opt->name; opt++) {
size_t len, i; char *optname;
int def; int def;
if (!opt->valp) { if (!opt->valp) {
@ -480,21 +478,7 @@ static void audio_process_options (const char *prefix,
continue; continue;
} }
len = strlen (opt->name); optname = g_strdup_printf("QEMU_%s_%s", prefix_upper, opt->name);
/* len of opt->name + len of prefix + size of qemu_prefix
* (includes trailing zero) + zero + underscore (on behalf of
* sizeof) */
optlen = len + preflen + sizeof (qemu_prefix) + 1;
optname = g_malloc (optlen);
pstrcpy (optname, optlen, qemu_prefix);
/* copy while upper-casing, including trailing zero */
for (i = 0; i <= preflen; ++i) {
optname[i + sizeof (qemu_prefix) - 1] = qemu_toupper(prefix[i]);
}
pstrcat (optname, optlen, "_");
pstrcat (optname, optlen, opt->name);
def = 1; def = 1;
switch (opt->tag) { switch (opt->tag) {
@ -532,6 +516,7 @@ static void audio_process_options (const char *prefix,
*opt->overriddenp = !def; *opt->overriddenp = !def;
g_free (optname); g_free (optname);
} }
g_free(prefix_upper);
} }
static void audio_print_settings (struct audsettings *as) static void audio_print_settings (struct audsettings *as)
@ -826,12 +811,7 @@ static int audio_attach_capture (HWVoiceOut *hw)
SWVoiceOut *sw; SWVoiceOut *sw;
HWVoiceOut *hw_cap = &cap->hw; HWVoiceOut *hw_cap = &cap->hw;
sc = audio_calloc(__func__, 1, sizeof(*sc)); sc = g_malloc0(sizeof(*sc));
if (!sc) {
dolog ("Could not allocate soft capture voice (%zu bytes)\n",
sizeof (*sc));
return -1;
}
sc->cap = cap; sc->cap = cap;
sw = &sc->sw; sw = &sc->sw;
@ -1975,15 +1955,10 @@ CaptureVoiceOut *AUD_add_capture (
if (audio_validate_settings (as)) { if (audio_validate_settings (as)) {
dolog ("Invalid settings were passed when trying to add capture\n"); dolog ("Invalid settings were passed when trying to add capture\n");
audio_print_settings (as); audio_print_settings (as);
goto err0; return NULL;
} }
cb = audio_calloc(__func__, 1, sizeof(*cb)); cb = g_malloc0(sizeof(*cb));
if (!cb) {
dolog ("Could not allocate capture callback information, size %zu\n",
sizeof (*cb));
goto err0;
}
cb->ops = *ops; cb->ops = *ops;
cb->opaque = cb_opaque; cb->opaque = cb_opaque;
@ -1996,12 +1971,7 @@ CaptureVoiceOut *AUD_add_capture (
HWVoiceOut *hw; HWVoiceOut *hw;
CaptureVoiceOut *cap; CaptureVoiceOut *cap;
cap = audio_calloc(__func__, 1, sizeof(*cap)); cap = g_malloc0(sizeof(*cap));
if (!cap) {
dolog ("Could not allocate capture voice, size %zu\n",
sizeof (*cap));
goto err1;
}
hw = &cap->hw; hw = &cap->hw;
QLIST_INIT (&hw->sw_head); QLIST_INIT (&hw->sw_head);
@ -2009,23 +1979,11 @@ CaptureVoiceOut *AUD_add_capture (
/* XXX find a more elegant way */ /* XXX find a more elegant way */
hw->samples = 4096 * 4; hw->samples = 4096 * 4;
hw->mix_buf = audio_calloc(__func__, hw->samples, hw->mix_buf = g_new0(struct st_sample, hw->samples);
sizeof(struct st_sample));
if (!hw->mix_buf) {
dolog ("Could not allocate capture mix buffer (%d samples)\n",
hw->samples);
goto err2;
}
audio_pcm_init_info (&hw->info, as); audio_pcm_init_info (&hw->info, as);
cap->buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); cap->buf = g_malloc0_n(hw->samples, 1 << hw->info.shift);
if (!cap->buf) {
dolog ("Could not allocate capture buffer "
"(%d samples, each %d bytes)\n",
hw->samples, 1 << hw->info.shift);
goto err3;
}
hw->clip = mixeng_clip hw->clip = mixeng_clip
[hw->info.nchannels == 2] [hw->info.nchannels == 2]
@ -2040,15 +1998,6 @@ CaptureVoiceOut *AUD_add_capture (
audio_attach_capture (hw); audio_attach_capture (hw);
} }
return cap; return cap;
err3:
g_free (cap->hw.mix_buf);
err2:
g_free (cap);
err1:
g_free (cb);
err0:
return NULL;
} }
} }

View File

@ -38,14 +38,9 @@
#define AUDIO_CAP "sdl" #define AUDIO_CAP "sdl"
#include "audio_int.h" #include "audio_int.h"
#define USE_SEMAPHORE (SDL_MAJOR_VERSION < 2)
typedef struct SDLVoiceOut { typedef struct SDLVoiceOut {
HWVoiceOut hw; HWVoiceOut hw;
int live; int live;
#if USE_SEMAPHORE
int rpos;
#endif
int decr; int decr;
} SDLVoiceOut; } SDLVoiceOut;
@ -57,10 +52,6 @@ static struct {
static struct SDLAudioState { static struct SDLAudioState {
int exit; int exit;
#if USE_SEMAPHORE
SDL_mutex *mutex;
SDL_sem *sem;
#endif
int initialized; int initialized;
bool driver_created; bool driver_created;
} glob_sdl; } glob_sdl;
@ -77,66 +68,6 @@ static void GCC_FMT_ATTR (1, 2) sdl_logerr (const char *fmt, ...)
AUD_log (AUDIO_CAP, "Reason: %s\n", SDL_GetError ()); AUD_log (AUDIO_CAP, "Reason: %s\n", SDL_GetError ());
} }
static int sdl_lock (SDLAudioState *s, const char *forfn)
{
#if USE_SEMAPHORE
if (SDL_LockMutex (s->mutex)) {
sdl_logerr ("SDL_LockMutex for %s failed\n", forfn);
return -1;
}
#else
SDL_LockAudio();
#endif
return 0;
}
static int sdl_unlock (SDLAudioState *s, const char *forfn)
{
#if USE_SEMAPHORE
if (SDL_UnlockMutex (s->mutex)) {
sdl_logerr ("SDL_UnlockMutex for %s failed\n", forfn);
return -1;
}
#else
SDL_UnlockAudio();
#endif
return 0;
}
static int sdl_post (SDLAudioState *s, const char *forfn)
{
#if USE_SEMAPHORE
if (SDL_SemPost (s->sem)) {
sdl_logerr ("SDL_SemPost for %s failed\n", forfn);
return -1;
}
#endif
return 0;
}
#if USE_SEMAPHORE
static int sdl_wait (SDLAudioState *s, const char *forfn)
{
if (SDL_SemWait (s->sem)) {
sdl_logerr ("SDL_SemWait for %s failed\n", forfn);
return -1;
}
return 0;
}
#endif
static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn)
{
if (sdl_unlock (s, forfn)) {
return -1;
}
return sdl_post (s, forfn);
}
static int aud_to_sdlfmt (audfmt_e fmt) static int aud_to_sdlfmt (audfmt_e fmt)
{ {
switch (fmt) { switch (fmt) {
@ -243,9 +174,9 @@ static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
static void sdl_close (SDLAudioState *s) static void sdl_close (SDLAudioState *s)
{ {
if (s->initialized) { if (s->initialized) {
sdl_lock (s, "sdl_close"); SDL_LockAudio();
s->exit = 1; s->exit = 1;
sdl_unlock_and_post (s, "sdl_close"); SDL_UnlockAudio();
SDL_PauseAudio (1); SDL_PauseAudio (1);
SDL_CloseAudio (); SDL_CloseAudio ();
s->initialized = 0; s->initialized = 0;
@ -258,76 +189,36 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len)
SDLAudioState *s = &glob_sdl; SDLAudioState *s = &glob_sdl;
HWVoiceOut *hw = &sdl->hw; HWVoiceOut *hw = &sdl->hw;
int samples = len >> hw->info.shift; int samples = len >> hw->info.shift;
int to_mix, decr;
if (s->exit) { if (s->exit || !sdl->live) {
return; return;
} }
while (samples) { /* dolog ("in callback samples=%d live=%d\n", samples, sdl->live); */
int to_mix, decr;
/* dolog ("in callback samples=%d\n", samples); */ to_mix = audio_MIN(samples, sdl->live);
#if USE_SEMAPHORE decr = to_mix;
sdl_wait (s, "sdl_callback"); while (to_mix) {
if (s->exit) { int chunk = audio_MIN(to_mix, hw->samples - hw->rpos);
return; struct st_sample *src = hw->mix_buf + hw->rpos;
}
if (sdl_lock (s, "sdl_callback")) { /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
return; hw->clip(buf, src, chunk);
} hw->rpos = (hw->rpos + chunk) % hw->samples;
to_mix -= chunk;
if (audio_bug(__func__, sdl->live < 0 || sdl->live > hw->samples)) { buf += chunk << hw->info.shift;
dolog ("sdl->live=%d hw->samples=%d\n",
sdl->live, hw->samples);
return;
}
if (!sdl->live) {
goto again;
}
#else
if (s->exit || !sdl->live) {
break;
}
#endif
/* dolog ("in callback live=%d\n", live); */
to_mix = audio_MIN (samples, sdl->live);
decr = to_mix;
while (to_mix) {
int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
struct st_sample *src = hw->mix_buf + hw->rpos;
/* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
hw->clip (buf, src, chunk);
#if USE_SEMAPHORE
sdl->rpos = (sdl->rpos + chunk) % hw->samples;
#else
hw->rpos = (hw->rpos + chunk) % hw->samples;
#endif
to_mix -= chunk;
buf += chunk << hw->info.shift;
}
samples -= decr;
sdl->live -= decr;
sdl->decr += decr;
#if USE_SEMAPHORE
again:
if (sdl_unlock (s, "sdl_callback")) {
return;
}
#endif
} }
samples -= decr;
sdl->live -= decr;
sdl->decr += decr;
/* dolog ("done len=%d\n", len); */ /* dolog ("done len=%d\n", len); */
#if (SDL_MAJOR_VERSION >= 2)
/* SDL2 does not clear the remaining buffer for us, so do it on our own */ /* SDL2 does not clear the remaining buffer for us, so do it on our own */
if (samples) { if (samples) {
memset(buf, 0, samples << hw->info.shift); memset(buf, 0, samples << hw->info.shift);
} }
#endif
} }
static int sdl_write_out (SWVoiceOut *sw, void *buf, int len) static int sdl_write_out (SWVoiceOut *sw, void *buf, int len)
@ -339,11 +230,8 @@ static int sdl_run_out (HWVoiceOut *hw, int live)
{ {
int decr; int decr;
SDLVoiceOut *sdl = (SDLVoiceOut *) hw; SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
SDLAudioState *s = &glob_sdl;
if (sdl_lock (s, "sdl_run_out")) { SDL_LockAudio();
return 0;
}
if (sdl->decr > live) { if (sdl->decr > live) {
ldebug ("sdl->decr %d live %d sdl->live %d\n", ldebug ("sdl->decr %d live %d sdl->live %d\n",
@ -355,19 +243,10 @@ static int sdl_run_out (HWVoiceOut *hw, int live)
decr = audio_MIN (sdl->decr, live); decr = audio_MIN (sdl->decr, live);
sdl->decr -= decr; sdl->decr -= decr;
#if USE_SEMAPHORE
sdl->live = live - decr;
hw->rpos = sdl->rpos;
#else
sdl->live = live; sdl->live = live;
#endif
if (sdl->live > 0) { SDL_UnlockAudio();
sdl_unlock_and_post (s, "sdl_run_out");
}
else {
sdl_unlock (s, "sdl_run_out");
}
return decr; return decr;
} }
@ -449,23 +328,6 @@ static void *sdl_audio_init (void)
return NULL; return NULL;
} }
#if USE_SEMAPHORE
s->mutex = SDL_CreateMutex ();
if (!s->mutex) {
sdl_logerr ("Failed to create SDL mutex\n");
SDL_QuitSubSystem (SDL_INIT_AUDIO);
return NULL;
}
s->sem = SDL_CreateSemaphore (0);
if (!s->sem) {
sdl_logerr ("Failed to create SDL semaphore\n");
SDL_DestroyMutex (s->mutex);
SDL_QuitSubSystem (SDL_INIT_AUDIO);
return NULL;
}
#endif
s->driver_created = true; s->driver_created = true;
return s; return s;
} }
@ -474,10 +336,6 @@ static void sdl_audio_fini (void *opaque)
{ {
SDLAudioState *s = opaque; SDLAudioState *s = opaque;
sdl_close (s); sdl_close (s);
#if USE_SEMAPHORE
SDL_DestroySemaphore (s->sem);
SDL_DestroyMutex (s->mutex);
#endif
SDL_QuitSubSystem (SDL_INIT_AUDIO); SDL_QuitSubSystem (SDL_INIT_AUDIO);
s->driver_created = false; s->driver_created = false;
} }

2
configure vendored
View File

@ -879,7 +879,7 @@ Haiku)
LIBS="-lposix_error_mapper -lnetwork $LIBS" LIBS="-lposix_error_mapper -lnetwork $LIBS"
;; ;;
Linux) Linux)
audio_drv_list="try-pa try-alsa try-sdl oss" audio_drv_list="try-pa oss"
audio_possible_drivers="oss alsa sdl pa" audio_possible_drivers="oss alsa sdl pa"
linux="yes" linux="yes"
linux_user="yes" linux_user="yes"